HistoryScreen: Remove paging (#8125)
* HistoryScreen: Remove paging Per my testing performance-wise there's virtually no difference in loading time. * cleanups * add key and contentType
This commit is contained in:
parent
8d1f99a480
commit
42b0e3e438
9 changed files with 52 additions and 160 deletions
|
@ -1,6 +1,5 @@
|
|||
package eu.kanade.data.history
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.chapter.chapterMapper
|
||||
import eu.kanade.data.manga.mangaMapper
|
||||
|
@ -10,19 +9,17 @@ import eu.kanade.domain.history.model.HistoryWithRelations
|
|||
import eu.kanade.domain.history.repository.HistoryRepository
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import logcat.LogPriority
|
||||
|
||||
class HistoryRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
) : HistoryRepository {
|
||||
|
||||
override fun getHistory(query: String): PagingSource<Long, HistoryWithRelations> {
|
||||
return handler.subscribeToPagingSource(
|
||||
countQuery = { historyViewQueries.countHistory(query) },
|
||||
queryProvider = { limit, offset ->
|
||||
historyViewQueries.history(query, limit, offset, historyWithRelationsMapper)
|
||||
},
|
||||
)
|
||||
override fun getHistory(query: String): Flow<List<HistoryWithRelations>> {
|
||||
return handler.subscribeToList {
|
||||
historyViewQueries.history(query, historyWithRelationsMapper)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getLastHistory(): HistoryWithRelations? {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package eu.kanade.domain.history.interactor
|
||||
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
import eu.kanade.domain.history.repository.HistoryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -10,12 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
class GetHistory(
|
||||
private val repository: HistoryRepository,
|
||||
) {
|
||||
|
||||
fun subscribe(query: String): Flow<PagingData<HistoryWithRelations>> {
|
||||
return Pager(
|
||||
PagingConfig(pageSize = 25),
|
||||
) {
|
||||
repository.getHistory(query)
|
||||
}.flow
|
||||
fun subscribe(query: String): Flow<List<HistoryWithRelations>> {
|
||||
return repository.getHistory(query)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package eu.kanade.domain.history.repository
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import eu.kanade.domain.chapter.model.Chapter
|
||||
import eu.kanade.domain.history.model.HistoryUpdate
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface HistoryRepository {
|
||||
|
||||
fun getHistory(query: String): PagingSource<Long, HistoryWithRelations>
|
||||
fun getHistory(query: String): Flow<List<HistoryWithRelations>>
|
||||
|
||||
suspend fun getLastHistory(): HistoryWithRelations?
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@ package eu.kanade.presentation.history
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.paging.LoadState
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
import eu.kanade.presentation.components.EmptyScreen
|
||||
import eu.kanade.presentation.components.LoadingScreen
|
||||
|
@ -39,20 +40,25 @@ fun HistoryScreen(
|
|||
)
|
||||
},
|
||||
) { contentPadding ->
|
||||
val items = presenter.getLazyHistory()
|
||||
when {
|
||||
items.loadState.refresh is LoadState.Loading && items.itemCount < 1 -> LoadingScreen()
|
||||
items.loadState.refresh is LoadState.NotLoading && items.itemCount < 1 -> EmptyScreen(textResource = R.string.information_no_recent_manga)
|
||||
else -> HistoryContent(
|
||||
history = items,
|
||||
val items by presenter.getHistory().collectAsState(initial = null)
|
||||
items.let {
|
||||
if (it == null) {
|
||||
LoadingScreen()
|
||||
} else if (it.isEmpty()) {
|
||||
EmptyScreen(textResource = R.string.information_no_recent_manga)
|
||||
} else {
|
||||
HistoryContent(
|
||||
history = it,
|
||||
contentPadding = contentPadding,
|
||||
onClickCover = onClickCover,
|
||||
onClickResume = onClickResume,
|
||||
onClickDelete = { presenter.dialog = Dialog.Delete(it) },
|
||||
onClickDelete = { item -> presenter.dialog = Dialog.Delete(item) },
|
||||
)
|
||||
}
|
||||
LaunchedEffect(items.loadState.refresh) {
|
||||
if (items.loadState.refresh is LoadState.NotLoading) {
|
||||
}
|
||||
|
||||
LaunchedEffect(items) {
|
||||
if (items != null) {
|
||||
(presenter.view?.activity as? MainActivity)?.ready = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,10 @@
|
|||
package eu.kanade.presentation.history.components
|
||||
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.items
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.presentation.components.RelativeDateHeader
|
||||
|
@ -21,7 +12,6 @@ import eu.kanade.presentation.components.ScrollbarLazyColumn
|
|||
import eu.kanade.presentation.history.HistoryUiModel
|
||||
import eu.kanade.presentation.util.bottomNavPaddingValues
|
||||
import eu.kanade.presentation.util.plus
|
||||
import eu.kanade.presentation.util.shimmerGradient
|
||||
import eu.kanade.presentation.util.topPaddingValues
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -29,7 +19,7 @@ import java.text.DateFormat
|
|||
|
||||
@Composable
|
||||
fun HistoryContent(
|
||||
history: LazyPagingItems<HistoryUiModel>,
|
||||
history: List<HistoryUiModel>,
|
||||
contentPadding: PaddingValues,
|
||||
onClickCover: (HistoryWithRelations) -> Unit,
|
||||
onClickResume: (HistoryWithRelations) -> Unit,
|
||||
|
@ -41,14 +31,21 @@ fun HistoryContent(
|
|||
|
||||
ScrollbarLazyColumn(
|
||||
contentPadding = contentPadding + bottomNavPaddingValues + topPaddingValues,
|
||||
state = rememberLazyListState(),
|
||||
) {
|
||||
items(history) { item ->
|
||||
items(
|
||||
items = history,
|
||||
key = { "history-${it.hashCode()}" },
|
||||
contentType = {
|
||||
when (it) {
|
||||
is HistoryUiModel.Header -> "header"
|
||||
is HistoryUiModel.Item -> "item"
|
||||
}
|
||||
},
|
||||
) { item ->
|
||||
when (item) {
|
||||
is HistoryUiModel.Header -> {
|
||||
RelativeDateHeader(
|
||||
modifier = Modifier
|
||||
.animateItemPlacement(),
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
date = item.date,
|
||||
relativeTime = relativeTime,
|
||||
dateFormat = dateFormat,
|
||||
|
@ -64,31 +61,6 @@ fun HistoryContent(
|
|||
onClickDelete = { onClickDelete(value) },
|
||||
)
|
||||
}
|
||||
null -> {
|
||||
val transition = rememberInfiniteTransition()
|
||||
val translateAnimation = transition.animateFloat(
|
||||
initialValue = 0f,
|
||||
targetValue = 1000f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(
|
||||
durationMillis = 1000,
|
||||
easing = LinearEasing,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val brush = remember {
|
||||
Brush.linearGradient(
|
||||
colors = shimmerGradient,
|
||||
start = Offset(0f, 0f),
|
||||
end = Offset(
|
||||
x = translateAnimation.value,
|
||||
y = 00f,
|
||||
),
|
||||
)
|
||||
}
|
||||
HistoryItemShimmer(brush = brush)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
package eu.kanade.presentation.history.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material3.Icon
|
||||
|
@ -20,9 +16,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
@ -65,9 +58,10 @@ fun HistoryItem(
|
|||
val textStyle = MaterialTheme.typography.bodyMedium
|
||||
Text(
|
||||
text = history.title,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = textStyle.copy(fontWeight = FontWeight.SemiBold),
|
||||
style = textStyle,
|
||||
)
|
||||
val readAt = remember { history.readAt?.toTimestampString() ?: "" }
|
||||
Text(
|
||||
|
@ -95,49 +89,6 @@ fun HistoryItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HistoryItemShimmer(brush: Brush) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(HISTORY_ITEM_HEIGHT)
|
||||
.padding(horizontal = horizontalPadding, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.aspectRatio(MangaCover.Book.ratio)
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.drawBehind {
|
||||
drawRect(brush = brush)
|
||||
},
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = horizontalPadding, end = 8.dp),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.drawBehind {
|
||||
drawRect(brush = brush)
|
||||
}
|
||||
.height(14.dp)
|
||||
.fillMaxWidth(0.70f),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp)
|
||||
.height(14.dp)
|
||||
.fillMaxWidth(0.45f)
|
||||
.drawBehind {
|
||||
drawRect(brush = brush)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val chapterFormatter = DecimalFormat(
|
||||
"#.###",
|
||||
DecimalFormatSymbols().apply { decimalSeparator = '.' },
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package eu.kanade.presentation.util
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val shimmerGradient = listOf(
|
||||
Color.LightGray.copy(alpha = 0.8f),
|
||||
Color.LightGray.copy(alpha = 0.2f),
|
||||
Color.LightGray.copy(alpha = 0.8f),
|
||||
)
|
|
@ -5,14 +5,8 @@ import androidx.compose.runtime.Stable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.cachedIn
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.insertSeparators
|
||||
import androidx.paging.map
|
||||
import eu.kanade.core.util.insertSeparators
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.chapter.model.Chapter
|
||||
import eu.kanade.domain.history.interactor.DeleteHistoryTable
|
||||
|
@ -32,6 +26,7 @@ import eu.kanade.tachiyomi.util.system.toast
|
|||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import logcat.LogPriority
|
||||
|
@ -57,11 +52,11 @@ class HistoryPresenter(
|
|||
val isIncognitoMode: Boolean by preferences.incognitoMode().asState()
|
||||
|
||||
@Composable
|
||||
fun getLazyHistory(): LazyPagingItems<HistoryUiModel> {
|
||||
val scope = rememberCoroutineScope()
|
||||
fun getHistory(): Flow<List<HistoryUiModel>> {
|
||||
val query = searchQuery ?: ""
|
||||
val flow = remember(query) {
|
||||
return remember(query) {
|
||||
getHistory.subscribe(query)
|
||||
.distinctUntilChanged()
|
||||
.catch { error ->
|
||||
logcat(LogPriority.ERROR, error)
|
||||
_events.send(Event.InternalError)
|
||||
|
@ -69,15 +64,11 @@ class HistoryPresenter(
|
|||
.map { pagingData ->
|
||||
pagingData.toHistoryUiModels()
|
||||
}
|
||||
.cachedIn(scope)
|
||||
}
|
||||
return flow.collectAsLazyPagingItems()
|
||||
}
|
||||
|
||||
private fun PagingData<HistoryWithRelations>.toHistoryUiModels(): PagingData<HistoryUiModel> {
|
||||
return this.map {
|
||||
HistoryUiModel.Item(it)
|
||||
}
|
||||
private fun List<HistoryWithRelations>.toHistoryUiModels(): List<HistoryUiModel> {
|
||||
return map { HistoryUiModel.Item(it) }
|
||||
.insertSeparators { before, after ->
|
||||
val beforeDate = before?.item?.readAt?.time?.toDateKey() ?: Date(0)
|
||||
val afterDate = after?.item?.readAt?.time?.toDateKey() ?: Date(0)
|
||||
|
|
|
@ -26,13 +26,6 @@ JOIN (
|
|||
) AS max_last_read
|
||||
ON chapters.manga_id = max_last_read.manga_id;
|
||||
|
||||
countHistory:
|
||||
SELECT count(*)
|
||||
FROM historyView
|
||||
WHERE historyView.readAt > 0
|
||||
AND maxReadAtChapterId = historyView.chapterId
|
||||
AND lower(historyView.title) LIKE ('%' || :query || '%');
|
||||
|
||||
history:
|
||||
SELECT
|
||||
id,
|
||||
|
@ -50,8 +43,7 @@ FROM historyView
|
|||
WHERE historyView.readAt > 0
|
||||
AND maxReadAtChapterId = historyView.chapterId
|
||||
AND lower(historyView.title) LIKE ('%' || :query || '%')
|
||||
ORDER BY readAt DESC
|
||||
LIMIT :limit OFFSET :offset;
|
||||
ORDER BY readAt DESC;
|
||||
|
||||
getLatestHistory:
|
||||
SELECT
|
||||
|
|
Reference in a new issue