Add ViewModel for push rules settings fragment

This commit is contained in:
Florian Renaud 2023-02-09 11:32:24 +01:00
parent 1f5df94c37
commit 40119733b9
6 changed files with 191 additions and 32 deletions

View file

@ -108,6 +108,7 @@ import im.vector.app.features.settings.labs.VectorSettingsLabsViewModel
import im.vector.app.features.settings.legals.LegalsViewModel
import im.vector.app.features.settings.locale.LocalePickerViewModel
import im.vector.app.features.settings.notifications.VectorSettingsNotificationPreferenceViewModel
import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationPreferenceViewModel
import im.vector.app.features.settings.push.PushGatewaysViewModel
import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel
import im.vector.app.features.share.IncomingShareViewModel
@ -694,6 +695,13 @@ interface MavericksViewModelModule {
factory: VectorSettingsNotificationPreferenceViewModel.Factory
): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(VectorSettingsPushRuleNotificationPreferenceViewModel::class)
fun vectorSettingsPushRuleNotificationPreferenceViewModelFactory(
factory: VectorSettingsPushRuleNotificationPreferenceViewModel.Factory
): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(SetLinkViewModel::class)

View file

@ -16,19 +16,36 @@
package im.vector.app.features.settings.notifications
import androidx.lifecycle.lifecycleScope
import android.os.Bundle
import android.view.View
import androidx.preference.Preference
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.app.core.preference.VectorCheckboxPreference
import im.vector.app.features.settings.VectorSettingsBaseFragment
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.pushrules.RuleKind
import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind
abstract class VectorSettingsPushRuleNotificationPreferenceFragment :
VectorSettingsBaseFragment() {
private val viewModel: VectorSettingsPushRuleNotificationPreferenceViewModel by fragmentViewModel()
abstract val prefKeyToPushRuleId: Map<String, String>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
observeViewEvents()
}
private fun observeViewEvents() {
viewModel.observeViewEvents {
when (it) {
is VectorSettingsPushRuleNotificationPreferenceViewEvent.Failure -> refreshDisplay()
is VectorSettingsPushRuleNotificationPreferenceViewEvent.PushRuleUpdated -> updatePreference(it.ruleId, it.enabled)
}
}
}
override fun bindPref() {
for (preferenceKey in prefKeyToPushRuleId.keys) {
val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
@ -42,45 +59,29 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment :
val initialIndex = ruleAndKind.pushRule.notificationIndex
preference.isChecked = initialIndex != NotificationIndex.OFF
preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
updatePushRule(ruleAndKind.pushRule.ruleId, ruleAndKind.kind, newValue as Boolean, preference)
viewModel.handle(VectorSettingsPushRuleNotificationPreferenceViewAction.UpdatePushRule(ruleAndKind, newValue as Boolean))
false
}
}
}
}
fun updatePushRule(ruleId: String, kind: RuleKind, checked: Boolean, preference: VectorCheckboxPreference) {
val newIndex = if (checked) NotificationIndex.NOISY else NotificationIndex.OFF
val standardAction = getStandardAction(ruleId, newIndex) ?: return
val enabled = standardAction != StandardActions.Disabled
val newActions = standardAction.actions
displayLoadingView()
lifecycleScope.launch {
val result = runCatching {
session.pushRuleService().updatePushRuleActions(
kind,
ruleId,
enabled,
newActions
)
}
override fun invalidate() = withState(viewModel) { state ->
if (state.isLoading) {
displayLoadingView()
} else {
hideLoadingView()
if (!isAdded) {
return@launch
}
result.onSuccess {
preference.isChecked = checked
}
result.onFailure { failure ->
// Restore the previous value
refreshDisplay()
displayErrorDialog(failure)
}
}
}
fun refreshDisplay() {
protected fun refreshDisplay() {
listView?.adapter?.notifyDataSetChanged()
}
private fun updatePreference(ruleId: String, checked: Boolean) {
val preferenceKey = prefKeyToPushRuleId.entries.find { it.value == ruleId }?.key ?: return
val preference = findPreference<VectorCheckboxPreference>(preferenceKey) ?: return
preference.isChecked = checked
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.settings.notifications
import im.vector.app.core.platform.VectorViewModelAction
import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind
sealed interface VectorSettingsPushRuleNotificationPreferenceViewAction : VectorViewModelAction {
data class UpdatePushRule(val pushRuleAndKind: PushRuleAndKind, val checked: Boolean) : VectorSettingsPushRuleNotificationPreferenceViewAction
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.settings.notifications
import im.vector.app.core.platform.VectorViewEvents
sealed interface VectorSettingsPushRuleNotificationPreferenceViewEvent : VectorViewEvents {
data class PushRuleUpdated(val ruleId: String, val enabled: Boolean) : VectorSettingsPushRuleNotificationPreferenceViewEvent
data class Failure(val throwable: Throwable) : VectorSettingsPushRuleNotificationPreferenceViewEvent
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.settings.notifications
import com.airbnb.mvrx.MavericksViewModelFactory
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind
class VectorSettingsPushRuleNotificationPreferenceViewModel @AssistedInject constructor(
@Assisted initialState: VectorSettingsPushRuleNotificationPreferenceViewState,
private val activeSessionHolder: ActiveSessionHolder,
) : VectorViewModel<VectorSettingsPushRuleNotificationPreferenceViewState,
VectorSettingsPushRuleNotificationPreferenceViewAction,
VectorSettingsPushRuleNotificationPreferenceViewEvent>(initialState) {
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<VectorSettingsPushRuleNotificationPreferenceViewModel, VectorSettingsPushRuleNotificationPreferenceViewState> {
override fun create(initialState: VectorSettingsPushRuleNotificationPreferenceViewState): VectorSettingsPushRuleNotificationPreferenceViewModel
}
companion object : MavericksViewModelFactory<VectorSettingsPushRuleNotificationPreferenceViewModel, VectorSettingsPushRuleNotificationPreferenceViewState> by hiltMavericksViewModelFactory()
override fun handle(action: VectorSettingsPushRuleNotificationPreferenceViewAction) {
when (action) {
is VectorSettingsPushRuleNotificationPreferenceViewAction.UpdatePushRule -> handleUpdatePushRule(action.pushRuleAndKind, action.checked)
}
}
private fun handleUpdatePushRule(pushRuleAndKind: PushRuleAndKind, checked: Boolean) {
val ruleId = pushRuleAndKind.pushRule.ruleId
val kind = pushRuleAndKind.kind
val newIndex = if (checked) NotificationIndex.NOISY else NotificationIndex.OFF
val standardAction = getStandardAction(ruleId, newIndex) ?: return
val enabled = standardAction != StandardActions.Disabled
val newActions = standardAction.actions
setState { copy(isLoading = true) }
viewModelScope.launch {
runCatching {
activeSessionHolder.getSafeActiveSession()?.pushRuleService()?.updatePushRuleActions(
kind = kind,
ruleId = ruleId,
enable = enabled,
actions = newActions
)
}.fold(
onSuccess = {
setState { copy(isLoading = false) }
_viewEvents.post(VectorSettingsPushRuleNotificationPreferenceViewEvent.PushRuleUpdated(ruleId, checked))
},
onFailure = { failure ->
setState { copy(isLoading = false) }
_viewEvents.post(VectorSettingsPushRuleNotificationPreferenceViewEvent.Failure(failure))
}
)
}
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.settings.notifications
import com.airbnb.mvrx.MavericksState
data class VectorSettingsPushRuleNotificationPreferenceViewState(
val isLoading: Boolean = false,
): MavericksState