android: fix issue where default avatar wasn't shown (#558)

Always render the default icon first so that if the profile picture is not loaded or has an issue, the default is shown.

Fixes tailscale/corp#24217

Signed-off-by: kari-ts <kari@tailscale.com>
kari/test
kari-ts 1 year ago committed by GitHub
parent 18ca09d0f3
commit 4c4148bd8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -43,35 +43,38 @@ fun Avatar(
var isFocused = remember { mutableStateOf(false) } var isFocused = remember { mutableStateOf(false) }
val focusManager = LocalFocusManager.current val focusManager = LocalFocusManager.current
// Determine the modifier based on whether the avatar is focusable // Outer Box for the larger focusable and clickable area
val outerModifier = Box(
Modifier.then( contentAlignment = Alignment.Center,
if (isFocusable) { modifier = Modifier
Modifier.padding(4.dp) .padding(4.dp)
} else Modifier) // Add padding if focusable .size((size * 1.5f).dp) // Focusable area is larger than the avatar
.size((size * 1.5f).dp) .clip(CircleShape) // Ensure both the focus and click area are circular
.clip(CircleShape) .background(
.background(if (isFocused.value) MaterialTheme.colorScheme.surface else Color.Transparent) if (isFocused.value) MaterialTheme.colorScheme.surface
.onFocusChanged { focusState -> isFocused.value = focusState.isFocused } else Color.Transparent,
.then(if (isFocusable) Modifier.focusable() else Modifier) // Conditionally add focusable )
.onFocusChanged { focusState ->
isFocused.value = focusState.isFocused
}
.focusable() // Make this outer Box focusable (after onFocusChanged)
.clickable( .clickable(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = ripple(bounded = true), indication = ripple(bounded = true), // Apply ripple effect inside circular bounds
onClick = { onClick = {
action?.invoke() action?.invoke()
focusManager.clearFocus() // Clear focus after clicking focusManager.clearFocus() // Clear focus after clicking the avatar
}) }
)
// Outer Box for the larger focusable and clickable area ) {
Box(contentAlignment = Alignment.Center, modifier = outerModifier) {
// Inner Box to hold the avatar content (Icon or AsyncImage) // Inner Box to hold the avatar content (Icon or AsyncImage)
Box(contentAlignment = Alignment.Center, modifier = Modifier.size(size.dp).clip(CircleShape)) { Box(
if (profile?.UserProfile?.ProfilePicURL != null) { contentAlignment = Alignment.Center,
AsyncImage( modifier = Modifier
model = profile.UserProfile.ProfilePicURL, .size(size.dp)
modifier = Modifier.size(size.dp).clip(CircleShape), .clip(CircleShape)
contentDescription = null) ) {
} else { // Always display the default icon as a background layer
Icon( Icon(
imageVector = Icons.Default.Person, imageVector = Icons.Default.Person,
contentDescription = stringResource(R.string.settings_title), contentDescription = stringResource(R.string.settings_title),
@ -79,6 +82,13 @@ fun Avatar(
Modifier.size((size * 0.8f).dp) Modifier.size((size * 0.8f).dp)
.clip(CircleShape) // Icon size slightly smaller than the Box .clip(CircleShape) // Icon size slightly smaller than the Box
) )
// Overlay the profile picture if available
profile?.UserProfile?.ProfilePicURL?.let { url ->
AsyncImage(
model = url,
modifier = Modifier.size(size.dp).clip(CircleShape),
contentDescription = null)
} }
} }
} }

Loading…
Cancel
Save