feat: offline support, performance benchmark, y-indexeddb integration
- Add y-indexeddb for offline CRDT persistence (IndexedDB) - useYjsBinding now creates IndexeddbPersistence per document - State syncs from IndexedDB on reconnect - Graceful fallback if IndexedDB unavailable - Add Performance Benchmark test (50k elements) - Bulk insert: 50k elements in <2s - Viewport search: <10ms for ~1000 visible elements - Full viewport search: <100ms for all 50k elements - 100 sequential searches: <500ms - Remove 1000 elements: <200ms - Clear all: <50ms - Bearbeitungs-Tools already fully implemented (move, copy, rotate, scale, mirror, trim, extend, fillet, offset) - Bestuhlungs-Tools already fully implemented (seating-row, seating-block, table, stage, templates) All 634 tests passing (254 backend + 380 frontend)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import * as Y from 'yjs';
|
||||
import { IndexeddbPersistence } from 'y-indexeddb';
|
||||
import { YjsDocument } from './YjsDocument';
|
||||
import { WebSocketProvider, type ConnectionStatus } from './WebSocketProvider';
|
||||
import { AwarenessManager, type UserCursor, type UserSelection } from './AwarenessManager';
|
||||
@@ -90,6 +91,22 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
const doc = new YjsDocument();
|
||||
yjsDocRef.current = doc;
|
||||
|
||||
// IndexedDB offline persistence — allows editing without network connection
|
||||
let indexedDbProvider: IndexeddbPersistence | null = null;
|
||||
try {
|
||||
indexedDbProvider = new IndexeddbPersistence(`webcad-${docName}`, doc.doc);
|
||||
indexedDbProvider.whenSynced.then(() => {
|
||||
// Sync state from IndexedDB once loaded
|
||||
setElements(doc.getElements());
|
||||
setLayers(doc.getLayers());
|
||||
setBlocks(doc.getBlocks());
|
||||
setGroups(doc.getGroups());
|
||||
setBgConfigs(doc.getBgConfigs());
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn('[useYjsBinding] IndexedDB persistence unavailable:', err);
|
||||
}
|
||||
|
||||
const awareness = new AwarenessManager(doc, userId);
|
||||
awarenessRef.current = awareness;
|
||||
|
||||
@@ -150,6 +167,10 @@ export function useYjsBinding(opts: UseYjsBindingOptions): UseYjsBindingResult {
|
||||
awareness.removeSelf();
|
||||
awareness.destroy();
|
||||
provider.disconnect();
|
||||
if (indexedDbProvider) {
|
||||
indexedDbProvider.destroy();
|
||||
indexedDbProvider = null;
|
||||
}
|
||||
doc.destroy();
|
||||
yjsDocRef.current = null;
|
||||
providerRef.current = null;
|
||||
|
||||
Reference in New Issue
Block a user