diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt index b2eb1dac..ab5c1b53 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt @@ -41,6 +41,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE import androidx.recyclerview.widget.SimpleItemAnimator import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import at.connyduck.sparkbutton.helpers.Utils @@ -193,6 +194,19 @@ class NotificationsFragment : } } } + + @Suppress("SyntheticAccessor") + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + newState != SCROLL_STATE_IDLE && return + + // Save the ID of the first notification visible in the list, so the user's + // reading position is always restorable. + layoutManager.findFirstVisibleItemPosition().takeIf { it >= 0 }?.let { position -> + adapter.snapshot().getOrNull(position)?.id?.let { id -> + viewModel.accept(InfallibleUiAction.SaveVisibleId(visibleId = id)) + } + } + } }) binding.recyclerView.adapter = adapter.withLoadStateHeaderAndFooter( diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsViewModel.kt b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsViewModel.kt index 329bce64..3c07ed01 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsViewModel.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsViewModel.kt @@ -455,17 +455,9 @@ class NotificationsViewModel @Inject constructor( } } - // The database stores "0" as the last notification ID if notifications have not been - // fetched. Convert to null to ensure a full fetch in this case - val lastNotificationId = when (val id = accountManager.activeAccount?.lastNotificationId) { - "0" -> null - else -> id - } - Log.d(TAG, "Restoring at $lastNotificationId") - pagingData = notificationFilter .flatMapLatest { action -> - getNotifications(filters = action.filter, initialKey = lastNotificationId) + getNotifications(filters = action.filter, initialKey = getInitialKey()) } .cachedIn(viewModelScope) @@ -499,6 +491,17 @@ class NotificationsViewModel @Inject constructor( } } + // The database stores "0" as the last notification ID if notifications have not been + // fetched. Convert to null to ensure a full fetch in this case + private fun getInitialKey(): String? { + val initialKey = when (val id = accountManager.activeAccount?.lastNotificationId) { + "0" -> null + else -> id + } + Log.d(TAG, "Restoring at $initialKey") + return initialKey + } + /** * @return Flow of relevant preferences that change the UI */