feat(android,ios): offer posters and synopses on the library, as the desktop does

The offer appears when metadata is off and there is a library to put
posters on. It says what turning metadata on sends, links to Settings
and never turns anything on itself. "Not now" is stored on the device.
The existing library screenshots now run with metadata on, as their
shelf implies, and a new screenshot covers the offer.
This commit is contained in:
nvrl committed 2026-10-13 15:15:28 +02:00
1 parent a79e41aa8a
commit 6ddbcea429
8 files changed
+113 -4

No files matched your search

+2 -1
View File
@@ -203,7 +203,8 @@ struct RootView: View {
onAddShare: {
incomingLink = ""
destination = .shares
}
},
onOpenSettings: { select(.settings) }
)
if width >= twoPaneWidth {
HStack(spacing: 0) {
+7
View File
@@ -51,6 +51,12 @@ struct SettingsStore {
nonmutating set { defaults.set(String(describing: newValue), forKey: Key.librarySort) }
}
/// The library's offer of posters and synopses was turned down.
var metadataOfferDismissed: Bool {
get { bool(Key.metadataOfferDismissed, default: false) }
nonmutating set { defaults.set(newValue, forKey: Key.metadataOfferDismissed) }
}
/// Whether the library folds each franchise into one tile.
var libraryGrouped: Bool {
get { bool(Key.libraryGrouped, default: true) }
@@ -70,5 +76,6 @@ struct SettingsStore {
static let cacheBudgetGib = "cache_budget_gib"
static let librarySort = "library_sort"
static let libraryGrouped = "library_grouped"
static let metadataOfferDismissed = "metadata_offer_dismissed"
}
}
+33
View File
@@ -58,12 +58,16 @@ struct LibraryView: View {
let onResume: (TitleRecord, Int) -> Void
let onTitle: (TitleRecord) -> Void
var onAddShare: () -> Void = {}
var onOpenSettings: () -> Void = {}
// What a long press opened a menu for: a title, or a Continue watching card.
@State private var menuFor: TitleRecord?
@State private var menuResume: Resumable?
@State private var matching: TitleRecord?
@State private var downloading: DownloadRequest?
// Posters and synopses, offered once there is a library to put them on
// and never turned on unasked: switching them on sends title names out.
@State private var offerDismissed = SettingsStore().metadataOfferDismissed
/// The same, for a download asked about once the menu has gone.
@State private var pendingDownload: DownloadRequest?
/// "Change match" picked in the tile menu, waiting for that menu to finish
@@ -196,6 +200,12 @@ struct LibraryView: View {
}
}
}
if browsing, !model.metadataSettings.enabled, !offerDismissed {
MetadataOfferCard(onOpenSettings: onOpenSettings) {
offerDismissed = true
SettingsStore().metadataOfferDismissed = true
}
}
if let featured {
FeaturedBanner(
title: featured,
@@ -411,6 +421,29 @@ private struct LibrarySkeleton: View {
}
}
/// The offer of posters and synopses, and its two answers.
private struct MetadataOfferCard: View {
let onOpenSettings: () -> Void
let onDismiss: () -> Void
@Environment(\.scheme) private var scheme
var body: some View {
VStack(alignment: .leading, spacing: 4) {
Text("Add posters and synopses?").textStyle(.titleSmall).foregroundStyle(scheme.onSurface)
Text("Turning it on in Settings sends the titles in your library — not your files, and nothing about what you have watched — to AniList or TMDB.")
.textStyle(.bodySmall)
.foregroundStyle(scheme.onSurfaceVariant)
HStack {
Spacer()
Button("Not now", action: onDismiss).buttonStyle(.quiet)
Button("Open settings", action: onOpenSettings).buttonStyle(.quiet)
}
}
.padding(EdgeInsets(top: 12, leading: 16, bottom: 4, trailing: 8))
.background(scheme.surfaceContainer, in: RoundedRectangle(cornerRadius: 12))
}
}
/// The title the banner shows: the one watched last, or with nothing part
/// watched, one of the titles the provider has a backdrop for, turning over
/// once a day — the desktop's `featured`.