Make Timeline tab filters persistent (fixes #138)

This commit is contained in:
Shinokuni 2024-09-22 19:08:45 +02:00
parent 9b1f7339eb
commit 84a54224b5
3 changed files with 93 additions and 46 deletions

View File

@ -100,27 +100,49 @@ class TimelineScreenModel(
}
screenModelScope.launch(dispatcher) {
combine(
preferences.timelineItemSize.flow,
preferences.scrollRead.flow,
preferences.displayNotificationsPermission.flow
) { a, b, c -> Triple(a, b, c) }
.collect { (itemSize, scrollRead, notificationPermission) ->
getTimelinePreferences()
.collect { preferences ->
_timelineState.update {
it.copy(
itemSize = when (itemSize) {
"compact" -> TimelineItemSize.COMPACT
"regular" -> TimelineItemSize.REGULAR
else -> TimelineItemSize.LARGE
},
markReadOnScroll = scrollRead,
displayNotificationsPermission = notificationPermission
preferences = preferences,
filters = updateFilters {
it.filters.copy(
showReadItems = preferences.showReadItems,
orderField = preferences.orderField,
orderType = preferences.orderType
)
}
)
}
}
}
}
private fun getTimelinePreferences(): Flow<TimelinePreferences> {
return combine(
preferences.timelineItemSize.flow,
preferences.scrollRead.flow,
preferences.displayNotificationsPermission.flow,
preferences.showReadItems.flow,
preferences.orderField.flow,
preferences.orderType.flow,
transform = {
TimelinePreferences(
itemSize = when (it[0]) {
"compact" -> TimelineItemSize.COMPACT
"regular" -> TimelineItemSize.REGULAR
else -> TimelineItemSize.LARGE
},
markReadOnScroll = it[1] as Boolean,
displayNotificationsPermission = it[2] as Boolean,
showReadItems = it[3] as Boolean,
orderField = OrderField.valueOf(it[4] as String),
orderType = OrderType.valueOf(it[5] as String)
)
}
)
}
private fun buildPager(empty: Boolean = false) {
val query = ItemsQueryBuilder.buildItemsQuery(
filters.value,
@ -364,38 +386,36 @@ class TimelineScreenModel(
}
fun setShowReadItemsState(showReadItems: Boolean) {
screenModelScope.launch {
preferences.showReadItems.write(showReadItems)
_timelineState.update {
it.copy(
filters = updateFilters {
it.filters.copy(
showReadItems = showReadItems
filters = it.filters.copy(showReadItems = showReadItems)
)
}
)
}
}
fun setOrderFieldState(orderField: OrderField) {
screenModelScope.launch {
preferences.orderField.write(orderField.name)
_timelineState.update {
it.copy(
filters = updateFilters {
it.filters.copy(
orderField = orderField
filters = it.filters.copy(orderField = orderField)
)
}
)
}
}
fun setOrderTypeState(orderType: OrderType) {
screenModelScope.launch {
preferences.orderType.write(orderType.name)
_timelineState.update {
it.copy(
filters = updateFilters {
it.filters.copy(
orderType = orderType
)
it.copy(filters = it.filters.copy(orderType = orderType))
}
)
}
}
@ -437,9 +457,7 @@ data class TimelineState(
val dialog: DialogState? = null,
val isAccountLocal: Boolean = false,
val hideReadAllFAB: Boolean = false,
val itemSize: TimelineItemSize = TimelineItemSize.LARGE,
val markReadOnScroll: Boolean = false,
val displayNotificationsPermission: Boolean = false
val preferences: TimelinePreferences = TimelinePreferences()
) {
val showSubtitle = filters.subFilter != SubFilter.ALL
@ -447,6 +465,16 @@ data class TimelineState(
val displayRefreshScreen = isRefreshing && isAccountLocal
}
@Stable
data class TimelinePreferences(
val itemSize: TimelineItemSize = TimelineItemSize.LARGE,
val markReadOnScroll: Boolean = false,
val displayNotificationsPermission: Boolean = false,
val showReadItems: Boolean = true,
val orderField: OrderField = OrderField.DATE,
val orderType: OrderType = OrderType.DESC
)
sealed interface DialogState {
data object ConfirmDialog : DialogState
data object FilterSheet : DialogState

View File

@ -93,6 +93,7 @@ object TimelineTab : Tab {
val screenModel = getScreenModel<TimelineScreenModel>()
val state by screenModel.timelineState.collectAsStateWithLifecycle()
val preferences = state.preferences
val items = state.itemState.collectAsLazyPagingItems()
val lazyListState = rememberLazyListState()
@ -105,9 +106,9 @@ object TimelineTab : Tab {
screenModel.disableDisplayNotificationsPermission()
}
LaunchedEffect(state.displayNotificationsPermission) {
LaunchedEffect(preferences.displayNotificationsPermission) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU
&& state.displayNotificationsPermission
&& preferences.displayNotificationsPermission
) {
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
@ -372,21 +373,21 @@ object TimelineTab : Tab {
MarkItemsRead(
lazyListState = lazyListState,
items = items,
markReadOnScroll = state.markReadOnScroll,
markReadOnScroll = preferences.markReadOnScroll,
screenModel = screenModel
)
LazyColumn(
state = lazyListState,
contentPadding = PaddingValues(
vertical = if (state.itemSize == TimelineItemSize.COMPACT) {
vertical = if (preferences.itemSize == TimelineItemSize.COMPACT) {
0.dp
} else {
MaterialTheme.spacing.shortSpacing
}
),
verticalArrangement = Arrangement.spacedBy(
if (state.itemSize == TimelineItemSize.COMPACT) {
if (preferences.itemSize == TimelineItemSize.COMPACT) {
0.dp
} else
MaterialTheme.spacing.shortSpacing
@ -417,7 +418,7 @@ object TimelineTab : Tab {
onSetReadState = {
screenModel.updateItemReadState(itemWithFeed.item)
},
size = state.itemSize
size = preferences.itemSize
)
}
}

View File

@ -73,6 +73,24 @@ class Preferences(
key = intPreferencesKey("last_version_code"),
default = 0
)
val showReadItems = Preference(
dataStore = dataStore,
key = booleanPreferencesKey("show_read_items"),
default = true
)
val orderField = Preference(
dataStore = dataStore,
key = stringPreferencesKey("order_field"),
default = "DATE" // or "ID", uppercase important, used with Enum.valueOf()
)
val orderType = Preference(
dataStore = dataStore,
key = stringPreferencesKey("order_type"),
default = "DESC" // or "ASC", uppercase important, used with Enum.valueOf()
)
}