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()
|
onRefresh()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
R.id.load_newest -> {
|
||||||
|
viewModel.accept(InfallibleUiAction.LoadNewest)
|
||||||
|
true
|
||||||
|
}
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.filterIsInstance
|
import kotlinx.coroutines.flow.filterIsInstance
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.getAndUpdate
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.onStart
|
import kotlinx.coroutines.flow.onStart
|
||||||
|
@ -123,6 +124,12 @@ sealed class InfallibleUiAction : UiAction() {
|
||||||
* can do.
|
* can do.
|
||||||
*/
|
*/
|
||||||
data class SaveVisibleId(val visibleId: String) : InfallibleUiAction()
|
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. */
|
/** 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 */
|
/** Flow of user actions received from the UI */
|
||||||
private val uiAction = MutableSharedFlow<UiAction>()
|
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 */
|
/** Flow of successful action results */
|
||||||
// Note: This is a SharedFlow instead of a StateFlow because success state does not need to be
|
// 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
|
// 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
|
// Save the visible notification ID
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
uiAction
|
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 ->
|
.flatMapLatest { action ->
|
||||||
getNotifications(filters = action.filter, initialKey = getInitialKey())
|
getNotifications(filters = action.filter, initialKey = getInitialKey())
|
||||||
}
|
}.cachedIn(viewModelScope)
|
||||||
.cachedIn(viewModelScope)
|
|
||||||
|
|
||||||
uiState = combine(notificationFilter, getUiPrefs()) { filter, prefs ->
|
uiState = combine(notificationFilter, getUiPrefs()) { filter, prefs ->
|
||||||
UiState(
|
UiState(
|
||||||
|
|
|
@ -22,4 +22,9 @@
|
||||||
android:id="@+id/action_refresh"
|
android:id="@+id/action_refresh"
|
||||||
android:title="@string/action_refresh"
|
android:title="@string/action_refresh"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/load_newest"
|
||||||
|
android:title="@string/load_newest_notifications"
|
||||||
|
app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -810,4 +810,5 @@
|
||||||
you follow.\n\nTo explore accounts you can either discover them in one of the other timelines.
|
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
|
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>
|
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>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue