From 02c5f2607a65e9f7d7509ad5dc278a28c1d42bd2 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 30 Jun 2024 21:34:42 +0530 Subject: [PATCH] Cache paging data using the cachedIn() extension --- app/build.gradle | 2 +- .../schabi/newpipe/compose/comment/Comment.kt | 8 +++- .../newpipe/compose/comment/CommentSection.kt | 14 +++---- .../list/comments/CommentsFragment.kt | 8 +++- .../schabi/newpipe/paging/CommentsSource.kt | 39 +++++++++++-------- .../schabi/newpipe/util/ExtractorHelper.java | 20 ---------- 6 files changed, 43 insertions(+), 48 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7bea96099..5929582b0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -293,7 +293,7 @@ dependencies { implementation 'androidx.compose.material3:material3' implementation 'androidx.activity:activity-compose' implementation 'androidx.compose.ui:ui-tooling-preview' - implementation 'androidx.compose.ui:ui-text:1.7.0-beta03' // Needed for parsing HTML to AnnotatedString + implementation 'androidx.compose.ui:ui-text:1.7.0-beta04' // Needed for parsing HTML to AnnotatedString implementation 'com.github.nanihadesuka:LazyColumnScrollbar:2.1.0' // Paging diff --git a/app/src/main/java/org/schabi/newpipe/compose/comment/Comment.kt b/app/src/main/java/org/schabi/newpipe/compose/comment/Comment.kt index b63845ae1..97dce39a5 100644 --- a/app/src/main/java/org/schabi/newpipe/compose/comment/Comment.kt +++ b/app/src/main/java/org/schabi/newpipe/compose/comment/Comment.kt @@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -37,6 +38,7 @@ import androidx.compose.ui.unit.dp import androidx.fragment.app.FragmentActivity import androidx.paging.Pager import androidx.paging.PagingConfig +import androidx.paging.cachedIn import coil.compose.AsyncImage import org.schabi.newpipe.R import org.schabi.newpipe.compose.theme.AppTheme @@ -141,13 +143,15 @@ fun Comment(comment: CommentsInfoItem) { if (showReplies) { ModalBottomSheet(onDismissRequest = { showReplies = false }) { - val flow = remember(comment) { + val coroutineScope = rememberCoroutineScope() + val flow = remember(coroutineScope) { Pager(PagingConfig(pageSize = 20, enablePlaceholders = false)) { CommentsSource(comment.serviceId, comment.url, comment.replies) }.flow + .cachedIn(coroutineScope) } - CommentSection(parentComment = comment, flow = flow) + CommentSection(parentComment = comment, commentsData = flow) } } } diff --git a/app/src/main/java/org/schabi/newpipe/compose/comment/CommentSection.kt b/app/src/main/java/org/schabi/newpipe/compose/comment/CommentSection.kt index 72e401d9a..df2c470a9 100644 --- a/app/src/main/java/org/schabi/newpipe/compose/comment/CommentSection.kt +++ b/app/src/main/java/org/schabi/newpipe/compose/comment/CommentSection.kt @@ -36,13 +36,13 @@ import org.schabi.newpipe.paging.CommentsDisabledException @Composable fun CommentSection( parentComment: CommentsInfoItem? = null, - flow: Flow> + commentsData: Flow> ) { - val replies = flow.collectAsLazyPagingItems() - val itemCount by remember { derivedStateOf { replies.itemCount } } + val comments = commentsData.collectAsLazyPagingItems() + val itemCount by remember { derivedStateOf { comments.itemCount } } Surface(color = MaterialTheme.colorScheme.background) { - val refresh = replies.loadState.refresh + val refresh = comments.loadState.refresh if (itemCount == 0 && refresh !is LoadState.Loading) { NoCommentsMessage((refresh as? LoadState.Error)?.error) } else { @@ -58,7 +58,7 @@ fun CommentSection( } items(itemCount) { - Comment(comment = replies[it]!!) + Comment(comment = comments[it]!!) } } } @@ -113,7 +113,7 @@ private fun CommentSectionPreview( @PreviewParameter(CommentDataProvider::class) pagingData: PagingData ) { AppTheme { - CommentSection(flow = flowOf(pagingData)) + CommentSection(commentsData = flowOf(pagingData)) } } @@ -137,6 +137,6 @@ private fun CommentRepliesPreview() { val flow = flowOf(PagingData.from(replies)) AppTheme { - CommentSection(parentComment = comment, flow = flow) + CommentSection(parentComment = comment, commentsData = flow) } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.kt b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.kt index 76eb0041e..5933ea809 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.kt @@ -5,12 +5,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.paging.Pager import androidx.paging.PagingConfig +import androidx.paging.cachedIn import org.schabi.newpipe.compose.comment.CommentSection import org.schabi.newpipe.compose.theme.AppTheme import org.schabi.newpipe.paging.CommentsSource @@ -29,14 +31,16 @@ class CommentsFragment : Fragment() { return ComposeView(requireContext()).apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - val flow = remember(serviceId, url) { + val coroutineScope = rememberCoroutineScope() + val flow = remember(coroutineScope) { Pager(PagingConfig(pageSize = 20, enablePlaceholders = false)) { CommentsSource(serviceId, url, null) }.flow + .cachedIn(coroutineScope) } AppTheme { - CommentSection(flow = flow) + CommentSection(commentsData = flow) } } } diff --git a/app/src/main/java/org/schabi/newpipe/paging/CommentsSource.kt b/app/src/main/java/org/schabi/newpipe/paging/CommentsSource.kt index d78a7a83d..aec24a344 100644 --- a/app/src/main/java/org/schabi/newpipe/paging/CommentsSource.kt +++ b/app/src/main/java/org/schabi/newpipe/paging/CommentsSource.kt @@ -1,35 +1,42 @@ package org.schabi.newpipe.paging +import androidx.paging.PagingSource import androidx.paging.PagingState -import androidx.paging.rxjava3.RxPagingSource -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.schedulers.Schedulers +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.schabi.newpipe.extractor.NewPipe import org.schabi.newpipe.extractor.Page +import org.schabi.newpipe.extractor.comments.CommentsInfo import org.schabi.newpipe.extractor.comments.CommentsInfoItem -import org.schabi.newpipe.util.ExtractorHelper +import org.schabi.newpipe.util.NO_SERVICE_ID class CommentsSource( - private val serviceId: Int, + serviceId: Int, private val url: String?, private val repliesPage: Page? -) : RxPagingSource() { - override fun loadSingle(params: LoadParams): Single> { +) : PagingSource() { + init { + require(serviceId != NO_SERVICE_ID) { "serviceId is NO_SERVICE_ID" } + } + private val service = NewPipe.getService(serviceId) + + override suspend fun load(params: LoadParams): LoadResult { // repliesPage is non-null only when used to load the comment replies val nextKey = params.key ?: repliesPage - return nextKey?.let { - ExtractorHelper.getMoreCommentItems(serviceId, url, it) - .subscribeOn(Schedulers.io()) - .map { LoadResult.Page(it.items, null, it.nextPage) } - } ?: ExtractorHelper.getCommentsInfo(serviceId, url, false) - .subscribeOn(Schedulers.io()) - .map { - if (it.isCommentsDisabled) { + return withContext(Dispatchers.IO) { + nextKey?.let { + val info = CommentsInfo.getMoreItems(service, url, it) + LoadResult.Page(info.items, null, info.nextPage) + } ?: run { + val info = CommentsInfo.getInfo(service, url) + if (info.isCommentsDisabled) { LoadResult.Error(CommentsDisabledException()) } else { - LoadResult.Page(it.relatedItems, null, it.nextPage) + LoadResult.Page(info.relatedItems, null, info.nextPage) } } + } } override fun getRefreshKey(state: PagingState) = null diff --git a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java index abf8d24c1..83f2332ed 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java @@ -42,8 +42,6 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo; -import org.schabi.newpipe.extractor.comments.CommentsInfo; -import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.extractor.kiosk.KioskInfo; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; @@ -146,24 +144,6 @@ public final class ExtractorHelper { listLinkHandler, nextPage)); } - public static Single getCommentsInfo(final int serviceId, - final String url, - final boolean forceLoad) { - checkServiceId(serviceId); - return checkCache(forceLoad, serviceId, url, InfoCache.Type.COMMENTS, - Single.fromCallable(() -> - CommentsInfo.getInfo(NewPipe.getService(serviceId), url))); - } - - public static Single> getMoreCommentItems( - final int serviceId, - final String url, - final Page nextPage) { - checkServiceId(serviceId); - return Single.fromCallable(() -> - CommentsInfo.getMoreItems(NewPipe.getService(serviceId), url, nextPage)); - } - public static Single getPlaylistInfo(final int serviceId, final String url, final boolean forceLoad) {