@@ -16,8 +16,9 @@ import com.damn.anotherglass.extensions.notifications.filter.from
1616import com.damn.anotherglass.ui.notifications.AppRoute
1717import kotlinx.coroutines.flow.firstOrNull
1818import kotlinx.coroutines.launch
19- import java.net.URLDecoder
2019import java.util.UUID
20+ import kotlin.io.encoding.Base64
21+ import kotlin.io.encoding.ExperimentalEncodingApi
2122
2223class FilterEditViewModel (
2324 private val savedStateHandle : SavedStateHandle ,
@@ -41,8 +42,7 @@ class FilterEditViewModel(
4142
4243 init {
4344 viewModelScope.launch {
44- val existingFilterId: String? =
45- savedStateHandle[AppRoute .FilterEditScreen .FILTER_EDIT_ARG_FILTER_ID ]
45+ val existingFilterId: String? = savedStateHandle.get<String >(AppRoute .FilterEditScreen .FILTER_EDIT_ARG_FILTER_ID )?.urlDecode()
4646 if (existingFilterId != null ) {
4747 isNewFilter = false
4848 filterId.value = existingFilterId
@@ -52,7 +52,7 @@ class FilterEditViewModel(
5252
5353 // Set package name from navigation arguments
5454 savedStateHandle.get<String >(AppRoute .FilterEditScreen .FILTER_EDIT_ARG_PACKAGE_NAME )
55- ?.urlDecodeFix ()
55+ ?.urlDecode ()
5656 ?.let { value ->
5757 if (value.isNotBlank()) {
5858 packageName.value = value
@@ -61,7 +61,7 @@ class FilterEditViewModel(
6161
6262 ARG_TO_CONDITION_MAP .forEach { (argKey, conditionType) ->
6363 savedStateHandle.get<String >(argKey)
64- ?.urlDecodeFix ()
64+ ?.urlDecode ()
6565 ?.let { value ->
6666 if (value.isNotBlank()) {
6767 conditions.add(
@@ -122,7 +122,16 @@ class FilterEditViewModel(
122122 fun updateConditionType (index : Int , newType : ConditionType ) {
123123 if (index in conditions.indices) {
124124 val currentItem = conditions[index]
125- conditions[index] = currentItem.copy(type = newType)
125+ when {
126+ // 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 = " " )
129+ // 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" )
132+ }
133+ else -> conditions[index] = currentItem.copy(type = newType)
134+ }
126135 }
127136 }
128137
@@ -156,15 +165,23 @@ class FilterEditViewModel(
156165 }
157166
158167 companion object {
168+
159169 private val ARG_TO_CONDITION_MAP = mapOf (
160170 AppRoute .FilterEditScreen .FILTER_EDIT_ARG_TITLE to ConditionType .TITLE_CONTAINS ,
161171 AppRoute .FilterEditScreen .FILTER_EDIT_ARG_TEXT to ConditionType .TEXT_CONTAINS ,
162172 AppRoute .FilterEditScreen .FILTER_EDIT_ARG_TICKER_TEXT to ConditionType .TICKER_TEXT_CONTAINS
163173 // AppRoute.FilterEditScreen.FILTER_EDIT_ARG_IS_ONGOING is handled separately due to Boolean type
164174 )
165175
166- private fun String?.urlDecodeFix (): String? =
167- this ?.let { URLDecoder .decode(it, " UTF-8" ).replace(" +" , " " ) }
176+ @OptIn(ExperimentalEncodingApi ::class )
177+ fun String?.urlDecode (): String? =
178+ this ?.let {
179+ Base64 .Default .decode(it).decodeToString()
180+ }
181+
182+ // URLEncoder has issues with % (it assumes its already encoded), so we use Base64 for URL encoding
183+ @OptIn(ExperimentalEncodingApi ::class )
184+ fun String.urlEncode (): String = Base64 .Default .encode(encodeToByteArray())
168185
169186 class Factory (
170187 private val context : Context ,
0 commit comments