Fix profile avatar emoji fallback and bump TV/mobile app versions.

This commit is contained in:
Jos Vooges | STH 2026-09-13 16:29:49 +02:00
parent 91e7502d3b
commit 9efcfff484
9 changed files with 113 additions and 73 deletions

View file

@ -20,8 +20,8 @@ android {
applicationId = "nl.vonas.mediacluster" applicationId = "nl.vonas.mediacluster"
minSdk = 24 minSdk = 24
targetSdk = 36 targetSdk = 36
versionCode = 20 versionCode = 21
versionName = "1.0.19" versionName = "1.0.20"
buildConfigField("String", "DEFAULT_API_BASE", "\"https://master.vonas.nl\"") buildConfigField("String", "DEFAULT_API_BASE", "\"https://master.vonas.nl\"")
ndk { ndk {
abiFilters += listOf("arm64-v8a", "armeabi-v7a") abiFilters += listOf("arm64-v8a", "armeabi-v7a")

View file

@ -885,14 +885,21 @@ private fun JSONArray?.toProfiles(): List<ViewerProfile> {
} }
} }
private fun JSONObject.toProfile(): ViewerProfile = ViewerProfile( private fun JSONObject.toProfile(): ViewerProfile {
id = getString("id"), val hasCustom = optBoolean("hasCustomAvatar")
name = optString("name"), val rawUrl = optString("avatarUrl").takeIf { it.isNotBlank() }
avatarId = optString("avatarId").ifBlank { "fox" }, return ViewerProfile(
isOwner = optBoolean("isOwner"), id = getString("id"),
isKids = optBoolean("isKids"), name = optString("name"),
hasPin = optBoolean("hasPin"), avatarId = optString("avatarId").ifBlank { "fox" },
showAvatar = if (has("showAvatar")) optBoolean("showAvatar") else true, isOwner = optBoolean("isOwner"),
hasCustomAvatar = optBoolean("hasCustomAvatar"), isKids = optBoolean("isKids"),
avatarUrl = optString("avatarUrl").ifBlank { null }, hasPin = optBoolean("hasPin"),
) showAvatar = when {
!has("showAvatar") || isNull("showAvatar") -> true
else -> optBoolean("showAvatar", true)
},
hasCustomAvatar = hasCustom,
avatarUrl = if (hasCustom) rawUrl else null,
)
}

View file

@ -86,10 +86,9 @@ class SessionStore(private val context: Context) {
if (showAvatar != null) { if (showAvatar != null) {
prefs[profileShowAvatarKey] = if (showAvatar) "1" else "0" prefs[profileShowAvatarKey] = if (showAvatar) "1" else "0"
} }
if (avatarUrl != null) { // Altijd syncen: null/blank = geen custom foto (emoji tonen)
if (avatarUrl.isBlank()) prefs.remove(profileAvatarUrlKey) if (avatarUrl.isNullOrBlank()) prefs.remove(profileAvatarUrlKey)
else prefs[profileAvatarUrlKey] = avatarUrl else prefs[profileAvatarUrlKey] = avatarUrl
}
} }
} }
} }

View file

@ -1350,22 +1350,32 @@ private fun SettingsScreen(
.background(Color(0xFF2E2E3A)), .background(Color(0xFF2E2E3A)),
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
if (profileShowAvatar && !profileAvatarUrl.isNullOrBlank()) { if (profileShowAvatar) {
AsyncImage( Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
model = ImageRequest.Builder(LocalContext.current) Text(avatarEmoji(profileAvatarId ?: "fox"), fontSize = 22.sp)
.data(profileAvatarUrl) if (!profileAvatarUrl.isNullOrBlank()) {
.apply { AsyncImage(
if (!profileAuthHeader.isNullOrBlank()) { model = ImageRequest.Builder(LocalContext.current)
addHeader("Authorization", profileAuthHeader) .data(profileAvatarUrl)
} .apply {
} if (!profileAuthHeader.isNullOrBlank()) {
.build(), addHeader("Authorization", profileAuthHeader)
contentDescription = null, }
modifier = Modifier.fillMaxSize(), }
contentScale = ContentScale.Crop, .build(),
) contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
}
}
} else { } else {
Text(avatarEmoji(profileAvatarId ?: "fox"), fontSize = 22.sp) Text(
(profileName?.firstOrNull()?.uppercaseChar() ?: '?').toString(),
color = Color.White,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
)
} }
} }
Column(Modifier.weight(1f)) { Column(Modifier.weight(1f)) {

View file

@ -20,8 +20,8 @@ android {
applicationId = "nl.vonas.mediacluster.tv" applicationId = "nl.vonas.mediacluster.tv"
minSdk = 24 minSdk = 24
targetSdk = 36 targetSdk = 36
versionCode = 106 versionCode = 107
versionName = "0.14.43" versionName = "0.14.44"
buildConfigField("String", "DEFAULT_API_BASE", "\"https://master.vonas.nl\"") buildConfigField("String", "DEFAULT_API_BASE", "\"https://master.vonas.nl\"")
ndk { ndk {
abiFilters += listOf("arm64-v8a", "armeabi-v7a") abiFilters += listOf("arm64-v8a", "armeabi-v7a")

View file

@ -875,14 +875,21 @@ private fun JSONArray?.toProfiles(): List<ViewerProfile> {
} }
} }
private fun JSONObject.toProfile(): ViewerProfile = ViewerProfile( private fun JSONObject.toProfile(): ViewerProfile {
id = getString("id"), val hasCustom = optBoolean("hasCustomAvatar")
name = optString("name"), val rawUrl = optString("avatarUrl").takeIf { it.isNotBlank() }
avatarId = optString("avatarId").ifBlank { "fox" }, return ViewerProfile(
isOwner = optBoolean("isOwner"), id = getString("id"),
isKids = optBoolean("isKids"), name = optString("name"),
hasPin = optBoolean("hasPin"), avatarId = optString("avatarId").ifBlank { "fox" },
showAvatar = if (has("showAvatar")) optBoolean("showAvatar") else true, isOwner = optBoolean("isOwner"),
hasCustomAvatar = optBoolean("hasCustomAvatar"), isKids = optBoolean("isKids"),
avatarUrl = optString("avatarUrl").ifBlank { null }, hasPin = optBoolean("hasPin"),
) showAvatar = when {
!has("showAvatar") || isNull("showAvatar") -> true
else -> optBoolean("showAvatar", true)
},
hasCustomAvatar = hasCustom,
avatarUrl = if (hasCustom) rawUrl else null,
)
}

View file

@ -105,10 +105,9 @@ class SessionStore(private val context: Context) {
if (showAvatar != null) { if (showAvatar != null) {
prefs[profileShowAvatarKey] = if (showAvatar) "1" else "0" prefs[profileShowAvatarKey] = if (showAvatar) "1" else "0"
} }
if (avatarUrl != null) { // Altijd syncen: null/blank = geen custom foto (emoji tonen)
if (avatarUrl.isBlank()) prefs.remove(profileAvatarUrlKey) if (avatarUrl.isNullOrBlank()) prefs.remove(profileAvatarUrlKey)
else prefs[profileAvatarUrlKey] = avatarUrl else prefs[profileAvatarUrlKey] = avatarUrl
}
} }
} }
} }

