web(review): switch cause tabs to PhotoGrid, add date-from-path suggestion

- CauseGroupCard now wraps PhotoGrid so selection, keyboard nav, and
  preview flow through the standard timeline plumbing. Per-tile hover
  Approve/Archive and the group-wide Approve all are gone — the bottom
  BulkActionBar's review-section Keep/Archive handle single + bulk.
- Low Resolution tab opts into a new PhotoTile dimensionBadge prop so
  WxH stays visible on each tile.
- New suggestDateFromPath util parses YYYY-MM-DD from filename or
  folder path. RightSidebar surfaces it as an amber Apply row above
  the Taken-at input whenever the photo lacks a trusted TakenAt.
- BulkActionBar gains a "Accept date & Keep" button (review section
  only) that patches each selected photo's TakenAt from its path
  suggestion when available, then approves.
- Drop the Same folder / Same camera / Same year strips and the
  RelatedStrip component from the metadata sidebar.

Also bundles in-progress Notes route + tile components and small
tweaks to LeftSidebar, DuplicatesView, CrossFolderGroupCard, and
photoprism.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 11:20:02 +02:00
parent 55c870c155
commit d1ddc48f81
15 changed files with 607 additions and 512 deletions

View File

@@ -179,7 +179,7 @@
bind:this={sectionEl}
tabindex="0"
role="application"
aria-label={`Cross-folder duplicate · ${group.files.length} copies`}
aria-label={`Duplicate group · ${group.files.length} copies`}
onkeydown={onKeydown}
class="space-y-2 rounded-md border border-border bg-card/30 p-3 outline-none
focus-visible:ring-2 focus-visible:ring-primary/50"

View File

@@ -65,7 +65,7 @@
toast.error(
crossQuery.error instanceof Error
? crossQuery.error.message
: 'Cross-folder scan failed'
: 'Duplicates scan failed'
);
}
});
@@ -91,7 +91,7 @@
<p>
The library stacks byte-identical (or EXIF-identical) files. If you don't have
any, this tab stays empty. Cross-folder copies dropped at index time live under
the Cross-folder tab.
the Duplicates tab.
</p>
{/snippet}
</EmptyState>
@@ -105,9 +105,9 @@
</div>
{/if}
<!-- Cross-folder tab ----------------------------------------------- -->
<!-- Duplicates tab (cross-folder scan) ----------------------------- -->
{#if activeTab === 'cross-folder'}
<div role="tabpanel" aria-label="Cross-folder duplicates" class="space-y-3 px-6 py-4 pb-6">
<div role="tabpanel" aria-label="Duplicates" class="space-y-3 px-6 py-4 pb-6">
<header class="flex items-baseline justify-between gap-3">
<p class="text-[11px] text-muted-foreground">
Byte-identical files the indexer dropped at index time. Found by scanning the
@@ -139,7 +139,7 @@
: 'unknown error'}
/>
{:else if crossCount === 0}
<EmptyState icon={CheckCircle2} title="No cross-folder duplicates found">
<EmptyState icon={CheckCircle2} title="No duplicates found">
{#snippet descriptionSnippet()}
{#if crossQuery.data}
<p class="text-[10px] text-muted-foreground/70">