Skip to content

Commit

Permalink
Sync notif timeline with cachedtimeline code. Remove dead code
Browse files Browse the repository at this point in the history
  • Loading branch information
nikclayton committed Feb 1, 2025
1 parent 1ef22c7 commit 5c02d3d
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
Expand Down Expand Up @@ -261,6 +260,7 @@ class NotificationsFragment :
}

// Update the UI from the loadState
// TODO: Move to bindLoadState function
adapter.loadStateFlow.distinctUntilChangedBy { it.refresh }.collect { loadState ->
when (loadState.refresh) {
is LoadState.Error -> {
Expand All @@ -274,7 +274,6 @@ class NotificationsFragment :
}

LoadState.Loading -> {
/* nothing */
binding.statusView.hide()
binding.progressIndicator.show()
}
Expand Down Expand Up @@ -347,12 +346,13 @@ class NotificationsFragment :
// remove it.
is NotificationActionSuccess.AcceptFollowRequest,
is NotificationActionSuccess.RejectFollowRequest,
-> refreshAdapterAndScrollToVisibleId()
-> adapter.refresh()
}
}

when (uiSuccess) {
is UiSuccess.Block, is UiSuccess.Mute, is UiSuccess.MuteConversation -> refreshAdapterAndScrollToVisibleId()
is UiSuccess.Block, is UiSuccess.Mute, is UiSuccess.MuteConversation,
-> adapter.refresh()

is UiSuccess.LoadNewest -> {
// Scroll to the top when prepending completes.
Expand All @@ -371,25 +371,6 @@ class NotificationsFragment :
}
}

/**
* Refreshes the adapter, waits for the first page to be updated, and scrolls the
* recyclerview to the first notification that was visible before the refresh.
*
* This ensures the user's position is not lost during adapter refreshes.
*/
private fun refreshAdapterAndScrollToVisibleId() {
getFirstVisibleNotification()?.id?.let { id ->
viewLifecycleOwner.lifecycleScope.launch {
adapter.onPagesUpdatedFlow.conflate().take(1).collect {
binding.recyclerView.scrollToPosition(
adapter.snapshot().items.indexOfFirst { it.id == id },
)
}
}
}
adapter.refresh()
}

override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.fragment_notifications, menu)
menu.findItem(R.id.action_refresh)?.apply {
Expand Down Expand Up @@ -438,7 +419,7 @@ class NotificationsFragment :
}

binding.swipeRefreshLayout.isRefreshing = false
refreshAdapterAndScrollToVisibleId()
adapter.refresh()
clearNotificationsForAccount(requireContext(), pachliAccountId)
}

Expand Down Expand Up @@ -605,11 +586,11 @@ class NotificationsFragment :
}

override fun onMute(mute: Boolean, id: String, position: Int, notifications: Boolean) {
refreshAdapterAndScrollToVisibleId()
adapter.refresh()
}

override fun onBlock(block: Boolean, id: String, position: Int) {
refreshAdapterAndScrollToVisibleId()
adapter.refresh()
}

override fun onRespondToFollowRequest(accept: Boolean, accountId: String, position: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,9 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.zip
Expand Down Expand Up @@ -189,7 +187,7 @@ class TimelineFragment :
isSwipeToRefreshEnabled = arguments.getBoolean(ARG_ENABLE_SWIPE_TO_REFRESH, true)

adapter = TimelinePagingAdapter(this, viewModel.statusDisplayOptions.value)
adapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT
// adapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT
}

override fun onCreateView(
Expand Down Expand Up @@ -224,26 +222,6 @@ class TimelineFragment :
}
}

viewLifecycleOwner.lifecycleScope.launch {
adapter.onPagesUpdatedFlow.map { adapter.snapshot() }.distinctUntilChanged()
.combine(adapter.loadStateFlow.distinctUntilChanged()) { s, l ->
Pair(s, l)
}.collect { (snapshot, l) ->
Timber.e("snapshot-loadstate")
Timber.d(" loadstate: $l")
Timber.d(" loadstate.refresh: ${l.refresh}")
Timber.d(" loadstate.source.refresh: ${l.source.refresh}")
Timber.d(" loadstate.mediator.refresh: ${l.mediator?.refresh}")
Timber.d(" loadstate.prepend: ${l.prepend}")
Timber.d(" loadstate. append: ${l.append}")
Timber.d(" snapshot size = ${snapshot.items.size}")
Timber.d(" first ID: ${snapshot.items.firstOrNull()?.id}")
Timber.d(" last ID: ${snapshot.items.lastOrNull()?.id}")
Timber.d(" p before: ${snapshot.placeholdersBefore}")
Timber.d(" p after: ${snapshot.placeholdersAfter}")
}
}

viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
Expand All @@ -254,7 +232,6 @@ class TimelineFragment :
.take(1)
.filterNotNull()
.collect { key ->
Timber.d("First onPagesUpdatedFlow, restoring $key")
val snapshot = adapter.snapshot()
val index = snapshot.items.indexOfFirst { it.id == key }
binding.recyclerView.scrollToPosition(
Expand All @@ -264,12 +241,7 @@ class TimelineFragment :
}
}

launch {
viewModel.statuses.collectLatest {
Timber.w("Calling submitData(), expect a pageflow update")
adapter.submitData(it)
}
}
launch { viewModel.statuses.collectLatest { adapter.submitData(it) } }

launch { viewModel.uiResult.collect(::bindUiResult) }

Expand Down Expand Up @@ -299,6 +271,7 @@ class TimelineFragment :
}
}

// TODO: Move to bindLoadState function
adapter.loadStateFlow.distinctUntilChangedBy { it.refresh }.collect { loadState ->
when (loadState.refresh) {
is LoadState.Error -> {
Expand All @@ -312,17 +285,13 @@ class TimelineFragment :
}

LoadState.Loading -> {
/* nothing */
binding.statusView.hide()
binding.progressIndicator.show()
}

is LoadState.NotLoading -> {
// Might still be loading if source.refresh is Loading, so only update
// the UI when loading is completely quiet.
Timber.d("NotLoading .refresh: ${loadState.refresh}")
Timber.d(" NotLoading .source.refresh: ${loadState.source.refresh}")
Timber.d(" NotLoading .mediator.refresh: ${loadState.mediator?.refresh}")
if (loadState.source.refresh !is LoadState.Loading) {
binding.progressIndicator.hide()
binding.swipeRefreshLayout.isRefreshing = false
Expand Down Expand Up @@ -427,9 +396,7 @@ class TimelineFragment :

// Refresh adapter on mutes and blocks
when (it) {
is UiSuccess.Block,
is UiSuccess.Mute,
is UiSuccess.MuteConversation,
is UiSuccess.Block, is UiSuccess.Mute, is UiSuccess.MuteConversation,
-> adapter.refresh()

is UiSuccess.StatusSent -> handleStatusSentOrEdit(it.status)
Expand Down
10 changes: 0 additions & 10 deletions app/src/main/java/app/pachli/util/EmptyPagingSource.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import timber.log.Timber

/**
* Errors that can occur acting on a status.
Expand Down Expand Up @@ -113,10 +114,10 @@ class NotificationsRepository @Inject constructor(
// Room is row-keyed, not item-keyed. Find the user's REFRESH key, then find the
// row of the notification with that ID, and use that as the Pager's initialKey.
val initialKey = remoteKeyDao.remoteKeyForKind(pachliAccountId, RKE_TIMELINE_ID, RemoteKeyKind.REFRESH)?.key
val row = initialKey?.let { notificationDao.getNotificationRowNumber(pachliAccountId, it) } ?: 0
val row = initialKey?.let { notificationDao.getNotificationRowNumber(pachliAccountId, it) }

return Pager(
initialKey = (row - ((PAGE_SIZE * 3) / 2)).coerceAtLeast(0),
initialKey = row?.let { (row - ((PAGE_SIZE * 3) / 2)).coerceAtLeast(0) },
config = PagingConfig(
pageSize = PAGE_SIZE,
enablePlaceholders = true,
Expand Down Expand Up @@ -145,6 +146,7 @@ class NotificationsRepository @Inject constructor(
* refresh the newest notifications.
*/
suspend fun saveRefreshKey(pachliAccountId: Long, key: String?) = externalScope.async {
Timber.d("saveRefreshKey: $key")
remoteKeyDao.upsert(
RemoteKeyEntity(pachliAccountId, RKE_TIMELINE_ID, RemoteKeyKind.REFRESH, key),
)
Expand Down

0 comments on commit 5c02d3d

Please sign in to comment.