deskview
This commit is contained in:
@@ -8,7 +8,8 @@ import React, {
|
||||
} from 'react';
|
||||
import { resolveDocumentAssetUrl, createAssetView } from './asset_manager';
|
||||
import { useAssetNavigator } from './hooks/useAssetNavigator';
|
||||
import { ArrowLeftIcon, ArrowRightIcon, RefreshIcon } from './ui/icons';
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from './ui/icons';
|
||||
import { createDocumentsTableHeaderActions } from './documents/DocumentsTable';
|
||||
import { clamp, formatTransform } from './desktop/math';
|
||||
import { preventAll } from './desktop/events';
|
||||
import useDocumentDrag from './desktop/useDocumentDrag';
|
||||
@@ -122,7 +123,7 @@ const readTransferData = (dataTransfer, mimeTypes) => {
|
||||
}
|
||||
} catch (error) {
|
||||
if (DEBUG_DROP) {
|
||||
console.warn('[skeuo] readTransferData failed for type', type, error);
|
||||
console.warn('[desk] readTransferData failed for type', type, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +141,7 @@ const parseTagTransferPayload = (event) => {
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch (error) {
|
||||
console.warn('[skeuo] parseTagTransferPayload failed', error);
|
||||
console.warn('[desk] parseTagTransferPayload failed', error);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -207,8 +208,8 @@ const DesktopPreviewCard = ({
|
||||
onNavigatorSnapshot,
|
||||
]);
|
||||
const hasPreview = Boolean(currentUrl);
|
||||
const cardClasses = ['skeuo-item__card'];
|
||||
if (!hasPreview) cardClasses.push('skeuo-item__card--empty');
|
||||
const cardClasses = ['desk-item__card'];
|
||||
if (!hasPreview) cardClasses.push('desk-item__card--empty');
|
||||
const showNav = hasPreview && (cardinality > 1 || canGoPrev || canGoNext);
|
||||
|
||||
return (
|
||||
@@ -216,18 +217,18 @@ const DesktopPreviewCard = ({
|
||||
{hasPreview ? (
|
||||
<img src={currentUrl} alt={title} />
|
||||
) : (
|
||||
<div className="skeuo-item__empty">
|
||||
<div className="skeuo-item__placeholder">DOC</div>
|
||||
<div className="skeuo-item__title" title={title}>
|
||||
<div className="desk-item__empty">
|
||||
<div className="desk-item__placeholder">DOC</div>
|
||||
<div className="desk-item__title" title={title}>
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showNav ? (
|
||||
<div className="skeuo-card__nav">
|
||||
<div className="desk-card__nav">
|
||||
<button
|
||||
type="button"
|
||||
className="skeuo-card__nav-button"
|
||||
className="desk-card__nav-button"
|
||||
onClick={(event) => {
|
||||
preventAll(event);
|
||||
navigator.goPrev();
|
||||
@@ -251,7 +252,7 @@ const DesktopPreviewCard = ({
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="skeuo-card__nav-button"
|
||||
className="desk-card__nav-button"
|
||||
onClick={(event) => {
|
||||
preventAll(event);
|
||||
navigator.goNext();
|
||||
@@ -463,7 +464,7 @@ const usePreviewMetadata = (documents, getDocumentAsset, ensureAssetUrl) => {
|
||||
metadata = view.getPrimaryMetadata();
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[skeuo] ensureDocumentSize metadata fetch failed', error);
|
||||
console.warn('[desk] ensureDocumentSize metadata fetch failed', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,15 +751,15 @@ const DesktopWorkspace = ({
|
||||
const focusTarget = () => {
|
||||
try {
|
||||
if (DEBUG_FOCUS) {
|
||||
console.log('[skeuo] focusCanvas -> attempting focus', canvas);
|
||||
console.log('[desk] focusCanvas -> attempting focus', canvas);
|
||||
}
|
||||
canvas.focus({ preventScroll: true });
|
||||
if (DEBUG_FOCUS) {
|
||||
console.log('[skeuo] focusCanvas: applied focus. activeElement:', document?.activeElement);
|
||||
console.log('[desk] focusCanvas: applied focus. activeElement:', document?.activeElement);
|
||||
}
|
||||
} catch (error) {
|
||||
if (DEBUG_FOCUS) {
|
||||
console.warn('[skeuo] focusTarget failed to focus canvas', error);
|
||||
console.warn('[desk] focusTarget failed to focus canvas', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -769,20 +770,20 @@ const DesktopWorkspace = ({
|
||||
}
|
||||
|
||||
if (DEBUG_FOCUS) {
|
||||
console.log('[skeuo] requestCanvasFocus -> scheduling deferred focus');
|
||||
console.log('[desk] requestCanvasFocus -> scheduling deferred focus');
|
||||
}
|
||||
|
||||
if (typeof window.requestAnimationFrame === 'function') {
|
||||
window.requestAnimationFrame(() => {
|
||||
if (DEBUG_FOCUS) {
|
||||
console.log('[skeuo] requestCanvasFocus -> executing deferred focus (rAF)');
|
||||
console.log('[desk] requestCanvasFocus -> executing deferred focus (rAF)');
|
||||
}
|
||||
focusTarget();
|
||||
});
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (DEBUG_FOCUS) {
|
||||
console.log('[skeuo] requestCanvasFocus -> executing deferred focus (timeout)');
|
||||
console.log('[desk] requestCanvasFocus -> executing deferred focus (timeout)');
|
||||
}
|
||||
focusTarget();
|
||||
}, 0);
|
||||
@@ -802,9 +803,9 @@ const DesktopWorkspace = ({
|
||||
}
|
||||
removalCursorActiveRef.current = active;
|
||||
if (active) {
|
||||
body.classList.add('skeuo-cursor-remove');
|
||||
body.classList.add('desk-cursor-remove');
|
||||
} else {
|
||||
body.classList.remove('skeuo-cursor-remove');
|
||||
body.classList.remove('desk-cursor-remove');
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -1080,7 +1081,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
|
||||
const nodeEnv = typeof globalThis !== 'undefined' ? globalThis.process?.env?.NODE_ENV : undefined;
|
||||
if (nodeEnv !== 'production') {
|
||||
console.log('[skeuo] canvas element', container);
|
||||
console.log('[desk] canvas element', container);
|
||||
}
|
||||
|
||||
const commitSize = () => {
|
||||
@@ -1238,7 +1239,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
return;
|
||||
}
|
||||
const container = itemRefs.current.get(docId);
|
||||
const imageNode = container?.querySelector?.('.skeuo-item__card img');
|
||||
const imageNode = container?.querySelector?.('.desk-item__card img');
|
||||
if (!container || !imageNode) {
|
||||
return;
|
||||
}
|
||||
@@ -1353,24 +1354,24 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
async (event, doc) => {
|
||||
if (!doc || !isTagTransfer(event) || typeof onAssignTagToDocument !== 'function') {
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: drop ignored', { doc, hasTransfer: isTagTransfer(event) });
|
||||
console.log('[desk] handleTagDropOnDoc: drop ignored', { doc, hasTransfer: isTagTransfer(event) });
|
||||
}
|
||||
return;
|
||||
}
|
||||
preventAll(event);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: drop accepted for doc', doc.id, 'event', event);
|
||||
console.log('[desk] handleTagDropOnDoc: drop accepted for doc', doc.id, 'event', event);
|
||||
}
|
||||
setTagDropTargetId(null);
|
||||
|
||||
const payload = parseTagTransferPayload(event);
|
||||
if (!payload && DEBUG_DROP) {
|
||||
console.warn('[skeuo] handleTagDropOnDoc: failed to parse payload');
|
||||
console.warn('[desk] handleTagDropOnDoc: failed to parse payload');
|
||||
}
|
||||
|
||||
if (!payload?.id) {
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: missing tag id payload', payload);
|
||||
console.log('[desk] handleTagDropOnDoc: missing tag id payload', payload);
|
||||
}
|
||||
requestCanvasFocus();
|
||||
return;
|
||||
@@ -1379,13 +1380,13 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
const tagId = payload.id;
|
||||
const sourceDocId = payload.sourceDocId || null;
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: parsed payload', { tagId, sourceDocId });
|
||||
console.log('[desk] handleTagDropOnDoc: parsed payload', { tagId, sourceDocId });
|
||||
}
|
||||
|
||||
if (sourceDocId && sourceDocId === doc.id) {
|
||||
markActiveTagDropHandled(tagId, sourceDocId);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: drop from same doc ignored', tagId);
|
||||
console.log('[desk] handleTagDropOnDoc: drop from same doc ignored', tagId);
|
||||
}
|
||||
requestCanvasFocus();
|
||||
return;
|
||||
@@ -1397,7 +1398,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
if (alreadyAssigned) {
|
||||
markActiveTagDropHandled(tagId, sourceDocId);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: tag already assigned', tagId);
|
||||
console.log('[desk] handleTagDropOnDoc: tag already assigned', tagId);
|
||||
}
|
||||
requestCanvasFocus();
|
||||
return;
|
||||
@@ -1405,7 +1406,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
|
||||
const movingBetweenDocuments = Boolean(sourceDocId && sourceDocId !== doc.id);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: movingBetweenDocuments', movingBetweenDocuments);
|
||||
console.log('[desk] handleTagDropOnDoc: movingBetweenDocuments', movingBetweenDocuments);
|
||||
}
|
||||
|
||||
setPendingTagDocId(doc.id);
|
||||
@@ -1413,14 +1414,14 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
await onAssignTagToDocument({ documentId: doc.id, tagId, tag: payload });
|
||||
markActiveTagDropHandled(tagId, sourceDocId);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: assigned tag', tagId, 'to doc', doc.id);
|
||||
console.log('[desk] handleTagDropOnDoc: assigned tag', tagId, 'to doc', doc.id);
|
||||
}
|
||||
if (movingBetweenDocuments && typeof onRemoveTagFromDocument === 'function') {
|
||||
setPendingRemovalTag({ docId: sourceDocId, tagId });
|
||||
try {
|
||||
await onRemoveTagFromDocument(sourceDocId, tagId);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: removed tag from source doc', sourceDocId);
|
||||
console.log('[desk] handleTagDropOnDoc: removed tag from source doc', sourceDocId);
|
||||
}
|
||||
} finally {
|
||||
setPendingRemovalTag(null);
|
||||
@@ -1429,7 +1430,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
} finally {
|
||||
setPendingTagDocId(null);
|
||||
if (DEBUG_DROP) {
|
||||
console.log('[skeuo] handleTagDropOnDoc: finalizing drop for tag', tagId);
|
||||
console.log('[desk] handleTagDropOnDoc: finalizing drop for tag', tagId);
|
||||
}
|
||||
requestCanvasFocus();
|
||||
}
|
||||
@@ -1551,7 +1552,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
event.dataTransfer.effectAllowed = 'copyMove';
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[skeuo] Failed to set drag effect', error);
|
||||
console.warn('[desk] Failed to set drag effect', error);
|
||||
}
|
||||
|
||||
const payload = JSON.stringify({ id: tag.id, label: tag.label, sourceDocId: doc.id });
|
||||
@@ -1560,7 +1561,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
event.dataTransfer?.setData('text/papercrate-tag', payload);
|
||||
event.dataTransfer?.setData('text/plain', tag.label || 'Tag');
|
||||
} catch (error) {
|
||||
console.warn('[skeuo] Failed to populate drag data for tag', error);
|
||||
console.warn('[desk] Failed to populate drag data for tag', error);
|
||||
}
|
||||
|
||||
const pending = pendingDocTagDragRef.current;
|
||||
@@ -1591,7 +1592,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
try {
|
||||
event.dataTransfer.setDragImage(preview.clone, preview.offsetX, preview.offsetY);
|
||||
} catch (error) {
|
||||
console.warn('[skeuo] Failed to set drag image', error);
|
||||
console.warn('[desk] Failed to set drag image', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1678,7 +1679,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
};
|
||||
|
||||
const dropEffect = event?.dataTransfer?.dropEffect || 'none';
|
||||
console.log('[skeuo] dragEnd dropEffect', dropEffect, 'dropHandled', state.dropHandled);
|
||||
console.log('[desk] dragEnd dropEffect', dropEffect, 'dropHandled', state.dropHandled);
|
||||
const shouldRemove =
|
||||
!state.dropHandled &&
|
||||
dropEffect === 'none' &&
|
||||
@@ -1687,7 +1688,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
(state.distance || 0) >= TAG_REMOVE_DISTANCE;
|
||||
|
||||
if (!shouldRemove) {
|
||||
console.log('[skeuo] dragEnd -> no removal. distance:', state.distance);
|
||||
console.log('[desk] dragEnd -> no removal. distance:', state.distance);
|
||||
scheduleShowNode();
|
||||
requestCanvasFocus();
|
||||
updateRemovalCursor(false);
|
||||
@@ -1700,7 +1701,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
||||
void (async () => {
|
||||
try {
|
||||
await onRemoveTagFromDocument(state.sourceDocId, state.tagId);
|
||||
console.log('[skeuo] dragEnd -> removed tag due to fling');
|
||||
console.log('[desk] dragEnd -> removed tag due to fling');
|
||||
} catch (error) {
|
||||
console.error('Failed to remove tag after drag', error);
|
||||
scheduleShowNode();
|
||||
@@ -1854,20 +1855,20 @@ const DesktopWorkspaceView = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="skeuo-shell">
|
||||
<div className="desk-shell">
|
||||
<div
|
||||
className="skeuo-canvas"
|
||||
className="desk-canvas"
|
||||
ref={containerRef}
|
||||
onDragOver={handleCanvasDragOver}
|
||||
onDragLeave={handleCanvasDragLeave}
|
||||
onDrop={handleCanvasDrop}
|
||||
>
|
||||
{!allSizesReady ? (
|
||||
<div className="skeuo-empty">
|
||||
<div className="desk-empty">
|
||||
<p>Loading previews…</p>
|
||||
</div>
|
||||
) : items.length === 0 ? (
|
||||
<div className="skeuo-empty">
|
||||
<div className="desk-empty">
|
||||
<p>No documents to show here yet. Drop files to make this space come alive.</p>
|
||||
</div>
|
||||
) : (
|
||||
@@ -1914,7 +1915,7 @@ const DesktopWorkspaceView = () => {
|
||||
activeTagSet.size === 0 || docTagKeys.some((key) => activeTagSet.has(key));
|
||||
const dropActive = tagDropTargetId === doc.id;
|
||||
const dropPending = pendingTagDocId === doc.id;
|
||||
const itemClasses = ['skeuo-item'];
|
||||
const itemClasses = ['desk-item'];
|
||||
if (dragging) itemClasses.push('is-dragging');
|
||||
if (dropActive) itemClasses.push('is-tag-target');
|
||||
if (dropPending) itemClasses.push('is-tag-pending');
|
||||
@@ -1951,7 +1952,7 @@ const DesktopWorkspaceView = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="skeuo-item__body">
|
||||
<div className="desk-item__body">
|
||||
<DesktopPreviewCard
|
||||
doc={doc}
|
||||
title={title}
|
||||
@@ -1961,7 +1962,7 @@ const DesktopWorkspaceView = () => {
|
||||
shouldLoad={shouldLoad}
|
||||
/>
|
||||
{tags.length > 0 && (
|
||||
<div className="skeuo-item__tags" aria-hidden="true">
|
||||
<div className="desk-item__tags" aria-hidden="true">
|
||||
{tags.map((tag) => {
|
||||
const key = tag.id || tag.label || String(tag);
|
||||
if (
|
||||
@@ -2021,7 +2022,13 @@ export const createDesktopSurface = ({ workspaceProps, renderSidebarToggle }) =>
|
||||
return null;
|
||||
}
|
||||
|
||||
const { currentFolderName, searchResults, onRefresh, onExit } = workspaceProps;
|
||||
const {
|
||||
currentFolderName,
|
||||
searchResults,
|
||||
onRefresh,
|
||||
viewMode,
|
||||
onViewModeChange,
|
||||
} = workspaceProps;
|
||||
const title = Array.isArray(searchResults) ? 'Search results' : currentFolderName;
|
||||
const subtitle = Array.isArray(searchResults)
|
||||
? `${searchResults.length} matching document${searchResults.length === 1 ? '' : 's'}`
|
||||
@@ -2030,22 +2037,11 @@ export const createDesktopSurface = ({ workspaceProps, renderSidebarToggle }) =>
|
||||
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
|
||||
const leading = sidebarToggle ? <>{sidebarToggle}</> : null;
|
||||
|
||||
const actions = (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className="icon-button"
|
||||
onClick={onRefresh}
|
||||
aria-label="Refresh"
|
||||
title="Refresh"
|
||||
>
|
||||
<RefreshIcon />
|
||||
</button>
|
||||
<button type="button" className="secondary" onClick={onExit}>
|
||||
Back to List
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
const actions = createDocumentsTableHeaderActions({
|
||||
viewMode: viewMode || 'desk',
|
||||
onViewModeChange,
|
||||
onRefresh,
|
||||
});
|
||||
|
||||
return {
|
||||
key: 'workspace',
|
||||
|
||||
Reference in New Issue
Block a user