fix(crdt): sync groups and bgConfig via Yjs (Issue #6)
This commit is contained in:
@@ -8,6 +8,8 @@ import { YjsDocument } from './YjsDocument';
|
||||
import { WebSocketProvider, type ConnectionStatus } from './WebSocketProvider';
|
||||
import { AwarenessManager, type UserCursor, type UserSelection } from './AwarenessManager';
|
||||
import type { CADElement, CADLayer, BlockDefinition } from '../types/cad.types';
|
||||
import type { ElementGroup } from '../tools/modification/GroupTool';
|
||||
import type { BackgroundConfig } from '../services/backgroundService';
|
||||
|
||||
export interface UseYjsBindingOptions {
|
||||
docName: string;
|
||||
@@ -27,6 +29,8 @@ export interface UseYjsBindingResult {
|
||||
elements: CADElement[];
|
||||
layers: CADLayer[];
|
||||
blocks: BlockDefinition[];
|
||||
groups: ElementGroup[];
|
||||
bgConfigs: BackgroundConfig[];
|
||||
cursors: UserCursor[];
|
||||
selections: UserSelection[];
|
||||
setElement: (el: CADElement) => void;
|
||||
@@ -35,7 +39,17 @@ export interface UseYjsBindingResult {
|
||||
deleteLayer: (id: string) => void;
|
||||
setBlock: (block: BlockDefinition) => void;
|
||||
deleteBlock: (id: string) => void;
|
||||
loadFromState: (state: { elements: CADElement[]; layers: CADLayer[]; blocks: BlockDefinition[] }) => void;
|
||||
setGroup: (group: ElementGroup) => void;
|
||||
deleteGroup: (id: string) => void;
|
||||
setBgConfig: (id: string, config: BackgroundConfig) => void;
|
||||
deleteBgConfig: (id: string) => void;
|
||||
loadFromState: (state: {
|
||||
elements: CADElement[];
|
||||
layers: CADLayer[];
|
||||
blocks: BlockDefinition[];
|
||||
groups?: ElementGroup[];
|
||||
bgConfigs?: BackgroundConfig[];
|
||||
}) => void;
|
||||
setCursor: (x: number, y: number) => void;
|
||||
hideCursor: () => void;
|
||||
setSelection: (elementIds: string[]) => void;
|
||||
@@ -56,6 +70,8 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
const [elements, setElements] = useState<CADElement[]>([]);
|
||||
const [layers, setLayers] = useState<CADLayer[]>([]);
|
||||
const [blocks, setBlocks] = useState<BlockDefinition[]>([]);
|
||||
const [groups, setGroups] = useState<ElementGroup[]>([]);
|
||||
const [bgConfigs, setBgConfigs] = useState<BackgroundConfig[]>([]);
|
||||
const [cursors, setCursors] = useState<UserCursor[]>([]);
|
||||
const [selections, setSelections] = useState<UserSelection[]>([]);
|
||||
|
||||
@@ -82,6 +98,8 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
setElements(doc.getElements());
|
||||
setLayers(doc.getLayers());
|
||||
setBlocks(doc.getBlocks());
|
||||
setGroups(doc.getGroups());
|
||||
setBgConfigs(doc.getBgConfigs());
|
||||
setCursors(awareness.getAllCursors());
|
||||
setSelections(awareness.getAllSelections());
|
||||
};
|
||||
@@ -89,6 +107,20 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
const unbindDoc = doc.onChange(syncState);
|
||||
const unbindAwareness = awareness.onChange(syncState);
|
||||
|
||||
// Dedicated observers for groups and bgConfig maps
|
||||
const groupsMap = doc.data.groups;
|
||||
const bgConfigMap = doc.data.bgConfig;
|
||||
|
||||
const groupsObserver = () => {
|
||||
setGroups(Array.from(groupsMap.values()));
|
||||
};
|
||||
const bgConfigObserver = () => {
|
||||
setBgConfigs(Array.from(bgConfigMap.values()));
|
||||
};
|
||||
|
||||
groupsMap.observe(groupsObserver);
|
||||
bgConfigMap.observe(bgConfigObserver);
|
||||
|
||||
// Forward local updates to server
|
||||
const unbindLocal = provider.bindLocalUpdates();
|
||||
|
||||
@@ -98,6 +130,8 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
|
||||
// Cleanup
|
||||
return () => {
|
||||
groupsMap.unobserve(groupsObserver);
|
||||
bgConfigMap.unobserve(bgConfigObserver);
|
||||
unbindDoc();
|
||||
unbindAwareness();
|
||||
unbindLocal();
|
||||
@@ -135,7 +169,29 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
yjsDocRef.current?.deleteBlock(id);
|
||||
}, []);
|
||||
|
||||
const loadFromState = useCallback((state: { elements: CADElement[]; layers: CADLayer[]; blocks: BlockDefinition[] }) => {
|
||||
const setGroup = useCallback((group: ElementGroup) => {
|
||||
yjsDocRef.current?.setGroup(group);
|
||||
}, []);
|
||||
|
||||
const deleteGroup = useCallback((id: string) => {
|
||||
yjsDocRef.current?.deleteGroup(id);
|
||||
}, []);
|
||||
|
||||
const setBgConfig = useCallback((id: string, config: BackgroundConfig) => {
|
||||
yjsDocRef.current?.setBgConfig(id, config);
|
||||
}, []);
|
||||
|
||||
const deleteBgConfig = useCallback((id: string) => {
|
||||
yjsDocRef.current?.deleteBgConfig(id);
|
||||
}, []);
|
||||
|
||||
const loadFromState = useCallback((state: {
|
||||
elements: CADElement[];
|
||||
layers: CADLayer[];
|
||||
blocks: BlockDefinition[];
|
||||
groups?: ElementGroup[];
|
||||
bgConfigs?: BackgroundConfig[];
|
||||
}) => {
|
||||
yjsDocRef.current?.loadFromState(state);
|
||||
}, []);
|
||||
|
||||
@@ -163,6 +219,8 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
elements,
|
||||
layers,
|
||||
blocks,
|
||||
groups,
|
||||
bgConfigs,
|
||||
cursors,
|
||||
selections,
|
||||
setElement,
|
||||
@@ -171,6 +229,10 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
deleteLayer,
|
||||
setBlock,
|
||||
deleteBlock,
|
||||
setGroup,
|
||||
deleteGroup,
|
||||
setBgConfig,
|
||||
deleteBgConfig,
|
||||
loadFromState,
|
||||
setCursor,
|
||||
hideCursor,
|
||||
|
||||
Reference in New Issue
Block a user