mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	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:
		| @@ -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, | ||||
|                 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 | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user