feat(preview): inline split-pane preview + sidebar metadata pass
Replace the fullscreen PreviewOverlay with an inline top pane above
each grid surface. SplitGrid + InlinePreview render the focused
photo/video inside the host page; a resizableVertical action drives
the divider and the height persists via the view store. Applied to
the timeline, /tags drill-in, /review cause tabs, /photo/[uid], and
/map. selection.focused is now the single source of truth for both
the inline pane and the right sidebar — preview.svelte store and
PreviewOverlay are removed.
Sidebar: drop the thumb; lead with icon-led filename and folder
rows that match the date/place rhythm. Move dims+size to the top
(below date) and camera/lens/exposure into the collapsible File
section. Read-only spans share the input padding so the text column
aligns across rows. Folder row sits between date and dims+size.
VideoPlayer: stop forcing width/height: 100% so videos honour their
intrinsic aspect ratio inside the pane. Key the player on file hash
in InlinePreview so navigating between videos remounts the element
and autoplay fires again.
Sidebar (LeftSidebar): switch the labels badge to a dedicated
countPhotos('label:*') query so it reports photos with a label
rather than PhotoPrism's category roll-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ interface Persisted {
|
||||
thumbnailSize?: ThumbnailSize;
|
||||
leftSidebarWidth?: number;
|
||||
rightSidebarWidth?: number;
|
||||
previewPaneHeight?: number;
|
||||
/**
|
||||
* Per-section expanded state for the right-sidebar metadata panel
|
||||
* (GPS, Credits, File). Keyed by section id; missing entries use a
|
||||
@@ -39,6 +40,14 @@ export const DEFAULT_LEFT_WIDTH = 224;
|
||||
export const MIN_RIGHT_WIDTH = 220;
|
||||
export const MAX_RIGHT_WIDTH = 480;
|
||||
export const DEFAULT_RIGHT_WIDTH = 280;
|
||||
export const MIN_PREVIEW_HEIGHT = 160;
|
||||
export const DEFAULT_PREVIEW_HEIGHT = 360;
|
||||
/**
|
||||
* Cap the preview pane at 70 % of the viewport so the grid is always
|
||||
* visible underneath. Resolved against `window.innerHeight` at set-time
|
||||
* (the localStorage load happens before any viewport size is known).
|
||||
*/
|
||||
export const MAX_PREVIEW_HEIGHT_FRAC = 0.7;
|
||||
|
||||
function clamp(n: number, lo: number, hi: number): number {
|
||||
return Math.min(hi, Math.max(lo, n));
|
||||
@@ -69,6 +78,7 @@ export const view = $state<{
|
||||
thumbnailSize: ThumbnailSize;
|
||||
leftSidebarWidth: number;
|
||||
rightSidebarWidth: number;
|
||||
previewPaneHeight: number;
|
||||
metadataSections: Record<string, boolean>;
|
||||
}>({
|
||||
rightSidebarCollapsed: initial.rightSidebarCollapsed ?? false,
|
||||
@@ -86,6 +96,12 @@ export const view = $state<{
|
||||
MIN_RIGHT_WIDTH,
|
||||
MAX_RIGHT_WIDTH
|
||||
),
|
||||
previewPaneHeight: Math.max(
|
||||
MIN_PREVIEW_HEIGHT,
|
||||
typeof initial.previewPaneHeight === 'number'
|
||||
? initial.previewPaneHeight
|
||||
: DEFAULT_PREVIEW_HEIGHT
|
||||
),
|
||||
metadataSections:
|
||||
initial.metadataSections && typeof initial.metadataSections === 'object'
|
||||
? { ...initial.metadataSections }
|
||||
@@ -100,6 +116,7 @@ function persist(): void {
|
||||
thumbnailSize: view.thumbnailSize,
|
||||
leftSidebarWidth: view.leftSidebarWidth,
|
||||
rightSidebarWidth: view.rightSidebarWidth,
|
||||
previewPaneHeight: view.previewPaneHeight,
|
||||
metadataSections: view.metadataSections
|
||||
};
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
|
||||
@@ -115,6 +132,14 @@ export function setRightSidebarWidth(px: number): void {
|
||||
persist();
|
||||
}
|
||||
|
||||
export function setPreviewPaneHeight(px: number): void {
|
||||
const maxH = browser
|
||||
? Math.max(MIN_PREVIEW_HEIGHT + 1, Math.floor(window.innerHeight * MAX_PREVIEW_HEIGHT_FRAC))
|
||||
: 1024;
|
||||
view.previewPaneHeight = clamp(Math.round(px), MIN_PREVIEW_HEIGHT, maxH);
|
||||
persist();
|
||||
}
|
||||
|
||||
export function setThumbnailSize(size: ThumbnailSize): void {
|
||||
view.thumbnailSize = size;
|
||||
persist();
|
||||
|
||||
Reference in New Issue
Block a user