mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-04 16:57: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
@@ -67,6 +67,65 @@ extension ButtonStyle where Self == ProtonButtonStyle {
|
||||
static var quiet: ProtonButtonStyle { ProtonButtonStyle(kind: .quiet) }
|
||||
}
|
||||
|
||||
/// A button with no chrome of its own — an icon, a row, a chip — that still
|
||||
/// shows it was pressed: a little smaller, with a wash behind it.
|
||||
///
|
||||
/// `.plain` shows nothing at all, and on a slow device, where what the press
|
||||
/// does can take a second to appear, a press that shows nothing reads as one
|
||||
/// that missed — and gets pressed again.
|
||||
struct PressableStyle: ButtonStyle {
|
||||
var circle = false
|
||||
/// The wash's colour; the scheme's text colour when nil. White over video.
|
||||
var wash: Color?
|
||||
@Environment(\.scheme) private var scheme
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
let pressed = configuration.isPressed
|
||||
let fill = (wash ?? scheme.onSurface).opacity(pressed ? 0.12 : 0)
|
||||
configuration.label
|
||||
.background {
|
||||
if circle {
|
||||
Circle().fill(fill)
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: Corner.standard).fill(fill)
|
||||
}
|
||||
}
|
||||
.scaleEffect(pressed ? 0.96 : 1)
|
||||
.animation(.easeOut(duration: 0.1), value: pressed)
|
||||
}
|
||||
}
|
||||
|
||||
extension ButtonStyle where Self == PressableStyle {
|
||||
static var pressable: PressableStyle { PressableStyle() }
|
||||
static var pressableIcon: PressableStyle { PressableStyle(circle: true) }
|
||||
}
|
||||
|
||||
/// A tap and a long press on something that is not a button — a poster, a
|
||||
/// card, an episode row — showing the press the moment the finger lands, as
|
||||
/// `PressableStyle` does for a button.
|
||||
private struct TapAndHold: ViewModifier {
|
||||
let onTap: () -> Void
|
||||
let onHold: (() -> Void)?
|
||||
@State private var pressed = false
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.scaleEffect(pressed ? 0.96 : 1)
|
||||
.opacity(pressed ? 0.8 : 1)
|
||||
.animation(.easeOut(duration: 0.1), value: pressed)
|
||||
.onTapGesture(perform: onTap)
|
||||
.onLongPressGesture(perform: { onHold?() }, onPressingChanged: { pressed = $0 })
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
/// `onTapGesture`, plus `onLongPressGesture` when `onHold` is given, with
|
||||
/// the press drawn.
|
||||
func tapAndHold(_ onTap: @escaping () -> Void, onHold: (() -> Void)? = nil) -> some View {
|
||||
modifier(TapAndHold(onTap: onTap, onHold: onHold))
|
||||
}
|
||||
}
|
||||
|
||||
/// How far along something is, drawn in the accent.
|
||||
///
|
||||
/// `solid` is for the one bar that is deliberately not the accent: a download in
|
||||
|
||||
Reference in new issue
Block a user