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:
foxyzandClaude Opus 5.5 committed 2026-10-11 07:53:42 +03:00
1 parent 6b10cae4e6
commit 771b961b32
27 files changed
+1396 -558

No files matched your search

-10
View File
@@ -54,16 +54,6 @@ void main() {
expect(queueJanitor([member('m9'), member('m1', stale: true), member('m2')]), 'm2');
});
test('warming starts in the last 90 s, once buffered to the end, or at the end', () {
bool due(double pos, {double buffered = 0, String t = 'playing'}) =>
queueWarmDue(transport: t, position: pos, duration: 1000, bufferedTo: pos + buffered);
expect(due(100), isFalse);
expect(due(911), isTrue);
expect(due(100, buffered: 900), isTrue);
expect(due(0, t: 'finished'), isTrue);
expect(queueWarmDue(transport: 'playing', position: 5, duration: 0, bufferedTo: 5), isFalse);
});
test('labels', () {
expect(queueHowLabel(item(QueueHow.through), selfId: 'm2'), 'through you');
expect(queueHowLabel(item(QueueHow.through), selfId: 'm1'), 'through Bob');