From 36052f99fcc36bca07d0e1f69b8186f344767db4 Mon Sep 17 00:00:00 2001 From: DynamycSound Date: Mon, 8 Jun 2026 04:32:04 +0000 Subject: [PATCH 1/3] fix(android): keep app language out of per-profile settings sync --- .../app/features/settings/ThemeSettingsStorage.android.kt | 4 ---- .../nuvio/app/features/settings/ThemeSettingsStorage.ios.kt | 6 ------ 2 files changed, 10 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.android.kt index e082a536..6a2e1584 100644 --- a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.android.kt +++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.android.kt @@ -24,7 +24,6 @@ actual object ThemeSettingsStorage { amoledEnabledKey, liquidGlassNativeTabBarEnabledKey, ) - private val globalSyncKeys = listOf(selectedAppLanguageKey) private var preferences: SharedPreferences? = null @@ -94,19 +93,16 @@ actual object ThemeSettingsStorage { loadSelectedTheme()?.let { put(selectedThemeKey, encodeSyncString(it)) } loadAmoledEnabled()?.let { put(amoledEnabledKey, encodeSyncBoolean(it)) } loadLiquidGlassNativeTabBarEnabled()?.let { put(liquidGlassNativeTabBarEnabledKey, encodeSyncBoolean(it)) } - loadSelectedAppLanguage()?.let { put(selectedAppLanguageKey, encodeSyncString(it)) } } actual fun replaceFromSyncPayload(payload: JsonObject) { preferences?.edit()?.apply { profileScopedSyncKeys.forEach { remove(ProfileScopedKey.of(it)) } - globalSyncKeys.forEach { remove(it) } }?.apply() payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme) payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled) payload.decodeSyncBoolean(liquidGlassNativeTabBarEnabledKey)?.let(::saveLiquidGlassNativeTabBarEnabled) - payload.decodeSyncString(selectedAppLanguageKey)?.let(::saveSelectedAppLanguage) applySelectedAppLanguage(loadSelectedAppLanguage() ?: AppLanguage.ENGLISH.code) } } diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.ios.kt index f66f8b8c..bf14a452 100644 --- a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.ios.kt +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsStorage.ios.kt @@ -20,7 +20,6 @@ actual object ThemeSettingsStorage { amoledEnabledKey, liquidGlassNativeTabBarEnabledKey, ) - private val globalSyncKeys = listOf(selectedAppLanguageKey) actual fun loadSelectedTheme(): String? = NSUserDefaults.standardUserDefaults.stringForKey(ProfileScopedKey.of(selectedThemeKey)) @@ -88,21 +87,16 @@ actual object ThemeSettingsStorage { loadSelectedTheme()?.let { put(selectedThemeKey, encodeSyncString(it)) } loadAmoledEnabled()?.let { put(amoledEnabledKey, encodeSyncBoolean(it)) } loadLiquidGlassNativeTabBarEnabled()?.let { put(liquidGlassNativeTabBarEnabledKey, encodeSyncBoolean(it)) } - loadSelectedAppLanguage()?.let { put(selectedAppLanguageKey, encodeSyncString(it)) } } actual fun replaceFromSyncPayload(payload: JsonObject) { profileScopedSyncKeys.forEach { key -> NSUserDefaults.standardUserDefaults.removeObjectForKey(ProfileScopedKey.of(key)) } - globalSyncKeys.forEach { key -> - NSUserDefaults.standardUserDefaults.removeObjectForKey(key) - } payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme) payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled) payload.decodeSyncBoolean(liquidGlassNativeTabBarEnabledKey)?.let(::saveLiquidGlassNativeTabBarEnabled) - payload.decodeSyncString(selectedAppLanguageKey)?.let(::saveSelectedAppLanguage) applySelectedAppLanguage(loadSelectedAppLanguage() ?: AppLanguage.ENGLISH.code) } } From b1bb101fc9f4e19f1ec520fdee9b5268965e9229 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Tue, 9 Jun 2026 02:04:11 +0530 Subject: [PATCH 2/3] Use Nuvio MPVKit submodule branch --- .gitmodules | 3 ++- MPVKit | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 00634e56..480f411b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "MPVKit"] path = MPVKit - url = https://github.com/tapframe/MPVNuvio.git + url = https://github.com/NuvioMedia/MPVKit.git + branch = Nuvio diff --git a/MPVKit b/MPVKit index 2e81303b..20afe97c 160000 --- a/MPVKit +++ b/MPVKit @@ -1 +1 @@ -Subproject commit 2e81303b74762424f4187c905d532a716c8e1ff5 +Subproject commit 20afe97c34e46fce08a3794e2afa64613ea62794 From ed2d29ffc546bfd4e82a4c88ca1f09459d6855b8 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:39:20 +0530 Subject: [PATCH 3/3] Fix appearance theme grid layout --- .../settings/AppearanceSettingsPage.kt | 108 ++++++++++++------ 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/AppearanceSettingsPage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/AppearanceSettingsPage.kt index abbf58e7..157bed8e 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/AppearanceSettingsPage.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/AppearanceSettingsPage.kt @@ -5,9 +5,9 @@ import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -38,6 +38,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.nuvio.app.core.ui.AppTheme import com.nuvio.app.core.ui.NuvioBottomSheetActionRow @@ -67,7 +68,6 @@ import org.jetbrains.compose.resources.stringResource import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState -@OptIn(ExperimentalLayoutApi::class) internal fun LazyListScope.appearanceSettingsContent( isTablet: Boolean, selectedTheme: AppTheme, @@ -89,28 +89,50 @@ internal fun LazyListScope.appearanceSettingsContent( ) { SettingsGroup(isTablet = isTablet) { val themes = listOf(AppTheme.WHITE) + AppTheme.entries.filterNot { it == AppTheme.WHITE } - FlowRow( + val horizontalPadding = if (isTablet) 20.dp else 16.dp + val verticalPadding = if (isTablet) 18.dp else 14.dp + val themeSpacing = if (isTablet) 16.dp else 12.dp + BoxWithConstraints( modifier = Modifier .fillMaxWidth() .padding( - horizontal = if (isTablet) 20.dp else 16.dp, - vertical = if (isTablet) 18.dp else 14.dp, + horizontal = horizontalPadding, + vertical = verticalPadding, ), - horizontalArrangement = Arrangement.spacedBy(if (isTablet) 16.dp else 12.dp), - verticalArrangement = Arrangement.spacedBy(if (isTablet) 16.dp else 12.dp), ) { - themes.forEach { theme -> - ThemeChip( - theme = theme, - isSelected = theme == selectedTheme, - onClick = { onThemeSelected(theme) }, - ) + val preferredColumns = if (isTablet) 4 else 3 + val minThemeCellWidth = if (isTablet) 92.dp else 78.dp + val themeColumns = ((maxWidth + themeSpacing) / (minThemeCellWidth + themeSpacing)) + .toInt() + .coerceAtLeast(1) + .coerceAtMost(preferredColumns) + + Column( + verticalArrangement = Arrangement.spacedBy(themeSpacing), + ) { + themes.chunked(themeColumns).forEach { rowThemes -> + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(themeSpacing), + ) { + rowThemes.forEach { theme -> + ThemeChip( + theme = theme, + isSelected = theme == selectedTheme, + onClick = { onThemeSelected(theme) }, + modifier = Modifier.weight(1f), + ) + } + repeat(themeColumns - rowThemes.size) { + Spacer(modifier = Modifier.weight(1f)) + } + } + } } } } } } - item { var showLanguageSheet by remember { mutableStateOf(false) } SettingsSection( @@ -262,41 +284,48 @@ private fun ThemeChip( theme: AppTheme, isSelected: Boolean, onClick: () -> Unit, + modifier: Modifier = Modifier, ) { val palette = ThemeColors.getColorPalette(theme) Column( - modifier = Modifier + modifier = modifier .clip(RoundedCornerShape(12.dp)) .clickable(onClick = onClick) - .then( - if (isSelected) { - Modifier.border( - width = 1.5.dp, - color = palette.focusRing, - shape = RoundedCornerShape(12.dp), - ) - } else { - Modifier - }, - ) - .padding(horizontal = 12.dp, vertical = 10.dp), + .padding(horizontal = 4.dp, vertical = 8.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { Box( modifier = Modifier - .size(44.dp) - .clip(CircleShape) - .background(palette.secondary), + .size(56.dp) + .then( + if (isSelected) { + Modifier.border( + width = 1.5.dp, + color = palette.focusRing, + shape = RoundedCornerShape(14.dp), + ) + } else { + Modifier + }, + ), contentAlignment = Alignment.Center, ) { - if (isSelected) { - Icon( - imageVector = Icons.Default.Check, - contentDescription = stringResource(Res.string.cd_selected), - tint = palette.onSecondary, - modifier = Modifier.size(22.dp), - ) + Box( + modifier = Modifier + .size(44.dp) + .clip(CircleShape) + .background(palette.secondary), + contentAlignment = Alignment.Center, + ) { + if (isSelected) { + Icon( + imageVector = Icons.Default.Check, + contentDescription = stringResource(Res.string.cd_selected), + tint = palette.onSecondary, + modifier = Modifier.size(22.dp), + ) + } } } @@ -312,6 +341,9 @@ private fun ThemeChip( }, fontWeight = if (isSelected) FontWeight.SemiBold else FontWeight.Medium, textAlign = TextAlign.Center, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.fillMaxWidth(), ) Spacer(modifier = Modifier.height(4.dp))