diff --git a/composeApp/src/commonMain/composeResources/values-es/strings.xml b/composeApp/src/commonMain/composeResources/values-es/strings.xml
index b52d5056..8cbc7328 100644
--- a/composeApp/src/commonMain/composeResources/values-es/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values-es/strings.xml
@@ -757,8 +757,8 @@
Esmeralda
Océano
Rosa
- Violeta
- Blanco
+ Amatista
+ Glaciar
Siguiente episodio
Buscando fuente…
Reproduciendo vía %1$s en %2$d…
diff --git a/composeApp/src/commonMain/composeResources/values-fr/strings.xml b/composeApp/src/commonMain/composeResources/values-fr/strings.xml
index 15b373b8..8911db91 100644
--- a/composeApp/src/commonMain/composeResources/values-fr/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values-fr/strings.xml
@@ -790,8 +790,8 @@
Émeraude
Océan
Rose
- Violet
- Blanc
+ Améthyste
+ Glacier
Épisode suivant
Recherche de la source…
Lecture via %1$s dans %2$d…
diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 3c21777b..aa4fcaf8 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -905,8 +905,8 @@
Emerald
Ocean
Rose
- Violet
- White
+ Amethyst
+ Glacier
Next Episode
Finding source…
Playing via %1$s in %2$d…
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/AppTheme.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/AppTheme.kt
index 081f1756..555a10b0 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/AppTheme.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/AppTheme.kt
@@ -13,20 +13,20 @@ import org.jetbrains.compose.resources.StringResource
enum class AppTheme {
CRIMSON,
OCEAN,
- VIOLET,
+ AMETHYST,
EMERALD,
AMBER,
ROSE,
- WHITE,
+ GLACIER,
}
val AppTheme.labelRes: StringResource
get() = when (this) {
AppTheme.CRIMSON -> Res.string.theme_crimson
AppTheme.OCEAN -> Res.string.theme_ocean
- AppTheme.VIOLET -> Res.string.theme_violet
+ AppTheme.AMETHYST -> Res.string.theme_violet
AppTheme.EMERALD -> Res.string.theme_emerald
AppTheme.AMBER -> Res.string.theme_amber
AppTheme.ROSE -> Res.string.theme_rose
- AppTheme.WHITE -> Res.string.theme_white
+ AppTheme.GLACIER -> Res.string.theme_white
}
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioTheme.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioTheme.kt
index d86a1a81..2e4bcab0 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioTheme.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioTheme.kt
@@ -25,7 +25,7 @@ import nuvio.composeapp.generated.resources.jetbrains_sans_regular
import nuvio.composeapp.generated.resources.jetbrains_sans_semibold
import org.jetbrains.compose.resources.Font
-val LocalAppTheme = staticCompositionLocalOf { AppTheme.WHITE }
+val LocalAppTheme = staticCompositionLocalOf { AppTheme.GLACIER }
val MaterialTheme.appTheme: AppTheme
@Composable
@@ -207,7 +207,7 @@ private val NuvioRippleConfiguration = RippleConfiguration(
@Composable
fun NuvioTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
- appTheme: AppTheme = AppTheme.WHITE,
+ appTheme: AppTheme = AppTheme.GLACIER,
amoled: Boolean = false,
content: @Composable () -> Unit,
) {
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ThemeColors.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ThemeColors.kt
index 5ee217bf..cc1555dc 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ThemeColors.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ThemeColors.kt
@@ -36,7 +36,7 @@ object ThemeColors {
backgroundCard = Color(0xFF1A1F24),
)
- val Violet = ThemeColorPalette(
+ val Amethyst = ThemeColorPalette(
secondary = Color(0xFF8E24AA),
secondaryVariant = Color(0xFF6A1B9A),
focusRing = Color(0xFFAB47BC),
@@ -76,7 +76,7 @@ object ThemeColors {
backgroundCard = Color(0xFF241A1F),
)
- val White = ThemeColorPalette(
+ val Glacier = ThemeColorPalette(
secondary = Color(0xFFF5F5F5),
secondaryVariant = Color(0xFFE0E0E0),
onSecondary = Color(0xFF111111),
@@ -91,10 +91,10 @@ object ThemeColors {
fun getColorPalette(theme: AppTheme): ThemeColorPalette = when (theme) {
AppTheme.CRIMSON -> Crimson
AppTheme.OCEAN -> Ocean
- AppTheme.VIOLET -> Violet
+ AppTheme.AMETHYST -> Amethyst
AppTheme.EMERALD -> Emerald
AppTheme.AMBER -> Amber
AppTheme.ROSE -> Rose
- AppTheme.WHITE -> White
+ AppTheme.GLACIER -> Glacier
}
}
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsModels.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsModels.kt
index 3ac52ded..6749ba42 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsModels.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsModels.kt
@@ -38,6 +38,17 @@ data class MetaDetails(
val videos: List = emptyList(),
)
+fun MetaDetails.toMetaPreview(): MetaPreview = MetaPreview(
+ id = id,
+ type = type,
+ name = name,
+ poster = poster,
+ banner = background,
+ logo = logo,
+ description = description,
+ releaseInfo = releaseInfo,
+)
+
data class MetaExternalRating(
val source: String,
val value: Double,
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt
index d8bfbf27..823c0da5 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt
@@ -93,6 +93,7 @@ import com.nuvio.app.features.trailer.TrailerPlaybackSource
import com.nuvio.app.features.watched.WatchedRepository
import com.nuvio.app.features.watched.previousReleasedEpisodesBefore
import com.nuvio.app.features.watched.releasedEpisodesForSeason
+import com.nuvio.app.features.watched.watchedItemKey
import com.nuvio.app.features.watchprogress.CurrentDateProvider
import com.nuvio.app.features.watchprogress.WatchProgressEntry
import com.nuvio.app.features.watchprogress.WatchProgressRepository
@@ -662,10 +663,12 @@ fun MetaDetailsScreen(
isTablet = isTablet,
playButtonLabel = playButtonLabel,
isSaved = isSaved,
+ isWatched = WatchingState.isPosterWatched(watchedUiState.watchedKeys, meta.type, meta.id),
onPrimaryPlayClick = onPrimaryPlayClick,
onPrimaryPlayLongClick = onPrimaryPlayLongClick,
onSaveClick = toggleSaved,
onSaveLongClick = openLibraryListPicker,
+ onWatchedClick = { WatchingActions.toggleMetaWatched(meta) },
showManualPlayOption = showManualPlayOption,
preferredEpisodeSeasonNumber = seriesAction?.seasonNumber,
preferredEpisodeNumber = seriesAction?.episodeNumber,
@@ -996,10 +999,12 @@ private fun ConfiguredMetaSections(
isTablet: Boolean,
playButtonLabel: String,
isSaved: Boolean,
+ isWatched: Boolean,
onPrimaryPlayClick: () -> Unit,
onPrimaryPlayLongClick: (() -> Unit)?,
onSaveClick: () -> Unit,
onSaveLongClick: (() -> Unit)?,
+ onWatchedClick: () -> Unit,
showManualPlayOption: Boolean,
preferredEpisodeSeasonNumber: Int?,
preferredEpisodeNumber: Int?,
@@ -1062,11 +1067,13 @@ private fun ConfiguredMetaSections(
stringResource(Res.string.action_save)
},
isSaved = isSaved,
+ isWatched = isWatched,
isTablet = isTablet,
onPlayClick = onPrimaryPlayClick,
onPlayLongClick = if (showManualPlayOption) onPrimaryPlayLongClick else null,
onSaveClick = onSaveClick,
onSaveLongClick = onSaveLongClick,
+ onWatchedClick = onWatchedClick,
)
}
MetaScreenSectionKey.OVERVIEW -> {
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt
index d5be0d59..5e43d842 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt
@@ -13,6 +13,8 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Visibility
+import androidx.compose.material3.IconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
@@ -37,11 +39,13 @@ fun DetailActionButtons(
playLabel: String = stringResource(Res.string.action_play),
saveLabel: String = stringResource(Res.string.action_save),
isSaved: Boolean = false,
+ isWatched: Boolean = false,
isTablet: Boolean = false,
onPlayClick: () -> Unit = {},
onPlayLongClick: (() -> Unit)? = null,
onSaveClick: () -> Unit = {},
onSaveLongClick: (() -> Unit)? = null,
+ onWatchedClick: () -> Unit = {},
) {
val playPainter = appIconPainter(AppIconResource.PlayerPlay)
val libraryAddPainter = appIconPainter(AppIconResource.LibraryAddPlus)
@@ -138,5 +142,21 @@ fun DetailActionButtons(
)
}
}
+
+ Surface(
+ modifier = Modifier.size(50.dp),
+ shape = RoundedCornerShape(40.dp),
+ border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline),
+ color = if (isWatched) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface.copy(alpha = 0f),
+ contentColor = if (isWatched) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface,
+ ) {
+ IconButton(onClick = onWatchedClick) {
+ Icon(
+ imageVector = Icons.Default.Visibility,
+ contentDescription = null,
+ modifier = Modifier.size(20.dp),
+ )
+ }
+ }
}
}
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSkeletonLoading.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSkeletonLoading.kt
index 3609fd00..b48b6098 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSkeletonLoading.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSkeletonLoading.kt
@@ -40,21 +40,23 @@ import com.nuvio.app.core.ui.rememberPosterCardStyleUiState
private fun rememberHomeSkeletonBrush(): Brush {
val shimmerColors = listOf(
MaterialTheme.colorScheme.surface,
- MaterialTheme.colorScheme.surface.copy(alpha = 0.5f),
+ MaterialTheme.colorScheme.surface,
+ MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
+ MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.surface,
)
val transition = rememberInfiniteTransition()
val translateAnim by transition.animateFloat(
initialValue = 0f,
- targetValue = 1000f,
+ targetValue = 1300f,
animationSpec = infiniteRepeatable(
- animation = tween(durationMillis = 1200, easing = LinearEasing),
+ animation = tween(durationMillis = 1500, easing = LinearEasing),
repeatMode = RepeatMode.Restart,
),
)
val brush = Brush.linearGradient(
colors = shimmerColors,
- start = Offset(translateAnim - 200f, 0f),
+ start = Offset(translateAnim - 600f, 0f),
end = Offset(translateAnim, 0f),
)
return brush
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 bc312982..f9c54f80 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
@@ -86,7 +86,7 @@ internal fun LazyListScope.appearanceSettingsContent(
isTablet = isTablet,
) {
SettingsGroup(isTablet = isTablet) {
- val themes = listOf(AppTheme.WHITE) + AppTheme.entries.filterNot { it == AppTheme.WHITE }
+ val themes = listOf(AppTheme.GLACIER) + AppTheme.entries.filterNot { it == AppTheme.GLACIER }
FlowRow(
modifier = Modifier
.fillMaxWidth()
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsRepository.kt
index 2f1221dd..be2db2cb 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsRepository.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/ThemeSettingsRepository.kt
@@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
object ThemeSettingsRepository {
- private val _selectedTheme = MutableStateFlow(AppTheme.WHITE)
+ private val _selectedTheme = MutableStateFlow(AppTheme.GLACIER)
val selectedTheme: StateFlow = _selectedTheme.asStateFlow()
private val _amoledEnabled = MutableStateFlow(false)
@@ -32,10 +32,10 @@ object ThemeSettingsRepository {
fun clearLocalState() {
hasLoaded = false
- _selectedTheme.value = AppTheme.WHITE
+ _selectedTheme.value = AppTheme.GLACIER
_amoledEnabled.value = false
_liquidGlassNativeTabBarEnabled.value = false
- NativeTabBridge.publishAccentColor(AppTheme.WHITE.nativeTabAccentHex())
+ NativeTabBridge.publishAccentColor(AppTheme.GLACIER.nativeTabAccentHex())
NativeTabBridge.publishLiquidGlassEnabled(false)
_selectedAppLanguage.value = AppLanguage.ENGLISH
}
@@ -45,12 +45,16 @@ object ThemeSettingsRepository {
val stored = ThemeSettingsStorage.loadSelectedTheme()
val theme = if (stored != null) {
try {
- AppTheme.valueOf(stored)
+ when (stored) {
+ "VIOLET" -> AppTheme.AMETHYST
+ "WHITE" -> AppTheme.GLACIER
+ else -> AppTheme.valueOf(stored)
+ }
} catch (_: IllegalArgumentException) {
- AppTheme.WHITE
+ AppTheme.GLACIER
}
} else {
- AppTheme.WHITE
+ AppTheme.GLACIER
}
_selectedTheme.value = theme
NativeTabBridge.publishAccentColor(theme.nativeTabAccentHex())
@@ -98,9 +102,9 @@ object ThemeSettingsRepository {
private fun AppTheme.nativeTabAccentHex(): String = when (this) {
AppTheme.CRIMSON -> "#E53935"
AppTheme.OCEAN -> "#1E88E5"
- AppTheme.VIOLET -> "#8E24AA"
+ AppTheme.AMETHYST -> "#8E24AA"
AppTheme.EMERALD -> "#43A047"
AppTheme.AMBER -> "#FB8C00"
AppTheme.ROSE -> "#D81B60"
- AppTheme.WHITE -> "#F5F5F5"
+ AppTheme.GLACIER -> "#F5F5F5"
}
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt
index 4a79954e..212394d5 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt
@@ -3,6 +3,7 @@ package com.nuvio.app.features.watching.application
import com.nuvio.app.features.details.MetaDetails
import com.nuvio.app.features.details.MetaDetailsRepository
import com.nuvio.app.features.details.MetaVideo
+import com.nuvio.app.features.details.toMetaPreview
import com.nuvio.app.features.home.MetaPreview
import com.nuvio.app.features.watched.WatchedItem
import com.nuvio.app.features.watched.WatchedRepository
@@ -22,6 +23,12 @@ import kotlinx.coroutines.launch
object WatchingActions {
private val actionScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
+ fun toggleMetaWatched(meta: MetaDetails) {
+ actionScope.launch {
+ togglePosterWatched(meta.toMetaPreview())
+ }
+ }
+
suspend fun togglePosterWatched(preview: MetaPreview) {
if (preview.type != "series") {
WatchedRepository.toggleWatched(preview.toWatchedItem(markedAtEpochMs = 0L))
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingState.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingState.kt
index c0f1474f..6dfd9f63 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingState.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingState.kt
@@ -18,7 +18,13 @@ object WatchingState {
fun isPosterWatched(
watchedKeys: Set,
item: MetaPreview,
- ): Boolean = watchedKeys.contains(watchedItemKey(item.type, item.id))
+ ): Boolean = isPosterWatched(watchedKeys, item.type, item.id)
+
+ fun isPosterWatched(
+ watchedKeys: Set,
+ type: String,
+ id: String,
+ ): Boolean = watchedKeys.contains(watchedItemKey(type, id))
fun isEpisodeWatched(
watchedKeys: Set,