From adb117672cbc5914bd94529d3cee2dda2551ef92 Mon Sep 17 00:00:00 2001 From: bahmcloud Date: Thu, 15 Jan 2026 09:56:53 +0000 Subject: [PATCH] custom_components/bahmcloud_store/panel/panel.js aktualisiert --- .../bahmcloud_store/panel/panel.js | 98 +++++++++++++------ 1 file changed, 67 insertions(+), 31 deletions(-) diff --git a/custom_components/bahmcloud_store/panel/panel.js b/custom_components/bahmcloud_store/panel/panel.js index 98b500e..3b39102 100644 --- a/custom_components/bahmcloud_store/panel/panel.js +++ b/custom_components/bahmcloud_store/panel/panel.js @@ -21,6 +21,9 @@ class BahmcloudStorePanel extends HTMLElement { this._readmeLoading = false; this._readmeText = null; this._readmeError = null; + + // Prevent multiple concurrent markdown mounts + this._mdMountToken = 0; } set hass(hass) { @@ -335,6 +338,11 @@ class BahmcloudStorePanel extends HTMLElement { details{ margin-top: 10px; } summary{ cursor:pointer; color: var(--bcs-accent); font-weight: 800; } + + /* Make HA markdown look nice inside our card */ + ha-markdown{ + display:block; + }
@@ -388,9 +396,7 @@ class BahmcloudStorePanel extends HTMLElement { tag === "select" || t.isContentEditable; - if (isEditable) { - e.stopPropagation(); - } + if (isEditable) e.stopPropagation(); }; root.addEventListener("keydown", stopIfFormField, true); @@ -406,13 +412,12 @@ class BahmcloudStorePanel extends HTMLElement { const supported = new Set(["searchInput", "categorySelect", "addUrl", "addName"]); if (!supported.has(ae.id)) return null; - const state = { + return { id: ae.id, value: ae.value, selectionStart: typeof ae.selectionStart === "number" ? ae.selectionStart : null, selectionEnd: typeof ae.selectionEnd === "number" ? ae.selectionEnd : null, }; - return state; } _restoreFocusState(state) { @@ -431,7 +436,6 @@ class BahmcloudStorePanel extends HTMLElement { _update() { const root = this.shadowRoot; - const focusState = this._captureFocusState(); const content = root.getElementById("content"); @@ -515,13 +519,11 @@ class BahmcloudStorePanel extends HTMLElement { : `Index`; const desc = r.description || "No description available."; - const creator = r.owner ? `Creator: ${r.owner}` : "Creator: -"; + const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown"; const cat = r.category ? `Category: ${r.category}` : null; const metaSrc = r.meta_source ? `Meta: ${r.meta_source}` : null; - const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown"; - const lineBits = [creator, latest, cat, metaSrc].filter(Boolean); return ` @@ -552,7 +554,6 @@ class BahmcloudStorePanel extends HTMLElement { _wireStore() { const root = this.shadowRoot; - const search = root.getElementById("searchInput"); const cat = root.getElementById("categorySelect"); @@ -587,7 +588,6 @@ class BahmcloudStorePanel extends HTMLElement { : `Index`; const desc = r.description || "No description available."; - const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown"; const infoBits = [ @@ -659,6 +659,60 @@ class BahmcloudStorePanel extends HTMLElement { `; } + async _mountPrettyMarkdown(container, markdown) { + // token prevents race conditions when switching repos fast + const token = ++this._mdMountToken; + + container.innerHTML = ""; + + // If user switched views/repo while we were waiting + const stillValid = () => token === this._mdMountToken && this._view === "detail" && !!this._readmeText; + + // Wait until HA registers the component + try { + await customElements.whenDefined("ha-markdown"); + } catch (_) { + // ignored + } + if (!stillValid()) return; + + // Create markdown element + let el; + try { + el = document.createElement("ha-markdown"); + } catch (_) { + el = null; + } + + // If creation failed, fallback to plain pre + if (!el) { + const pre = document.createElement("pre"); + pre.className = "readme"; + pre.textContent = markdown; + container.appendChild(pre); + return; + } + + // Attach first (some HA internals react after connection) + container.appendChild(el); + + // Set hass + content + try { el.hass = this._hass; } catch (_) {} + try { el.content = markdown; } catch (_) { + // some builds used `markdown` property in the past + try { el.markdown = markdown; } catch (_) {} + } + + // Nudge render (some builds need a microtask/frame after setting properties) + await new Promise((resolve) => requestAnimationFrame(resolve)); + if (!stillValid()) return; + + try { el.hass = this._hass; } catch (_) {} + try { el.content = markdown; } catch (_) { + try { el.markdown = markdown; } catch (_) {} + } + } + _wireDetail() { const root = this.shadowRoot; const container = root.getElementById("readmeContainer"); @@ -668,26 +722,8 @@ class BahmcloudStorePanel extends HTMLElement { if (!this._readmeText) return; - // Only attempt ha-markdown if the custom element exists - const hasHaMarkdown = typeof customElements !== "undefined" && !!customElements.get("ha-markdown"); - - if (hasHaMarkdown) { - try { - const el = document.createElement("ha-markdown"); - try { el.hass = this._hass; } catch (_) {} - el.content = this._readmeText; - container.appendChild(el); - return; - } catch (_) { - // fall through to raw fallback (details already exists) - } - } - - // If ha-markdown is missing, show a minimal rendered area: - const pre = document.createElement("pre"); - pre.className = "readme"; - pre.textContent = this._readmeText; - container.appendChild(pre); + // Always try pretty markdown; raw fallback is already available in
+ this._mountPrettyMarkdown(container, this._readmeText); } _renderFabs() {