Merge "[CredManUi] App can specify preferred top level branding for sign-in flow" into udc-dev

This commit is contained in:
Helen Qin
2023-04-13 20:55:26 +00:00
committed by Android (Google) Code Review
3 changed files with 60 additions and 19 deletions

View File

@@ -46,6 +46,7 @@ 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.getflow.TopBrandingContent
import androidx.credentials.CreateCredentialRequest
import androidx.credentials.CreateCustomCredentialRequest
import androidx.credentials.CreatePasswordRequest
@@ -207,6 +208,23 @@ class GetFlowUtils {
false
}
}
val preferUiBrandingComponentName =
getCredentialRequest.data.getParcelable(
"androidx.credentials.BUNDLE_KEY_PREFER_UI_BRANDING_COMPONENT_NAME",
ComponentName::class.java
)
val preferTopBrandingContent: TopBrandingContent? =
if (preferUiBrandingComponentName == null) null
else {
val (displayName, icon) = getServiceLabelAndIcon(
context.packageManager, preferUiBrandingComponentName.flattenToString())
?: Pair(null, null)
if (displayName != null && icon != null) {
TopBrandingContent(icon, displayName)
} else {
null
}
}
return com.android.credentialmanager.getflow.RequestDisplayInfo(
appName = originName
?: getAppLabel(context.packageManager, requestInfo.appPackageName)
@@ -216,6 +234,7 @@ class GetFlowUtils {
// TODO(b/276777444): replace with direct library constant reference once
// exposed.
"androidx.credentials.BUNDLE_KEY_PREFER_IDENTITY_DOC_UI"),
preferTopBrandingContent = preferTopBrandingContent,
)
}

View File

@@ -16,6 +16,7 @@
package com.android.credentialmanager.getflow
import android.graphics.drawable.Drawable
import android.text.TextUtils
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
@@ -34,7 +35,6 @@ import androidx.compose.material3.Divider
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
@@ -168,26 +168,30 @@ fun PrimarySelectionCard(
providerDisplayInfo.sortedUserNameToCredentialEntryList
val authenticationEntryList = providerDisplayInfo.authenticationEntryList
SheetContainerCard {
// When only one provider (not counting the remote-only provider) exists, display that
// provider's icon + name up top.
if (providerInfoList.size <= 2) { // It's only possible to be the single provider case
// if we are started with no more than 2 providers.
val nonRemoteProviderList = providerInfoList.filter(
{ it.credentialEntryList.isNotEmpty() || it.authenticationEntryList.isNotEmpty() }
)
if (nonRemoteProviderList.size == 1) {
val providerInfo = nonRemoteProviderList.firstOrNull() // First should always work
// but just to be safe.
val preferTopBrandingContent = requestDisplayInfo.preferTopBrandingContent
if (preferTopBrandingContent != null) {
item {
HeadlineProviderIconAndName(
preferTopBrandingContent.icon,
preferTopBrandingContent.displayName
)
}
} else {
// When only one provider (not counting the remote-only provider) exists, display that
// provider's icon + name up top.
val providersWithActualEntries = providerInfoList.filter {
it.credentialEntryList.isNotEmpty() || it.authenticationEntryList.isNotEmpty()
}
if (providersWithActualEntries.size == 1) {
// First should always work but just to be safe.
val providerInfo = providersWithActualEntries.firstOrNull()
if (providerInfo != null) {
item {
HeadlineIcon(
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
tint = Color.Unspecified,
HeadlineProviderIconAndName(
providerInfo.icon,
providerInfo.displayName
)
}
item { Divider(thickness = 4.dp, color = Color.Transparent) }
item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
item { Divider(thickness = 16.dp, color = Color.Transparent) }
}
}
}
@@ -369,8 +373,19 @@ fun AllSignInOptionCard(
onLog(GetCredentialEvent.CREDMAN_GET_CRED_ALL_SIGN_IN_OPTION_CARD)
}
// TODO: create separate rows for primary and secondary pages.
// TODO: reuse rows and columns across types.
@Composable
fun HeadlineProviderIconAndName(
icon: Drawable,
name: String,
) {
HeadlineIcon(
bitmap = icon.toBitmap().asImageBitmap(),
tint = Color.Unspecified,
)
Divider(thickness = 4.dp, color = Color.Transparent)
LargeLabelTextOnSurfaceVariant(text = name)
Divider(thickness = 16.dp, color = Color.Transparent)
}
@Composable
fun ActionChips(

View File

@@ -173,6 +173,13 @@ data class RequestDisplayInfo(
val appName: String,
val preferImmediatelyAvailableCredentials: Boolean,
val preferIdentityDocUi: Boolean,
// A top level branding icon + display name preferred by the app.
val preferTopBrandingContent: TopBrandingContent?,
)
data class TopBrandingContent(
val icon: Drawable,
val displayName: String,
)
/**