Commit Graph
20 Commits
Author SHA1 Message Date
foxyzandClaude Opus 5.5 cf80bb2167 End of video plays out, no false 'loading' near/after the end; bigger status pill avatars; start card fits the mini
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:31:03 +03:00
foxyzandClaude Opus 5.5 8effa573a0 Protocol 10 presence gate, drop/paste anywhere, quick UI fixes
Ready gate: whoever is in the server while it is not playing counts (joining
while playing does not pause anyone); a swap counts everyone present and
keeps ready flags; the quorum rule is gone. Optional 'Unready when the
video changes'. No 'Skip 1:30' guess when the media has chapters.

Drag & drop and Ctrl+V anywhere (fox_utils): files, folders and links get a
small card asking how to open them. Files series start collapsed.

UI: Tab never moves focus and Space is always ready outside text fields;
chat focuses its field; unread badge on uosc and a chip in fullscreen;
people-only chat with an Activity toggle; skip pills show 5 s then with
the controls; volume up to 150%; own avatar same size as the party.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:06:48 +03:00
foxyz 0c38528520 Release v1.0.0
ci / core (push) Successful in 25s
ci / updater-windows (push) Successful in 48s
ci / server (push) Successful in 49s
release / linux (push) Successful in 3m34s
release / windows (push) Successful in 4m38s
2026-10-09 01:39:35 +03:00
foxyzandClaude Opus 5.5 b534c8c7ea Player: now-playing title with cover, start banner, one status pill; media art for everyone
The swapper sends the media's poster and banner once (`art`, Jellyfin
images or AniList by parsed name); state carries their hashes and every
member fetches them from /i/ like avatars. state.media.swapBy names who
put the media up. uosc and the standard bar show cover, title and
episode; a banner card shows before playback starts. The top-left health
pill and the waiting pill become one frosted status pill in plain words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:19:34 +03:00
foxyzandClaude Opus 5.5 d092ea371a 1.0 library + player settings: Jellyfin/Link/Files library with details panel, player gear, settings cards, host flag
Library: source switch, selectable cards with a details panel, one merged
Continue row, Latest grouped per series without re-releases, Link page with
previews and recent links, Files embedded. Player: gear popover in both
designs, progress line while controls hide, live hwdec. Settings rebuilt as
cards. State marks the host member (proto stays 9, unreleased); hosting
shows LAN invite addresses; window buttons in fullscreen. fadeThrough keeps
the outgoing view's state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:58:12 +03:00
foxyzandClaude Opus 5.5 d29c12e4f0 1.0 shell: one window with a party strip; protocol 9 profile + avatars by hash
The shell (lib/src/shell/) replaces the Home and session screens:
- Party strip: profile, Library / Schedule / Settings tabs, Join and
  Host cards (hosting no longer takes media), status-ring avatar stack
  with the member list, chat & activity panel, Leave.
- The real session player is mounted once and shown full, as a
  draggable corner-snapping mini player, or fullscreen (window_manager,
  party and toasts overlaid); the Video is never mounted twice.
- Profile popover with inline rename, colour and a crop picker (256 px
  PNG), pushed live to the session; avatar toasts; waiting pill.
- Motion kit (fastEaseInToSlowEaseOut, fade-through, popovers,
  mouse-drag/wheel horizontal scrolling).
- Library = the existing picker for now (restyled next round); Schedule
  = the new SchedulePage; Settings = left nav over the existing panels.

Protocol 9 (packages/core, packages/server, sync client):
- {"t":"profile"} renames / changes the picture mid-session ("rename",
  "avatar" feed actions); names are cleaned the same way at hello.
- state.members carry avatarHash; pictures are served once from
  /a/<sid>/<token>/<hash> (PNG/JPEG/WebP/GIF by magic bytes only) and
  cached by hash in the app (AvatarCache).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:23:46 +03:00
foxyzandClaude Opus 5.5 e7f33b5dc3 Relay: a member's media through the server's buffer (proto 8)
ci / core (push) Successful in 28s
ci / updater-windows (push) Successful in 49s
ci / server (push) Successful in 49s
Viewers who cannot reach the media get it through the server: a file on
any member's computer, a link passed on by a member ("Through me") or
fetched by the server ("Server fetches it", password-protected servers
only), and Jellyfin items for guests without an account, sourced by
whoever put them up with their own sign-in (or a pasted link's key),
which never leaves their machine. Fixes guests on a dedicated server
without a Jellyfin login being blocked.

The source dials /r/.../source (works behind NAT) and answers pulls with
an adaptive in-flight window (2 x rate x min RTT, 256 KiB..8 MiB). The
server keeps a memory-only buffer of 1 MiB slices sized like a viewer's
mpv buffer (pinned head/tail, 64 MiB back, 256 MiB ahead), fills it with
one sequential pull at a time (blocked viewers first, newest request
only), fetches nothing while nobody watches through it, and drops it on
the next swap or stop. Measured with mpv through shaped links
(tool/relay_e2e.dart): 400 Mbit/s seeks ~0.03 s; 40 Mbit/s no stalls,
3 viewers cost the source ~1x the bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:41:01 +03:00
foxyz 9c5733719b Release v0.2.2
ci / core (push) Successful in 24s
ci / updater-windows (push) Successful in 45s
ci / server (push) Successful in 36s
release / linux (push) Successful in 3m31s
release / windows (push) Successful in 4m49s
2026-10-08 05:30:59 +03:00
foxyz e6f243d6a6 Release v0.2.1
ci / core (push) Successful in 24s
ci / server (push) Successful in 36s
release / linux (push) Successful in 3m35s
2026-10-07 03:39:00 +03:00
foxyz 8c71ee21c1 Release v0.2.0
ci / core (push) Successful in 24s
ci / server (push) Failing after 38s
release / linux (push) Failing after 3m27s
2026-10-07 03:15:36 +03:00
foxyzandClaude Opus 5.5 bc98c5c665 Chapters on the scrubber, Skip OP/ED, audio/subtitle menus
- PlaybackController exposes chapters, segments (Jellyfin
  MediaSegments for account holders), tracks, position/duration.
- Own seek bar with chapter diamonds and chapter title on hover,
  seeking through the sync user-seek path.
- Skip OP / Skip ED pills from Intro/Outro segments or chapter names
  (ED skips to its end only); Skip 1:30 fallback for >20 min videos
  without OP info; next-episode pill now starts at the ED.
- PgUp/PgDn chapters, Shift+Right +1:30; Audio and Subtitles menus
  with count badges via the existing track path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 02:56:41 +03:00
foxyzandClaude Opus 5.5 ae4edc29e8 Jellyfin end to end: per-viewer playback, progress, episodes, swap browser
- Host/swap send refs only; pasted Jellyfin links become refs; the host
  hands the relay its own app-obtained credential.
- Each viewer resolves with their own account (token in a header) or
  via the relay, else a clear blocked card with Link account.
- Per-account progress reporting (Playing/Progress/Stopped), 401 marks
  the account expired.
- Previous/next episode in the controls (< > / Shift+P/N), floating
  Next episode pill near the end, auto-advance countdown (one
  designated swapper), track carry-over per series.
- Swap panel uses the shared MediaPicker; browser location remembered
  per server and opens on the current series.
- Fix: states are applied one at a time (a stale pause could land
  after a newer play).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 02:38:24 +03:00
foxyzandClaude Opus 5.5 45f4c1bc84 Jellyfin refs on the wire + guest relay (proto 7)
- Media can be a Jellyfin ref {serverId, itemId, mediaSourceId, title,
  subtitle, runtimeSecs}; the server never stores or broadcasts a URL
  or token for it.
- Optional server-side Jellyfin credential (serve map / --jellyfin
  file) enables GET /j/<sid>/<token>/<itemId>: range-faithful proxy of
  the active item only, exact client header fields, upstream aborted on
  disconnect, bytes counted. welcome.relayUrl / state.relay advertise it.
- Members report jf access (own account vs relay).
- /m now sends the real Content-Type (Relic overrode it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 01:57:04 +03:00
foxyzandClaude Opus 5.5 4814bfb561 Core: pure-Dart Jellyfin client
Auth (Quick Connect incl. the Initiate 400 fix: Content-Length + full
client header; password), server identity and link parsing, browsing
(views, resume, next up, latest, paged items, search, seasons,
episodes, next episode), images, PlaybackInfo and stream URLs,
progress reporting and user data, and a track matcher for carrying
audio/subtitle choices across episodes. Fixture tests plus env-gated
live tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 01:42:03 +03:00
foxyzandClaude Opus 5.5 d8d487c189 Sync fixes: clean seeks, clock offset, end of file, 2.5 min read-ahead (proto 6)
- User seeks are intercepted at the player (SyncPlayer), previewed
  locally, sent once 300 ms after the drag ends; own echoes are matched
  by seekSeq and never re-applied; the landed check can't reapply a
  stale target. 1 s position poll removed.
- ping/pong clock offset (min-RTT ClockSync); positions use server time.
- Reports carry duration; buffer gate is min(4 s, remaining - 2 s);
  new finished transport instead of a HELD stall at the end.
- cache/readahead 150 s, 256 MiB demuxer cache, pins read back.
- Resumed reports put a stale ready member back in the set; hello.resume
  takes over the old member after an unclean drop (no ghost).
- Docs: roadmap rendering findings (HW path works; shaders verified).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 01:20:18 +03:00
foxyzandClaude Opus 5.5 81cac1214d Server on an isolate, dedicated server binary, room -> server (proto 5)
- serve(Map config, events) is the one server entrypoint: the app
  hosts it via Isolate.spawn (crash surfaced on the Host card, logs
  forwarded as [server]); bin/server.dart is the dedicated server,
  compiled into the bundle as watch-together-server. --headless gone.
- Host identity via a per-hosting hostKey in hello, replacing the
  loopback heuristic.
- Rename room -> server across code, files and wire (t:"state",
  /health name); protocol bumped to 5.
- CI compiles the server binary; isolate smoke tests in server and
  desktop suites. Docs updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:55:14 +03:00
foxyzandClaude Opus 5.5 e2301aa4ec Server hardening: finite numbers, open servers, unkickable host, no URL leaks
- Reject non-finite numerics at protocol parse and in the engine
  (a 1e400 seek became Infinity and broke every broadcast).
- Reject empty swaps; sanitize URL-looking media names.
- Blank password = open server; defaults no longer 'change-me'.
- Loopback peers (the in-process host) can't be kicked.
- /health no longer exposes media/transport; file URLs use the
  host the client dialled instead of 127.0.0.1.
- Count served bytes as streamed, not as requested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:30:12 +03:00
foxyz 2760c823c0 Avatar cap to 256 KiB; idle warn only while ready
Private-server headroom over any pipeline PNG. The 8-min
auto-unready warning now mirrors the 10-min action guard: no toast
when self isn't ready, since there's nothing to lose.
2026-09-12 11:47:51 +03:00
foxyz 190faf63c0 Raise avatar cap 64 to 128 KiB, pipeline checks encoded size
64 KiB rejected normal 128px PNGs. 128 KiB fits any 128x128 PNG
(raw <= 64 KiB, worst-case base64 ~95 KiB chars) while still
bounding abuse. PNG kept for transparency. Pipeline now measures
the encoded base64 against RelayConstants (was checking the wrong
variable with its own 512 KiB limit) and drops dead crop code.
Server policy, still v4. Trade noted: avatars ride the 1 Hz room
broadcast, uplink scales with cap; hash-reference follow-up later.
2026-09-12 11:45:34 +03:00
foxyz 427d851a5b Initial commit: watch-together phases 0-4 + presence hardening, internet-tested 2026-09-12 00:13:43 +03:00