Add a menu option to load the newest notifications (#3708)
- Create a flow with new items (arbitrary ints) when a reload from the top should happen - Combine this flow with notificationFilter, so changes to either of them trigger a reload - Provide a menu item in NotificationsFragment to initiate the reload - Handle the action in the view model
This commit is contained in:
parent
4cddd2c5e6
commit
5755801e6f
4 changed files with 36 additions and 3 deletions
|
@ -454,6 +454,10 @@ class NotificationsFragment :
|
|||
onRefresh()
|
||||
true
|
||||
}
|
||||
R.id.load_newest -> {
|
||||
viewModel.accept(InfallibleUiAction.LoadNewest)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
|
|||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.getAndUpdate
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
|
@ -123,6 +124,12 @@ sealed class InfallibleUiAction : UiAction() {
|
|||
* can do.
|
||||
*/
|
||||
data class SaveVisibleId(val visibleId: String) : InfallibleUiAction()
|
||||
|
||||
/** Ignore the saved reading position, load the page with the newest items */
|
||||
// Resets the account's `lastNotificationId`, which can't fail, which is why this is
|
||||
// infallible. Reloading the data may fail, but that's handled by the paging system /
|
||||
// adapter refresh logic.
|
||||
object LoadNewest : InfallibleUiAction()
|
||||
}
|
||||
|
||||
/** Actions the user can trigger on an individual notification. These may fail. */
|
||||
|
@ -300,6 +307,9 @@ class NotificationsViewModel @Inject constructor(
|
|||
/** Flow of user actions received from the UI */
|
||||
private val uiAction = MutableSharedFlow<UiAction>()
|
||||
|
||||
/** Flow that can be used to trigger a full reload */
|
||||
private val reload = MutableStateFlow(0)
|
||||
|
||||
/** Flow of successful action results */
|
||||
// Note: This is a SharedFlow instead of a StateFlow because success state does not need to be
|
||||
// retained. A message is shown once to a user and then dismissed. Re-collecting the flow
|
||||
|
@ -342,6 +352,18 @@ class NotificationsViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
// Reset the last notification ID to "0" to fetch the newest notifications, and
|
||||
// increment `reload` to trigger creation of a new PagingSource.
|
||||
viewModelScope.launch {
|
||||
uiAction
|
||||
.filterIsInstance<InfallibleUiAction.LoadNewest>()
|
||||
.collectLatest {
|
||||
account.lastNotificationId = "0"
|
||||
accountManager.saveAccount(account)
|
||||
reload.getAndUpdate { it + 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Save the visible notification ID
|
||||
viewModelScope.launch {
|
||||
uiAction
|
||||
|
@ -465,11 +487,12 @@ class NotificationsViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
pagingData = notificationFilter
|
||||
// Re-fetch notifications if either of `notificationFilter` or `reload` flows have
|
||||
// new items.
|
||||
pagingData = combine(notificationFilter, reload) { action, _ -> action }
|
||||
.flatMapLatest { action ->
|
||||
getNotifications(filters = action.filter, initialKey = getInitialKey())
|
||||
}
|
||||
.cachedIn(viewModelScope)
|
||||
}.cachedIn(viewModelScope)
|
||||
|
||||
uiState = combine(notificationFilter, getUiPrefs()) { filter, prefs ->
|
||||
UiState(
|
||||
|
|
|
@ -22,4 +22,9 @@
|
|||
android:id="@+id/action_refresh"
|
||||
android:title="@string/action_refresh"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/load_newest"
|
||||
android:title="@string/load_newest_notifications"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
|
|
|
@ -810,4 +810,5 @@
|
|||
you follow.\n\nTo explore accounts you can either discover them in one of the other timelines.
|
||||
For example the local timeline of your instance [iconics gmd_group]. Or you can search them
|
||||
by name [iconics gmd_search]; for example search for Tusky to find our Mastodon account.</string>
|
||||
<string name="load_newest_notifications">Load newest notifications</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue