diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/AndroidSettingsDataSource.kt b/app/src/main/java/com/fluxa/app/ui/catalog/AndroidSettingsDataSource.kt index f5b1026..59070ec 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/AndroidSettingsDataSource.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/AndroidSettingsDataSource.kt @@ -124,11 +124,9 @@ class AndroidSettingsDataSource( avatarUrl = profile.avatarUrl, isGuest = profile.isGuest, hasTrakt = !profile.traktAccessToken.isNullOrBlank(), - hasMal = !profile.malAccessToken.isNullOrBlank(), hasSimkl = !profile.simklAccessToken.isNullOrBlank(), hasAnilist = !profile.anilistAccessToken.isNullOrBlank(), hasAnySync = !profile.traktAccessToken.isNullOrBlank() || - !profile.malAccessToken.isNullOrBlank() || !profile.simklAccessToken.isNullOrBlank() || !profile.anilistAccessToken.isNullOrBlank(), tmdbApiKey = profile.tmdbApiKey, @@ -442,8 +440,6 @@ class AndroidSettingsDataSource( it.copy( traktAccessToken = null, traktRefreshToken = null, - malAccessToken = null, - malRefreshToken = null, simklAccessToken = null, anilistAccessToken = null, anilistRefreshToken = null, diff --git a/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt b/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt index 7376fbd..13be6fe 100644 --- a/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt +++ b/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt @@ -201,6 +201,27 @@ internal fun AppRoutesHost( modifier = Modifier.size(22.dp) ) }, + traktIcon = { + androidx.compose.foundation.Image( + painter = androidx.compose.ui.res.painterResource(id = com.fluxa.app.R.drawable.ic_trakt), + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + }, + simklIcon = { + androidx.compose.foundation.Image( + painter = androidx.compose.ui.res.painterResource(id = com.fluxa.app.R.drawable.ic_simkl), + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + }, + anilistIcon = { + androidx.compose.foundation.Image( + painter = androidx.compose.ui.res.painterResource(id = com.fluxa.app.R.drawable.ic_anilist), + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + }, onSettingsBackRequested = navigateBackSafely, onManageAddonsRequested = { navigator.navigateTo(Screen.AddonStore) }, onConnectStremioRequested = { @@ -244,13 +265,6 @@ internal fun AppRoutesHost( connectTrakt(context, activeProfile, profileManager, homeViewModel, onActiveProfileChanged, onTraktDeviceAuthChanged) } }, - onConnectMalRequested = { - if (!activeProfile?.malAccessToken.isNullOrBlank()) { - onShowMalSheet() - } else { - connectMal(context, activeProfile, oauthPrefs, onPendingMalCodeVerifierChanged) - } - }, onConnectSimklRequested = { if (!activeProfile?.simklAccessToken.isNullOrBlank()) { onShowSimklSheet() diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt index 8672ead..148df0c 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt @@ -131,6 +131,7 @@ fun FluxaApp( onSettingsAction: (SettingsAction) -> Unit = {}, onSwitchProfilesRequested: () -> Unit = {}, onSettingsBackRequested: () -> Unit = {}, + settingsBrandIcons: com.fluxa.app.shared.feature.settings.SettingsBrandIcons = com.fluxa.app.shared.feature.settings.SettingsBrandIcons(), addonStoreState: AddonStoreUiState? = null, onAddonStoreAction: (AddonStoreAction) -> Unit = {}, onOpenUrlRequested: (String) -> Unit = {}, @@ -225,6 +226,7 @@ fun FluxaApp( onAction = onSettingsAction, onSwitchProfilesRequested = onSwitchProfilesRequested, onBackRequested = onSettingsBackRequested, + brandIcons = settingsBrandIcons, modifier = Modifier.weight(1f) ) state.destination == FluxaDestination.AddonStore && addonStoreState != null -> AddonStoreScreen( diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt index c816ba7..fade6f6 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt @@ -71,6 +71,9 @@ fun FluxaAppHost( authStartOnNuvio: Boolean = false, nuvioIcon: @Composable () -> Unit = {}, stremioIcon: @Composable () -> Unit = {}, + traktIcon: @Composable () -> Unit = {}, + simklIcon: @Composable () -> Unit = {}, + anilistIcon: @Composable () -> Unit = {}, biometricAvailable: Boolean = false, onPickAvatarRequested: (onPicked: (String?) -> Unit) -> Unit = {}, onBiometricAuthRequested: (ProfileUiModel, onResult: (Boolean) -> Unit) -> Unit = { _, _ -> }, @@ -78,7 +81,6 @@ fun FluxaAppHost( onConnectStremioRequested: () -> Unit = {}, onConnectNuvioRequested: () -> Unit = {}, onConnectTraktRequested: () -> Unit = {}, - onConnectMalRequested: () -> Unit = {}, onConnectSimklRequested: () -> Unit = {}, onConnectAnilistRequested: () -> Unit = {}, onCheckForUpdateRequested: () -> Unit = {}, @@ -109,6 +111,9 @@ fun FluxaAppHost( authStartOnNuvio = authStartOnNuvio, nuvioIcon = nuvioIcon, stremioIcon = stremioIcon, + traktIcon = traktIcon, + simklIcon = simklIcon, + anilistIcon = anilistIcon, biometricAvailable = biometricAvailable, onPickAvatarRequested = onPickAvatarRequested, onBiometricAuthRequested = onBiometricAuthRequested, @@ -116,7 +121,6 @@ fun FluxaAppHost( onConnectStremioRequested = onConnectStremioRequested, onConnectNuvioRequested = onConnectNuvioRequested, onConnectTraktRequested = onConnectTraktRequested, - onConnectMalRequested = onConnectMalRequested, onConnectSimklRequested = onConnectSimklRequested, onConnectAnilistRequested = onConnectAnilistRequested, onCheckForUpdateRequested = onCheckForUpdateRequested, @@ -150,6 +154,9 @@ fun FluxaAppHost( authStartOnNuvio: Boolean = false, nuvioIcon: @Composable () -> Unit = {}, stremioIcon: @Composable () -> Unit = {}, + traktIcon: @Composable () -> Unit = {}, + simklIcon: @Composable () -> Unit = {}, + anilistIcon: @Composable () -> Unit = {}, biometricAvailable: Boolean = false, onPickAvatarRequested: (onPicked: (String?) -> Unit) -> Unit = {}, onBiometricAuthRequested: (ProfileUiModel, onResult: (Boolean) -> Unit) -> Unit = { _, _ -> }, @@ -157,7 +164,6 @@ fun FluxaAppHost( onConnectStremioRequested: () -> Unit = {}, onConnectNuvioRequested: () -> Unit = {}, onConnectTraktRequested: () -> Unit = {}, - onConnectMalRequested: () -> Unit = {}, onConnectSimklRequested: () -> Unit = {}, onConnectAnilistRequested: () -> Unit = {}, onCheckForUpdateRequested: () -> Unit = {}, @@ -342,7 +348,6 @@ fun FluxaAppHost( SettingsAction.ConnectStremioRequested -> onConnectStremioRequested() SettingsAction.ConnectNuvioRequested -> onConnectNuvioRequested() SettingsAction.ConnectTraktRequested -> onConnectTraktRequested() - SettingsAction.ConnectMalRequested -> onConnectMalRequested() SettingsAction.ConnectSimklRequested -> onConnectSimklRequested() SettingsAction.ConnectAnilistRequested -> onConnectAnilistRequested() SettingsAction.CheckForUpdateRequested -> onCheckForUpdateRequested() @@ -352,6 +357,13 @@ fun FluxaAppHost( }, onSwitchProfilesRequested = { appState.selectDestination(FluxaDestination.ProfileList) }, onSettingsBackRequested = onSettingsBackRequested, + settingsBrandIcons = com.fluxa.app.shared.feature.settings.SettingsBrandIcons( + stremio = stremioIcon, + nuvio = nuvioIcon, + trakt = traktIcon, + simkl = simklIcon, + anilist = anilistIcon + ), addonStoreState = addonStoreState, onAddonStoreAction = { action -> scope.launch { diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsContracts.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsContracts.kt index c6c9ea6..a9a764c 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsContracts.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsContracts.kt @@ -12,7 +12,6 @@ data class SettingsAccountUiModel( val avatarUrl: String? = null, val isGuest: Boolean = true, val hasTrakt: Boolean = false, - val hasMal: Boolean = false, val hasSimkl: Boolean = false, val hasAnilist: Boolean = false, val hasAnySync: Boolean = false, @@ -205,7 +204,6 @@ sealed interface SettingsAction { data object ConnectStremioRequested : SettingsAction data object ConnectNuvioRequested : SettingsAction data object ConnectTraktRequested : SettingsAction - data object ConnectMalRequested : SettingsAction data object ConnectSimklRequested : SettingsAction data object ConnectAnilistRequested : SettingsAction data object DisconnectSyncRequested : SettingsAction diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsRows.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsRows.kt index 1a4aec8..64e323a 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsRows.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsRows.kt @@ -267,6 +267,7 @@ fun SettingsActionRow( label: String, value: String? = null, destructive: Boolean = false, + icon: (@Composable () -> Unit)? = null, onClick: () -> Unit ) { Row( @@ -274,7 +275,21 @@ fun SettingsActionRow( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text(label, color = if (destructive) FluxaColors.errorRed else Color.White, fontWeight = FontWeight.Medium) + Row(verticalAlignment = Alignment.CenterVertically) { + if (icon != null) { + Box( + modifier = Modifier + .size(32.dp) + .clip(RoundedCornerShape(9.dp)) + .background(Color.White.copy(alpha = 0.08f)), + contentAlignment = Alignment.Center + ) { + icon() + } + Spacer(Modifier.width(14.dp)) + } + Text(label, color = if (destructive) FluxaColors.errorRed else Color.White, fontWeight = FontWeight.Medium) + } if (value != null) { Text(value, color = Color.White.copy(alpha = 0.5f), fontSize = 13.sp) } diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsScreen.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsScreen.kt index d6087f2..1d47018 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsScreen.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsScreen.kt @@ -21,7 +21,7 @@ import androidx.compose.material.icons.filled.AccountCircle import androidx.compose.material.icons.filled.Code import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Extension -import androidx.compose.material.icons.filled.MenuBook +import androidx.compose.material.icons.filled.LibraryBooks import androidx.compose.material.icons.filled.Palette import androidx.compose.material.icons.filled.PlayCircle import androidx.compose.material.icons.filled.Tune @@ -41,6 +41,14 @@ import androidx.compose.ui.unit.sp import com.fluxa.app.common.AppStrings import com.fluxa.app.ui.catalog.FluxaColors +data class SettingsBrandIcons( + val stremio: @Composable () -> Unit = {}, + val nuvio: @Composable () -> Unit = {}, + val trakt: @Composable () -> Unit = {}, + val simkl: @Composable () -> Unit = {}, + val anilist: @Composable () -> Unit = {} +) + @Composable fun SettingsScreen( state: SettingsUiState, @@ -48,6 +56,7 @@ fun SettingsScreen( onAction: (SettingsAction) -> Unit, onSwitchProfilesRequested: () -> Unit, onBackRequested: () -> Unit, + brandIcons: SettingsBrandIcons = SettingsBrandIcons(), modifier: Modifier = Modifier ) { var category by remember { mutableStateOf(SettingsCategory.Hub) } @@ -68,7 +77,7 @@ fun SettingsScreen( onSwitchProfiles = onSwitchProfilesRequested, onAction = onAction ) - SettingsCategory.Account -> SettingsAccountContent(state.account, lang, onAction) + SettingsCategory.Account -> SettingsAccountContent(state.account, lang, brandIcons, onAction) SettingsCategory.General -> SettingsGeneralContent(state.general, lang, onAction) SettingsCategory.Appearance -> SettingsAppearanceContent(state.appearance, lang, onAction, onNavigate = { category = it }) SettingsCategory.AppearanceHome -> SettingsAppearanceHomeContent(state.appearanceHome, lang, onAction) @@ -149,7 +158,7 @@ private fun SettingsHubContent( SettingsNavRow(AppStrings.t(lang, "auto.playback"), icon = Icons.Filled.PlayCircle) { onNavigate(SettingsCategory.Playback) } SettingsSectionHeader(AppStrings.t(lang, "settings.section_content")) - SettingsNavRow(AppStrings.t(lang, "auto.catalogs"), icon = Icons.Filled.MenuBook) { onNavigate(SettingsCategory.Content) } + SettingsNavRow(AppStrings.t(lang, "auto.catalogs"), icon = Icons.Filled.LibraryBooks) { onNavigate(SettingsCategory.Content) } SettingsNavRow(AppStrings.t(lang, "auto.add_ons"), icon = Icons.Filled.Extension) { onNavigate(SettingsCategory.Addons) } SettingsNavRow(AppStrings.t(lang, "auto.downloads"), icon = Icons.Filled.Download) { onNavigate(SettingsCategory.Downloads) } @@ -168,24 +177,29 @@ private fun SettingsHubContent( } @Composable -private fun SettingsAccountContent(model: SettingsAccountUiModel, lang: String?, onAction: (SettingsAction) -> Unit) { +private fun SettingsAccountContent(model: SettingsAccountUiModel, lang: String?, brandIcons: SettingsBrandIcons, onAction: (SettingsAction) -> Unit) { SettingsSectionHeader(AppStrings.t(lang, "auto.account_sync")) - SettingsActionRow(AppStrings.t(lang, "brand.stremio"), value = if (!model.isGuest) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected")) { - onAction(SettingsAction.ConnectStremioRequested) - } - SettingsActionRow(AppStrings.t(lang, "brand.nuvio")) { onAction(SettingsAction.ConnectNuvioRequested) } - SettingsActionRow(AppStrings.t(lang, "brand.trakt"), value = if (model.hasTrakt) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected")) { - onAction(SettingsAction.ConnectTraktRequested) - } - SettingsActionRow(AppStrings.t(lang, "brand.myanimelist"), value = if (model.hasMal) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected")) { - onAction(SettingsAction.ConnectMalRequested) - } - SettingsActionRow(AppStrings.t(lang, "brand.simkl"), value = if (model.hasSimkl) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected")) { - onAction(SettingsAction.ConnectSimklRequested) - } - SettingsActionRow(AppStrings.t(lang, "brand.anilist"), value = if (model.hasAnilist) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected")) { - onAction(SettingsAction.ConnectAnilistRequested) - } + SettingsActionRow( + AppStrings.t(lang, "brand.stremio"), + value = if (!model.isGuest) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected"), + icon = brandIcons.stremio + ) { onAction(SettingsAction.ConnectStremioRequested) } + SettingsActionRow(AppStrings.t(lang, "brand.nuvio"), icon = brandIcons.nuvio) { onAction(SettingsAction.ConnectNuvioRequested) } + SettingsActionRow( + AppStrings.t(lang, "brand.trakt"), + value = if (model.hasTrakt) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected"), + icon = brandIcons.trakt + ) { onAction(SettingsAction.ConnectTraktRequested) } + SettingsActionRow( + AppStrings.t(lang, "brand.simkl"), + value = if (model.hasSimkl) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected"), + icon = brandIcons.simkl + ) { onAction(SettingsAction.ConnectSimklRequested) } + SettingsActionRow( + AppStrings.t(lang, "brand.anilist"), + value = if (model.hasAnilist) AppStrings.t(lang, "auto.connected") else AppStrings.t(lang, "auto.not_connected"), + icon = brandIcons.anilist + ) { onAction(SettingsAction.ConnectAnilistRequested) } if (model.hasAnySync) { SettingsActionRow(AppStrings.t(lang, "auto.disconnect"), destructive = true) { onAction(SettingsAction.DisconnectSyncRequested) } } diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsStore.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsStore.kt index 7ee7e84..31e4d41 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsStore.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/feature/settings/SettingsStore.kt @@ -37,7 +37,6 @@ class SettingsStore( SettingsAction.ConnectStremioRequested -> Unit SettingsAction.ConnectNuvioRequested -> Unit SettingsAction.ConnectTraktRequested -> Unit - SettingsAction.ConnectMalRequested -> Unit SettingsAction.ConnectSimklRequested -> Unit SettingsAction.ConnectAnilistRequested -> Unit SettingsAction.DisconnectSyncRequested -> dataSource.disconnectSync()