mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-08-01 00:59:27 +00:00
cleanup logs
This commit is contained in:
parent
f6f427b170
commit
6d2abeab84
6 changed files with 145 additions and 144 deletions
|
|
@ -176,7 +176,9 @@ import com.nuvio.app.features.settings.ThemeSettingsRepository
|
|||
import com.nuvio.app.features.collection.CollectionManagementScreen
|
||||
import com.nuvio.app.features.collection.CollectionEditorScreen
|
||||
import com.nuvio.app.features.collection.CollectionEditorRepository
|
||||
import com.nuvio.app.features.collection.CollectionRepository
|
||||
import com.nuvio.app.features.collection.CollectionSyncService
|
||||
import com.nuvio.app.features.home.HomeCatalogSettingsRepository
|
||||
import com.nuvio.app.features.home.HomeCatalogSettingsSyncService
|
||||
import com.nuvio.app.features.collection.FolderDetailScreen
|
||||
import com.nuvio.app.features.collection.FolderDetailRepository
|
||||
|
|
@ -194,6 +196,7 @@ import com.nuvio.app.features.player.PlayerSettingsRepository
|
|||
import com.nuvio.app.features.trakt.TraktAuthRepository
|
||||
import com.nuvio.app.features.trakt.TraktListTab
|
||||
import com.nuvio.app.features.trakt.TraktScrobbleRepository
|
||||
import com.nuvio.app.features.trakt.TraktSettingsRepository
|
||||
import com.nuvio.app.features.updater.AppUpdaterHost
|
||||
import com.nuvio.app.features.updater.rememberAppUpdaterController
|
||||
import com.nuvio.app.features.watched.WatchedRepository
|
||||
|
|
@ -206,10 +209,13 @@ import com.nuvio.app.features.watchprogress.nextUpDismissKey
|
|||
import com.nuvio.app.features.watchprogress.toContinueWatchingItem
|
||||
import com.nuvio.app.features.watching.application.WatchingActions
|
||||
import com.nuvio.app.features.watching.application.WatchingState
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import nuvio.composeapp.generated.resources.*
|
||||
import nuvio.composeapp.generated.resources.app_logo_wordmark
|
||||
|
|
@ -350,10 +356,37 @@ private enum class AppGateScreen {
|
|||
Loading,
|
||||
Auth,
|
||||
ProfileSelection,
|
||||
ProfileSwitching,
|
||||
ProfileEdit,
|
||||
Main,
|
||||
}
|
||||
|
||||
private data class PendingProfileSwitch(
|
||||
val profile: NuvioProfile,
|
||||
val syncOnEnter: Boolean,
|
||||
)
|
||||
|
||||
private suspend fun warmProfileBoundRepositories() {
|
||||
withContext(Dispatchers.Default) {
|
||||
AddonRepository.initialize()
|
||||
CollectionRepository.initialize()
|
||||
ContinueWatchingPreferencesRepository.ensureLoaded()
|
||||
DownloadsRepository.ensureLoaded()
|
||||
EpisodeReleaseNotificationsRepository.ensureLoaded()
|
||||
HomeCatalogSettingsRepository.snapshot()
|
||||
LibraryRepository.ensureLoaded()
|
||||
P2pSettingsRepository.ensureLoaded()
|
||||
PlayerSettingsRepository.ensureLoaded()
|
||||
TraktAuthRepository.ensureLoaded()
|
||||
TraktSettingsRepository.ensureLoaded()
|
||||
WatchedRepository.ensureLoaded()
|
||||
WatchProgressRepository.ensureLoaded()
|
||||
CollectionSyncService.startObserving()
|
||||
HomeCatalogSettingsSyncService.startObserving()
|
||||
ProfileSettingsSync.startObserving()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@Preview
|
||||
|
|
@ -416,6 +449,7 @@ fun App() {
|
|||
var editingProfile by remember { mutableStateOf<NuvioProfile?>(null) }
|
||||
var isNewProfile by remember { mutableStateOf(false) }
|
||||
var autoSkipProfileSelection by rememberSaveable { mutableStateOf(false) }
|
||||
var pendingProfileSwitch by remember { mutableStateOf<PendingProfileSwitch?>(null) }
|
||||
|
||||
fun rememberedStartupProfile(profiles: List<NuvioProfile>): NuvioProfile? {
|
||||
val currentProfileState = ProfileRepository.state.value
|
||||
|
|
@ -431,6 +465,12 @@ fun App() {
|
|||
?.takeUnless { it.pinEnabled }
|
||||
}
|
||||
|
||||
fun requestProfileSwitch(profile: NuvioProfile, syncOnEnter: Boolean) {
|
||||
autoSkipProfileSelection = false
|
||||
pendingProfileSwitch = PendingProfileSwitch(profile, syncOnEnter)
|
||||
gateScreen = AppGateScreen.ProfileSwitching.name
|
||||
}
|
||||
|
||||
fun enterProfileGate(profiles: List<NuvioProfile>, syncOnEnter: Boolean) {
|
||||
if (profiles.isEmpty()) {
|
||||
autoSkipProfileSelection = true
|
||||
|
|
@ -439,12 +479,7 @@ fun App() {
|
|||
}
|
||||
|
||||
rememberedStartupProfile(profiles)?.let { profile ->
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
if (syncOnEnter) {
|
||||
SyncManager.pullAllForProfile(profile.profileIndex)
|
||||
}
|
||||
gateScreen = AppGateScreen.Main.name
|
||||
autoSkipProfileSelection = false
|
||||
requestProfileSwitch(profile, syncOnEnter)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -455,18 +490,40 @@ fun App() {
|
|||
gateScreen = AppGateScreen.ProfileSelection.name
|
||||
return
|
||||
}
|
||||
ProfileRepository.selectProfile(onlyProfile.profileIndex)
|
||||
if (syncOnEnter) {
|
||||
SyncManager.pullAllForProfile(onlyProfile.profileIndex)
|
||||
}
|
||||
gateScreen = AppGateScreen.Main.name
|
||||
autoSkipProfileSelection = false
|
||||
requestProfileSwitch(onlyProfile, syncOnEnter)
|
||||
} else {
|
||||
gateScreen = AppGateScreen.ProfileSelection.name
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(gateScreen, pendingProfileSwitch) {
|
||||
if (gateScreen == AppGateScreen.ProfileSwitching.name && pendingProfileSwitch == null) {
|
||||
gateScreen = AppGateScreen.Loading.name
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(pendingProfileSwitch) {
|
||||
val request = pendingProfileSwitch ?: return@LaunchedEffect
|
||||
runCatching {
|
||||
ProfileRepository.switchToProfile(request.profile.profileIndex)
|
||||
warmProfileBoundRepositories()
|
||||
if (request.syncOnEnter) {
|
||||
SyncManager.pullAllForProfile(request.profile.profileIndex)
|
||||
}
|
||||
}.onSuccess {
|
||||
pendingProfileSwitch = null
|
||||
autoSkipProfileSelection = false
|
||||
gateScreen = AppGateScreen.Main.name
|
||||
}.onFailure {
|
||||
pendingProfileSwitch = null
|
||||
autoSkipProfileSelection = false
|
||||
gateScreen = AppGateScreen.ProfileSelection.name
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(authState, networkStatusUiState.condition, profileState.profiles) {
|
||||
if (gateScreen == AppGateScreen.ProfileSwitching.name) return@LaunchedEffect
|
||||
|
||||
val cachedProfiles = profileState.profiles
|
||||
val allowOfflineProfileAccess =
|
||||
cachedProfiles.isNotEmpty() &&
|
||||
|
|
@ -519,10 +576,10 @@ fun App() {
|
|||
gateScreen == AppGateScreen.ProfileSelection.name
|
||||
) {
|
||||
rememberedStartupProfile(profileState.profiles)?.let { profile ->
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
SyncManager.pullAllForProfile(profile.profileIndex)
|
||||
gateScreen = AppGateScreen.Main.name
|
||||
autoSkipProfileSelection = false
|
||||
requestProfileSwitch(
|
||||
profile = profile,
|
||||
syncOnEnter = authState is AuthState.Authenticated,
|
||||
)
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
|
|
@ -531,10 +588,10 @@ fun App() {
|
|||
val onlyProfile = profileState.profiles.first()
|
||||
if (onlyProfile.pinEnabled) return@LaunchedEffect
|
||||
|
||||
ProfileRepository.selectProfile(onlyProfile.profileIndex)
|
||||
SyncManager.pullAllForProfile(onlyProfile.profileIndex)
|
||||
gateScreen = AppGateScreen.Main.name
|
||||
autoSkipProfileSelection = false
|
||||
requestProfileSwitch(
|
||||
profile = onlyProfile,
|
||||
syncOnEnter = authState is AuthState.Authenticated,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,15 +604,9 @@ fun App() {
|
|||
},
|
||||
) { currentGate ->
|
||||
when (currentGate) {
|
||||
AppGateScreen.Loading.name -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.nuvio.colors.background),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator(color = MaterialTheme.nuvio.colors.accent)
|
||||
}
|
||||
AppGateScreen.Loading.name,
|
||||
AppGateScreen.ProfileSwitching.name -> {
|
||||
AppLaunchOverlay(modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
AppGateScreen.Auth.name -> {
|
||||
AuthScreen(modifier = Modifier.fillMaxSize())
|
||||
|
|
@ -568,11 +619,10 @@ fun App() {
|
|||
}
|
||||
ProfileSelectionScreen(
|
||||
onProfileSelected = { profile ->
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
if (authState is AuthState.Authenticated) {
|
||||
SyncManager.pullAllForProfile(profile.profileIndex)
|
||||
}
|
||||
gateScreen = AppGateScreen.Main.name
|
||||
requestProfileSwitch(
|
||||
profile = profile,
|
||||
syncOnEnter = authState is AuthState.Authenticated,
|
||||
)
|
||||
},
|
||||
onEditProfile = { profile ->
|
||||
editingProfile = profile
|
||||
|
|
@ -618,18 +668,6 @@ private fun MainAppContent(
|
|||
) {
|
||||
val navController = rememberNavController()
|
||||
val appUpdaterController = rememberAppUpdaterController()
|
||||
remember {
|
||||
EpisodeReleaseNotificationsRepository.ensureLoaded()
|
||||
}
|
||||
remember {
|
||||
CollectionSyncService.startObserving()
|
||||
}
|
||||
remember {
|
||||
HomeCatalogSettingsSyncService.startObserving()
|
||||
}
|
||||
remember {
|
||||
ProfileSettingsSync.startObserving()
|
||||
}
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var selectedTab by rememberSaveable { mutableStateOf(AppScreenTab.Home) }
|
||||
|
|
@ -638,6 +676,10 @@ private fun MainAppContent(
|
|||
val searchScrollToTopRequests = remember { MutableSharedFlow<Unit>(extraBufferCapacity = 1) }
|
||||
val libraryScrollToTopRequests = remember { MutableSharedFlow<Unit>(extraBufferCapacity = 1) }
|
||||
val settingsRootActionRequests = remember { MutableSharedFlow<Unit>(extraBufferCapacity = 1) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
warmProfileBoundRepositories()
|
||||
}
|
||||
val currentBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val liquidGlassNativeTabBarEnabled by remember {
|
||||
ThemeSettingsRepository.liquidGlassNativeTabBarEnabled
|
||||
|
|
@ -654,32 +696,14 @@ private fun MainAppContent(
|
|||
var pickerMembership by remember { mutableStateOf<Map<String, Boolean>>(emptyMap()) }
|
||||
var pickerPending by remember { mutableStateOf(false) }
|
||||
var pickerError by remember { mutableStateOf<String?>(null) }
|
||||
val addonsUiState by remember {
|
||||
AddonRepository.initialize()
|
||||
AddonRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val libraryUiState by remember {
|
||||
LibraryRepository.ensureLoaded()
|
||||
LibraryRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val addonsUiState by AddonRepository.uiState.collectAsStateWithLifecycle()
|
||||
val libraryUiState by LibraryRepository.uiState.collectAsStateWithLifecycle()
|
||||
val authState by AuthRepository.state.collectAsStateWithLifecycle()
|
||||
val profileState by ProfileRepository.state.collectAsStateWithLifecycle()
|
||||
val playerSettingsUiState by remember {
|
||||
PlayerSettingsRepository.ensureLoaded()
|
||||
PlayerSettingsRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val p2pSettingsUiState by remember {
|
||||
P2pSettingsRepository.ensureLoaded()
|
||||
P2pSettingsRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val watchedUiState by remember {
|
||||
WatchedRepository.ensureLoaded()
|
||||
WatchedRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val downloadsUiState by remember {
|
||||
DownloadsRepository.ensureLoaded()
|
||||
DownloadsRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val playerSettingsUiState by PlayerSettingsRepository.uiState.collectAsStateWithLifecycle()
|
||||
val p2pSettingsUiState by P2pSettingsRepository.uiState.collectAsStateWithLifecycle()
|
||||
val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle()
|
||||
val downloadsUiState by DownloadsRepository.uiState.collectAsStateWithLifecycle()
|
||||
val networkStatusUiState by remember {
|
||||
NetworkStatusRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
|
|
@ -913,10 +937,7 @@ private fun MainAppContent(
|
|||
}
|
||||
}
|
||||
}
|
||||
val continueWatchingPreferencesUiState by remember {
|
||||
ContinueWatchingPreferencesRepository.ensureLoaded()
|
||||
ContinueWatchingPreferencesRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val continueWatchingPreferencesUiState by ContinueWatchingPreferencesRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(
|
||||
initialHomeReady,
|
||||
|
|
@ -1339,8 +1360,16 @@ private fun MainAppContent(
|
|||
val onProfileSelected: (NuvioProfile) -> Unit = { profile ->
|
||||
profileSwitchLoading = true
|
||||
selectedTab = AppScreenTab.Home
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
com.nuvio.app.core.sync.SyncManager.pullAllForProfile(profile.profileIndex)
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
ProfileRepository.switchToProfile(profile.profileIndex)
|
||||
warmProfileBoundRepositories()
|
||||
SyncManager.pullAllForProfile(profile.profileIndex)
|
||||
delay(300)
|
||||
} finally {
|
||||
profileSwitchLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
|
|
@ -1723,10 +1752,7 @@ private fun MainAppContent(
|
|||
hasResolvedVideoId = true
|
||||
}
|
||||
|
||||
val playerSettings by remember {
|
||||
PlayerSettingsRepository.ensureLoaded()
|
||||
PlayerSettingsRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val playerSettings by PlayerSettingsRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
fun p2pSentinelUrl(infoHash: String, fileIdx: Int?): String =
|
||||
"torrent://$infoHash${fileIdx?.let { "?index=$it" }.orEmpty()}"
|
||||
|
|
@ -2751,15 +2777,6 @@ private fun MainAppContent(
|
|||
AppLaunchOverlay(modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
|
||||
// Auto-dismiss profile switch overlay
|
||||
if (profileSwitchLoading) {
|
||||
LaunchedEffect(Unit) {
|
||||
// Brief loading screen while home refreshes for the new profile
|
||||
kotlinx.coroutines.delay(1200)
|
||||
profileSwitchLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
NuvioFloatingPrompt(
|
||||
visible = resumePromptItem != null,
|
||||
imageUrl = resumePromptItem?.poster ?: resumePromptItem?.imageUrl,
|
||||
|
|
|
|||
|
|
@ -104,19 +104,21 @@ fun HomeScreen(
|
|||
onFirstCatalogRendered: (() -> Unit)? = null,
|
||||
) {
|
||||
LaunchedEffect(Unit) {
|
||||
AddonRepository.initialize()
|
||||
CollectionRepository.initialize()
|
||||
ContinueWatchingPreferencesRepository.ensureLoaded()
|
||||
WatchedRepository.ensureLoaded()
|
||||
WatchProgressRepository.ensureLoaded()
|
||||
withContext(Dispatchers.Default) {
|
||||
AddonRepository.initialize()
|
||||
CollectionRepository.initialize()
|
||||
ContinueWatchingPreferencesRepository.ensureLoaded()
|
||||
HomeCatalogSettingsRepository.snapshot()
|
||||
TraktSettingsRepository.ensureLoaded()
|
||||
TraktAuthRepository.ensureLoaded()
|
||||
WatchedRepository.ensureLoaded()
|
||||
WatchProgressRepository.ensureLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
val addonsUiState by AddonRepository.uiState.collectAsStateWithLifecycle()
|
||||
val homeUiState by HomeRepository.uiState.collectAsStateWithLifecycle()
|
||||
val homeSettingsUiState by remember {
|
||||
HomeCatalogSettingsRepository.snapshot()
|
||||
HomeCatalogSettingsRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val homeSettingsUiState by HomeCatalogSettingsRepository.uiState.collectAsStateWithLifecycle()
|
||||
val homeListState = rememberLazyListState()
|
||||
val collections by CollectionRepository.collections.collectAsStateWithLifecycle()
|
||||
val continueWatchingPreferences by ContinueWatchingPreferencesRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
|
@ -124,14 +126,8 @@ fun HomeScreen(
|
|||
val watchProgressUiState by WatchProgressRepository.uiState.collectAsStateWithLifecycle()
|
||||
val cloudLibraryUiState by CloudLibraryRepository.uiState.collectAsStateWithLifecycle()
|
||||
val networkStatusUiState by NetworkStatusRepository.uiState.collectAsStateWithLifecycle()
|
||||
val traktSettingsUiState by remember {
|
||||
TraktSettingsRepository.ensureLoaded()
|
||||
TraktSettingsRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val isTraktAuthenticated by remember {
|
||||
TraktAuthRepository.ensureLoaded()
|
||||
TraktAuthRepository.isAuthenticated
|
||||
}.collectAsStateWithLifecycle()
|
||||
val traktSettingsUiState by TraktSettingsRepository.uiState.collectAsStateWithLifecycle()
|
||||
val isTraktAuthenticated by TraktAuthRepository.isAuthenticated.collectAsStateWithLifecycle()
|
||||
var observedOfflineState by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(scrollToTopRequests) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
|
|
@ -62,6 +65,7 @@ object ProfileRepository {
|
|||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
private val log = Logger.withTag("ProfileRepository")
|
||||
private val json = Json { ignoreUnknownKeys = true; encodeDefaults = true }
|
||||
private val profileSwitchMutex = Mutex()
|
||||
private fun localizedString(resource: StringResource): String = runBlocking { getString(resource) }
|
||||
|
||||
private val _state = MutableStateFlow(ProfileState())
|
||||
|
|
@ -141,7 +145,15 @@ object ProfileRepository {
|
|||
}
|
||||
}
|
||||
|
||||
fun selectProfile(profileIndex: Int) {
|
||||
suspend fun switchToProfile(profileIndex: Int) {
|
||||
profileSwitchMutex.withLock {
|
||||
withContext(Dispatchers.Default) {
|
||||
selectProfile(profileIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectProfile(profileIndex: Int) {
|
||||
activeProfileIndex = profileIndex
|
||||
val selectedProfile = _state.value.profiles.find { it.profileIndex == profileIndex }
|
||||
_state.value = _state.value.copy(
|
||||
|
|
|
|||
|
|
@ -176,7 +176,6 @@ fun ProfileSelectionScreen(
|
|||
} else if (profile.pinEnabled) {
|
||||
pinDialogProfile = profile
|
||||
} else {
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
onProfileSelected(profile)
|
||||
}
|
||||
},
|
||||
|
|
@ -217,7 +216,6 @@ fun ProfileSelectionScreen(
|
|||
} else if (profile.pinEnabled) {
|
||||
pinDialogProfile = profile
|
||||
} else {
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
onProfileSelected(profile)
|
||||
}
|
||||
},
|
||||
|
|
@ -282,7 +280,6 @@ fun ProfileSelectionScreen(
|
|||
onVerify = { pin -> ProfileRepository.verifyPin(profile.profileIndex, pin) },
|
||||
onVerified = {
|
||||
pinDialogProfile = null
|
||||
ProfileRepository.selectProfile(profile.profileIndex)
|
||||
onProfileSelected(profile)
|
||||
},
|
||||
onDismiss = { pinDialogProfile = null },
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.nuvio.app.features.trakt.parseTraktIsoDateTimeToEpochMs
|
|||
import nuvio.composeapp.generated.resources.*
|
||||
import org.jetbrains.compose.resources.pluralStringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import co.touchlab.kermit.Logger
|
||||
|
||||
@Composable
|
||||
fun computeAirDateBadgeText(
|
||||
|
|
@ -67,46 +66,32 @@ class ReleaseAlertState(
|
|||
val isNewSeasonRelease: Boolean,
|
||||
)
|
||||
|
||||
private const val ReleaseAlertWindowMs = 60L * 24 * 60 * 60 * 1000
|
||||
private val NoReleaseAlertState = ReleaseAlertState(false, false)
|
||||
|
||||
fun calculateReleaseAlertState(
|
||||
seedLastUpdatedEpochMs: Long,
|
||||
seedSeasonNumber: Int?,
|
||||
nextSeasonNumber: Int?,
|
||||
releasedIso: String?,
|
||||
): ReleaseAlertState {
|
||||
if (releasedIso.isNullOrBlank()) return NoReleaseAlertState
|
||||
|
||||
val releaseEpoch = parseReleaseDateToEpochMs(releasedIso)
|
||||
?: return NoReleaseAlertState
|
||||
|
||||
val nowMs = WatchProgressClock.nowEpochMs()
|
||||
if (nowMs < releaseEpoch) return NoReleaseAlertState
|
||||
if (releaseEpoch <= seedLastUpdatedEpochMs) return NoReleaseAlertState
|
||||
if (nowMs - releaseEpoch >= ReleaseAlertWindowMs) return NoReleaseAlertState
|
||||
|
||||
val log = Logger.withTag("ReleaseAlert")
|
||||
log.d {
|
||||
"calculateReleaseAlertState inputs: releasedIso=$releasedIso, " +
|
||||
"releaseEpoch=$releaseEpoch, seedLastUpdatedEpochMs=$seedLastUpdatedEpochMs, " +
|
||||
"seedSeasonNumber=$seedSeasonNumber, nextSeasonNumber=$nextSeasonNumber, nowMs=$nowMs"
|
||||
}
|
||||
|
||||
if (releaseEpoch == null) {
|
||||
log.d { "calculateReleaseAlertState failed: releaseEpoch is null" }
|
||||
return ReleaseAlertState(false, false)
|
||||
}
|
||||
|
||||
val hasAired = nowMs >= releaseEpoch
|
||||
val sixtyDaysMs = 60L * 24 * 60 * 60 * 1000
|
||||
val isReleaseAlert = hasAired &&
|
||||
releaseEpoch > seedLastUpdatedEpochMs &&
|
||||
(nowMs - releaseEpoch) < sixtyDaysMs
|
||||
|
||||
val isNewSeasonRelease = isReleaseAlert &&
|
||||
val isNewSeasonRelease =
|
||||
seedSeasonNumber != null &&
|
||||
nextSeasonNumber != null &&
|
||||
nextSeasonNumber != seedSeasonNumber
|
||||
|
||||
log.d {
|
||||
"calculateReleaseAlertState result: isReleaseAlert=$isReleaseAlert (hasAired=$hasAired, " +
|
||||
"epoch>seed=${releaseEpoch > seedLastUpdatedEpochMs}, ageMs=${nowMs - releaseEpoch}), " +
|
||||
"isNewSeasonRelease=$isNewSeasonRelease"
|
||||
}
|
||||
|
||||
return ReleaseAlertState(
|
||||
isReleaseAlert = isReleaseAlert,
|
||||
isReleaseAlert = true,
|
||||
isNewSeasonRelease = isNewSeasonRelease
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@ package com.nuvio.app
|
|||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.window.Window
|
||||
|
|
@ -48,15 +44,13 @@ fun main() {
|
|||
if (smokePlayerUrl == null) {
|
||||
App()
|
||||
} else {
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
PlatformPlayerSurface(
|
||||
sourceUrl = smokePlayerUrl,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
onControllerReady = {},
|
||||
onSnapshot = {},
|
||||
onError = { error = it },
|
||||
onError = {},
|
||||
)
|
||||
error?.let { println("Nuvio desktop player smoke error: $it") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue