Files
sync_replay_project/apps/desktop/lib/src/session/party.dart
T
foxyzandClaude Opus 5.5 741b258ac1 Restructure step 6: what's next and watch tracking
- What's next is the server's: state.advance counts down (10 s) when the
  media finishes with an Up next item first, holds while its performer or
  warm source is gone, and sets queuePlay at its end; cancel is shared, a
  seek or swap ends it; the server skips items nobody can put up. Shared
  rules in core whats_next.dart; the app's janitor, per-screen countdown
  and end-of-episode card are gone.
- The continuation (next Jellyfin episode, next file of a local show
  with its gaps) is an auto item under "Continues with", prepared like
  Up next's first item.
- Watch tracking by time In (D3): only time played while this viewer is
  in counts; away, paused, held, jumps and stalls never do (P7, P9).
  WatchTracker + device WatchHistory (files, links); Jellyfin progress
  reads the same watch; records are the AniList seam.
- A server restart no longer loses what played: apps hold their media
  and one offers it back (swap.restore, first offer wins), Up next is
  re-added, the source re-feeds, and the watch carries on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:06:04 +03:00

28 lines
1.2 KiB
Dart

import 'package:sync_relay_core/core.dart';
// The app's reading of presence (PROTOCOL.md "Presence"): every count,
// list and wait in the UI goes through these, on top of core's
// [PresencePolicy] and [isAlone].
/// What each presence counts for (the one table, shared with the server).
const presencePolicy = PresencePolicy();
/// Counted in "2/3 ready" and waited for by name: its presence counts for
/// the ready counter and its player can open the media.
bool countsForReady(MemberView m) => m.error.isEmpty && presencePolicy.countsFor(m.presence, Purpose.readyCounter);
/// Connected and watching (`in` or `joining`): can do things for the
/// party now (put up an Up next item; core's [isPresentMember]).
bool isPresent(MemberView m) => isPresentMember(m);
/// Nobody but [selfId] is connected in [members] (D9, core's [isAlone]).
bool aloneIn(List<MemberView> members, String selfId) =>
isAlone([for (final m in members) if (m.id != selfId) m.presence]);
/// "3 min" / "40 s": how long since [since] (a `goneSince`), at [now].
String sinceText(DateTime since, DateTime now) {
final d = now.difference(since);
if (d.inMinutes >= 1) return '${d.inMinutes} min';
return '${d.inSeconds.clamp(0, 59)} s';
}