Files
MajoorWaldi-ComfyUI-Majoor-…/ui/vue/composables/useGridState.ts
T

143 lines
4.4 KiB
TypeScript

import { computed, shallowReactive } from "vue";
function normalizeIds(value: any) {
return Array.from(value || [])
.map((id) => String(id || "").trim())
.filter(Boolean);
}
export function useGridState() {
const state = shallowReactive({
query: "*",
offset: 0,
cursor: null as any,
total: null as number | null,
loading: false,
done: false,
seenKeys: new Set(),
assets: [] as any[],
assetIdSet: new Set(),
filenameCounts: new Map(),
nonImageSiblingKeys: new Set(),
stemMap: new Map(),
renderedFilenameMap: new Map(),
hiddenPngSiblings: 0,
requestId: 0,
abortController: null,
loadingMessage: "",
statusMessage: "",
statusError: false,
selectedIds: [] as string[],
activeId: "",
selectionAnchorId: "",
cardElements: new Map(),
virtualGrid: null as any,
});
state.virtualGrid = {
setItems(items: any) {
state.assets = Array.isArray(items) ? items.slice() : [];
},
};
const selectedIdSet = computed(() => new Set(normalizeIds(state.selectedIds)));
function setStatusMessage(message = "", { error = false } = {}) {
state.statusMessage = String(message || "");
state.statusError = !!error;
}
function clearStatusMessage() {
state.statusMessage = "";
state.statusError = false;
}
function clearLoadingMessage() {
state.loadingMessage = "";
}
function setLoadingMessage(message = "") {
state.loadingMessage = String(message || "");
}
function resetCollections() {
state.seenKeys = new Set();
state.assetIdSet = new Set();
state.filenameCounts = new Map();
state.nonImageSiblingKeys = new Set();
state.stemMap = new Map();
state.renderedFilenameMap = new Map();
state.hiddenPngSiblings = 0;
}
function resetAssets({ query = "*", total = null, done = false } = {}) {
state.query = String(query || "*") || "*";
state.offset = 0;
state.cursor = null;
state.total = total == null ? null : Number(total) || 0;
state.done = !!done;
state.assets = [];
resetCollections();
}
function setSelection(ids: any, activeId = "", { preserveAnchor = false } = {}) {
const nextIds = Array.from(new Set(normalizeIds(ids)));
const nextActive = String(activeId || nextIds[0] || "").trim();
state.selectedIds = nextIds;
state.activeId = nextActive;
if (!preserveAnchor) {
if (nextActive) {
state.selectionAnchorId = nextActive;
} else if (!nextIds.length) {
state.selectionAnchorId = "";
}
}
return {
selectedIds: nextIds,
activeId: nextActive,
};
}
function reconcileSelection(visibleAssetIds: any, { activeId = "" } = {}) {
const visible = new Set(normalizeIds(visibleAssetIds));
const nextIds = normalizeIds(state.selectedIds).filter((id) => visible.has(id));
const nextActive = String(activeId || state.activeId || nextIds[0] || "").trim();
const resolvedActive = visible.has(nextActive) ? nextActive : nextIds[0] || "";
// Pruning visible assets must not reset the Shift+Click anchor.
return setSelection(nextIds, resolvedActive, { preserveAnchor: true });
}
function getSelectedAssets() {
const selected = selectedIdSet.value;
return (Array.isArray(state.assets) ? state.assets : []).filter((asset) =>
selected.has(String(asset?.id || "")),
);
}
function getActiveAsset() {
const activeId = String(state.activeId || "").trim();
if (activeId) {
const found = (Array.isArray(state.assets) ? state.assets : []).find(
(asset) => String(asset?.id || "") === activeId,
);
if (found) return found;
}
return getSelectedAssets()[0] || null;
}
return {
state,
selectedIdSet,
setLoadingMessage,
clearLoadingMessage,
setStatusMessage,
clearStatusMessage,
resetCollections,
resetAssets,
setSelection,
reconcileSelection,
getSelectedAssets,
getActiveAsset,
};
}