feat: Lightroom-style workspace UI #2

Merged
iu merged 18 commits from feature/lightroom-workspace-ui into develop 2026-10-10 19:56:23 +00:00
Showing only changes of commit d8da885020 - Show all commits
+29 -8
View File
@@ -42,6 +42,7 @@
let isFullscreen = $state(false);
let zoomed = $state(false);
let scale = $state(1);
let hiResLoaded = $state(false);
let showTop = $state(false);
let showBottom = $state(false);
@@ -60,17 +61,41 @@
let startL = 0;
let startT = 0;
const previewSrc = $derived(
fresh?.preview_url ?? fresh?.original_url ?? current?.preview_url ?? current?.original_url ?? ''
);
const fullSrc = $derived(fresh?.original_url ?? current?.original_url ?? '');
const displaySrc = $derived(zoomed && hiResLoaded && fullSrc ? fullSrc : previewSrc);
$effect(() => {
const id = current?.id;
fresh = null;
zoomed = false;
scale = 1;
hiResLoaded = false;
if (!id) return;
api<{ photo: Photo }>(`/photos/${id}`)
.then((data) => (fresh = data.photo))
.catch(() => {});
});
// In zoom mode, preload the full-resolution original and swap it in once loaded.
$effect(() => {
if (!zoomed || hiResLoaded) return;
const url = fullSrc;
if (!url) return;
const im = new Image();
let alive = true;
im.onload = () => {
if (alive) hiResLoaded = true;
};
im.src = url;
return () => {
alive = false;
im.onload = null;
};
});
$effect(() => {
const el = scroller;
if (!el) return;
@@ -205,10 +230,10 @@
}
function baseWidth(): number {
return imgEl?.naturalWidth || fresh?.width || current?.width || 0;
return fresh?.width || current?.width || imgEl?.naturalWidth || 0;
}
function baseHeight(): number {
return imgEl?.naturalHeight || fresh?.height || current?.height || 0;
return fresh?.height || current?.height || imgEl?.naturalHeight || 0;
}
function prev() {
@@ -219,8 +244,7 @@
}
function toggleActual() {
const atHundred = zoomed && Math.abs(scale - 1) < 0.01;
if (atHundred) {
if (zoomed) {
zoomed = false;
scale = 1;
if (scroller) {
@@ -434,10 +458,7 @@
{#if current}
<img
bind:this={imgEl}
src={fresh?.preview_url ??
fresh?.original_url ??
current.preview_url ??
current.original_url}
src={displaySrc}
alt={current.original_filename}
draggable="false"
style={zoomed ? `width: ${baseWidth() * scale}px; height: auto;` : ''}