mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 23:12:12 +00:00
Merge branch 'cmp-rewrite' of https://github.com/NuvioMedia/NuvioMobile into cmp-rewrite
This commit is contained in:
commit
46a82dce9a
14 changed files with 1487 additions and 4 deletions
|
|
@ -260,6 +260,7 @@ kotlin {
|
|||
commonMain.dependencies {
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.coil.network.ktor3)
|
||||
implementation(libs.coil.svg)
|
||||
implementation("dev.chrisbanes.haze:haze:1.7.2")
|
||||
implementation(libs.compose.runtime)
|
||||
implementation(libs.compose.foundation)
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@
|
|||
<locale android:name="el"/>
|
||||
<locale android:name="pl"/>
|
||||
<locale android:name="de"/>
|
||||
<locale android:name="cs"/>
|
||||
</locale-config>
|
||||
|
|
|
|||
1245
composeApp/src/commonMain/composeResources/values-cs/strings.xml
Normal file
1245
composeApp/src/commonMain/composeResources/values-cs/strings.xml
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -541,6 +541,12 @@
|
|||
<string name="settings_continue_watching_blur_next_up_title">Blur Unwatched in Continue Watching</string>
|
||||
<string name="settings_continue_watching_show_unaired_next_up_description">Include upcoming episodes in Continue Watching before they air.</string>
|
||||
<string name="settings_continue_watching_show_unaired_next_up_title">Show Unaired Next Up Episodes</string>
|
||||
<string name="settings_continue_watching_section_sort_order">SORT ORDER</string>
|
||||
<string name="settings_continue_watching_sort_mode_title">Sort Order</string>
|
||||
<string name="settings_continue_watching_sort_mode_default">Default</string>
|
||||
<string name="settings_continue_watching_sort_mode_default_desc">Sort all items by recency</string>
|
||||
<string name="settings_continue_watching_sort_mode_streaming">Streaming Style</string>
|
||||
<string name="settings_continue_watching_sort_mode_streaming_desc">Released items first, upcoming at the end</string>
|
||||
<string name="settings_continue_watching_section_card_style">Poster Card Style</string>
|
||||
<string name="settings_continue_watching_section_on_launch">ON LAUNCH</string>
|
||||
<string name="settings_continue_watching_section_up_next_behavior">UP NEXT BEHAVIOR</string>
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ import coil3.ImageLoader
|
|||
import coil3.compose.setSingletonImageLoaderFactory
|
||||
import coil3.request.CachePolicy
|
||||
import coil3.request.crossfade
|
||||
import coil3.svg.SvgDecoder
|
||||
import com.nuvio.app.core.build.AppFeaturePolicy
|
||||
import com.nuvio.app.core.auth.AuthRepository
|
||||
import com.nuvio.app.core.auth.AuthState
|
||||
|
|
@ -304,6 +305,9 @@ fun App() {
|
|||
.crossfade(true)
|
||||
.diskCachePolicy(CachePolicy.ENABLED)
|
||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.components {
|
||||
add(SvgDecoder.Factory())
|
||||
}
|
||||
.configurePlatformImageLoader()
|
||||
.build()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import com.nuvio.app.features.watchprogress.ContinueWatchingEnrichmentCache
|
|||
import com.nuvio.app.features.watchprogress.CurrentDateProvider
|
||||
import com.nuvio.app.features.watchprogress.ContinueWatchingPreferencesRepository
|
||||
import com.nuvio.app.features.watchprogress.ContinueWatchingItem
|
||||
import com.nuvio.app.features.watchprogress.ContinueWatchingSortMode
|
||||
import com.nuvio.app.features.watchprogress.isSeriesTypeForContinueWatching
|
||||
import com.nuvio.app.features.watchprogress.nextUpDismissKey
|
||||
import com.nuvio.app.features.watchprogress.WatchProgressClock
|
||||
|
|
@ -247,11 +248,14 @@ fun HomeScreen(
|
|||
visibleContinueWatchingEntries,
|
||||
cachedInProgressItems,
|
||||
effectivNextUpItems,
|
||||
continueWatchingPreferences.sortMode,
|
||||
) {
|
||||
buildHomeContinueWatchingItems(
|
||||
visibleEntries = visibleContinueWatchingEntries,
|
||||
cachedInProgressByVideoId = cachedInProgressItems,
|
||||
nextUpItemsBySeries = effectivNextUpItems,
|
||||
sortMode = continueWatchingPreferences.sortMode,
|
||||
todayIsoDate = CurrentDateProvider.todayIsoDate(),
|
||||
)
|
||||
}
|
||||
val availableManifests = remember(addonsUiState.addons) {
|
||||
|
|
@ -639,6 +643,8 @@ internal fun buildHomeContinueWatchingItems(
|
|||
visibleEntries: List<WatchProgressEntry>,
|
||||
cachedInProgressByVideoId: Map<String, ContinueWatchingItem> = emptyMap(),
|
||||
nextUpItemsBySeries: Map<String, Pair<Long, ContinueWatchingItem>>,
|
||||
sortMode: ContinueWatchingSortMode = ContinueWatchingSortMode.DEFAULT,
|
||||
todayIsoDate: String = "",
|
||||
): List<ContinueWatchingItem> {
|
||||
val inProgressSeriesIds = visibleEntries
|
||||
.asSequence()
|
||||
|
|
@ -647,7 +653,7 @@ internal fun buildHomeContinueWatchingItems(
|
|||
.filter(String::isNotBlank)
|
||||
.toSet()
|
||||
|
||||
return buildList {
|
||||
val candidates = buildList {
|
||||
addAll(
|
||||
visibleEntries.map { entry ->
|
||||
val liveItem = entry.toContinueWatchingItem()
|
||||
|
|
@ -669,13 +675,62 @@ internal fun buildHomeContinueWatchingItems(
|
|||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Deduplicate by series/content id first (order-stable)
|
||||
val seen = mutableSetOf<String>()
|
||||
val deduplicated = candidates
|
||||
.sortedWith(
|
||||
compareByDescending<HomeContinueWatchingCandidate> { it.lastUpdatedEpochMs }
|
||||
.thenByDescending { it.isProgressEntry },
|
||||
)
|
||||
.filter { candidate -> candidate.item.shouldDisplayInContinueWatching() }
|
||||
.distinctBy { candidate -> candidate.item.parentMetaId.ifBlank { candidate.item.videoId } }
|
||||
.filter { candidate ->
|
||||
val key = candidate.item.parentMetaId.ifBlank { candidate.item.videoId }
|
||||
seen.add(key)
|
||||
}
|
||||
|
||||
return when (sortMode) {
|
||||
ContinueWatchingSortMode.DEFAULT -> deduplicated.map(HomeContinueWatchingCandidate::item)
|
||||
ContinueWatchingSortMode.STREAMING_STYLE -> applyStreamingStyleSort(deduplicated, todayIsoDate)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyStreamingStyleSort(
|
||||
candidates: List<HomeContinueWatchingCandidate>,
|
||||
todayIsoDate: String,
|
||||
): List<ContinueWatchingItem> {
|
||||
val (released, unreleased) = candidates.partition { candidate ->
|
||||
val item = candidate.item
|
||||
if (!item.isNextUp) {
|
||||
true // in-progress items are always "released"
|
||||
} else {
|
||||
val itemReleased = item.released
|
||||
if (itemReleased.isNullOrBlank() || todayIsoDate.isBlank()) {
|
||||
true // no date info → treat as released
|
||||
} else {
|
||||
isReleasedBy(todayIsoDate = todayIsoDate, releasedDate = itemReleased)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Released: most recently watched first (already sorted by dedup pass)
|
||||
val sortedReleased = released.map(HomeContinueWatchingCandidate::item)
|
||||
|
||||
// Unaired: soonest air date first; unknown dates go to the end
|
||||
val sortedUnreleased = unreleased
|
||||
.sortedWith { a, b ->
|
||||
val dateA = a.item.released?.takeIf { it.isNotBlank() }
|
||||
val dateB = b.item.released?.takeIf { it.isNotBlank() }
|
||||
when {
|
||||
dateA == null && dateB == null -> 0
|
||||
dateA == null -> 1
|
||||
dateB == null -> -1
|
||||
else -> dateA.compareTo(dateB)
|
||||
}
|
||||
}
|
||||
.map(HomeContinueWatchingCandidate::item)
|
||||
|
||||
return sortedReleased + sortedUnreleased
|
||||
}
|
||||
|
||||
private data class CompletedSeriesCandidate(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import nuvio.composeapp.generated.resources.lang_turkish
|
|||
import nuvio.composeapp.generated.resources.lang_italian
|
||||
import nuvio.composeapp.generated.resources.lang_greek
|
||||
import nuvio.composeapp.generated.resources.lang_polish
|
||||
import nuvio.composeapp.generated.resources.lang_czech
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
enum class AppLanguage(
|
||||
|
|
@ -25,6 +26,7 @@ enum class AppLanguage(
|
|||
ITALIAN("it", Res.string.lang_italian),
|
||||
GREEK("el", Res.string.lang_greek),
|
||||
POLISH("pl", Res.string.lang_polish),
|
||||
CZECH("cs", Res.string.lang_czech),
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -5,18 +5,27 @@ import androidx.compose.foundation.layout.Arrangement
|
|||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Check
|
||||
import androidx.compose.material.icons.rounded.CheckCircle
|
||||
import androidx.compose.material3.BasicAlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
|
|
@ -25,6 +34,7 @@ import androidx.compose.ui.unit.dp
|
|||
import com.nuvio.app.features.home.components.ContinueWatchingStylePreview
|
||||
import com.nuvio.app.features.watchprogress.ContinueWatchingPreferencesRepository
|
||||
import com.nuvio.app.features.watchprogress.ContinueWatchingSectionStyle
|
||||
import com.nuvio.app.features.watchprogress.ContinueWatchingSortMode
|
||||
import nuvio.composeapp.generated.resources.Res
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_resume_prompt_description
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_resume_prompt_title
|
||||
|
|
@ -34,10 +44,16 @@ import nuvio.composeapp.generated.resources.settings_continue_watching_show_unai
|
|||
import nuvio.composeapp.generated.resources.settings_continue_watching_show_unaired_next_up_title
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_section_card_style
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_section_on_launch
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_section_sort_order
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_section_up_next_behavior
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_section_visibility
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_show_description
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_show_title
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_sort_mode_default
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_sort_mode_default_desc
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_sort_mode_streaming
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_sort_mode_streaming_desc
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_sort_mode_title
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_style_poster
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_style_poster_description
|
||||
import nuvio.composeapp.generated.resources.settings_continue_watching_style_wide
|
||||
|
|
@ -58,6 +74,7 @@ internal fun LazyListScope.continueWatchingSettingsContent(
|
|||
showUnairedNextUp: Boolean,
|
||||
blurNextUp: Boolean,
|
||||
showResumePromptOnLaunch: Boolean,
|
||||
sortMode: ContinueWatchingSortMode,
|
||||
) {
|
||||
item {
|
||||
SettingsSection(
|
||||
|
|
@ -145,6 +162,39 @@ internal fun LazyListScope.continueWatchingSettingsContent(
|
|||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
var showSortModeSheet by remember { mutableStateOf(false) }
|
||||
SettingsSection(
|
||||
title = stringResource(Res.string.settings_continue_watching_section_sort_order),
|
||||
isTablet = isTablet,
|
||||
) {
|
||||
SettingsGroup(isTablet = isTablet) {
|
||||
val currentModeLabel = stringResource(
|
||||
when (sortMode) {
|
||||
ContinueWatchingSortMode.DEFAULT -> Res.string.settings_continue_watching_sort_mode_default
|
||||
ContinueWatchingSortMode.STREAMING_STYLE -> Res.string.settings_continue_watching_sort_mode_streaming
|
||||
}
|
||||
)
|
||||
SettingsNavigationRow(
|
||||
title = stringResource(Res.string.settings_continue_watching_sort_mode_title),
|
||||
description = currentModeLabel,
|
||||
isTablet = isTablet,
|
||||
onClick = { showSortModeSheet = true },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showSortModeSheet) {
|
||||
ContinueWatchingSortModeDialog(
|
||||
currentMode = sortMode,
|
||||
onModeSelected = { mode ->
|
||||
ContinueWatchingPreferencesRepository.setSortMode(mode)
|
||||
showSortModeSheet = false
|
||||
},
|
||||
onDismiss = { showSortModeSheet = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -250,3 +300,101 @@ private val ContinueWatchingSectionStyle.descriptionRes: StringResource
|
|||
ContinueWatchingSectionStyle.Wide -> Res.string.settings_continue_watching_style_wide_description
|
||||
ContinueWatchingSectionStyle.Poster -> Res.string.settings_continue_watching_style_poster_description
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ContinueWatchingSortModeDialog(
|
||||
currentMode: ContinueWatchingSortMode,
|
||||
onModeSelected: (ContinueWatchingSortMode) -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val options = listOf(
|
||||
Triple(
|
||||
ContinueWatchingSortMode.DEFAULT,
|
||||
Res.string.settings_continue_watching_sort_mode_default,
|
||||
Res.string.settings_continue_watching_sort_mode_default_desc,
|
||||
),
|
||||
Triple(
|
||||
ContinueWatchingSortMode.STREAMING_STYLE,
|
||||
Res.string.settings_continue_watching_sort_mode_streaming,
|
||||
Res.string.settings_continue_watching_sort_mode_streaming_desc,
|
||||
),
|
||||
)
|
||||
|
||||
BasicAlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(20.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(Res.string.settings_continue_watching_sort_mode_title),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
options.forEach { (mode, titleRes, descriptionRes) ->
|
||||
val isSelected = mode == currentMode
|
||||
val containerColor = if (isSelected) {
|
||||
MaterialTheme.colorScheme.primary.copy(alpha = 0.14f)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.35f)
|
||||
}
|
||||
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onModeSelected(mode) },
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = containerColor,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 14.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = stringResource(titleRes),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(
|
||||
text = stringResource(descriptionRes),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.size(24.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (isSelected) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Check,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ fun ContinueWatchingSettingsScreen(
|
|||
showUnairedNextUp = continueWatchingPreferencesUiState.showUnairedNextUp,
|
||||
blurNextUp = continueWatchingPreferencesUiState.blurNextUp,
|
||||
showResumePromptOnLaunch = continueWatchingPreferencesUiState.showResumePromptOnLaunch,
|
||||
sortMode = continueWatchingPreferencesUiState.sortMode,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -509,6 +509,7 @@ private fun MobileSettingsScreen(
|
|||
showUnairedNextUp = continueWatchingPreferencesUiState.showUnairedNextUp,
|
||||
blurNextUp = continueWatchingPreferencesUiState.blurNextUp,
|
||||
showResumePromptOnLaunch = continueWatchingPreferencesUiState.showResumePromptOnLaunch,
|
||||
sortMode = continueWatchingPreferencesUiState.sortMode,
|
||||
)
|
||||
SettingsPage.PosterCustomization -> posterCustomizationSettingsContent(
|
||||
isTablet = false,
|
||||
|
|
@ -866,6 +867,7 @@ private fun TabletSettingsScreen(
|
|||
showUnairedNextUp = continueWatchingPreferencesUiState.showUnairedNextUp,
|
||||
blurNextUp = continueWatchingPreferencesUiState.blurNextUp,
|
||||
showResumePromptOnLaunch = continueWatchingPreferencesUiState.showResumePromptOnLaunch,
|
||||
sortMode = continueWatchingPreferencesUiState.sortMode,
|
||||
)
|
||||
SettingsPage.PosterCustomization -> posterCustomizationSettingsContent(
|
||||
isTablet = true,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ private const val COMMENTS_SORT = "likes"
|
|||
private const val COMMENTS_LIMIT = 100
|
||||
private const val COMMENTS_CACHE_TTL_MS = 10 * 60_000L
|
||||
private val INLINE_SPOILER_REGEX = Regex(
|
||||
"\\[spoiler\\].*?\\[/spoiler\\]",
|
||||
setOf(RegexOption.IGNORE_CASE, RegexOption.DOT_MATCHES_ALL),
|
||||
"(?is)\\[spoiler\\].*?\\[/spoiler\\]"
|
||||
)
|
||||
private val INLINE_SPOILER_TAG_REGEX = Regex("\\[/?spoiler\\]", RegexOption.IGNORE_CASE)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ private data class StoredContinueWatchingPreferences(
|
|||
val blurNextUp: Boolean = false,
|
||||
val dismissedNextUpKeys: Set<String> = emptySet(),
|
||||
val showResumePromptOnLaunch: Boolean = true,
|
||||
@SerialName("sort_mode")
|
||||
val sortMode: ContinueWatchingSortMode = ContinueWatchingSortMode.DEFAULT,
|
||||
)
|
||||
|
||||
object ContinueWatchingPreferencesRepository {
|
||||
|
|
@ -97,6 +99,7 @@ object ContinueWatchingPreferencesRepository {
|
|||
blurNextUp = stored.blurNextUp,
|
||||
dismissedNextUpKeys = stored.dismissedNextUpKeys,
|
||||
showResumePromptOnLaunch = stored.showResumePromptOnLaunch,
|
||||
sortMode = stored.sortMode,
|
||||
)
|
||||
} else {
|
||||
ContinueWatchingPreferencesUiState()
|
||||
|
|
@ -155,6 +158,13 @@ object ContinueWatchingPreferencesRepository {
|
|||
persist()
|
||||
}
|
||||
|
||||
fun setSortMode(mode: ContinueWatchingSortMode) {
|
||||
ensureLoaded()
|
||||
if (_uiState.value.sortMode == mode) return
|
||||
_uiState.value = _uiState.value.copy(sortMode = mode)
|
||||
persist()
|
||||
}
|
||||
|
||||
fun removeDismissedNextUpKeysForContent(contentId: String) {
|
||||
ensureLoaded()
|
||||
val normalizedContentId = contentId.trim()
|
||||
|
|
@ -178,6 +188,7 @@ object ContinueWatchingPreferencesRepository {
|
|||
blurNextUp = _uiState.value.blurNextUp,
|
||||
dismissedNextUpKeys = _uiState.value.dismissedNextUpKeys,
|
||||
showResumePromptOnLaunch = _uiState.value.showResumePromptOnLaunch,
|
||||
sortMode = _uiState.value.sortMode,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ enum class ContinueWatchingSectionStyle {
|
|||
Poster,
|
||||
}
|
||||
|
||||
@Serializable
|
||||
enum class ContinueWatchingSortMode {
|
||||
DEFAULT,
|
||||
STREAMING_STYLE,
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class WatchProgressEntry(
|
||||
val contentType: String,
|
||||
|
|
@ -175,6 +181,7 @@ data class ContinueWatchingPreferencesUiState(
|
|||
val blurNextUp: Boolean = false,
|
||||
val dismissedNextUpKeys: Set<String> = emptySet(),
|
||||
val showResumePromptOnLaunch: Boolean = true,
|
||||
val sortMode: ContinueWatchingSortMode = ContinueWatchingSortMode.DEFAULT,
|
||||
)
|
||||
|
||||
internal fun nextUpDismissKey(
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ compose-uiToolingPreview = { module = "org.jetbrains.compose.ui:ui-tooling-previ
|
|||
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
|
||||
coil-gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" }
|
||||
coil-network-ktor3 = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref = "coil" }
|
||||
coil-svg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" }
|
||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
|
||||
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktor" }
|
||||
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
|
||||
|
|
|
|||
Loading…
Reference in a new issue