feat: Introduce spatial workspace architecture design document, enhance layout store item synchronization, and prevent metadata fetch retries.
This commit is contained in:
@@ -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 (
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user