Files
ComfyAssets-ComfyUI_PromptM…/web/js/gallery-settings.js
T
Vito dff08bc161 fix(images): open Masonry by default, keep a saved Default layout, crop portraits from the top (#451) (#455)
- A Default layout or Thumbnail size saved in System now reaches the next Images
  visit in an open tab (this tab or another): the last visit records the
  defaults it started from, and a value its toolbar never changed follows newer
  defaults. A toolbar choice stays the current view's own.
- Images opens in Masonry when the browser has no stored Default layout
  (gallery-settings.js DEFAULT_SETTINGS.workspaceLayout); stored choices are kept.
- Grid/List card art, Library card art, the inspector cover and the Tag image
  preview crop with object-position 50% 20%, so portrait images keep their top.
- D157 in TESTING.md; concept comparisons start from the concept's stored Grid.
2026-10-29 02:55:55 +00:00

99 lines
5.0 KiB
JavaScript

/**
* Gallery display settings: defaults, validation of what localStorage holds,
* and the grid template for a chosen column count.
*
* Settings are per browser (localStorage key "gallerySettings"). Anything
* stored can be stale or hand-edited, so every value is checked before use.
* The workspace shares this object ("One display configuration", #249 System
* S3): it adds workspaceLayout and workspaceDensity, and every key either page
* does not know is kept.
*
* Loadable in the browser (window.GallerySettings) and in Node for tests.
*/
(function (root) {
"use strict";
const VIEW_MODES = ["grid", "list"];
// The workspace Images defaults; the legacy gallery's defaultViewMode has no masonry.
const WORKSPACE_LAYOUTS = ["grid", "list", "masonry"];
const WORKSPACE_DENSITIES = ["comfortable", "large", "compact"];
const LIMIT_OPTIONS = [50, 100, 200, 500];
const MIN_COLUMNS = 2;
const MAX_COLUMNS = 12;
const DEFAULT_SETTINGS = Object.freeze({
lazyLoading: true,
imageQuality: "medium",
defaultViewMode: "grid",
defaultLimit: 100,
gridColumns: 8,
showImageInfo: true,
autoLoadMetadata: true,
cacheMetadata: true,
showFilePaths: true,
sidebarCollapsedByDefault: false,
infiniteScroll: false,
debugMode: false,
apiTimeout: 30,
thumbnailsGenerated: false,
checkThumbnailsAtStartup: true,
videoAutoplay: false,
videoMute: true,
videoLoop: true,
// #451: Images opens in Masonry unless this browser chose another layout.
workspaceLayout: "masonry",
workspaceDensity: "comfortable",
});
function toInt(value) {
const n = typeof value === "string" ? Number(value.trim()) : value;
return typeof n === "number" && Number.isInteger(n) ? n : null;
}
function bool(value, fallback) {
return typeof value === "boolean" ? value : fallback;
}
/** Merge stored settings over the defaults, replacing anything invalid. */
function normalizeGallerySettings(raw) {
const stored = raw && typeof raw === "object" ? raw : {};
const merged = { ...DEFAULT_SETTINGS, ...stored };
const limit = toInt(merged.defaultLimit);
const columns = toInt(merged.gridColumns);
const timeout = toInt(merged.apiTimeout);
return {
...merged,
defaultViewMode: VIEW_MODES.includes(merged.defaultViewMode) ? merged.defaultViewMode : DEFAULT_SETTINGS.defaultViewMode,
defaultLimit: limit !== null && LIMIT_OPTIONS.includes(limit) ? limit : DEFAULT_SETTINGS.defaultLimit,
gridColumns: columns === null ? DEFAULT_SETTINGS.gridColumns : Math.min(MAX_COLUMNS, Math.max(MIN_COLUMNS, columns)),
apiTimeout: timeout !== null && timeout > 0 ? timeout : DEFAULT_SETTINGS.apiTimeout,
imageQuality: ["low", "medium", "high"].includes(merged.imageQuality) ? merged.imageQuality : DEFAULT_SETTINGS.imageQuality,
lazyLoading: bool(merged.lazyLoading, DEFAULT_SETTINGS.lazyLoading),
showImageInfo: bool(merged.showImageInfo, DEFAULT_SETTINGS.showImageInfo),
autoLoadMetadata: bool(merged.autoLoadMetadata, DEFAULT_SETTINGS.autoLoadMetadata),
cacheMetadata: bool(merged.cacheMetadata, DEFAULT_SETTINGS.cacheMetadata),
showFilePaths: bool(merged.showFilePaths, DEFAULT_SETTINGS.showFilePaths),
sidebarCollapsedByDefault: bool(merged.sidebarCollapsedByDefault, DEFAULT_SETTINGS.sidebarCollapsedByDefault),
infiniteScroll: bool(merged.infiniteScroll, DEFAULT_SETTINGS.infiniteScroll),
debugMode: bool(merged.debugMode, DEFAULT_SETTINGS.debugMode),
thumbnailsGenerated: bool(merged.thumbnailsGenerated, DEFAULT_SETTINGS.thumbnailsGenerated),
checkThumbnailsAtStartup: bool(merged.checkThumbnailsAtStartup, DEFAULT_SETTINGS.checkThumbnailsAtStartup),
videoAutoplay: bool(merged.videoAutoplay, DEFAULT_SETTINGS.videoAutoplay),
videoMute: bool(merged.videoMute, DEFAULT_SETTINGS.videoMute),
videoLoop: bool(merged.videoLoop, DEFAULT_SETTINGS.videoLoop),
workspaceLayout: WORKSPACE_LAYOUTS.includes(merged.workspaceLayout) ? merged.workspaceLayout : DEFAULT_SETTINGS.workspaceLayout,
workspaceDensity: WORKSPACE_DENSITIES.includes(merged.workspaceDensity) ? merged.workspaceDensity : DEFAULT_SETTINGS.workspaceDensity,
};
}
/** CSS grid-template-columns for the desktop grid. */
function gridColumnsStyle(columns) {
const n = normalizeGallerySettings({ gridColumns: columns }).gridColumns;
return `repeat(${n}, minmax(0, 1fr))`;
}
const api = { DEFAULT_SETTINGS, LIMIT_OPTIONS, VIEW_MODES, WORKSPACE_LAYOUTS, WORKSPACE_DENSITIES, normalizeGallerySettings, gridColumnsStyle };
if (typeof module !== "undefined" && module.exports) module.exports = api;
else root.GallerySettings = api;
})(typeof window !== "undefined" ? window : globalThis);