Skip to content

Commit 6fee533

Browse files
author
Ink
committed
+ add "stable" Ids for conditions items
1 parent 9301d2d commit 6fee533

File tree

3 files changed

+70
-33
lines changed

3 files changed

+70
-33
lines changed

mobile/src/main/java/com/damn/anotherglass/extensions/notifications/filter/Filter.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package com.damn.anotherglass.extensions.notifications.filter
33
import com.google.gson.annotations.SerializedName
44
import java.util.UUID
55

6+
// We probably could do better with much simpler fixed fields filter class,
7+
// since this one can create logical conflicts like having two opposite Ongoing conditions
8+
69

710
enum class ConditionType {
811
@SerializedName("title_contains")

mobile/src/main/java/com/damn/anotherglass/ui/notifications/editfilter/FilterEditScreen.kt

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,11 @@ fun FilterEditScreen(
172172
verticalAlignment = Alignment.CenterVertically,
173173
horizontalArrangement = Arrangement.SpaceBetween
174174
) {
175-
Text("Match:",
175+
Text(
176+
"Match:",
176177
style = MaterialTheme.typography.bodyLarge,
177-
modifier = Modifier.weight(1f))
178+
modifier = Modifier.weight(1f)
179+
)
178180
Row(verticalAlignment = Alignment.CenterVertically) {
179181
RadioButton(
180182
selected = matchAllConditions,
@@ -223,9 +225,9 @@ fun FilterEditScreen(
223225
} else {
224226
itemsIndexed(
225227
viewModel.conditions,
226-
key = { _, item -> item.hashCode() /* Assuming FilterConditionItem has a unique ID */ }) { index, conditionItem ->
228+
key = { _, item -> item.id }) { index, conditionItem ->
227229
ConditionEditItemView(
228-
conditionItem = conditionItem,
230+
conditionItem = conditionItem.condition,
229231
availableTypes = viewModel.availableConditionTypes,
230232
onTypeChange = { newType -> viewModel.updateConditionType(index, newType) },
231233
onValueChange = { newValue ->
@@ -255,15 +257,22 @@ fun FilterEditScreenPreview_NewFilter() {
255257
)
256258
// Simulate pre-fill from notification
257259
previewViewModel.conditions.add(
258-
FilterConditionItem(
259-
type = ConditionType.TITLE_CONTAINS,
260-
value = "Important News"
260+
FilterConditionVM(
261+
id = previewViewModel.conditions.size.toString(),
262+
FilterConditionItem(
263+
type = ConditionType.TITLE_CONTAINS,
264+
value = "Important News"
265+
)
261266
)
267+
262268
)
263269
previewViewModel.conditions.add(
264-
FilterConditionItem(
265-
type = ConditionType.TEXT_CONTAINS,
266-
value = "Order Confirmation"
270+
FilterConditionVM(
271+
id = previewViewModel.conditions.size.toString(),
272+
FilterConditionItem(
273+
type = ConditionType.TEXT_CONTAINS,
274+
value = "Order Confirmation"
275+
)
267276
)
268277
)
269278
previewViewModel.filterName.value = "Filter from News"
@@ -294,15 +303,21 @@ fun FilterEditScreenPreview_ExistingFilter() {
294303
previewViewModel.isFilterEnabled.value = false
295304
previewViewModel.matchAllConditions.value = false // OR
296305
previewViewModel.conditions.add(
297-
FilterConditionItem(
298-
type = ConditionType.TEXT_CONTAINS,
299-
value = "urgent"
306+
FilterConditionVM(
307+
id = previewViewModel.conditions.size.toString(),
308+
FilterConditionItem(
309+
type = ConditionType.TEXT_CONTAINS,
310+
value = "urgent"
311+
)
300312
)
301313
)
302314
previewViewModel.conditions.add(
303-
FilterConditionItem(
304-
type = ConditionType.IS_ONGOING_EQUALS,
305-
value = "true"
315+
FilterConditionVM(
316+
id = previewViewModel.conditions.size.toString(),
317+
FilterConditionItem(
318+
type = ConditionType.IS_ONGOING_EQUALS,
319+
value = "true"
320+
)
306321
)
307322
)
308323

mobile/src/main/java/com/damn/anotherglass/ui/notifications/editfilter/FilterEditViewModel.kt

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ import java.util.UUID
2020
import kotlin.io.encoding.Base64
2121
import kotlin.io.encoding.ExperimentalEncodingApi
2222

23+
// wrapper to have stable ID for each condition item to preserve focus
24+
data class FilterConditionVM(
25+
val id: String,
26+
val condition: FilterConditionItem,
27+
)
28+
2329
class FilterEditViewModel(
2430
private val savedStateHandle: SavedStateHandle,
2531
private val filterRepository: IFilterRepository
@@ -31,9 +37,8 @@ class FilterEditViewModel(
3137
val packageName = mutableStateOf("")
3238
val isFilterEnabled = mutableStateOf(true)
3339
val matchAllConditions = mutableStateOf(true) // true for AND, false for OR
34-
val conditions = mutableStateListOf<FilterConditionItem>()
35-
val filterAction =
36-
mutableStateOf(FilterAction.BLOCK) // Add state for the action, default to BLOCK
40+
val conditions = mutableStateListOf<FilterConditionVM>()
41+
val filterAction = mutableStateOf(FilterAction.BLOCK) // Add state for the action, default to BLOCK
3742

3843
val availableConditionTypes: List<ConditionType> = ConditionType.entries
3944
val availableFilterActions: List<FilterAction> = FilterAction.entries
@@ -64,12 +69,13 @@ class FilterEditViewModel(
6469
?.urlDecode()
6570
?.let { value ->
6671
if (value.isNotBlank()) {
67-
conditions.add(
72+
conditions.add(FilterConditionVM(
73+
id = UUID.randomUUID().toString(),
6874
FilterConditionItem(
6975
type = conditionType,
7076
value = value
7177
)
72-
)
78+
))
7379
}
7480
}
7581
}
@@ -79,10 +85,12 @@ class FilterEditViewModel(
7985
savedStateHandle[AppRoute.FilterEditScreen.FILTER_EDIT_ARG_IS_ONGOING]
8086
?: false
8187
conditions.add(
88+
FilterConditionVM(
89+
id = UUID.randomUUID().toString(),
8290
FilterConditionItem(
8391
type = ConditionType.IS_ONGOING_EQUALS,
8492
value = isOngoingFromNav.toString()
85-
)
93+
))
8694
)
8795
}
8896

@@ -106,39 +114,50 @@ class FilterEditViewModel(
106114
isFilterEnabled.value = loadedFilter.isEnabled
107115
matchAllConditions.value = loadedFilter.matchAllConditions
108116
conditions.clear()
109-
conditions.addAll(loadedFilter.conditions)
117+
conditions.addAll(loadedFilter.conditions.mapIndexed {
118+
index, condition ->
119+
FilterConditionVM(
120+
id = UUID.randomUUID().toString(),
121+
condition = condition
122+
)
123+
})
110124
filterAction.value = loadedFilter.action // Load the action
111125
}
112126
}
113127

114128
fun addCondition() {
115-
conditions.add(FilterConditionItem(type = ConditionType.TITLE_CONTAINS, value = ""))
129+
conditions.add(
130+
FilterConditionVM(
131+
id = UUID.randomUUID().toString(),
132+
FilterConditionItem(type = ConditionType.TITLE_CONTAINS, value = "")
133+
)
134+
)
116135
}
117136

118-
fun removeCondition(item: FilterConditionItem) {
137+
fun removeCondition(item: FilterConditionVM) {
119138
conditions.remove(item)
120139
}
121140

122141
fun updateConditionType(index: Int, newType: ConditionType) {
123142
if (index in conditions.indices) {
124-
val currentItem = conditions[index]
143+
val item = conditions[index]
125144
when {
126145
// If changing from IS_ONGOING_EQUALS, reset value to empty string
127-
currentItem.type == ConditionType.IS_ONGOING_EQUALS && newType != ConditionType.IS_ONGOING_EQUALS ->
128-
conditions[index] = currentItem.copy(type = newType, value = "")
146+
item.condition.type == ConditionType.IS_ONGOING_EQUALS && newType != ConditionType.IS_ONGOING_EQUALS ->
147+
conditions[index] = item.copy(condition = item.condition.copy(type = newType, value = ""))
129148
// If changing to IS_ONGOING_EQUALS, reset value to false
130-
currentItem.type != ConditionType.IS_ONGOING_EQUALS && newType == ConditionType.IS_ONGOING_EQUALS -> {
131-
conditions[index] = currentItem.copy(type = newType, value = "false")
149+
item.condition.type != ConditionType.IS_ONGOING_EQUALS && newType == ConditionType.IS_ONGOING_EQUALS -> {
150+
conditions[index] = item.copy(condition = item.condition.copy(type = newType, value = "false"))
132151
}
133-
else -> conditions[index] = currentItem.copy(type = newType)
152+
else -> conditions[index] = item.copy(condition = item.condition.copy(type = newType))
134153
}
135154
}
136155
}
137156

138157
fun updateConditionValue(index: Int, newValue: String) {
139158
if (index in conditions.indices) {
140159
val currentItem = conditions[index]
141-
conditions[index] = currentItem.copy(value = newValue)
160+
conditions[index] = currentItem.copy(condition = currentItem.condition.copy(value = newValue))
142161
}
143162
}
144163

@@ -151,7 +170,7 @@ class FilterEditViewModel(
151170
isEnabled = isFilterEnabled.value,
152171
matchAllConditions = matchAllConditions.value,
153172
// todo: filter empty conditions
154-
conditions = ArrayList(conditions),
173+
conditions = conditions.map { it.condition },
155174
action = filterAction.value
156175
)
157176

0 commit comments

Comments
 (0)