desk view

This commit is contained in:
2025-10-14 10:27:13 +02:00
parent 9aa43d2753
commit 4d5f7b4ccd
2 changed files with 84 additions and 57 deletions
+38 -2
View File
@@ -12,7 +12,7 @@
flex-direction: column;
min-height: 0;
position: relative;
background: #7a7c7c;
background-color: var(--surface-subtle);
}
.skeuo-header {
@@ -21,7 +21,7 @@
justify-content: space-between;
gap: 1rem;
padding: 0.75rem 1rem 0.5rem;
background-color: var(--surface-subtle, rgba(255, 255, 255, 0.08));
background-color: var(--surface-subtle);
}
.skeuo-header__meta {
@@ -277,6 +277,20 @@ body.skeuo-cursor-remove * {
overflow: hidden;
}
.skeuo-item__card--empty {
background:
radial-gradient(circle at 28% 24%, rgba(255, 255, 255, 0.32), transparent 60%),
radial-gradient(circle at 72% 78%, rgba(0, 0, 0, 0.08), transparent 65%),
linear-gradient(135deg, #e6e1d6 0%, #d2cdc2 100%);
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.skeuo-item__card img {
}
@@ -286,3 +300,25 @@ body.skeuo-cursor-remove * {
letter-spacing: normal;
color: var(--muted);
}
.skeuo-item__empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
gap: 0.5rem;
padding: 1rem;
text-align: center;
}
.skeuo-item__title {
font-size: 0.95rem;
font-weight: 500;
color: #3b3b3b;
max-width: 90%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
+46 -55
View File
@@ -22,13 +22,10 @@ const TAG_MIME_TYPES = ['application/x-papercrate-tag', 'text/papercrate-tag'];
const resolveSizeKey = (doc) =>
doc?.id || doc?.document_id || doc?.uuid || doc?.original_name || doc?.title || 'doc';
const CARD_WIDTH_MIN = 200;
const CARD_WIDTH_MAX = 260;
const CARD_HEIGHT_MIN = 240;
const CARD_HEIGHT_MAX = 340;
const CARD_ASPECT_MIN = 0.8; // height / width
const CARD_ASPECT_MAX = 1.35;
const ZOOM_FILL_RATIO = 0.97;
const CARD_MIN = 240;
const CARD_MAX = 340;
const EMPTY_CARD_ASPECT = 1.4;
const ZOOM_FILL_RATIO = 0.99;
const ZOOM_MIN_SCALE = 1.05;
const ZOOM_MAX_SCALE = 5;
const TAG_REMOVE_DISTANCE = 160;
@@ -554,54 +551,40 @@ const SkeuomorphicWorkspace = ({
const intrinsic = resolvePreviewDimensions(doc);
if (intrinsic?.width && intrinsic?.height) {
const ratio = intrinsic.height / intrinsic.width || 1;
width = intrinsic.width;
height = intrinsic.height;
// scale down to fit within max bounds
if (width > CARD_WIDTH_MAX || height > CARD_HEIGHT_MAX) {
const scale = Math.min(CARD_WIDTH_MAX / width, CARD_HEIGHT_MAX / height);
width *= scale;
height *= scale;
}
// scale up to satisfy minimum bounds while respecting ratio
if (width < CARD_WIDTH_MIN || height < CARD_HEIGHT_MIN) {
const scale = Math.max(CARD_WIDTH_MIN / width, CARD_HEIGHT_MIN / height);
width *= scale;
height *= scale;
if (width > CARD_WIDTH_MAX || height > CARD_HEIGHT_MAX) {
const downScale = Math.min(CARD_WIDTH_MAX / width, CARD_HEIGHT_MAX / height);
width *= downScale;
height *= downScale;
}
}
width = clamp(width, CARD_WIDTH_MIN, CARD_WIDTH_MAX);
height = clamp(height, CARD_HEIGHT_MIN, CARD_HEIGHT_MAX);
} else {
const widthSeed = seededRandom(`${key}:width`);
const ratioSeed = seededRandom(`${key}:ratio`);
const ratio = CARD_ASPECT_MIN + ratioSeed * (CARD_ASPECT_MAX - CARD_ASPECT_MIN);
width = CARD_WIDTH_MIN + widthSeed * (CARD_WIDTH_MAX - CARD_WIDTH_MIN);
height = width * ratio;
if (width > CARD_WIDTH_MAX || height > CARD_HEIGHT_MAX) {
const scale = Math.min(CARD_WIDTH_MAX / width, CARD_HEIGHT_MAX / height);
width *= scale;
height *= scale;
}
if (width < CARD_WIDTH_MIN || height < CARD_HEIGHT_MIN) {
const scale = Math.max(CARD_WIDTH_MIN / width, CARD_HEIGHT_MIN / height);
width *= scale;
height *= scale;
}
width = clamp(width, CARD_WIDTH_MIN, CARD_WIDTH_MAX);
height = clamp(height, CARD_HEIGHT_MIN, CARD_HEIGHT_MAX);
const seed = seededRandom(`${key}:size`);
width = CARD_MIN + seed * (Math.min(CARD_MAX, CARD_MAX / EMPTY_CARD_ASPECT) - CARD_MIN);
width = clamp(width, CARD_MIN, Math.min(CARD_MAX, CARD_MAX / EMPTY_CARD_ASPECT));
height = width * EMPTY_CARD_ASPECT;
}
if (!Number.isFinite(width) || width <= 0) {
width = CARD_MIN;
}
if (!Number.isFinite(height) || height <= 0) {
height = CARD_MIN;
}
const scaleDown = Math.min(1, CARD_MAX / width, CARD_MAX / height);
width *= scaleDown;
height *= scaleDown;
const minDim = Math.min(width, height);
if (minDim < CARD_MIN) {
const scaleUp = CARD_MIN / minDim;
width *= scaleUp;
height *= scaleUp;
const adjust = Math.min(1, CARD_MAX / width, CARD_MAX / height);
width *= adjust;
height *= adjust;
}
width = clamp(width, CARD_MIN, CARD_MAX);
height = clamp(height, CARD_MIN, CARD_MAX);
const size = { width, height };
docSizeMapRef.current.set(key, size);
return size;
@@ -636,8 +619,8 @@ const SkeuomorphicWorkspace = ({
(doc, cardWidth, cardHeight) => {
const canvasWidth = canvasSize.width || DEFAULT_CANVAS_WIDTH;
const canvasHeight = canvasSize.height || DEFAULT_CANVAS_HEIGHT;
const safeCardWidth = cardWidth || CARD_WIDTH_MIN;
const safeCardHeight = cardHeight || CARD_HEIGHT_MIN;
const safeCardWidth = cardWidth || CARD_MIN;
const safeCardHeight = cardHeight || CARD_MIN;
const usableWidth = Math.max(canvasWidth - CANVAS_PADDING * 2, safeCardWidth);
const usableHeight = Math.max(canvasHeight - CANVAS_PADDING * 2, safeCardHeight);
const viewportTargetWidth = usableWidth * ZOOM_FILL_RATIO;
@@ -1406,6 +1389,7 @@ const SkeuomorphicWorkspace = ({
const tagsStyle = { '--tag-scale': inverseTagScale };
const previewUrl = resolvePreviewUrl(doc);
const imageUrl = previewUrl;
const hasPreview = Boolean(imageUrl);
const title = doc.title || doc.original_name || 'Document';
const dragging = draggingId === doc.id;
const tags = Array.isArray(doc.tags) ? doc.tags : [];
@@ -1422,6 +1406,8 @@ const SkeuomorphicWorkspace = ({
if (dropActive) itemClasses.push('is-tag-target');
if (dropPending) itemClasses.push('is-tag-pending');
if (!matchesFilter) itemClasses.push('is-filtered-out');
const cardClasses = ['skeuo-item__card'];
if (!hasPreview) cardClasses.push('skeuo-item__card--empty');
const docTagTokens = docTagKeys.join(' ');
return (
<div
@@ -1458,11 +1444,16 @@ const SkeuomorphicWorkspace = ({
}}
>
<div className="skeuo-item__body" style={bodyStyle}>
<div className="skeuo-item__card">
{imageUrl ? (
<div className={cardClasses.join(' ')}>
{hasPreview ? (
<img src={imageUrl} alt={title} />
) : (
<div className="skeuo-item__placeholder">DOC</div>
<div className="skeuo-item__empty">
<div className="skeuo-item__placeholder">DOC</div>
<div className="skeuo-item__title" title={title}>
{title}
</div>
</div>
)}
</div>
{tags.length > 0 && (