Merge branch 'NuvioMedia:cmp-rewrite' into introdb

This commit is contained in:
paregi12 2026-05-02 15:55:17 +05:30 committed by GitHub
commit b0f2767925
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 153 additions and 134 deletions

View file

@ -223,7 +223,6 @@ fun PlayerScreen(
activeEpisodeNumber, activeEpisodeNumber,
) { mutableStateOf(false) } ) { mutableStateOf(false) }
var hasSentCompletionScrobbleForCurrentItem by remember( var hasSentCompletionScrobbleForCurrentItem by remember(
activeSourceUrl,
activeVideoId, activeVideoId,
activeSeasonNumber, activeSeasonNumber,
activeEpisodeNumber, activeEpisodeNumber,
@ -383,7 +382,6 @@ fun PlayerScreen(
val progressPercent = currentPlaybackProgressPercent() val progressPercent = currentPlaybackProgressPercent()
if (progressPercent >= 1f && progressPercent < 80f) { if (progressPercent >= 1f && progressPercent < 80f) {
emitTraktScrobbleStop(progressPercent) emitTraktScrobbleStop(progressPercent)
hasSentCompletionScrobbleForCurrentItem = false
return return
} }
@ -1199,15 +1197,20 @@ fun PlayerScreen(
pausedOverlayVisible = true pausedOverlayVisible = true
} }
LaunchedEffect(playbackSnapshot.positionMs, playbackSnapshot.isPlaying, playbackSnapshot.isEnded, playbackSnapshot.durationMs) { LaunchedEffect(
playbackSnapshot.positionMs,
playbackSnapshot.isPlaying,
playbackSnapshot.isLoading,
playbackSnapshot.isEnded,
playbackSnapshot.durationMs,
) {
if (playbackSnapshot.isEnded) { if (playbackSnapshot.isEnded) {
hasSentCompletionScrobbleForCurrentItem = false
flushWatchProgress() flushWatchProgress()
previousIsPlaying = false previousIsPlaying = false
return@LaunchedEffect return@LaunchedEffect
} }
if (previousIsPlaying && !playbackSnapshot.isPlaying) { if (previousIsPlaying && !playbackSnapshot.isPlaying && !playbackSnapshot.isLoading) {
flushWatchProgress() flushWatchProgress()
} }
@ -1215,7 +1218,9 @@ fun PlayerScreen(
emitTraktScrobbleStart() emitTraktScrobbleStart()
} }
if (!playbackSnapshot.isLoading) {
previousIsPlaying = playbackSnapshot.isPlaying previousIsPlaying = playbackSnapshot.isPlaying
}
if (!playbackSnapshot.isPlaying) { if (!playbackSnapshot.isPlaying) {
return@LaunchedEffect return@LaunchedEffect

View file

@ -4,7 +4,7 @@ import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.lang_english import nuvio.composeapp.generated.resources.lang_english
import nuvio.composeapp.generated.resources.lang_french import nuvio.composeapp.generated.resources.lang_french
import nuvio.composeapp.generated.resources.lang_spanish import nuvio.composeapp.generated.resources.lang_spanish
import nuvio.composeapp.generated.resources.lang_portuguese import nuvio.composeapp.generated.resources.lang_portuguese_portugal
import nuvio.composeapp.generated.resources.lang_turkish import nuvio.composeapp.generated.resources.lang_turkish
import nuvio.composeapp.generated.resources.lang_italian import nuvio.composeapp.generated.resources.lang_italian
import nuvio.composeapp.generated.resources.lang_greek import nuvio.composeapp.generated.resources.lang_greek
@ -18,6 +18,7 @@ enum class AppLanguage(
ENGLISH("en", Res.string.lang_english), ENGLISH("en", Res.string.lang_english),
FRENCH("fr", Res.string.lang_french), FRENCH("fr", Res.string.lang_french),
SPANISH("es", Res.string.lang_spanish), SPANISH("es", Res.string.lang_spanish),
PORTUGUESE("pt", Res.string.lang_portuguese_portugal),
TURKISH("tr", Res.string.lang_turkish), TURKISH("tr", Res.string.lang_turkish),
ITALIAN("it", Res.string.lang_italian), ITALIAN("it", Res.string.lang_italian),
GREEK("el", Res.string.lang_greek), GREEK("el", Res.string.lang_greek),

View file

@ -48,8 +48,8 @@ object ThemeSettingsRepository {
_selectedTheme.value = theme _selectedTheme.value = theme
_amoledEnabled.value = ThemeSettingsStorage.loadAmoledEnabled() ?: false _amoledEnabled.value = ThemeSettingsStorage.loadAmoledEnabled() ?: false
val appLanguage = AppLanguage.fromCode(ThemeSettingsStorage.loadSelectedAppLanguage()) val appLanguage = AppLanguage.fromCode(ThemeSettingsStorage.loadSelectedAppLanguage())
_selectedAppLanguage.value = appLanguage
ThemeSettingsStorage.applySelectedAppLanguage(appLanguage.code) ThemeSettingsStorage.applySelectedAppLanguage(appLanguage.code)
_selectedAppLanguage.value = appLanguage
} }
fun setTheme(theme: AppTheme) { fun setTheme(theme: AppTheme) {
@ -69,8 +69,8 @@ object ThemeSettingsRepository {
fun setAppLanguage(language: AppLanguage) { fun setAppLanguage(language: AppLanguage) {
ensureLoaded() ensureLoaded()
if (_selectedAppLanguage.value == language) return if (_selectedAppLanguage.value == language) return
_selectedAppLanguage.value = language
ThemeSettingsStorage.saveSelectedAppLanguage(language.code) ThemeSettingsStorage.saveSelectedAppLanguage(language.code)
ThemeSettingsStorage.applySelectedAppLanguage(language.code) ThemeSettingsStorage.applySelectedAppLanguage(language.code)
_selectedAppLanguage.value = language
} }
} }

View file

@ -34,23 +34,22 @@ actual fun PlatformPlayerSurface(
onError: (String?) -> Unit, onError: (String?) -> Unit,
) { ) {
sanitizePlaybackResponseHeaders(sourceResponseHeaders) sanitizePlaybackResponseHeaders(sourceResponseHeaders)
val latestOnControllerReady = rememberUpdatedState(onControllerReady)
val latestOnSnapshot = rememberUpdatedState(onSnapshot) val latestOnSnapshot = rememberUpdatedState(onSnapshot)
val latestOnError = rememberUpdatedState(onError) val latestOnError = rememberUpdatedState(onError)
val bridge = remember(sourceUrl) { val bridge = remember {
NuvioPlayerBridgeFactory.create() NuvioPlayerBridgeFactory.create()
} }
if (bridge == null) { if (bridge == null) {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
onError("MPV player engine not available. Please rebuild the app.") latestOnError.value("MPV player engine not available. Please rebuild the app.")
} }
return return
} }
// Create controller val controller = remember(bridge) {
LaunchedEffect(bridge) {
onControllerReady(
object : PlayerEngineController { object : PlayerEngineController {
override fun play() { override fun play() {
bridge.play() bridge.play()
@ -207,7 +206,10 @@ actual fun PlatformPlayerSurface(
) )
} }
} }
) }
LaunchedEffect(controller, sourceUrl, sourceAudioUrl, sourceHeaders, sourceResponseHeaders) {
latestOnControllerReady.value(controller)
} }
// Load file and set initial state // Load file and set initial state

View file

@ -50,7 +50,17 @@ actual object ThemeSettingsStorage {
NSUserDefaults.standardUserDefaults.setObject(languageCode, forKey = selectedAppLanguageKey) NSUserDefaults.standardUserDefaults.setObject(languageCode, forKey = selectedAppLanguageKey)
} }
actual fun applySelectedAppLanguage(languageCode: String) = Unit actual fun applySelectedAppLanguage(languageCode: String) {
val normalizedCode = languageCode
.trim()
.takeIf { it.isNotBlank() }
?: AppLanguage.ENGLISH.code
NSUserDefaults.standardUserDefaults.setObject(
listOf(normalizedCode),
forKey = "AppleLanguages",
)
NSUserDefaults.standardUserDefaults.synchronize()
}
actual fun exportToSyncPayload(): JsonObject = buildJsonObject { actual fun exportToSyncPayload(): JsonObject = buildJsonObject {
loadSelectedTheme()?.let { put(selectedThemeKey, encodeSyncString(it)) } loadSelectedTheme()?.let { put(selectedThemeKey, encodeSyncString(it)) }
@ -69,5 +79,6 @@ actual object ThemeSettingsStorage {
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme) payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled) payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled)
payload.decodeSyncString(selectedAppLanguageKey)?.let(::saveSelectedAppLanguage) payload.decodeSyncString(selectedAppLanguageKey)?.let(::saveSelectedAppLanguage)
applySelectedAppLanguage(loadSelectedAppLanguage() ?: AppLanguage.ENGLISH.code)
} }
} }

View file

@ -1,3 +1,3 @@
CURRENT_PROJECT_VERSION=49 CURRENT_PROJECT_VERSION=50
MARKETING_VERSION=0.1.0 MARKETING_VERSION=0.1.13