UI: Improve queue/history card collapsing and styling
This commit is contained in:
@@ -132,7 +132,7 @@
|
||||
.pqueue-thumb-placeholder--failed{color:var(--danger-300,#fb7185)}
|
||||
.pqueue-thumb-placeholder--interrupted{color:var(--warning-300,#facc15)}
|
||||
.pqueue-thumb-wrap-placeholder{cursor:default;border-style:dashed}
|
||||
.pqueue-gallery-overlay{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(15,23,42,.75);backdrop-filter:blur(6px);z-index:100000}
|
||||
.pqueue-gallery-overlay{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(26, 26, 26, 0.65);backdrop-filter:blur(10px);z-index:100000}
|
||||
.pqueue-gallery{position:relative;max-width:92vw;max-height:92vh;display:flex;align-items:center;justify-content:center}
|
||||
.pqueue-gallery__img{max-width:90vw;max-height:90vh;border-radius:12px;box-shadow:0 20px 45px rgba(0,0,0,.6)}
|
||||
.pqueue-gallery__counter{position:absolute;left:50%;bottom:-32px;transform:translateX(-50%);color:#fff;font-size:.85rem}
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
container: null,
|
||||
dom: {},
|
||||
uiMetricsCollapsed: false,
|
||||
uiQueueCollapsed: false,
|
||||
uiHistoryCollapsed: false,
|
||||
};
|
||||
|
||||
PQ.state = state;
|
||||
|
||||
@@ -175,16 +175,76 @@
|
||||
const base = (count != null) ? `${count} entries` : null;
|
||||
const range = UI.currentHistoryRangeLabel();
|
||||
const subtitle = [base, range].filter(Boolean).join(' • ');
|
||||
const card = UI.card("History", {
|
||||
icon: "ti ti-clock-bolt",
|
||||
subtitle,
|
||||
actions: UI.historyFilters(),
|
||||
content: grid,
|
||||
|
||||
// Collapsible card structure
|
||||
const bodyInner = grid;
|
||||
const body = UI.el("div", { class: "pqueue-card__body" }, [bodyInner]);
|
||||
try {
|
||||
body.style.overflow = 'hidden';
|
||||
body.style.transition = 'height 120ms ease, opacity 120ms ease';
|
||||
} catch (err) { /* noop */ }
|
||||
|
||||
const titleWrap = UI.el("div", { class: "pqueue-card__title-wrap" });
|
||||
titleWrap.appendChild(UI.icon("ti ti-clock-bolt", { size: "md" }));
|
||||
titleWrap.appendChild(UI.el("h3", { class: "pqueue-card__title", text: "History" }));
|
||||
if (subtitle) titleWrap.appendChild(UI.el("span", { class: "pqueue-card__subtitle", text: subtitle }));
|
||||
|
||||
const toggle = UI.button({ icon: state.uiHistoryCollapsed ? "ti ti-chevron-down" : "ti ti-chevron-up", variant: "ghost", subtle: true, title: state.uiHistoryCollapsed ? "Expand" : "Collapse" });
|
||||
toggle.addEventListener("click", () => {
|
||||
try {
|
||||
const isCollapsed = !!state.uiHistoryCollapsed;
|
||||
const setIcon = (name) => { try { toggle.innerHTML = ''; toggle.appendChild(UI.icon(name)); } catch (err) { /* noop */ } };
|
||||
if (!isCollapsed) {
|
||||
const start = body.scrollHeight;
|
||||
body.style.height = `${start}px`;
|
||||
body.style.opacity = '1';
|
||||
requestAnimationFrame(() => {
|
||||
body.style.height = '0px';
|
||||
body.style.opacity = '0';
|
||||
});
|
||||
const onEnd = () => {
|
||||
body.removeEventListener('transitionend', onEnd);
|
||||
setIcon('ti ti-chevron-down');
|
||||
state.uiHistoryCollapsed = true;
|
||||
try { wrap.setAttribute('data-collapsed', 'true'); } catch (err) { /* noop */ }
|
||||
};
|
||||
body.addEventListener('transitionend', onEnd);
|
||||
} else {
|
||||
const target = bodyInner.scrollHeight;
|
||||
body.style.height = '0px';
|
||||
body.style.opacity = '0';
|
||||
requestAnimationFrame(() => {
|
||||
const h = bodyInner.scrollHeight || target;
|
||||
body.style.height = `${h}px`;
|
||||
body.style.opacity = '1';
|
||||
});
|
||||
const onEnd = () => {
|
||||
body.removeEventListener('transitionend', onEnd);
|
||||
try { body.style.height = ''; } catch (err) { /* noop */ }
|
||||
setIcon('ti ti-chevron-up');
|
||||
state.uiHistoryCollapsed = false;
|
||||
try { wrap.setAttribute('data-collapsed', 'false'); } catch (err) { /* noop */ }
|
||||
};
|
||||
body.addEventListener('transitionend', onEnd);
|
||||
}
|
||||
} catch (err) { /* noop */ }
|
||||
});
|
||||
state.dom.historyCard = card;
|
||||
state.dom.historySubtitle = card.querySelector('.pqueue-card__subtitle');
|
||||
|
||||
const actions = UI.el("div", { class: "pqueue-card__actions" }, [...UI.historyFilters(), toggle]);
|
||||
const header = UI.el("header", { class: "pqueue-card__header" }, [titleWrap, actions]);
|
||||
const wrap = UI.el("section", { class: ["pqueue-card"] }, [header]);
|
||||
try { wrap.setAttribute('data-collapsed', state.uiHistoryCollapsed ? 'true' : 'false'); } catch (err) { /* noop */ }
|
||||
if (state.uiHistoryCollapsed) {
|
||||
try { body.style.height = '0px'; body.style.opacity = '0'; } catch (err) { /* noop */ }
|
||||
} else {
|
||||
try { body.style.height = ''; body.style.opacity = '1'; } catch (err) { /* noop */ }
|
||||
}
|
||||
|
||||
wrap.appendChild(body);
|
||||
state.dom.historyCard = wrap;
|
||||
state.dom.historySubtitle = wrap.querySelector('.pqueue-card__subtitle');
|
||||
try { UI.ensureThumbObserver(); } catch (err) { /* noop */ }
|
||||
return card;
|
||||
return wrap;
|
||||
};
|
||||
|
||||
UI.ensureHistoryObserver = function ensureHistoryObserver() {
|
||||
|
||||
@@ -190,14 +190,73 @@
|
||||
UI.el("div", { class: "pqueue-table__footer-right" }, [deleteSelected]),
|
||||
]);
|
||||
|
||||
const card = UI.card("Queue", {
|
||||
icon: "ti ti-stack-front",
|
||||
subtitle: state.metrics.queueCount ? `${state.metrics.queueCount} pending` : null,
|
||||
actions: [filter],
|
||||
content: [wrapper, footer],
|
||||
// Build collapsible card (mirrors metrics behavior)
|
||||
const bodyInner = UI.el("div", { class: "pqueue-pending" }, [wrapper, footer]);
|
||||
const body = UI.el("div", { class: "pqueue-card__body" }, [bodyInner]);
|
||||
try {
|
||||
body.style.overflow = 'hidden';
|
||||
body.style.transition = 'height 120ms ease, opacity 120ms ease';
|
||||
} catch (err) { /* noop */ }
|
||||
|
||||
const titleWrap = UI.el("div", { class: "pqueue-card__title-wrap" });
|
||||
titleWrap.appendChild(UI.icon("ti ti-stack-front", { size: "md" }));
|
||||
titleWrap.appendChild(UI.el("h3", { class: "pqueue-card__title", text: "Queue" }));
|
||||
const subtitleText = state.metrics.queueCount ? `${state.metrics.queueCount} pending` : null;
|
||||
if (subtitleText) titleWrap.appendChild(UI.el("span", { class: "pqueue-card__subtitle", text: subtitleText }));
|
||||
|
||||
const toggle = UI.button({ icon: state.uiQueueCollapsed ? "ti ti-chevron-down" : "ti ti-chevron-up", variant: "ghost", subtle: true, title: state.uiQueueCollapsed ? "Expand" : "Collapse" });
|
||||
toggle.addEventListener("click", () => {
|
||||
try {
|
||||
const isCollapsed = !!state.uiQueueCollapsed;
|
||||
const setIcon = (name) => { try { toggle.innerHTML = ''; toggle.appendChild(UI.icon(name)); } catch (err) { /* noop */ } };
|
||||
if (!isCollapsed) {
|
||||
const start = body.scrollHeight;
|
||||
body.style.height = `${start}px`;
|
||||
body.style.opacity = '1';
|
||||
requestAnimationFrame(() => {
|
||||
body.style.height = '0px';
|
||||
body.style.opacity = '0';
|
||||
});
|
||||
const onEnd = () => {
|
||||
body.removeEventListener('transitionend', onEnd);
|
||||
setIcon('ti ti-chevron-down');
|
||||
state.uiQueueCollapsed = true;
|
||||
try { wrap.setAttribute('data-collapsed', 'true'); } catch (err) { /* noop */ }
|
||||
};
|
||||
body.addEventListener('transitionend', onEnd);
|
||||
} else {
|
||||
const target = bodyInner.scrollHeight;
|
||||
body.style.height = '0px';
|
||||
body.style.opacity = '0';
|
||||
requestAnimationFrame(() => {
|
||||
const h = bodyInner.scrollHeight || target;
|
||||
body.style.height = `${h}px`;
|
||||
body.style.opacity = '1';
|
||||
});
|
||||
const onEnd = () => {
|
||||
body.removeEventListener('transitionend', onEnd);
|
||||
try { body.style.height = ''; } catch (err) { /* noop */ }
|
||||
setIcon('ti ti-chevron-up');
|
||||
state.uiQueueCollapsed = false;
|
||||
try { wrap.setAttribute('data-collapsed', 'false'); } catch (err) { /* noop */ }
|
||||
};
|
||||
body.addEventListener('transitionend', onEnd);
|
||||
}
|
||||
} catch (err) { /* noop */ }
|
||||
});
|
||||
state.dom.pendingCard = card;
|
||||
return card;
|
||||
|
||||
const actions = UI.el("div", { class: "pqueue-card__actions" }, [filter, toggle]);
|
||||
const header = UI.el("header", { class: "pqueue-card__header" }, [titleWrap, actions]);
|
||||
const wrap = UI.el("section", { class: ["pqueue-card"] }, [header]);
|
||||
try { wrap.setAttribute('data-collapsed', state.uiQueueCollapsed ? 'true' : 'false'); } catch (err) { /* noop */ }
|
||||
if (state.uiQueueCollapsed) {
|
||||
try { body.style.height = '0px'; body.style.opacity = '0'; } catch (err) { /* noop */ }
|
||||
} else {
|
||||
try { body.style.height = ''; body.style.opacity = '1'; } catch (err) { /* noop */ }
|
||||
}
|
||||
wrap.appendChild(body);
|
||||
state.dom.pendingCard = wrap;
|
||||
return wrap;
|
||||
};
|
||||
|
||||
UI.pendingRow = function pendingRow(item) {
|
||||
|
||||
Reference in New Issue
Block a user