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(() => {
|
useEffect(() => {
|
||||||
if (tenantId && viewId) {
|
if (tenantId && viewId) {
|
||||||
|
// Clear store when switching views to prevent stale items
|
||||||
|
layoutStore.clear();
|
||||||
layoutStore.loadLayout(String(tenantId), viewId);
|
layoutStore.loadLayout(String(tenantId), viewId);
|
||||||
}
|
}
|
||||||
}, [layoutStore, 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
|
// Selection Context
|
||||||
const {
|
const {
|
||||||
selectedDocumentIds,
|
selectedDocumentIds,
|
||||||
@@ -216,8 +230,8 @@ const DesktopWorkspace: React.FC<DesktopWorkspaceProps> = ({
|
|||||||
const size = ensureDocumentSize(doc);
|
const size = ensureDocumentSize(doc);
|
||||||
|
|
||||||
const layoutCard = layoutStore.initialize(docId, null, {
|
const layoutCard = layoutStore.initialize(docId, null, {
|
||||||
width: size.width,
|
width: Number.isFinite(size.width) && size.width > 0 ? size.width : 200,
|
||||||
height: size.height
|
height: Number.isFinite(size.height) && size.height > 0 ? size.height : 200
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -363,6 +363,12 @@ export class LayoutStore {
|
|||||||
this.items.delete(id);
|
this.items.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.items.clear();
|
||||||
|
this.zCounter = 100;
|
||||||
|
this.savedLayouts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
setContainerSize(width: number, height: number) {
|
setContainerSize(width: number, height: number) {
|
||||||
this.containerWidth = width;
|
this.containerWidth = width;
|
||||||
this.containerHeight = height;
|
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 { DocumentId } from '../../types/identifiers';
|
||||||
import type { Document } from '../../types/documents';
|
import type { Document } from '../../types/documents';
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ const usePreviewMetadata = (
|
|||||||
ensureAssetUrl?: EnsureAssetUrl,
|
ensureAssetUrl?: EnsureAssetUrl,
|
||||||
) => {
|
) => {
|
||||||
const [metadataMap, setMetadataMap] = useState<Map<string, PreviewMetadataEntry>>(() => new Map());
|
const [metadataMap, setMetadataMap] = useState<Map<string, PreviewMetadataEntry>>(() => new Map());
|
||||||
|
const failedIds = useRef(new Set<string>()); // Track failed fetches to prevent loops
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
@@ -51,14 +52,23 @@ const usePreviewMetadata = (
|
|||||||
Number(meta.height) > 0;
|
Number(meta.height) > 0;
|
||||||
|
|
||||||
if (!hasDimensions(metadata) && ensureAssetUrl && docId && asset?.id) {
|
if (!hasDimensions(metadata) && ensureAssetUrl && docId && asset?.id) {
|
||||||
try {
|
// Skip if we already failed for this doc to avoid infinite loops
|
||||||
const ensured = await ensureAssetUrl(doc.id, asset);
|
if (!failedIds.current.has(docId)) {
|
||||||
if (ensured) {
|
try {
|
||||||
asset = ensured;
|
const ensured = await ensureAssetUrl(doc.id, asset);
|
||||||
metadata = (asset?.metadata as { width?: number; height?: number } | null) || null;
|
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