Sync poll rules with messages rule
This commit is contained in:
parent
1c47983a99
commit
71455706cb
|
@ -47,8 +47,36 @@ object RuleIds {
|
||||||
const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
|
const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
|
||||||
const val RULE_ID_ENCRYPTED = ".m.rule.encrypted"
|
const val RULE_ID_ENCRYPTED = ".m.rule.encrypted"
|
||||||
|
|
||||||
|
const val RULE_ID_POLL_START_ONE_TO_ONE = ".m.rule.poll_start_one_to_one"
|
||||||
|
const val RULE_ID_POLL_START_ONE_TO_ONE_UNSTABLE = ".org.matrix.msc3930.rule.poll_start_one_to_one"
|
||||||
|
const val RULE_ID_POLL_END_ONE_TO_ONE = ".m.rule.poll_end_one_to_one"
|
||||||
|
const val RULE_ID_POLL_END_ONE_TO_ONE_UNSTABLE = ".org.matrix.msc3930.rule.poll_end_one_to_one"
|
||||||
|
|
||||||
|
const val RULE_ID_POLL_START = ".m.rule.poll_start"
|
||||||
|
const val RULE_ID_POLL_START_UNSTABLE = ".org.matrix.msc3930.rule.poll_start"
|
||||||
|
const val RULE_ID_POLL_END = ".m.rule.poll_end"
|
||||||
|
const val RULE_ID_POLL_END_UNSTABLE = ".org.matrix.msc3930.rule.poll_end"
|
||||||
|
|
||||||
// Not documented
|
// Not documented
|
||||||
const val RULE_ID_FALLBACK = ".m.rule.fallback"
|
const val RULE_ID_FALLBACK = ".m.rule.fallback"
|
||||||
|
|
||||||
const val RULE_ID_REACTION = ".m.rule.reaction"
|
const val RULE_ID_REACTION = ".m.rule.reaction"
|
||||||
|
|
||||||
|
fun getSyncedRules(ruleId: String): List<String> {
|
||||||
|
return when (ruleId) {
|
||||||
|
RULE_ID_ONE_TO_ONE_ROOM -> listOf(
|
||||||
|
RULE_ID_POLL_START_ONE_TO_ONE,
|
||||||
|
RULE_ID_POLL_START_ONE_TO_ONE_UNSTABLE,
|
||||||
|
RULE_ID_POLL_END_ONE_TO_ONE,
|
||||||
|
RULE_ID_POLL_END_ONE_TO_ONE_UNSTABLE,
|
||||||
|
)
|
||||||
|
RULE_ID_ALL_OTHER_MESSAGES_ROOMS -> listOf(
|
||||||
|
RULE_ID_POLL_START,
|
||||||
|
RULE_ID_POLL_START_UNSTABLE,
|
||||||
|
RULE_ID_POLL_END,
|
||||||
|
RULE_ID_POLL_END_UNSTABLE,
|
||||||
|
)
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,22 +47,15 @@ data class RuleSet(
|
||||||
* @param ruleId a RULE_ID_XX value
|
* @param ruleId a RULE_ID_XX value
|
||||||
* @return the matched bing rule or null it doesn't exist.
|
* @return the matched bing rule or null it doesn't exist.
|
||||||
*/
|
*/
|
||||||
fun findDefaultRule(ruleId: String?): PushRuleAndKind? {
|
fun findDefaultRule(ruleId: String): PushRuleAndKind? {
|
||||||
var result: PushRuleAndKind? = null
|
return if (RuleIds.RULE_ID_CONTAIN_USER_NAME == ruleId) {
|
||||||
// sanity check
|
findRule(content, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.CONTENT) }
|
||||||
if (null != ruleId) {
|
|
||||||
if (RuleIds.RULE_ID_CONTAIN_USER_NAME == ruleId) {
|
|
||||||
result = findRule(content, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.CONTENT) }
|
|
||||||
} else {
|
} else {
|
||||||
// assume that the ruleId is unique.
|
// assume that the ruleId is unique.
|
||||||
result = findRule(override, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.OVERRIDE) }
|
findRule(override, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.OVERRIDE) }
|
||||||
if (null == result) {
|
?: findRule(underride, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.UNDERRIDE) }
|
||||||
result = findRule(underride, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.UNDERRIDE) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a rule from its rule Id.
|
* Find a rule from its rule Id.
|
||||||
|
|
|
@ -38,7 +38,12 @@ fun getStandardAction(ruleId: String, index: NotificationIndex): StandardActions
|
||||||
NotificationIndex.SILENT -> StandardActions.Notify
|
NotificationIndex.SILENT -> StandardActions.Notify
|
||||||
NotificationIndex.NOISY -> StandardActions.Highlight
|
NotificationIndex.NOISY -> StandardActions.Highlight
|
||||||
}
|
}
|
||||||
RuleIds.RULE_ID_ONE_TO_ONE_ROOM ->
|
RuleIds.RULE_ID_ONE_TO_ONE_ROOM,
|
||||||
|
RuleIds.RULE_ID_POLL_START_ONE_TO_ONE,
|
||||||
|
RuleIds.RULE_ID_POLL_START_ONE_TO_ONE_UNSTABLE,
|
||||||
|
RuleIds.RULE_ID_POLL_END_ONE_TO_ONE,
|
||||||
|
RuleIds.RULE_ID_POLL_END_ONE_TO_ONE_UNSTABLE,
|
||||||
|
->
|
||||||
when (index) {
|
when (index) {
|
||||||
NotificationIndex.OFF -> StandardActions.DontNotify
|
NotificationIndex.OFF -> StandardActions.DontNotify
|
||||||
NotificationIndex.SILENT -> StandardActions.Notify
|
NotificationIndex.SILENT -> StandardActions.Notify
|
||||||
|
@ -50,7 +55,11 @@ fun getStandardAction(ruleId: String, index: NotificationIndex): StandardActions
|
||||||
NotificationIndex.SILENT -> StandardActions.Notify
|
NotificationIndex.SILENT -> StandardActions.Notify
|
||||||
NotificationIndex.NOISY -> StandardActions.NotifyDefaultSound
|
NotificationIndex.NOISY -> StandardActions.NotifyDefaultSound
|
||||||
}
|
}
|
||||||
RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS ->
|
RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS,
|
||||||
|
RuleIds.RULE_ID_POLL_START,
|
||||||
|
RuleIds.RULE_ID_POLL_START_UNSTABLE,
|
||||||
|
RuleIds.RULE_ID_POLL_END,
|
||||||
|
RuleIds.RULE_ID_POLL_END_UNSTABLE ->
|
||||||
when (index) {
|
when (index) {
|
||||||
NotificationIndex.OFF -> StandardActions.DontNotify
|
NotificationIndex.OFF -> StandardActions.DontNotify
|
||||||
NotificationIndex.SILENT -> StandardActions.Notify
|
NotificationIndex.SILENT -> StandardActions.Notify
|
||||||
|
|
|
@ -23,7 +23,6 @@ import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.core.preference.VectorCheckboxPreference
|
import im.vector.app.core.preference.VectorCheckboxPreference
|
||||||
import im.vector.app.features.settings.VectorSettingsBaseFragment
|
import im.vector.app.features.settings.VectorSettingsBaseFragment
|
||||||
import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind
|
|
||||||
|
|
||||||
abstract class VectorSettingsPushRuleNotificationFragment :
|
abstract class VectorSettingsPushRuleNotificationFragment :
|
||||||
VectorSettingsBaseFragment() {
|
VectorSettingsBaseFragment() {
|
||||||
|
@ -35,13 +34,20 @@ abstract class VectorSettingsPushRuleNotificationFragment :
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
observeViewEvents()
|
observeViewEvents()
|
||||||
|
viewModel.onEach(VectorSettingsPushRuleNotificationViewState::isLoading) { isLoading ->
|
||||||
|
if (isLoading) {
|
||||||
|
displayLoadingView()
|
||||||
|
} else {
|
||||||
|
hideLoadingView()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeViewEvents() {
|
private fun observeViewEvents() {
|
||||||
viewModel.observeViewEvents {
|
viewModel.observeViewEvents {
|
||||||
when (it) {
|
when (it) {
|
||||||
is VectorSettingsPushRuleNotificationViewEvent.Failure -> refreshDisplay()
|
is VectorSettingsPushRuleNotificationViewEvent.Failure -> refreshDisplay()
|
||||||
is VectorSettingsPushRuleNotificationViewEvent.PushRuleUpdated -> updatePreference(it.ruleId, it.enabled)
|
is VectorSettingsPushRuleNotificationViewEvent.PushRuleUpdated -> updatePreference(it.ruleId, it.checked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,14 +56,13 @@ abstract class VectorSettingsPushRuleNotificationFragment :
|
||||||
for (preferenceKey in prefKeyToPushRuleId.keys) {
|
for (preferenceKey in prefKeyToPushRuleId.keys) {
|
||||||
val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
|
val preference = findPreference<VectorCheckboxPreference>(preferenceKey)!!
|
||||||
preference.isIconSpaceReserved = false
|
preference.isIconSpaceReserved = false
|
||||||
val ruleAndKind: PushRuleAndKind? = session.pushRuleService().getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey])
|
val ruleAndKind = prefKeyToPushRuleId[preferenceKey]?.let { viewModel.getPushRuleAndKind(it) }
|
||||||
if (ruleAndKind == null) {
|
if (ruleAndKind == null) {
|
||||||
// The rule is not defined, hide the preference
|
// The rule is not defined, hide the preference
|
||||||
preference.isVisible = false
|
preference.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
preference.isVisible = true
|
preference.isVisible = true
|
||||||
val initialIndex = ruleAndKind.pushRule.notificationIndex
|
updatePreference(ruleAndKind.pushRule.ruleId, viewModel.isPushRuleChecked(ruleAndKind.pushRule.ruleId))
|
||||||
preference.isChecked = initialIndex != NotificationIndex.OFF
|
|
||||||
preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||||
viewModel.handle(VectorSettingsPushRuleNotificationViewAction.UpdatePushRule(ruleAndKind, newValue as Boolean))
|
viewModel.handle(VectorSettingsPushRuleNotificationViewAction.UpdatePushRule(ruleAndKind, newValue as Boolean))
|
||||||
false
|
false
|
||||||
|
@ -81,7 +86,6 @@ abstract class VectorSettingsPushRuleNotificationFragment :
|
||||||
private fun updatePreference(ruleId: String, checked: Boolean) {
|
private fun updatePreference(ruleId: String, checked: Boolean) {
|
||||||
val preferenceKey = prefKeyToPushRuleId.entries.find { it.value == ruleId }?.key ?: return
|
val preferenceKey = prefKeyToPushRuleId.entries.find { it.value == ruleId }?.key ?: return
|
||||||
val preference = findPreference<VectorCheckboxPreference>(preferenceKey) ?: return
|
val preference = findPreference<VectorCheckboxPreference>(preferenceKey) ?: return
|
||||||
|
|
||||||
preference.isChecked = checked
|
preference.isChecked = checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,6 @@ package im.vector.app.features.settings.notifications
|
||||||
import im.vector.app.core.platform.VectorViewEvents
|
import im.vector.app.core.platform.VectorViewEvents
|
||||||
|
|
||||||
sealed interface VectorSettingsPushRuleNotificationViewEvent : VectorViewEvents {
|
sealed interface VectorSettingsPushRuleNotificationViewEvent : VectorViewEvents {
|
||||||
data class PushRuleUpdated(val ruleId: String, val enabled: Boolean) : VectorSettingsPushRuleNotificationViewEvent
|
data class PushRuleUpdated(val ruleId: String, val checked: Boolean) : VectorSettingsPushRuleNotificationViewEvent
|
||||||
data class Failure(val throwable: Throwable) : VectorSettingsPushRuleNotificationViewEvent
|
data class Failure(val throwable: Throwable) : VectorSettingsPushRuleNotificationViewEvent
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,11 @@ import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationViewEvent.Failure
|
import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationViewEvent.Failure
|
||||||
import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationViewEvent.PushRuleUpdated
|
import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationViewEvent.PushRuleUpdated
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.failure.Failure.ServerError
|
||||||
|
import org.matrix.android.sdk.api.failure.MatrixError
|
||||||
|
import org.matrix.android.sdk.api.session.pushrules.Action
|
||||||
|
import org.matrix.android.sdk.api.session.pushrules.RuleIds
|
||||||
|
import org.matrix.android.sdk.api.session.pushrules.RuleKind
|
||||||
import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind
|
import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind
|
||||||
|
|
||||||
private typealias ViewModel = VectorSettingsPushRuleNotificationViewModel
|
private typealias ViewModel = VectorSettingsPushRuleNotificationViewModel
|
||||||
|
@ -52,6 +57,15 @@ class VectorSettingsPushRuleNotificationViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPushRuleAndKind(ruleId: String): PushRuleAndKind? {
|
||||||
|
return activeSessionHolder.getSafeActiveSession()?.pushRuleService()?.getPushRules()?.findDefaultRule(ruleId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isPushRuleChecked(ruleId: String): Boolean {
|
||||||
|
val rulesGroup = listOf(ruleId) + RuleIds.getSyncedRules(ruleId)
|
||||||
|
return rulesGroup.mapNotNull { getPushRuleAndKind(it) }.any { it.pushRule.notificationIndex != NotificationIndex.OFF }
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleUpdatePushRule(pushRuleAndKind: PushRuleAndKind, checked: Boolean) {
|
private fun handleUpdatePushRule(pushRuleAndKind: PushRuleAndKind, checked: Boolean) {
|
||||||
val ruleId = pushRuleAndKind.pushRule.ruleId
|
val ruleId = pushRuleAndKind.pushRule.ruleId
|
||||||
val kind = pushRuleAndKind.kind
|
val kind = pushRuleAndKind.kind
|
||||||
|
@ -62,23 +76,35 @@ class VectorSettingsPushRuleNotificationViewModel @AssistedInject constructor(
|
||||||
setState { copy(isLoading = true) }
|
setState { copy(isLoading = true) }
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
val rulesToUpdate = listOf(ruleId) + RuleIds.getSyncedRules(ruleId)
|
||||||
|
val results = rulesToUpdate.map { ruleId ->
|
||||||
runCatching {
|
runCatching {
|
||||||
|
updatePushRule(kind, ruleId, enabled, newActions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setState { copy(isLoading = false) }
|
||||||
|
val failure = results.firstNotNullOfOrNull { it.exceptionOrNull() }
|
||||||
|
if (failure == null) {
|
||||||
|
_viewEvents.post(PushRuleUpdated(ruleId, checked))
|
||||||
|
} else {
|
||||||
|
_viewEvents.post(Failure(failure))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun updatePushRule(kind: RuleKind, ruleId: String, enable: Boolean, newActions: List<Action>?) {
|
||||||
|
try {
|
||||||
activeSessionHolder.getSafeActiveSession()?.pushRuleService()?.updatePushRuleActions(
|
activeSessionHolder.getSafeActiveSession()?.pushRuleService()?.updatePushRuleActions(
|
||||||
kind = kind,
|
kind = kind,
|
||||||
ruleId = ruleId,
|
ruleId = ruleId,
|
||||||
enable = enabled,
|
enable = enable,
|
||||||
actions = newActions
|
actions = newActions
|
||||||
)
|
)
|
||||||
}.fold(
|
} catch (failure: ServerError) {
|
||||||
onSuccess = {
|
// Ignore the error if the rule id is not known from the server
|
||||||
setState { copy(isLoading = false) }
|
if (failure.error.code != MatrixError.M_NOT_FOUND) {
|
||||||
_viewEvents.post(PushRuleUpdated(ruleId, checked))
|
throw failure
|
||||||
},
|
|
||||||
onFailure = { failure ->
|
|
||||||
setState { copy(isLoading = false) }
|
|
||||||
_viewEvents.post(Failure(failure))
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue