mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-04 00:47:00 +01:00
feat(core,app,android,ios,cli): look up new titles after every crawl, show presses and work on iOS
Metadata was only fetched after adding a share (mobile) or from the Settings buttons (desktop), so a show or episode that turned up in an existing share stayed bare. Every crawl is now followed by a match run when enrichment is on; `plan` makes no requests for a library that is already matched. A stored episode guide is fetched again when a file newer than it has no named entry, and daily for two weeks while an aired episode is still unnamed. Removing a share now carries its watch state to any other share holding the same file, `pstr remove` drops the share's catalog rows, and the app forgets catalog rows of shares no longer configured — an older `pstr remove` left them, and every episode showed twice. iOS, for a slow iPad: - swipe back on a settings page uses its own edge strip; on the whole page it also pressed the row under the finger and opened the metadata sheet - "Change match" from the tile menu opens once the menu has dismissed, not after a guessed 350 ms that a slow device missed - the activity banner tracks each running line by itself (also Android), so overlapping work no longer leaves it spinning forever - buttons, tiles and rows draw their press; marking watched shows at once; remove/repair share, sign out and deletions show the banner; the player says "Opening…" while the stream opens - posters are read into a reserved buffer instead of a byte at a time
This commit is contained in:
1 parent
2f3be1d193
commit
73973841c2
19 files changed
+692
-113
No files matched your search
@@ -35,7 +35,9 @@ struct TitleView: View {
|
||||
self.franchise = franchise
|
||||
self.onOpenTitle = onOpenTitle
|
||||
// One season on screen at a time, opened on the one Play would land in.
|
||||
let upNext = title.playlist.indices.contains(nextUpIndex(title.playlist)) ? title.playlist[nextUpIndex(title.playlist)] : nil
|
||||
let playlist = title.playlist
|
||||
let nextUp = nextUpIndex(playlist)
|
||||
let upNext = playlist.indices.contains(nextUp) ? playlist[nextUp] : nil
|
||||
_seasonIndex = State(initialValue: max(title.seasons.firstIndex { $0.episodes.contains { $0.linkId == upNext?.linkId } } ?? 0, 0))
|
||||
}
|
||||
|
||||
@@ -231,7 +233,7 @@ struct TitleView: View {
|
||||
LazyHStack(alignment: .top, spacing: 12) {
|
||||
ForEach(franchise, id: \.key) { member in
|
||||
FranchiseTile(title: member, here: member.key == title.key)
|
||||
.onTapGesture { if member.key != title.key { onOpenTitle(member) } }
|
||||
.tapAndHold { if member.key != title.key { onOpenTitle(member) } }
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, side + 16)
|
||||
@@ -282,7 +284,7 @@ struct FilterChip: View {
|
||||
if !selected { RoundedRectangle(cornerRadius: Corner.standard).strokeBorder(scheme.outlineVariant) }
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.buttonStyle(.pressable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +343,7 @@ private struct TitleAction: View {
|
||||
.frame(maxWidth: .infinity)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.buttonStyle(.pressable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,7 +451,7 @@ private struct EpisodeRow: View {
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 6)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture(perform: onPlay)
|
||||
.tapAndHold(onPlay)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,6 +470,7 @@ struct ChangeMatchSheet: View {
|
||||
/// Said here rather than in the snackbar, which this sheet covers.
|
||||
@State private var failure: String?
|
||||
@State private var searched = false
|
||||
@State private var forgetting = false
|
||||
|
||||
init(title: TitleRecord, onDone: @escaping () -> Void) {
|
||||
self.title = title
|
||||
@@ -510,7 +513,9 @@ struct ChangeMatchSheet: View {
|
||||
.disabled(choosing)
|
||||
}
|
||||
} buttons: {
|
||||
Button("Forget match") {
|
||||
Button(forgetting ? "Forgetting…" : "Forget match") {
|
||||
forgetting = true
|
||||
failure = nil
|
||||
Task {
|
||||
do {
|
||||
try await model.run { try $0.forgetMatch(titleKey: title.key) }
|
||||
@@ -518,9 +523,11 @@ struct ChangeMatchSheet: View {
|
||||
} catch {
|
||||
failure = errorMessage(error)
|
||||
}
|
||||
forgetting = false
|
||||
}
|
||||
}
|
||||
.buttonStyle(.quiet)
|
||||
.disabled(forgetting || choosing)
|
||||
Button("Close", action: onDone).buttonStyle(.tonal)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user