mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 23:12:12 +00:00
Refactor playback launch logic and navigation
Refactor launchPlaybackWithDownloadPreference to use StreamLaunchStore for launching streams and update related navigation logic.
This commit is contained in:
parent
727b48bbc8
commit
5b5a8b6906
1 changed files with 102 additions and 166 deletions
|
|
@ -656,6 +656,11 @@ private fun MainAppContent(
|
||||||
AppDeepLinkRepository.markConsumed(deepLink)
|
AppDeepLinkRepository.markConsumed(deepLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
null -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun launchPlaybackWithDownloadPreference(
|
fun launchPlaybackWithDownloadPreference(
|
||||||
type: String,
|
type: String,
|
||||||
videoId: String,
|
videoId: String,
|
||||||
|
|
@ -717,46 +722,14 @@ private fun MainAppContent(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun launchPlaybackWithDownloadPreference(
|
val streamLaunchId = StreamLaunchStore.put(
|
||||||
type: String,
|
StreamLaunch(
|
||||||
videoId: String,
|
type = type,
|
||||||
parentMetaId: String,
|
|
||||||
parentMetaType: String,
|
|
||||||
title: String,
|
|
||||||
logo: String?,
|
|
||||||
poster: String?,
|
|
||||||
background: String?,
|
|
||||||
seasonNumber: Int?,
|
|
||||||
episodeNumber: Int?,
|
|
||||||
episodeTitle: String?,
|
|
||||||
episodeThumbnail: String?,
|
|
||||||
pauseDescription: String?,
|
|
||||||
resumePositionMs: Long?,
|
|
||||||
resumeProgressFraction: Float?,
|
|
||||||
manualSelection: Boolean,
|
|
||||||
startFromBeginning: Boolean,
|
|
||||||
) {
|
|
||||||
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,
|
videoId = videoId,
|
||||||
)
|
parentMetaId = parentMetaId,
|
||||||
val localSourceUrl = downloadedItem?.localFileUri
|
parentMetaType = parentMetaType,
|
||||||
if (!localSourceUrl.isNullOrBlank()) {
|
|
||||||
val launchId = PlayerLaunchStore.put(
|
|
||||||
PlayerLaunch(
|
|
||||||
title = title,
|
title = title,
|
||||||
sourceUrl = localSourceUrl,
|
|
||||||
sourceHeaders = emptyMap(),
|
|
||||||
sourceResponseHeaders = emptyMap(),
|
|
||||||
logo = logo,
|
logo = logo,
|
||||||
poster = poster,
|
poster = poster,
|
||||||
background = background,
|
background = background,
|
||||||
|
|
@ -764,40 +737,38 @@ private fun MainAppContent(
|
||||||
episodeNumber = episodeNumber,
|
episodeNumber = episodeNumber,
|
||||||
episodeTitle = episodeTitle,
|
episodeTitle = episodeTitle,
|
||||||
episodeThumbnail = episodeThumbnail,
|
episodeThumbnail = episodeThumbnail,
|
||||||
streamTitle = downloadedItem.streamTitle.ifBlank { title },
|
|
||||||
streamSubtitle = downloadedItem.streamSubtitle,
|
|
||||||
pauseDescription = pauseDescription,
|
pauseDescription = pauseDescription,
|
||||||
providerName = downloadedItem.providerName.ifBlank { "Downloaded" },
|
resumePositionMs = if (startFromBeginning) 0L else resumePositionMs,
|
||||||
providerAddonId = downloadedItem.providerAddonId,
|
resumeProgressFraction = targetResumeProgressFraction,
|
||||||
contentType = type,
|
manualSelection = manualSelection,
|
||||||
|
startFromBeginning = startFromBeginning,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
navController.navigate(
|
||||||
|
StreamRoute(launchId = streamLaunchId),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val onPlay: (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,
|
videoId = videoId,
|
||||||
parentMetaId = parentMetaId,
|
parentMetaId = parentMetaId,
|
||||||
parentMetaType = parentMetaType,
|
parentMetaType = parentMetaType,
|
||||||
initialPositionMs = targetResumePositionMs,
|
title = title,
|
||||||
initialProgressFraction = targetResumeProgressFraction,
|
logo = logo,
|
||||||
),
|
poster = poster,
|
||||||
)
|
background = background,
|
||||||
navController.navigate(PlayerRoute(launchId = launchId))
|
seasonNumber = seasonNumber,
|
||||||
return
|
episodeNumber = episodeNumber,
|
||||||
}
|
episodeTitle = episodeTitle,
|
||||||
}
|
episodeThumbnail = episodeThumbnail,
|
||||||
|
pauseDescription = pauseDescription,
|
||||||
val librarySectionSubtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
resumePositionMs = resumePositionMs,
|
||||||
stringResource(Res.string.compose_catalog_subtitle_trakt_library)
|
resumeProgressFraction = null,
|
||||||
} else {
|
manualSelection = false,
|
||||||
stringResource(Res.string.compose_catalog_subtitle_library)
|
startFromBeginning = false,
|
||||||
}
|
|
||||||
|
|
||||||
val onLibrarySectionViewAllClick: (LibrarySection) -> Unit = { section ->
|
|
||||||
navController.navigate(
|
|
||||||
CatalogRoute(
|
|
||||||
title = section.displayTitle,
|
|
||||||
subtitle = librarySectionSubtitle,
|
|
||||||
manifestUrl = INTERNAL_LIBRARY_MANIFEST_URL,
|
|
||||||
type = section.items.firstOrNull()?.type ?: "movie",
|
|
||||||
catalogId = section.type,
|
|
||||||
supportsPagination = false,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -837,15 +808,17 @@ private fun MainAppContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val librarySectionSubtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
||||||
|
stringResource(Res.string.compose_catalog_subtitle_trakt_library)
|
||||||
|
} else {
|
||||||
|
stringResource(Res.string.compose_catalog_subtitle_library)
|
||||||
|
}
|
||||||
|
|
||||||
val onLibrarySectionViewAllClick: (LibrarySection) -> Unit = { section ->
|
val onLibrarySectionViewAllClick: (LibrarySection) -> Unit = { section ->
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
CatalogRoute(
|
CatalogRoute(
|
||||||
title = section.displayTitle,
|
title = section.displayTitle,
|
||||||
subtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
subtitle = librarySectionSubtitle,
|
||||||
"Trakt Library"
|
|
||||||
} else {
|
|
||||||
"Library"
|
|
||||||
},
|
|
||||||
manifestUrl = INTERNAL_LIBRARY_MANIFEST_URL,
|
manifestUrl = INTERNAL_LIBRARY_MANIFEST_URL,
|
||||||
type = section.items.firstOrNull()?.type ?: "movie",
|
type = section.items.firstOrNull()?.type ?: "movie",
|
||||||
catalogId = section.type,
|
catalogId = section.type,
|
||||||
|
|
@ -986,7 +959,7 @@ private fun MainAppContent(
|
||||||
},
|
},
|
||||||
onLibraryPosterLongClick = { item ->
|
onLibraryPosterLongClick = { item ->
|
||||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
selectedPosterForActions = item.toMetaPreview() // reuse existing sheet
|
selectedPosterForActions = item.toMetaPreview()
|
||||||
},
|
},
|
||||||
onLibrarySectionViewAllClick = onLibrarySectionViewAllClick,
|
onLibrarySectionViewAllClick = onLibrarySectionViewAllClick,
|
||||||
onContinueWatchingClick = onContinueWatchingClick,
|
onContinueWatchingClick = onContinueWatchingClick,
|
||||||
|
|
@ -1689,34 +1662,15 @@ private fun MainAppContent(
|
||||||
)
|
)
|
||||||
} == true,
|
} == true,
|
||||||
onDismiss = { selectedPosterForActions = null },
|
onDismiss = { selectedPosterForActions = null },
|
||||||
|
// TAP → direct save/remove (watchlist or local library)
|
||||||
onToggleLibrary = {
|
onToggleLibrary = {
|
||||||
selectedPosterForActions?.let { preview ->
|
selectedPosterForActions?.let { preview ->
|
||||||
val libraryItem = preview.toLibraryItem(savedAtEpochMs = 0L)
|
val libraryItem = preview.toLibraryItem(savedAtEpochMs = 0L)
|
||||||
if (!isTraktConnected) {
|
|
||||||
LibraryRepository.toggleSaved(libraryItem)
|
LibraryRepository.toggleSaved(libraryItem)
|
||||||
} else {
|
|
||||||
// Tap = directly toggle watchlist (first tab)
|
|
||||||
coroutineScope.launch {
|
|
||||||
runCatching {
|
|
||||||
val snapshot = LibraryRepository.getMembershipSnapshot(libraryItem)
|
|
||||||
val tabs = LibraryRepository.traktListTabs()
|
|
||||||
val watchlistKey = tabs.firstOrNull()?.key
|
|
||||||
if (watchlistKey != null) {
|
|
||||||
val currentlyIn = snapshot[watchlistKey] == true
|
|
||||||
val desired = tabs.associate { tab ->
|
|
||||||
tab.key to if (tab.key == watchlistKey) !currentlyIn else (snapshot[tab.key] == true)
|
|
||||||
}
|
|
||||||
}.onFailure { error ->
|
|
||||||
pickerError = error.message ?: getString(Res.string.trakt_lists_load_failed)
|
|
||||||
}
|
|
||||||
}.onFailure {
|
|
||||||
LibraryRepository.toggleSaved(libraryItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenListPicker = if (isTraktConnected) {
|
// LONG PRESS → open Trakt list picker (only when Trakt is connected)
|
||||||
|
onToggleLibraryLongClick = if (isTraktConnected) {
|
||||||
{
|
{
|
||||||
selectedPosterForActions?.let { preview ->
|
selectedPosterForActions?.let { preview ->
|
||||||
val libraryItem = preview.toLibraryItem(savedAtEpochMs = 0L)
|
val libraryItem = preview.toLibraryItem(savedAtEpochMs = 0L)
|
||||||
|
|
@ -1736,7 +1690,7 @@ private fun MainAppContent(
|
||||||
tab.key to (snapshot[tab.key] == true)
|
tab.key to (snapshot[tab.key] == true)
|
||||||
}
|
}
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
pickerError = error.message ?: "Failed to load Trakt lists"
|
pickerError = error.message ?: getString(Res.string.trakt_lists_load_failed)
|
||||||
}
|
}
|
||||||
pickerPending = false
|
pickerPending = false
|
||||||
}
|
}
|
||||||
|
|
@ -1807,24 +1761,6 @@ private fun MainAppContent(
|
||||||
pickerError = 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
|
|
||||||
pickerItem = null
|
|
||||||
pickerError = null
|
|
||||||
}.onFailure { error ->
|
|
||||||
pickerError = error.message ?: "Failed to update Trakt lists"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSave = {
|
onSave = {
|
||||||
val item = pickerItem ?: return@TraktListPickerDialog
|
val item = pickerItem ?: return@TraktListPickerDialog
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
|
|
@ -1940,6 +1876,7 @@ 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,
|
||||||
|
|
@ -1956,7 +1893,6 @@ private fun AppTabHost(
|
||||||
onCollectionsSettingsClick: () -> Unit = {},
|
onCollectionsSettingsClick: () -> Unit = {},
|
||||||
onFolderClick: ((collectionId: String, folderId: String) -> Unit)? = null,
|
onFolderClick: ((collectionId: String, folderId: String) -> Unit)? = null,
|
||||||
onInitialHomeContentRendered: () -> Unit = {},
|
onInitialHomeContentRendered: () -> Unit = {},
|
||||||
onLibraryPosterLongClick: ((LibraryItem) -> Unit)? = null,
|
|
||||||
) {
|
) {
|
||||||
val tabStateHolder = rememberSaveableStateHolder()
|
val tabStateHolder = rememberSaveableStateHolder()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue