Merge pull request #7675 from vector-im/fix/mna/unified-push-selection
ANR when asking to select the notification method
This commit is contained in:
commit
a2f8fed63c
|
@ -0,0 +1 @@
|
|||
ANR when asking to select the notification method
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package im.vector.app.push.fcm
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.pushers.FcmHelper
|
||||
|
@ -44,7 +43,7 @@ class FdroidFcmHelper @Inject constructor(
|
|||
// No op
|
||||
}
|
||||
|
||||
override fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) {
|
||||
override fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean) {
|
||||
// No op
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package im.vector.app.push.fcm
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.widget.Toast
|
||||
|
@ -23,6 +22,7 @@ import androidx.core.content.edit
|
|||
import com.google.android.gms.common.ConnectionResult
|
||||
import com.google.android.gms.common.GoogleApiAvailability
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.di.DefaultPreferences
|
||||
|
@ -36,8 +36,8 @@ import javax.inject.Inject
|
|||
* It has an alter ego in the fdroid variant.
|
||||
*/
|
||||
class GoogleFcmHelper @Inject constructor(
|
||||
@DefaultPreferences
|
||||
private val sharedPrefs: SharedPreferences,
|
||||
@ApplicationContext private val context: Context,
|
||||
@DefaultPreferences private val sharedPrefs: SharedPreferences,
|
||||
) : FcmHelper {
|
||||
companion object {
|
||||
private const val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN"
|
||||
|
@ -56,10 +56,9 @@ class GoogleFcmHelper @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) {
|
||||
// if (TextUtils.isEmpty(getFcmToken(activity))) {
|
||||
override fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean) {
|
||||
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
|
||||
if (checkPlayServices(activity)) {
|
||||
if (checkPlayServices(context)) {
|
||||
try {
|
||||
FirebaseMessaging.getInstance().token
|
||||
.addOnSuccessListener { token ->
|
||||
|
@ -75,7 +74,7 @@ class GoogleFcmHelper @Inject constructor(
|
|||
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.no_valid_google_play_services_apk, Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, R.string.no_valid_google_play_services_apk, Toast.LENGTH_SHORT).show()
|
||||
Timber.e("No valid Google Play Services found. Cannot use FCM.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ package im.vector.app.core.di
|
|||
import android.content.Context
|
||||
import im.vector.app.ActiveSessionDataSource
|
||||
import im.vector.app.core.extensions.startSyncing
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
|
||||
import im.vector.app.core.services.GuardServiceStarter
|
||||
import im.vector.app.core.session.ConfigureAndStartSessionUseCase
|
||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||
|
@ -46,12 +46,12 @@ class ActiveSessionHolder @Inject constructor(
|
|||
private val pushRuleTriggerListener: PushRuleTriggerListener,
|
||||
private val sessionListener: SessionListener,
|
||||
private val imageManager: ImageManager,
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
private val guardServiceStarter: GuardServiceStarter,
|
||||
private val sessionInitializer: SessionInitializer,
|
||||
private val applicationContext: Context,
|
||||
private val authenticationService: AuthenticationService,
|
||||
private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase,
|
||||
private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||
) {
|
||||
|
||||
private var activeSessionReference: AtomicReference<Session?> = AtomicReference()
|
||||
|
@ -85,7 +85,7 @@ class ActiveSessionHolder @Inject constructor(
|
|||
incomingVerificationRequestHandler.stop()
|
||||
pushRuleTriggerListener.stop()
|
||||
// No need to unregister the pusher, the sign out will (should?) do it server side.
|
||||
unifiedPushHelper.unregister(pushersManager = null)
|
||||
unregisterUnifiedPushUseCase.execute(pushersManager = null)
|
||||
guardServiceStarter.stop()
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ import im.vector.app.features.settings.ignored.IgnoredUsersViewModel
|
|||
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.push.PushGatewaysViewModel
|
||||
import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel
|
||||
import im.vector.app.features.share.IncomingShareViewModel
|
||||
|
@ -683,4 +684,11 @@ interface MavericksViewModelModule {
|
|||
@IntoMap
|
||||
@MavericksViewModelKey(AttachmentTypeSelectorViewModel::class)
|
||||
fun attachmentTypeSelectorViewModelFactory(factory: AttachmentTypeSelectorViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(VectorSettingsNotificationPreferenceViewModel::class)
|
||||
fun vectorSettingsNotificationPreferenceViewModelFactory(
|
||||
factory: VectorSettingsNotificationPreferenceViewModel.Factory
|
||||
): MavericksAssistedViewModelFactory<*, *>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.core.pushers
|
||||
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import javax.inject.Inject
|
||||
|
||||
class EnsureFcmTokenIsRetrievedUseCase @Inject constructor(
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
private val fcmHelper: FcmHelper,
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
) {
|
||||
|
||||
fun execute(pushersManager: PushersManager, registerPusher: Boolean) {
|
||||
if (unifiedPushHelper.isEmbeddedDistributor()) {
|
||||
fcmHelper.ensureFcmTokenIsRetrieved(pushersManager, shouldAddHttpPusher(registerPusher))
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldAddHttpPusher(registerPusher: Boolean) = if (registerPusher) {
|
||||
val currentSession = activeSessionHolder.getActiveSession()
|
||||
val currentPushers = currentSession.pushersService().getPushers()
|
||||
currentPushers.none { it.deviceId == currentSession.sessionParams.deviceId }
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.app.core.pushers
|
||||
|
||||
import android.app.Activity
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
|
||||
interface FcmHelper {
|
||||
|
@ -39,11 +38,10 @@ interface FcmHelper {
|
|||
/**
|
||||
* onNewToken may not be called on application upgrade, so ensure my shared pref is set.
|
||||
*
|
||||
* @param activity the first launch Activity.
|
||||
* @param pushersManager the instance to register the pusher on.
|
||||
* @param registerPusher whether the pusher should be registered.
|
||||
*/
|
||||
fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean)
|
||||
fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean)
|
||||
|
||||
fun onEnterForeground(activeSessionHolder: ActiveSessionHolder)
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.core.pushers
|
||||
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import im.vector.app.features.VectorFeatures
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
import javax.inject.Inject
|
||||
|
||||
class RegisterUnifiedPushUseCase @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val vectorFeatures: VectorFeatures,
|
||||
) {
|
||||
|
||||
sealed interface RegisterUnifiedPushResult {
|
||||
object Success : RegisterUnifiedPushResult
|
||||
object NeedToAskUserForDistributor : RegisterUnifiedPushResult
|
||||
}
|
||||
|
||||
fun execute(distributor: String = ""): RegisterUnifiedPushResult {
|
||||
if (distributor.isNotEmpty()) {
|
||||
saveAndRegisterApp(distributor)
|
||||
return RegisterUnifiedPushResult.Success
|
||||
}
|
||||
|
||||
if (!vectorFeatures.allowExternalUnifiedPushDistributors()) {
|
||||
saveAndRegisterApp(context.packageName)
|
||||
return RegisterUnifiedPushResult.Success
|
||||
}
|
||||
|
||||
if (UnifiedPush.getDistributor(context).isNotEmpty()) {
|
||||
registerApp()
|
||||
return RegisterUnifiedPushResult.Success
|
||||
}
|
||||
|
||||
val distributors = UnifiedPush.getDistributors(context)
|
||||
|
||||
return if (distributors.size == 1) {
|
||||
saveAndRegisterApp(distributors.first())
|
||||
RegisterUnifiedPushResult.Success
|
||||
} else {
|
||||
RegisterUnifiedPushResult.NeedToAskUserForDistributor
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveAndRegisterApp(distributor: String) {
|
||||
UnifiedPush.saveDistributor(context, distributor)
|
||||
registerApp()
|
||||
}
|
||||
|
||||
private fun registerApp() {
|
||||
UnifiedPush.registerApp(context)
|
||||
}
|
||||
}
|
|
@ -17,18 +17,13 @@
|
|||
package im.vector.app.core.pushers
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.annotation.MainThread
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.utils.getApplicationLabel
|
||||
import im.vector.app.features.VectorFeatures
|
||||
import im.vector.app.features.settings.BackgroundSyncMode
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.Matrix
|
||||
import org.matrix.android.sdk.api.cache.CacheStrategy
|
||||
import org.matrix.android.sdk.api.util.MatrixJsonParser
|
||||
|
@ -41,90 +36,14 @@ class UnifiedPushHelper @Inject constructor(
|
|||
private val context: Context,
|
||||
private val unifiedPushStore: UnifiedPushStore,
|
||||
private val stringProvider: StringProvider,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val matrix: Matrix,
|
||||
private val vectorFeatures: VectorFeatures,
|
||||
private val fcmHelper: FcmHelper,
|
||||
) {
|
||||
|
||||
// Called when the home activity starts
|
||||
// or when notifications are enabled
|
||||
fun register(
|
||||
activity: FragmentActivity,
|
||||
onDoneRunnable: Runnable? = null,
|
||||
) {
|
||||
registerInternal(
|
||||
activity,
|
||||
onDoneRunnable = onDoneRunnable
|
||||
)
|
||||
}
|
||||
|
||||
// If registration is forced:
|
||||
// * the current distributor (if any) is removed
|
||||
// * The dialog is opened
|
||||
//
|
||||
// The registration is forced in 2 cases :
|
||||
// * in the settings
|
||||
// * in the troubleshoot list (doFix)
|
||||
fun forceRegister(
|
||||
activity: FragmentActivity,
|
||||
pushersManager: PushersManager,
|
||||
onDoneRunnable: Runnable? = null
|
||||
) {
|
||||
registerInternal(
|
||||
activity,
|
||||
force = true,
|
||||
pushersManager = pushersManager,
|
||||
onDoneRunnable = onDoneRunnable
|
||||
)
|
||||
}
|
||||
|
||||
private fun registerInternal(
|
||||
activity: FragmentActivity,
|
||||
force: Boolean = false,
|
||||
pushersManager: PushersManager? = null,
|
||||
onDoneRunnable: Runnable? = null
|
||||
) {
|
||||
activity.lifecycleScope.launch {
|
||||
if (!vectorFeatures.allowExternalUnifiedPushDistributors()) {
|
||||
UnifiedPush.saveDistributor(context, context.packageName)
|
||||
UnifiedPush.registerApp(context)
|
||||
onDoneRunnable?.run()
|
||||
return@launch
|
||||
}
|
||||
if (force) {
|
||||
// Un-register first
|
||||
unregister(pushersManager)
|
||||
}
|
||||
// the !force should not be needed
|
||||
if (!force && UnifiedPush.getDistributor(context).isNotEmpty()) {
|
||||
UnifiedPush.registerApp(context)
|
||||
onDoneRunnable?.run()
|
||||
return@launch
|
||||
}
|
||||
|
||||
val distributors = UnifiedPush.getDistributors(context)
|
||||
|
||||
if (!force && distributors.size == 1) {
|
||||
UnifiedPush.saveDistributor(context, distributors.first())
|
||||
UnifiedPush.registerApp(context)
|
||||
onDoneRunnable?.run()
|
||||
} else {
|
||||
openDistributorDialogInternal(
|
||||
activity = activity,
|
||||
onDoneRunnable = onDoneRunnable,
|
||||
distributors = distributors
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There is no case where this function is called
|
||||
// with a saved distributor and/or a pusher
|
||||
private fun openDistributorDialogInternal(
|
||||
activity: FragmentActivity,
|
||||
onDoneRunnable: Runnable?,
|
||||
distributors: List<String>
|
||||
@MainThread
|
||||
fun showSelectDistributorDialog(
|
||||
context: Context,
|
||||
onDistributorSelected: (String) -> Unit,
|
||||
) {
|
||||
val internalDistributorName = stringProvider.getString(
|
||||
if (fcmHelper.isFirebaseAvailable()) {
|
||||
|
@ -134,6 +53,7 @@ class UnifiedPushHelper @Inject constructor(
|
|||
}
|
||||
)
|
||||
|
||||
val distributors = UnifiedPush.getDistributors(context)
|
||||
val distributorsName = distributors.map {
|
||||
if (it == context.packageName) {
|
||||
internalDistributorName
|
||||
|
@ -142,44 +62,23 @@ class UnifiedPushHelper @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle(stringProvider.getString(R.string.unifiedpush_getdistributors_dialog_title))
|
||||
.setItems(distributorsName.toTypedArray()) { _, which ->
|
||||
val distributor = distributors[which]
|
||||
|
||||
activity.lifecycleScope.launch {
|
||||
UnifiedPush.saveDistributor(context, distributor)
|
||||
Timber.i("Saving distributor: $distributor")
|
||||
UnifiedPush.registerApp(context)
|
||||
onDoneRunnable?.run()
|
||||
}
|
||||
onDistributorSelected(distributor)
|
||||
}
|
||||
.setOnCancelListener {
|
||||
// By default, use internal solution (fcm/background sync)
|
||||
UnifiedPush.saveDistributor(context, context.packageName)
|
||||
UnifiedPush.registerApp(context)
|
||||
onDoneRunnable?.run()
|
||||
// we do not want to change the distributor on behalf of the user
|
||||
if (UnifiedPush.getDistributor(context).isEmpty()) {
|
||||
// By default, use internal solution (fcm/background sync)
|
||||
onDistributorSelected(context.packageName)
|
||||
}
|
||||
}
|
||||
.setCancelable(true)
|
||||
.show()
|
||||
}
|
||||
|
||||
suspend fun unregister(pushersManager: PushersManager? = null) {
|
||||
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
||||
vectorPreferences.setFdroidSyncBackgroundMode(mode)
|
||||
try {
|
||||
getEndpointOrToken()?.let {
|
||||
Timber.d("Removing $it")
|
||||
pushersManager?.unregisterPusher(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.d(e, "Probably unregistering a non existing pusher")
|
||||
}
|
||||
unifiedPushStore.storeUpEndpoint(null)
|
||||
unifiedPushStore.storePushGateway(null)
|
||||
UnifiedPush.unregisterApp(context)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class DiscoveryResponse(
|
||||
@Json(name = "unifiedpush") val unifiedpush: DiscoveryUnifiedPush = DiscoveryUnifiedPush()
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.core.pushers
|
||||
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import im.vector.app.features.settings.BackgroundSyncMode
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class UnregisterUnifiedPushUseCase @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val unifiedPushStore: UnifiedPushStore,
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
) {
|
||||
|
||||
suspend fun execute(pushersManager: PushersManager?) {
|
||||
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
||||
vectorPreferences.setFdroidSyncBackgroundMode(mode)
|
||||
try {
|
||||
unifiedPushHelper.getEndpointOrToken()?.let {
|
||||
Timber.d("Removing $it")
|
||||
pushersManager?.unregisterPusher(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.d(e, "Probably unregistering a non existing pusher")
|
||||
}
|
||||
unifiedPushStore.storeUpEndpoint(null)
|
||||
unifiedPushStore.storePushGateway(null)
|
||||
UnifiedPush.unregisterApp(context)
|
||||
}
|
||||
}
|
|
@ -44,8 +44,6 @@ import im.vector.app.core.extensions.restart
|
|||
import im.vector.app.core.extensions.validateBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.platform.VectorMenuProvider
|
||||
import im.vector.app.core.pushers.FcmHelper
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
|
@ -128,7 +126,6 @@ class HomeActivity :
|
|||
private val serverBackupStatusViewModel: ServerBackupStatusViewModel by viewModel()
|
||||
|
||||
@Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
|
||||
@Inject lateinit var pushersManager: PushersManager
|
||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||
@Inject lateinit var popupAlertManager: PopupAlertManager
|
||||
@Inject lateinit var shortcutsHandler: ShortcutsHandler
|
||||
|
@ -137,7 +134,6 @@ class HomeActivity :
|
|||
@Inject lateinit var initSyncStepFormatter: InitSyncStepFormatter
|
||||
@Inject lateinit var spaceStateHandler: SpaceStateHandler
|
||||
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
||||
@Inject lateinit var fcmHelper: FcmHelper
|
||||
@Inject lateinit var nightlyProxy: NightlyProxy
|
||||
@Inject lateinit var disclaimerDialog: DisclaimerDialog
|
||||
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager
|
||||
|
@ -209,16 +205,6 @@ class HomeActivity :
|
|||
isNewAppLayoutEnabled = vectorPreferences.isNewAppLayoutEnabled()
|
||||
analyticsScreenName = MobileScreen.ScreenName.Home
|
||||
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false)
|
||||
unifiedPushHelper.register(this) {
|
||||
if (unifiedPushHelper.isEmbeddedDistributor()) {
|
||||
fcmHelper.ensureFcmTokenIsRetrieved(
|
||||
this,
|
||||
pushersManager,
|
||||
homeActivityViewModel.shouldAddHttpPusher()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
sharedActionViewModel = viewModelProvider[HomeSharedActionViewModel::class.java]
|
||||
roomListSharedActionViewModel = viewModelProvider[RoomListSharedActionViewModel::class.java]
|
||||
views.drawerLayout.addDrawerListener(drawerListener)
|
||||
|
@ -280,6 +266,7 @@ class HomeActivity :
|
|||
HomeActivityViewEvents.ShowReleaseNotes -> handleShowReleaseNotes()
|
||||
HomeActivityViewEvents.NotifyUserForThreadsMigration -> handleNotifyUserForThreadsMigration()
|
||||
is HomeActivityViewEvents.MigrateThreads -> migrateThreadsIfNeeded(it.checkSession)
|
||||
is HomeActivityViewEvents.AskUserForPushDistributor -> askUserToSelectPushDistributor()
|
||||
}
|
||||
}
|
||||
homeActivityViewModel.onEach { renderState(it) }
|
||||
|
@ -292,6 +279,12 @@ class HomeActivity :
|
|||
homeActivityViewModel.handle(HomeActivityViewActions.ViewStarted)
|
||||
}
|
||||
|
||||
private fun askUserToSelectPushDistributor() {
|
||||
unifiedPushHelper.showSelectDistributorDialog(this) { selection ->
|
||||
homeActivityViewModel.handle(HomeActivityViewActions.RegisterPushDistributor(selection))
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleShowNotificationDialog() {
|
||||
notificationPermissionManager.eventuallyRequestPermission(this, postPermissionLauncher)
|
||||
}
|
||||
|
@ -415,14 +408,6 @@ class HomeActivity :
|
|||
}
|
||||
|
||||
private fun renderState(state: HomeActivityViewState) {
|
||||
lifecycleScope.launch {
|
||||
if (state.areNotificationsSilenced) {
|
||||
unifiedPushHelper.unregister(pushersManager)
|
||||
} else {
|
||||
unifiedPushHelper.register(this@HomeActivity)
|
||||
}
|
||||
}
|
||||
|
||||
when (val status = state.syncRequestState) {
|
||||
is SyncRequestState.InitialSyncProgressing -> {
|
||||
val initSyncStepStr = initSyncStepFormatter.format(status.initialSyncStep)
|
||||
|
|
|
@ -21,4 +21,5 @@ import im.vector.app.core.platform.VectorViewModelAction
|
|||
sealed interface HomeActivityViewActions : VectorViewModelAction {
|
||||
object ViewStarted : HomeActivityViewActions
|
||||
object PushPromptHasBeenReviewed : HomeActivityViewActions
|
||||
data class RegisterPushDistributor(val distributor: String) : HomeActivityViewActions
|
||||
}
|
||||
|
|
|
@ -25,9 +25,11 @@ sealed interface HomeActivityViewEvents : VectorViewEvents {
|
|||
val userItem: MatrixItem.UserItem,
|
||||
val waitForIncomingRequest: Boolean = true,
|
||||
) : HomeActivityViewEvents
|
||||
|
||||
data class CurrentSessionCannotBeVerified(
|
||||
val userItem: MatrixItem.UserItem,
|
||||
) : HomeActivityViewEvents
|
||||
|
||||
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents
|
||||
object PromptToEnableSessionPush : HomeActivityViewEvents
|
||||
object ShowAnalyticsOptIn : HomeActivityViewEvents
|
||||
|
@ -37,4 +39,5 @@ sealed interface HomeActivityViewEvents : VectorViewEvents {
|
|||
data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents
|
||||
object StartRecoverySetupFlow : HomeActivityViewEvents
|
||||
data class ForceVerification(val sendRequest: Boolean) : HomeActivityViewEvents
|
||||
object AskUserForPushDistributor : HomeActivityViewEvents
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.app.features.home
|
||||
|
||||
import androidx.lifecycle.asFlow
|
||||
import com.airbnb.mvrx.Mavericks
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
|
@ -27,7 +26,9 @@ 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 im.vector.app.features.VectorFeatures
|
||||
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.features.analytics.AnalyticsConfig
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.extensions.toAnalyticsType
|
||||
|
@ -48,12 +49,10 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.account.LocalNotificationSettingsContent
|
||||
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||
import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
||||
|
@ -62,11 +61,9 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
|||
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.raw.RawService
|
||||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService
|
||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.getUserOrDefault
|
||||
import org.matrix.android.sdk.api.session.pushrules.RuleIds
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
|
@ -92,8 +89,10 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
private val analyticsTracker: AnalyticsTracker,
|
||||
private val analyticsConfig: AnalyticsConfig,
|
||||
private val releaseNotesPreferencesStore: ReleaseNotesPreferencesStore,
|
||||
private val vectorFeatures: VectorFeatures,
|
||||
private val stopOngoingVoiceBroadcastUseCase: StopOngoingVoiceBroadcastUseCase,
|
||||
private val pushersManager: PushersManager,
|
||||
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
||||
private val ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase,
|
||||
) : VectorViewModel<HomeActivityViewState, HomeActivityViewActions, HomeActivityViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
|
@ -117,17 +116,36 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
private fun initialize() {
|
||||
if (isInitialized) return
|
||||
isInitialized = true
|
||||
registerUnifiedPushIfNeeded()
|
||||
cleanupFiles()
|
||||
observeInitialSync()
|
||||
checkSessionPushIsOn()
|
||||
observeCrossSigningReset()
|
||||
observeAnalytics()
|
||||
observeReleaseNotes()
|
||||
observeLocalNotificationsSilenced()
|
||||
initThreadsMigration()
|
||||
viewModelScope.launch { stopOngoingVoiceBroadcastUseCase.execute() }
|
||||
}
|
||||
|
||||
private fun registerUnifiedPushIfNeeded() {
|
||||
if (vectorPreferences.areNotificationEnabledForDevice()) {
|
||||
registerUnifiedPush(distributor = "")
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerUnifiedPush(distributor: String) {
|
||||
viewModelScope.launch {
|
||||
when (registerUnifiedPushUseCase.execute(distributor = distributor)) {
|
||||
is RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor -> {
|
||||
_viewEvents.post(HomeActivityViewEvents.AskUserForPushDistributor)
|
||||
}
|
||||
RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success -> {
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(pushersManager, registerPusher = vectorPreferences.areNotificationEnabledForDevice())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeReleaseNotes() = withState { state ->
|
||||
if (vectorPreferences.isNewAppLayoutEnabled()) {
|
||||
// we don't want to show release notes for new users or after relogin
|
||||
|
@ -146,26 +164,6 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun shouldAddHttpPusher() = if (vectorPreferences.areNotificationEnabledForDevice()) {
|
||||
val currentSession = activeSessionHolder.getActiveSession()
|
||||
val currentPushers = currentSession.pushersService().getPushers()
|
||||
currentPushers.none { it.deviceId == currentSession.sessionParams.deviceId }
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
fun observeLocalNotificationsSilenced() {
|
||||
val currentSession = activeSessionHolder.getActiveSession()
|
||||
val deviceId = currentSession.cryptoService().getMyDevice().deviceId
|
||||
viewModelScope.launch {
|
||||
currentSession.accountDataService()
|
||||
.getLiveUserAccountDataEvent(UserAccountDataTypes.TYPE_LOCAL_NOTIFICATION_SETTINGS + deviceId)
|
||||
.asFlow()
|
||||
.map { it.getOrNull()?.content?.toModel<LocalNotificationSettingsContent>()?.isSilenced ?: false }
|
||||
.onEach { setState { copy(areNotificationsSilenced = it) } }
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeAnalytics() {
|
||||
if (analyticsConfig.isEnabled) {
|
||||
analyticsStore.didAskUserConsentFlow
|
||||
|
@ -501,6 +499,9 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
HomeActivityViewActions.ViewStarted -> {
|
||||
initialize()
|
||||
}
|
||||
is HomeActivityViewActions.RegisterPushDistributor -> {
|
||||
registerUnifiedPush(distributor = action.distributor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,5 +23,4 @@ import org.matrix.android.sdk.api.session.sync.SyncRequestState
|
|||
data class HomeActivityViewState(
|
||||
val syncRequestState: SyncRequestState = SyncRequestState.Idle,
|
||||
val authenticationDescription: AuthenticationDescription? = null,
|
||||
val areNotificationsSilenced: Boolean = false,
|
||||
) : MavericksState
|
||||
|
|
|
@ -28,6 +28,8 @@ import im.vector.app.R
|
|||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.singletonEntryPoint
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.MobileScreen
|
||||
|
@ -60,6 +62,19 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), Maverick
|
|||
protected lateinit var session: Session
|
||||
protected lateinit var errorFormatter: ErrorFormatter
|
||||
|
||||
/* ==========================================================================================
|
||||
* ViewEvents
|
||||
* ========================================================================================== */
|
||||
|
||||
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
|
||||
viewEvents
|
||||
.stream()
|
||||
.onEach {
|
||||
observer(it)
|
||||
}
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* Views
|
||||
* ========================================================================================== */
|
||||
|
@ -148,7 +163,7 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), Maverick
|
|||
}
|
||||
}
|
||||
|
||||
protected fun displayErrorDialog(throwable: Throwable) {
|
||||
protected fun displayErrorDialog(throwable: Throwable?) {
|
||||
displayErrorDialog(errorFormatter.toHumanReadable(throwable))
|
||||
}
|
||||
|
||||
|
|
|
@ -18,17 +18,17 @@ package im.vector.app.features.settings.notifications
|
|||
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
|
||||
import im.vector.app.features.settings.devices.v2.notification.CheckIfCanTogglePushNotificationsViaPusherUseCase
|
||||
import im.vector.app.features.settings.devices.v2.notification.TogglePushNotificationUseCase
|
||||
import javax.inject.Inject
|
||||
|
||||
class DisableNotificationsForCurrentSessionUseCase @Inject constructor(
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
private val pushersManager: PushersManager,
|
||||
private val checkIfCanTogglePushNotificationsViaPusherUseCase: CheckIfCanTogglePushNotificationsViaPusherUseCase,
|
||||
private val togglePushNotificationUseCase: TogglePushNotificationUseCase,
|
||||
private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||
) {
|
||||
|
||||
suspend fun execute() {
|
||||
|
@ -37,7 +37,7 @@ class DisableNotificationsForCurrentSessionUseCase @Inject constructor(
|
|||
if (checkIfCanTogglePushNotificationsViaPusherUseCase.execute(session)) {
|
||||
togglePushNotificationUseCase.execute(deviceId, enabled = false)
|
||||
} else {
|
||||
unifiedPushHelper.unregister(pushersManager)
|
||||
unregisterUnifiedPushUseCase.execute(pushersManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,56 +16,44 @@
|
|||
|
||||
package im.vector.app.features.settings.notifications
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.pushers.FcmHelper
|
||||
import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
import im.vector.app.features.settings.devices.v2.notification.CheckIfCanTogglePushNotificationsViaPusherUseCase
|
||||
import im.vector.app.core.pushers.RegisterUnifiedPushUseCase
|
||||
import im.vector.app.features.settings.devices.v2.notification.TogglePushNotificationUseCase
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class EnableNotificationsForCurrentSessionUseCase @Inject constructor(
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
private val pushersManager: PushersManager,
|
||||
private val fcmHelper: FcmHelper,
|
||||
private val checkIfCanTogglePushNotificationsViaPusherUseCase: CheckIfCanTogglePushNotificationsViaPusherUseCase,
|
||||
private val togglePushNotificationUseCase: TogglePushNotificationUseCase,
|
||||
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
||||
private val ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase,
|
||||
) {
|
||||
|
||||
suspend fun execute(fragmentActivity: FragmentActivity) {
|
||||
sealed interface EnableNotificationsResult {
|
||||
object Success : EnableNotificationsResult
|
||||
object Failure : EnableNotificationsResult
|
||||
object NeedToAskUserForDistributor : EnableNotificationsResult
|
||||
}
|
||||
|
||||
suspend fun execute(distributor: String = ""): EnableNotificationsResult {
|
||||
val pusherForCurrentSession = pushersManager.getPusherForCurrentSession()
|
||||
if (pusherForCurrentSession == null) {
|
||||
registerPusher(fragmentActivity)
|
||||
}
|
||||
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||
if (checkIfCanTogglePushNotificationsViaPusherUseCase.execute(session)) {
|
||||
val deviceId = session.sessionParams.deviceId ?: return
|
||||
togglePushNotificationUseCase.execute(deviceId, enabled = true)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun registerPusher(fragmentActivity: FragmentActivity) {
|
||||
suspendCoroutine { continuation ->
|
||||
try {
|
||||
unifiedPushHelper.register(fragmentActivity) {
|
||||
if (unifiedPushHelper.isEmbeddedDistributor()) {
|
||||
fcmHelper.ensureFcmTokenIsRetrieved(
|
||||
fragmentActivity,
|
||||
pushersManager,
|
||||
registerPusher = true
|
||||
)
|
||||
}
|
||||
continuation.resume(Unit)
|
||||
when (registerUnifiedPushUseCase.execute(distributor)) {
|
||||
is RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor -> {
|
||||
return EnableNotificationsResult.NeedToAskUserForDistributor
|
||||
}
|
||||
RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success -> {
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(pushersManager, registerPusher = true)
|
||||
}
|
||||
} catch (error: Exception) {
|
||||
continuation.resumeWithException(error)
|
||||
}
|
||||
}
|
||||
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return EnableNotificationsResult.Failure
|
||||
val deviceId = session.sessionParams.deviceId ?: return EnableNotificationsResult.Failure
|
||||
togglePushNotificationUseCase.execute(deviceId, enabled = true)
|
||||
|
||||
return EnableNotificationsResult.Success
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.content.Intent
|
|||
import android.media.RingtoneManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
|
@ -29,6 +30,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.lifecycle.map
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.SwitchPreference
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
|
@ -37,6 +39,7 @@ import im.vector.app.core.preference.VectorEditTextPreference
|
|||
import im.vector.app.core.preference.VectorPreference
|
||||
import im.vector.app.core.preference.VectorPreferenceCategory
|
||||
import im.vector.app.core.preference.VectorSwitchPreference
|
||||
import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase
|
||||
import im.vector.app.core.pushers.FcmHelper
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
|
@ -80,14 +83,15 @@ class VectorSettingsNotificationPreferenceFragment :
|
|||
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
||||
@Inject lateinit var vectorFeatures: VectorFeatures
|
||||
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager
|
||||
@Inject lateinit var disableNotificationsForCurrentSessionUseCase: DisableNotificationsForCurrentSessionUseCase
|
||||
@Inject lateinit var enableNotificationsForCurrentSessionUseCase: EnableNotificationsForCurrentSessionUseCase
|
||||
@Inject lateinit var ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase
|
||||
|
||||
override var titleRes: Int = R.string.settings_notifications
|
||||
override val preferenceXmlRes = R.xml.vector_settings_notifications
|
||||
|
||||
private var interactionListener: VectorSettingsFragmentInteractionListener? = null
|
||||
|
||||
private val viewModel: VectorSettingsNotificationPreferenceViewModel by fragmentViewModel()
|
||||
|
||||
private val notificationStartForActivityResult = registerStartForActivityResult { _ ->
|
||||
// No op
|
||||
}
|
||||
|
@ -104,6 +108,23 @@ class VectorSettingsNotificationPreferenceFragment :
|
|||
analyticsScreenName = MobileScreen.ScreenName.SettingsNotifications
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
observeViewEvents()
|
||||
}
|
||||
|
||||
private fun observeViewEvents() {
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
VectorSettingsNotificationPreferenceViewEvent.NotificationsForDeviceEnabled -> onNotificationsForDeviceEnabled()
|
||||
VectorSettingsNotificationPreferenceViewEvent.NotificationsForDeviceDisabled -> onNotificationsForDeviceDisabled()
|
||||
is VectorSettingsNotificationPreferenceViewEvent.AskUserForPushDistributor -> askUserToSelectPushDistributor()
|
||||
VectorSettingsNotificationPreferenceViewEvent.EnableNotificationForDeviceFailure -> displayErrorDialog(throwable = null)
|
||||
VectorSettingsNotificationPreferenceViewEvent.NotificationMethodChanged -> onNotificationMethodChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindPref() {
|
||||
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY)!!.let { pref ->
|
||||
val pushRuleService = session.pushRuleService()
|
||||
|
@ -121,23 +142,15 @@ class VectorSettingsNotificationPreferenceFragment :
|
|||
}
|
||||
|
||||
findPreference<SwitchPreference>(VectorPreferences.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)
|
||||
?.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked ->
|
||||
if (isChecked) {
|
||||
enableNotificationsForCurrentSessionUseCase.execute(requireActivity())
|
||||
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_NOTIFICATION_METHOD_KEY)
|
||||
?.summary = unifiedPushHelper.getCurrentDistributorName()
|
||||
|
||||
notificationPermissionManager.eventuallyRequestPermission(
|
||||
requireActivity(),
|
||||
postPermissionLauncher,
|
||||
showRationale = false,
|
||||
ignorePreference = true
|
||||
)
|
||||
?.setOnPreferenceChangeListener { _, isChecked ->
|
||||
val action = if (isChecked as Boolean) {
|
||||
VectorSettingsNotificationPreferenceViewAction.EnableNotificationsForDevice(pushDistributor = "")
|
||||
} else {
|
||||
disableNotificationsForCurrentSessionUseCase.execute()
|
||||
notificationPermissionManager.eventuallyRevokePermission(requireActivity())
|
||||
VectorSettingsNotificationPreferenceViewAction.DisableNotificationsForDevice
|
||||
}
|
||||
viewModel.handle(action)
|
||||
// preference will be updated on ViewEvent reception
|
||||
false
|
||||
}
|
||||
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_FDROID_BACKGROUND_SYNC_MODE)?.let {
|
||||
|
@ -182,18 +195,7 @@ class VectorSettingsNotificationPreferenceFragment :
|
|||
if (vectorFeatures.allowExternalUnifiedPushDistributors()) {
|
||||
it.summary = unifiedPushHelper.getCurrentDistributorName()
|
||||
it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
unifiedPushHelper.forceRegister(requireActivity(), pushersManager) {
|
||||
if (unifiedPushHelper.isEmbeddedDistributor()) {
|
||||
fcmHelper.ensureFcmTokenIsRetrieved(
|
||||
requireActivity(),
|
||||
pushersManager,
|
||||
vectorPreferences.areNotificationEnabledForDevice()
|
||||
)
|
||||
}
|
||||
it.summary = unifiedPushHelper.getCurrentDistributorName()
|
||||
session.pushersService().refreshPushers()
|
||||
refreshBackgroundSyncPrefs()
|
||||
}
|
||||
askUserToSelectPushDistributor(withUnregister = true)
|
||||
true
|
||||
}
|
||||
} else {
|
||||
|
@ -207,6 +209,42 @@ class VectorSettingsNotificationPreferenceFragment :
|
|||
handleSystemPreference()
|
||||
}
|
||||
|
||||
private fun onNotificationsForDeviceEnabled() {
|
||||
findPreference<SwitchPreference>(VectorPreferences.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)
|
||||
?.isChecked = true
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_NOTIFICATION_METHOD_KEY)
|
||||
?.summary = unifiedPushHelper.getCurrentDistributorName()
|
||||
|
||||
notificationPermissionManager.eventuallyRequestPermission(
|
||||
requireActivity(),
|
||||
postPermissionLauncher,
|
||||
showRationale = false,
|
||||
ignorePreference = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun onNotificationsForDeviceDisabled() {
|
||||
findPreference<SwitchPreference>(VectorPreferences.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)
|
||||
?.isChecked = false
|
||||
notificationPermissionManager.eventuallyRevokePermission(requireActivity())
|
||||
}
|
||||
|
||||
private fun askUserToSelectPushDistributor(withUnregister: Boolean = false) {
|
||||
unifiedPushHelper.showSelectDistributorDialog(requireContext()) { selection ->
|
||||
if (withUnregister) {
|
||||
viewModel.handle(VectorSettingsNotificationPreferenceViewAction.RegisterPushDistributor(selection))
|
||||
} else {
|
||||
viewModel.handle(VectorSettingsNotificationPreferenceViewAction.EnableNotificationsForDevice(selection))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onNotificationMethodChanged() {
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_NOTIFICATION_METHOD_KEY)?.summary = unifiedPushHelper.getCurrentDistributorName()
|
||||
session.pushersService().refreshPushers()
|
||||
refreshBackgroundSyncPrefs()
|
||||
}
|
||||
|
||||
private fun bindEmailNotifications() {
|
||||
val initialEmails = session.getEmailsWithPushInformation()
|
||||
bindEmailNotificationCategory(initialEmails)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.notifications
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed interface VectorSettingsNotificationPreferenceViewAction : VectorViewModelAction {
|
||||
data class EnableNotificationsForDevice(val pushDistributor: String) : VectorSettingsNotificationPreferenceViewAction
|
||||
object DisableNotificationsForDevice : VectorSettingsNotificationPreferenceViewAction
|
||||
data class RegisterPushDistributor(val pushDistributor: String) : VectorSettingsNotificationPreferenceViewAction
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.notifications
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
|
||||
sealed interface VectorSettingsNotificationPreferenceViewEvent : VectorViewEvents {
|
||||
object NotificationsForDeviceEnabled : VectorSettingsNotificationPreferenceViewEvent
|
||||
object EnableNotificationForDeviceFailure : VectorSettingsNotificationPreferenceViewEvent
|
||||
object NotificationsForDeviceDisabled : VectorSettingsNotificationPreferenceViewEvent
|
||||
object AskUserForPushDistributor : VectorSettingsNotificationPreferenceViewEvent
|
||||
object NotificationMethodChanged : VectorSettingsNotificationPreferenceViewEvent
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.notifications
|
||||
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.platform.VectorDummyViewState
|
||||
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.settings.VectorPreferences
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class VectorSettingsNotificationPreferenceViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: VectorDummyViewState,
|
||||
private val pushersManager: PushersManager,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val enableNotificationsForCurrentSessionUseCase: EnableNotificationsForCurrentSessionUseCase,
|
||||
private val disableNotificationsForCurrentSessionUseCase: DisableNotificationsForCurrentSessionUseCase,
|
||||
private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
||||
private val ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase,
|
||||
) : VectorViewModel<VectorDummyViewState, VectorSettingsNotificationPreferenceViewAction, VectorSettingsNotificationPreferenceViewEvent>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<VectorSettingsNotificationPreferenceViewModel, VectorDummyViewState> {
|
||||
override fun create(initialState: VectorDummyViewState): VectorSettingsNotificationPreferenceViewModel
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<VectorSettingsNotificationPreferenceViewModel, VectorDummyViewState> by hiltMavericksViewModelFactory()
|
||||
|
||||
override fun handle(action: VectorSettingsNotificationPreferenceViewAction) {
|
||||
when (action) {
|
||||
VectorSettingsNotificationPreferenceViewAction.DisableNotificationsForDevice -> handleDisableNotificationsForDevice()
|
||||
is VectorSettingsNotificationPreferenceViewAction.EnableNotificationsForDevice -> handleEnableNotificationsForDevice(action.pushDistributor)
|
||||
is VectorSettingsNotificationPreferenceViewAction.RegisterPushDistributor -> handleRegisterPushDistributor(action.pushDistributor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDisableNotificationsForDevice() {
|
||||
viewModelScope.launch {
|
||||
disableNotificationsForCurrentSessionUseCase.execute()
|
||||
_viewEvents.post(VectorSettingsNotificationPreferenceViewEvent.NotificationsForDeviceDisabled)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEnableNotificationsForDevice(distributor: String) {
|
||||
viewModelScope.launch {
|
||||
when (enableNotificationsForCurrentSessionUseCase.execute(distributor)) {
|
||||
EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.Failure -> {
|
||||
_viewEvents.post(VectorSettingsNotificationPreferenceViewEvent.EnableNotificationForDeviceFailure)
|
||||
}
|
||||
is EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.NeedToAskUserForDistributor -> {
|
||||
_viewEvents.post(VectorSettingsNotificationPreferenceViewEvent.AskUserForPushDistributor)
|
||||
}
|
||||
EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.Success -> {
|
||||
_viewEvents.post(VectorSettingsNotificationPreferenceViewEvent.NotificationsForDeviceEnabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRegisterPushDistributor(distributor: String) {
|
||||
viewModelScope.launch {
|
||||
unregisterUnifiedPushUseCase.execute(pushersManager)
|
||||
when (registerUnifiedPushUseCase.execute(distributor)) {
|
||||
RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor -> {
|
||||
_viewEvents.post(VectorSettingsNotificationPreferenceViewEvent.AskUserForPushDistributor)
|
||||
}
|
||||
RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success -> {
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(pushersManager, registerPusher = vectorPreferences.areNotificationEnabledForDevice())
|
||||
_viewEvents.post(VectorSettingsNotificationPreferenceViewEvent.NotificationMethodChanged)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,14 +17,17 @@
|
|||
package im.vector.app.features.settings.troubleshoot
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import im.vector.app.core.pushers.RegisterUnifiedPushUseCase
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.session.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.pushers.PusherState
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -34,6 +37,8 @@ class TestEndpointAsTokenRegistration @Inject constructor(
|
|||
private val pushersManager: PushersManager,
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
||||
private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||
) : TroubleshootTest(R.string.settings_troubleshoot_test_endpoint_registration_title) {
|
||||
|
||||
override fun perform(testParameters: TestParameters) {
|
||||
|
@ -56,27 +61,52 @@ class TestEndpointAsTokenRegistration @Inject constructor(
|
|||
)
|
||||
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_endpoint_registration_quick_fix) {
|
||||
override fun doFix() {
|
||||
unifiedPushHelper.forceRegister(
|
||||
context,
|
||||
pushersManager
|
||||
)
|
||||
val workId = pushersManager.enqueueRegisterPusherWithFcmKey(endpoint)
|
||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
|
||||
if (workInfo != null) {
|
||||
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
||||
manager?.retry(testParameters)
|
||||
} else if (workInfo.state == WorkInfo.State.FAILED) {
|
||||
manager?.retry(testParameters)
|
||||
}
|
||||
}
|
||||
})
|
||||
unregisterThenRegister(testParameters, endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
status = TestStatus.FAILED
|
||||
} else {
|
||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_registration_success)
|
||||
status = TestStatus.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
private fun unregisterThenRegister(testParameters: TestParameters, pushKey: String) {
|
||||
activeSessionHolder.getSafeActiveSession()?.coroutineScope?.launch {
|
||||
unregisterUnifiedPushUseCase.execute(pushersManager)
|
||||
registerUnifiedPush(distributor = "", testParameters, pushKey)
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerUnifiedPush(
|
||||
distributor: String,
|
||||
testParameters: TestParameters,
|
||||
pushKey: String,
|
||||
) {
|
||||
when (registerUnifiedPushUseCase.execute(distributor)) {
|
||||
is RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor ->
|
||||
askUserForDistributor(testParameters, pushKey)
|
||||
RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success -> {
|
||||
val workId = pushersManager.enqueueRegisterPusherWithFcmKey(pushKey)
|
||||
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context) { workInfo ->
|
||||
if (workInfo != null) {
|
||||
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
|
||||
manager?.retry(testParameters)
|
||||
} else if (workInfo.state == WorkInfo.State.FAILED) {
|
||||
manager?.retry(testParameters)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun askUserForDistributor(
|
||||
testParameters: TestParameters,
|
||||
pushKey: String,
|
||||
) {
|
||||
unifiedPushHelper.showSelectDistributorDialog(context) { selection ->
|
||||
registerUnifiedPush(distributor = selection, testParameters, pushKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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.core.pushers
|
||||
|
||||
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||
import im.vector.app.test.fakes.FakeFcmHelper
|
||||
import im.vector.app.test.fakes.FakePushersManager
|
||||
import im.vector.app.test.fakes.FakeUnifiedPushHelper
|
||||
import im.vector.app.test.fixtures.PusherFixture
|
||||
import org.junit.Test
|
||||
|
||||
class EnsureFcmTokenIsRetrievedUseCaseTest {
|
||||
|
||||
private val fakeUnifiedPushHelper = FakeUnifiedPushHelper()
|
||||
private val fakeFcmHelper = FakeFcmHelper()
|
||||
private val fakeActiveSessionHolder = FakeActiveSessionHolder()
|
||||
|
||||
private val ensureFcmTokenIsRetrievedUseCase = EnsureFcmTokenIsRetrievedUseCase(
|
||||
unifiedPushHelper = fakeUnifiedPushHelper.instance,
|
||||
fcmHelper = fakeFcmHelper.instance,
|
||||
activeSessionHolder = fakeActiveSessionHolder.instance,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `given no registered pusher and distributor as embedded when execute then ensure the FCM token is retrieved with register pusher option`() {
|
||||
// Given
|
||||
val aPushersManager = FakePushersManager()
|
||||
fakeUnifiedPushHelper.givenIsEmbeddedDistributorReturns(true)
|
||||
fakeFcmHelper.givenEnsureFcmTokenIsRetrieved(aPushersManager.instance)
|
||||
val aSessionId = "aSessionId"
|
||||
fakeActiveSessionHolder.fakeSession.givenSessionId(aSessionId)
|
||||
val expectedPusher = PusherFixture.aPusher(deviceId = "")
|
||||
fakeActiveSessionHolder.fakeSession.fakePushersService.givenGetPushers(listOf(expectedPusher))
|
||||
|
||||
// When
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(aPushersManager.instance, registerPusher = true)
|
||||
|
||||
// Then
|
||||
fakeFcmHelper.verifyEnsureFcmTokenIsRetrieved(aPushersManager.instance, registerPusher = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a registered pusher and distributor as embedded when execute then ensure the FCM token is retrieved without register pusher option`() {
|
||||
// Given
|
||||
val aPushersManager = FakePushersManager()
|
||||
fakeUnifiedPushHelper.givenIsEmbeddedDistributorReturns(true)
|
||||
fakeFcmHelper.givenEnsureFcmTokenIsRetrieved(aPushersManager.instance)
|
||||
val aSessionId = "aSessionId"
|
||||
fakeActiveSessionHolder.fakeSession.givenSessionId(aSessionId)
|
||||
val expectedPusher = PusherFixture.aPusher(deviceId = aSessionId)
|
||||
fakeActiveSessionHolder.fakeSession.fakePushersService.givenGetPushers(listOf(expectedPusher))
|
||||
|
||||
// When
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(aPushersManager.instance, registerPusher = true)
|
||||
|
||||
// Then
|
||||
fakeFcmHelper.verifyEnsureFcmTokenIsRetrieved(aPushersManager.instance, registerPusher = false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given no registering asked and distributor as embedded when execute then ensure the FCM token is retrieved without register pusher option`() {
|
||||
// Given
|
||||
val aPushersManager = FakePushersManager()
|
||||
fakeUnifiedPushHelper.givenIsEmbeddedDistributorReturns(true)
|
||||
fakeFcmHelper.givenEnsureFcmTokenIsRetrieved(aPushersManager.instance)
|
||||
val aSessionId = "aSessionId"
|
||||
fakeActiveSessionHolder.fakeSession.givenSessionId(aSessionId)
|
||||
val expectedPusher = PusherFixture.aPusher(deviceId = aSessionId)
|
||||
fakeActiveSessionHolder.fakeSession.fakePushersService.givenGetPushers(listOf(expectedPusher))
|
||||
|
||||
// When
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(aPushersManager.instance, registerPusher = false)
|
||||
|
||||
// Then
|
||||
fakeFcmHelper.verifyEnsureFcmTokenIsRetrieved(aPushersManager.instance, registerPusher = false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given distributor as not embedded when execute then nothing is done`() {
|
||||
// Given
|
||||
val aPushersManager = FakePushersManager()
|
||||
fakeUnifiedPushHelper.givenIsEmbeddedDistributorReturns(false)
|
||||
|
||||
// When
|
||||
ensureFcmTokenIsRetrievedUseCase.execute(aPushersManager.instance, registerPusher = true)
|
||||
|
||||
// Then
|
||||
fakeFcmHelper.verifyEnsureFcmTokenIsRetrieved(aPushersManager.instance, registerPusher = true, inverse = true)
|
||||
fakeFcmHelper.verifyEnsureFcmTokenIsRetrieved(aPushersManager.instance, registerPusher = false, inverse = true)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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.core.pushers
|
||||
|
||||
import im.vector.app.test.fakes.FakeContext
|
||||
import im.vector.app.test.fakes.FakeVectorFeatures
|
||||
import io.mockk.every
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkAll
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyAll
|
||||
import io.mockk.verifyOrder
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.amshove.kluent.shouldBe
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
|
||||
class RegisterUnifiedPushUseCaseTest {
|
||||
|
||||
private val fakeContext = FakeContext()
|
||||
private val fakeVectorFeatures = FakeVectorFeatures()
|
||||
|
||||
private val registerUnifiedPushUseCase = RegisterUnifiedPushUseCase(
|
||||
context = fakeContext.instance,
|
||||
vectorFeatures = fakeVectorFeatures,
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(UnifiedPush::class)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given non empty distributor when execute then distributor is saved and app is registered`() = runTest {
|
||||
// Given
|
||||
val aDistributor = "distributor"
|
||||
justRun { UnifiedPush.registerApp(any()) }
|
||||
justRun { UnifiedPush.saveDistributor(any(), any()) }
|
||||
|
||||
// When
|
||||
val result = registerUnifiedPushUseCase.execute(aDistributor)
|
||||
|
||||
// Then
|
||||
result shouldBe RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success
|
||||
verifyOrder {
|
||||
UnifiedPush.saveDistributor(fakeContext.instance, aDistributor)
|
||||
UnifiedPush.registerApp(fakeContext.instance)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given external distributors are not allowed when execute then internal distributor is saved and app is registered`() = runTest {
|
||||
// Given
|
||||
val aPackageName = "packageName"
|
||||
fakeContext.givenPackageName(aPackageName)
|
||||
justRun { UnifiedPush.registerApp(any()) }
|
||||
justRun { UnifiedPush.saveDistributor(any(), any()) }
|
||||
fakeVectorFeatures.givenExternalDistributorsAreAllowed(false)
|
||||
|
||||
// When
|
||||
val result = registerUnifiedPushUseCase.execute()
|
||||
|
||||
// Then
|
||||
result shouldBe RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success
|
||||
verifyOrder {
|
||||
UnifiedPush.saveDistributor(fakeContext.instance, aPackageName)
|
||||
UnifiedPush.registerApp(fakeContext.instance)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a saved distributor and external distributors are allowed when execute then app is registered`() = runTest {
|
||||
// Given
|
||||
justRun { UnifiedPush.registerApp(any()) }
|
||||
val aDistributor = "distributor"
|
||||
every { UnifiedPush.getDistributor(any()) } returns aDistributor
|
||||
fakeVectorFeatures.givenExternalDistributorsAreAllowed(true)
|
||||
|
||||
// When
|
||||
val result = registerUnifiedPushUseCase.execute()
|
||||
|
||||
// Then
|
||||
result shouldBe RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success
|
||||
verifyAll {
|
||||
UnifiedPush.getDistributor(fakeContext.instance)
|
||||
UnifiedPush.registerApp(fakeContext.instance)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given no saved distributor and a unique distributor available when execute then the distributor is saved and app is registered`() = runTest {
|
||||
// Given
|
||||
justRun { UnifiedPush.registerApp(any()) }
|
||||
justRun { UnifiedPush.saveDistributor(any(), any()) }
|
||||
every { UnifiedPush.getDistributor(any()) } returns ""
|
||||
fakeVectorFeatures.givenExternalDistributorsAreAllowed(true)
|
||||
val aDistributor = "distributor"
|
||||
every { UnifiedPush.getDistributors(any()) } returns listOf(aDistributor)
|
||||
|
||||
// When
|
||||
val result = registerUnifiedPushUseCase.execute()
|
||||
|
||||
// Then
|
||||
result shouldBe RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success
|
||||
verifyOrder {
|
||||
UnifiedPush.getDistributor(fakeContext.instance)
|
||||
UnifiedPush.getDistributors(fakeContext.instance)
|
||||
UnifiedPush.saveDistributor(fakeContext.instance, aDistributor)
|
||||
UnifiedPush.registerApp(fakeContext.instance)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given no saved distributor and multiple distributors available when execute then result is to ask user`() = runTest {
|
||||
// Given
|
||||
every { UnifiedPush.getDistributor(any()) } returns ""
|
||||
fakeVectorFeatures.givenExternalDistributorsAreAllowed(true)
|
||||
val aDistributor1 = "distributor1"
|
||||
val aDistributor2 = "distributor2"
|
||||
every { UnifiedPush.getDistributors(any()) } returns listOf(aDistributor1, aDistributor2)
|
||||
|
||||
// When
|
||||
val result = registerUnifiedPushUseCase.execute()
|
||||
|
||||
// Then
|
||||
result shouldBe RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor
|
||||
verifyOrder {
|
||||
UnifiedPush.getDistributor(fakeContext.instance)
|
||||
UnifiedPush.getDistributors(fakeContext.instance)
|
||||
}
|
||||
verify(inverse = true) {
|
||||
UnifiedPush.saveDistributor(any(), any())
|
||||
UnifiedPush.registerApp(any())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.core.pushers
|
||||
|
||||
import im.vector.app.features.settings.BackgroundSyncMode
|
||||
import im.vector.app.test.fakes.FakeContext
|
||||
import im.vector.app.test.fakes.FakePushersManager
|
||||
import im.vector.app.test.fakes.FakeUnifiedPushHelper
|
||||
import im.vector.app.test.fakes.FakeUnifiedPushStore
|
||||
import im.vector.app.test.fakes.FakeVectorPreferences
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkAll
|
||||
import io.mockk.verifyAll
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
|
||||
class UnregisterUnifiedPushUseCaseTest {
|
||||
|
||||
private val fakeContext = FakeContext()
|
||||
private val fakeVectorPreferences = FakeVectorPreferences()
|
||||
private val fakeUnifiedPushStore = FakeUnifiedPushStore()
|
||||
private val fakeUnifiedPushHelper = FakeUnifiedPushHelper()
|
||||
|
||||
private val unregisterUnifiedPushUseCase = UnregisterUnifiedPushUseCase(
|
||||
context = fakeContext.instance,
|
||||
vectorPreferences = fakeVectorPreferences.instance,
|
||||
unifiedPushStore = fakeUnifiedPushStore.instance,
|
||||
unifiedPushHelper = fakeUnifiedPushHelper.instance,
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(UnifiedPush::class)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given pushersManager when execute then unregister and clean everything which is needed`() = runTest {
|
||||
// Given
|
||||
val aEndpoint = "endpoint"
|
||||
fakeUnifiedPushHelper.givenGetEndpointOrTokenReturns(aEndpoint)
|
||||
val aPushersManager = FakePushersManager()
|
||||
aPushersManager.givenUnregisterPusher(aEndpoint)
|
||||
justRun { UnifiedPush.unregisterApp(any()) }
|
||||
fakeVectorPreferences.givenSetFdroidSyncBackgroundMode(BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME)
|
||||
fakeUnifiedPushStore.givenStorePushGateway(null)
|
||||
fakeUnifiedPushStore.givenStoreUpEndpoint(null)
|
||||
|
||||
// When
|
||||
unregisterUnifiedPushUseCase.execute(aPushersManager.instance)
|
||||
|
||||
// Then
|
||||
fakeVectorPreferences.verifySetFdroidSyncBackgroundMode(BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME)
|
||||
aPushersManager.verifyUnregisterPusher(aEndpoint)
|
||||
verifyAll {
|
||||
UnifiedPush.unregisterApp(fakeContext.instance)
|
||||
}
|
||||
fakeUnifiedPushStore.verifyStorePushGateway(null)
|
||||
fakeUnifiedPushStore.verifyStoreUpEndpoint(null)
|
||||
}
|
||||
}
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package im.vector.app.features.settings.notifications
|
||||
|
||||
import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
|
||||
import im.vector.app.features.settings.devices.v2.notification.CheckIfCanTogglePushNotificationsViaPusherUseCase
|
||||
import im.vector.app.features.settings.devices.v2.notification.TogglePushNotificationUseCase
|
||||
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||
import im.vector.app.test.fakes.FakePushersManager
|
||||
import im.vector.app.test.fakes.FakeUnifiedPushHelper
|
||||
import io.mockk.coJustRun
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
|
@ -33,17 +33,17 @@ private const val A_SESSION_ID = "session-id"
|
|||
class DisableNotificationsForCurrentSessionUseCaseTest {
|
||||
|
||||
private val fakeActiveSessionHolder = FakeActiveSessionHolder()
|
||||
private val fakeUnifiedPushHelper = FakeUnifiedPushHelper()
|
||||
private val fakePushersManager = FakePushersManager()
|
||||
private val fakeCheckIfCanTogglePushNotificationsViaPusherUseCase = mockk<CheckIfCanTogglePushNotificationsViaPusherUseCase>()
|
||||
private val fakeTogglePushNotificationUseCase = mockk<TogglePushNotificationUseCase>()
|
||||
private val fakeUnregisterUnifiedPushUseCase = mockk<UnregisterUnifiedPushUseCase>()
|
||||
|
||||
private val disableNotificationsForCurrentSessionUseCase = DisableNotificationsForCurrentSessionUseCase(
|
||||
activeSessionHolder = fakeActiveSessionHolder.instance,
|
||||
unifiedPushHelper = fakeUnifiedPushHelper.instance,
|
||||
pushersManager = fakePushersManager.instance,
|
||||
checkIfCanTogglePushNotificationsViaPusherUseCase = fakeCheckIfCanTogglePushNotificationsViaPusherUseCase,
|
||||
togglePushNotificationUseCase = fakeTogglePushNotificationUseCase,
|
||||
unregisterUnifiedPushUseCase = fakeUnregisterUnifiedPushUseCase,
|
||||
)
|
||||
|
||||
@Test
|
||||
|
@ -67,12 +67,14 @@ class DisableNotificationsForCurrentSessionUseCaseTest {
|
|||
val fakeSession = fakeActiveSessionHolder.fakeSession
|
||||
fakeSession.givenSessionId(A_SESSION_ID)
|
||||
every { fakeCheckIfCanTogglePushNotificationsViaPusherUseCase.execute(fakeSession) } returns false
|
||||
fakeUnifiedPushHelper.givenUnregister(fakePushersManager.instance)
|
||||
coJustRun { fakeUnregisterUnifiedPushUseCase.execute(any()) }
|
||||
|
||||
// When
|
||||
disableNotificationsForCurrentSessionUseCase.execute()
|
||||
|
||||
// Then
|
||||
fakeUnifiedPushHelper.verifyUnregister(fakePushersManager.instance)
|
||||
coVerify {
|
||||
fakeUnregisterUnifiedPushUseCase.execute(fakePushersManager.instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,18 +16,18 @@
|
|||
|
||||
package im.vector.app.features.settings.notifications
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import im.vector.app.features.settings.devices.v2.notification.CheckIfCanTogglePushNotificationsViaPusherUseCase
|
||||
import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase
|
||||
import im.vector.app.core.pushers.RegisterUnifiedPushUseCase
|
||||
import im.vector.app.features.settings.devices.v2.notification.TogglePushNotificationUseCase
|
||||
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||
import im.vector.app.test.fakes.FakeFcmHelper
|
||||
import im.vector.app.test.fakes.FakePushersManager
|
||||
import im.vector.app.test.fakes.FakeUnifiedPushHelper
|
||||
import io.mockk.coJustRun
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.amshove.kluent.shouldBe
|
||||
import org.junit.Test
|
||||
|
||||
private const val A_SESSION_ID = "session-id"
|
||||
|
@ -35,53 +35,71 @@ private const val A_SESSION_ID = "session-id"
|
|||
class EnableNotificationsForCurrentSessionUseCaseTest {
|
||||
|
||||
private val fakeActiveSessionHolder = FakeActiveSessionHolder()
|
||||
private val fakeUnifiedPushHelper = FakeUnifiedPushHelper()
|
||||
private val fakePushersManager = FakePushersManager()
|
||||
private val fakeFcmHelper = FakeFcmHelper()
|
||||
private val fakeCheckIfCanTogglePushNotificationsViaPusherUseCase = mockk<CheckIfCanTogglePushNotificationsViaPusherUseCase>()
|
||||
private val fakeTogglePushNotificationUseCase = mockk<TogglePushNotificationUseCase>()
|
||||
private val fakeRegisterUnifiedPushUseCase = mockk<RegisterUnifiedPushUseCase>()
|
||||
private val fakeEnsureFcmTokenIsRetrievedUseCase = mockk<EnsureFcmTokenIsRetrievedUseCase>()
|
||||
|
||||
private val enableNotificationsForCurrentSessionUseCase = EnableNotificationsForCurrentSessionUseCase(
|
||||
activeSessionHolder = fakeActiveSessionHolder.instance,
|
||||
unifiedPushHelper = fakeUnifiedPushHelper.instance,
|
||||
pushersManager = fakePushersManager.instance,
|
||||
fcmHelper = fakeFcmHelper.instance,
|
||||
checkIfCanTogglePushNotificationsViaPusherUseCase = fakeCheckIfCanTogglePushNotificationsViaPusherUseCase,
|
||||
togglePushNotificationUseCase = fakeTogglePushNotificationUseCase,
|
||||
registerUnifiedPushUseCase = fakeRegisterUnifiedPushUseCase,
|
||||
ensureFcmTokenIsRetrievedUseCase = fakeEnsureFcmTokenIsRetrievedUseCase,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `given no existing pusher for current session when execute then a new pusher is registered`() = runTest {
|
||||
fun `given no existing pusher and a registered distributor when execute then a new pusher is registered and result is success`() = runTest {
|
||||
// Given
|
||||
val fragmentActivity = mockk<FragmentActivity>()
|
||||
fakePushersManager.givenGetPusherForCurrentSessionReturns(null)
|
||||
fakeUnifiedPushHelper.givenRegister(fragmentActivity)
|
||||
fakeUnifiedPushHelper.givenIsEmbeddedDistributorReturns(true)
|
||||
fakeFcmHelper.givenEnsureFcmTokenIsRetrieved(fragmentActivity, fakePushersManager.instance)
|
||||
every { fakeCheckIfCanTogglePushNotificationsViaPusherUseCase.execute(fakeActiveSessionHolder.fakeSession) } returns false
|
||||
|
||||
// When
|
||||
enableNotificationsForCurrentSessionUseCase.execute(fragmentActivity)
|
||||
|
||||
// Then
|
||||
fakeUnifiedPushHelper.verifyRegister(fragmentActivity)
|
||||
fakeFcmHelper.verifyEnsureFcmTokenIsRetrieved(fragmentActivity, fakePushersManager.instance, registerPusher = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given toggle via Pusher is possible when execute then current pusher is toggled to true`() = runTest {
|
||||
// Given
|
||||
val fragmentActivity = mockk<FragmentActivity>()
|
||||
fakePushersManager.givenGetPusherForCurrentSessionReturns(mockk())
|
||||
val aDistributor = "distributor"
|
||||
val fakeSession = fakeActiveSessionHolder.fakeSession
|
||||
fakeSession.givenSessionId(A_SESSION_ID)
|
||||
every { fakeCheckIfCanTogglePushNotificationsViaPusherUseCase.execute(fakeActiveSessionHolder.fakeSession) } returns true
|
||||
fakePushersManager.givenGetPusherForCurrentSessionReturns(null)
|
||||
every { fakeRegisterUnifiedPushUseCase.execute(any()) } returns RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success
|
||||
justRun { fakeEnsureFcmTokenIsRetrievedUseCase.execute(any(), any()) }
|
||||
coJustRun { fakeTogglePushNotificationUseCase.execute(A_SESSION_ID, any()) }
|
||||
|
||||
// When
|
||||
enableNotificationsForCurrentSessionUseCase.execute(fragmentActivity)
|
||||
val result = enableNotificationsForCurrentSessionUseCase.execute(aDistributor)
|
||||
|
||||
// Then
|
||||
coVerify { fakeTogglePushNotificationUseCase.execute(A_SESSION_ID, true) }
|
||||
result shouldBe EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.Success
|
||||
verify {
|
||||
fakeRegisterUnifiedPushUseCase.execute(aDistributor)
|
||||
fakeEnsureFcmTokenIsRetrievedUseCase.execute(fakePushersManager.instance, registerPusher = true)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given no existing pusher and a no registered distributor when execute then result is need to ask user for distributor`() = runTest {
|
||||
// Given
|
||||
val aDistributor = "distributor"
|
||||
fakePushersManager.givenGetPusherForCurrentSessionReturns(null)
|
||||
every { fakeRegisterUnifiedPushUseCase.execute(any()) } returns RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor
|
||||
|
||||
// When
|
||||
val result = enableNotificationsForCurrentSessionUseCase.execute(aDistributor)
|
||||
|
||||
// Then
|
||||
result shouldBe EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.NeedToAskUserForDistributor
|
||||
verify {
|
||||
fakeRegisterUnifiedPushUseCase.execute(aDistributor)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given no deviceId for current session when execute then result is failure`() = runTest {
|
||||
// Given
|
||||
val aDistributor = "distributor"
|
||||
val fakeSession = fakeActiveSessionHolder.fakeSession
|
||||
fakeSession.givenSessionId(null)
|
||||
fakePushersManager.givenGetPusherForCurrentSessionReturns(mockk())
|
||||
every { fakeRegisterUnifiedPushUseCase.execute(any()) } returns RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor
|
||||
|
||||
// When
|
||||
val result = enableNotificationsForCurrentSessionUseCase.execute(aDistributor)
|
||||
|
||||
// Then
|
||||
result shouldBe EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.Failure
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* 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.notifications
|
||||
|
||||
import com.airbnb.mvrx.test.MavericksTestRule
|
||||
import im.vector.app.core.platform.VectorDummyViewState
|
||||
import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase
|
||||
import im.vector.app.core.pushers.RegisterUnifiedPushUseCase
|
||||
import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
|
||||
import im.vector.app.test.fakes.FakePushersManager
|
||||
import im.vector.app.test.fakes.FakeVectorPreferences
|
||||
import im.vector.app.test.test
|
||||
import im.vector.app.test.testDispatcher
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coJustRun
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockk
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class VectorSettingsNotificationPreferenceViewModelTest {
|
||||
|
||||
@get:Rule
|
||||
val mavericksTestRule = MavericksTestRule(testDispatcher = testDispatcher)
|
||||
|
||||
private val fakePushersManager = FakePushersManager()
|
||||
private val fakeVectorPreferences = FakeVectorPreferences()
|
||||
private val fakeEnableNotificationsForCurrentSessionUseCase = mockk<EnableNotificationsForCurrentSessionUseCase>()
|
||||
private val fakeDisableNotificationsForCurrentSessionUseCase = mockk<DisableNotificationsForCurrentSessionUseCase>()
|
||||
private val fakeUnregisterUnifiedPushUseCase = mockk<UnregisterUnifiedPushUseCase>()
|
||||
private val fakeRegisterUnifiedPushUseCase = mockk<RegisterUnifiedPushUseCase>()
|
||||
private val fakeEnsureFcmTokenIsRetrievedUseCase = mockk<EnsureFcmTokenIsRetrievedUseCase>()
|
||||
|
||||
private fun createViewModel() = VectorSettingsNotificationPreferenceViewModel(
|
||||
initialState = VectorDummyViewState(),
|
||||
pushersManager = fakePushersManager.instance,
|
||||
vectorPreferences = fakeVectorPreferences.instance,
|
||||
enableNotificationsForCurrentSessionUseCase = fakeEnableNotificationsForCurrentSessionUseCase,
|
||||
disableNotificationsForCurrentSessionUseCase = fakeDisableNotificationsForCurrentSessionUseCase,
|
||||
unregisterUnifiedPushUseCase = fakeUnregisterUnifiedPushUseCase,
|
||||
registerUnifiedPushUseCase = fakeRegisterUnifiedPushUseCase,
|
||||
ensureFcmTokenIsRetrievedUseCase = fakeEnsureFcmTokenIsRetrievedUseCase,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `given DisableNotificationsForDevice action when handling action then disable use case is called`() {
|
||||
// Given
|
||||
val viewModel = createViewModel()
|
||||
val action = VectorSettingsNotificationPreferenceViewAction.DisableNotificationsForDevice
|
||||
coJustRun { fakeDisableNotificationsForCurrentSessionUseCase.execute() }
|
||||
val expectedEvent = VectorSettingsNotificationPreferenceViewEvent.NotificationsForDeviceDisabled
|
||||
|
||||
// When
|
||||
val viewModelTest = viewModel.test()
|
||||
viewModel.handle(action)
|
||||
|
||||
// Then
|
||||
viewModelTest
|
||||
.assertEvent { event -> event == expectedEvent }
|
||||
.finish()
|
||||
coVerify {
|
||||
fakeDisableNotificationsForCurrentSessionUseCase.execute()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given EnableNotificationsForDevice action and enable success when handling action then enable use case is called`() {
|
||||
// Given
|
||||
val viewModel = createViewModel()
|
||||
val aDistributor = "aDistributor"
|
||||
val action = VectorSettingsNotificationPreferenceViewAction.EnableNotificationsForDevice(aDistributor)
|
||||
coEvery { fakeEnableNotificationsForCurrentSessionUseCase.execute(any()) } returns
|
||||
EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.Success
|
||||
val expectedEvent = VectorSettingsNotificationPreferenceViewEvent.NotificationsForDeviceEnabled
|
||||
|
||||
// When
|
||||
val viewModelTest = viewModel.test()
|
||||
viewModel.handle(action)
|
||||
|
||||
// Then
|
||||
viewModelTest
|
||||
.assertEvent { event -> event == expectedEvent }
|
||||
.finish()
|
||||
coVerify {
|
||||
fakeEnableNotificationsForCurrentSessionUseCase.execute(aDistributor)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given EnableNotificationsForDevice action and enable needs user choice when handling action then enable use case is called`() {
|
||||
// Given
|
||||
val viewModel = createViewModel()
|
||||
val aDistributor = "aDistributor"
|
||||
val action = VectorSettingsNotificationPreferenceViewAction.EnableNotificationsForDevice(aDistributor)
|
||||
coEvery { fakeEnableNotificationsForCurrentSessionUseCase.execute(any()) } returns
|
||||
EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.NeedToAskUserForDistributor
|
||||
val expectedEvent = VectorSettingsNotificationPreferenceViewEvent.AskUserForPushDistributor
|
||||
|
||||
// When
|
||||
val viewModelTest = viewModel.test()
|
||||
viewModel.handle(action)
|
||||
|
||||
// Then
|
||||
viewModelTest
|
||||
.assertEvent { event -> event == expectedEvent }
|
||||
.finish()
|
||||
coVerify {
|
||||
fakeEnableNotificationsForCurrentSessionUseCase.execute(aDistributor)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given EnableNotificationsForDevice action and enable failure when handling action then enable use case is called`() {
|
||||
// Given
|
||||
val viewModel = createViewModel()
|
||||
val aDistributor = "aDistributor"
|
||||
val action = VectorSettingsNotificationPreferenceViewAction.EnableNotificationsForDevice(aDistributor)
|
||||
coEvery { fakeEnableNotificationsForCurrentSessionUseCase.execute(any()) } returns
|
||||
EnableNotificationsForCurrentSessionUseCase.EnableNotificationsResult.Failure
|
||||
val expectedEvent = VectorSettingsNotificationPreferenceViewEvent.EnableNotificationForDeviceFailure
|
||||
|
||||
// When
|
||||
val viewModelTest = viewModel.test()
|
||||
viewModel.handle(action)
|
||||
|
||||
// Then
|
||||
viewModelTest
|
||||
.assertEvent { event -> event == expectedEvent }
|
||||
.finish()
|
||||
coVerify {
|
||||
fakeEnableNotificationsForCurrentSessionUseCase.execute(aDistributor)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given RegisterPushDistributor action and register success when handling action then register use case is called`() {
|
||||
// Given
|
||||
val viewModel = createViewModel()
|
||||
val aDistributor = "aDistributor"
|
||||
val action = VectorSettingsNotificationPreferenceViewAction.RegisterPushDistributor(aDistributor)
|
||||
coEvery { fakeRegisterUnifiedPushUseCase.execute(any()) } returns RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.Success
|
||||
coJustRun { fakeUnregisterUnifiedPushUseCase.execute(any()) }
|
||||
val areNotificationsEnabled = true
|
||||
fakeVectorPreferences.givenAreNotificationsEnabledForDevice(areNotificationsEnabled)
|
||||
justRun { fakeEnsureFcmTokenIsRetrievedUseCase.execute(any(), any()) }
|
||||
val expectedEvent = VectorSettingsNotificationPreferenceViewEvent.NotificationMethodChanged
|
||||
|
||||
// When
|
||||
val viewModelTest = viewModel.test()
|
||||
viewModel.handle(action)
|
||||
|
||||
// Then
|
||||
viewModelTest
|
||||
.assertEvent { event -> event == expectedEvent }
|
||||
.finish()
|
||||
coVerifyOrder {
|
||||
fakeUnregisterUnifiedPushUseCase.execute(fakePushersManager.instance)
|
||||
fakeRegisterUnifiedPushUseCase.execute(aDistributor)
|
||||
fakeEnsureFcmTokenIsRetrievedUseCase.execute(fakePushersManager.instance, registerPusher = areNotificationsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given RegisterPushDistributor action and register needs user choice when handling action then register use case is called`() {
|
||||
// Given
|
||||
val viewModel = createViewModel()
|
||||
val aDistributor = "aDistributor"
|
||||
val action = VectorSettingsNotificationPreferenceViewAction.RegisterPushDistributor(aDistributor)
|
||||
coEvery { fakeRegisterUnifiedPushUseCase.execute(any()) } returns RegisterUnifiedPushUseCase.RegisterUnifiedPushResult.NeedToAskUserForDistributor
|
||||
coJustRun { fakeUnregisterUnifiedPushUseCase.execute(any()) }
|
||||
val expectedEvent = VectorSettingsNotificationPreferenceViewEvent.AskUserForPushDistributor
|
||||
|
||||
// When
|
||||
val viewModelTest = viewModel.test()
|
||||
viewModel.handle(action)
|
||||
|
||||
// Then
|
||||
viewModelTest
|
||||
.assertEvent { event -> event == expectedEvent }
|
||||
.finish()
|
||||
coVerifyOrder {
|
||||
fakeUnregisterUnifiedPushUseCase.execute(fakePushersManager.instance)
|
||||
fakeRegisterUnifiedPushUseCase.execute(aDistributor)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -81,4 +81,8 @@ class FakeContext(
|
|||
givenService(Context.CLIPBOARD_SERVICE, ClipboardManager::class.java, fakeClipboardManager.instance)
|
||||
return fakeClipboardManager
|
||||
}
|
||||
|
||||
fun givenPackageName(name: String) {
|
||||
every { instance.packageName } returns name
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import im.vector.app.core.pushers.FcmHelper
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import io.mockk.justRun
|
||||
|
@ -27,18 +26,15 @@ class FakeFcmHelper {
|
|||
|
||||
val instance = mockk<FcmHelper>()
|
||||
|
||||
fun givenEnsureFcmTokenIsRetrieved(
|
||||
fragmentActivity: FragmentActivity,
|
||||
pushersManager: PushersManager,
|
||||
) {
|
||||
justRun { instance.ensureFcmTokenIsRetrieved(fragmentActivity, pushersManager, any()) }
|
||||
fun givenEnsureFcmTokenIsRetrieved(pushersManager: PushersManager) {
|
||||
justRun { instance.ensureFcmTokenIsRetrieved(pushersManager, any()) }
|
||||
}
|
||||
|
||||
fun verifyEnsureFcmTokenIsRetrieved(
|
||||
fragmentActivity: FragmentActivity,
|
||||
pushersManager: PushersManager,
|
||||
registerPusher: Boolean,
|
||||
inverse: Boolean = false,
|
||||
) {
|
||||
verify { instance.ensureFcmTokenIsRetrieved(fragmentActivity, pushersManager, registerPusher) }
|
||||
verify(inverse = inverse) { instance.ensureFcmTokenIsRetrieved(pushersManager, registerPusher) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import io.mockk.coJustRun
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
||||
|
@ -28,4 +30,12 @@ class FakePushersManager {
|
|||
fun givenGetPusherForCurrentSessionReturns(pusher: Pusher?) {
|
||||
every { instance.getPusherForCurrentSession() } returns pusher
|
||||
}
|
||||
|
||||
fun givenUnregisterPusher(pushKey: String) {
|
||||
coJustRun { instance.unregisterPusher(pushKey) }
|
||||
}
|
||||
|
||||
fun verifyUnregisterPusher(pushKey: String) {
|
||||
coVerify { instance.unregisterPusher(pushKey) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,38 +16,19 @@
|
|||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||
import io.mockk.coJustRun
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
|
||||
class FakeUnifiedPushHelper {
|
||||
|
||||
val instance = mockk<UnifiedPushHelper>()
|
||||
|
||||
fun givenRegister(fragmentActivity: FragmentActivity) {
|
||||
every { instance.register(fragmentActivity, any()) } answers {
|
||||
secondArg<Runnable>().run()
|
||||
}
|
||||
}
|
||||
|
||||
fun verifyRegister(fragmentActivity: FragmentActivity) {
|
||||
verify { instance.register(fragmentActivity, any()) }
|
||||
}
|
||||
|
||||
fun givenUnregister(pushersManager: PushersManager) {
|
||||
coJustRun { instance.unregister(pushersManager) }
|
||||
}
|
||||
|
||||
fun verifyUnregister(pushersManager: PushersManager) {
|
||||
coVerify { instance.unregister(pushersManager) }
|
||||
}
|
||||
|
||||
fun givenIsEmbeddedDistributorReturns(isEmbedded: Boolean) {
|
||||
every { instance.isEmbeddedDistributor() } returns isEmbedded
|
||||
}
|
||||
|
||||
fun givenGetEndpointOrTokenReturns(endpoint: String?) {
|
||||
every { instance.getEndpointOrToken() } returns endpoint
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.test.fakes
|
||||
|
||||
import im.vector.app.core.pushers.UnifiedPushStore
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
|
||||
class FakeUnifiedPushStore {
|
||||
|
||||
val instance = mockk<UnifiedPushStore>()
|
||||
|
||||
fun givenStoreUpEndpoint(endpoint: String?) {
|
||||
justRun { instance.storeUpEndpoint(endpoint) }
|
||||
}
|
||||
|
||||
fun verifyStoreUpEndpoint(endpoint: String?) {
|
||||
verify { instance.storeUpEndpoint(endpoint) }
|
||||
}
|
||||
|
||||
fun givenStorePushGateway(gateway: String?) {
|
||||
justRun { instance.storePushGateway(gateway) }
|
||||
}
|
||||
|
||||
fun verifyStorePushGateway(gateway: String?) {
|
||||
verify { instance.storePushGateway(gateway) }
|
||||
}
|
||||
}
|
|
@ -54,4 +54,8 @@ class FakeVectorFeatures : VectorFeatures by spyk<DefaultVectorFeatures>() {
|
|||
fun givenUnverifiedSessionsAlertEnabled(isEnabled: Boolean) {
|
||||
every { isUnverifiedSessionsAlertEnabled() } returns isEnabled
|
||||
}
|
||||
|
||||
fun givenExternalDistributorsAreAllowed(allowed: Boolean) {
|
||||
every { allowExternalUnifiedPushDistributors() } returns allowed
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.features.settings.BackgroundSyncMode
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import io.mockk.every
|
||||
import io.mockk.justRun
|
||||
|
@ -60,4 +61,16 @@ class FakeVectorPreferences {
|
|||
fun givenUnverifiedSessionsAlertLastShownMillis(lastShownMillis: Long) {
|
||||
every { instance.getUnverifiedSessionsAlertLastShownMillis(any()) } returns lastShownMillis
|
||||
}
|
||||
|
||||
fun givenSetFdroidSyncBackgroundMode(mode: BackgroundSyncMode) {
|
||||
justRun { instance.setFdroidSyncBackgroundMode(mode) }
|
||||
}
|
||||
|
||||
fun verifySetFdroidSyncBackgroundMode(mode: BackgroundSyncMode) {
|
||||
verify { instance.setFdroidSyncBackgroundMode(mode) }
|
||||
}
|
||||
|
||||
fun givenAreNotificationsEnabledForDevice(notificationsEnabled: Boolean) {
|
||||
every { instance.areNotificationEnabledForDevice() } returns notificationsEnabled
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue