diff --git a/Checks/app-startup.py b/Checks/app-startup.py index 4c830f4..4ec23db 100644 --- a/Checks/app-startup.py +++ b/Checks/app-startup.py @@ -332,11 +332,6 @@ def check_cli_instances(root, app, fixtures): print("PASS actual resolved CLI handoff: two isolated GUI episodes, authenticated encrypted HLS, independent default VTT, v2 progress and quit") def check_stream_queue_instance(): - # DEBUG-queue-startup: distinguish queue startup from ordinary empty startup. - invoke(["--new-instance", "--no-config"]) - empty_states = wait_states(1, lambda _: True, "diagnostic empty startup creates its window") - quit_instance(next(iter(empty_states)), 1) - wait_states(0, lambda _: True, "diagnostic empty startup quits") session = (root / "stream-queue-session").resolve() session.mkdir(mode=0o700) paths = [session / "first.jsonl", session / "second.jsonl"] diff --git a/README.md b/README.md index 120e524..da029c8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ To run without installing, use `make run`. The built `.build/terebi.app` is self - **Streams:** use **Open Stream…** (**⇧⌘O**) or drop a supported link. YouTube supports individual videos, not playlists or channels. Miruro links must use `https://barelystarted.miruro.tv/watch//?ep=` with an explicit positive episode number; arbitrary streaming sites are not supported. - **Stream queues:** integrations can supply an ordered YouTube/Miruro queue with `--new-instance --queue-file /absolute/queue.json`. The same sidebar supports play, reorder, remove, previous/next and automatic advance. Only the selected item resolves, including fresh resolution on revisits; local-file batches still use natural filename order. - **Seeking:** click or drag the progress track or thumb to seek. The thumb centers on the cursor, clamped to the track endpoints. -- **Miruro metadata:** titles and opening/ending intervals load independently of playback when available. Small rounded gaps mark interval boundaries in the slider. Inside a segment, **Skip Opening** or **Skip Ending** appears at the top-right below the titlebar for up to ten seconds or until the segment ends; clicking seeks to its end. Its background fill drains as the offer expires, with a short entrance/exit transition; Reduce Motion uses stepped countdown updates without the transition. Ignored offers stay dismissed until the media is closed or replaced. Missing/invalid metadata leaves playback usable, and timings may differ between cuts. Nothing skips automatically. +- **Miruro metadata:** titles and opening/ending intervals load independently of playback when available. Small rounded gaps mark interval boundaries in the slider. Inside a segment, **Skip Opening** or **Skip Ending** appears at the top-right below the titlebar for up to ten seconds or until the segment ends; clicking seeks to its end. A light background fill grows as the offer expires, with a short entrance/exit transition; Reduce Motion uses stepped countdown updates without the transition. Ignored offers stay dismissed until the media is closed or replaced. Missing/invalid metadata leaves playback usable, and timings may differ between cuts. Nothing skips automatically. - **Resume:** videos resume their saved position; finished videos restart from the beginning. Live and audio-only media do not save progress. - **Compact mode:** press **P** for a floating player; double-click it to restore. Drag noninteractive areas to move the window. Use the titlebar pin to keep the normal window on top. - **Quality:** YouTube defaults to SDR up to 1080p. Use **gear → Quality** for other available resolutions or automatic quality. diff --git a/Sources/App/TerebiApp.swift b/Sources/App/TerebiApp.swift index a02f12b..8ecd0f0 100644 --- a/Sources/App/TerebiApp.swift +++ b/Sources/App/TerebiApp.swift @@ -3354,10 +3354,10 @@ private struct PlayerContent: View { PlayerGlass(cornerRadius: 8) TimelineView(.animation(minimumInterval: reduceMotion ? 1 : 1.0 / 30)) { _ in GeometryReader { geometry in - let remaining = model.skipOfferRemainingFraction - Color(SunsetPalette.accent).opacity(0.25) + let elapsed = 1 - model.skipOfferRemainingFraction + Color(SunsetPalette.text).opacity(0.25) .frame(width: geometry.size.width * - (reduceMotion ? ceil(remaining * 10) / 10 : remaining)) + (reduceMotion ? floor(elapsed * 10) / 10 : elapsed)) } } } @@ -3574,6 +3574,7 @@ struct TerebiApp: App { PlayerContent(model: model) .focusedSceneObject(model) } + .defaultLaunchBehavior(.presented) .defaultSize(width: 640, height: 400) .windowResizability(.contentSize) .windowStyle(.hiddenTitleBar) diff --git a/TODO.md b/TODO.md index ecc6202..4772838 100644 --- a/TODO.md +++ b/TODO.md @@ -22,7 +22,7 @@ - audited SDK 27.0 / Swift 6.4 with the macOS 15 minimum retained; migrated Cast discovery to NWBrowser and production activation to activate(). Real Bonjour identity/name/update/order/deduplication/removal/restart and routable-endpoint checks, loopback Cast transitions, focused startup-error alerts and a cooperating-launcher production smoke for cold start/CLI reuse/document handoff/keyboard playback passed. The existing full CLI snapshot-harness timeout remains; macOS 15 runtime and physical-Cast verification remain unverified. Observation, glass and the existing native bridges were left unchanged. - [x] fix the readme. it's currently bloated with irrelevant implementation detail and other such nonsense. it should do the job of a readme only, nothing more. - [x] add a skip button when current playback is inside either an opening or an ending segment. - - Skip Opening/Ending uses validated metadata, seeks to the segment end and disappears after ten seconds (including while paused) or on leaving the segment; ignored segments stay dismissed until close/media replacement. A draining background shows remaining offer time, with 200 ms fade/slide transitions; Reduce Motion uses stepped countdown updates without transitions. Native HLS, exact-EOF, controlled-clock countdown/dismissal and loopback Cast checks passed. Button placement, animation feel and physical-Cast verification remain unverified; rapid play/seek probes encountered Core Audio startup errors on Bluetooth output. + - Skip Opening/Ending uses validated metadata, seeks to the segment end and disappears after ten seconds (including while paused) or on leaving the segment; ignored segments stay dismissed until close/media replacement. A light background fills with elapsed offer time, with 200 ms fade/slide transitions; Reduce Motion uses stepped countdown updates without transitions. Native HLS, exact-EOF, controlled-clock countdown/dismissal and loopback Cast checks passed. Button placement, animation feel and physical-Cast verification remain unverified; rapid play/seek probes encountered Core Audio startup errors on Bluetooth output. - [ ] improve: subtitles. - decrease padding on captions - decrease font size of captions by 10 percent \ No newline at end of file