Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0c6781e
Adding changelog entry
Nov 16, 2022
9d684bc
Check if account data has content to decide if push notifications can…
Nov 16, 2022
c56eb33
Update use cases to enable/disable push notifications for the current…
Nov 16, 2022
81c6450
Adding SetNotificationSettingsAccountDataUseCase
Nov 16, 2022
b163b42
Use new sub usecase in the TogglePushNotificationUseCase
Nov 17, 2022
14b21dc
Adding use cases to create and delete notifications settings in accou…
Nov 17, 2022
7c51174
Renaming some use cases to be consistent
Nov 17, 2022
ab6a6b5
Some refactorings + update unit tests
Nov 18, 2022
e99dc1d
Remove unused parameters from some ViewModel
Nov 18, 2022
637961b
Update related account data event on notification method change
Nov 23, 2022
7c10a4c
Adding tests for notifications setting updater
Nov 23, 2022
a2ae3af
Removing unused imports
Nov 23, 2022
68d00e0
Fix method used to check if background sync is enabled
Nov 24, 2022
9dff4ff
Fixing import order after rebase
Dec 1, 2022
8973f38
Fixing unit tests after rebase
Dec 1, 2022
3f5147d
Fixing the toggle notifications use case for current session
Dec 1, 2022
06681fd
Removing listening on background sync preference
Dec 1, 2022
5248a69
Updating existing unit tests
Dec 1, 2022
b78de15
Adding unit tests for new toggle notification for current session use…
Dec 1, 2022
e09b9a2
Fixing wrong notification status when no registered pusher for the se…
Dec 2, 2022
635f975
Fix missing unregister of pusher when notifications are disabled
Dec 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7596.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Save m.local_notification_settings.<device-id> event in account_data
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class LocalNotificationSettingsContent(
@Json(name = "is_silenced") val isSilenced: Boolean = false
@Json(name = "is_silenced")
val isSilenced: Boolean?
)
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,21 @@ import org.matrix.android.sdk.api.session.Session
import javax.inject.Inject
import javax.inject.Singleton

/**
* Listen changes in Pusher or Account Data to update the local setting for notification toggle.
*/
@Singleton
class EnableNotificationsSettingUpdater @Inject constructor(
class NotificationsSettingUpdater @Inject constructor(
private val updateEnableNotificationsSettingOnChangeUseCase: UpdateEnableNotificationsSettingOnChangeUseCase,
) {

private var job: Job? = null

fun onSessionsStarted(session: Session) {
fun onSessionStarted(session: Session) {
updateEnableNotificationsSettingOnChange(session)
}

private fun updateEnableNotificationsSettingOnChange(session: Session) {
job?.cancel()
job = session.coroutineScope.launch {
updateEnableNotificationsSettingOnChangeUseCase.execute(session)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ package im.vector.app.core.session
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.notification.EnableNotificationsSettingUpdater
import im.vector.app.core.notification.NotificationsSettingUpdater
import im.vector.app.core.session.clientinfo.UpdateMatrixClientInfoUseCase
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.devices.v2.notification.UpdateNotificationSettingsAccountDataUseCase
import im.vector.app.features.sync.SyncUtils
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
Expand All @@ -35,7 +36,8 @@ class ConfigureAndStartSessionUseCase @Inject constructor(
private val webRtcCallManager: WebRtcCallManager,
private val updateMatrixClientInfoUseCase: UpdateMatrixClientInfoUseCase,
private val vectorPreferences: VectorPreferences,
private val enableNotificationsSettingUpdater: EnableNotificationsSettingUpdater,
private val notificationsSettingUpdater: NotificationsSettingUpdater,
private val updateNotificationSettingsAccountDataUseCase: UpdateNotificationSettingsAccountDataUseCase,
) {

fun execute(session: Session, startSyncing: Boolean = true) {
Expand All @@ -49,11 +51,22 @@ class ConfigureAndStartSessionUseCase @Inject constructor(
}
session.pushersService().refreshPushers()
webRtcCallManager.checkForProtocolsSupportIfNeeded()
updateMatrixClientInfoIfNeeded(session)
createNotificationSettingsAccountDataIfNeeded(session)
notificationsSettingUpdater.onSessionStarted(session)
}

private fun updateMatrixClientInfoIfNeeded(session: Session) {
session.coroutineScope.launch {
if (vectorPreferences.isClientInfoRecordingEnabled()) {
updateMatrixClientInfoUseCase.execute(session)
}
}
enableNotificationsSettingUpdater.onSessionsStarted(session)
}

private fun createNotificationSettingsAccountDataIfNeeded(session: Session) {
session.coroutineScope.launch {
updateNotificationSettingsAccountDataUseCase.execute(session)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.pushers.RegisterUnifiedPushUseCase
import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
import im.vector.app.features.analytics.AnalyticsConfig
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsType
Expand Down Expand Up @@ -92,6 +93,7 @@ class HomeActivityViewModel @AssistedInject constructor(
private val stopOngoingVoiceBroadcastUseCase: StopOngoingVoiceBroadcastUseCase,
private val pushersManager: PushersManager,
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
private val ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase,
) : VectorViewModel<HomeActivityViewState, HomeActivityViewActions, HomeActivityViewEvents>(initialState) {

Expand Down Expand Up @@ -130,6 +132,8 @@ class HomeActivityViewModel @AssistedInject constructor(
private fun registerUnifiedPushIfNeeded() {
if (vectorPreferences.areNotificationEnabledForDevice()) {
registerUnifiedPush(distributor = "")
} else {
unregisterUnifiedPush()
}
}

Expand All @@ -146,6 +150,12 @@ class HomeActivityViewModel @AssistedInject constructor(
}
}

private fun unregisterUnifiedPush() {
viewModelScope.launch {
unregisterUnifiedPushUseCase.execute(pushersManager)
}
}

private fun observeReleaseNotes() = withState { state ->
if (vectorPreferences.isNewAppLayoutEnabled()) {
// we don't want to show release notes for new users or after relogin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.features.auth.PendingAuthHandler
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
import im.vector.app.features.settings.devices.v2.signout.InterceptSignoutFlowResponseUseCase
import im.vector.app.features.settings.devices.v2.signout.SignoutSessionsReAuthNeeded
import im.vector.app.features.settings.devices.v2.signout.SignoutSessionsUseCase
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
Expand All @@ -48,7 +47,6 @@ class DevicesViewModel @AssistedInject constructor(
private val refreshDevicesOnCryptoDevicesChangeUseCase: RefreshDevicesOnCryptoDevicesChangeUseCase,
private val checkIfCurrentSessionCanBeVerifiedUseCase: CheckIfCurrentSessionCanBeVerifiedUseCase,
private val signoutSessionsUseCase: SignoutSessionsUseCase,
private val interceptSignoutFlowResponseUseCase: InterceptSignoutFlowResponseUseCase,
private val pendingAuthHandler: PendingAuthHandler,
refreshDevicesUseCase: RefreshDevicesUseCase,
private val vectorPreferences: VectorPreferences,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.flow.unwrap
import javax.inject.Inject

class CanTogglePushNotificationsViaPusherUseCase @Inject constructor() {
class CanToggleNotificationsViaPusherUseCase @Inject constructor() {

fun execute(session: Session): Flow<Boolean> {
return session
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
package im.vector.app.features.settings.devices.v2.notification

import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import javax.inject.Inject

class CheckIfCanTogglePushNotificationsViaAccountDataUseCase @Inject constructor() {
class CheckIfCanToggleNotificationsViaAccountDataUseCase @Inject constructor(
private val getNotificationSettingsAccountDataUseCase: GetNotificationSettingsAccountDataUseCase,
) {

fun execute(session: Session, deviceId: String): Boolean {
return session
.accountDataService()
.getUserAccountDataEvent(UserAccountDataTypes.TYPE_LOCAL_NOTIFICATION_SETTINGS + deviceId) != null
return getNotificationSettingsAccountDataUseCase.execute(session, deviceId)?.isSilenced != null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package im.vector.app.features.settings.devices.v2.notification
import org.matrix.android.sdk.api.session.Session
import javax.inject.Inject

class CheckIfCanTogglePushNotificationsViaPusherUseCase @Inject constructor() {
class CheckIfCanToggleNotificationsViaPusherUseCase @Inject constructor() {

fun execute(session: Session): Boolean {
return session
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 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.devices.v2.notification

import org.matrix.android.sdk.api.account.LocalNotificationSettingsContent
import org.matrix.android.sdk.api.session.Session
import javax.inject.Inject

/**
* Delete the content of any associated notification settings to the current session.
*/
class DeleteNotificationSettingsAccountDataUseCase @Inject constructor(
private val getNotificationSettingsAccountDataUseCase: GetNotificationSettingsAccountDataUseCase,
private val setNotificationSettingsAccountDataUseCase: SetNotificationSettingsAccountDataUseCase,
) {

suspend fun execute(session: Session) {
val deviceId = session.sessionParams.deviceId ?: return
if (getNotificationSettingsAccountDataUseCase.execute(session, deviceId)?.isSilenced != null) {
val emptyNotificationSettingsContent = LocalNotificationSettingsContent(
isSilenced = null
)
setNotificationSettingsAccountDataUseCase.execute(session, deviceId, emptyNotificationSettingsContent)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 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.devices.v2.notification

import org.matrix.android.sdk.api.account.LocalNotificationSettingsContent
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.toModel
import javax.inject.Inject

class GetNotificationSettingsAccountDataUseCase @Inject constructor() {

fun execute(session: Session, deviceId: String): LocalNotificationSettingsContent? {
return session
.accountDataService()
.getUserAccountDataEvent(UserAccountDataTypes.TYPE_LOCAL_NOTIFICATION_SETTINGS + deviceId)
?.content
.toModel<LocalNotificationSettingsContent>()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,34 @@ import org.matrix.android.sdk.flow.unwrap
import javax.inject.Inject

class GetNotificationsStatusUseCase @Inject constructor(
private val canTogglePushNotificationsViaPusherUseCase: CanTogglePushNotificationsViaPusherUseCase,
private val checkIfCanTogglePushNotificationsViaAccountDataUseCase: CheckIfCanTogglePushNotificationsViaAccountDataUseCase,
private val canToggleNotificationsViaPusherUseCase: CanToggleNotificationsViaPusherUseCase,
private val checkIfCanToggleNotificationsViaAccountDataUseCase: CheckIfCanToggleNotificationsViaAccountDataUseCase,
) {

fun execute(session: Session, deviceId: String): Flow<NotificationsStatus> {
return when {
checkIfCanTogglePushNotificationsViaAccountDataUseCase.execute(session, deviceId) -> {
checkIfCanToggleNotificationsViaAccountDataUseCase.execute(session, deviceId) -> {
session.flow()
.liveUserAccountData(UserAccountDataTypes.TYPE_LOCAL_NOTIFICATION_SETTINGS + deviceId)
.unwrap()
.map { it.content.toModel<LocalNotificationSettingsContent>()?.isSilenced?.not() }
.map { if (it == true) NotificationsStatus.ENABLED else NotificationsStatus.DISABLED }
.distinctUntilChanged()
}
else -> canTogglePushNotificationsViaPusherUseCase.execute(session)
else -> canToggleNotificationsViaPusherUseCase.execute(session)
.flatMapLatest { canToggle ->
if (canToggle) {
session.flow()
.livePushers()
.map { it.filter { pusher -> pusher.deviceId == deviceId } }
.map { it.takeIf { it.isNotEmpty() }?.any { pusher -> pusher.enabled } }
.map { if (it == true) NotificationsStatus.ENABLED else NotificationsStatus.DISABLED }
.map {
when (it) {
true -> NotificationsStatus.ENABLED
false -> NotificationsStatus.DISABLED
else -> NotificationsStatus.NOT_SUPPORTED
}
}
.distinctUntilChanged()
} else {
flowOf(NotificationsStatus.NOT_SUPPORTED)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2022 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.devices.v2.notification

import org.matrix.android.sdk.api.account.LocalNotificationSettingsContent
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.toContent
import javax.inject.Inject

class SetNotificationSettingsAccountDataUseCase @Inject constructor() {

suspend fun execute(session: Session, deviceId: String, localNotificationSettingsContent: LocalNotificationSettingsContent) {
session.accountDataService().updateUserAccountData(
UserAccountDataTypes.TYPE_LOCAL_NOTIFICATION_SETTINGS + deviceId,
localNotificationSettingsContent.toContent(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,28 @@ package im.vector.app.features.settings.devices.v2.notification

import im.vector.app.core.di.ActiveSessionHolder
import org.matrix.android.sdk.api.account.LocalNotificationSettingsContent
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.toContent
import javax.inject.Inject

class TogglePushNotificationUseCase @Inject constructor(
class ToggleNotificationsUseCase @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder,
private val checkIfCanTogglePushNotificationsViaPusherUseCase: CheckIfCanTogglePushNotificationsViaPusherUseCase,
private val checkIfCanTogglePushNotificationsViaAccountDataUseCase: CheckIfCanTogglePushNotificationsViaAccountDataUseCase,
private val checkIfCanToggleNotificationsViaPusherUseCase: CheckIfCanToggleNotificationsViaPusherUseCase,
private val checkIfCanToggleNotificationsViaAccountDataUseCase: CheckIfCanToggleNotificationsViaAccountDataUseCase,
private val setNotificationSettingsAccountDataUseCase: SetNotificationSettingsAccountDataUseCase,
) {

suspend fun execute(deviceId: String, enabled: Boolean) {
val session = activeSessionHolder.getSafeActiveSession() ?: return

if (checkIfCanTogglePushNotificationsViaPusherUseCase.execute(session)) {
if (checkIfCanToggleNotificationsViaPusherUseCase.execute(session)) {
val devicePusher = session.pushersService().getPushers().firstOrNull { it.deviceId == deviceId }
devicePusher?.let { pusher ->
session.pushersService().togglePusher(pusher, enabled)
}
}

if (checkIfCanTogglePushNotificationsViaAccountDataUseCase.execute(session, deviceId)) {
if (checkIfCanToggleNotificationsViaAccountDataUseCase.execute(session, deviceId)) {
val newNotificationSettingsContent = LocalNotificationSettingsContent(isSilenced = !enabled)
session.accountDataService().updateUserAccountData(
UserAccountDataTypes.TYPE_LOCAL_NOTIFICATION_SETTINGS + deviceId,
newNotificationSettingsContent.toContent(),
)
setNotificationSettingsAccountDataUseCase.execute(session, deviceId, newNotificationSettingsContent)
}
}
}
Loading