mirror of https://github.com/readrops/Readrops.git
Make Timeline tab filters persistent (fixes #138)
This commit is contained in:
parent
9b1f7339eb
commit
84a54224b5
|
@ -100,27 +100,49 @@ class TimelineScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
screenModelScope.launch(dispatcher) {
|
screenModelScope.launch(dispatcher) {
|
||||||
combine(
|
getTimelinePreferences()
|
||||||
preferences.timelineItemSize.flow,
|
.collect { preferences ->
|
||||||
preferences.scrollRead.flow,
|
|
||||||
preferences.displayNotificationsPermission.flow
|
|
||||||
) { a, b, c -> Triple(a, b, c) }
|
|
||||||
.collect { (itemSize, scrollRead, notificationPermission) ->
|
|
||||||
_timelineState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
itemSize = when (itemSize) {
|
preferences = preferences,
|
||||||
"compact" -> TimelineItemSize.COMPACT
|
filters = updateFilters {
|
||||||
"regular" -> TimelineItemSize.REGULAR
|
it.filters.copy(
|
||||||
else -> TimelineItemSize.LARGE
|
showReadItems = preferences.showReadItems,
|
||||||
},
|
orderField = preferences.orderField,
|
||||||
markReadOnScroll = scrollRead,
|
orderType = preferences.orderType
|
||||||
displayNotificationsPermission = notificationPermission
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
private fun buildPager(empty: Boolean = false) {
|
||||||
val query = ItemsQueryBuilder.buildItemsQuery(
|
val query = ItemsQueryBuilder.buildItemsQuery(
|
||||||
filters.value,
|
filters.value,
|
||||||
|
@ -364,38 +386,36 @@ class TimelineScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setShowReadItemsState(showReadItems: Boolean) {
|
fun setShowReadItemsState(showReadItems: Boolean) {
|
||||||
|
screenModelScope.launch {
|
||||||
|
preferences.showReadItems.write(showReadItems)
|
||||||
|
|
||||||
_timelineState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
filters = updateFilters {
|
filters = it.filters.copy(showReadItems = showReadItems)
|
||||||
it.filters.copy(
|
|
||||||
showReadItems = showReadItems
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOrderFieldState(orderField: OrderField) {
|
fun setOrderFieldState(orderField: OrderField) {
|
||||||
|
screenModelScope.launch {
|
||||||
|
preferences.orderField.write(orderField.name)
|
||||||
|
|
||||||
_timelineState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
filters = updateFilters {
|
filters = it.filters.copy(orderField = orderField)
|
||||||
it.filters.copy(
|
|
||||||
orderField = orderField
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOrderTypeState(orderType: OrderType) {
|
fun setOrderTypeState(orderType: OrderType) {
|
||||||
|
screenModelScope.launch {
|
||||||
|
preferences.orderType.write(orderType.name)
|
||||||
|
|
||||||
_timelineState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(filters = it.filters.copy(orderType = orderType))
|
||||||
filters = updateFilters {
|
|
||||||
it.filters.copy(
|
|
||||||
orderType = orderType
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,9 +457,7 @@ data class TimelineState(
|
||||||
val dialog: DialogState? = null,
|
val dialog: DialogState? = null,
|
||||||
val isAccountLocal: Boolean = false,
|
val isAccountLocal: Boolean = false,
|
||||||
val hideReadAllFAB: Boolean = false,
|
val hideReadAllFAB: Boolean = false,
|
||||||
val itemSize: TimelineItemSize = TimelineItemSize.LARGE,
|
val preferences: TimelinePreferences = TimelinePreferences()
|
||||||
val markReadOnScroll: Boolean = false,
|
|
||||||
val displayNotificationsPermission: Boolean = false
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val showSubtitle = filters.subFilter != SubFilter.ALL
|
val showSubtitle = filters.subFilter != SubFilter.ALL
|
||||||
|
@ -447,6 +465,16 @@ data class TimelineState(
|
||||||
val displayRefreshScreen = isRefreshing && isAccountLocal
|
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 {
|
sealed interface DialogState {
|
||||||
data object ConfirmDialog : DialogState
|
data object ConfirmDialog : DialogState
|
||||||
data object FilterSheet : DialogState
|
data object FilterSheet : DialogState
|
||||||
|
|
|
@ -93,6 +93,7 @@ object TimelineTab : Tab {
|
||||||
|
|
||||||
val screenModel = getScreenModel<TimelineScreenModel>()
|
val screenModel = getScreenModel<TimelineScreenModel>()
|
||||||
val state by screenModel.timelineState.collectAsStateWithLifecycle()
|
val state by screenModel.timelineState.collectAsStateWithLifecycle()
|
||||||
|
val preferences = state.preferences
|
||||||
val items = state.itemState.collectAsLazyPagingItems()
|
val items = state.itemState.collectAsLazyPagingItems()
|
||||||
|
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
|
@ -105,9 +106,9 @@ object TimelineTab : Tab {
|
||||||
screenModel.disableDisplayNotificationsPermission()
|
screenModel.disableDisplayNotificationsPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(state.displayNotificationsPermission) {
|
LaunchedEffect(preferences.displayNotificationsPermission) {
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU
|
||||||
&& state.displayNotificationsPermission
|
&& preferences.displayNotificationsPermission
|
||||||
) {
|
) {
|
||||||
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
}
|
}
|
||||||
|
@ -372,21 +373,21 @@ object TimelineTab : Tab {
|
||||||
MarkItemsRead(
|
MarkItemsRead(
|
||||||
lazyListState = lazyListState,
|
lazyListState = lazyListState,
|
||||||
items = items,
|
items = items,
|
||||||
markReadOnScroll = state.markReadOnScroll,
|
markReadOnScroll = preferences.markReadOnScroll,
|
||||||
screenModel = screenModel
|
screenModel = screenModel
|
||||||
)
|
)
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = lazyListState,
|
state = lazyListState,
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
vertical = if (state.itemSize == TimelineItemSize.COMPACT) {
|
vertical = if (preferences.itemSize == TimelineItemSize.COMPACT) {
|
||||||
0.dp
|
0.dp
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.spacing.shortSpacing
|
MaterialTheme.spacing.shortSpacing
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(
|
verticalArrangement = Arrangement.spacedBy(
|
||||||
if (state.itemSize == TimelineItemSize.COMPACT) {
|
if (preferences.itemSize == TimelineItemSize.COMPACT) {
|
||||||
0.dp
|
0.dp
|
||||||
} else
|
} else
|
||||||
MaterialTheme.spacing.shortSpacing
|
MaterialTheme.spacing.shortSpacing
|
||||||
|
@ -417,7 +418,7 @@ object TimelineTab : Tab {
|
||||||
onSetReadState = {
|
onSetReadState = {
|
||||||
screenModel.updateItemReadState(itemWithFeed.item)
|
screenModel.updateItemReadState(itemWithFeed.item)
|
||||||
},
|
},
|
||||||
size = state.itemSize
|
size = preferences.itemSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,24 @@ class Preferences(
|
||||||
key = intPreferencesKey("last_version_code"),
|
key = intPreferencesKey("last_version_code"),
|
||||||
default = 0
|
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()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue