Merge "Add remote entry for get flow."
This commit is contained in:
@@ -62,4 +62,8 @@
|
||||
<string name="locked_credential_entry_label_subtext">Tap to unlock</string>
|
||||
<!-- Column heading for displaying action chips for managing sign-ins from each credential provider. [CHAR LIMIT=80] -->
|
||||
<string name="get_dialog_heading_manage_sign_ins">Manage sign-ins</string>
|
||||
<!-- Column heading for displaying option to use sign-ins saved on a different device. [CHAR LIMIT=80] -->
|
||||
<string name="get_dialog_heading_from_another_device">From another device</string>
|
||||
<!-- Headline text for an option to use sign-ins saved on a different device. [CHAR LIMIT=120] -->
|
||||
<string name="get_dialog_option_headline_use_a_different_device">Use a different device</string>
|
||||
</resources>
|
||||
@@ -194,7 +194,7 @@ class CredentialManagerRepo(
|
||||
)
|
||||
)
|
||||
.setRemoteEntry(
|
||||
newRemoteEntry("key1", "subkey-1")
|
||||
newRemoteEntry("key2", "subkey-1")
|
||||
)
|
||||
.setIsDefaultProvider(true)
|
||||
.build(),
|
||||
@@ -252,6 +252,8 @@ class CredentialManagerRepo(
|
||||
"Open Google Password Manager", "beckett-family@gmail.com"
|
||||
),
|
||||
)
|
||||
).setRemoteEntry(
|
||||
newRemoteEntry("key4", "subkey-1")
|
||||
).build(),
|
||||
GetCredentialProviderData.Builder("com.dashlane")
|
||||
.setCredentialEntries(
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.android.credentialmanager.getflow.ActionEntryInfo
|
||||
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
|
||||
import com.android.credentialmanager.getflow.CredentialEntryInfo
|
||||
import com.android.credentialmanager.getflow.ProviderInfo
|
||||
import com.android.credentialmanager.getflow.RemoteEntryInfo
|
||||
import com.android.credentialmanager.jetpack.provider.ActionUi
|
||||
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi
|
||||
import com.android.credentialmanager.jetpack.provider.SaveEntryUi
|
||||
@@ -59,10 +60,11 @@ class GetFlowUtils {
|
||||
credentialEntryList = getCredentialOptionInfoList(
|
||||
it.providerFlattenedComponentName, it.credentialEntries, context),
|
||||
authenticationEntry = getAuthenticationEntry(
|
||||
it.providerFlattenedComponentName,
|
||||
providerDisplayName,
|
||||
providerIcon,
|
||||
it.authenticationEntry),
|
||||
it.providerFlattenedComponentName,
|
||||
providerDisplayName,
|
||||
providerIcon,
|
||||
it.authenticationEntry),
|
||||
remoteEntry = getRemoteEntry(it.providerFlattenedComponentName, it.remoteEntry),
|
||||
actionEntryList = getActionEntryList(
|
||||
it.providerFlattenedComponentName, it.actionChips, context),
|
||||
)
|
||||
@@ -116,6 +118,18 @@ class GetFlowUtils {
|
||||
)
|
||||
}
|
||||
|
||||
private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? {
|
||||
// TODO: should also call fromSlice after getting the official jetpack code.
|
||||
if (remoteEntry == null) {
|
||||
return null
|
||||
}
|
||||
return RemoteEntryInfo(
|
||||
providerId = providerId,
|
||||
entryKey = remoteEntry.key,
|
||||
entrySubkey = remoteEntry.subkey,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getActionEntryList(
|
||||
providerId: String,
|
||||
actionEntries: List<Entry>,
|
||||
|
||||
@@ -45,6 +45,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -220,16 +221,25 @@ fun AllSignInOptionCard(
|
||||
)
|
||||
}
|
||||
// Locked password manager
|
||||
item {
|
||||
if (!authenticationEntryList.isEmpty()) {
|
||||
if (!authenticationEntryList.isEmpty()) {
|
||||
item {
|
||||
LockedCredentials(
|
||||
authenticationEntryList = authenticationEntryList,
|
||||
onEntrySelected = onEntrySelected,
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO: Remote action
|
||||
// Manage sign-ins
|
||||
// From another device
|
||||
val remoteEntry = providerDisplayInfo.remoteEntry
|
||||
if (remoteEntry != null) {
|
||||
item {
|
||||
RemoteEntryCard(
|
||||
remoteEntry = remoteEntry,
|
||||
onEntrySelected = onEntrySelected,
|
||||
)
|
||||
}
|
||||
}
|
||||
// Manage sign-ins (action chips)
|
||||
item {
|
||||
ActionChips(providerInfoList = providerInfoList, onEntrySelected = onEntrySelected)
|
||||
}
|
||||
@@ -270,6 +280,47 @@ fun ActionChips(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RemoteEntryCard(
|
||||
remoteEntry: RemoteEntryInfo,
|
||||
onEntrySelected: (EntryInfo) -> Unit,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.get_dialog_heading_from_another_device),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
Entry(
|
||||
onClick = {onEntrySelected(remoteEntry)},
|
||||
icon = {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_other_devices),
|
||||
contentDescription = null,
|
||||
tint = Color.Unspecified,
|
||||
modifier = Modifier.padding(start = 18.dp)
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.get_dialog_option_headline_use_a_different_device),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
|
||||
.align(alignment = Alignment.CenterHorizontally)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LockedCredentials(
|
||||
authenticationEntryList: List<AuthenticationEntryInfo>,
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.credentialmanager.CredentialManagerRepo
|
||||
import com.android.credentialmanager.common.DialogResult
|
||||
import com.android.credentialmanager.common.ResultState
|
||||
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
|
||||
import com.android.internal.util.Preconditions
|
||||
|
||||
data class GetCredentialUiState(
|
||||
val providerInfoList: List<ProviderInfo>,
|
||||
@@ -86,10 +87,14 @@ private fun toProviderDisplayInfo(
|
||||
|
||||
val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
|
||||
val authenticationEntryList = mutableListOf<AuthenticationEntryInfo>()
|
||||
val remoteEntryList = mutableListOf<RemoteEntryInfo>()
|
||||
providerInfoList.forEach { providerInfo ->
|
||||
if (providerInfo.authenticationEntry != null) {
|
||||
authenticationEntryList.add(providerInfo.authenticationEntry)
|
||||
}
|
||||
if (providerInfo.remoteEntry != null) {
|
||||
remoteEntryList.add(providerInfo.remoteEntry)
|
||||
}
|
||||
|
||||
providerInfo.credentialEntryList.forEach {
|
||||
userNameToCredentialEntryMap.compute(
|
||||
@@ -105,6 +110,9 @@ private fun toProviderDisplayInfo(
|
||||
}
|
||||
}
|
||||
}
|
||||
// There can only be at most one remote entry
|
||||
// TODO: fail elegantly
|
||||
Preconditions.checkState(remoteEntryList.size <= 1)
|
||||
|
||||
// Compose sortedUserNameToCredentialEntryList
|
||||
val comparator = CredentialEntryInfoComparator()
|
||||
@@ -122,6 +130,7 @@ private fun toProviderDisplayInfo(
|
||||
return ProviderDisplayInfo(
|
||||
sortedUserNameToCredentialEntryList = sortedUserNameToCredentialEntryList,
|
||||
authenticationEntryList = authenticationEntryList,
|
||||
remoteEntry = remoteEntryList.getOrNull(0),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ data class ProviderInfo(
|
||||
val displayName: String,
|
||||
val credentialEntryList: List<CredentialEntryInfo>,
|
||||
val authenticationEntry: AuthenticationEntryInfo?,
|
||||
val remoteEntry: RemoteEntryInfo?,
|
||||
val actionEntryList: List<ActionEntryInfo>,
|
||||
// TODO: add remote entry
|
||||
)
|
||||
|
||||
/** Display-centric data structure derived from the [ProviderInfo]. This abstraction is not grouping
|
||||
@@ -41,6 +41,7 @@ data class ProviderDisplayInfo(
|
||||
*/
|
||||
val sortedUserNameToCredentialEntryList: List<PerUserNameCredentialEntryList>,
|
||||
val authenticationEntryList: List<AuthenticationEntryInfo>,
|
||||
val remoteEntry: RemoteEntryInfo?
|
||||
)
|
||||
|
||||
abstract class EntryInfo (
|
||||
@@ -72,6 +73,12 @@ class AuthenticationEntryInfo(
|
||||
val icon: Drawable,
|
||||
) : EntryInfo(providerId, entryKey, entrySubkey)
|
||||
|
||||
class RemoteEntryInfo(
|
||||
providerId: String,
|
||||
entryKey: String,
|
||||
entrySubkey: String,
|
||||
) : EntryInfo(providerId, entryKey, entrySubkey)
|
||||
|
||||
class ActionEntryInfo(
|
||||
providerId: String,
|
||||
entryKey: String,
|
||||
|
||||
Reference in New Issue
Block a user