forked from Foxyz/sync_replay_project
- 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>
30 lines
1.1 KiB
Dart
30 lines
1.1 KiB
Dart
import 'package:sync_relay_core/core.dart';
|
|
|
|
// Up next's words for an item. Who puts an item up is core's
|
|
// `queuePerformer` (whats_next.dart), read the same by the server and
|
|
// every app.
|
|
|
|
/// How [item] plays, in a few words for its row: "through Foxyz" (you:
|
|
/// "through you"), "server fetches", "everyone fetches", "Jellyfin",
|
|
/// "Foxyz's file".
|
|
String queueHowLabel(QueueItem item, {required String selfId}) {
|
|
final mine = item.by == selfId && selfId.isNotEmpty;
|
|
final who = mine ? 'you' : (item.byName.isEmpty ? 'who added it' : item.byName);
|
|
return switch (item.how) {
|
|
QueueHow.through => 'through $who',
|
|
QueueHow.file => mine ? 'your file' : "$who's file",
|
|
QueueHow.server => 'server fetches',
|
|
QueueHow.direct => 'everyone fetches',
|
|
QueueHow.jellyfin => 'Jellyfin',
|
|
};
|
|
}
|
|
|
|
/// "1:23:45" / "23:45" for [secs]; empty when unknown.
|
|
String queueClock(double secs) {
|
|
if (secs <= 0) return '';
|
|
final s = secs.round();
|
|
final h = s ~/ 3600, m = (s % 3600) ~/ 60, r = s % 60;
|
|
String two(int v) => v.toString().padLeft(2, '0');
|
|
return h > 0 ? '$h:${two(m)}:${two(r)}' : '$m:${two(r)}';
|
|
}
|