fix(sync): close canonical recovery merge blockers

This commit is contained in:
Timo
2026-08-25 22:24:37 +02:00
parent 213a639314
commit 0d23859a9f
14 changed files with 484 additions and 87 deletions
+24 -8
View File
@@ -5,6 +5,11 @@ function clampMediaTime(value) {
return Math.max(0, Math.min(MAX_MEDIA_TIME, value));
}
function normalizeMediaTitle(value) {
if (typeof value !== 'string' || !value) return null;
return value.substring(0, 100);
}
export function effectiveMediaPosition(mediaState, now = Date.now()) {
if (!mediaState) return null;
const currentTime = clampMediaTime(mediaState.currentTime);
@@ -25,15 +30,18 @@ export function snapshotMediaState(mediaState, now = Date.now()) {
|| (mediaState.playbackState !== 'playing' && mediaState.playbackState !== 'paused')) {
return null;
}
return {
const snapshot = {
revision: mediaState.revision,
playbackState: mediaState.playbackState,
currentTime,
updatedBy: mediaState.updatedBy
};
const mediaTitle = normalizeMediaTitle(mediaState.mediaTitle);
if (mediaTitle) snapshot.mediaTitle = mediaTitle;
return snapshot;
}
function commitMediaState(room, playbackState, currentTime, updatedBy, now) {
function commitMediaState(room, playbackState, currentTime, updatedBy, now, mediaTitle = null) {
const normalizedTime = clampMediaTime(currentTime);
if (normalizedTime === null
|| (playbackState !== 'playing' && playbackState !== 'paused')
@@ -41,21 +49,28 @@ function commitMediaState(room, playbackState, currentTime, updatedBy, now) {
|| !updatedBy) {
return false;
}
room.mediaState = {
const nextState = {
revision: (room.mediaState?.revision || 0) + 1,
playbackState,
currentTime: normalizedTime,
updatedAt: now,
updatedBy
};
const normalizedTitle = normalizeMediaTitle(mediaTitle);
if (normalizedTitle) nextState.mediaTitle = normalizedTitle;
room.mediaState = nextState;
return true;
}
export function updateMediaStateFromControl(room, eventName, payload, senderPeerId, {
now = Date.now(),
senderPlaybackState = null
senderPlaybackState = null,
senderMediaTitle = null
} = {}) {
if (!room || !payload || typeof payload !== 'object') return false;
const mediaTitle = payload.mediaTitle === null
? null
: (normalizeMediaTitle(payload.mediaTitle) || normalizeMediaTitle(senderMediaTitle));
if (eventName === EVENTS.PLAY || eventName === EVENTS.PAUSE) {
const eventPosition = clampMediaTime(payload.currentTime);
@@ -66,7 +81,8 @@ export function updateMediaStateFromControl(room, eventName, payload, senderPeer
eventName === EVENTS.PLAY ? 'playing' : 'paused',
currentTime,
senderPeerId,
now
now,
mediaTitle
);
}
@@ -74,12 +90,12 @@ export function updateMediaStateFromControl(room, eventName, payload, senderPeer
const targetTime = clampMediaTime(payload.targetTime) ?? clampMediaTime(payload.currentTime);
const playbackState = room.mediaState?.playbackState || senderPlaybackState;
if (targetTime === null) return false;
return commitMediaState(room, playbackState, targetTime, senderPeerId, now);
return commitMediaState(room, playbackState, targetTime, senderPeerId, now, mediaTitle);
}
return false;
}
export function commitForceSyncMediaState(room, targetTime, senderPeerId, now = Date.now()) {
return commitMediaState(room, 'playing', targetTime, senderPeerId, now);
export function commitForceSyncMediaState(room, targetTime, senderPeerId, now = Date.now(), mediaTitle = null) {
return commitMediaState(room, 'playing', targetTime, senderPeerId, now, mediaTitle);
}