idbdatabase

This commit is contained in:
2025-11-02 22:33:27 +01:00
parent 626b6c16e0
commit 5c0f350296
+59 -67
View File
@@ -24,6 +24,7 @@ import {
parseTagTransferPayload,
writeTagTransferData,
} from './documents/tagTransfer';
import { fetchLayoutRecords, upsertLayoutRecords } from './desk/db';
import './DesktopWorkspace.css';
const CANVAS_PADDING = 24;
@@ -628,58 +629,7 @@ const DesktopWorkspace = ({
documentLookupRef.current = documentLookup;
}, [documentLookup]);
const storageKey = useMemo(() => {
if (!tenantId || !viewId) {
return null;
}
const normalizedViewId = encodeURIComponent(String(viewId));
return `papercrate.desk-layout.${tenantId}.${normalizedViewId}`;
}, [tenantId, viewId]);
const initialPersistedLayout = useMemo(() => {
if (!storageKey || typeof window === 'undefined') {
return new Map();
}
try {
const raw = window.localStorage.getItem(storageKey);
if (!raw) {
return new Map();
}
const parsed = JSON.parse(raw);
if (!parsed || typeof parsed !== 'object') {
return new Map();
}
const map = new Map();
Object.entries(parsed).forEach(([docId, value]) => {
if (!value || typeof value !== 'object') {
return;
}
const centerX = Number(value.centerX);
const centerY = Number(value.centerY);
if (!Number.isFinite(centerX) || !Number.isFinite(centerY)) {
return;
}
const rotation = Number.isFinite(Number(value.rotation)) ? Number(value.rotation) : 0;
const z = Number.isFinite(Number(value.z)) ? Number(value.z) : undefined;
map.set(String(docId), {
centerX,
centerY,
rotation,
z,
});
});
return map;
} catch (error) {
console.warn('[desk] Failed to parse persisted layout', error);
return new Map();
}
}, [storageKey]);
const persistedLayoutRef = useRef(initialPersistedLayout);
useEffect(() => {
persistedLayoutRef.current = initialPersistedLayout;
}, [initialPersistedLayout]);
const persistedLayoutRef = useRef(new Map());
const markLayoutDirty = useCallback(() => {
layoutDirtyRef.current = true;
@@ -1167,8 +1117,8 @@ const recalcVisibleDocIds = useCallback(() => {
]);
const persistLayoutSnapshot = useCallback(
(snapshot, force = false) => {
if (!storageKey || typeof window === 'undefined') {
async (snapshot, force = false) => {
if (!tenantId || !viewId) {
return;
}
if (!force && !layoutDirtyRef.current) {
@@ -1190,21 +1140,25 @@ const recalcVisibleDocIds = useCallback(() => {
merged.set(docId, { centerX, centerY, rotation, z });
});
const payload = {};
persistedLayoutRef.current = merged;
const records = [];
merged.forEach((entry, docId) => {
if (!docId || !entry) {
return;
}
payload[docId] = entry;
records.push({
documentId: docId,
centerX: entry.centerX,
centerY: entry.centerY,
rotation: entry.rotation ?? 0,
zIndex: entry.z ?? 0,
});
});
try {
window.localStorage.setItem(storageKey, JSON.stringify(payload));
persistedLayoutRef.current = merged;
} catch (error) {
console.warn('[desk] Failed to persist desk layout', error);
}
await upsertLayoutRecords({ tenantId, viewId, entries: records });
},
[storageKey],
[tenantId, viewId],
);
const syncLayoutSnapshot = useCallback((force = false) => {
@@ -1250,6 +1204,47 @@ const recalcVisibleDocIds = useCallback(() => {
observer.observe(container);
return () => observer.disconnect();
}, []);
useEffect(() => {
if (!tenantId || !viewId) {
return;
}
let cancelled = false;
const loadLayouts = async () => {
const records = await fetchLayoutRecords({ tenantId, viewId });
if (cancelled) {
return;
}
const map = new Map();
records.forEach((record) => {
if (!record || !record.documentId) {
return;
}
map.set(String(record.documentId), {
centerX: Number(record.centerX) || 0,
centerY: Number(record.centerY) || 0,
rotation: Number(record.rotation) || 0,
z: Number(record.zIndex) || 0,
});
});
persistedLayoutRef.current = map;
layoutDirtyRef.current = false;
if (records.length) {
zCounterRef.current = Math.max(
zCounterRef.current,
...records.map((r) => Number(r.zIndex) || 0),
);
}
setDocSizeVersion((value) => value + 1);
};
loadLayouts();
return () => {
cancelled = true;
};
}, [tenantId, viewId]);
useLayoutEffect(() => {
if (!containerRef.current || !canvasSize.width || !canvasSize.height) {
return;
@@ -1291,9 +1286,7 @@ const recalcVisibleDocIds = useCallback(() => {
const persisted = docKey ? persistedLayoutRef.current.get(docKey) : null;
let existing = previous.get(doc.id) || null;
if (persisted) {
existing = existing
? { ...existing, ...persisted }
: { ...persisted };
existing = existing ? { ...existing, ...persisted } : { ...persisted };
}
if (existing) {
const defaultCenterX = (minCenterX + maxCenterX) / 2;
@@ -1349,7 +1342,6 @@ const recalcVisibleDocIds = useCallback(() => {
syncLayoutSnapshot,
recalcVisibleDocIds,
]);
useEffect(() => {
recalcVisibleDocIds();
}, [recalcVisibleDocIds, items.length, canvasSize.width, canvasSize.height, docSizeVersion]);