Player overlay as one piece, Up next always warm and on every source, Jellyfin never unmarks a watched episode
- Overlay: one layout for both designs (top bar with Up next as one of its buttons; one action band above the controls for the status pill, skips, next episode and end cards), one glass recipe (AppGlass) and one pill (FloatingPill); hovering any of them, or the open queue, holds the controls up. - Up next: the first item (or the first continuation episode) is kept resolved on the app that puts it up, refreshed before it expires; Schedule and drop/paste can queue too. - Jellyfin: WatchSession (core) counts real watched coverage; an episode is watched at 80 % or at its ending after half; a played one is re-marked after Playing (10.11 unmarks on open) and never gets a position; a peek leaves the old resume point; part-way resume points stay under 85 %. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6b10cae4e6
commit
771b961b32
27 files changed
+1396
-558
No files matched your search
@@ -2,9 +2,9 @@ import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../jellyfin/session_media.dart' show compareMemberIds;
|
||||
|
||||
// Who puts an Up next item up, and when to get the first one ready. Pure:
|
||||
// only what every client sees in `state` decides, so all clients agree
|
||||
// without a wire message (like the Jellyfin auto-advance swapper).
|
||||
// Who puts an Up next item up. Pure: only what every client sees in
|
||||
// `state` decides, so all clients agree without a wire message (like the
|
||||
// Jellyfin auto-advance swapper).
|
||||
|
||||
/// Who puts [item] up: [id] a member id; null with [why] when nobody here
|
||||
/// can (the item is skipped), null without [why] when nobody is around
|
||||
@@ -66,22 +66,6 @@ String queueHowLabel(QueueItem item, {required String selfId}) {
|
||||
};
|
||||
}
|
||||
|
||||
/// Seconds before the end at which the first Up next item is got ready.
|
||||
const queueWarmLeadSecs = 90.0;
|
||||
|
||||
/// Whether to get the next item ready now: the current media is in its
|
||||
/// last [queueWarmLeadSecs], is buffered to its end, or has finished.
|
||||
bool queueWarmDue({
|
||||
required String transport,
|
||||
required double position,
|
||||
required double duration,
|
||||
required double bufferedTo,
|
||||
}) {
|
||||
if (transport == 'finished') return true;
|
||||
if (duration <= 0) return false;
|
||||
return duration - position <= queueWarmLeadSecs || bufferedTo >= duration - 1;
|
||||
}
|
||||
|
||||
/// "1:23:45" / "23:45" for [secs]; empty when unknown.
|
||||
String queueClock(double secs) {
|
||||
if (secs <= 0) return '';
|
||||
|
||||
Reference in new issue
Block a user