@@ -34,57 +34,52 @@ import com.tailscale.ipn.ui.model.IpnLocal
3434
3535@OptIn(ExperimentalCoilApi ::class )
3636@Composable
37- fun Avatar (profile : IpnLocal .LoginProfile ? , size : Int = 50, action : (() -> Unit )? = null) {
38- var isFocused = remember { mutableStateOf(false ) }
39- val focusManager = LocalFocusManager .current
37+ fun Avatar (
38+ profile : IpnLocal .LoginProfile ? ,
39+ size : Int = 50,
40+ action : (() -> Unit )? = null,
41+ isFocusable : Boolean = false
42+ ) {
43+ var isFocused = remember { mutableStateOf(false ) }
44+ val focusManager = LocalFocusManager .current
4045
41- // Outer Box for the larger focusable and clickable area
42- Box (
43- contentAlignment = Alignment .Center ,
44- modifier = Modifier
45- .padding(4 .dp)
46- .size((size * 1.5f ).dp) // Focusable area is larger than the avatar
47- .clip(CircleShape ) // Ensure both the focus and click area are circular
48- .background(
49- if (isFocused.value) MaterialTheme .colorScheme.surface
50- else Color .Transparent ,
51- )
52- .onFocusChanged { focusState ->
53- isFocused.value = focusState.isFocused
54- }
55- .focusable() // Make this outer Box focusable (after onFocusChanged)
56- .clickable(
57- interactionSource = remember { MutableInteractionSource () },
58- indication = ripple(bounded = true ), // Apply ripple effect inside circular bounds
59- onClick = {
60- action?.invoke()
61- focusManager.clearFocus() // Clear focus after clicking the avatar
62- }
46+ // Determine the modifier based on whether the avatar is focusable
47+ val outerModifier =
48+ Modifier .then(
49+ if (isFocusable) {
50+ Modifier .padding(4 .dp)
51+ } else Modifier ) // Add padding if focusable
52+ .size((size * 1.5f ).dp)
53+ .clip(CircleShape )
54+ .background(if (isFocused.value) MaterialTheme .colorScheme.surface else Color .Transparent )
55+ .onFocusChanged { focusState -> isFocused.value = focusState.isFocused }
56+ .then(if (isFocusable) Modifier .focusable() else Modifier ) // Conditionally add focusable
57+ .clickable(
58+ interactionSource = remember { MutableInteractionSource () },
59+ indication = ripple(bounded = true ),
60+ onClick = {
61+ action?.invoke()
62+ focusManager.clearFocus() // Clear focus after clicking
63+ })
64+
65+ // Outer Box for the larger focusable and clickable area
66+ Box (contentAlignment = Alignment .Center , modifier = outerModifier) {
67+ // Inner Box to hold the avatar content (Icon or AsyncImage)
68+ Box (contentAlignment = Alignment .Center , modifier = Modifier .size(size.dp).clip(CircleShape )) {
69+ if (profile?.UserProfile ?.ProfilePicURL != null ) {
70+ AsyncImage (
71+ model = profile.UserProfile .ProfilePicURL ,
72+ modifier = Modifier .size(size.dp).clip(CircleShape ),
73+ contentDescription = null )
74+ } else {
75+ Icon (
76+ imageVector = Icons .Default .Person ,
77+ contentDescription = stringResource(R .string.settings_title),
78+ modifier =
79+ Modifier .size((size * 0.8f ).dp)
80+ .clip(CircleShape ) // Icon size slightly smaller than the Box
6381 )
64- ) {
65- // Inner Box to hold the avatar content (Icon or AsyncImage)
66- Box (
67- contentAlignment = Alignment .Center ,
68- modifier = Modifier
69- .size(size.dp)
70- .clip(CircleShape )
71- ) {
72- if (profile?.UserProfile ?.ProfilePicURL != null ) {
73- AsyncImage (
74- model = profile.UserProfile .ProfilePicURL ,
75- modifier = Modifier .size(size.dp).clip(CircleShape ),
76- contentDescription = null
77- )
78- } else {
79- Icon (
80- imageVector = Icons .Default .Person ,
81- contentDescription = stringResource(R .string.settings_title),
82- modifier = Modifier
83- .size((size * 0.8f ).dp)
84- .clip(CircleShape ) // Icon size slightly smaller than the Box
85- )
86- }
87- }
82+ }
8883 }
84+ }
8985}
90-
0 commit comments