feat: photo multiselect, move/copy, trash and compact chrome
- backend: soft delete + trash (photos.deleted_at, migration 000005), GET /trash, restore, permanent delete with storage-key refcount (S3 objects removed only when no other album references them); batch endpoints photo-batch/{delete,move,copy} - metadata only, copies clone rows sharing storage keys
- frontend: Ctrl/Shift multiselect; right-panel 'Действия' as icon text rows (Открыть (просмотр), Переместить, Копировать, Удалить); drag selected photos onto rail album -> TransferDialog; /trash route; trash entry as last item in the left rail; empty right panel hidden on overview
- frontend: compact top bars (app header and viewer), compact theme switcher
- openspec: sync lightroom-workspace-ui artifacts (photos/ui-workspace specs, design #20-24, tasks 9.11-9.17)
This commit is contained in:
@@ -99,8 +99,8 @@
|
||||
|
||||
const topClass = $derived(
|
||||
isFullscreen
|
||||
? `border-border bg-chrome absolute inset-x-0 top-0 z-30 flex items-center justify-between gap-2 border-b px-3 py-2 transition-transform duration-200 ${showTop ? 'translate-y-0' : '-translate-y-full'}`
|
||||
: 'border-border bg-chrome flex shrink-0 items-center justify-between gap-2 border-b px-3 py-2'
|
||||
? `border-border bg-chrome absolute inset-x-0 top-0 z-30 flex items-center justify-between gap-1 border-b px-2 py-0.5 transition-transform duration-200 ${showTop ? 'translate-y-0' : '-translate-y-full'}`
|
||||
: 'border-border bg-chrome flex shrink-0 items-center justify-between gap-1 border-b px-2 py-0.5'
|
||||
);
|
||||
const bottomClass = $derived(
|
||||
isFullscreen
|
||||
@@ -289,22 +289,21 @@
|
||||
}
|
||||
|
||||
const btn =
|
||||
'border-border text-text hover:bg-bg-muted inline-flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm';
|
||||
const dangerBtn =
|
||||
'border-border text-danger hover:bg-bg-muted inline-flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm';
|
||||
'text-text-muted hover:bg-bg-muted hover:text-text inline-flex items-center justify-center rounded-md p-1';
|
||||
const dangerBtn = 'text-danger hover:bg-bg-muted inline-flex items-center justify-center rounded-md p-1';
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={onKey} onmousemove={onWinMouseMove} />
|
||||
|
||||
<div bind:this={viewerEl} class="bg-canvas relative flex h-full flex-col overflow-hidden">
|
||||
<div bind:this={topEl} class={topClass}>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<button type="button" class={btn} aria-label="Назад" title="Назад" onclick={onClose}>
|
||||
<Icon name="arrow_back" />
|
||||
<Icon name="arrow_back" class="size-4" />
|
||||
</button>
|
||||
<span class="text-text-muted text-sm">{index + 1} / {photos.length}</span>
|
||||
<span class="text-text-muted text-xs">{index + 1} / {photos.length}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<button
|
||||
type="button"
|
||||
class={btn}
|
||||
@@ -315,7 +314,7 @@
|
||||
aria-pressed={isFullscreen}
|
||||
onclick={toggleViewerFullscreen}
|
||||
>
|
||||
<Icon name={isFullscreen ? 'fullscreen_exit' : 'fullscreen'} />
|
||||
<Icon name={isFullscreen ? 'fullscreen_exit' : 'fullscreen'} class="size-4" />
|
||||
</button>
|
||||
{#if fresh?.download_url}
|
||||
<a
|
||||
|
||||
Reference in New Issue
Block a user