canvu-react 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chatbot.d.cts +1 -1
- package/dist/chatbot.d.ts +1 -1
- package/dist/react.cjs +61 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +61 -0
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +244 -11
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +20 -7
- package/dist/realtime.d.ts +20 -7
- package/dist/realtime.js +244 -12
- package/dist/realtime.js.map +1 -1
- package/dist/{types-CW146bKP.d.cts → types-BtLGGw0r.d.cts} +10 -1
- package/dist/{types-CpqlbbCP.d.ts → types-ChnTSRSe.d.ts} +10 -1
- package/package.json +1 -1
package/dist/realtime.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PlacementPreview, X as RemotePresenceMarkupStroke, Y as RemotePresencePeer, Z as RealtimeConnectionState, J as VectorViewportHandle, b as VectorToolDefinition, K as VectorViewportProps, C as CanvasPlugin, f as CanvasPluginRenderContext } from './types-
|
|
2
|
-
export {
|
|
1
|
+
import { P as PlacementPreview, X as RemotePresenceMarkupStroke, Y as RemotePresencePeer, Z as RemotePresenceCamera, _ as RealtimeConnectionState, J as VectorViewportHandle, b as VectorToolDefinition, K as VectorViewportProps, C as CanvasPlugin, f as CanvasPluginRenderContext } from './types-BtLGGw0r.cjs';
|
|
2
|
+
export { $ as PresenceOverlayRenderContext } from './types-BtLGGw0r.cjs';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { C as Camera2D } from './camera-BwQjm5oh.cjs';
|
|
5
5
|
import { V as VectorSceneItem, R as Rect } from './types-CB0TZZuk.cjs';
|
|
@@ -62,6 +62,7 @@ type RealtimePresencePayload = {
|
|
|
62
62
|
readonly y: number;
|
|
63
63
|
} | null;
|
|
64
64
|
readonly markupStroke?: RemotePresenceMarkupStroke | null;
|
|
65
|
+
readonly camera?: RemotePresenceCamera | null;
|
|
65
66
|
readonly activeTool?: string;
|
|
66
67
|
};
|
|
67
68
|
type RealtimeClientPeer = {
|
|
@@ -191,6 +192,7 @@ type UseRealtimeCommentsResult = {
|
|
|
191
192
|
tools: VectorToolDefinition[];
|
|
192
193
|
overlay: ReactNode;
|
|
193
194
|
viewport: RealtimeCommentsViewportBindings;
|
|
195
|
+
handleViewportItemsChange: (items: VectorSceneItem[], onItemsChange?: (items: VectorSceneItem[]) => void) => void;
|
|
194
196
|
isComposerOpen: boolean;
|
|
195
197
|
closeComposer: () => void;
|
|
196
198
|
};
|
|
@@ -215,16 +217,19 @@ type UseRealtimeSessionOptions = {
|
|
|
215
217
|
connectTimeoutMs?: number;
|
|
216
218
|
onError?: (message: string) => void;
|
|
217
219
|
};
|
|
218
|
-
type RealtimeViewportPresenceBindings = Pick<VectorViewportProps, "remotePresence" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange">;
|
|
220
|
+
type RealtimeViewportPresenceBindings = Pick<VectorViewportProps, "remotePresence" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange" | "onCameraChange">;
|
|
221
|
+
type BindViewportPresenceOptions = {
|
|
222
|
+
activeTool?: string;
|
|
223
|
+
viewportRef?: RefObject<VectorViewportHandle | null>;
|
|
224
|
+
};
|
|
219
225
|
type UseRealtimeSessionResult = {
|
|
220
226
|
connection: RealtimeConnectionInfo;
|
|
221
227
|
sessionPeers: RealtimeSessionPeer[];
|
|
222
228
|
remotePresence: RealtimeSessionPeer[];
|
|
223
229
|
remoteAdapter: VectorCanvasRemoteAdapter;
|
|
224
230
|
document: RealtimeDocumentSnapshot | null;
|
|
225
|
-
bindViewportPresence: (options?:
|
|
226
|
-
|
|
227
|
-
}) => RealtimeViewportPresenceBindings;
|
|
231
|
+
bindViewportPresence: (options?: BindViewportPresenceOptions) => RealtimeViewportPresenceBindings;
|
|
232
|
+
syncViewportPresence: (options?: BindViewportPresenceOptions) => boolean;
|
|
228
233
|
disconnect: () => void;
|
|
229
234
|
reconnectNow: () => void;
|
|
230
235
|
};
|
|
@@ -307,4 +312,12 @@ type RealtimeSessionPluginOptions = RealtimeSessionPanelProps;
|
|
|
307
312
|
*/
|
|
308
313
|
declare function realtimeSessionPlugin(options: RealtimeSessionPluginOptions): CanvasPlugin;
|
|
309
314
|
|
|
310
|
-
|
|
315
|
+
type UseRealtimePeerFollowOptions = {
|
|
316
|
+
viewportRef: RefObject<VectorViewportHandle | null>;
|
|
317
|
+
sessionPeers: RealtimeSessionPeer[];
|
|
318
|
+
followedPeerId: string | null | undefined;
|
|
319
|
+
onFollowEnd?: () => void;
|
|
320
|
+
};
|
|
321
|
+
declare function useRealtimePeerFollow(options: UseRealtimePeerFollowOptions): void;
|
|
322
|
+
|
|
323
|
+
export { PresenceRemoteLayer, type PresenceRemoteLayerProps, REALTIME_COMMENT_TOOL, type RealtimeClientMessage, type RealtimeCollaborationPluginOptions, type RealtimeCommentData, type RealtimeCommentsAuthor, RealtimeCommentsOverlay, type RealtimeCommentsOverlayProps, type RealtimeCommentsPluginOptions, type RealtimeCommentsViewportBindings, type RealtimeConnectionInfo, RealtimeConnectionState, type RealtimeDocumentSnapshot, type RealtimePresencePayload, type RealtimeServerMessage, RealtimeSessionPanel, type RealtimeSessionPanelProps, type RealtimeSessionPeer, type RealtimeSessionPluginOptions, type RealtimeViewportPresenceBindings, RemotePresenceCamera, RemotePresenceMarkupStroke, RemotePresencePeer, type UseRealtimeCommentsOptions, type UseRealtimeCommentsResult, type UseRealtimePeerFollowOptions, type UseRealtimeSessionOptions, type UseRealtimeSessionResult, createRealtimeCommentAvatarDataUrl, createRealtimeCommentDraftItem, createRealtimeCommentItem, defaultPresenceColorForId, getRealtimeCommentData, isRealtimeCommentDraftItem, isRealtimeCommentItem, parseRealtimeClientMessage, parseRealtimeServerMessage, realtimeCollaborationPlugin, realtimeCommentsPlugin, realtimeSessionPlugin, remoteMarkupStrokeFromPlacementPreview, useRealtimeComments, useRealtimePeerFollow, useRealtimeSession, withRealtimeCommentTool };
|
package/dist/realtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PlacementPreview, X as RemotePresenceMarkupStroke, Y as RemotePresencePeer, Z as RealtimeConnectionState, J as VectorViewportHandle, b as VectorToolDefinition, K as VectorViewportProps, C as CanvasPlugin, f as CanvasPluginRenderContext } from './types-
|
|
2
|
-
export {
|
|
1
|
+
import { P as PlacementPreview, X as RemotePresenceMarkupStroke, Y as RemotePresencePeer, Z as RemotePresenceCamera, _ as RealtimeConnectionState, J as VectorViewportHandle, b as VectorToolDefinition, K as VectorViewportProps, C as CanvasPlugin, f as CanvasPluginRenderContext } from './types-ChnTSRSe.js';
|
|
2
|
+
export { $ as PresenceOverlayRenderContext } from './types-ChnTSRSe.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { C as Camera2D } from './camera-KwCYYPhm.js';
|
|
5
5
|
import { V as VectorSceneItem, R as Rect } from './types-CB0TZZuk.js';
|
|
@@ -62,6 +62,7 @@ type RealtimePresencePayload = {
|
|
|
62
62
|
readonly y: number;
|
|
63
63
|
} | null;
|
|
64
64
|
readonly markupStroke?: RemotePresenceMarkupStroke | null;
|
|
65
|
+
readonly camera?: RemotePresenceCamera | null;
|
|
65
66
|
readonly activeTool?: string;
|
|
66
67
|
};
|
|
67
68
|
type RealtimeClientPeer = {
|
|
@@ -191,6 +192,7 @@ type UseRealtimeCommentsResult = {
|
|
|
191
192
|
tools: VectorToolDefinition[];
|
|
192
193
|
overlay: ReactNode;
|
|
193
194
|
viewport: RealtimeCommentsViewportBindings;
|
|
195
|
+
handleViewportItemsChange: (items: VectorSceneItem[], onItemsChange?: (items: VectorSceneItem[]) => void) => void;
|
|
194
196
|
isComposerOpen: boolean;
|
|
195
197
|
closeComposer: () => void;
|
|
196
198
|
};
|
|
@@ -215,16 +217,19 @@ type UseRealtimeSessionOptions = {
|
|
|
215
217
|
connectTimeoutMs?: number;
|
|
216
218
|
onError?: (message: string) => void;
|
|
217
219
|
};
|
|
218
|
-
type RealtimeViewportPresenceBindings = Pick<VectorViewportProps, "remotePresence" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange">;
|
|
220
|
+
type RealtimeViewportPresenceBindings = Pick<VectorViewportProps, "remotePresence" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange" | "onCameraChange">;
|
|
221
|
+
type BindViewportPresenceOptions = {
|
|
222
|
+
activeTool?: string;
|
|
223
|
+
viewportRef?: RefObject<VectorViewportHandle | null>;
|
|
224
|
+
};
|
|
219
225
|
type UseRealtimeSessionResult = {
|
|
220
226
|
connection: RealtimeConnectionInfo;
|
|
221
227
|
sessionPeers: RealtimeSessionPeer[];
|
|
222
228
|
remotePresence: RealtimeSessionPeer[];
|
|
223
229
|
remoteAdapter: VectorCanvasRemoteAdapter;
|
|
224
230
|
document: RealtimeDocumentSnapshot | null;
|
|
225
|
-
bindViewportPresence: (options?:
|
|
226
|
-
|
|
227
|
-
}) => RealtimeViewportPresenceBindings;
|
|
231
|
+
bindViewportPresence: (options?: BindViewportPresenceOptions) => RealtimeViewportPresenceBindings;
|
|
232
|
+
syncViewportPresence: (options?: BindViewportPresenceOptions) => boolean;
|
|
228
233
|
disconnect: () => void;
|
|
229
234
|
reconnectNow: () => void;
|
|
230
235
|
};
|
|
@@ -307,4 +312,12 @@ type RealtimeSessionPluginOptions = RealtimeSessionPanelProps;
|
|
|
307
312
|
*/
|
|
308
313
|
declare function realtimeSessionPlugin(options: RealtimeSessionPluginOptions): CanvasPlugin;
|
|
309
314
|
|
|
310
|
-
|
|
315
|
+
type UseRealtimePeerFollowOptions = {
|
|
316
|
+
viewportRef: RefObject<VectorViewportHandle | null>;
|
|
317
|
+
sessionPeers: RealtimeSessionPeer[];
|
|
318
|
+
followedPeerId: string | null | undefined;
|
|
319
|
+
onFollowEnd?: () => void;
|
|
320
|
+
};
|
|
321
|
+
declare function useRealtimePeerFollow(options: UseRealtimePeerFollowOptions): void;
|
|
322
|
+
|
|
323
|
+
export { PresenceRemoteLayer, type PresenceRemoteLayerProps, REALTIME_COMMENT_TOOL, type RealtimeClientMessage, type RealtimeCollaborationPluginOptions, type RealtimeCommentData, type RealtimeCommentsAuthor, RealtimeCommentsOverlay, type RealtimeCommentsOverlayProps, type RealtimeCommentsPluginOptions, type RealtimeCommentsViewportBindings, type RealtimeConnectionInfo, RealtimeConnectionState, type RealtimeDocumentSnapshot, type RealtimePresencePayload, type RealtimeServerMessage, RealtimeSessionPanel, type RealtimeSessionPanelProps, type RealtimeSessionPeer, type RealtimeSessionPluginOptions, type RealtimeViewportPresenceBindings, RemotePresenceCamera, RemotePresenceMarkupStroke, RemotePresencePeer, type UseRealtimeCommentsOptions, type UseRealtimeCommentsResult, type UseRealtimePeerFollowOptions, type UseRealtimeSessionOptions, type UseRealtimeSessionResult, createRealtimeCommentAvatarDataUrl, createRealtimeCommentDraftItem, createRealtimeCommentItem, defaultPresenceColorForId, getRealtimeCommentData, isRealtimeCommentDraftItem, isRealtimeCommentItem, parseRealtimeClientMessage, parseRealtimeServerMessage, realtimeCollaborationPlugin, realtimeCommentsPlugin, realtimeSessionPlugin, remoteMarkupStrokeFromPlacementPreview, useRealtimeComments, useRealtimePeerFollow, useRealtimeSession, withRealtimeCommentTool };
|
package/dist/realtime.js
CHANGED
|
@@ -233,6 +233,19 @@ function parseCursor(value) {
|
|
|
233
233
|
if (x == null || y == null) return void 0;
|
|
234
234
|
return { x, y };
|
|
235
235
|
}
|
|
236
|
+
function parseCamera(value) {
|
|
237
|
+
if (value === null) return null;
|
|
238
|
+
if (!isRecord(value)) return void 0;
|
|
239
|
+
const x = getNumber(value.x);
|
|
240
|
+
const y = getNumber(value.y);
|
|
241
|
+
const zoom = getNumber(value.zoom);
|
|
242
|
+
const viewportWidth = getNumber(value.viewportWidth);
|
|
243
|
+
const viewportHeight = getNumber(value.viewportHeight);
|
|
244
|
+
if (x == null || y == null || zoom == null || viewportWidth == null || viewportHeight == null) {
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
return { x, y, zoom, viewportWidth, viewportHeight };
|
|
248
|
+
}
|
|
236
249
|
function parseMarkupStroke(value) {
|
|
237
250
|
if (value === null) return null;
|
|
238
251
|
if (!isRecord(value) || !Array.isArray(value.points)) return void 0;
|
|
@@ -256,9 +269,12 @@ function parsePresencePayload(value) {
|
|
|
256
269
|
const markupStroke = parseMarkupStroke(value.markupStroke);
|
|
257
270
|
if (markupStroke === void 0 && value.markupStroke !== void 0)
|
|
258
271
|
return void 0;
|
|
272
|
+
const camera = parseCamera(value.camera);
|
|
273
|
+
if (camera === void 0 && value.camera !== void 0) return void 0;
|
|
259
274
|
return {
|
|
260
275
|
cursor,
|
|
261
276
|
...markupStroke !== void 0 ? { markupStroke } : {},
|
|
277
|
+
...camera !== void 0 ? { camera } : {},
|
|
262
278
|
...getString(value.activeTool) ? { activeTool: getString(value.activeTool) } : {}
|
|
263
279
|
};
|
|
264
280
|
}
|
|
@@ -292,6 +308,8 @@ function parseRealtimeSessionPeer(value) {
|
|
|
292
308
|
const markupStroke = parseMarkupStroke(value.markupStroke);
|
|
293
309
|
if (markupStroke === void 0 && value.markupStroke !== void 0)
|
|
294
310
|
return void 0;
|
|
311
|
+
const camera = parseCamera(value.camera);
|
|
312
|
+
if (camera === void 0 && value.camera !== void 0) return void 0;
|
|
295
313
|
const isSelf = value.isSelf === true;
|
|
296
314
|
const connectionState = getString(value.connectionState);
|
|
297
315
|
return {
|
|
@@ -307,6 +325,7 @@ function parseRealtimeSessionPeer(value) {
|
|
|
307
325
|
...getString(value.color) ? { color: getString(value.color) } : {},
|
|
308
326
|
...getString(value.image) ? { image: getString(value.image) } : {},
|
|
309
327
|
...markupStroke !== void 0 ? { markupStroke } : {},
|
|
328
|
+
...camera !== void 0 ? { camera } : {},
|
|
310
329
|
...getString(value.activeTool) ? { activeTool: getString(value.activeTool) } : {},
|
|
311
330
|
...connectionState ? { connectionState } : {}
|
|
312
331
|
};
|
|
@@ -1518,20 +1537,21 @@ function useRealtimeComments({
|
|
|
1518
1537
|
}),
|
|
1519
1538
|
[author.color]
|
|
1520
1539
|
);
|
|
1521
|
-
const
|
|
1522
|
-
(nextItems) => {
|
|
1540
|
+
const handleViewportItemsChange = useCallback(
|
|
1541
|
+
(nextItems, overrideOnItemsChange) => {
|
|
1542
|
+
const applyItemsChange = overrideOnItemsChange ?? onItemsChange;
|
|
1523
1543
|
const currentIds = new Set(items.map((item) => item.id));
|
|
1524
1544
|
const draftItem = nextItems.find(
|
|
1525
1545
|
(item) => !currentIds.has(item.id) && isRealtimeCommentDraftItem(item)
|
|
1526
1546
|
);
|
|
1527
1547
|
if (!draftItem) {
|
|
1528
|
-
|
|
1548
|
+
applyItemsChange(nextItems);
|
|
1529
1549
|
return;
|
|
1530
1550
|
}
|
|
1531
1551
|
const filteredItems = nextItems.filter((item) => item.id !== draftItem.id);
|
|
1532
1552
|
const shouldPersistFiltered = filteredItems.length !== items.length || filteredItems.some((item, index) => items[index]?.id !== item.id);
|
|
1533
1553
|
if (shouldPersistFiltered) {
|
|
1534
|
-
|
|
1554
|
+
applyItemsChange(filteredItems);
|
|
1535
1555
|
}
|
|
1536
1556
|
setCommentComposer({
|
|
1537
1557
|
worldX: draftItem.bounds.x + draftItem.bounds.width / 2,
|
|
@@ -1631,22 +1651,159 @@ function useRealtimeComments({
|
|
|
1631
1651
|
const viewport = useMemo(
|
|
1632
1652
|
() => ({
|
|
1633
1653
|
customPlacement,
|
|
1634
|
-
onItemsChange:
|
|
1654
|
+
onItemsChange: (nextItems) => handleViewportItemsChange(nextItems),
|
|
1635
1655
|
onCameraChange
|
|
1636
1656
|
}),
|
|
1637
|
-
[customPlacement,
|
|
1657
|
+
[customPlacement, handleViewportItemsChange, onCameraChange]
|
|
1638
1658
|
);
|
|
1639
1659
|
return useMemo(
|
|
1640
1660
|
() => ({
|
|
1641
1661
|
tools,
|
|
1642
1662
|
overlay,
|
|
1643
1663
|
viewport,
|
|
1664
|
+
handleViewportItemsChange,
|
|
1644
1665
|
isComposerOpen: commentComposer != null,
|
|
1645
1666
|
closeComposer
|
|
1646
1667
|
}),
|
|
1647
|
-
[
|
|
1668
|
+
[
|
|
1669
|
+
closeComposer,
|
|
1670
|
+
commentComposer,
|
|
1671
|
+
handleViewportItemsChange,
|
|
1672
|
+
overlay,
|
|
1673
|
+
tools,
|
|
1674
|
+
viewport
|
|
1675
|
+
]
|
|
1648
1676
|
);
|
|
1649
1677
|
}
|
|
1678
|
+
var viewportFollowSyncSnapshots = /* @__PURE__ */ new WeakMap();
|
|
1679
|
+
function getFollowedPeer(sessionPeers, followedPeerId) {
|
|
1680
|
+
return sessionPeers.find(
|
|
1681
|
+
(peerState) => peerState.peerId === followedPeerId || peerState.id === followedPeerId
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
function getCameraKey(peer) {
|
|
1685
|
+
if (!peer.camera) return null;
|
|
1686
|
+
return [
|
|
1687
|
+
peer.peerId,
|
|
1688
|
+
peer.camera.x,
|
|
1689
|
+
peer.camera.y,
|
|
1690
|
+
peer.camera.zoom,
|
|
1691
|
+
peer.camera.viewportWidth,
|
|
1692
|
+
peer.camera.viewportHeight
|
|
1693
|
+
].join(":");
|
|
1694
|
+
}
|
|
1695
|
+
function getViewportSizeKey(viewport) {
|
|
1696
|
+
if (!viewport) return null;
|
|
1697
|
+
const viewportSize = viewport.getViewportSize();
|
|
1698
|
+
return [viewportSize.width, viewportSize.height].join(":");
|
|
1699
|
+
}
|
|
1700
|
+
function getFollowedCameraPosition(viewport, peer) {
|
|
1701
|
+
if (!peer.camera) return null;
|
|
1702
|
+
const viewportSize = viewport.getViewportSize();
|
|
1703
|
+
return {
|
|
1704
|
+
x: peer.camera.x + (viewportSize.width - peer.camera.viewportWidth) / 2,
|
|
1705
|
+
y: peer.camera.y + (viewportSize.height - peer.camera.viewportHeight) / 2,
|
|
1706
|
+
zoom: peer.camera.zoom
|
|
1707
|
+
};
|
|
1708
|
+
}
|
|
1709
|
+
function applyPeerCamera(viewport, peer) {
|
|
1710
|
+
const camera = viewport.getCamera();
|
|
1711
|
+
const nextCamera = getFollowedCameraPosition(viewport, peer);
|
|
1712
|
+
const viewportSize = viewport.getViewportSize();
|
|
1713
|
+
if (!camera || !nextCamera) return false;
|
|
1714
|
+
if (camera.x === nextCamera.x && camera.y === nextCamera.y && camera.zoom === nextCamera.zoom) {
|
|
1715
|
+
return true;
|
|
1716
|
+
}
|
|
1717
|
+
markViewportFollowSync(viewport, {
|
|
1718
|
+
x: nextCamera.x,
|
|
1719
|
+
y: nextCamera.y,
|
|
1720
|
+
zoom: nextCamera.zoom,
|
|
1721
|
+
viewportWidth: viewportSize.width,
|
|
1722
|
+
viewportHeight: viewportSize.height
|
|
1723
|
+
});
|
|
1724
|
+
camera.x = nextCamera.x;
|
|
1725
|
+
camera.y = nextCamera.y;
|
|
1726
|
+
camera.zoom = nextCamera.zoom;
|
|
1727
|
+
viewport.requestRender();
|
|
1728
|
+
return true;
|
|
1729
|
+
}
|
|
1730
|
+
function markViewportFollowSync(viewport, snapshot) {
|
|
1731
|
+
viewportFollowSyncSnapshots.set(viewport, snapshot);
|
|
1732
|
+
}
|
|
1733
|
+
function consumeViewportFollowSync(viewport, snapshot) {
|
|
1734
|
+
const currentSnapshot = viewportFollowSyncSnapshots.get(viewport);
|
|
1735
|
+
if (!currentSnapshot || currentSnapshot.x !== snapshot.x || currentSnapshot.y !== snapshot.y || currentSnapshot.zoom !== snapshot.zoom || currentSnapshot.viewportWidth !== snapshot.viewportWidth || currentSnapshot.viewportHeight !== snapshot.viewportHeight) {
|
|
1736
|
+
return false;
|
|
1737
|
+
}
|
|
1738
|
+
viewportFollowSyncSnapshots.delete(viewport);
|
|
1739
|
+
return true;
|
|
1740
|
+
}
|
|
1741
|
+
function useRealtimePeerFollow(options) {
|
|
1742
|
+
const { viewportRef, sessionPeers, followedPeerId, onFollowEnd } = options;
|
|
1743
|
+
const endedPeerIdRef = useRef(null);
|
|
1744
|
+
const lastAppliedCameraKeyRef = useRef(null);
|
|
1745
|
+
const [viewportSizeVersion, setViewportSizeVersion] = useState(0);
|
|
1746
|
+
useEffect(() => {
|
|
1747
|
+
if (!followedPeerId) return;
|
|
1748
|
+
let animationFrameId = 0;
|
|
1749
|
+
let lastViewportSizeKey = getViewportSizeKey(viewportRef.current ?? null);
|
|
1750
|
+
const checkViewportSize = () => {
|
|
1751
|
+
const nextViewportSizeKey = getViewportSizeKey(viewportRef.current ?? null);
|
|
1752
|
+
if (nextViewportSizeKey !== lastViewportSizeKey) {
|
|
1753
|
+
lastViewportSizeKey = nextViewportSizeKey;
|
|
1754
|
+
setViewportSizeVersion((value) => value + 1);
|
|
1755
|
+
}
|
|
1756
|
+
animationFrameId = window.requestAnimationFrame(checkViewportSize);
|
|
1757
|
+
};
|
|
1758
|
+
animationFrameId = window.requestAnimationFrame(checkViewportSize);
|
|
1759
|
+
return () => {
|
|
1760
|
+
window.cancelAnimationFrame(animationFrameId);
|
|
1761
|
+
};
|
|
1762
|
+
}, [followedPeerId, viewportRef]);
|
|
1763
|
+
useEffect(() => {
|
|
1764
|
+
if (!followedPeerId) {
|
|
1765
|
+
endedPeerIdRef.current = null;
|
|
1766
|
+
lastAppliedCameraKeyRef.current = null;
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
const followedPeer = getFollowedPeer(sessionPeers, followedPeerId);
|
|
1770
|
+
if (!followedPeer) {
|
|
1771
|
+
lastAppliedCameraKeyRef.current = null;
|
|
1772
|
+
if (endedPeerIdRef.current === followedPeerId) {
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
endedPeerIdRef.current = followedPeerId;
|
|
1776
|
+
onFollowEnd?.();
|
|
1777
|
+
return;
|
|
1778
|
+
}
|
|
1779
|
+
if (!followedPeer.camera) {
|
|
1780
|
+
endedPeerIdRef.current = null;
|
|
1781
|
+
lastAppliedCameraKeyRef.current = null;
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
endedPeerIdRef.current = null;
|
|
1785
|
+
const viewport = viewportRef.current;
|
|
1786
|
+
const nextCameraKey = [
|
|
1787
|
+
getCameraKey(followedPeer),
|
|
1788
|
+
getViewportSizeKey(viewport ?? null)
|
|
1789
|
+
].join(":");
|
|
1790
|
+
if (nextCameraKey && nextCameraKey === lastAppliedCameraKeyRef.current) {
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
if (!viewport || !applyPeerCamera(viewport, followedPeer)) {
|
|
1794
|
+
return;
|
|
1795
|
+
}
|
|
1796
|
+
lastAppliedCameraKeyRef.current = nextCameraKey;
|
|
1797
|
+
}, [
|
|
1798
|
+
followedPeerId,
|
|
1799
|
+
onFollowEnd,
|
|
1800
|
+
sessionPeers,
|
|
1801
|
+
viewportRef,
|
|
1802
|
+
viewportSizeVersion
|
|
1803
|
+
]);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
// src/react/plugins/realtime/use-realtime-session.ts
|
|
1650
1807
|
function createClientId() {
|
|
1651
1808
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
1652
1809
|
return crypto.randomUUID();
|
|
@@ -1689,6 +1846,19 @@ function sameSerializedItems(left, right) {
|
|
|
1689
1846
|
function nowMs() {
|
|
1690
1847
|
return Date.now();
|
|
1691
1848
|
}
|
|
1849
|
+
function getViewportCameraSnapshot(viewport) {
|
|
1850
|
+
if (!viewport) return null;
|
|
1851
|
+
const camera = viewport.getCamera();
|
|
1852
|
+
if (!camera) return null;
|
|
1853
|
+
const viewportSize = viewport.getViewportSize();
|
|
1854
|
+
return {
|
|
1855
|
+
x: camera.x,
|
|
1856
|
+
y: camera.y,
|
|
1857
|
+
zoom: camera.zoom,
|
|
1858
|
+
viewportWidth: viewportSize.width,
|
|
1859
|
+
viewportHeight: viewportSize.height
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1692
1862
|
function useRealtimeSession(options) {
|
|
1693
1863
|
const {
|
|
1694
1864
|
url,
|
|
@@ -1715,6 +1885,9 @@ function useRealtimeSession(options) {
|
|
|
1715
1885
|
const subscriberRefs = useRef(/* @__PURE__ */ new Set());
|
|
1716
1886
|
const lastCursorRef = useRef(null);
|
|
1717
1887
|
const lastMarkupStrokeRef = useRef(null);
|
|
1888
|
+
const lastCameraRef = useRef(
|
|
1889
|
+
null
|
|
1890
|
+
);
|
|
1718
1891
|
const lastActiveToolRef = useRef(void 0);
|
|
1719
1892
|
const latestDocumentRef = useRef(null);
|
|
1720
1893
|
const connectionStateRef = useRef(
|
|
@@ -1839,6 +2012,7 @@ function useRealtimeSession(options) {
|
|
|
1839
2012
|
presence: {
|
|
1840
2013
|
cursor: lastCursorRef.current,
|
|
1841
2014
|
markupStroke: lastMarkupStrokeRef.current ?? null,
|
|
2015
|
+
camera: lastCameraRef.current ?? null,
|
|
1842
2016
|
...lastActiveToolRef.current ? { activeTool: lastActiveToolRef.current } : {}
|
|
1843
2017
|
}
|
|
1844
2018
|
});
|
|
@@ -2164,6 +2338,18 @@ function useRealtimeSession(options) {
|
|
|
2164
2338
|
() => sessionPeers.filter((peerState) => !peerState.isSelf),
|
|
2165
2339
|
[sessionPeers]
|
|
2166
2340
|
);
|
|
2341
|
+
const syncViewportPresence = useCallback(
|
|
2342
|
+
(bindingOptions) => {
|
|
2343
|
+
const viewport = bindingOptions?.viewportRef?.current;
|
|
2344
|
+
const cameraSnapshot = getViewportCameraSnapshot(viewport);
|
|
2345
|
+
if (!cameraSnapshot) return false;
|
|
2346
|
+
lastCameraRef.current = cameraSnapshot;
|
|
2347
|
+
lastActiveToolRef.current = bindingOptions?.activeTool;
|
|
2348
|
+
sendPresenceUpdate();
|
|
2349
|
+
return true;
|
|
2350
|
+
},
|
|
2351
|
+
[sendPresenceUpdate]
|
|
2352
|
+
);
|
|
2167
2353
|
const bindViewportPresence = useCallback(
|
|
2168
2354
|
(bindingOptions) => ({
|
|
2169
2355
|
remotePresence,
|
|
@@ -2181,6 +2367,18 @@ function useRealtimeSession(options) {
|
|
|
2181
2367
|
lastMarkupStrokeRef.current = remoteMarkupStrokeFromPlacementPreview(preview);
|
|
2182
2368
|
lastActiveToolRef.current = bindingOptions?.activeTool;
|
|
2183
2369
|
sendPresenceUpdate();
|
|
2370
|
+
},
|
|
2371
|
+
onCameraChange() {
|
|
2372
|
+
const viewport = bindingOptions?.viewportRef?.current;
|
|
2373
|
+
const cameraSnapshot = getViewportCameraSnapshot(viewport);
|
|
2374
|
+
if (!cameraSnapshot) return;
|
|
2375
|
+
if (viewport && consumeViewportFollowSync(viewport, cameraSnapshot)) {
|
|
2376
|
+
lastCameraRef.current = cameraSnapshot;
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
lastCameraRef.current = cameraSnapshot;
|
|
2380
|
+
lastActiveToolRef.current = bindingOptions?.activeTool;
|
|
2381
|
+
sendPresenceUpdate();
|
|
2184
2382
|
}
|
|
2185
2383
|
}),
|
|
2186
2384
|
[remotePresence, sendPresenceUpdate]
|
|
@@ -2192,6 +2390,7 @@ function useRealtimeSession(options) {
|
|
|
2192
2390
|
remoteAdapter,
|
|
2193
2391
|
document: document2,
|
|
2194
2392
|
bindViewportPresence,
|
|
2393
|
+
syncViewportPresence,
|
|
2195
2394
|
disconnect,
|
|
2196
2395
|
reconnectNow
|
|
2197
2396
|
};
|
|
@@ -2236,9 +2435,37 @@ function RealtimeCollaborationPluginComponent({
|
|
|
2236
2435
|
...commentOptions ?? {}
|
|
2237
2436
|
});
|
|
2238
2437
|
const presenceBindings = useMemo(
|
|
2239
|
-
() => session.bindViewportPresence({
|
|
2240
|
-
|
|
2438
|
+
() => session.bindViewportPresence({
|
|
2439
|
+
activeTool: viewport.toolId,
|
|
2440
|
+
viewportRef
|
|
2441
|
+
}),
|
|
2442
|
+
[session.bindViewportPresence, viewport.toolId, viewportRef]
|
|
2241
2443
|
);
|
|
2444
|
+
const onViewportCameraChange = useCallback(() => {
|
|
2445
|
+
presenceBindings.onCameraChange?.();
|
|
2446
|
+
comments.viewport.onCameraChange?.();
|
|
2447
|
+
}, [comments.viewport, presenceBindings]);
|
|
2448
|
+
useEffect(() => {
|
|
2449
|
+
if (!session.connection.connected) return;
|
|
2450
|
+
let animationFrameId = 0;
|
|
2451
|
+
const syncViewportPresence = () => {
|
|
2452
|
+
const didSync = session.syncViewportPresence({
|
|
2453
|
+
activeTool: viewport.toolId,
|
|
2454
|
+
viewportRef
|
|
2455
|
+
});
|
|
2456
|
+
if (didSync) return;
|
|
2457
|
+
animationFrameId = window.requestAnimationFrame(syncViewportPresence);
|
|
2458
|
+
};
|
|
2459
|
+
syncViewportPresence();
|
|
2460
|
+
return () => {
|
|
2461
|
+
window.cancelAnimationFrame(animationFrameId);
|
|
2462
|
+
};
|
|
2463
|
+
}, [
|
|
2464
|
+
session.connection.connected,
|
|
2465
|
+
session.syncViewportPresence,
|
|
2466
|
+
viewport.toolId,
|
|
2467
|
+
viewportRef
|
|
2468
|
+
]);
|
|
2242
2469
|
useEffect(() => {
|
|
2243
2470
|
if (!onItemsChange || !session.document) return;
|
|
2244
2471
|
if (session.document.updatedByClientId === session.connection.clientId) return;
|
|
@@ -2255,11 +2482,14 @@ function RealtimeCollaborationPluginComponent({
|
|
|
2255
2482
|
onWorldPointerMove: presenceBindings.onWorldPointerMove,
|
|
2256
2483
|
onWorldPointerLeave: presenceBindings.onWorldPointerLeave,
|
|
2257
2484
|
onPlacementPreviewChange: presenceBindings.onPlacementPreviewChange,
|
|
2258
|
-
onCameraChange:
|
|
2485
|
+
onCameraChange: onViewportCameraChange
|
|
2259
2486
|
},
|
|
2260
2487
|
wrapOnItemsChange: (nextItems, ctx) => {
|
|
2261
2488
|
if (commentOptions) {
|
|
2262
|
-
comments.
|
|
2489
|
+
comments.handleViewportItemsChange(nextItems, (processedItems) => {
|
|
2490
|
+
ctx.next(processedItems);
|
|
2491
|
+
session.remoteAdapter.send?.([...processedItems]);
|
|
2492
|
+
});
|
|
2263
2493
|
return;
|
|
2264
2494
|
}
|
|
2265
2495
|
ctx.next(nextItems);
|
|
@@ -2270,6 +2500,8 @@ function RealtimeCollaborationPluginComponent({
|
|
|
2270
2500
|
commentOptions,
|
|
2271
2501
|
comments.tools,
|
|
2272
2502
|
comments.viewport,
|
|
2503
|
+
comments.handleViewportItemsChange,
|
|
2504
|
+
onViewportCameraChange,
|
|
2273
2505
|
presenceBindings,
|
|
2274
2506
|
session.remoteAdapter
|
|
2275
2507
|
]
|
|
@@ -2312,6 +2544,6 @@ function realtimeSessionPlugin(options) {
|
|
|
2312
2544
|
};
|
|
2313
2545
|
}
|
|
2314
2546
|
|
|
2315
|
-
export { PresenceRemoteLayer, REALTIME_COMMENT_TOOL, RealtimeCommentsOverlay, RealtimeSessionPanel, createRealtimeCommentAvatarDataUrl, createRealtimeCommentDraftItem, createRealtimeCommentItem, defaultPresenceColorForId, getRealtimeCommentData, isRealtimeCommentDraftItem, isRealtimeCommentItem, parseRealtimeClientMessage, parseRealtimeServerMessage, realtimeCollaborationPlugin, realtimeCommentsPlugin, realtimeSessionPlugin, remoteMarkupStrokeFromPlacementPreview, useRealtimeComments, useRealtimeSession, withRealtimeCommentTool };
|
|
2547
|
+
export { PresenceRemoteLayer, REALTIME_COMMENT_TOOL, RealtimeCommentsOverlay, RealtimeSessionPanel, createRealtimeCommentAvatarDataUrl, createRealtimeCommentDraftItem, createRealtimeCommentItem, defaultPresenceColorForId, getRealtimeCommentData, isRealtimeCommentDraftItem, isRealtimeCommentItem, parseRealtimeClientMessage, parseRealtimeServerMessage, realtimeCollaborationPlugin, realtimeCommentsPlugin, realtimeSessionPlugin, remoteMarkupStrokeFromPlacementPreview, useRealtimeComments, useRealtimePeerFollow, useRealtimeSession, withRealtimeCommentTool };
|
|
2316
2548
|
//# sourceMappingURL=realtime.js.map
|
|
2317
2549
|
//# sourceMappingURL=realtime.js.map
|