Loading packages/CredentialManager/res/values/strings.xml +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ <string name="passkeys">passkeys</string> <string name="passwords">passwords</string> <string name="sign_ins">sign-ins</string> <string name="other_password_manager">Other password manager</string> <string name="createOptionInfo_icon_description">CreateOptionInfo credentialType icon</string> <!-- Spoken content description of an element which will close the sheet when clicked. --> <string name="close_sheet">"Close sheet"</string> Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +33 −14 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.credentials.ui.Constants import android.credentials.ui.Entry import android.credentials.ui.CreateCredentialProviderData import android.credentials.ui.GetCredentialProviderData import android.credentials.ui.DisabledProviderData import android.credentials.ui.ProviderData import android.credentials.ui.RequestInfo import android.credentials.ui.BaseDialogResult Loading @@ -39,7 +40,7 @@ import android.os.ResultReceiver import com.android.credentialmanager.createflow.ActiveEntry import com.android.credentialmanager.createflow.CreatePasskeyUiState import com.android.credentialmanager.createflow.CreateScreenState import com.android.credentialmanager.createflow.ProviderInfo import com.android.credentialmanager.createflow.EnabledProviderInfo import com.android.credentialmanager.createflow.RequestDisplayInfo import com.android.credentialmanager.getflow.GetCredentialUiState import com.android.credentialmanager.getflow.GetScreenState Loading @@ -51,7 +52,8 @@ class CredentialManagerRepo( intent: Intent, ) { private val requestInfo: RequestInfo private val providerList: List<ProviderData> private val providerEnabledList: List<ProviderData> private val providerDisabledList: List<DisabledProviderData> // TODO: require non-null. val resultReceiver: ResultReceiver? Loading @@ -61,16 +63,16 @@ class CredentialManagerRepo( RequestInfo::class.java ) ?: testCreateRequestInfo() providerList = when (requestInfo.type) { providerEnabledList = when (requestInfo.type) { RequestInfo.TYPE_CREATE -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, CreateCredentialProviderData::class.java ) ?: testCreateCredentialProviderList() ) ?: testCreateCredentialEnabledProviderList() RequestInfo.TYPE_GET -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, GetCredentialProviderData::class.java DisabledProviderData::class.java ) ?: testGetCredentialProviderList() else -> { // TODO: fail gracefully Loading @@ -78,6 +80,12 @@ class CredentialManagerRepo( } } providerDisabledList = intent.extras?.getParcelableArrayList( ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, DisabledProviderData::class.java ) ?: testDisabledProviderList() resultReceiver = intent.getParcelableExtra( Constants.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java Loading @@ -103,25 +111,28 @@ class CredentialManagerRepo( } fun getCredentialInitialUiState(): GetCredentialUiState { val providerList = GetFlowUtils.toProviderList( val providerEnabledList = GetFlowUtils.toProviderList( // TODO: handle runtime cast error providerList as List<GetCredentialProviderData>, context) providerEnabledList as List<GetCredentialProviderData>, context) // TODO: covert from real requestInfo val requestDisplayInfo = com.android.credentialmanager.getflow.RequestDisplayInfo("tribank") return GetCredentialUiState( providerList, providerEnabledList, GetScreenState.PRIMARY_SELECTION, requestDisplayInfo, ) } fun createPasskeyInitialUiState(): CreatePasskeyUiState { val providerList = CreateFlowUtils.toProviderList( val providerEnabledList = CreateFlowUtils.toEnabledProviderList( // Handle runtime cast error providerList as List<CreateCredentialProviderData>, context) providerEnabledList as List<CreateCredentialProviderData>, context) val providerDisabledList = CreateFlowUtils.toDisabledProviderList( // Handle runtime cast error providerDisabledList as List<DisabledProviderData>, context) var hasDefault = false var defaultProvider: ProviderInfo = providerList.first() providerList.forEach{providerInfo -> providerInfo.createOptions = var defaultProvider: EnabledProviderInfo = providerEnabledList.first() providerEnabledList.forEach{providerInfo -> providerInfo.createOptions = providerInfo.createOptions.sortedWith(compareBy { it.lastUsedTimeMillis }).reversed() if (providerInfo.isDefault) {hasDefault = true; defaultProvider = providerInfo} } // TODO: covert from real requestInfo Loading @@ -131,7 +142,8 @@ class CredentialManagerRepo( TYPE_PUBLIC_KEY_CREDENTIAL, "tribank") return CreatePasskeyUiState( providers = providerList, enabledProviders = providerEnabledList, disabledProviders = providerDisabledList, if (hasDefault) {CreateScreenState.CREATION_OPTION_SELECTION} else {CreateScreenState.PASSKEY_INTRO}, requestDisplayInfo, Loading @@ -157,7 +169,7 @@ class CredentialManagerRepo( } // TODO: below are prototype functionalities. To be removed for productionization. private fun testCreateCredentialProviderList(): List<CreateCredentialProviderData> { private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> { return listOf( CreateCredentialProviderData .Builder("com.google/com.google.CredentialManagerService") Loading Loading @@ -185,6 +197,13 @@ class CredentialManagerRepo( ) } private fun testDisabledProviderList(): List<DisabledProviderData> { return listOf( DisabledProviderData("LastPass"), DisabledProviderData("Xyzinstalledbutdisabled"), ) } private fun testGetCredentialProviderList(): List<GetCredentialProviderData> { return listOf( GetCredentialProviderData.Builder("com.google/com.google.CredentialManagerService") Loading packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +18 −3 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context import android.credentials.ui.Entry import android.credentials.ui.GetCredentialProviderData import android.credentials.ui.CreateCredentialProviderData import android.credentials.ui.DisabledProviderData import com.android.credentialmanager.createflow.CreateOptionInfo import com.android.credentialmanager.getflow.ActionEntryInfo import com.android.credentialmanager.getflow.AuthenticationEntryInfo Loading Loading @@ -103,12 +104,12 @@ class GetFlowUtils { class CreateFlowUtils { companion object { fun toProviderList( fun toEnabledProviderList( providerDataList: List<CreateCredentialProviderData>, context: Context, ): List<com.android.credentialmanager.createflow.ProviderInfo> { ): List<com.android.credentialmanager.createflow.EnabledProviderInfo> { return providerDataList.map { com.android.credentialmanager.createflow.ProviderInfo( com.android.credentialmanager.createflow.EnabledProviderInfo( // TODO: replace to extract from the service data structure when available icon = context.getDrawable(R.drawable.ic_passkey)!!, name = it.providerFlattenedComponentName, Loading @@ -119,6 +120,20 @@ class CreateFlowUtils { } } fun toDisabledProviderList( providerDataList: List<DisabledProviderData>, context: Context, ): List<com.android.credentialmanager.createflow.DisabledProviderInfo> { return providerDataList.map { com.android.credentialmanager.createflow.DisabledProviderInfo( // TODO: replace to extract from the service data structure when available icon = context.getDrawable(R.drawable.ic_passkey)!!, name = it.providerFlattenedComponentName, displayName = it.providerFlattenedComponentName, ) } } private fun toCreationOptionInfoList( creationEntries: List<Entry>, context: Context, Loading packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt +15 −3 Original line number Diff line number Diff line Loading @@ -18,13 +18,25 @@ package com.android.credentialmanager.createflow import android.graphics.drawable.Drawable data class ProviderInfo( open class ProviderInfo( val icon: Drawable, val name: String, val displayName: String, ) class EnabledProviderInfo( icon: Drawable, name: String, displayName: String, var createOptions: List<CreateOptionInfo>, val isDefault: Boolean, ) ) : ProviderInfo(icon, name, displayName) class DisabledProviderInfo( icon: Drawable, name: String, displayName: String, ) : ProviderInfo(icon, name, displayName) open class EntryInfo ( val entryKey: String, Loading Loading @@ -55,7 +67,7 @@ data class RequestDisplayInfo( * user selects a different entry on the more option page. */ data class ActiveEntry ( val activeProvider: ProviderInfo, val activeProvider: EnabledProviderInfo, val activeEntryInfo: EntryInfo, ) Loading packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt +58 −14 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.Add import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment Loading Loading @@ -59,7 +60,7 @@ fun CreatePasskeyScreen( onCancel = viewModel::onCancel, ) CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard( providerList = uiState.providers, enabledProviderList = uiState.enabledProviders, onCancel = viewModel::onCancel, onProviderSelected = viewModel::onProviderSelected ) Loading @@ -70,14 +71,16 @@ fun CreatePasskeyScreen( onOptionSelected = viewModel::onPrimaryCreateOptionInfoSelected, onConfirm = viewModel::onPrimaryCreateOptionInfoSelected, onCancel = viewModel::onCancel, multiProvider = uiState.providers.size > 1, multiProvider = uiState.enabledProviders.size > 1, onMoreOptionsSelected = viewModel::onMoreOptionsSelected ) CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard( requestDisplayInfo = uiState.requestDisplayInfo, providerList = uiState.providers, enabledProviderList = uiState.enabledProviders, disabledProviderList = uiState.disabledProviders, onBackButtonSelected = viewModel::onBackButtonSelected, onOptionSelected = viewModel::onMoreOptionsRowSelected onOptionSelected = viewModel::onMoreOptionsRowSelected, onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected ) CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard( providerInfo = uiState.activeEntry?.activeProvider!!, Loading Loading @@ -153,7 +156,7 @@ fun ConfirmationCard( @OptIn(ExperimentalMaterial3Api::class) @Composable fun ProviderSelectionCard( providerList: List<ProviderInfo>, enabledProviderList: List<EnabledProviderInfo>, onProviderSelected: (String) -> Unit, onCancel: () -> Unit ) { Loading Loading @@ -182,7 +185,7 @@ fun ProviderSelectionCard( LazyColumn( verticalArrangement = Arrangement.spacedBy(2.dp) ) { providerList.forEach { enabledProviderList.forEach { item { ProviderRow(providerInfo = it, onProviderSelected = onProviderSelected) } Loading Loading @@ -212,9 +215,11 @@ fun ProviderSelectionCard( @Composable fun MoreOptionsSelectionCard( requestDisplayInfo: RequestDisplayInfo, providerList: List<ProviderInfo>, enabledProviderList: List<EnabledProviderInfo>, disabledProviderList: List<DisabledProviderInfo>, onBackButtonSelected: () -> Unit, onOptionSelected: (ActiveEntry) -> Unit onOptionSelected: (ActiveEntry) -> Unit, onDisabledPasswordManagerSelected: () -> Unit, ) { Card() { Column() { Loading Loading @@ -250,18 +255,24 @@ fun MoreOptionsSelectionCard( LazyColumn( verticalArrangement = Arrangement.spacedBy(2.dp) ) { providerList.forEach { providerInfo -> providerInfo.createOptions.forEach { createOptionInfo -> enabledProviderList.forEach { enabledProviderInfo -> enabledProviderInfo.createOptions.forEach { createOptionInfo -> item { MoreOptionsInfoRow( providerInfo = providerInfo, providerInfo = enabledProviderInfo, createOptionInfo = createOptionInfo, onOptionSelected = { onOptionSelected(ActiveEntry(providerInfo, createOptionInfo)) onOptionSelected(ActiveEntry(enabledProviderInfo, createOptionInfo)) }) } } } item { MoreOptionsDisabledProvidersRow( disabledProviders = disabledProviderList, onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected, ) } } } Divider( Loading @@ -276,7 +287,7 @@ fun MoreOptionsSelectionCard( @OptIn(ExperimentalMaterial3Api::class) @Composable fun MoreOptionsRowIntroCard( providerInfo: ProviderInfo, providerInfo: EnabledProviderInfo, onDefaultOrNotSelected: () -> Unit, ) { Card() { Loading Loading @@ -483,7 +494,7 @@ fun PrimaryCreateOptionRow( @OptIn(ExperimentalMaterial3Api::class) @Composable fun MoreOptionsInfoRow( providerInfo: ProviderInfo, providerInfo: EnabledProviderInfo, createOptionInfo: CreateOptionInfo, onOptionSelected: () -> Unit ) { Loading Loading @@ -547,3 +558,36 @@ fun MoreOptionsInfoRow( } ) } @OptIn(ExperimentalMaterial3Api::class) @Composable fun MoreOptionsDisabledProvidersRow( disabledProviders: List<ProviderInfo>, onDisabledPasswordManagerSelected: () -> Unit, ) { SuggestionChip( modifier = Modifier.fillMaxWidth(), onClick = onDisabledPasswordManagerSelected, icon = { Icon( Icons.Filled.Add, contentDescription = null ) }, shape = MaterialTheme.shapes.large, label = { Column() { Text( text = stringResource(R.string.other_password_manager), style = MaterialTheme.typography.titleLarge, modifier = Modifier.padding(top = 16.dp) ) Text( text = disabledProviders.joinToString(separator = ", "){ it.displayName }, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(bottom = 16.dp) ) } } ) } No newline at end of file Loading
packages/CredentialManager/res/values/strings.xml +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ <string name="passkeys">passkeys</string> <string name="passwords">passwords</string> <string name="sign_ins">sign-ins</string> <string name="other_password_manager">Other password manager</string> <string name="createOptionInfo_icon_description">CreateOptionInfo credentialType icon</string> <!-- Spoken content description of an element which will close the sheet when clicked. --> <string name="close_sheet">"Close sheet"</string> Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +33 −14 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.credentials.ui.Constants import android.credentials.ui.Entry import android.credentials.ui.CreateCredentialProviderData import android.credentials.ui.GetCredentialProviderData import android.credentials.ui.DisabledProviderData import android.credentials.ui.ProviderData import android.credentials.ui.RequestInfo import android.credentials.ui.BaseDialogResult Loading @@ -39,7 +40,7 @@ import android.os.ResultReceiver import com.android.credentialmanager.createflow.ActiveEntry import com.android.credentialmanager.createflow.CreatePasskeyUiState import com.android.credentialmanager.createflow.CreateScreenState import com.android.credentialmanager.createflow.ProviderInfo import com.android.credentialmanager.createflow.EnabledProviderInfo import com.android.credentialmanager.createflow.RequestDisplayInfo import com.android.credentialmanager.getflow.GetCredentialUiState import com.android.credentialmanager.getflow.GetScreenState Loading @@ -51,7 +52,8 @@ class CredentialManagerRepo( intent: Intent, ) { private val requestInfo: RequestInfo private val providerList: List<ProviderData> private val providerEnabledList: List<ProviderData> private val providerDisabledList: List<DisabledProviderData> // TODO: require non-null. val resultReceiver: ResultReceiver? Loading @@ -61,16 +63,16 @@ class CredentialManagerRepo( RequestInfo::class.java ) ?: testCreateRequestInfo() providerList = when (requestInfo.type) { providerEnabledList = when (requestInfo.type) { RequestInfo.TYPE_CREATE -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, CreateCredentialProviderData::class.java ) ?: testCreateCredentialProviderList() ) ?: testCreateCredentialEnabledProviderList() RequestInfo.TYPE_GET -> intent.extras?.getParcelableArrayList( ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, GetCredentialProviderData::class.java DisabledProviderData::class.java ) ?: testGetCredentialProviderList() else -> { // TODO: fail gracefully Loading @@ -78,6 +80,12 @@ class CredentialManagerRepo( } } providerDisabledList = intent.extras?.getParcelableArrayList( ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, DisabledProviderData::class.java ) ?: testDisabledProviderList() resultReceiver = intent.getParcelableExtra( Constants.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java Loading @@ -103,25 +111,28 @@ class CredentialManagerRepo( } fun getCredentialInitialUiState(): GetCredentialUiState { val providerList = GetFlowUtils.toProviderList( val providerEnabledList = GetFlowUtils.toProviderList( // TODO: handle runtime cast error providerList as List<GetCredentialProviderData>, context) providerEnabledList as List<GetCredentialProviderData>, context) // TODO: covert from real requestInfo val requestDisplayInfo = com.android.credentialmanager.getflow.RequestDisplayInfo("tribank") return GetCredentialUiState( providerList, providerEnabledList, GetScreenState.PRIMARY_SELECTION, requestDisplayInfo, ) } fun createPasskeyInitialUiState(): CreatePasskeyUiState { val providerList = CreateFlowUtils.toProviderList( val providerEnabledList = CreateFlowUtils.toEnabledProviderList( // Handle runtime cast error providerList as List<CreateCredentialProviderData>, context) providerEnabledList as List<CreateCredentialProviderData>, context) val providerDisabledList = CreateFlowUtils.toDisabledProviderList( // Handle runtime cast error providerDisabledList as List<DisabledProviderData>, context) var hasDefault = false var defaultProvider: ProviderInfo = providerList.first() providerList.forEach{providerInfo -> providerInfo.createOptions = var defaultProvider: EnabledProviderInfo = providerEnabledList.first() providerEnabledList.forEach{providerInfo -> providerInfo.createOptions = providerInfo.createOptions.sortedWith(compareBy { it.lastUsedTimeMillis }).reversed() if (providerInfo.isDefault) {hasDefault = true; defaultProvider = providerInfo} } // TODO: covert from real requestInfo Loading @@ -131,7 +142,8 @@ class CredentialManagerRepo( TYPE_PUBLIC_KEY_CREDENTIAL, "tribank") return CreatePasskeyUiState( providers = providerList, enabledProviders = providerEnabledList, disabledProviders = providerDisabledList, if (hasDefault) {CreateScreenState.CREATION_OPTION_SELECTION} else {CreateScreenState.PASSKEY_INTRO}, requestDisplayInfo, Loading @@ -157,7 +169,7 @@ class CredentialManagerRepo( } // TODO: below are prototype functionalities. To be removed for productionization. private fun testCreateCredentialProviderList(): List<CreateCredentialProviderData> { private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> { return listOf( CreateCredentialProviderData .Builder("com.google/com.google.CredentialManagerService") Loading Loading @@ -185,6 +197,13 @@ class CredentialManagerRepo( ) } private fun testDisabledProviderList(): List<DisabledProviderData> { return listOf( DisabledProviderData("LastPass"), DisabledProviderData("Xyzinstalledbutdisabled"), ) } private fun testGetCredentialProviderList(): List<GetCredentialProviderData> { return listOf( GetCredentialProviderData.Builder("com.google/com.google.CredentialManagerService") Loading
packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +18 −3 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context import android.credentials.ui.Entry import android.credentials.ui.GetCredentialProviderData import android.credentials.ui.CreateCredentialProviderData import android.credentials.ui.DisabledProviderData import com.android.credentialmanager.createflow.CreateOptionInfo import com.android.credentialmanager.getflow.ActionEntryInfo import com.android.credentialmanager.getflow.AuthenticationEntryInfo Loading Loading @@ -103,12 +104,12 @@ class GetFlowUtils { class CreateFlowUtils { companion object { fun toProviderList( fun toEnabledProviderList( providerDataList: List<CreateCredentialProviderData>, context: Context, ): List<com.android.credentialmanager.createflow.ProviderInfo> { ): List<com.android.credentialmanager.createflow.EnabledProviderInfo> { return providerDataList.map { com.android.credentialmanager.createflow.ProviderInfo( com.android.credentialmanager.createflow.EnabledProviderInfo( // TODO: replace to extract from the service data structure when available icon = context.getDrawable(R.drawable.ic_passkey)!!, name = it.providerFlattenedComponentName, Loading @@ -119,6 +120,20 @@ class CreateFlowUtils { } } fun toDisabledProviderList( providerDataList: List<DisabledProviderData>, context: Context, ): List<com.android.credentialmanager.createflow.DisabledProviderInfo> { return providerDataList.map { com.android.credentialmanager.createflow.DisabledProviderInfo( // TODO: replace to extract from the service data structure when available icon = context.getDrawable(R.drawable.ic_passkey)!!, name = it.providerFlattenedComponentName, displayName = it.providerFlattenedComponentName, ) } } private fun toCreationOptionInfoList( creationEntries: List<Entry>, context: Context, Loading
packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt +15 −3 Original line number Diff line number Diff line Loading @@ -18,13 +18,25 @@ package com.android.credentialmanager.createflow import android.graphics.drawable.Drawable data class ProviderInfo( open class ProviderInfo( val icon: Drawable, val name: String, val displayName: String, ) class EnabledProviderInfo( icon: Drawable, name: String, displayName: String, var createOptions: List<CreateOptionInfo>, val isDefault: Boolean, ) ) : ProviderInfo(icon, name, displayName) class DisabledProviderInfo( icon: Drawable, name: String, displayName: String, ) : ProviderInfo(icon, name, displayName) open class EntryInfo ( val entryKey: String, Loading Loading @@ -55,7 +67,7 @@ data class RequestDisplayInfo( * user selects a different entry on the more option page. */ data class ActiveEntry ( val activeProvider: ProviderInfo, val activeProvider: EnabledProviderInfo, val activeEntryInfo: EntryInfo, ) Loading
packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt +58 −14 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.Add import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment Loading Loading @@ -59,7 +60,7 @@ fun CreatePasskeyScreen( onCancel = viewModel::onCancel, ) CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard( providerList = uiState.providers, enabledProviderList = uiState.enabledProviders, onCancel = viewModel::onCancel, onProviderSelected = viewModel::onProviderSelected ) Loading @@ -70,14 +71,16 @@ fun CreatePasskeyScreen( onOptionSelected = viewModel::onPrimaryCreateOptionInfoSelected, onConfirm = viewModel::onPrimaryCreateOptionInfoSelected, onCancel = viewModel::onCancel, multiProvider = uiState.providers.size > 1, multiProvider = uiState.enabledProviders.size > 1, onMoreOptionsSelected = viewModel::onMoreOptionsSelected ) CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard( requestDisplayInfo = uiState.requestDisplayInfo, providerList = uiState.providers, enabledProviderList = uiState.enabledProviders, disabledProviderList = uiState.disabledProviders, onBackButtonSelected = viewModel::onBackButtonSelected, onOptionSelected = viewModel::onMoreOptionsRowSelected onOptionSelected = viewModel::onMoreOptionsRowSelected, onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected ) CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard( providerInfo = uiState.activeEntry?.activeProvider!!, Loading Loading @@ -153,7 +156,7 @@ fun ConfirmationCard( @OptIn(ExperimentalMaterial3Api::class) @Composable fun ProviderSelectionCard( providerList: List<ProviderInfo>, enabledProviderList: List<EnabledProviderInfo>, onProviderSelected: (String) -> Unit, onCancel: () -> Unit ) { Loading Loading @@ -182,7 +185,7 @@ fun ProviderSelectionCard( LazyColumn( verticalArrangement = Arrangement.spacedBy(2.dp) ) { providerList.forEach { enabledProviderList.forEach { item { ProviderRow(providerInfo = it, onProviderSelected = onProviderSelected) } Loading Loading @@ -212,9 +215,11 @@ fun ProviderSelectionCard( @Composable fun MoreOptionsSelectionCard( requestDisplayInfo: RequestDisplayInfo, providerList: List<ProviderInfo>, enabledProviderList: List<EnabledProviderInfo>, disabledProviderList: List<DisabledProviderInfo>, onBackButtonSelected: () -> Unit, onOptionSelected: (ActiveEntry) -> Unit onOptionSelected: (ActiveEntry) -> Unit, onDisabledPasswordManagerSelected: () -> Unit, ) { Card() { Column() { Loading Loading @@ -250,18 +255,24 @@ fun MoreOptionsSelectionCard( LazyColumn( verticalArrangement = Arrangement.spacedBy(2.dp) ) { providerList.forEach { providerInfo -> providerInfo.createOptions.forEach { createOptionInfo -> enabledProviderList.forEach { enabledProviderInfo -> enabledProviderInfo.createOptions.forEach { createOptionInfo -> item { MoreOptionsInfoRow( providerInfo = providerInfo, providerInfo = enabledProviderInfo, createOptionInfo = createOptionInfo, onOptionSelected = { onOptionSelected(ActiveEntry(providerInfo, createOptionInfo)) onOptionSelected(ActiveEntry(enabledProviderInfo, createOptionInfo)) }) } } } item { MoreOptionsDisabledProvidersRow( disabledProviders = disabledProviderList, onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected, ) } } } Divider( Loading @@ -276,7 +287,7 @@ fun MoreOptionsSelectionCard( @OptIn(ExperimentalMaterial3Api::class) @Composable fun MoreOptionsRowIntroCard( providerInfo: ProviderInfo, providerInfo: EnabledProviderInfo, onDefaultOrNotSelected: () -> Unit, ) { Card() { Loading Loading @@ -483,7 +494,7 @@ fun PrimaryCreateOptionRow( @OptIn(ExperimentalMaterial3Api::class) @Composable fun MoreOptionsInfoRow( providerInfo: ProviderInfo, providerInfo: EnabledProviderInfo, createOptionInfo: CreateOptionInfo, onOptionSelected: () -> Unit ) { Loading Loading @@ -547,3 +558,36 @@ fun MoreOptionsInfoRow( } ) } @OptIn(ExperimentalMaterial3Api::class) @Composable fun MoreOptionsDisabledProvidersRow( disabledProviders: List<ProviderInfo>, onDisabledPasswordManagerSelected: () -> Unit, ) { SuggestionChip( modifier = Modifier.fillMaxWidth(), onClick = onDisabledPasswordManagerSelected, icon = { Icon( Icons.Filled.Add, contentDescription = null ) }, shape = MaterialTheme.shapes.large, label = { Column() { Text( text = stringResource(R.string.other_password_manager), style = MaterialTheme.typography.titleLarge, modifier = Modifier.padding(top = 16.dp) ) Text( text = disabledProviders.joinToString(separator = ", "){ it.displayName }, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(bottom = 16.dp) ) } } ) } No newline at end of file