From 114982d64aec8b5d8e7767048d979f6c058eb921 Mon Sep 17 00:00:00 2001 From: Andre Rosado Date: Wed, 20 Nov 2024 18:56:46 +0000 Subject: [PATCH] adding MainViewModel navigation to LoginApprovalViewModel --- .../java/com/x8bit/bitwarden/MainActivity.kt | 8 +++++++ .../java/com/x8bit/bitwarden/MainViewModel.kt | 24 +++++++++++++------ .../AuthRequestNotificationManagerImpl.kt | 12 +++++++++- .../data/auth/manager/di/AuthManagerModule.kt | 3 +++ .../loginapproval/LoginApprovalNavigation.kt | 15 +++++++++--- .../loginapproval/LoginApprovalViewModel.kt | 20 +++++++++++----- 6 files changed, 65 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt b/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt index 175487965b2..29886529f43 100644 --- a/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt +++ b/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt @@ -25,6 +25,7 @@ import com.x8bit.bitwarden.ui.platform.composition.LocalManagerProvider import com.x8bit.bitwarden.ui.platform.feature.debugmenu.manager.DebugMenuLaunchManager import com.x8bit.bitwarden.ui.platform.feature.debugmenu.navigateToDebugMenuScreen import com.x8bit.bitwarden.ui.platform.feature.rootnav.RootNavScreen +import com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.loginapproval.navigateToLoginApproval import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -94,6 +95,13 @@ class MainActivity : AppCompatActivity() { ) .show() } + + is MainEvent.NavigateToLoginApproval -> { + navController.navigateToLoginApproval( + fingerprint = "", + requestId = event.requestId, + ) + } } } updateScreenCapture(isScreenCaptureAllowed = state.isScreenCaptureAllowed) diff --git a/app/src/main/java/com/x8bit/bitwarden/MainViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/MainViewModel.kt index 8432a388d70..bac858312a2 100644 --- a/app/src/main/java/com/x8bit/bitwarden/MainViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/MainViewModel.kt @@ -273,13 +273,16 @@ class MainViewModel @Inject constructor( authRepository.switchAccount(passwordlessRequestData.userId) } } - specialCircumstanceManager.specialCircumstance = - SpecialCircumstance.PasswordlessRequest( - passwordlessRequestData = passwordlessRequestData, - // Allow users back into the already-running app when completing the - // autofill task when this is not the first intent. - shouldFinishWhenComplete = isFirstIntent, - ) + + sendEvent(MainEvent.NavigateToLoginApproval(passwordlessRequestData.loginRequestId)) + +// specialCircumstanceManager.specialCircumstance = +// SpecialCircumstance.PasswordlessRequest( +// passwordlessRequestData = passwordlessRequestData, +// // Allow users back into the already-running app when completing the +// // autofill task when this is not the first intent. +// shouldFinishWhenComplete = isFirstIntent, +// ) } completeRegistrationData != null -> { @@ -518,4 +521,11 @@ sealed class MainEvent { * Show a toast with the given [message]. */ data class ShowToast(val message: Text) : MainEvent() + + /** + * Navigates to the Login Approval screen with the given fingerprint. + */ + data class NavigateToLoginApproval( + val requestId: String, + ) : MainEvent() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/AuthRequestNotificationManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/AuthRequestNotificationManagerImpl.kt index f2752a54d81..a1e4aef530b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/AuthRequestNotificationManagerImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/AuthRequestNotificationManagerImpl.kt @@ -12,8 +12,10 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.auth.util.createPasswordlessRequestDataIntent import com.x8bit.bitwarden.data.autofill.util.toPendingIntentMutabilityFlag import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage +import com.x8bit.bitwarden.data.platform.manager.AppStateManager import com.x8bit.bitwarden.data.platform.manager.PushManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager +import com.x8bit.bitwarden.data.platform.manager.model.AppForegroundState import com.x8bit.bitwarden.data.platform.manager.model.PasswordlessRequestData import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn @@ -28,6 +30,7 @@ class AuthRequestNotificationManagerImpl( private val authDiskSource: AuthDiskSource, pushManager: PushManager, dispatcherManager: DispatcherManager, + private val appStateManager: AppStateManager, ) : AuthRequestNotificationManager { private val ioScope = CoroutineScope(dispatcherManager.io) @@ -40,6 +43,13 @@ class AuthRequestNotificationManagerImpl( @SuppressLint("MissingPermission") private fun handlePasswordlessRequestData(data: PasswordlessRequestData) { + + val pendingIntent = createContentIntent(data) + if (appStateManager.appForegroundStateFlow.value == AppForegroundState.FOREGROUNDED) { + pendingIntent.send() + return + } + val notificationManager = NotificationManagerCompat.from(context) // Construct the channel, calling this more than once is safe notificationManager.createNotificationChannel( @@ -54,7 +64,7 @@ class AuthRequestNotificationManagerImpl( if (!notificationManager.areNotificationsEnabled(NOTIFICATION_CHANNEL_ID)) return // Create the notification val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) - .setContentIntent(createContentIntent(data)) + .setContentIntent(pendingIntent) .setContentTitle(context.getString(R.string.log_in_requested)) .setContentText( authDiskSource diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/di/AuthManagerModule.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/di/AuthManagerModule.kt index 0b84837ee73..8539c19e2a4 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/di/AuthManagerModule.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/di/AuthManagerModule.kt @@ -21,6 +21,7 @@ import com.x8bit.bitwarden.data.auth.manager.UserLogoutManager import com.x8bit.bitwarden.data.auth.manager.UserLogoutManagerImpl import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource +import com.x8bit.bitwarden.data.platform.manager.AppStateManager import com.x8bit.bitwarden.data.platform.manager.PushManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.tools.generator.datasource.disk.GeneratorDiskSource @@ -49,12 +50,14 @@ object AuthManagerModule { authDiskSource: AuthDiskSource, pushManager: PushManager, dispatcherManager: DispatcherManager, + appStateManager: AppStateManager, ): AuthRequestNotificationManager = AuthRequestNotificationManagerImpl( context = context, authDiskSource = authDiskSource, pushManager = pushManager, dispatcherManager = dispatcherManager, + appStateManager = appStateManager, ) @Provides diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalNavigation.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalNavigation.kt index 17aeba6d3bc..ddfd040a15f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalNavigation.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalNavigation.kt @@ -10,16 +10,19 @@ import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage import com.x8bit.bitwarden.ui.platform.base.util.composableWithSlideTransitions private const val FINGERPRINT: String = "fingerprint" +private const val REQUEST_ID: String = "requestId" private const val LOGIN_APPROVAL_PREFIX = "login_approval" -private const val LOGIN_APPROVAL_ROUTE = "$LOGIN_APPROVAL_PREFIX?$FINGERPRINT={$FINGERPRINT}" +private const val LOGIN_APPROVAL_ROUTE = + "$LOGIN_APPROVAL_PREFIX?$FINGERPRINT={$FINGERPRINT}&$REQUEST_ID={$REQUEST_ID}" /** * Class to retrieve login approval arguments from the [SavedStateHandle]. */ @OmitFromCoverage -data class LoginApprovalArgs(val fingerprint: String?) { +data class LoginApprovalArgs(val fingerprint: String?, val requestId: String?) { constructor(savedStateHandle: SavedStateHandle) : this( fingerprint = savedStateHandle.get(FINGERPRINT), + requestId = savedStateHandle.get(REQUEST_ID), ) } @@ -37,6 +40,11 @@ fun NavGraphBuilder.loginApprovalDestination( nullable = true defaultValue = null }, + navArgument(REQUEST_ID) { + type = NavType.StringType + nullable = true + defaultValue = null + }, ), ) { LoginApprovalScreen( @@ -50,7 +58,8 @@ fun NavGraphBuilder.loginApprovalDestination( */ fun NavController.navigateToLoginApproval( fingerprint: String?, + requestId: String? = null, navOptions: NavOptions? = null, ) { - navigate("$LOGIN_APPROVAL_PREFIX?$FINGERPRINT=$fingerprint", navOptions) + navigate("$LOGIN_APPROVAL_PREFIX?$FINGERPRINT=$fingerprint&$REQUEST_ID=$requestId", navOptions) } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModel.kt index b09cd9aa0b5..c45d23a5e49 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModel.kt @@ -48,7 +48,7 @@ class LoginApprovalViewModel @Inject constructor( ?: requireNotNull(LoginApprovalArgs(savedStateHandle).fingerprint), masterPasswordHash = null, publicKey = "", - requestId = "", + requestId = LoginApprovalArgs(savedStateHandle).requestId.orEmpty(), viewState = LoginApprovalState.ViewState.Loading, dialogState = null, ) @@ -86,11 +86,19 @@ class LoginApprovalViewModel @Inject constructor( } } ?: run { - authRepository - .getAuthRequestByFingerprintFlow(state.fingerprint) - .map { LoginApprovalAction.Internal.AuthRequestResultReceive(it) } - .onEach(::sendAction) - .launchIn(viewModelScope) + if (state.requestId.isNotEmpty()) { + authRepository + .getAuthRequestByIdFlow(state.requestId) + .map { LoginApprovalAction.Internal.AuthRequestResultReceive(it) } + .onEach(::sendAction) + .launchIn(viewModelScope) + } else { + authRepository + .getAuthRequestByIdFlow(state.fingerprint) + .map { LoginApprovalAction.Internal.AuthRequestResultReceive(it) } + .onEach(::sendAction) + .launchIn(viewModelScope) + } } }