Dashboard Studio 1.9.0: real swiping, tap for next photo, bigger vacuum card
- Swipe card: pointer-driven drag for mouse and touch with resistance at the ends and flick detection, keyboard arrows, cards fill the whole card, page dots float and hide after a few seconds; updates wait until a swipe ends and the release never presses a button underneath - Tapping the clock background or a Photos card skips to the next photo - Media card: removing players works inside scroll/swipe cards, and pre-1.5 single-player cards are migrated into the list - Vacuum card grows with its size: robot with battery ring, cleaning pulse and charging badge, stat tiles, suction power and labelled buttons; compact layout on small cards Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -173,6 +173,12 @@
|
||||
d.nav = { show: false, style: "icons", ...(d.nav || {}) };
|
||||
if (!Array.isArray(d.tabs) || !d.tabs.length) d.tabs = [{ ...newTab(tr("Overview")), widgets: d.widgets || [] }];
|
||||
delete d.widgets;
|
||||
// Media cards from before 1.5 kept one player in cfg.entity; move it into the list so it can be edited.
|
||||
const fix = (w) => {
|
||||
if (w.type === "media" && w.cfg.entity) { w.cfg.entities = [...new Set([w.cfg.entity, ...(w.cfg.entities || [])])]; delete w.cfg.entity; }
|
||||
(w.cfg.children || []).forEach(fix);
|
||||
};
|
||||
d.tabs.forEach((t) => t.widgets.forEach(fix));
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -505,6 +511,7 @@
|
||||
}
|
||||
const ctxFor = (w) => ({
|
||||
ha, w, api, cache: (caches[w.id] ||= {}),
|
||||
rerender: () => renderWidget(w),
|
||||
isVisible: (child) => editMode || isVisible(child),
|
||||
// Containers draw placeholders (.w.child); this fills each with its card.
|
||||
renderChildren: (el) => el.querySelectorAll(".w.child[data-id]").forEach((ph) => {
|
||||
@@ -556,6 +563,7 @@
|
||||
for (const w of affected) {
|
||||
const el = gridEl.querySelector(`.w[data-id="${w.id}"]`);
|
||||
if (interacting && el?.contains(document.activeElement)) continue; // don't yank a slider mid-drag
|
||||
if (caches[w.id]?.busy) { caches[w.id].dirty = true; continue; } // mid-swipe: redraw when the swipe ends
|
||||
const focused = el?.contains(document.activeElement) ? document.activeElement.dataset.act : null;
|
||||
renderWidget(w, el);
|
||||
if (focused) el.querySelector(`[data-act="${focused}"]`)?.focus();
|
||||
@@ -1078,10 +1086,11 @@
|
||||
const track = a.closest(".hs").querySelector(".hs-track");
|
||||
track.scrollBy({ left: (act === "hs-next" ? 1 : -1) * track.clientWidth * 0.8, behavior: reducedMotion() ? "auto" : "smooth" });
|
||||
}
|
||||
else if (act === "sw-go") {
|
||||
const track = a.closest(".sw").querySelector(".sw-track");
|
||||
track.scrollTo({ left: Number(a.dataset.v) * track.clientWidth, behavior: reducedMotion() ? "auto" : "smooth" });
|
||||
else if (act === "photo-next") {
|
||||
const c = caches[a.closest(".w").dataset.id];
|
||||
(c?.bg?.next || c?.next)?.(); // the clock keeps its slideshow under .bg
|
||||
}
|
||||
else if (act === "sw-go") caches[a.closest(".w:not(.child)").dataset.id]?.go?.(Number(a.dataset.v));
|
||||
else if (act === "svc") { const [d, s] = a.dataset.v.split("."); ha.callService(d, s, {}, eid); }
|
||||
else if (act === "button") {
|
||||
const c = findWidget(a.closest(".w").dataset.id).cfg;
|
||||
@@ -1436,9 +1445,9 @@
|
||||
}
|
||||
const del = e.target.closest("[data-ent-del]");
|
||||
if (del) {
|
||||
const w = tab().widgets.find((x) => x.id === selectedId);
|
||||
mutate(() => w.cfg[del.dataset.k].splice(Number(del.dataset.entDel), 1), null, { rerender: false });
|
||||
renderWidget(w); renderInspector(); return;
|
||||
const w = editTarget(); // may be a card inside a scroll or swipe card
|
||||
mutate(() => (w.cfg[del.dataset.k] || []).splice(Number(del.dataset.entDel), 1), null, { rerender: false });
|
||||
renderWidget(selectedWidget()); renderInspector(); return;
|
||||
}
|
||||
const childEdit = e.target.closest("[data-child-edit]"), childBtn = e.target.closest("[data-child-op]");
|
||||
if (childEdit) { childIndex = Number(childEdit.dataset.childEdit); renderInspector(); return; }
|
||||
|
||||
Reference in New Issue
Block a user