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 {
val hasCustom = optBoolean("hasCustomAvatar")
val rawUrl = optString("avatarUrl").takeIf { it.isNotBlank() }
return ViewerProfile(
id = getString("id"), id = getString("id"),
name = optString("name"), name = optString("name"),
avatarId = optString("avatarId").ifBlank { "fox" }, avatarId = optString("avatarId").ifBlank { "fox" },
isOwner = optBoolean("isOwner"), isOwner = optBoolean("isOwner"),
isKids = optBoolean("isKids"), isKids = optBoolean("isKids"),
hasPin = optBoolean("hasPin"), hasPin = optBoolean("hasPin"),
showAvatar = if (has("showAvatar")) optBoolean("showAvatar") else true, showAvatar = when {
hasCustomAvatar = optBoolean("hasCustomAvatar"), !has("showAvatar") || isNull("showAvatar") -> true
avatarUrl = optString("avatarUrl").ifBlank { null }, else -> optBoolean("showAvatar", true)
},
hasCustomAvatar = hasCustom,
avatarUrl = if (hasCustom) rawUrl else null,
) )
}

View file

@ -86,13 +86,12 @@ 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
} }
} }
} }
}
suspend fun setApiBase(url: String) { suspend fun setApiBase(url: String) {
context.dataStore.edit { it[apiKey] = url.trim().trimEnd('/') } context.dataStore.edit { it[apiKey] = url.trim().trimEnd('/') }

View file

@ -1350,7 +1350,10 @@ private fun SettingsScreen(
.background(Color(0xFF2E2E3A)), .background(Color(0xFF2E2E3A)),
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
if (profileShowAvatar && !profileAvatarUrl.isNullOrBlank()) { if (profileShowAvatar) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(avatarEmoji(profileAvatarId ?: "fox"), fontSize = 22.sp)
if (!profileAvatarUrl.isNullOrBlank()) {
AsyncImage( AsyncImage(
model = ImageRequest.Builder(LocalContext.current) model = ImageRequest.Builder(LocalContext.current)
.data(profileAvatarUrl) .data(profileAvatarUrl)
@ -1364,8 +1367,15 @@ private fun SettingsScreen(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop, 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 {
val hasCustom = optBoolean("hasCustomAvatar")
val rawUrl = optString("avatarUrl").takeIf { it.isNotBlank() }
return ViewerProfile(
id = getString("id"), id = getString("id"),
name = optString("name"), name = optString("name"),
avatarId = optString("avatarId").ifBlank { "fox" }, avatarId = optString("avatarId").ifBlank { "fox" },
isOwner = optBoolean("isOwner"), isOwner = optBoolean("isOwner"),
isKids = optBoolean("isKids"), isKids = optBoolean("isKids"),
hasPin = optBoolean("hasPin"), hasPin = optBoolean("hasPin"),
showAvatar = if (has("showAvatar")) optBoolean("showAvatar") else true, showAvatar = when {
hasCustomAvatar = optBoolean("hasCustomAvatar"), !has("showAvatar") || isNull("showAvatar") -> true
avatarUrl = optString("avatarUrl").ifBlank { null }, else -> optBoolean("showAvatar", true)
},
hasCustomAvatar = hasCustom,
avatarUrl = if (hasCustom) rawUrl else null,
) )
}

View file

@ -105,13 +105,12 @@ 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
} }
} }
} }
}
suspend fun setApiBase(url: String) { suspend fun setApiBase(url: String) {
context.dataStore.edit { it[apiKey] = url.trim().trimEnd('/') } context.dataStore.edit { it[apiKey] = url.trim().trimEnd('/') }

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,
) { ) {
if (profileShowAvatar) {
Text( Text(
avatarEmoji(profileAvatarId ?: "fox"), avatarEmoji(profileAvatarId ?: "fox"),
fontSize = 30.sp, fontSize = 30.sp,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(), 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,6 +321,14 @@ fun TopNavBar(
horizontalArrangement = Arrangement.spacedBy(6.dp), horizontalArrangement = Arrangement.spacedBy(6.dp),
) { ) {
if (profileShowAvatar) { if (profileShowAvatar) {
Box(
Modifier.size(22.dp),
contentAlignment = Alignment.Center,
) {
// Emoji altijd als basis; custom foto eroverheen indien beschikbaar
if (profileAvatarEmoji != null) {
Text(profileAvatarEmoji, fontSize = 15.sp)
}
if (!profileAvatarUrl.isNullOrBlank()) { if (!profileAvatarUrl.isNullOrBlank()) {
val ctx = LocalContext.current val ctx = LocalContext.current
AsyncImage( AsyncImage(
@ -338,8 +346,7 @@ fun TopNavBar(
.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()) {