View file

@ -784,6 +784,7 @@ private fun MainHub(
MainTab.Settings -> SettingsScreen( MainTab.Settings -> SettingsScreen(
api = api, api = api,
profileAvatarId = profileAvatarId, profileAvatarId = profileAvatarId,
profileShowAvatar = profileShowAvatar,
profileName = profileName, profileName = profileName,
isOwner = isOwner, isOwner = isOwner,
onBack = { onBack = {
@ -1644,6 +1645,7 @@ private fun ShelfBlock(
private fun SettingsScreen( private fun SettingsScreen(
api: ApiClient, api: ApiClient,
profileAvatarId: String? = null, profileAvatarId: String? = null,
profileShowAvatar: Boolean = true,
profileName: String? = null, profileName: String? = null,
isOwner: Boolean = false, isOwner: Boolean = false,
onBack: () -> Unit, onBack: () -> Unit,
@ -1737,12 +1739,21 @@ private fun SettingsScreen(
.background(Color(0xFF2E2E3A)), .background(Color(0xFF2E2E3A)),
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
Text( if (profileShowAvatar) {
avatarEmoji(profileAvatarId ?: "fox"), Text(
fontSize = 30.sp, avatarEmoji(profileAvatarId ?: "fox"),
textAlign = TextAlign.Center, fontSize = 30.sp,
modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center,
) modifier = Modifier.fillMaxWidth(),
)
} else {
Text(
(profileName?.firstOrNull()?.uppercaseChar() ?: '?').toString(),
color = Color.White,
fontSize = 26.sp,
fontWeight = FontWeight.Bold,
)
}
} }
Column(Modifier.weight(1f)) { Column(Modifier.weight(1f)) {
Text( Text(

View file

@ -321,25 +321,32 @@ fun TopNavBar(
horizontalArrangement = Arrangement.spacedBy(6.dp), horizontalArrangement = Arrangement.spacedBy(6.dp),
) { ) {
if (profileShowAvatar) { if (profileShowAvatar) {
if (!profileAvatarUrl.isNullOrBlank()) { Box(
val ctx = LocalContext.current Modifier.size(22.dp),
AsyncImage( contentAlignment = Alignment.Center,
model = ImageRequest.Builder(ctx) ) {
.data(profileAvatarUrl) // Emoji altijd als basis; custom foto eroverheen indien beschikbaar
.apply { if (profileAvatarEmoji != null) {
if (!profileAuthHeader.isNullOrBlank()) { Text(profileAvatarEmoji, fontSize = 15.sp)
addHeader("Authorization", profileAuthHeader) }
if (!profileAvatarUrl.isNullOrBlank()) {
val ctx = LocalContext.current
AsyncImage(
model = ImageRequest.Builder(ctx)
.data(profileAvatarUrl)
.apply {
if (!profileAuthHeader.isNullOrBlank()) {
addHeader("Authorization", profileAuthHeader)
}
} }
} .build(),
.build(), contentDescription = null,
contentDescription = null, modifier = Modifier
modifier = Modifier .size(22.dp)
.size(22.dp) .clip(RoundedCornerShape(50)),
.clip(RoundedCornerShape(50)), contentScale = ContentScale.Crop,
contentScale = ContentScale.Crop, )
) }
} else if (profileAvatarEmoji != null) {
Text(profileAvatarEmoji, fontSize = 15.sp)
} }
} }
if (!profileLabel.isNullOrBlank()) { if (!profileLabel.isNullOrBlank()) {