feat: Introduce spatial workspace architecture design document, enhance layout store item synchronization, and prevent metadata fetch retries.

This commit is contained in:
2025-11-26 22:03:09 +01:00
parent e36732cc2d
commit 0c6504ef1c
3 changed files with 40 additions and 10 deletions
+16 -2
View File
@@ -124,10 +124,24 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
useEffect(() => {
if (tenantId && viewId) {
// Clear store when switching views to prevent stale items
layoutStore.clear();
layoutStore.loadLayout(String(tenantId), viewId);
}
}, [layoutStore, tenantId, viewId]);
// Sync LayoutStore items with current entries to remove stale items
useEffect(() => {
const currentIds = new Set(items.map((doc, index) => doc.id ? String(doc.id) : `temp-${index}`));
// Identify and remove items that are no longer present
for (const id of layoutStore.items.keys()) {
if (!currentIds.has(id)) {
layoutStore.unregister(id);
}
}
}, [items, layoutStore]);
// Selection Context
const {
selectedDocumentIds,
@@ -216,8 +230,8 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
const size = ensureDocumentSize(doc);
const layoutCard = layoutStore.initialize(docId, null, {
width: size.width,
height: size.height
width: Number.isFinite(size.width) && size.width > 0 ? size.width : 200,
height: Number.isFinite(size.height) && size.height > 0 ? size.height : 200
});
return (
+6
View File
@@ -363,6 +363,12 @@ export class LayoutStore {
this.items.delete(id);
}
clear() {
this.items.clear();
this.zCounter = 100;
this.savedLayouts.clear();
}
setContainerSize(width: number, height: number) {
this.containerWidth = width;
this.containerHeight = height;
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';
import type { DocumentId } from '../../types/identifiers';
import type { Document } from '../../types/documents';
@@ -22,6 +22,7 @@ const usePreviewMetadata = (
ensureAssetUrl?: EnsureAssetUrl,
) => {
const [metadataMap, setMetadataMap] = useState<Map<string, PreviewMetadataEntry>>(() => new Map());
const failedIds = useRef(new Set<string>()); // Track failed fetches to prevent loops
useEffect(() => {
let cancelled = false;
@@ -51,14 +52,23 @@ const usePreviewMetadata = (
Number(meta.height) > 0;
if (!hasDimensions(metadata) && ensureAssetUrl && docId && asset?.id) {
try {
const ensured = await ensureAssetUrl(doc.id, asset);
if (ensured) {
asset = ensured;
metadata = (asset?.metadata as { width?: number; height?: number } | null) || null;
// Skip if we already failed for this doc to avoid infinite loops
if (!failedIds.current.has(docId)) {
try {
const ensured = await ensureAssetUrl(doc.id, asset);
if (ensured) {
asset = ensured;
metadata = (asset?.metadata as { width?: number; height?: number } | null) || null;
}
// If still no dimensions, mark as failed so we don't try again
if (!hasDimensions(metadata)) {
failedIds.current.add(docId);
}
} catch (error) {
console.warn('[desk] ensureDocumentSize metadata fetch failed', error);
failedIds.current.add(docId);
}
} catch (error) {
console.warn('[desk] ensureDocumentSize metadata fetch failed', error);
}
}