Loading packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +12 −8 Original line number Original line Diff line number Diff line Loading @@ -214,17 +214,21 @@ class CredentialManagerRepo( GetCredentialProviderData.Builder("io.enpass.app") GetCredentialProviderData.Builder("io.enpass.app") .setCredentialEntries( .setCredentialEntries( listOf<Entry>( listOf<Entry>( newGetEntry( "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.family@outlook.com", null, 3L ), newGetEntry( newGetEntry( "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "elisa.bakery@gmail.com", "Elisa Beckett", 300L "elisa.bakery@gmail.com", "Elisa Beckett", 0L ), ), newGetEntry( newGetEntry( "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password", "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.bakery@gmail.com", null, 300L "elisa.bakery@gmail.com", null, 10L ), ), newGetEntry( newGetEntry( "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password", "key1", "subkey-3", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "elisa.family@outlook.com", null, 100L "elisa.family@outlook.com", "Elisa Beckett", 1L ), ), ) ) ).setAuthenticationEntry( ).setAuthenticationEntry( Loading @@ -247,12 +251,12 @@ class CredentialManagerRepo( .setCredentialEntries( .setCredentialEntries( listOf<Entry>( listOf<Entry>( newGetEntry( newGetEntry( "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password", "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.family@outlook.com", null, 600L "elisa.family@outlook.com", null, 4L ), ), newGetEntry( newGetEntry( "key1", "subkey-2", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.family@outlook.com", null, 100L "elisa.work@outlook.com", null, 11L ), ), ) ) ).setAuthenticationEntry( ).setAuthenticationEntry( Loading packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt +49 −17 Original line number Original line Diff line number Diff line Loading @@ -146,13 +146,19 @@ fun PrimarySelectionCard( textAlign = TextAlign.Center, textAlign = TextAlign.Center, style = MaterialTheme.typography.headlineSmall, style = MaterialTheme.typography.headlineSmall, text = stringResource( text = stringResource( if (sortedUserNameToCredentialEntryList.size == 1) { if (sortedUserNameToCredentialEntryList if (sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList .size == 1 && authenticationEntryList.isEmpty() .first().credentialType ) { if (sortedUserNameToCredentialEntryList.first() .sortedCredentialEntryList.first().credentialType == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ) ) R.string.get_dialog_title_use_passkey_for R.string.get_dialog_title_use_passkey_for else R.string.get_dialog_title_use_sign_in_for else R.string.get_dialog_title_use_sign_in_for } else if ( sortedUserNameToCredentialEntryList .isEmpty() && authenticationEntryList.size == 1 ) { R.string.get_dialog_title_use_sign_in_for } else R.string.get_dialog_title_choose_sign_in_for, } else R.string.get_dialog_title_choose_sign_in_for, requestDisplayInfo.appDomainName requestDisplayInfo.appDomainName ), ), Loading @@ -164,9 +170,14 @@ fun PrimarySelectionCard( .padding(horizontal = 24.dp) .padding(horizontal = 24.dp) .align(alignment = Alignment.CenterHorizontally) .align(alignment = Alignment.CenterHorizontally) ) { ) { val usernameForCredentialSize = sortedUserNameToCredentialEntryList .size val authenticationEntrySize = authenticationEntryList.size LazyColumn( LazyColumn( verticalArrangement = Arrangement.spacedBy(2.dp) verticalArrangement = Arrangement.spacedBy(2.dp) ) { ) { // Show max 4 entries in this primary page if (usernameForCredentialSize + authenticationEntrySize <= 4) { items(sortedUserNameToCredentialEntryList) { items(sortedUserNameToCredentialEntryList) { CredentialEntryRow( CredentialEntryRow( credentialEntryInfo = it.sortedCredentialEntryList.first(), credentialEntryInfo = it.sortedCredentialEntryList.first(), Loading @@ -179,6 +190,27 @@ fun PrimarySelectionCard( onEntrySelected = onEntrySelected, onEntrySelected = onEntrySelected, ) ) } } } else if (usernameForCredentialSize < 4) { items(sortedUserNameToCredentialEntryList) { CredentialEntryRow( credentialEntryInfo = it.sortedCredentialEntryList.first(), onEntrySelected = onEntrySelected, ) } items(authenticationEntryList.take(4 - usernameForCredentialSize)) { AuthenticationEntryRow( authenticationEntryInfo = it, onEntrySelected = onEntrySelected, ) } } else { items(sortedUserNameToCredentialEntryList.take(4)) { CredentialEntryRow( credentialEntryInfo = it.sortedCredentialEntryList.first(), onEntrySelected = onEntrySelected, ) } } } } } } Divider( Divider( Loading Loading @@ -257,7 +289,7 @@ fun AllSignInOptionCard( ) ) } } // Locked password manager // Locked password manager if (!authenticationEntryList.isEmpty()) { if (authenticationEntryList.isNotEmpty()) { item { item { LockedCredentials( LockedCredentials( authenticationEntryList = authenticationEntryList, authenticationEntryList = authenticationEntryList, Loading packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt +3 −3 Original line number Original line Diff line number Diff line Loading @@ -182,7 +182,7 @@ private fun toProviderDisplayInfo( Preconditions.checkState(remoteEntryList.size <= 1) Preconditions.checkState(remoteEntryList.size <= 1) // Compose sortedUserNameToCredentialEntryList // Compose sortedUserNameToCredentialEntryList val comparator = CredentialEntryInfoComparator() val comparator = CredentialEntryInfoComparatorByTypeThenTimestamp() // Sort per username // Sort per username userNameToCredentialEntryMap.values.forEach { userNameToCredentialEntryMap.values.forEach { it.sortWith(comparator) it.sortWith(comparator) Loading @@ -191,7 +191,7 @@ private fun toProviderDisplayInfo( val sortedUserNameToCredentialEntryList = userNameToCredentialEntryMap.map { val sortedUserNameToCredentialEntryList = userNameToCredentialEntryMap.map { PerUserNameCredentialEntryList(it.key, it.value) PerUserNameCredentialEntryList(it.key, it.value) }.sortedWith( }.sortedWith( compareBy(comparator) { it.sortedCredentialEntryList.first() } compareByDescending{ it.sortedCredentialEntryList.first().lastUsedTimeMillis } ) ) return ProviderDisplayInfo( return ProviderDisplayInfo( Loading Loading @@ -219,7 +219,7 @@ private fun toGetScreenState( GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION } } internal class CredentialEntryInfoComparator : Comparator<CredentialEntryInfo> { internal class CredentialEntryInfoComparatorByTypeThenTimestamp : Comparator<CredentialEntryInfo> { override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int { override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int { // First prefer passkey type for its security benefits // First prefer passkey type for its security benefits if (p0.credentialType != p1.credentialType) { if (p0.credentialType != p1.credentialType) { Loading Loading
packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +12 −8 Original line number Original line Diff line number Diff line Loading @@ -214,17 +214,21 @@ class CredentialManagerRepo( GetCredentialProviderData.Builder("io.enpass.app") GetCredentialProviderData.Builder("io.enpass.app") .setCredentialEntries( .setCredentialEntries( listOf<Entry>( listOf<Entry>( newGetEntry( "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.family@outlook.com", null, 3L ), newGetEntry( newGetEntry( "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "elisa.bakery@gmail.com", "Elisa Beckett", 300L "elisa.bakery@gmail.com", "Elisa Beckett", 0L ), ), newGetEntry( newGetEntry( "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password", "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.bakery@gmail.com", null, 300L "elisa.bakery@gmail.com", null, 10L ), ), newGetEntry( newGetEntry( "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password", "key1", "subkey-3", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "elisa.family@outlook.com", null, 100L "elisa.family@outlook.com", "Elisa Beckett", 1L ), ), ) ) ).setAuthenticationEntry( ).setAuthenticationEntry( Loading @@ -247,12 +251,12 @@ class CredentialManagerRepo( .setCredentialEntries( .setCredentialEntries( listOf<Entry>( listOf<Entry>( newGetEntry( newGetEntry( "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password", "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.family@outlook.com", null, 600L "elisa.family@outlook.com", null, 4L ), ), newGetEntry( newGetEntry( "key1", "subkey-2", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey", "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password", "elisa.family@outlook.com", null, 100L "elisa.work@outlook.com", null, 11L ), ), ) ) ).setAuthenticationEntry( ).setAuthenticationEntry( Loading
packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt +49 −17 Original line number Original line Diff line number Diff line Loading @@ -146,13 +146,19 @@ fun PrimarySelectionCard( textAlign = TextAlign.Center, textAlign = TextAlign.Center, style = MaterialTheme.typography.headlineSmall, style = MaterialTheme.typography.headlineSmall, text = stringResource( text = stringResource( if (sortedUserNameToCredentialEntryList.size == 1) { if (sortedUserNameToCredentialEntryList if (sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList .size == 1 && authenticationEntryList.isEmpty() .first().credentialType ) { if (sortedUserNameToCredentialEntryList.first() .sortedCredentialEntryList.first().credentialType == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ) ) R.string.get_dialog_title_use_passkey_for R.string.get_dialog_title_use_passkey_for else R.string.get_dialog_title_use_sign_in_for else R.string.get_dialog_title_use_sign_in_for } else if ( sortedUserNameToCredentialEntryList .isEmpty() && authenticationEntryList.size == 1 ) { R.string.get_dialog_title_use_sign_in_for } else R.string.get_dialog_title_choose_sign_in_for, } else R.string.get_dialog_title_choose_sign_in_for, requestDisplayInfo.appDomainName requestDisplayInfo.appDomainName ), ), Loading @@ -164,9 +170,14 @@ fun PrimarySelectionCard( .padding(horizontal = 24.dp) .padding(horizontal = 24.dp) .align(alignment = Alignment.CenterHorizontally) .align(alignment = Alignment.CenterHorizontally) ) { ) { val usernameForCredentialSize = sortedUserNameToCredentialEntryList .size val authenticationEntrySize = authenticationEntryList.size LazyColumn( LazyColumn( verticalArrangement = Arrangement.spacedBy(2.dp) verticalArrangement = Arrangement.spacedBy(2.dp) ) { ) { // Show max 4 entries in this primary page if (usernameForCredentialSize + authenticationEntrySize <= 4) { items(sortedUserNameToCredentialEntryList) { items(sortedUserNameToCredentialEntryList) { CredentialEntryRow( CredentialEntryRow( credentialEntryInfo = it.sortedCredentialEntryList.first(), credentialEntryInfo = it.sortedCredentialEntryList.first(), Loading @@ -179,6 +190,27 @@ fun PrimarySelectionCard( onEntrySelected = onEntrySelected, onEntrySelected = onEntrySelected, ) ) } } } else if (usernameForCredentialSize < 4) { items(sortedUserNameToCredentialEntryList) { CredentialEntryRow( credentialEntryInfo = it.sortedCredentialEntryList.first(), onEntrySelected = onEntrySelected, ) } items(authenticationEntryList.take(4 - usernameForCredentialSize)) { AuthenticationEntryRow( authenticationEntryInfo = it, onEntrySelected = onEntrySelected, ) } } else { items(sortedUserNameToCredentialEntryList.take(4)) { CredentialEntryRow( credentialEntryInfo = it.sortedCredentialEntryList.first(), onEntrySelected = onEntrySelected, ) } } } } } } Divider( Divider( Loading Loading @@ -257,7 +289,7 @@ fun AllSignInOptionCard( ) ) } } // Locked password manager // Locked password manager if (!authenticationEntryList.isEmpty()) { if (authenticationEntryList.isNotEmpty()) { item { item { LockedCredentials( LockedCredentials( authenticationEntryList = authenticationEntryList, authenticationEntryList = authenticationEntryList, Loading
packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt +3 −3 Original line number Original line Diff line number Diff line Loading @@ -182,7 +182,7 @@ private fun toProviderDisplayInfo( Preconditions.checkState(remoteEntryList.size <= 1) Preconditions.checkState(remoteEntryList.size <= 1) // Compose sortedUserNameToCredentialEntryList // Compose sortedUserNameToCredentialEntryList val comparator = CredentialEntryInfoComparator() val comparator = CredentialEntryInfoComparatorByTypeThenTimestamp() // Sort per username // Sort per username userNameToCredentialEntryMap.values.forEach { userNameToCredentialEntryMap.values.forEach { it.sortWith(comparator) it.sortWith(comparator) Loading @@ -191,7 +191,7 @@ private fun toProviderDisplayInfo( val sortedUserNameToCredentialEntryList = userNameToCredentialEntryMap.map { val sortedUserNameToCredentialEntryList = userNameToCredentialEntryMap.map { PerUserNameCredentialEntryList(it.key, it.value) PerUserNameCredentialEntryList(it.key, it.value) }.sortedWith( }.sortedWith( compareBy(comparator) { it.sortedCredentialEntryList.first() } compareByDescending{ it.sortedCredentialEntryList.first().lastUsedTimeMillis } ) ) return ProviderDisplayInfo( return ProviderDisplayInfo( Loading Loading @@ -219,7 +219,7 @@ private fun toGetScreenState( GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION } } internal class CredentialEntryInfoComparator : Comparator<CredentialEntryInfo> { internal class CredentialEntryInfoComparatorByTypeThenTimestamp : Comparator<CredentialEntryInfo> { override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int { override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int { // First prefer passkey type for its security benefits // First prefer passkey type for its security benefits if (p0.credentialType != p1.credentialType) { if (p0.credentialType != p1.credentialType) { Loading