@@ -34,57 +34,52 @@ import com.tailscale.ipn.ui.model.IpnLocal
34
34
35
35
@OptIn(ExperimentalCoilApi ::class )
36
36
@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
40
45
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
63
81
)
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
+ }
88
83
}
84
+ }
89
85
}
90
-
0 commit comments