summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/CredentialManager/res/values/strings.xml2
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt20
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt21
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt19
4 files changed, 55 insertions, 7 deletions
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index e9b2e1041c22..3e652517270d 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -117,6 +117,8 @@
<string name="get_dialog_sign_in_type_username_separator" translatable="false">" • "</string>
<!-- This text is followed by a list of one or more options. [CHAR LIMIT=80] -->
<string name="get_dialog_title_sign_in_options">Sign-in options</string>
+ <!-- Button label for viewing the full information about an account. [CHAR LIMIT=80] -->
+ <string name="button_label_view_more">View more</string>
<!-- Column heading for displaying sign-ins for a specific username. [CHAR LIMIT=80] -->
<string name="get_dialog_heading_for_username">For <xliff:g id="username" example="becket@gmail.com">%1$s</xliff:g></string>
<!-- Column heading for displaying locked (that is, the user needs to first authenticate via pin, fingerprint, faceId, etc.) sign-ins. [CHAR LIMIT=80] -->
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index 0623ff629812..2dba2ab6777c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -51,6 +51,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
@@ -79,6 +80,7 @@ fun Entry(
/** If true, draws a trailing lock icon. */
isLockedAuthEntry: Boolean = false,
enforceOneLine: Boolean = false,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
) {
val iconPadding = Modifier.wrapContentSize().padding(
// Horizontal padding should be 16dp, but the suggestion chip itself
@@ -103,7 +105,11 @@ fun Entry(
) {
// Apply weight so that the trailing icon can always show.
Column(modifier = Modifier.wrapContentHeight().fillMaxWidth().weight(1f)) {
- SmallTitleText(text = entryHeadlineText, enforceOneLine = enforceOneLine)
+ SmallTitleText(
+ text = entryHeadlineText,
+ enforceOneLine = enforceOneLine,
+ onTextLayout = onTextLayout,
+ )
if (passwordValue != null) {
Row(
modifier = Modifier.fillMaxWidth().padding(top = 4.dp),
@@ -141,10 +147,18 @@ fun Entry(
)
}
} else if (entrySecondLineText != null) {
- BodySmallText(text = entrySecondLineText, enforceOneLine = enforceOneLine)
+ BodySmallText(
+ text = entrySecondLineText,
+ enforceOneLine = enforceOneLine,
+ onTextLayout = onTextLayout,
+ )
}
if (entryThirdLineText != null) {
- BodySmallText(text = entryThirdLineText, enforceOneLine = enforceOneLine)
+ BodySmallText(
+ text = entryThirdLineText,
+ enforceOneLine = enforceOneLine,
+ onTextLayout = onTextLayout,
+ )
}
}
if (isLockedAuthEntry) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
index 61c03b4041f5..6b46636964e4 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
@@ -22,6 +22,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
@@ -59,14 +60,20 @@ fun BodyMediumText(text: String, modifier: Modifier = Modifier) {
* Body-small typography; on-surface-variant color.
*/
@Composable
-fun BodySmallText(text: String, modifier: Modifier = Modifier, enforceOneLine: Boolean = false) {
+fun BodySmallText(
+ text: String,
+ modifier: Modifier = Modifier,
+ enforceOneLine: Boolean = false,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+) {
Text(
modifier = modifier.wrapContentSize(),
text = text,
color = LocalAndroidColorScheme.current.colorOnSurfaceVariant,
style = MaterialTheme.typography.bodySmall,
overflow = TextOverflow.Ellipsis,
- maxLines = if (enforceOneLine) 1 else Int.MAX_VALUE
+ maxLines = if (enforceOneLine) 1 else Int.MAX_VALUE,
+ onTextLayout = onTextLayout,
)
}
@@ -87,14 +94,20 @@ fun LargeTitleText(text: String, modifier: Modifier = Modifier) {
* Title-small typography; on-surface color.
*/
@Composable
-fun SmallTitleText(text: String, modifier: Modifier = Modifier, enforceOneLine: Boolean = false) {
+fun SmallTitleText(
+ text: String,
+ modifier: Modifier = Modifier,
+ enforceOneLine: Boolean = false,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+) {
Text(
modifier = modifier.wrapContentSize(),
text = text,
color = LocalAndroidColorScheme.current.colorOnSurface,
style = MaterialTheme.typography.titleSmall,
overflow = TextOverflow.Ellipsis,
- maxLines = if (enforceOneLine) 1 else Int.MAX_VALUE
+ maxLines = if (enforceOneLine) 1 else Int.MAX_VALUE,
+ onTextLayout = onTextLayout,
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 6d7ecd70eb0b..c1ea1d8d1746 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -34,11 +34,15 @@ 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
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.TextLayoutResult
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
import com.android.credentialmanager.CredentialSelectorViewModel
@@ -158,6 +162,7 @@ fun PrimarySelectionCard(
onMoreOptionSelected: () -> Unit,
onLog: @Composable (UiEventEnum) -> Unit,
) {
+ val showMoreForTruncatedEntry = remember { mutableStateOf(false) }
val sortedUserNameToCredentialEntryList =
providerDisplayInfo.sortedUserNameToCredentialEntryList
val authenticationEntryList = providerDisplayInfo.authenticationEntryList
@@ -209,6 +214,8 @@ fun PrimarySelectionCard(
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
val authenticationEntrySize = authenticationEntryList.size
+ // If true, render a view more button for the single truncated entry on the
+ // front page.
// Show max 4 entries in this primary page
if (usernameForCredentialSize + authenticationEntrySize <= 4) {
sortedUserNameToCredentialEntryList.forEach {
@@ -216,6 +223,9 @@ fun PrimarySelectionCard(
credentialEntryInfo = it.sortedCredentialEntryList.first(),
onEntrySelected = onEntrySelected,
enforceOneLine = true,
+ onTextLayout = {
+ showMoreForTruncatedEntry.value = it.hasVisualOverflow
+ }
)
}
authenticationEntryList.forEach {
@@ -269,6 +279,13 @@ fun PrimarySelectionCard(
onMoreOptionSelected
)
}
+ } else if (showMoreForTruncatedEntry.value) {
+ {
+ ActionButton(
+ stringResource(R.string.button_label_view_more),
+ onMoreOptionSelected
+ )
+ }
} else null,
rightButton = if (activeEntry != null) { // Only one sign-in options exist
{
@@ -438,6 +455,7 @@ fun CredentialEntryRow(
credentialEntryInfo: CredentialEntryInfo,
onEntrySelected: (BaseEntry) -> Unit,
enforceOneLine: Boolean = false,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
) {
Entry(
onClick = { onEntrySelected(credentialEntryInfo) },
@@ -463,6 +481,7 @@ fun CredentialEntryRow(
)
},
enforceOneLine = enforceOneLine,
+ onTextLayout = onTextLayout,
)
}