mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-04 16:57:00 +01:00
feat(core,app,android,ios): more like this and browse by genre, studio, person
pstr_core::discover scores every title against another by shared director, studio, genres, leading tags and format, leaves out its own franchise and keeps one title per other franchise. It drives a "More like this" row under a title's episodes and, seeded by the title most recently watched to the end, a "Because you watched" row on the library of titles not yet started. Genre chips on the title page now open a page of every title with that genre, and the studios and director move from the line of facts onto chips of their own that do the same. The desktop has a Browse page whose back link returns to the title; Android and iOS show it over the library pane. The bridge exposes more_like, browse and facet_kind. Also moves a doc comment the My List commit left on the wrong function.
This commit is contained in:
1 parent
f66faf6b75
commit
fafe0c3087
23 files changed
+1139
-92
No files matched your search
@@ -801,3 +801,48 @@ extension EpisodeRecord {
|
||||
extension TitleRecord: Identifiable {
|
||||
public var id: String { key }
|
||||
}
|
||||
|
||||
/// Every title sharing a genre, a studio or a director: what a chip on a title
|
||||
/// page opens. Android's `BrowseScreen`, the desktop's `library::browse`.
|
||||
struct BrowseView: View {
|
||||
let facet: BrowseFacet
|
||||
let titles: [TitleRecord]
|
||||
let onBack: () -> Void
|
||||
let onTitle: (TitleRecord) -> Void
|
||||
@Environment(\.scheme) private var scheme
|
||||
|
||||
var body: some View {
|
||||
TabPage(facet.label, leading: {
|
||||
IconButton("chevron.backward", "Back", tint: scheme.onSurface, action: onBack)
|
||||
}) {
|
||||
if titles.isEmpty {
|
||||
// A recrawl or a new match took the last one away.
|
||||
EmptyState(facet.label, "Nothing in the library has this any more.")
|
||||
} else {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("\(facetKind(facet: facet)) · \(titles.count == 1 ? "1 title" : "\(titles.count) titles")")
|
||||
.textStyle(.bodyMedium)
|
||||
.foregroundStyle(scheme.onSurfaceVariant)
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 108), spacing: 12, alignment: .top)], spacing: 16) {
|
||||
ForEach(titles, id: \.key) { title in
|
||||
PosterTile(title: title)
|
||||
.tapAndHold { onTitle(title) }
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(EdgeInsets(top: 8, leading: 16, bottom: 24, trailing: 16))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension BrowseFacet {
|
||||
/// The name it stands for: the chip's text and its page's heading.
|
||||
var label: String {
|
||||
switch self {
|
||||
case .genre(let name), .studio(let name), .person(let name): name
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user