show rounded circle for avatar

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2025-05-06 23:50:06 +02:00
parent 15d7c8371c
commit 91b0e97589
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
3 changed files with 48 additions and 24 deletions

View File

@ -10,37 +10,56 @@ package com.nextcloud.talk.call.components
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.nextcloud.talk.call.ParticipantUiState import com.nextcloud.talk.call.ParticipantUiState
@Composable @Composable
fun AvatarWithFallback(participant: ParticipantUiState) { fun AvatarWithFallback(participant: ParticipantUiState, modifier: Modifier = Modifier) {
if (!participant.avatarUrl.isNullOrEmpty()) { val initials = participant.nick
AsyncImage( .split(" ")
model = participant.avatarUrl, .mapNotNull { it.firstOrNull()?.uppercase() }
contentDescription = "Avatar", .take(2)
contentScale = ContentScale.Crop, .joinToString("")
modifier = Modifier.fillMaxSize()
) Box(
} else { modifier = modifier
Box( .size(150.dp)
modifier = Modifier .clip(CircleShape),
.fillMaxSize() contentAlignment = Alignment.Center
.background(Color.Gray), ) {
contentAlignment = Alignment.Center if (!participant.avatarUrl.isNullOrEmpty()) {
) { AsyncImage(
Text( model = participant.avatarUrl,
text = participant.nick.firstOrNull()?.uppercase() ?: "?", contentDescription = "Avatar",
color = Color.White, contentScale = ContentScale.Crop,
fontSize = 40.sp modifier = Modifier
.fillMaxSize()
.clip(CircleShape)
) )
} else {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White, CircleShape),
contentAlignment = Alignment.Center
) {
Text(
text = if (initials.isNotEmpty()) initials else "?",
color = Color.Black,
fontSize = 24.sp
)
}
} }
} }
} }

View File

@ -49,7 +49,7 @@ fun ParticipantGrid(
} else { } else {
when (participants.size) { when (participants.size) {
1 -> 1 1 -> 1
2 -> 2 2, 4 -> 2
else -> 3 else -> 3
} }
} }
@ -238,7 +238,7 @@ fun getTestParticipants(numberOfParticipants: Int): List<ParticipantUiState> {
for (i: Int in 1..numberOfParticipants) { for (i: Int in 1..numberOfParticipants) {
val participant = ParticipantUiState( val participant = ParticipantUiState(
sessionKey = i.toString(), sessionKey = i.toString(),
nick = "testuser$i", nick = "testuser$i Test",
isConnected = true, isConnected = true,
isAudioEnabled = if (i == 3) true else false, isAudioEnabled = if (i == 3) true else false,
isStreamEnabled = true, isStreamEnabled = true,

View File

@ -11,6 +11,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@ -46,7 +47,10 @@ fun ParticipantTile(
if (participant.isStreamEnabled && participant.mediaStream != null) { if (participant.isStreamEnabled && participant.mediaStream != null) {
WebRTCVideoView(participant, eglBase) WebRTCVideoView(participant, eglBase)
} else { } else {
AvatarWithFallback(participant) AvatarWithFallback(
participant = participant,
modifier = Modifier.align(Alignment.Center)
)
} }
if (participant.raisedHand) { if (participant.raisedHand) {
@ -96,7 +100,7 @@ fun ParticipantTile(
fun ParticipantTilePreview() { fun ParticipantTilePreview() {
val participant = ParticipantUiState( val participant = ParticipantUiState(
sessionKey = "", sessionKey = "",
nick = "testuser", nick = "testuser one",
isConnected = true, isConnected = true,
isAudioEnabled = false, isAudioEnabled = false,
isStreamEnabled = true, isStreamEnabled = true,
@ -107,7 +111,8 @@ fun ParticipantTilePreview() {
ParticipantTile( ParticipantTile(
participant = participant, participant = participant,
modifier = Modifier modifier = Modifier
.fillMaxWidth(), .fillMaxWidth()
.height(300.dp),
eglBase = null eglBase = null
) )
} }