mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-07-26 22:42:17 +00:00
fix: multiple ios crashes
This commit is contained in:
parent
f2ef1e1383
commit
3e49c78de7
2 changed files with 80 additions and 80 deletions
|
|
@ -47,12 +47,14 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.withFrameNanos
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -111,7 +113,6 @@ import com.nuvio.app.features.addons.AddonRepository
|
|||
import com.nuvio.app.features.catalog.CatalogRepository
|
||||
import com.nuvio.app.features.catalog.CatalogScreen
|
||||
import com.nuvio.app.features.catalog.CatalogTarget
|
||||
import com.nuvio.app.features.catalog.CatalogTargetKind
|
||||
import com.nuvio.app.features.cloud.CloudLibraryContentType
|
||||
import com.nuvio.app.features.cloud.CloudLibraryFile
|
||||
import com.nuvio.app.features.cloud.CloudLibraryItem
|
||||
|
|
@ -303,65 +304,30 @@ data class StreamRoute(
|
|||
|
||||
@Serializable
|
||||
data class CatalogRoute(
|
||||
val launchId: Long,
|
||||
)
|
||||
|
||||
private data class CatalogLaunch(
|
||||
val title: String,
|
||||
val subtitle: String,
|
||||
val targetKind: String,
|
||||
val contentType: String,
|
||||
val supportsPagination: Boolean = false,
|
||||
val manifestUrl: String? = null,
|
||||
val addonCatalogId: String? = null,
|
||||
val genre: String? = null,
|
||||
val librarySectionType: String? = null,
|
||||
val collectionId: String? = null,
|
||||
val folderId: String? = null,
|
||||
val sourceKey: String? = null,
|
||||
) {
|
||||
constructor(
|
||||
title: String,
|
||||
subtitle: String,
|
||||
target: CatalogTarget,
|
||||
) : this(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
targetKind = when (target) {
|
||||
is CatalogTarget.Addon -> CatalogTargetKind.ADDON
|
||||
is CatalogTarget.Library -> CatalogTargetKind.LIBRARY
|
||||
is CatalogTarget.CollectionSource -> CatalogTargetKind.COLLECTION_SOURCE
|
||||
}.name,
|
||||
contentType = target.contentType,
|
||||
supportsPagination = target.supportsPagination,
|
||||
manifestUrl = (target as? CatalogTarget.Addon)?.manifestUrl,
|
||||
addonCatalogId = (target as? CatalogTarget.Addon)?.catalogId,
|
||||
genre = (target as? CatalogTarget.Addon)?.genre,
|
||||
librarySectionType = (target as? CatalogTarget.Library)?.sectionType,
|
||||
collectionId = (target as? CatalogTarget.CollectionSource)?.collectionId,
|
||||
folderId = (target as? CatalogTarget.CollectionSource)?.folderId,
|
||||
sourceKey = (target as? CatalogTarget.CollectionSource)?.sourceKey,
|
||||
)
|
||||
val target: CatalogTarget,
|
||||
)
|
||||
|
||||
fun toCatalogTarget(): CatalogTarget =
|
||||
when (CatalogTargetKind.valueOf(targetKind)) {
|
||||
CatalogTargetKind.ADDON -> CatalogTarget.Addon(
|
||||
manifestUrl = requireNotNull(manifestUrl),
|
||||
contentType = contentType,
|
||||
catalogId = requireNotNull(addonCatalogId),
|
||||
genre = genre,
|
||||
supportsPagination = supportsPagination,
|
||||
)
|
||||
private object CatalogLaunchStore {
|
||||
private var nextLaunchId = 1L
|
||||
private val launches = mutableMapOf<Long, CatalogLaunch>()
|
||||
|
||||
CatalogTargetKind.LIBRARY -> CatalogTarget.Library(
|
||||
contentType = contentType,
|
||||
sectionType = requireNotNull(librarySectionType),
|
||||
)
|
||||
fun put(launch: CatalogLaunch): Long {
|
||||
val launchId = nextLaunchId++
|
||||
launches[launchId] = launch
|
||||
return launchId
|
||||
}
|
||||
|
||||
CatalogTargetKind.COLLECTION_SOURCE -> CatalogTarget.CollectionSource(
|
||||
collectionId = requireNotNull(collectionId),
|
||||
folderId = requireNotNull(folderId),
|
||||
sourceKey = requireNotNull(sourceKey),
|
||||
contentType = contentType,
|
||||
supportsPagination = supportsPagination,
|
||||
)
|
||||
}
|
||||
fun get(launchId: Long): CatalogLaunch? = launches[launchId]
|
||||
|
||||
fun remove(launchId: Long) {
|
||||
launches.remove(launchId)
|
||||
}
|
||||
}
|
||||
|
||||
private data class PosterActionTarget(
|
||||
|
|
@ -726,6 +692,7 @@ private fun MainAppContent(
|
|||
ProfileSettingsSync.startObserving()
|
||||
}
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val focusManager = LocalFocusManager.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var selectedTab by rememberSaveable { mutableStateOf(AppScreenTab.Home) }
|
||||
var searchFocusRequestCount by remember { mutableStateOf(0) }
|
||||
|
|
@ -758,6 +725,14 @@ private fun MainAppContent(
|
|||
LibraryRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val authState by AuthRepository.state.collectAsStateWithLifecycle()
|
||||
val openPosterActions: (PosterActionTarget) -> Unit = { target ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
focusManager.clearFocus(force = true)
|
||||
coroutineScope.launch {
|
||||
withFrameNanos { }
|
||||
selectedPosterActionTarget = target
|
||||
}
|
||||
}
|
||||
val profileState by ProfileRepository.state.collectAsStateWithLifecycle()
|
||||
val playerSettingsUiState by remember {
|
||||
PlayerSettingsRepository.ensureLoaded()
|
||||
|
|
@ -1297,13 +1272,18 @@ private fun MainAppContent(
|
|||
}
|
||||
|
||||
val onCatalogClick: (HomeCatalogSection) -> Unit = { section ->
|
||||
navController.navigate(
|
||||
CatalogRoute(
|
||||
val launchId = CatalogLaunchStore.put(
|
||||
CatalogLaunch(
|
||||
title = section.title,
|
||||
subtitle = section.subtitle,
|
||||
target = section.target,
|
||||
),
|
||||
)
|
||||
navController.navigate(
|
||||
CatalogRoute(
|
||||
launchId = launchId,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val librarySectionSubtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
||||
|
|
@ -1313,8 +1293,8 @@ private fun MainAppContent(
|
|||
}
|
||||
|
||||
val onLibrarySectionViewAllClick: (LibrarySection) -> Unit = { section ->
|
||||
navController.navigate(
|
||||
CatalogRoute(
|
||||
val launchId = CatalogLaunchStore.put(
|
||||
CatalogLaunch(
|
||||
title = section.displayTitle,
|
||||
subtitle = librarySectionSubtitle,
|
||||
target = CatalogTarget.Library(
|
||||
|
|
@ -1323,6 +1303,11 @@ private fun MainAppContent(
|
|||
),
|
||||
),
|
||||
)
|
||||
navController.navigate(
|
||||
CatalogRoute(
|
||||
launchId = launchId,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val openContinueWatching: (ContinueWatchingItem, Boolean, Boolean) -> Unit = { item, manualSelection, startFromBeginning ->
|
||||
|
|
@ -1505,18 +1490,18 @@ private fun MainAppContent(
|
|||
navController.navigate(DetailRoute(type = meta.type, id = meta.id))
|
||||
},
|
||||
onPosterLongClick = { meta ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
selectedPosterActionTarget = PosterActionTarget(preview = meta)
|
||||
openPosterActions(PosterActionTarget(preview = meta))
|
||||
},
|
||||
onLibraryPosterClick = { item ->
|
||||
navController.navigate(DetailRoute(type = item.type, id = item.id))
|
||||
},
|
||||
onLibraryPosterLongClick = { item, section ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
selectedPosterActionTarget = PosterActionTarget(
|
||||
preview = item.toMetaPreview(),
|
||||
libraryItem = item,
|
||||
libraryListKey = section.type,
|
||||
openPosterActions(
|
||||
PosterActionTarget(
|
||||
preview = item.toMetaPreview(),
|
||||
libraryItem = item,
|
||||
libraryListKey = section.type,
|
||||
),
|
||||
)
|
||||
},
|
||||
onLibrarySectionViewAllClick = onLibrarySectionViewAllClick,
|
||||
|
|
@ -2487,29 +2472,38 @@ private fun MainAppContent(
|
|||
}
|
||||
composable<CatalogRoute> { backStackEntry ->
|
||||
val route = backStackEntry.toRoute<CatalogRoute>()
|
||||
val target = route.toCatalogTarget()
|
||||
val launch = remember(route.launchId) { CatalogLaunchStore.get(route.launchId) }
|
||||
if (launch == null) {
|
||||
LaunchedEffect(route.launchId) {
|
||||
navController.popBackStack()
|
||||
}
|
||||
return@composable
|
||||
}
|
||||
val target = launch.target
|
||||
CatalogScreen(
|
||||
title = route.title,
|
||||
subtitle = route.subtitle,
|
||||
title = launch.title,
|
||||
subtitle = launch.subtitle,
|
||||
target = target,
|
||||
onBack = {
|
||||
CatalogRepository.clear()
|
||||
CatalogLaunchStore.remove(route.launchId)
|
||||
navController.popBackStack()
|
||||
},
|
||||
onPosterClick = { meta ->
|
||||
navController.navigate(DetailRoute(type = meta.type, id = meta.id))
|
||||
},
|
||||
onPosterLongClick = { meta ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
selectedPosterActionTarget = if (target is CatalogTarget.Library) {
|
||||
PosterActionTarget(
|
||||
preview = meta,
|
||||
libraryItem = meta.toLibraryItem(savedAtEpochMs = 0L),
|
||||
libraryListKey = target.sectionType,
|
||||
)
|
||||
} else {
|
||||
PosterActionTarget(preview = meta)
|
||||
}
|
||||
openPosterActions(
|
||||
if (target is CatalogTarget.Library) {
|
||||
PosterActionTarget(
|
||||
preview = meta,
|
||||
libraryItem = meta.toLibraryItem(savedAtEpochMs = 0L),
|
||||
libraryListKey = target.sectionType,
|
||||
)
|
||||
} else {
|
||||
PosterActionTarget(preview = meta)
|
||||
},
|
||||
)
|
||||
},
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ import androidx.compose.foundation.layout.Row
|
|||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
|
|
@ -86,7 +88,10 @@ fun SubmitIntroDialog(
|
|||
|
||||
BasicAlertDialog(onDismissRequest = onDismiss) {
|
||||
Surface(
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 24.dp),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp, vertical = 24.dp)
|
||||
.widthIn(max = 420.dp)
|
||||
.heightIn(max = 560.dp),
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
tonalElevation = 8.dp,
|
||||
|
|
@ -94,6 +99,7 @@ fun SubmitIntroDialog(
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.padding(24.dp)
|
||||
.heightIn(max = 512.dp)
|
||||
.verticalScroll(scrollState),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue