forked from Foxyz/sync_replay_project
Swap shows only the new media, no guessed endings, quieter screen
- A swap stops the previous media at once; buffer counts only for the media the player holds (client) and the current mediaId (server), so the old video can no longer start the new one. - The automatic frozen-picture reload is gone (false alarms on still scenes); Reload video stays. - The "Next episode" pill shows only from a known ending. - A web link's thumbnail is its cover, under the video's own name. - While playing, the unread chip stays off the picture; chat pop-ups can be All / Only when paused / Off. - Server fetch failures say when the server has no cookies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ab133dd82f
commit
27b4ec2c96
25 files changed
+274
-485
No files matched your search
@@ -429,7 +429,11 @@ class SyncEngine {
|
||||
_setError(member, mediaId == this.mediaId ? error : '');
|
||||
_seen(member);
|
||||
if (jf != null) member.jf = Map.unmodifiable(jf);
|
||||
member.buffered = member.out || !buffered.isFinite || buffered < 0 ? 0 : buffered;
|
||||
// A report for an earlier media (sent before the swap reached the
|
||||
// client) says nothing about this one's buffer.
|
||||
final earlier = mediaId != 0 && mediaId != this.mediaId;
|
||||
member.buffered =
|
||||
member.out || earlier || !buffered.isFinite || buffered < 0 ? 0 : buffered;
|
||||
final m = media;
|
||||
// First report of the length wins; only for the media the client has open.
|
||||
if (m != null && m.duration <= 0 && mediaId == this.mediaId &&
|
||||
|
||||
@@ -429,6 +429,24 @@ void main() {
|
||||
expect(engine.members['b']!.inSet, isTrue);
|
||||
expect(engine.transport, Transport.held);
|
||||
});
|
||||
|
||||
test("the previous media's buffer never starts the new one", () {
|
||||
join('a', 'alice');
|
||||
join('b', 'bob');
|
||||
engine.applyReady('a', true);
|
||||
engine.applyReady('b', true);
|
||||
engine.applySwap('a', ep2);
|
||||
final oldEvent = engine.eventId - 1;
|
||||
// Sent before the swap reached the clients, landing after it.
|
||||
engine.applyReport('a', 30, 20.0, oldEvent, mediaId: 1);
|
||||
engine.applyReport('b', 30, 20.0, oldEvent, mediaId: 1);
|
||||
expect(engine.members['a']!.buffered, 0);
|
||||
engine.tick();
|
||||
expect(engine.transport, Transport.held);
|
||||
engine.applyReport('a', 0, 6.0, engine.eventId, mediaId: 2);
|
||||
engine.applyReport('b', 0, 6.0, engine.eventId, mediaId: 2);
|
||||
expect(engine.transport, Transport.playing);
|
||||
});
|
||||
});
|
||||
|
||||
group('force with actor feed', () {
|
||||
|
||||
@@ -34,6 +34,23 @@ class ServerHub {
|
||||
return ref != null && cred != null && cred.serverId.isNotEmpty && cred.serverId == ref.serverId;
|
||||
}
|
||||
|
||||
/// What the swapper reads when the server cannot fetch a link ([why]
|
||||
/// from the relay). A yt-dlp failure on a server without cookies says
|
||||
/// so, unless cookies would not help (unknown site, gone, unreachable).
|
||||
String fetchFailText(String why) {
|
||||
const head = "The server can't fetch this link";
|
||||
final y = ytDlp;
|
||||
final plain = playErrorText(why);
|
||||
final cookiesMightHelp = y != null &&
|
||||
y.enabled &&
|
||||
why.contains('yt-dlp') &&
|
||||
!const {unsupportedUrlText, notFoundText, unreachableText}.contains(plain) &&
|
||||
y.cookies.read(count: false) == null;
|
||||
return cookiesMightHelp
|
||||
? '$head: it has no cookies (set them in Settings → Player → yt-dlp on the hosting app, or --yt-dlp-cookies)'
|
||||
: '$head: $why';
|
||||
}
|
||||
|
||||
StateBroadcast stateBroadcast() => engine.broadcast(relay: relayAvailable);
|
||||
|
||||
/// The relay of the current media (`/r/...`), if it is relayed.
|
||||
@@ -362,7 +379,7 @@ void mountSyncRoute(
|
||||
? ActiveRelay.fetch(hub.engine.mediaId, name, link!,
|
||||
ytDlp: hub.ytDlp,
|
||||
onLiveChanged: () => hub.relayLiveChanged(active),
|
||||
onFail: (why) => wsErr(ws, "The server can't fetch this link: $why"))
|
||||
onFail: (why) => wsErr(ws, hub.fetchFailText(why)))
|
||||
: _memberRelay(hub, token, name, media.relay!.tracks);
|
||||
hub.setRelay(active);
|
||||
hub.changed();
|
||||
|
||||
Reference in new issue
Block a user