This commit is contained in:
AdityasahuX07 2026-05-16 11:15:12 +05:30 committed by GitHub
commit 878bcdb4a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -21,10 +21,10 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.nuvio.app.core.network.NetworkCondition import com.nuvio.app.core.network.NetworkCondition
import com.nuvio.app.core.network.NetworkStatusRepository import com.nuvio.app.core.network.NetworkStatusRepository
import com.nuvio.app.core.ui.NuvioPosterActionSheet
import com.nuvio.app.core.ui.NuvioScreen import com.nuvio.app.core.ui.NuvioScreen
import com.nuvio.app.core.ui.NuvioNetworkOfflineCard import com.nuvio.app.core.ui.NuvioNetworkOfflineCard
import com.nuvio.app.core.ui.NuvioScreenHeader import com.nuvio.app.core.ui.NuvioScreenHeader
import com.nuvio.app.core.ui.NuvioStatusModal
import com.nuvio.app.core.ui.NuvioToastController import com.nuvio.app.core.ui.NuvioToastController
import com.nuvio.app.core.ui.NuvioViewAllPillSize import com.nuvio.app.core.ui.NuvioViewAllPillSize
import com.nuvio.app.core.ui.NuvioShelfSection import com.nuvio.app.core.ui.NuvioShelfSection
@ -32,15 +32,14 @@ import com.nuvio.app.features.home.components.HomeEmptyStateCard
import com.nuvio.app.features.home.components.HomePosterCard import com.nuvio.app.features.home.components.HomePosterCard
import com.nuvio.app.features.home.components.HomeSkeletonRow import com.nuvio.app.features.home.components.HomeSkeletonRow
import com.nuvio.app.features.profiles.ProfileRepository import com.nuvio.app.features.profiles.ProfileRepository
import com.nuvio.app.features.watched.WatchedRepository
import com.nuvio.app.features.watching.application.WatchingActions
import com.nuvio.app.features.watching.application.WatchingState
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import nuvio.composeapp.generated.resources.*
import org.jetbrains.compose.resources.getString
import org.jetbrains.compose.resources.stringResource
private data class LibraryRemovalTarget( private data class LibraryActionTarget(
val item: LibraryItem, val item: LibraryItem,
val listKey: String? = null, val section: LibrarySection,
val listTitle: String? = null,
) )
@Composable @Composable
@ -54,7 +53,11 @@ fun LibraryScreen(
LibraryRepository.uiState LibraryRepository.uiState
}.collectAsStateWithLifecycle() }.collectAsStateWithLifecycle()
val networkStatusUiState by NetworkStatusRepository.uiState.collectAsStateWithLifecycle() val networkStatusUiState by NetworkStatusRepository.uiState.collectAsStateWithLifecycle()
var pendingRemovalTarget by remember { mutableStateOf<LibraryRemovalTarget?>(null) } val watchedUiState by remember {
WatchedRepository.ensureLoaded()
WatchedRepository.uiState
}.collectAsStateWithLifecycle()
var actionTarget by remember { mutableStateOf<LibraryActionTarget?>(null) }
var observedOfflineState by remember { mutableStateOf(false) } var observedOfflineState by remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val isTraktSource = uiState.sourceMode == LibrarySourceMode.TRAKT val isTraktSource = uiState.sourceMode == LibrarySourceMode.TRAKT
@ -100,11 +103,7 @@ fun LibraryScreen(
.background(MaterialTheme.colorScheme.background), .background(MaterialTheme.colorScheme.background),
) { ) {
NuvioScreenHeader( NuvioScreenHeader(
title = if (isTraktSource) { title = if (isTraktSource) "Trakt Library" else "Library",
stringResource(Res.string.library_trakt_title)
} else {
stringResource(Res.string.library_title)
},
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(horizontal = 16.dp),
) )
Spacer(modifier = Modifier.height(6.dp)) Spacer(modifier = Modifier.height(6.dp))
@ -129,13 +128,9 @@ fun LibraryScreen(
} else { } else {
HomeEmptyStateCard( HomeEmptyStateCard(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(horizontal = 16.dp),
title = if (isTraktSource) { title = if (isTraktSource) "Couldn't load Trakt library" else "Couldn't load library",
stringResource(Res.string.library_trakt_load_failed)
} else {
stringResource(Res.string.library_load_failed)
},
message = uiState.errorMessage.orEmpty(), message = uiState.errorMessage.orEmpty(),
actionLabel = stringResource(Res.string.action_retry), actionLabel = "Retry",
onActionClick = retryLibraryLoad, onActionClick = retryLibraryLoad,
) )
} }
@ -153,15 +148,11 @@ fun LibraryScreen(
} else { } else {
HomeEmptyStateCard( HomeEmptyStateCard(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(horizontal = 16.dp),
title = if (isTraktSource) { title = if (isTraktSource) "Your Trakt library is empty" else "Your library is empty",
stringResource(Res.string.library_trakt_empty_title)
} else {
stringResource(Res.string.library_empty_title)
},
message = if (isTraktSource) { message = if (isTraktSource) {
stringResource(Res.string.library_trakt_empty_message) "Connect Trakt and save titles to your watchlist or personal lists."
} else { } else {
stringResource(Res.string.library_empty_message) "Saved titles will appear here after you tap Save on a details screen."
}, },
) )
} }
@ -171,63 +162,62 @@ fun LibraryScreen(
else -> { else -> {
librarySections( librarySections(
sections = uiState.sections, sections = uiState.sections,
watchedKeys = watchedUiState.watchedKeys,
onPosterClick = onPosterClick, onPosterClick = onPosterClick,
onSectionViewAllClick = onSectionViewAllClick, onSectionViewAllClick = onSectionViewAllClick,
onPosterLongClick = { item, section -> onPosterLongClick = { item, section ->
pendingRemovalTarget = if (isTraktSource) { actionTarget = LibraryActionTarget(item = item, section = section)
LibraryRemovalTarget(
item = item,
listKey = section.type,
listTitle = section.displayTitle,
)
} else {
LibraryRemovalTarget(item = item)
}
}, },
) )
} }
} }
} }
NuvioStatusModal( // Action sheet — same UI as home screen poster long-press
title = stringResource(Res.string.library_remove_title), val target = actionTarget
message = pendingRemovalTarget?.let { target -> if (target != null) {
val listTitle = target.listTitle val preview = target.item.toMetaPreview()
if (listTitle.isNullOrBlank()) { NuvioPosterActionSheet(
stringResource(Res.string.library_remove_message, target.item.name) item = preview,
} else { isSaved = LibraryRepository.isSaved(preview.id, preview.type),
stringResource(Res.string.library_remove_from_list_message, target.item.name, listTitle) isWatched = WatchingState.isPosterWatched(
} watchedKeys = watchedUiState.watchedKeys,
}.orEmpty(), item = preview,
isVisible = pendingRemovalTarget != null, ),
confirmText = stringResource(Res.string.library_remove_confirm), onDismiss = { actionTarget = null },
dismissText = stringResource(Res.string.action_cancel), onToggleLibrary = {
onConfirm = { actionTarget = null
val target = pendingRemovalTarget val libraryItem = target.item
pendingRemovalTarget = null if (isTraktSource) {
target?.let {
val listKey = target.listKey
if (listKey.isNullOrBlank()) {
LibraryRepository.remove(target.item.id)
} else {
coroutineScope.launch { coroutineScope.launch {
runCatching { runCatching {
LibraryRepository.removeFromList(target.item, listKey) LibraryRepository.removeFromList(
libraryItem,
target.section.type,
)
}.onFailure { error -> }.onFailure { error ->
NuvioToastController.show( NuvioToastController.show(
error.message ?: getString(Res.string.trakt_lists_update_failed), error.message ?: "Failed to update Trakt list",
) )
} }
} }
} } else {
LibraryRepository.toggleSaved(libraryItem)
}
},
onToggleWatched = {
actionTarget = null
coroutineScope.launch {
WatchingActions.togglePosterWatched(preview)
} }
}, },
onDismiss = { pendingRemovalTarget = null },
) )
}
} }
private fun LazyListScope.librarySections( private fun LazyListScope.librarySections(
sections: List<LibrarySection>, sections: List<LibrarySection>,
watchedKeys: Set<String>,
onPosterClick: ((LibraryItem) -> Unit)?, onPosterClick: ((LibraryItem) -> Unit)?,
onSectionViewAllClick: ((LibrarySection) -> Unit)?, onSectionViewAllClick: ((LibrarySection) -> Unit)?,
onPosterLongClick: (LibraryItem, LibrarySection) -> Unit, onPosterLongClick: (LibraryItem, LibrarySection) -> Unit,
@ -250,8 +240,13 @@ private fun LazyListScope.librarySections(
viewAllPillSize = NuvioViewAllPillSize.Compact, viewAllPillSize = NuvioViewAllPillSize.Compact,
key = { item -> "${item.type}:${item.id}" }, key = { item -> "${item.type}:${item.id}" },
) { item -> ) { item ->
val preview = item.toMetaPreview()
HomePosterCard( HomePosterCard(
item = item.toMetaPreview(), item = preview,
isWatched = WatchingState.isPosterWatched(
watchedKeys = watchedKeys,
item = preview,
),
onClick = onPosterClick?.let { { it(item) } }, onClick = onPosterClick?.let { { it(item) } },
onLongClick = { onPosterLongClick(item, section) }, onLongClick = { onPosterLongClick(item, section) },
) )