Refactor LibraryScreen to use action targets

This commit is contained in:
AdityasahuX07 2026-05-12 23:01:29 +05:30 committed by GitHub
parent 4dc054e51e
commit c29f0cc064
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 com.nuvio.app.core.network.NetworkCondition
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.NuvioNetworkOfflineCard
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.NuvioViewAllPillSize
import com.nuvio.app.core.ui.NuvioShelfSection
@ -32,22 +32,20 @@ import com.nuvio.app.features.home.components.HomeEmptyStateCard
import com.nuvio.app.features.home.components.HomePosterCard
import com.nuvio.app.features.home.components.HomeSkeletonRow
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 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 listKey: String? = null,
val listTitle: String? = null,
val section: LibrarySection,
)
@Composable
fun LibraryScreen(
modifier: Modifier = Modifier,
onPosterClick: ((LibraryItem) -> Unit)? = null,
onPosterLongClick: ((LibraryItem) -> Unit)? = null,
onSectionViewAllClick: ((LibrarySection) -> Unit)? = null,
) {
val uiState by remember {
@ -55,7 +53,8 @@ fun LibraryScreen(
LibraryRepository.uiState
}.collectAsStateWithLifecycle()
val networkStatusUiState by NetworkStatusRepository.uiState.collectAsStateWithLifecycle()
var pendingRemovalTarget by remember { mutableStateOf<LibraryRemovalTarget?>(null) }
val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle()
var actionTarget by remember { mutableStateOf<LibraryActionTarget?>(null) }
var observedOfflineState by remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
val isTraktSource = uiState.sourceMode == LibrarySourceMode.TRAKT
@ -66,12 +65,11 @@ fun LibraryScreen(
}
}
LaunchedEffect(networkStatusUiState.condition, isTraktSource) {
when (networkStatusUiState.condition) {
NetworkCondition.NoInternet,
NetworkCondition.ServersUnreachable,
-> {
-> {
observedOfflineState = true
}
@ -87,7 +85,7 @@ fun LibraryScreen(
NetworkCondition.Unknown,
NetworkCondition.Checking,
-> Unit
-> Unit
}
}
@ -102,11 +100,7 @@ fun LibraryScreen(
.background(MaterialTheme.colorScheme.background),
) {
NuvioScreenHeader(
title = if (isTraktSource) {
stringResource(Res.string.library_trakt_title)
} else {
stringResource(Res.string.library_title)
},
title = if (isTraktSource) "Trakt Library" else "Library",
modifier = Modifier.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(6.dp))
@ -131,13 +125,9 @@ fun LibraryScreen(
} else {
HomeEmptyStateCard(
modifier = Modifier.padding(horizontal = 16.dp),
title = if (isTraktSource) {
stringResource(Res.string.library_trakt_load_failed)
} else {
stringResource(Res.string.library_load_failed)
},
title = if (isTraktSource) "Couldn't load Trakt library" else "Couldn't load library",
message = uiState.errorMessage.orEmpty(),
actionLabel = stringResource(Res.string.action_retry),
actionLabel = "Retry",
onActionClick = retryLibraryLoad,
)
}
@ -155,15 +145,11 @@ fun LibraryScreen(
} else {
HomeEmptyStateCard(
modifier = Modifier.padding(horizontal = 16.dp),
title = if (isTraktSource) {
stringResource(Res.string.library_trakt_empty_title)
} else {
stringResource(Res.string.library_empty_title)
},
title = if (isTraktSource) "Your Trakt library is empty" else "Your library is empty",
message = if (isTraktSource) {
stringResource(Res.string.library_trakt_empty_message)
"Connect Trakt and save titles to your watchlist or personal lists."
} else {
stringResource(Res.string.library_empty_message)
"Saved titles will appear here after you tap Save on a details screen."
},
)
}
@ -176,56 +162,53 @@ fun LibraryScreen(
onPosterClick = onPosterClick,
onSectionViewAllClick = onSectionViewAllClick,
onPosterLongClick = { item, section ->
pendingRemovalTarget = if (isTraktSource) {
LibraryRemovalTarget(
item = item,
listKey = section.type,
listTitle = section.displayTitle,
)
} else {
LibraryRemovalTarget(item = item)
}
actionTarget = LibraryActionTarget(item = item, section = section)
},
)
}
}
}
NuvioStatusModal(
title = stringResource(Res.string.library_remove_title),
message = pendingRemovalTarget?.let { target ->
val listTitle = target.listTitle
if (listTitle.isNullOrBlank()) {
stringResource(Res.string.library_remove_message, target.item.name)
} else {
stringResource(Res.string.library_remove_from_list_message, target.item.name, listTitle)
}
}.orEmpty(),
isVisible = pendingRemovalTarget != null,
confirmText = stringResource(Res.string.library_remove_confirm),
dismissText = stringResource(Res.string.action_cancel),
onConfirm = {
val target = pendingRemovalTarget
pendingRemovalTarget = null
target?.let {
val listKey = target.listKey
if (listKey.isNullOrBlank()) {
LibraryRepository.remove(target.item.id)
} else {
// Action sheet — same UI as home screen poster long-press
val target = actionTarget
if (target != null) {
val preview = target.item.toMetaPreview()
NuvioPosterActionSheet(
item = preview,
isSaved = LibraryRepository.isSaved(preview.id, preview.type),
isWatched = WatchingState.isPosterWatched(
watchedKeys = watchedUiState.watchedKeys,
item = preview,
),
onDismiss = { actionTarget = null },
onToggleLibrary = {
actionTarget = null
val libraryItem = target.item
if (isTraktSource) {
coroutineScope.launch {
runCatching {
LibraryRepository.removeFromList(target.item, listKey)
LibraryRepository.removeFromList(
libraryItem,
target.section.type,
)
}.onFailure { error ->
NuvioToastController.show(
error.message ?: getString(Res.string.trakt_lists_update_failed),
error.message ?: "Failed to update Trakt list",
)
}
}
} else {
LibraryRepository.toggleSaved(libraryItem)
}
}
},
onDismiss = { pendingRemovalTarget = null },
)
},
onToggleWatched = {
actionTarget = null
coroutineScope.launch {
WatchingActions.togglePosterWatched(preview)
}
},
)
}
}
private fun LazyListScope.librarySections(