diff --git a/app/src/main/java/com/h/pixeldroid/posts/feeds/CommonFeedFragmentUtils.kt b/app/src/main/java/com/h/pixeldroid/posts/feeds/CommonFeedFragmentUtils.kt index 30263739..53f8e62e 100644 --- a/app/src/main/java/com/h/pixeldroid/posts/feeds/CommonFeedFragmentUtils.kt +++ b/app/src/main/java/com/h/pixeldroid/posts/feeds/CommonFeedFragmentUtils.kt @@ -2,25 +2,32 @@ package com.h.pixeldroid.posts.feeds import android.view.LayoutInflater import android.view.ViewGroup +import android.widget.ProgressBar +import androidx.constraintlayout.motion.widget.MotionLayout import androidx.core.view.isVisible import androidx.core.view.size import androidx.paging.LoadState import androidx.paging.LoadStateAdapter import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.h.pixeldroid.R -import com.h.pixeldroid.databinding.FragmentFeedBinding +import com.h.pixeldroid.databinding.ErrorLayoutBinding import com.h.pixeldroid.databinding.LoadStateFooterViewItemBinding /** * Shows or hides the error in the different FeedFragments */ -private fun showError(errorText: String, show: Boolean = true, binding: FragmentFeedBinding){ - if(show){ - binding.motionLayout.transitionToEnd() - binding.errorLayout.errorText.text = errorText - } else if(binding.motionLayout.progress == 1F){ - binding.motionLayout.transitionToStart() +private fun showError( + errorText: String, show: Boolean = true, + motionLayout: MotionLayout, + errorLayout: ErrorLayoutBinding){ + + if(show) { + motionLayout.transitionToEnd() + errorLayout.errorText.text = errorText + } else if(motionLayout.progress == 1F) { + motionLayout.transitionToStart() } } @@ -29,28 +36,32 @@ private fun showError(errorText: String, show: Boolean = true, binding: Fragment * * Makes the UI respond to various [LoadState]s, including errors when an error message is shown. */ -internal fun initAdapter(binding: FragmentFeedBinding, adapter: PagingDataAdapter) { - binding.list.adapter = adapter.withLoadStateFooter( +internal fun initAdapter( + progressBar: ProgressBar, swipeRefreshLayout: SwipeRefreshLayout, + recyclerView: RecyclerView, motionLayout: MotionLayout, errorLayout: ErrorLayoutBinding, + adapter: PagingDataAdapter) { + + recyclerView.adapter = adapter.withLoadStateFooter( footer = ReposLoadStateAdapter { adapter.retry() } ) adapter.addLoadStateListener { loadState -> - if(!binding.progressBar.isVisible && binding.swipeRefreshLayout.isRefreshing) { + if(!progressBar.isVisible && swipeRefreshLayout.isRefreshing) { // Stop loading spinner when loading is done - binding.swipeRefreshLayout.isRefreshing = loadState.refresh is LoadState.Loading + swipeRefreshLayout.isRefreshing = loadState.refresh is LoadState.Loading } else { // ProgressBar should stop showing as soon as the source stops loading ("source" // meaning the database, so don't wait on the network) val sourceLoading = loadState.source.refresh is LoadState.Loading - if(!sourceLoading && binding.list.size > 0){ - binding.list.isVisible = true - binding.progressBar.isVisible = false - } else if(binding.list.size == 0 + if(!sourceLoading && recyclerView.size > 0){ + recyclerView.isVisible = true + progressBar.isVisible = false + } else if(recyclerView.size == 0 && loadState.append is LoadState.NotLoading && loadState.append.endOfPaginationReached){ - binding.progressBar.isVisible = false - showError(binding = binding, errorText = "Nothing to see here :(") + progressBar.isVisible = false + showError(motionLayout = motionLayout, errorLayout = errorLayout, errorText = "Nothing to see here :(") } } @@ -63,13 +74,15 @@ internal fun initAdapter(binding: FragmentFeedBinding, adapter: PagingD ?: loadState.prepend as? LoadState.Error ?: loadState.refresh as? LoadState.Error errorState?.let { - showError(binding = binding, errorText = it.error.toString()) + showError(motionLayout = motionLayout, errorLayout = errorLayout, errorText = it.error.toString()) + } + if(errorState == null) { + showError(motionLayout = motionLayout, errorLayout = errorLayout, show = false, errorText = "") } - if (errorState == null) showError(binding = binding, show = false, errorText = "") } - } + /** * Adapter to the show the a [RecyclerView] item for a [LoadState], with a callback to retry if * the retry button is pressed. diff --git a/app/src/main/java/com/h/pixeldroid/posts/feeds/cachedFeeds/CachedFeedFragment.kt b/app/src/main/java/com/h/pixeldroid/posts/feeds/cachedFeeds/CachedFeedFragment.kt index c02eb2f8..a9af376b 100644 --- a/app/src/main/java/com/h/pixeldroid/posts/feeds/cachedFeeds/CachedFeedFragment.kt +++ b/app/src/main/java/com/h/pixeldroid/posts/feeds/cachedFeeds/CachedFeedFragment.kt @@ -70,7 +70,8 @@ open class CachedFeedFragment : BaseFragment() { binding = FragmentFeedBinding.inflate(layoutInflater) - initAdapter(binding, adapter) + initAdapter(binding.progressBar, binding.swipeRefreshLayout, + binding.list, binding.motionLayout, binding.errorLayout, adapter) //binding.progressBar.visibility = View.GONE binding.swipeRefreshLayout.setOnRefreshListener { diff --git a/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/UncachedFeedFragment.kt b/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/UncachedFeedFragment.kt index 087477aa..6ad46d16 100644 --- a/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/UncachedFeedFragment.kt +++ b/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/UncachedFeedFragment.kt @@ -67,7 +67,8 @@ open class UncachedFeedFragment : BaseFragment() { binding = FragmentFeedBinding.inflate(layoutInflater) - initAdapter(binding, adapter) + initAdapter(binding.progressBar, binding.swipeRefreshLayout, binding.list, + binding.motionLayout, binding.errorLayout, adapter) binding.swipeRefreshLayout.setOnRefreshListener { //It shouldn't be necessary to also retry() in addition to refresh(), diff --git a/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/profile/ProfilePagingSource.kt b/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/profile/ProfilePagingSource.kt index e58301bb..2e178d0d 100644 --- a/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/profile/ProfilePagingSource.kt +++ b/app/src/main/java/com/h/pixeldroid/posts/feeds/uncachedFeeds/profile/ProfilePagingSource.kt @@ -33,8 +33,5 @@ class ProfilePagingSource( } } - override fun getRefreshKey(state: PagingState): String? = - state.anchorPosition?.run { - state.closestItemToPosition(this)?.id - } + override fun getRefreshKey(state: PagingState): String? = null } \ No newline at end of file diff --git a/app/src/main/java/com/h/pixeldroid/profile/ProfileActivity.kt b/app/src/main/java/com/h/pixeldroid/profile/ProfileActivity.kt index 427c0da0..199d3bcc 100644 --- a/app/src/main/java/com/h/pixeldroid/profile/ProfileActivity.kt +++ b/app/src/main/java/com/h/pixeldroid/profile/ProfileActivity.kt @@ -9,8 +9,6 @@ import android.view.ViewGroup import android.widget.* import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.ContextCompat -import androidx.core.view.isVisible -import androidx.core.view.size import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope @@ -24,7 +22,7 @@ import com.h.pixeldroid.R import com.h.pixeldroid.databinding.ActivityProfileBinding import com.h.pixeldroid.databinding.FragmentProfilePostsBinding import com.h.pixeldroid.posts.PostActivity -import com.h.pixeldroid.posts.feeds.ReposLoadStateAdapter +import com.h.pixeldroid.posts.feeds.initAdapter import com.h.pixeldroid.posts.feeds.uncachedFeeds.FeedViewModel import com.h.pixeldroid.posts.feeds.uncachedFeeds.UncachedContentRepository import com.h.pixeldroid.posts.feeds.uncachedFeeds.profile.ProfileContentRepository @@ -88,14 +86,13 @@ class ProfileActivity : BaseActivity() { ).get(FeedViewModel::class.java) as FeedViewModel profileAdapter = ProfilePostsAdapter() - initAdapter(binding, profileAdapter) + initAdapter(binding.profileProgressBar, binding.profileRefreshLayout, + binding.profilePostsRecyclerView, binding.motionLayout, binding.profileErrorLayout, + profileAdapter) binding.profilePostsRecyclerView.layoutManager = GridLayoutManager(this, 3) binding.profileRefreshLayout.setOnRefreshListener { - //It shouldn't be necessary to also retry() in addition to refresh(), - //but if we don't do this, reloads after an error fail immediately... - profileAdapter.retry() profileAdapter.refresh() } @@ -139,52 +136,6 @@ class ProfileActivity : BaseActivity() { binding.profileRefreshLayout.isRefreshing = false } - /** - * Initialises the [RecyclerView] adapter for the different FeedFragments. - * - * Makes the UI respond to various [LoadState]s, including errors when an error message is shown. - */ - internal fun initAdapter(binding: ActivityProfileBinding, adapter: PagingDataAdapter) { - binding.profilePostsRecyclerView.adapter = adapter.withLoadStateFooter( - footer = ReposLoadStateAdapter { adapter.retry() } - ) - - adapter.addLoadStateListener { loadState -> - - if(!binding.profileProgressBar.isVisible && binding.profileRefreshLayout.isRefreshing) { - // Stop loading spinner when loading is done - binding.profileRefreshLayout.isRefreshing = loadState.refresh is LoadState.Loading - } else { - // ProgressBar should stop showing as soon as the source stops loading ("source" - // meaning the database, so don't wait on the network) - val sourceLoading = loadState.source.refresh is LoadState.Loading - if(!sourceLoading && binding.profilePostsRecyclerView.size > 0){ - binding.profilePostsRecyclerView.isVisible = true - binding.profileProgressBar.isVisible = false - } else if(binding.profilePostsRecyclerView.size == 0 - && loadState.append is LoadState.NotLoading - && loadState.append.endOfPaginationReached){ - binding.profileProgressBar.isVisible = false - showError(errorText = "Nothing to see here :(") - } - } - - - // Toast on any error, regardless of whether it came from RemoteMediator or PagingSource - val errorState = loadState.source.append as? LoadState.Error - ?: loadState.source.prepend as? LoadState.Error - ?: loadState.source.refresh as? LoadState.Error - ?: loadState.append as? LoadState.Error - ?: loadState.prepend as? LoadState.Error - ?: loadState.refresh as? LoadState.Error - errorState?.let { - showError(errorText = it.error.toString()) - } - if (errorState == null) showError(show = false, errorText = "") - } - - } - override fun onSupportNavigateUp(): Boolean { onBackPressed() return true diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 1e300bf5..c595e0db 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -143,6 +143,7 @@ tools:visibility="visible">