diff --git a/android/app/src/main/java/io/narl/protonstream/ui/LibraryScreen.kt b/android/app/src/main/java/io/narl/protonstream/ui/LibraryScreen.kt index d43cd13..6e3cd21 100644 --- a/android/app/src/main/java/io/narl/protonstream/ui/LibraryScreen.kt +++ b/android/app/src/main/java/io/narl/protonstream/ui/LibraryScreen.kt @@ -23,6 +23,7 @@ import java.time.LocalDate import androidx.compose.foundation.combinedClickable import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.RemoveCircleOutline @@ -102,11 +103,14 @@ internal fun LibraryScreen( onSetTitleWatched: (TitleRecord, Boolean) -> Unit, onForgetPosition: (TitleRecord, EpisodeRecord) -> Unit, padding: PaddingValues, + onMatchChanged: () -> Unit = {}, + onError: (Throwable) -> Unit = {}, ) { val context = LocalContext.current // What a long press opened a menu for: a title, or a Continue watching card. var menuFor by remember { mutableStateOf(null) } var menuResume by remember { mutableStateOf(null) } + var matching by remember { mutableStateOf(null) } // Most recently played first, one episode per show: a shelf that lists four // episodes of the same series is a shelf with room for nothing else. val resumable = remember(state.titles) { @@ -189,8 +193,22 @@ internal fun LibraryScreen( if (allWatched) Icons.Outlined.CheckCircle else Icons.Default.CheckCircle, if (allWatched) "Mark unwatched" else "Mark watched", ) { onSetTitleWatched(title, !allWatched) } + // The same search the title page offers, for the tile that is + // plainly wrong — the wrong poster is what the grid shows. + MenuRow(Icons.Default.Edit, "Change match") { matching = title } } } + matching?.let { title -> + ChangeMatchDialog( + title = title, + onDismiss = { matching = null }, + onChanged = { + matching = null + onMatchChanged() + }, + onError = onError, + ) + } menuResume?.let { entry -> TileMenu( entry.title.canonicalName ?: entry.title.name, diff --git a/android/app/src/main/java/io/narl/protonstream/ui/ProtonStreamApp.kt b/android/app/src/main/java/io/narl/protonstream/ui/ProtonStreamApp.kt index d7a1ee3..83af747 100644 --- a/android/app/src/main/java/io/narl/protonstream/ui/ProtonStreamApp.kt +++ b/android/app/src/main/java/io/narl/protonstream/ui/ProtonStreamApp.kt @@ -201,6 +201,8 @@ fun ProtonStreamApp( model::setTitleWatched, model::forgetPosition, body, + onMatchChanged = model::reloadAfterMetadataChange, + onError = model::reportError, ) } else { TitleScreen( diff --git a/android/app/src/main/java/io/narl/protonstream/ui/TitleScreen.kt b/android/app/src/main/java/io/narl/protonstream/ui/TitleScreen.kt index 0d63b9a..9fbfac5 100644 --- a/android/app/src/main/java/io/narl/protonstream/ui/TitleScreen.kt +++ b/android/app/src/main/java/io/narl/protonstream/ui/TitleScreen.kt @@ -488,7 +488,7 @@ private fun EpisodeRow( } @Composable -private fun ChangeMatchDialog( +internal fun ChangeMatchDialog( title: TitleRecord, onDismiss: () -> Unit, onChanged: () -> Unit,