mirror of
https://github.com/bitwarden/android.git
synced 2025-02-02 05:01:02 +03:00
adding MainViewModel navigation to LoginApprovalViewModel
This commit is contained in:
parent
5ea17700b3
commit
114982d64a
6 changed files with 65 additions and 17 deletions
|
@ -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.manager.DebugMenuLaunchManager
|
||||||
import com.x8bit.bitwarden.ui.platform.feature.debugmenu.navigateToDebugMenuScreen
|
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.rootnav.RootNavScreen
|
||||||
|
import com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.loginapproval.navigateToLoginApproval
|
||||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -94,6 +95,13 @@ class MainActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is MainEvent.NavigateToLoginApproval -> {
|
||||||
|
navController.navigateToLoginApproval(
|
||||||
|
fingerprint = "",
|
||||||
|
requestId = event.requestId,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateScreenCapture(isScreenCaptureAllowed = state.isScreenCaptureAllowed)
|
updateScreenCapture(isScreenCaptureAllowed = state.isScreenCaptureAllowed)
|
||||||
|
|
|
@ -273,13 +273,16 @@ class MainViewModel @Inject constructor(
|
||||||
authRepository.switchAccount(passwordlessRequestData.userId)
|
authRepository.switchAccount(passwordlessRequestData.userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
specialCircumstanceManager.specialCircumstance =
|
|
||||||
SpecialCircumstance.PasswordlessRequest(
|
sendEvent(MainEvent.NavigateToLoginApproval(passwordlessRequestData.loginRequestId))
|
||||||
passwordlessRequestData = passwordlessRequestData,
|
|
||||||
// Allow users back into the already-running app when completing the
|
// specialCircumstanceManager.specialCircumstance =
|
||||||
// autofill task when this is not the first intent.
|
// SpecialCircumstance.PasswordlessRequest(
|
||||||
shouldFinishWhenComplete = isFirstIntent,
|
// 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 -> {
|
completeRegistrationData != null -> {
|
||||||
|
@ -518,4 +521,11 @@ sealed class MainEvent {
|
||||||
* Show a toast with the given [message].
|
* Show a toast with the given [message].
|
||||||
*/
|
*/
|
||||||
data class ShowToast(val message: Text) : MainEvent()
|
data class ShowToast(val message: Text) : MainEvent()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to the Login Approval screen with the given fingerprint.
|
||||||
|
*/
|
||||||
|
data class NavigateToLoginApproval(
|
||||||
|
val requestId: String,
|
||||||
|
) : MainEvent()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.auth.util.createPasswordlessRequestDataIntent
|
||||||
import com.x8bit.bitwarden.data.autofill.util.toPendingIntentMutabilityFlag
|
import com.x8bit.bitwarden.data.autofill.util.toPendingIntentMutabilityFlag
|
||||||
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
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.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
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 com.x8bit.bitwarden.data.platform.manager.model.PasswordlessRequestData
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -28,6 +30,7 @@ class AuthRequestNotificationManagerImpl(
|
||||||
private val authDiskSource: AuthDiskSource,
|
private val authDiskSource: AuthDiskSource,
|
||||||
pushManager: PushManager,
|
pushManager: PushManager,
|
||||||
dispatcherManager: DispatcherManager,
|
dispatcherManager: DispatcherManager,
|
||||||
|
private val appStateManager: AppStateManager,
|
||||||
) : AuthRequestNotificationManager {
|
) : AuthRequestNotificationManager {
|
||||||
private val ioScope = CoroutineScope(dispatcherManager.io)
|
private val ioScope = CoroutineScope(dispatcherManager.io)
|
||||||
|
|
||||||
|
@ -40,6 +43,13 @@ class AuthRequestNotificationManagerImpl(
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
private fun handlePasswordlessRequestData(data: PasswordlessRequestData) {
|
private fun handlePasswordlessRequestData(data: PasswordlessRequestData) {
|
||||||
|
|
||||||
|
val pendingIntent = createContentIntent(data)
|
||||||
|
if (appStateManager.appForegroundStateFlow.value == AppForegroundState.FOREGROUNDED) {
|
||||||
|
pendingIntent.send()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val notificationManager = NotificationManagerCompat.from(context)
|
val notificationManager = NotificationManagerCompat.from(context)
|
||||||
// Construct the channel, calling this more than once is safe
|
// Construct the channel, calling this more than once is safe
|
||||||
notificationManager.createNotificationChannel(
|
notificationManager.createNotificationChannel(
|
||||||
|
@ -54,7 +64,7 @@ class AuthRequestNotificationManagerImpl(
|
||||||
if (!notificationManager.areNotificationsEnabled(NOTIFICATION_CHANNEL_ID)) return
|
if (!notificationManager.areNotificationsEnabled(NOTIFICATION_CHANNEL_ID)) return
|
||||||
// Create the notification
|
// Create the notification
|
||||||
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
||||||
.setContentIntent(createContentIntent(data))
|
.setContentIntent(pendingIntent)
|
||||||
.setContentTitle(context.getString(R.string.log_in_requested))
|
.setContentTitle(context.getString(R.string.log_in_requested))
|
||||||
.setContentText(
|
.setContentText(
|
||||||
authDiskSource
|
authDiskSource
|
||||||
|
|
|
@ -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.auth.manager.UserLogoutManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource
|
import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
|
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.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||||
import com.x8bit.bitwarden.data.tools.generator.datasource.disk.GeneratorDiskSource
|
import com.x8bit.bitwarden.data.tools.generator.datasource.disk.GeneratorDiskSource
|
||||||
|
@ -49,12 +50,14 @@ object AuthManagerModule {
|
||||||
authDiskSource: AuthDiskSource,
|
authDiskSource: AuthDiskSource,
|
||||||
pushManager: PushManager,
|
pushManager: PushManager,
|
||||||
dispatcherManager: DispatcherManager,
|
dispatcherManager: DispatcherManager,
|
||||||
|
appStateManager: AppStateManager,
|
||||||
): AuthRequestNotificationManager =
|
): AuthRequestNotificationManager =
|
||||||
AuthRequestNotificationManagerImpl(
|
AuthRequestNotificationManagerImpl(
|
||||||
context = context,
|
context = context,
|
||||||
authDiskSource = authDiskSource,
|
authDiskSource = authDiskSource,
|
||||||
pushManager = pushManager,
|
pushManager = pushManager,
|
||||||
dispatcherManager = dispatcherManager,
|
dispatcherManager = dispatcherManager,
|
||||||
|
appStateManager = appStateManager,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -10,16 +10,19 @@ import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
||||||
import com.x8bit.bitwarden.ui.platform.base.util.composableWithSlideTransitions
|
import com.x8bit.bitwarden.ui.platform.base.util.composableWithSlideTransitions
|
||||||
|
|
||||||
private const val FINGERPRINT: String = "fingerprint"
|
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_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].
|
* Class to retrieve login approval arguments from the [SavedStateHandle].
|
||||||
*/
|
*/
|
||||||
@OmitFromCoverage
|
@OmitFromCoverage
|
||||||
data class LoginApprovalArgs(val fingerprint: String?) {
|
data class LoginApprovalArgs(val fingerprint: String?, val requestId: String?) {
|
||||||
constructor(savedStateHandle: SavedStateHandle) : this(
|
constructor(savedStateHandle: SavedStateHandle) : this(
|
||||||
fingerprint = savedStateHandle.get<String>(FINGERPRINT),
|
fingerprint = savedStateHandle.get<String>(FINGERPRINT),
|
||||||
|
requestId = savedStateHandle.get<String>(REQUEST_ID),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +40,11 @@ fun NavGraphBuilder.loginApprovalDestination(
|
||||||
nullable = true
|
nullable = true
|
||||||
defaultValue = null
|
defaultValue = null
|
||||||
},
|
},
|
||||||
|
navArgument(REQUEST_ID) {
|
||||||
|
type = NavType.StringType
|
||||||
|
nullable = true
|
||||||
|
defaultValue = null
|
||||||
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
LoginApprovalScreen(
|
LoginApprovalScreen(
|
||||||
|
@ -50,7 +58,8 @@ fun NavGraphBuilder.loginApprovalDestination(
|
||||||
*/
|
*/
|
||||||
fun NavController.navigateToLoginApproval(
|
fun NavController.navigateToLoginApproval(
|
||||||
fingerprint: String?,
|
fingerprint: String?,
|
||||||
|
requestId: String? = null,
|
||||||
navOptions: NavOptions? = null,
|
navOptions: NavOptions? = null,
|
||||||
) {
|
) {
|
||||||
navigate("$LOGIN_APPROVAL_PREFIX?$FINGERPRINT=$fingerprint", navOptions)
|
navigate("$LOGIN_APPROVAL_PREFIX?$FINGERPRINT=$fingerprint&$REQUEST_ID=$requestId", navOptions)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class LoginApprovalViewModel @Inject constructor(
|
||||||
?: requireNotNull(LoginApprovalArgs(savedStateHandle).fingerprint),
|
?: requireNotNull(LoginApprovalArgs(savedStateHandle).fingerprint),
|
||||||
masterPasswordHash = null,
|
masterPasswordHash = null,
|
||||||
publicKey = "",
|
publicKey = "",
|
||||||
requestId = "",
|
requestId = LoginApprovalArgs(savedStateHandle).requestId.orEmpty(),
|
||||||
viewState = LoginApprovalState.ViewState.Loading,
|
viewState = LoginApprovalState.ViewState.Loading,
|
||||||
dialogState = null,
|
dialogState = null,
|
||||||
)
|
)
|
||||||
|
@ -86,11 +86,19 @@ class LoginApprovalViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?: run {
|
?: run {
|
||||||
authRepository
|
if (state.requestId.isNotEmpty()) {
|
||||||
.getAuthRequestByFingerprintFlow(state.fingerprint)
|
authRepository
|
||||||
.map { LoginApprovalAction.Internal.AuthRequestResultReceive(it) }
|
.getAuthRequestByIdFlow(state.requestId)
|
||||||
.onEach(::sendAction)
|
.map { LoginApprovalAction.Internal.AuthRequestResultReceive(it) }
|
||||||
.launchIn(viewModelScope)
|
.onEach(::sendAction)
|
||||||
|
.launchIn(viewModelScope)
|
||||||
|
} else {
|
||||||
|
authRepository
|
||||||
|
.getAuthRequestByIdFlow(state.fingerprint)
|
||||||
|
.map { LoginApprovalAction.Internal.AuthRequestResultReceive(it) }
|
||||||
|
.onEach(::sendAction)
|
||||||
|
.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue