Files
MajoorWaldi-ComfyUI-Majoor-…/ui/features/panel/views/contextPillsView.ts
T
2026-06-09 10:28:25 +02:00

286 lines
11 KiB
TypeScript

import { t } from "../../../app/i18n.js";
const _safeText = (v: any) => {
try {
return String(v ?? "");
} catch {
return "";
}
};
const _labelSort = (key: any) => {
const k = String(key || "");
if (k === "name_asc") return t("sort.nameAZ");
if (k === "name_desc") return t("sort.nameZA");
if (k === "mtime_asc") return t("sort.oldest");
return t("sort.newest");
};
const _labelScope = (scope: any) => {
const s = String(scope || "").toLowerCase();
if (s === "similar") return t("scope.similar", "Similar");
if (s === "custom") return t("scope.customBrowser");
if (s === "workflow") return t("scope.workflow", "Workflow");
if (s === "all") return t("tab.all");
if (s === "input" || s === "inputs") return t("scope.input");
return t("scope.output");
};
function _createPill({ label, value, onClear }: Record<string, any> = {}) {
const pill = document.createElement("div");
pill.className = "mjr-context-pill";
const txt = document.createElement("span");
txt.className = "mjr-context-pill-text";
txt.textContent =
value != null && String(value).length ? `${label}: ${String(value)}` : String(label || "");
pill.appendChild(txt);
if (typeof onClear === "function") {
const x = document.createElement("button");
x.type = "button";
x.className = "mjr-context-pill-x";
x.title = t("tooltip.clearFilter", { label: label || t("label.filters") });
x.setAttribute(
"aria-label",
t("tooltip.clearFilter", { label: label || t("label.filters") }),
);
x.textContent = "x";
x.addEventListener("click", (e) => {
try {
e.preventDefault();
e.stopPropagation();
} catch (e) {
console.debug?.(e);
}
try {
onClear();
} catch (e) {
console.debug?.(e);
}
});
pill.appendChild(x);
}
return pill;
}
export function createContextPillsView(): Record<string, any> {
const root = document.createElement("div");
root.className = "mjr-am-context-pills";
const update = ({ state, rawQuery = "", actions = null }: Record<string, any> = {}) => {
const safeActions = actions && typeof actions === "object" ? actions : {};
const query = _safeText(rawQuery || "").trim();
const isQueryActive = query.length > 0 && query !== "*";
const isFilterActive = !!(
_safeText(state?.kindFilter || "").trim() ||
!!state?.workflowOnly ||
(Number(state?.minRating || 0) || 0) > 0 ||
(Number(state?.minSizeMB || 0) || 0) > 0 ||
(Number(state?.maxSizeMB || 0) || 0) > 0 ||
(Number(state?.minWidth || 0) || 0) > 0 ||
(Number(state?.minHeight || 0) || 0) > 0 ||
(Number(state?.maxWidth || 0) || 0) > 0 ||
(Number(state?.maxHeight || 0) || 0) > 0 ||
_safeText(state?.workflowType || "").trim() ||
_safeText(state?.workflowId || "").trim() ||
_safeText(state?.workflowModelFilter || "").trim() ||
_safeText(state?.workflowRunsOnFilter || "").trim() ||
_safeText(state?.dateRangeFilter || "").trim() ||
_safeText(state?.dateExactFilter || "").trim()
);
const isSortActive = _safeText(state?.sort || "mtime_desc").trim() !== "mtime_desc";
const isCollectionActive = _safeText(state?.collectionId || "").trim().length > 0;
const scopeValue = String(state?.viewScope || state?.scope || "output").toLowerCase();
const isSimilarScope = scopeValue === "similar";
const isBrowserScope = scopeValue === "custom";
const isScopeActive = scopeValue !== "output";
const similarSourceId = _safeText(state?.similarSourceAssetId || "").trim();
const anyContext =
isQueryActive ||
isFilterActive ||
isSortActive ||
isCollectionActive ||
isScopeActive ||
isSimilarScope;
if (!anyContext && !root.childElementCount) {
return;
}
try {
root.replaceChildren();
} catch (e) {
console.debug?.(e);
}
if (!isBrowserScope && isCollectionActive) {
root.appendChild(
_createPill({
label: t("label.collections"),
value: _safeText(state?.collectionName || state?.collectionId || "").trim(),
onClear: () => safeActions?.clearCollection?.(),
}),
);
}
if (isSimilarScope) {
root.appendChild(
_createPill({
label: t("search.findSimilar", "Find Similar"),
value: similarSourceId
? t("search.similarReference", "Reference #{id}", { id: similarSourceId })
: t("scope.similar", "Similar"),
onClear: () => safeActions?.clearSimilarScope?.(),
}),
);
}
if (isScopeActive) {
root.appendChild(
_createPill({
label: t("label.scope"),
value: _labelScope(scopeValue || "output"),
onClear: () =>
isSimilarScope
? safeActions?.clearSimilarScope?.()
: safeActions?.clearScope?.(),
}),
);
}
if (isQueryActive) {
root.appendChild(
_createPill({
label: t("label.query"),
value: query,
onClear: () => safeActions?.clearQuery?.(),
}),
);
}
if (_safeText(state?.kindFilter || "").trim()) {
root.appendChild(
_createPill({
label: t("label.type"),
value: _safeText(state?.kindFilter || "").trim(),
onClear: () => safeActions?.clearKind?.(),
}),
);
}
if (Number(state?.minRating || 0) > 0) {
root.appendChild(
_createPill({
label: t("label.rating"),
value: `>= ${Number(state?.minRating || 0)}`,
onClear: () => safeActions?.clearMinRating?.(),
}),
);
}
if (state?.workflowOnly) {
root.appendChild(
_createPill({
label: t("label.workflow"),
value: t("label.only"),
onClear: () => safeActions?.clearWorkflowOnly?.(),
}),
);
}
if (_safeText(state?.workflowType || "").trim()) {
root.appendChild(
_createPill({
label: t("label.workflowType"),
value: _safeText(state?.workflowType || "").trim(),
onClear: () => safeActions?.clearWorkflowType?.(),
}),
);
}
if (_safeText(state?.workflowId || "").trim()) {
const workflowId = _safeText(state?.workflowId || "").trim();
root.appendChild(
_createPill({
label: t("label.sameWorkflow", "Generated with Same Workflow"),
value: workflowId.length > 18 ? `${workflowId.slice(0, 8)}...${workflowId.slice(-6)}` : workflowId,
onClear: () => safeActions?.clearWorkflowId?.(),
}),
);
}
if (_safeText(state?.workflowModelFilter || "").trim()) {
root.appendChild(
_createPill({
label: t("label.workflowModelFamily", "Model family"),
value: _safeText(state?.workflowModelFilter || "").trim(),
onClear: () => safeActions?.clearWorkflowModel?.(),
}),
);
}
if (_safeText(state?.workflowRunsOnFilter || "").trim()) {
root.appendChild(
_createPill({
label: t("label.workflowRunsOn", "Runs on"),
value: _safeText(state?.workflowRunsOnFilter || "").trim(),
onClear: () => safeActions?.clearWorkflowRunsOn?.(),
}),
);
}
if ((Number(state?.minSizeMB || 0) || 0) > 0 || (Number(state?.maxSizeMB || 0) || 0) > 0) {
const min = Number(state?.minSizeMB || 0) || 0;
const max = Number(state?.maxSizeMB || 0) || 0;
const label =
min > 0 && max > 0 ? `${min}-${max} MB` : min > 0 ? `>= ${min} MB` : `<= ${max} MB`;
root.appendChild(
_createPill({
label: t("sidebar.size"),
value: label,
onClear: () => safeActions?.clearSize?.(),
}),
);
}
if (
(Number(state?.minWidth || 0) || 0) > 0 ||
(Number(state?.minHeight || 0) || 0) > 0 ||
(Number(state?.maxWidth || 0) || 0) > 0 ||
(Number(state?.maxHeight || 0) || 0) > 0
) {
const isLte = String(state?.resolutionCompare || "gte") === "lte";
const w = Number(isLte ? state?.maxWidth : state?.minWidth || 0) || 0;
const h = Number(isLte ? state?.maxHeight : state?.minHeight || 0) || 0;
root.appendChild(
_createPill({
label: t("label.resolution"),
value: `${isLte ? "<=" : ">="} ${w || 0}x${h || 0} px`,
onClear: () => safeActions?.clearResolution?.(),
}),
);
}
if (_safeText(state?.dateRangeFilter || "").trim()) {
root.appendChild(
_createPill({
label: t("sidebar.date"),
value: _safeText(state?.dateRangeFilter || "").trim(),
onClear: () => safeActions?.clearDateRange?.(),
}),
);
}
if (_safeText(state?.dateExactFilter || "").trim()) {
root.appendChild(
_createPill({
label: t("label.day"),
value: _safeText(state?.dateExactFilter || "").trim(),
onClear: () => safeActions?.clearDateExact?.(),
}),
);
}
if (isSortActive) {
root.appendChild(
_createPill({
label: t("label.sort"),
value: _labelSort(state?.sort),
onClear: () => safeActions?.clearSort?.(),
}),
);
}
};
return { wrap: root, update };
}