feat(home): partner photoUrl loaded and displayed in identity card
- PartnerHomeViewModel: loads partner photoUrl alongside name - PartnerIdentityCard: shows AsyncImage when photoUrl available, fallback to initial letter
This commit is contained in:
parent
a8fbbaa286
commit
adb61715fe
|
|
@ -44,7 +44,10 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
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 coil.compose.AsyncImage
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
@ -77,6 +80,7 @@ data class PartnerHomeUiState(
|
||||||
val isLoading: Boolean = true,
|
val isLoading: Boolean = true,
|
||||||
val error: String? = null,
|
val error: String? = null,
|
||||||
val partnerName: String? = null,
|
val partnerName: String? = null,
|
||||||
|
val partnerPhotoUrl: String? = null,
|
||||||
val streakCount: Int = 0,
|
val streakCount: Int = 0,
|
||||||
val hasPartnerAnsweredToday: Boolean = false,
|
val hasPartnerAnsweredToday: Boolean = false,
|
||||||
val coupleId: String? = null,
|
val coupleId: String? = null,
|
||||||
|
|
@ -119,11 +123,13 @@ class PartnerHomeViewModel @Inject constructor(
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
val partnerId = couple.userIds.firstOrNull { it != uid }
|
val partnerId = couple.userIds.firstOrNull { it != uid }
|
||||||
val partnerName = partnerId?.let { pid ->
|
val partner = partnerId?.let { pid ->
|
||||||
runCatching { userRepository.getUser(pid)?.displayName }
|
runCatching { userRepository.getUser(pid) }
|
||||||
.onFailure { Log.w(TAG, "Could not load partner name", it) }
|
.onFailure { Log.w(TAG, "Could not load partner", it) }
|
||||||
.getOrNull()
|
.getOrNull()
|
||||||
}
|
}
|
||||||
|
val partnerName = partner?.displayName
|
||||||
|
val partnerPhotoUrl = partner?.photoUrl
|
||||||
val dailyAssignment = runCatching {
|
val dailyAssignment = runCatching {
|
||||||
answerDataSource.getDailyQuestionAssignment(couple.id)
|
answerDataSource.getDailyQuestionAssignment(couple.id)
|
||||||
}.getOrNull()
|
}.getOrNull()
|
||||||
|
|
@ -132,6 +138,7 @@ class PartnerHomeViewModel @Inject constructor(
|
||||||
it.copy(
|
it.copy(
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
partnerName = partnerName,
|
partnerName = partnerName,
|
||||||
|
partnerPhotoUrl = partnerPhotoUrl,
|
||||||
streakCount = couple.streakCount,
|
streakCount = couple.streakCount,
|
||||||
coupleId = couple.id,
|
coupleId = couple.id,
|
||||||
dailyQuestionId = dailyAssignment?.questionId,
|
dailyQuestionId = dailyAssignment?.questionId,
|
||||||
|
|
@ -269,7 +276,7 @@ private fun PartnerHomeContent(
|
||||||
.padding(horizontal = 20.dp, vertical = 12.dp),
|
.padding(horizontal = 20.dp, vertical = 12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
PartnerIdentityCard(name = state.partnerName, streakCount = state.streakCount)
|
PartnerIdentityCard(name = state.partnerName, photoUrl = state.partnerPhotoUrl, streakCount = state.streakCount)
|
||||||
|
|
||||||
PartnerActivityCard(
|
PartnerActivityCard(
|
||||||
partnerName = state.partnerName,
|
partnerName = state.partnerName,
|
||||||
|
|
@ -299,6 +306,7 @@ private fun PartnerHomeContent(
|
||||||
@Composable
|
@Composable
|
||||||
private fun PartnerIdentityCard(
|
private fun PartnerIdentityCard(
|
||||||
name: String?,
|
name: String?,
|
||||||
|
photoUrl: String?,
|
||||||
streakCount: Int,
|
streakCount: Int,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
|
|
@ -313,20 +321,31 @@ private fun PartnerIdentityCard(
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Surface(
|
if (!photoUrl.isNullOrBlank()) {
|
||||||
shape = CircleShape,
|
AsyncImage(
|
||||||
color = CloserPalette.PurpleDeep.copy(alpha = 0.14f),
|
model = photoUrl,
|
||||||
modifier = Modifier.size(56.dp)
|
contentDescription = name,
|
||||||
) {
|
contentScale = ContentScale.Crop,
|
||||||
Box(contentAlignment = Alignment.Center) {
|
modifier = Modifier
|
||||||
Text(
|
.size(56.dp)
|
||||||
text = (name?.firstOrNull()?.uppercaseChar() ?: '?').toString(),
|
.clip(CircleShape)
|
||||||
style = MaterialTheme.typography.headlineMedium.copy(
|
)
|
||||||
fontWeight = FontWeight.SemiBold,
|
} else {
|
||||||
fontSize = 24.sp
|
Surface(
|
||||||
),
|
shape = CircleShape,
|
||||||
color = CloserPalette.PurpleDeep
|
color = CloserPalette.PurpleDeep.copy(alpha = 0.14f),
|
||||||
)
|
modifier = Modifier.size(56.dp)
|
||||||
|
) {
|
||||||
|
Box(contentAlignment = Alignment.Center) {
|
||||||
|
Text(
|
||||||
|
text = (name?.firstOrNull()?.uppercaseChar() ?: '?').toString(),
|
||||||
|
style = MaterialTheme.typography.headlineMedium.copy(
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
fontSize = 24.sp
|
||||||
|
),
|
||||||
|
color = CloserPalette.PurpleDeep
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue