Merge branch 'cmp-rewrite' of https://github.com/NuvioMedia/NuvioMobile into cmp-rewrite

This commit is contained in:
tapframe 2026-06-12 20:15:12 +05:30
commit 4c778a0b38
3 changed files with 50 additions and 9 deletions

View file

@ -2,6 +2,7 @@ package com.nuvio.app.features.library
import co.touchlab.kermit.Logger
import com.nuvio.app.core.auth.AuthRepository
import com.nuvio.app.core.ui.NuvioToastController
import com.nuvio.app.core.auth.AuthState
import com.nuvio.app.core.network.SupabaseProvider
import com.nuvio.app.features.home.PosterShape
@ -40,6 +41,7 @@ import kotlinx.serialization.json.put
import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.library_local_tab_title
import nuvio.composeapp.generated.resources.library_other
import nuvio.composeapp.generated.resources.trakt_lists_update_failed
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.getString
@ -218,7 +220,13 @@ object LibraryRepository {
if (isTraktLibrarySourceActive()) {
syncScope.launch {
runCatching { TraktLibraryRepository.toggleWatchlist(item) }
.onFailure { e -> log.e(e) { "Failed to toggle Trakt watchlist" } }
.onFailure { e ->
log.e(e) { "Failed to toggle Trakt watchlist" }
NuvioToastController.show(
e.message?.takeIf { it.isNotBlank() }
?: getString(Res.string.trakt_lists_update_failed),
)
}
publish()
}
return

View file

@ -239,8 +239,17 @@ internal fun PlayerScreenRuntime.BindPlayerRuntimeEffects() {
BindPlayerMetadataAndSkipEffects()
DisposableEffect(playbackSession.videoId, activeSourceUrl, activeSourceAudioUrl) {
val effectVideoId = playbackSession.videoId
val effectSourceUrl = activeSourceUrl
val effectSourceAudioUrl = activeSourceAudioUrl
onDispose {
flushWatchProgress()
if (
playbackSession.videoId == effectVideoId &&
activeSourceUrl == effectSourceUrl &&
activeSourceAudioUrl == effectSourceAudioUrl
) {
flushWatchProgress()
}
}
}

View file

@ -80,17 +80,40 @@ internal fun PlayerScreenRuntime.currentPlaybackProgressPercent(
.coerceIn(0f, 100f)
}
internal suspend fun PlayerScreenRuntime.currentTraktScrobbleItem() =
internal data class TraktScrobbleItemInputs(
val contentType: String,
val parentMetaId: String,
val videoId: String?,
val title: String,
val seasonNumber: Int?,
val episodeNumber: Int?,
val episodeTitle: String?,
)
internal fun PlayerScreenRuntime.snapshotTraktScrobbleItemInputs() = TraktScrobbleItemInputs(
contentType = contentType ?: parentMetaType,
parentMetaId = parentMetaId,
videoId = activeVideoId,
title = title,
seasonNumber = activeSeasonNumber,
episodeNumber = activeEpisodeNumber,
episodeTitle = activeEpisodeTitle,
)
private suspend fun TraktScrobbleItemInputs.buildItem() =
TraktScrobbleRepository.buildItem(
contentType = contentType ?: parentMetaType,
contentType = contentType,
parentMetaId = parentMetaId,
videoId = activeVideoId,
videoId = videoId,
title = title,
seasonNumber = activeSeasonNumber,
episodeNumber = activeEpisodeNumber,
episodeTitle = activeEpisodeTitle,
seasonNumber = seasonNumber,
episodeNumber = episodeNumber,
episodeTitle = episodeTitle,
)
internal suspend fun PlayerScreenRuntime.currentTraktScrobbleItem() =
snapshotTraktScrobbleItemInputs().buildItem()
internal fun PlayerScreenRuntime.emitTraktScrobbleStart() {
if (hasRequestedScrobbleStartForCurrentItem) return
hasRequestedScrobbleStartForCurrentItem = true
@ -120,8 +143,9 @@ internal fun PlayerScreenRuntime.emitTraktScrobbleStop(progressPercent: Float? =
val percent = provided ?: currentPlaybackProgressPercent()
val itemSnapshot = currentTraktScrobbleItem
val inputsSnapshot = snapshotTraktScrobbleItemInputs()
scope.launch(NonCancellable) {
val item = itemSnapshot ?: currentTraktScrobbleItem() ?: return@launch
val item = itemSnapshot ?: inputsSnapshot.buildItem() ?: return@launch
TraktScrobbleRepository.scrobbleStop(
item = item,
progressPercent = percent,