custom_components/bahmcloud_store/panel/panel.js aktualisiert

This commit is contained in:
2026-01-15 07:59:28 +00:00
parent b40e509362
commit 30a4daa884

View File

@@ -40,6 +40,45 @@ class BahmcloudStorePanel extends HTMLElement {
}
}
// --- Mobile navigation helpers ---
_toggleMenu() {
// Preferred: HA listens to these events in many builds
try {
window.dispatchEvent(new CustomEvent("hass-toggle-menu", { bubbles: true, composed: true }));
window.dispatchEvent(new CustomEvent("hass-toggle-drawer", { bubbles: true, composed: true }));
} catch (_) {}
// Fallback: try to find the drawer and toggle it (best-effort)
try {
const ha = document.querySelector("home-assistant");
const main = ha?.shadowRoot?.querySelector("home-assistant-main");
const drawerLayout =
main?.shadowRoot?.querySelector("app-drawer-layout") ||
main?.shadowRoot?.querySelector("ha-drawer") ||
main?.shadowRoot?.querySelector("ha-sidebar");
if (drawerLayout?.toggleDrawer) {
drawerLayout.toggleDrawer();
return;
}
} catch (_) {}
// If nothing works, show a hint
this._error = "Unable to open the sidebar on this client. Use the browser back button.";
this._update();
}
_goBack() {
// Works even if HA chrome is hidden
try {
history.back();
} catch (_) {
// fallback
window.location.href = "/";
}
}
async _addCustomRepo() {
if (!this._hass) return;
@@ -93,13 +132,66 @@ class BahmcloudStorePanel extends HTMLElement {
<style>
:host {
display: block;
/* Do NOT force viewport height on mobile.
Let Home Assistant handle layout (header/sidebar). */
height: auto;
min-height: 100%;
--bcs-accent: #1E88E5; /* Bahmcloud Blue */
}
/* Mobile-safe top bar that replaces HA chrome if HA renders this panel fullscreen */
.mobilebar {
position: sticky;
top: 0;
z-index: 50;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 10px 12px;
background: var(--app-header-background-color, var(--card-background-color));
color: var(--app-header-text-color, var(--primary-text-color));
border-bottom: 1px solid var(--divider-color);
}
.mobilebar .left,
.mobilebar .right {
display: flex;
align-items: center;
gap: 8px;
}
.iconbtn {
width: 40px;
height: 40px;
border-radius: 12px;
border: 1px solid var(--divider-color);
background: color-mix(in srgb, var(--card-background-color) 80%, transparent);
color: inherit;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
user-select: none;
font-weight: 900;
font-size: 18px;
line-height: 1;
}
.brandtitle {
display: flex;
flex-direction: column;
line-height: 1.2;
}
.brandtitle .t {
font-size: 16px;
font-weight: 900;
}
.brandtitle .s {
font-size: 12px;
color: var(--secondary-text-color);
margin-top: 2px;
}
.wrap {
padding: 16px;
max-width: 1100px;
@@ -108,26 +200,6 @@ class BahmcloudStorePanel extends HTMLElement {
color: var(--primary-text-color);
}
.topbar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.title {
font-size: 22px;
font-weight: 800;
letter-spacing: 0.2px;
}
.subtitle {
color: var(--secondary-text-color);
font-size: 13px;
margin-top: 2px;
}
.tabs {
display: flex;
gap: 8px;
@@ -151,12 +223,6 @@ class BahmcloudStorePanel extends HTMLElement {
box-shadow: 0 0 0 2px color-mix(in srgb, var(--bcs-accent) 20%, transparent);
}
.actions {
display: flex;
gap: 8px;
align-items: center;
}
button {
padding: 9px 12px;
border-radius: 12px;
@@ -244,18 +310,23 @@ class BahmcloudStorePanel extends HTMLElement {
a:hover { text-decoration: underline; }
</style>
<div class="wrap">
<div class="topbar">
<div>
<div class="title">Bahmcloud Store</div>
<div class="subtitle" id="subtitle">BCS — loading…</div>
</div>
<div class="actions">
<button id="refreshBtn">Refresh</button>
<!-- This bar ensures navigation on mobile even if HA renders fullscreen panels -->
<div class="mobilebar">
<div class="left">
<div class="iconbtn" id="menuBtn" title="Menu">☰</div>
<div class="iconbtn" id="backBtn" title="Back">←</div>
<div class="brandtitle">
<div class="t">Bahmcloud Store</div>
<div class="s" id="subtitle">BCS — loading…</div>
</div>
</div>
<div class="right">
<button id="refreshBtn">Refresh</button>
</div>
</div>
<div class="wrap">
<div class="tabs">
<div class="tab" data-view="store">Store</div>
<div class="tab" data-view="manage">Manage repositories</div>
@@ -268,6 +339,8 @@ class BahmcloudStorePanel extends HTMLElement {
`;
root.getElementById("refreshBtn").addEventListener("click", () => this._load());
root.getElementById("menuBtn").addEventListener("click", () => this._toggleMenu());
root.getElementById("backBtn").addEventListener("click", () => this._goBack());
for (const tab of root.querySelectorAll(".tab")) {
tab.addEventListener("click", () => {
@@ -281,8 +354,8 @@ class BahmcloudStorePanel extends HTMLElement {
const root = this.shadowRoot;
const content = root.getElementById("content");
const err = root.getElementById("error");
const subtitle = root.getElementById("subtitle");
const v = this._data?.version ? String(this._data.version) : null;
subtitle.textContent = v ? `BCS ${v}` : "BCS — loading…";
@@ -358,7 +431,7 @@ class BahmcloudStorePanel extends HTMLElement {
<div><strong>${this._esc(r.name)}</strong></div>
<div class="muted">${this._esc(r.url)}</div>
</div>
<div class="actions">
<div>
<button class="primary" data-remove="${this._esc(r.id)}">Remove</button>
</div>
</div>
@@ -382,7 +455,7 @@ class BahmcloudStorePanel extends HTMLElement {
<input id="addName" placeholder="My Integration" value="${this._esc(this._customAddName)}" />
</div>
<div class="actions">
<div>
<button id="addBtn" class="primary">Add repository</button>
</div>
</div>