mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-06 04:36:21 +02:00
fix: stable rtc object ref + per-device Matrix event filter
This commit is contained in:
parent
ce1ea1c91d
commit
0fd952708b
@ -287,8 +287,11 @@ function useDocumentSync(
|
||||
const applyDeltaEvent = (event: import("matrix-js-sdk/src/matrix").MatrixEvent): void => {
|
||||
if (event.getRoomId() !== room.roomId) return;
|
||||
if (event.getType() !== DOC_DELTA_EVENT_TYPE) return;
|
||||
// Skip our own events — local model already has our changes.
|
||||
if (event.getSender() === client.getUserId()) return;
|
||||
// Skip events sent by this exact device — we already have those
|
||||
// changes in our local model. We must NOT skip events from the same
|
||||
// user on a different device (e.g. two tabs open).
|
||||
const senderDeviceId = event.getContent<{ device_id?: string }>().device_id;
|
||||
if (event.getSender() === client.getUserId() && senderDeviceId === client.getDeviceId()) return;
|
||||
const data = event.getContent<{ data?: string }>().data;
|
||||
if (!data) return;
|
||||
logger.info(`[DocumentView] Matrix delta event from ${event.getSender()}, applying ${data.length}b (base64)`);
|
||||
@ -384,6 +387,7 @@ function useDocumentSync(
|
||||
await client.sendEvent(room.roomId, DOC_DELTA_EVENT_TYPE as any, {
|
||||
data: base64Encode(delta),
|
||||
heads,
|
||||
device_id: client.getDeviceId(),
|
||||
});
|
||||
|
||||
deltaSendCount.current++;
|
||||
@ -432,6 +436,7 @@ function useDocumentSync(
|
||||
client.sendEvent(room.roomId, DOC_DELTA_EVENT_TYPE as any, {
|
||||
data: base64Encode(delta),
|
||||
heads,
|
||||
device_id: client.getDeviceId(),
|
||||
}).catch((e) => logger.warn("[DocumentView] Failed to send final delta on unmount", e));
|
||||
}
|
||||
// Always save snapshot on close so next load starts fresh.
|
||||
|
||||
@ -19,7 +19,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
* `isConnected` stays false and the caller should fall back to Matrix events.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { type Room as MatrixRoom, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { isLivekitTransportConfig } from "matrix-js-sdk/src/matrixrtc";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
@ -245,5 +245,16 @@ export function useDocumentRTC(
|
||||
.catch((e: unknown) => logger.warn("[DocumentRTC] Failed to publish cursor", e));
|
||||
}, []);
|
||||
|
||||
return { publishDelta, publishCursor, onDeltaRef, onCursorRef, onPeerLeaveRef, isConnected };
|
||||
// Wrap in useMemo so the returned object reference is stable across renders
|
||||
// (only changes when isConnected changes). Without this, DocumentView's
|
||||
// wiring useEffect ([rtc, applyDeltaBytes]) fires on every render because
|
||||
// the plain object literal `{}` produces a new reference each time.
|
||||
const result = useMemo(
|
||||
() => ({ publishDelta, publishCursor, onDeltaRef, onCursorRef, onPeerLeaveRef, isConnected }),
|
||||
// publishDelta/publishCursor are useCallback stable; refs are always stable;
|
||||
// only isConnected can change.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[isConnected],
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user