diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt index cdff2d4295b03..686415f9d3e94 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt @@ -16,7 +16,9 @@ package com.android.credentialmanager +import android.content.Intent import android.os.Bundle +import android.provider.Settings import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult @@ -26,7 +28,7 @@ import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.lifecycle.Observer +import androidx.lifecycle.lifecycleScope import androidx.lifecycle.viewmodel.compose.viewModel import com.android.credentialmanager.common.DialogType import com.android.credentialmanager.common.DialogResult @@ -37,6 +39,7 @@ import com.android.credentialmanager.createflow.CreateCredentialViewModel import com.android.credentialmanager.getflow.GetCredentialScreen import com.android.credentialmanager.getflow.GetCredentialViewModel import com.android.credentialmanager.ui.theme.CredentialSelectorTheme +import kotlinx.coroutines.launch @ExperimentalMaterialApi class CredentialSelectorActivity : ComponentActivity() { @@ -64,10 +67,11 @@ class CredentialSelectorActivity : ComponentActivity() { when (dialogType) { DialogType.CREATE_PASSKEY -> { val viewModel: CreateCredentialViewModel = viewModel() - viewModel.observeDialogResult().observe( - this@CredentialSelectorActivity, - onCancel - ) + lifecycleScope.launch { + viewModel.observeDialogResult().collect{ dialogResult -> + onCancel(dialogResult) + } + } providerActivityResult.value?.let { viewModel.onProviderActivityResult(it) providerActivityResult.value = null @@ -76,10 +80,11 @@ class CredentialSelectorActivity : ComponentActivity() { } DialogType.GET_CREDENTIALS -> { val viewModel: GetCredentialViewModel = viewModel() - viewModel.observeDialogResult().observe( - this@CredentialSelectorActivity, - onCancel - ) + lifecycleScope.launch { + viewModel.observeDialogResult().collect{ dialogResult -> + onCancel(dialogResult) + } + } providerActivityResult.value?.let { viewModel.onProviderActivityResult(it) providerActivityResult.value = null @@ -93,8 +98,12 @@ class CredentialSelectorActivity : ComponentActivity() { } } - private val onCancel = Observer { - if (it.resultState == ResultState.COMPLETE || it.resultState == ResultState.CANCELED) { + private fun onCancel(dialogResut: DialogResult) { + if (dialogResut.resultState == ResultState + .COMPLETE || dialogResut.resultState == ResultState.NORMAL_CANCELED) { + this@CredentialSelectorActivity.finish() + } else if (dialogResut.resultState == ResultState.LAUNCH_SETTING_CANCELED) { + this@CredentialSelectorActivity.startActivity(Intent(Settings.ACTION_SYNC_SETTINGS)) this@CredentialSelectorActivity.finish() } } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt index b75166347c56b..743f49b18c3f4 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt @@ -18,7 +18,8 @@ package com.android.credentialmanager.common enum class ResultState { COMPLETE, - CANCELED, + NORMAL_CANCELED, + LAUNCH_SETTING_CANCELED } data class DialogResult( diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt index ea305a4e50669..0c11e91da7717 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt @@ -78,8 +78,7 @@ fun CreateCredentialScreen( disabledProviderList = uiState.disabledProviders, sortedCreateOptionsPairs = uiState.sortedCreateOptionsPairs, onOptionSelected = viewModel::onEntrySelectedFromFirstUseScreen, - onDisabledPasswordManagerSelected = - viewModel::onDisabledPasswordManagerSelected, + onDisabledProvidersSelected = viewModel::onDisabledProvidersSelected, onMoreOptionsSelected = viewModel::onMoreOptionsSelectedOnProviderSelection, ) CreateScreenState.CREATION_OPTION_SELECTION -> CreationSelectionCard( @@ -103,8 +102,7 @@ fun CreateCredentialScreen( onBackCreationSelectionButtonSelected = viewModel::onBackCreationSelectionButtonSelected, onOptionSelected = viewModel::onEntrySelectedFromMoreOptionScreen, - onDisabledPasswordManagerSelected = - viewModel::onDisabledPasswordManagerSelected, + onDisabledProvidersSelected = viewModel::onDisabledProvidersSelected, onRemoteEntrySelected = viewModel::onEntrySelected, ) CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard( @@ -250,7 +248,7 @@ fun ProviderSelectionCard( disabledProviderList: List?, sortedCreateOptionsPairs: List>, onOptionSelected: (ActiveEntry) -> Unit, - onDisabledPasswordManagerSelected: () -> Unit, + onDisabledProvidersSelected: () -> Unit, onMoreOptionsSelected: () -> Unit, ) { ContainerCard() { @@ -318,8 +316,8 @@ fun ProviderSelectionCard( item { MoreOptionsDisabledProvidersRow( disabledProviders = disabledProviderList, - onDisabledPasswordManagerSelected = - onDisabledPasswordManagerSelected, + onDisabledProvidersSelected = + onDisabledProvidersSelected, ) } } @@ -363,7 +361,7 @@ fun MoreOptionsSelectionCard( onBackProviderSelectionButtonSelected: () -> Unit, onBackCreationSelectionButtonSelected: () -> Unit, onOptionSelected: (ActiveEntry) -> Unit, - onDisabledPasswordManagerSelected: () -> Unit, + onDisabledProvidersSelected: () -> Unit, onRemoteEntrySelected: (EntryInfo) -> Unit, ) { ContainerCard() { @@ -436,8 +434,8 @@ fun MoreOptionsSelectionCard( item { MoreOptionsDisabledProvidersRow( disabledProviders = disabledProviderList, - onDisabledPasswordManagerSelected = - onDisabledPasswordManagerSelected, + onDisabledProvidersSelected = + onDisabledProvidersSelected, ) } } @@ -891,11 +889,11 @@ fun MoreOptionsInfoRow( @Composable fun MoreOptionsDisabledProvidersRow( disabledProviders: List?, - onDisabledPasswordManagerSelected: () -> Unit, + onDisabledProvidersSelected: () -> Unit, ) { if (disabledProviders != null && disabledProviders.isNotEmpty()) { Entry( - onClick = onDisabledPasswordManagerSelected, + onClick = onDisabledProvidersSelected, icon = { Icon( Icons.Filled.Add, diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt index 55e14a9ccb6ea..aadbbc6deb6c4 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt @@ -24,8 +24,6 @@ import androidx.activity.result.IntentSenderRequest import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.android.credentialmanager.CreateFlowUtils import com.android.credentialmanager.CredentialManagerRepo @@ -33,6 +31,9 @@ import com.android.credentialmanager.UserConfigRepo import com.android.credentialmanager.common.DialogResult import com.android.credentialmanager.common.ProviderActivityResult import com.android.credentialmanager.common.ResultState +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow data class CreateCredentialUiState( val enabledProviders: List, @@ -75,11 +76,11 @@ class CreateCredentialViewModel( isPasskeyFirstUse)) private set - val dialogResult: MutableLiveData by lazy { - MutableLiveData() - } + val dialogResult: MutableSharedFlow = + MutableSharedFlow(replay = 0, extraBufferCapacity = 1, + onBufferOverflow = BufferOverflow.DROP_OLDEST) - fun observeDialogResult(): LiveData { + fun observeDialogResult(): SharedFlow { return dialogResult } @@ -138,13 +139,14 @@ class CreateCredentialViewModel( onDefaultChanged(providerId) } - fun onDisabledPasswordManagerSelected() { - // TODO: Complete this function + fun onDisabledProvidersSelected() { + CredentialManagerRepo.getInstance().onCancel() + dialogResult.tryEmit(DialogResult(ResultState.LAUNCH_SETTING_CANCELED)) } fun onCancel() { CredentialManagerRepo.getInstance().onCancel() - dialogResult.value = DialogResult(ResultState.CANCELED) + dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED)) } fun onChangeDefaultSelected() { @@ -190,9 +192,7 @@ class CreateCredentialViewModel( entryKey, entrySubkey ) - dialogResult.value = DialogResult( - ResultState.COMPLETE, - ) + dialogResult.tryEmit(DialogResult(ResultState.COMPLETE)) } } @@ -219,9 +219,7 @@ class CreateCredentialViewModel( } else { Log.w("Account Selector", "Illegal state: confirm is pressed but activeEntry isn't set.") - dialogResult.value = DialogResult( - ResultState.COMPLETE, - ) + dialogResult.tryEmit(DialogResult(ResultState.COMPLETE)) } } @@ -250,9 +248,7 @@ class CreateCredentialViewModel( Log.w("Account Selector", "Illegal state: received a provider result but found no matching entry.") } - dialogResult.value = DialogResult( - ResultState.COMPLETE, - ) + dialogResult.tryEmit(DialogResult(ResultState.COMPLETE)) } } } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt index 294e4689b977b..af59a0a39c721 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt @@ -24,8 +24,6 @@ import androidx.activity.result.IntentSenderRequest import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.android.credentialmanager.CredentialManagerRepo import com.android.credentialmanager.common.DialogResult @@ -33,6 +31,9 @@ import com.android.credentialmanager.common.ProviderActivityResult import com.android.credentialmanager.common.ResultState import com.android.credentialmanager.jetpack.developer.PublicKeyCredential import com.android.internal.util.Preconditions +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow data class GetCredentialUiState( val providerInfoList: List, @@ -52,11 +53,11 @@ class GetCredentialViewModel( var uiState by mutableStateOf(credManRepo.getCredentialInitialUiState()) private set - val dialogResult: MutableLiveData by lazy { - MutableLiveData() - } + val dialogResult: MutableSharedFlow = + MutableSharedFlow(replay = 0, extraBufferCapacity = 1, + onBufferOverflow = BufferOverflow.DROP_OLDEST) - fun observeDialogResult(): LiveData { + fun observeDialogResult(): SharedFlow { return dialogResult } @@ -72,7 +73,7 @@ class GetCredentialViewModel( CredentialManagerRepo.getInstance().onOptionSelected( entry.providerId, entry.entryKey, entry.entrySubkey, ) - dialogResult.value = DialogResult(ResultState.COMPLETE) + dialogResult.tryEmit(DialogResult(ResultState.COMPLETE)) } } @@ -117,7 +118,7 @@ class GetCredentialViewModel( Log.w("Account Selector", "Illegal state: received a provider result but found no matching entry.") } - dialogResult.value = DialogResult(ResultState.COMPLETE) + dialogResult.tryEmit(DialogResult(ResultState.COMPLETE)) } } @@ -144,7 +145,7 @@ class GetCredentialViewModel( fun onCancel() { CredentialManagerRepo.getInstance().onCancel() - dialogResult.value = DialogResult(ResultState.CANCELED) + dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED)) } }