feat(sidebar): persist metadata section collapse across photo switches
GPS, Credits & notes, and File sections in the right sidebar now read
and write their expanded state through the view store and persist it
to localStorage. Closed by default; the user's first toggle pins their
choice across subsequent photos and reloads.
Switched from the previous data-driven defaults ("open if this photo
has GPS / IPTC fields") to static defaults: a data-driven default would
change between photos, fire a programmatic `toggle` event on the
<details> element, and silently overwrite the user's persisted choice.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,13 @@ interface Persisted {
|
||||
thumbnailSize?: ThumbnailSize;
|
||||
leftSidebarWidth?: number;
|
||||
rightSidebarWidth?: number;
|
||||
/**
|
||||
* Per-section expanded state for the right-sidebar metadata panel
|
||||
* (GPS, Credits, File). Keyed by section id; missing entries use a
|
||||
* static default supplied by the component, so the user's chosen
|
||||
* collapse state stays put as they navigate between photos.
|
||||
*/
|
||||
metadataSections?: Record<string, boolean>;
|
||||
}
|
||||
|
||||
export const MIN_LEFT_WIDTH = 180;
|
||||
@@ -62,6 +69,7 @@ export const view = $state<{
|
||||
thumbnailSize: ThumbnailSize;
|
||||
leftSidebarWidth: number;
|
||||
rightSidebarWidth: number;
|
||||
metadataSections: Record<string, boolean>;
|
||||
}>({
|
||||
rightSidebarCollapsed: initial.rightSidebarCollapsed ?? false,
|
||||
leftSidebarCollapsed: initial.leftSidebarCollapsed ?? false,
|
||||
@@ -77,7 +85,11 @@ export const view = $state<{
|
||||
typeof initial.rightSidebarWidth === 'number' ? initial.rightSidebarWidth : DEFAULT_RIGHT_WIDTH,
|
||||
MIN_RIGHT_WIDTH,
|
||||
MAX_RIGHT_WIDTH
|
||||
)
|
||||
),
|
||||
metadataSections:
|
||||
initial.metadataSections && typeof initial.metadataSections === 'object'
|
||||
? { ...initial.metadataSections }
|
||||
: {}
|
||||
});
|
||||
|
||||
function persist(): void {
|
||||
@@ -87,7 +99,8 @@ function persist(): void {
|
||||
leftSidebarCollapsed: view.leftSidebarCollapsed,
|
||||
thumbnailSize: view.thumbnailSize,
|
||||
leftSidebarWidth: view.leftSidebarWidth,
|
||||
rightSidebarWidth: view.rightSidebarWidth
|
||||
rightSidebarWidth: view.rightSidebarWidth,
|
||||
metadataSections: view.metadataSections
|
||||
};
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
|
||||
}
|
||||
@@ -121,3 +134,24 @@ export function toggleLeftSidebar(): void {
|
||||
view.leftSidebarCollapsed = !view.leftSidebarCollapsed;
|
||||
persist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the persisted expanded state for a right-sidebar metadata
|
||||
* section, falling back to `defaultOpen` when the user has never
|
||||
* toggled it. `defaultOpen` should be a *static* value — using a
|
||||
* per-photo data-driven default would change between photos, fire a
|
||||
* programmatic `toggle` event, and silently overwrite the user's
|
||||
* preference.
|
||||
*/
|
||||
export function getMetadataSectionOpen(id: string, defaultOpen: boolean): boolean {
|
||||
const v = view.metadataSections[id];
|
||||
return typeof v === 'boolean' ? v : defaultOpen;
|
||||
}
|
||||
|
||||
/** Record the user's explicit collapse/expand choice for a metadata
|
||||
* section. Persists immediately so a reload keeps the layout the
|
||||
* user picked. */
|
||||
export function setMetadataSection(id: string, open: boolean): void {
|
||||
view.metadataSections[id] = open;
|
||||
persist();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user