diff options
| author | 2022-11-30 22:45:59 +0000 | |
|---|---|---|
| committer | 2022-11-30 22:45:59 +0000 | |
| commit | 3708b3783021e708ea1a328e9c5078c55d7cede6 (patch) | |
| tree | 5c38b4c1ee28e04808c0b23728518e7df2446362 | |
| parent | 8dadc7e871a6908b84c8d924f07b0f0e60fee529 (diff) | |
| parent | 3b7090ae7417f10188db3d3413611e579425c870 (diff) | |
Merge "Add the screen when there's no create option for the default provider but there's remoteEntry"
5 files changed, 130 insertions, 18 deletions
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml index 252ecf4a6005..8c9023c55eff 100644 --- a/packages/CredentialManager/res/values/strings.xml +++ b/packages/CredentialManager/res/values/strings.xml @@ -49,6 +49,8 @@ <string name="save_password_to_title">Save password to</string> <!-- This appears as the title of the modal bottom sheet for users to choose other available places the created other credential types can be saved to. [CHAR LIMIT=200] --> <string name="save_sign_in_to_title">Save sign-in to</string> + <!-- This appears as the title of the modal bottom sheet for users to choose to create a passkey on another device. [CHAR LIMIT=200] --> + <string name="create_passkey_in_other_device_title">Create a passkey in another device?</string> <!-- This appears as the title of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=200] --> <string name="use_provider_for_all_title">Use <xliff:g id="providerInfoDisplayName" example="Google Password Manager">%1$s</xliff:g> for all your sign-ins?</string> <!-- TODO: Check the wording here. --> diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt index 530f1c467a76..0cc11946ca85 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt @@ -44,6 +44,8 @@ import com.android.credentialmanager.createflow.ActiveEntry import com.android.credentialmanager.createflow.CreateCredentialUiState import com.android.credentialmanager.createflow.CreateScreenState import com.android.credentialmanager.createflow.EnabledProviderInfo +import com.android.credentialmanager.createflow.RemoteInfo +import com.android.credentialmanager.createflow.RequestDisplayInfo import com.android.credentialmanager.getflow.GetCredentialUiState import com.android.credentialmanager.getflow.GetScreenState import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest.Companion.toBundle @@ -142,25 +144,22 @@ class CredentialManagerRepo( val providerDisabledList = CreateFlowUtils.toDisabledProviderList( // Handle runtime cast error providerDisabledList as List<DisabledProviderData>, context) - var hasDefault = false - var defaultProvider: EnabledProviderInfo = providerEnabledList.first() + var defaultProvider: EnabledProviderInfo? = null + var remoteEntry: RemoteInfo? = null providerEnabledList.forEach{providerInfo -> providerInfo.createOptions = providerInfo.createOptions.sortedWith(compareBy { it.lastUsedTimeMillis }).reversed() - if (providerInfo.isDefault) {hasDefault = true; defaultProvider = providerInfo} } + if (providerInfo.isDefault) {defaultProvider = providerInfo} + if (providerInfo.remoteEntry != null) { + remoteEntry = providerInfo.remoteEntry!! + } + } return CreateCredentialUiState( enabledProviders = providerEnabledList, disabledProviders = providerDisabledList, - // TODO: Add the screen when defaultProvider has no createOption but - // there's remoteInfo under other providers - if (!hasDefault || defaultProvider.createOptions.isEmpty()) { - if (requestDisplayInfo.type == TYPE_PUBLIC_KEY_CREDENTIAL) - {CreateScreenState.PASSKEY_INTRO} else {CreateScreenState.PROVIDER_SELECTION} - } else {CreateScreenState.CREATION_OPTION_SELECTION}, + toCreateScreenState(requestDisplayInfo, defaultProvider, remoteEntry), requestDisplayInfo, false, - if (hasDefault) { - ActiveEntry(defaultProvider, defaultProvider.createOptions.first()) - } else null + toActiveEntry(defaultProvider, remoteEntry), ) } @@ -509,4 +508,38 @@ class CredentialManagerRepo( "tribank.us" ) } + + private fun toCreateScreenState( + requestDisplayInfo: RequestDisplayInfo, + defaultProvider: EnabledProviderInfo?, + remoteEntry: RemoteInfo?, + ): CreateScreenState { + return if ( + defaultProvider != null && defaultProvider.createOptions.isEmpty() && remoteEntry != null + ){ + CreateScreenState.EXTERNAL_ONLY_SELECTION + } else if (defaultProvider == null || defaultProvider.createOptions.isEmpty()) { + if (requestDisplayInfo.type == TYPE_PUBLIC_KEY_CREDENTIAL) { + CreateScreenState.PASSKEY_INTRO + } else { + CreateScreenState.PROVIDER_SELECTION + } + } else { + CreateScreenState.CREATION_OPTION_SELECTION + } + } + + private fun toActiveEntry( + defaultProvider: EnabledProviderInfo?, + remoteEntry: RemoteInfo?, + ): ActiveEntry? { + return if ( + defaultProvider != null && defaultProvider.createOptions.isNotEmpty() + ) { + ActiveEntry(defaultProvider, defaultProvider.createOptions.first()) + } else if ( + defaultProvider != null && defaultProvider.createOptions.isEmpty() && remoteEntry != null) { + ActiveEntry(defaultProvider, remoteEntry) + } else null + } } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt index fde32792e8f8..20b3d81c8b3c 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt @@ -60,7 +60,7 @@ fun CreateCredentialScreen( viewModel.onEntrySelected(it, providerActivityLauncher) } val confirmEntryCallback: () -> Unit = { - viewModel.onConfirmCreationSelected(providerActivityLauncher) + viewModel.onConfirmEntrySelected(providerActivityLauncher) } val state = rememberModalBottomSheetState( initialValue = ModalBottomSheetValue.Expanded, @@ -108,6 +108,13 @@ fun CreateCredentialScreen( providerInfo = uiState.activeEntry?.activeProvider!!, onDefaultOrNotSelected = viewModel::onDefaultOrNotSelected ) + CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard( + requestDisplayInfo = uiState.requestDisplayInfo, + activeRemoteEntry = uiState.activeEntry?.activeEntryInfo!!, + onOptionSelected = selectEntryCallback, + onConfirm = confirmEntryCallback, + onCancel = viewModel::onCancel, + ) } }, scrimColor = MaterialTheme.colorScheme.scrim, @@ -489,7 +496,7 @@ fun CreationSelectionCard( ) { PrimaryCreateOptionRow( requestDisplayInfo = requestDisplayInfo, - createOptionInfo = createOptionInfo, + entryInfo = createOptionInfo, onOptionSelected = onOptionSelected ) } @@ -562,16 +569,85 @@ fun CreationSelectionCard( @OptIn(ExperimentalMaterial3Api::class) @Composable +fun ExternalOnlySelectionCard( + requestDisplayInfo: RequestDisplayInfo, + activeRemoteEntry: EntryInfo, + onOptionSelected: (EntryInfo) -> Unit, + onConfirm: () -> Unit, + onCancel: () -> Unit, +) { + Card() { + Column() { + Icon( + painter = painterResource(R.drawable.ic_other_devices), + contentDescription = null, + tint = Color.Unspecified, + modifier = Modifier.align(alignment = Alignment.CenterHorizontally) + .padding(all = 24.dp).size(32.dp) + ) + Text( + text = stringResource(R.string.create_passkey_in_other_device_title), + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.padding(horizontal = 24.dp) + .align(alignment = Alignment.CenterHorizontally), + textAlign = TextAlign.Center, + ) + Divider( + thickness = 24.dp, + color = Color.Transparent + ) + Card( + shape = MaterialTheme.shapes.medium, + modifier = Modifier + .padding(horizontal = 24.dp) + .align(alignment = Alignment.CenterHorizontally), + ) { + PrimaryCreateOptionRow( + requestDisplayInfo = requestDisplayInfo, + entryInfo = activeRemoteEntry, + onOptionSelected = onOptionSelected + ) + } + Divider( + thickness = 24.dp, + color = Color.Transparent + ) + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp) + ) { + CancelButton( + stringResource(R.string.string_cancel), + onClick = onCancel + ) + ConfirmButton( + stringResource(R.string.string_continue), + onClick = onConfirm + ) + } + Divider( + thickness = 18.dp, + color = Color.Transparent, + modifier = Modifier.padding(bottom = 16.dp) + ) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable fun PrimaryCreateOptionRow( requestDisplayInfo: RequestDisplayInfo, - createOptionInfo: CreateOptionInfo, + entryInfo: EntryInfo, onOptionSelected: (EntryInfo) -> Unit ) { Entry( - onClick = {onOptionSelected(createOptionInfo)}, + onClick = {onOptionSelected(entryInfo)}, icon = { Icon( - bitmap = createOptionInfo.profileIcon.toBitmap().asImageBitmap(), + bitmap = if (entryInfo is CreateOptionInfo) { + entryInfo.profileIcon.toBitmap().asImageBitmap() + } else {requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()}, contentDescription = null, tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant, modifier = Modifier.padding(start = 18.dp).size(32.dp) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt index 0f685a104329..393cf7d9ae01 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt @@ -155,7 +155,7 @@ class CreateCredentialViewModel( } } - fun onConfirmCreationSelected( + fun onConfirmEntrySelected( launcher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult> ) { val selectedEntry = uiState.activeEntry?.activeEntryInfo diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt index 31d0365a821f..9ac524a4e6d9 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt @@ -95,4 +95,5 @@ enum class CreateScreenState { CREATION_OPTION_SELECTION, MORE_OPTIONS_SELECTION, MORE_OPTIONS_ROW_INTRO, + EXTERNAL_ONLY_SELECTION, } |