mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 07:21:58 +00:00
Update App.kt
This commit is contained in:
parent
c29f0cc064
commit
753f19d581
1 changed files with 232 additions and 285 deletions
|
|
@ -123,7 +123,6 @@ import com.nuvio.app.features.library.LibrarySection
|
||||||
import com.nuvio.app.features.library.LibrarySourceMode
|
import com.nuvio.app.features.library.LibrarySourceMode
|
||||||
import com.nuvio.app.features.library.LibraryScreen
|
import com.nuvio.app.features.library.LibraryScreen
|
||||||
import com.nuvio.app.features.library.toLibraryItem
|
import com.nuvio.app.features.library.toLibraryItem
|
||||||
import com.nuvio.app.features.library.toMetaPreview
|
|
||||||
import com.nuvio.app.features.notifications.EpisodeReleaseNotificationsRepository
|
import com.nuvio.app.features.notifications.EpisodeReleaseNotificationsRepository
|
||||||
import com.nuvio.app.features.player.PlayerLaunch
|
import com.nuvio.app.features.player.PlayerLaunch
|
||||||
import com.nuvio.app.features.player.PlayerLaunchStore
|
import com.nuvio.app.features.player.PlayerLaunchStore
|
||||||
|
|
@ -385,8 +384,8 @@ fun App() {
|
||||||
val cachedProfiles = profileState.profiles
|
val cachedProfiles = profileState.profiles
|
||||||
val allowOfflineProfileAccess =
|
val allowOfflineProfileAccess =
|
||||||
cachedProfiles.isNotEmpty() &&
|
cachedProfiles.isNotEmpty() &&
|
||||||
authState !is AuthState.Authenticated &&
|
authState !is AuthState.Authenticated &&
|
||||||
networkStatusUiState.condition != NetworkCondition.Online
|
networkStatusUiState.condition != NetworkCondition.Online
|
||||||
|
|
||||||
when (authState) {
|
when (authState) {
|
||||||
is AuthState.Loading -> {
|
is AuthState.Loading -> {
|
||||||
|
|
@ -660,7 +659,7 @@ private fun MainAppContent(
|
||||||
|
|
||||||
NetworkCondition.Unknown,
|
NetworkCondition.Unknown,
|
||||||
NetworkCondition.Checking,
|
NetworkCondition.Checking,
|
||||||
-> Unit
|
-> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
lastNetworkToastCondition = condition.name
|
lastNetworkToastCondition = condition.name
|
||||||
|
|
@ -677,7 +676,7 @@ private fun MainAppContent(
|
||||||
when (networkStatusUiState.condition) {
|
when (networkStatusUiState.condition) {
|
||||||
NetworkCondition.Unknown,
|
NetworkCondition.Unknown,
|
||||||
NetworkCondition.Checking,
|
NetworkCondition.Checking,
|
||||||
-> return@LaunchedEffect
|
-> return@LaunchedEffect
|
||||||
|
|
||||||
NetworkCondition.Online -> {
|
NetworkCondition.Online -> {
|
||||||
offlineLaunchRouteHandled = true
|
offlineLaunchRouteHandled = true
|
||||||
|
|
@ -685,7 +684,7 @@ private fun MainAppContent(
|
||||||
|
|
||||||
NetworkCondition.NoInternet,
|
NetworkCondition.NoInternet,
|
||||||
NetworkCondition.ServersUnreachable,
|
NetworkCondition.ServersUnreachable,
|
||||||
-> {
|
-> {
|
||||||
offlineLaunchRouteHandled = true
|
offlineLaunchRouteHandled = true
|
||||||
val hasPlayableDownload = downloadsUiState.completedItems.any {
|
val hasPlayableDownload = downloadsUiState.completedItems.any {
|
||||||
DownloadsRepository.playableLocalFileUri(it) != null
|
DownloadsRepository.playableLocalFileUri(it) != null
|
||||||
|
|
@ -729,24 +728,29 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(navController) {
|
LaunchedEffect(navController) {
|
||||||
AppDeepLinkRepository.pendingDeepLink.collectLatest { deepLink ->
|
AppDeepLinkRepository.pendingDeepLink.collectLatest { deepLink ->
|
||||||
when (deepLink) {
|
when (deepLink) {
|
||||||
is AppDeepLink.Meta -> {
|
is AppDeepLink.Meta -> {
|
||||||
selectedTab = AppScreenTab.Home
|
selectedTab = AppScreenTab.Home
|
||||||
navController.navigate(DetailRoute(type = deepLink.type, id = deepLink.id)) {
|
navController.navigate(DetailRoute(type = deepLink.type, id = deepLink.id)) {
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
AppDeepLinkRepository.markConsumed(deepLink)
|
||||||
}
|
}
|
||||||
AppDeepLinkRepository.markConsumed(deepLink)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppDeepLink.Downloads -> {
|
AppDeepLink.Downloads -> {
|
||||||
selectedTab = AppScreenTab.Settings
|
selectedTab = AppScreenTab.Settings
|
||||||
navController.navigate(DownloadsSettingsRoute) {
|
navController.navigate(DownloadsSettingsRoute) {
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
AppDeepLinkRepository.markConsumed(deepLink)
|
||||||
}
|
}
|
||||||
AppDeepLinkRepository.markConsumed(deepLink)
|
|
||||||
|
null -> Unit
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun launchPlaybackWithDownloadPreference(
|
fun launchPlaybackWithDownloadPreference(
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -809,69 +813,90 @@ private fun MainAppContent(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun launchPlaybackWithDownloadPreference(
|
val streamLaunchId = StreamLaunchStore.put(
|
||||||
type: String,
|
StreamLaunch(
|
||||||
videoId: String,
|
type = type,
|
||||||
parentMetaId: String,
|
videoId = videoId,
|
||||||
parentMetaType: String,
|
parentMetaId = parentMetaId,
|
||||||
title: String,
|
parentMetaType = parentMetaType,
|
||||||
logo: String?,
|
title = title,
|
||||||
poster: String?,
|
logo = logo,
|
||||||
background: String?,
|
poster = poster,
|
||||||
seasonNumber: Int?,
|
background = background,
|
||||||
episodeNumber: Int?,
|
seasonNumber = seasonNumber,
|
||||||
episodeTitle: String?,
|
episodeNumber = episodeNumber,
|
||||||
episodeThumbnail: String?,
|
episodeTitle = episodeTitle,
|
||||||
pauseDescription: String?,
|
episodeThumbnail = episodeThumbnail,
|
||||||
resumePositionMs: Long?,
|
pauseDescription = pauseDescription,
|
||||||
resumeProgressFraction: Float?,
|
resumePositionMs = if (startFromBeginning) 0L else resumePositionMs,
|
||||||
manualSelection: Boolean,
|
resumeProgressFraction = targetResumeProgressFraction,
|
||||||
startFromBeginning: Boolean,
|
manualSelection = manualSelection,
|
||||||
) {
|
startFromBeginning = startFromBeginning,
|
||||||
val targetResumePositionMs = if (startFromBeginning) 0L else (resumePositionMs ?: 0L)
|
),
|
||||||
val targetResumeProgressFraction = if (startFromBeginning) null else resumeProgressFraction
|
|
||||||
|
|
||||||
if (!manualSelection) {
|
|
||||||
val downloadedItem = DownloadsRepository.findPlayableDownload(
|
|
||||||
parentMetaId = parentMetaId,
|
|
||||||
seasonNumber = seasonNumber,
|
|
||||||
episodeNumber = episodeNumber,
|
|
||||||
videoId = videoId,
|
|
||||||
)
|
)
|
||||||
val localSourceUrl = downloadedItem?.localFileUri
|
navController.navigate(
|
||||||
if (!localSourceUrl.isNullOrBlank()) {
|
StreamRoute(launchId = streamLaunchId),
|
||||||
val launchId = PlayerLaunchStore.put(
|
)
|
||||||
PlayerLaunch(
|
}
|
||||||
title = title,
|
|
||||||
sourceUrl = localSourceUrl,
|
val onPlay: (String, String, String, String, String, String?, String?, String?, Int?, Int?, String?, String?, String?, Long?) -> Unit =
|
||||||
sourceHeaders = emptyMap(),
|
{ type, videoId, parentMetaId, parentMetaType, title, logo, poster, background, seasonNumber, episodeNumber, episodeTitle, episodeThumbnail, pauseDescription, resumePositionMs ->
|
||||||
sourceResponseHeaders = emptyMap(),
|
launchPlaybackWithDownloadPreference(
|
||||||
logo = logo,
|
type = type,
|
||||||
poster = poster,
|
videoId = videoId,
|
||||||
background = background,
|
parentMetaId = parentMetaId,
|
||||||
seasonNumber = seasonNumber,
|
parentMetaType = parentMetaType,
|
||||||
episodeNumber = episodeNumber,
|
title = title,
|
||||||
episodeTitle = episodeTitle,
|
logo = logo,
|
||||||
episodeThumbnail = episodeThumbnail,
|
poster = poster,
|
||||||
streamTitle = downloadedItem.streamTitle.ifBlank { title },
|
background = background,
|
||||||
streamSubtitle = downloadedItem.streamSubtitle,
|
seasonNumber = seasonNumber,
|
||||||
pauseDescription = pauseDescription,
|
episodeNumber = episodeNumber,
|
||||||
providerName = downloadedItem.providerName.ifBlank { downloadedProviderLabel },
|
episodeTitle = episodeTitle,
|
||||||
providerAddonId = downloadedItem.providerAddonId,
|
episodeThumbnail = episodeThumbnail,
|
||||||
contentType = type,
|
pauseDescription = pauseDescription,
|
||||||
videoId = videoId,
|
resumePositionMs = resumePositionMs,
|
||||||
parentMetaId = parentMetaId,
|
resumeProgressFraction = null,
|
||||||
parentMetaType = parentMetaType,
|
manualSelection = false,
|
||||||
initialPositionMs = targetResumePositionMs,
|
startFromBeginning = false,
|
||||||
initialProgressFraction = targetResumeProgressFraction,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
navController.navigate(PlayerRoute(launchId = launchId))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val onPlayManually: (String, String, String, String, String, String?, String?, String?, Int?, Int?, String?, String?, String?, Long?) -> Unit =
|
||||||
|
{ type, videoId, parentMetaId, parentMetaType, title, logo, poster, background, seasonNumber, episodeNumber, episodeTitle, episodeThumbnail, pauseDescription, resumePositionMs ->
|
||||||
|
launchPlaybackWithDownloadPreference(
|
||||||
|
type = type,
|
||||||
|
videoId = videoId,
|
||||||
|
parentMetaId = parentMetaId,
|
||||||
|
parentMetaType = parentMetaType,
|
||||||
|
title = title,
|
||||||
|
logo = logo,
|
||||||
|
poster = poster,
|
||||||
|
background = background,
|
||||||
|
seasonNumber = seasonNumber,
|
||||||
|
episodeNumber = episodeNumber,
|
||||||
|
episodeTitle = episodeTitle,
|
||||||
|
episodeThumbnail = episodeThumbnail,
|
||||||
|
pauseDescription = pauseDescription,
|
||||||
|
resumePositionMs = resumePositionMs,
|
||||||
|
resumeProgressFraction = null,
|
||||||
|
manualSelection = true,
|
||||||
|
startFromBeginning = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val onCatalogClick: (HomeCatalogSection) -> Unit = { section ->
|
||||||
|
navController.navigate(
|
||||||
|
CatalogRoute(
|
||||||
|
title = section.title,
|
||||||
|
subtitle = section.subtitle,
|
||||||
|
manifestUrl = section.manifestUrl,
|
||||||
|
type = section.type,
|
||||||
|
catalogId = section.catalogId,
|
||||||
|
supportsPagination = section.supportsPagination,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val librarySectionSubtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
val librarySectionSubtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
||||||
|
|
@ -893,111 +918,56 @@ private fun MainAppContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val onPlayManually: (String, String, String, String, String, String?, String?, String?, Int?, Int?, String?, String?, String?, Long?) -> Unit =
|
val openContinueWatching: (ContinueWatchingItem, Boolean, Boolean) -> Unit = { item, manualSelection, startFromBeginning ->
|
||||||
{ type, videoId, parentMetaId, parentMetaType, title, logo, poster, background, seasonNumber, episodeNumber, episodeTitle, episodeThumbnail, pauseDescription, resumePositionMs ->
|
|
||||||
launchPlaybackWithDownloadPreference(
|
launchPlaybackWithDownloadPreference(
|
||||||
type = type,
|
type = item.parentMetaType,
|
||||||
videoId = videoId,
|
videoId = item.videoId,
|
||||||
parentMetaId = parentMetaId,
|
parentMetaId = item.parentMetaId,
|
||||||
parentMetaType = parentMetaType,
|
parentMetaType = item.parentMetaType,
|
||||||
title = title,
|
title = item.title,
|
||||||
logo = logo,
|
logo = item.logo,
|
||||||
poster = poster,
|
poster = item.poster,
|
||||||
background = background,
|
background = item.background,
|
||||||
seasonNumber = seasonNumber,
|
seasonNumber = item.seasonNumber,
|
||||||
episodeNumber = episodeNumber,
|
episodeNumber = item.episodeNumber,
|
||||||
episodeTitle = episodeTitle,
|
episodeTitle = item.episodeTitle,
|
||||||
episodeThumbnail = episodeThumbnail,
|
episodeThumbnail = item.episodeThumbnail,
|
||||||
pauseDescription = pauseDescription,
|
pauseDescription = item.pauseDescription,
|
||||||
resumePositionMs = resumePositionMs,
|
resumePositionMs = item.resumePositionMs,
|
||||||
resumeProgressFraction = null,
|
resumeProgressFraction = item.resumeProgressFraction,
|
||||||
manualSelection = true,
|
manualSelection = manualSelection,
|
||||||
startFromBeginning = false,
|
startFromBeginning = startFromBeginning,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val onCatalogClick: (HomeCatalogSection) -> Unit = { section ->
|
val onContinueWatchingClick: (ContinueWatchingItem) -> Unit = { item ->
|
||||||
navController.navigate(
|
openContinueWatching(item, false, false)
|
||||||
CatalogRoute(
|
}
|
||||||
title = section.title,
|
|
||||||
subtitle = section.subtitle,
|
|
||||||
manifestUrl = section.manifestUrl,
|
|
||||||
type = section.type,
|
|
||||||
catalogId = section.catalogId,
|
|
||||||
supportsPagination = section.supportsPagination,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val librarySectionSubtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
val onContinueWatchingStartFromBeginning: (ContinueWatchingItem) -> Unit = { item ->
|
||||||
stringResource(Res.string.compose_catalog_subtitle_trakt_library)
|
openContinueWatching(item, false, true)
|
||||||
} else {
|
}
|
||||||
stringResource(Res.string.compose_catalog_subtitle_library)
|
|
||||||
}
|
|
||||||
|
|
||||||
val onLibrarySectionViewAllClick: (LibrarySection) -> Unit = { section ->
|
val onContinueWatchingPlayManually: (ContinueWatchingItem) -> Unit = { item ->
|
||||||
navController.navigate(
|
openContinueWatching(item, true, false)
|
||||||
CatalogRoute(
|
}
|
||||||
title = section.displayTitle,
|
|
||||||
subtitle = librarySectionSubtitle,
|
|
||||||
manifestUrl = INTERNAL_LIBRARY_MANIFEST_URL,
|
|
||||||
type = section.items.firstOrNull()?.type ?: "movie",
|
|
||||||
catalogId = section.type,
|
|
||||||
supportsPagination = false,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val openContinueWatching: (ContinueWatchingItem, Boolean, Boolean) -> Unit = { item, manualSelection, startFromBeginning ->
|
val onContinueWatchingLongPress: (ContinueWatchingItem) -> Unit = { item ->
|
||||||
launchPlaybackWithDownloadPreference(
|
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
type = item.parentMetaType,
|
selectedContinueWatchingForActions = item
|
||||||
videoId = item.videoId,
|
}
|
||||||
parentMetaId = item.parentMetaId,
|
|
||||||
parentMetaType = item.parentMetaType,
|
|
||||||
title = item.title,
|
|
||||||
logo = item.logo,
|
|
||||||
poster = item.poster,
|
|
||||||
background = item.background,
|
|
||||||
seasonNumber = item.seasonNumber,
|
|
||||||
episodeNumber = item.episodeNumber,
|
|
||||||
episodeTitle = item.episodeTitle,
|
|
||||||
episodeThumbnail = item.episodeThumbnail,
|
|
||||||
pauseDescription = item.pauseDescription,
|
|
||||||
resumePositionMs = item.resumePositionMs,
|
|
||||||
resumeProgressFraction = item.resumeProgressFraction,
|
|
||||||
manualSelection = manualSelection,
|
|
||||||
startFromBeginning = startFromBeginning,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val onContinueWatchingClick: (ContinueWatchingItem) -> Unit = { item ->
|
Box(
|
||||||
openContinueWatching(item, false, false)
|
modifier = Modifier
|
||||||
}
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background),
|
||||||
val onContinueWatchingStartFromBeginning: (ContinueWatchingItem) -> Unit = { item ->
|
) {
|
||||||
openContinueWatching(item, false, true)
|
SharedTransitionLayout {
|
||||||
}
|
NavHost(
|
||||||
|
navController = navController,
|
||||||
val onContinueWatchingPlayManually: (ContinueWatchingItem) -> Unit = { item ->
|
startDestination = TabsRoute,
|
||||||
openContinueWatching(item, true, false)
|
modifier = Modifier.fillMaxSize(),
|
||||||
}
|
) {
|
||||||
|
|
||||||
val onContinueWatchingLongPress: (ContinueWatchingItem) -> Unit = { item ->
|
|
||||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
|
||||||
selectedContinueWatchingForActions = item
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.background(MaterialTheme.colorScheme.background),
|
|
||||||
) {
|
|
||||||
SharedTransitionLayout {
|
|
||||||
NavHost(
|
|
||||||
navController = navController,
|
|
||||||
startDestination = TabsRoute,
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
) {
|
|
||||||
composable<TabsRoute> {
|
composable<TabsRoute> {
|
||||||
PlatformBackHandler(
|
PlatformBackHandler(
|
||||||
enabled = true,
|
enabled = true,
|
||||||
|
|
@ -1303,8 +1273,8 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
val shouldResolveEpisodeVideoId =
|
val shouldResolveEpisodeVideoId =
|
||||||
launch.parentMetaId != null &&
|
launch.parentMetaId != null &&
|
||||||
launch.seasonNumber != null &&
|
launch.seasonNumber != null &&
|
||||||
launch.episodeNumber != null
|
launch.episodeNumber != null
|
||||||
var effectiveVideoId by rememberSaveable(
|
var effectiveVideoId by rememberSaveable(
|
||||||
launch.videoId,
|
launch.videoId,
|
||||||
launch.parentMetaId,
|
launch.parentMetaId,
|
||||||
|
|
@ -1345,7 +1315,7 @@ private fun MainAppContent(
|
||||||
?.videos
|
?.videos
|
||||||
?.firstOrNull { video ->
|
?.firstOrNull { video ->
|
||||||
video.season == launch.seasonNumber &&
|
video.season == launch.seasonNumber &&
|
||||||
video.episode == launch.episodeNumber
|
video.episode == launch.episodeNumber
|
||||||
}
|
}
|
||||||
?.id
|
?.id
|
||||||
?.takeIf { it.isNotBlank() }
|
?.takeIf { it.isNotBlank() }
|
||||||
|
|
@ -1818,8 +1788,8 @@ private fun MainAppContent(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
NuvioPosterActionSheet(
|
NuvioPosterActionSheet(
|
||||||
item = selectedPosterForActions,
|
item = selectedPosterForActions,
|
||||||
|
|
@ -1857,94 +1827,73 @@ private fun MainAppContent(
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
pickerError = error.message ?: getString(Res.string.trakt_lists_load_failed)
|
pickerError = error.message ?: getString(Res.string.trakt_lists_load_failed)
|
||||||
}
|
}
|
||||||
}.onFailure { error ->
|
pickerPending = false
|
||||||
pickerError = error.message ?: getString(Res.string.trakt_lists_load_failed)
|
|
||||||
}
|
}
|
||||||
pickerPending = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
onToggleWatched = {
|
||||||
onToggleWatched = {
|
selectedPosterForActions?.let { preview ->
|
||||||
selectedPosterForActions?.let { preview ->
|
coroutineScope.launch {
|
||||||
coroutineScope.launch {
|
WatchingActions.togglePosterWatched(preview)
|
||||||
WatchingActions.togglePosterWatched(preview)
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
)
|
||||||
)
|
|
||||||
|
|
||||||
NuvioContinueWatchingActionSheet(
|
NuvioContinueWatchingActionSheet(
|
||||||
item = selectedContinueWatchingForActions,
|
item = selectedContinueWatchingForActions,
|
||||||
showManualPlayOption = StreamAutoPlayPolicy.isEffectivelyEnabled(playerSettingsUiState),
|
showManualPlayOption = StreamAutoPlayPolicy.isEffectivelyEnabled(playerSettingsUiState),
|
||||||
onDismiss = { selectedContinueWatchingForActions = null },
|
onDismiss = { selectedContinueWatchingForActions = null },
|
||||||
onOpenDetails = {
|
onOpenDetails = {
|
||||||
selectedContinueWatchingForActions?.let { item ->
|
selectedContinueWatchingForActions?.let { item ->
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
DetailRoute(
|
DetailRoute(
|
||||||
type = item.parentMetaType,
|
type = item.parentMetaType,
|
||||||
id = item.parentMetaId,
|
id = item.parentMetaId,
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onStartFromBeginning = selectedContinueWatchingForActions
|
|
||||||
?.takeIf { !it.isNextUp }
|
|
||||||
?.let { item -> { onContinueWatchingStartFromBeginning(item) } },
|
|
||||||
onPlayManually = selectedContinueWatchingForActions
|
|
||||||
?.let { item -> { onContinueWatchingPlayManually(item) } },
|
|
||||||
onRemove = {
|
|
||||||
selectedContinueWatchingForActions?.let { item ->
|
|
||||||
if (item.isNextUp) {
|
|
||||||
ContinueWatchingPreferencesRepository.addDismissedNextUpKey(
|
|
||||||
nextUpDismissKey(
|
|
||||||
item.parentMetaId,
|
|
||||||
item.nextUpSeedSeasonNumber,
|
|
||||||
item.nextUpSeedEpisodeNumber,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
WatchProgressRepository.removeProgress(contentId = item.parentMetaId)
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
onStartFromBeginning = selectedContinueWatchingForActions
|
||||||
)
|
?.takeIf { !it.isNextUp }
|
||||||
|
?.let { item -> { onContinueWatchingStartFromBeginning(item) } },
|
||||||
|
onPlayManually = selectedContinueWatchingForActions
|
||||||
|
?.let { item -> { onContinueWatchingPlayManually(item) } },
|
||||||
|
onRemove = {
|
||||||
|
selectedContinueWatchingForActions?.let { item ->
|
||||||
|
if (item.isNextUp) {
|
||||||
|
ContinueWatchingPreferencesRepository.addDismissedNextUpKey(
|
||||||
|
nextUpDismissKey(
|
||||||
|
item.parentMetaId,
|
||||||
|
item.nextUpSeedSeasonNumber,
|
||||||
|
item.nextUpSeedEpisodeNumber,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
WatchProgressRepository.removeProgress(contentId = item.parentMetaId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
TraktListPickerDialog(
|
TraktListPickerDialog(
|
||||||
visible = showLibraryListPicker,
|
visible = showLibraryListPicker,
|
||||||
title = pickerTitle,
|
title = pickerTitle,
|
||||||
tabs = pickerTabs,
|
tabs = pickerTabs,
|
||||||
membership = pickerMembership,
|
membership = pickerMembership,
|
||||||
isPending = pickerPending,
|
isPending = pickerPending,
|
||||||
errorMessage = pickerError,
|
errorMessage = pickerError,
|
||||||
onToggle = { listKey ->
|
onToggle = { listKey ->
|
||||||
pickerMembership = pickerMembership.toMutableMap().apply {
|
pickerMembership = pickerMembership.toMutableMap().apply {
|
||||||
this[listKey] = !(this[listKey] == true)
|
this[listKey] = !(this[listKey] == true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
if (!pickerPending) {
|
if (!pickerPending) {
|
||||||
showLibraryListPicker = false
|
|
||||||
pickerItem = null
|
|
||||||
pickerError = null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSave = {
|
|
||||||
val item = pickerItem ?: return@TraktListPickerDialog
|
|
||||||
coroutineScope.launch {
|
|
||||||
pickerPending = true
|
|
||||||
pickerError = null
|
|
||||||
runCatching {
|
|
||||||
LibraryRepository.applyMembershipChanges(
|
|
||||||
item = item,
|
|
||||||
desiredMembership = pickerMembership,
|
|
||||||
)
|
|
||||||
}.onSuccess {
|
|
||||||
showLibraryListPicker = false
|
showLibraryListPicker = false
|
||||||
pickerItem = null
|
pickerItem = null
|
||||||
pickerError = null
|
pickerError = null
|
||||||
}.onFailure { error ->
|
|
||||||
pickerError = error.message ?: getString(Res.string.trakt_lists_update_failed)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSave = {
|
onSave = {
|
||||||
|
|
@ -1984,22 +1933,22 @@ private fun MainAppContent(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
androidx.compose.animation.AnimatedVisibility(
|
androidx.compose.animation.AnimatedVisibility(
|
||||||
visible = !initialHomeReady || profileSwitchLoading,
|
visible = !initialHomeReady || profileSwitchLoading,
|
||||||
enter = fadeIn(),
|
enter = fadeIn(),
|
||||||
exit = fadeOut(androidx.compose.animation.core.tween(400)),
|
exit = fadeOut(androidx.compose.animation.core.tween(400)),
|
||||||
) {
|
) {
|
||||||
AppLaunchOverlay(modifier = Modifier.fillMaxSize())
|
AppLaunchOverlay(modifier = Modifier.fillMaxSize())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-dismiss profile switch overlay
|
// Auto-dismiss profile switch overlay
|
||||||
if (profileSwitchLoading) {
|
if (profileSwitchLoading) {
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
// Brief loading screen while home refreshes for the new profile
|
// Brief loading screen while home refreshes for the new profile
|
||||||
kotlinx.coroutines.delay(1200)
|
kotlinx.coroutines.delay(1200)
|
||||||
profileSwitchLoading = false
|
profileSwitchLoading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
NuvioFloatingPrompt(
|
NuvioFloatingPrompt(
|
||||||
visible = resumePromptItem != null,
|
visible = resumePromptItem != null,
|
||||||
|
|
@ -2019,19 +1968,19 @@ private fun MainAppContent(
|
||||||
.zIndex(15f),
|
.zIndex(15f),
|
||||||
)
|
)
|
||||||
|
|
||||||
NuvioToastHost(
|
NuvioToastHost(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.TopCenter)
|
.align(Alignment.TopCenter)
|
||||||
.zIndex(20f),
|
.zIndex(20f),
|
||||||
)
|
)
|
||||||
|
|
||||||
AppUpdaterHost(
|
AppUpdaterHost(
|
||||||
controller = appUpdaterController,
|
controller = appUpdaterController,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
.zIndex(25f),
|
.zIndex(25f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -2063,7 +2012,6 @@ private fun AppTabHost(
|
||||||
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
||||||
onPosterLongClick: ((MetaPreview) -> Unit)? = null,
|
onPosterLongClick: ((MetaPreview) -> Unit)? = null,
|
||||||
onLibraryPosterClick: ((LibraryItem) -> Unit)? = null,
|
onLibraryPosterClick: ((LibraryItem) -> Unit)? = null,
|
||||||
onLibraryPosterLongClick: ((LibraryItem) -> Unit)? = null,
|
|
||||||
onLibrarySectionViewAllClick: ((LibrarySection) -> Unit)? = null,
|
onLibrarySectionViewAllClick: ((LibrarySection) -> Unit)? = null,
|
||||||
onContinueWatchingClick: ((ContinueWatchingItem) -> Unit)? = null,
|
onContinueWatchingClick: ((ContinueWatchingItem) -> Unit)? = null,
|
||||||
onContinueWatchingLongPress: ((ContinueWatchingItem) -> Unit)? = null,
|
onContinueWatchingLongPress: ((ContinueWatchingItem) -> Unit)? = null,
|
||||||
|
|
@ -2113,7 +2061,6 @@ private fun AppTabHost(
|
||||||
LibraryScreen(
|
LibraryScreen(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
onPosterClick = onLibraryPosterClick,
|
onPosterClick = onLibraryPosterClick,
|
||||||
onPosterLongClick = onLibraryPosterLongClick,
|
|
||||||
onSectionViewAllClick = onLibrarySectionViewAllClick,
|
onSectionViewAllClick = onLibrarySectionViewAllClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue