From 42b0e3e4389b78556ccf34b93edc7d454de5881e Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Sat, 1 Oct 2022 21:50:25 +0700 Subject: [PATCH] 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 --- .../data/history/HistoryRepositoryImpl.kt | 13 ++--- .../domain/history/interactor/GetHistory.kt | 12 +---- .../history/repository/HistoryRepository.kt | 4 +- .../presentation/history/HistoryScreen.kt | 34 +++++++----- .../history/components/HistoryContent.kt | 54 +++++-------------- .../history/components/HistoryItem.kt | 53 +----------------- .../eu/kanade/presentation/util/Shimmer.kt | 9 ---- .../ui/recent/history/HistoryPresenter.kt | 23 +++----- app/src/main/sqldelight/view/historyView.sq | 10 +--- 9 files changed, 52 insertions(+), 160 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/presentation/util/Shimmer.kt diff --git a/app/src/main/java/eu/kanade/data/history/HistoryRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/history/HistoryRepositoryImpl.kt index 808aeee653..44cd13b53f 100644 --- a/app/src/main/java/eu/kanade/data/history/HistoryRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/history/HistoryRepositoryImpl.kt @@ -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 { - return handler.subscribeToPagingSource( - countQuery = { historyViewQueries.countHistory(query) }, - queryProvider = { limit, offset -> - historyViewQueries.history(query, limit, offset, historyWithRelationsMapper) - }, - ) + override fun getHistory(query: String): Flow> { + return handler.subscribeToList { + historyViewQueries.history(query, historyWithRelationsMapper) + } } override suspend fun getLastHistory(): HistoryWithRelations? { diff --git a/app/src/main/java/eu/kanade/domain/history/interactor/GetHistory.kt b/app/src/main/java/eu/kanade/domain/history/interactor/GetHistory.kt index 1db219ed37..482995f25c 100644 --- a/app/src/main/java/eu/kanade/domain/history/interactor/GetHistory.kt +++ b/app/src/main/java/eu/kanade/domain/history/interactor/GetHistory.kt @@ -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> { - return Pager( - PagingConfig(pageSize = 25), - ) { - repository.getHistory(query) - }.flow + fun subscribe(query: String): Flow> { + return repository.getHistory(query) } } diff --git a/app/src/main/java/eu/kanade/domain/history/repository/HistoryRepository.kt b/app/src/main/java/eu/kanade/domain/history/repository/HistoryRepository.kt index f2c57894a6..dd18c300a0 100644 --- a/app/src/main/java/eu/kanade/domain/history/repository/HistoryRepository.kt +++ b/app/src/main/java/eu/kanade/domain/history/repository/HistoryRepository.kt @@ -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 + fun getHistory(query: String): Flow> suspend fun getLastHistory(): HistoryWithRelations? diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt index 4dd6d11718..e56876b096 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -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, - contentPadding = contentPadding, - onClickCover = onClickCover, - onClickResume = onClickResume, - onClickDelete = { presenter.dialog = Dialog.Delete(it) }, - ) + 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 = { 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 } } diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryContent.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryContent.kt index 8ab80f8a89..fc80f78335 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryContent.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryContent.kt @@ -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, + history: List, 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) - } } } } diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt index e720ce46d1..cbb851e3f0 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt @@ -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 = '.' }, diff --git a/app/src/main/java/eu/kanade/presentation/util/Shimmer.kt b/app/src/main/java/eu/kanade/presentation/util/Shimmer.kt deleted file mode 100644 index 4afeff9408..0000000000 --- a/app/src/main/java/eu/kanade/presentation/util/Shimmer.kt +++ /dev/null @@ -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), -) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt index a01fbd8975..9e60a5be28 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt @@ -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 { - val scope = rememberCoroutineScope() + fun getHistory(): Flow> { 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.toHistoryUiModels(): PagingData { - return this.map { - HistoryUiModel.Item(it) - } + private fun List.toHistoryUiModels(): List { + 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) diff --git a/app/src/main/sqldelight/view/historyView.sq b/app/src/main/sqldelight/view/historyView.sq index 1b0bb02d6c..bdaeb52594 100644 --- a/app/src/main/sqldelight/view/historyView.sq +++ b/app/src/main/sqldelight/view/historyView.sq @@ -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