custom_components/bahmcloud_store/panel/panel.js aktualisiert
This commit is contained in:
@@ -40,26 +40,19 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Mobile navigation helpers ---
|
||||
|
||||
_isDesktop() {
|
||||
// If the viewport is wide enough, HA typically shows the sidebar permanently.
|
||||
// We treat this as "desktop" and hide/disable the menu toggle.
|
||||
return window.matchMedia && window.matchMedia("(min-width: 1024px)").matches;
|
||||
}
|
||||
|
||||
_toggleMenu() {
|
||||
// On desktop the sidebar is usually always visible; do nothing.
|
||||
if (this._isDesktop()) return;
|
||||
|
||||
// Primary: dispatch the standard HA event from THIS element so it bubbles.
|
||||
try {
|
||||
const ev = new Event("hass-toggle-menu", { bubbles: true, composed: true });
|
||||
this.dispatchEvent(ev);
|
||||
return; // often enough on mobile
|
||||
return;
|
||||
} catch (_) {}
|
||||
|
||||
// Secondary: try again via host/root
|
||||
try {
|
||||
const host = this.shadowRoot?.host;
|
||||
if (host) {
|
||||
@@ -69,44 +62,6 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
// Fallback DOM attempts
|
||||
try {
|
||||
const ha = document.querySelector("home-assistant");
|
||||
const haRoot = ha?.shadowRoot;
|
||||
|
||||
const main =
|
||||
haRoot?.querySelector("home-assistant-main") ||
|
||||
haRoot?.querySelector("home-assistant-main#main");
|
||||
|
||||
const mainRoot = main?.shadowRoot;
|
||||
|
||||
const drawer =
|
||||
mainRoot?.querySelector("mwc-drawer") ||
|
||||
mainRoot?.querySelector("ha-drawer") ||
|
||||
mainRoot?.querySelector("app-drawer-layout");
|
||||
|
||||
if (drawer) {
|
||||
if ("open" in drawer) {
|
||||
drawer.open = true;
|
||||
return;
|
||||
}
|
||||
if (typeof drawer.toggleDrawer === "function") {
|
||||
drawer.toggleDrawer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const layout =
|
||||
mainRoot?.querySelector("ha-panel-lovelace") ||
|
||||
mainRoot?.querySelector("ha-panel");
|
||||
|
||||
if (layout && typeof layout.toggleMenu === "function") {
|
||||
layout.toggleMenu();
|
||||
return;
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
// Only show an error on mobile if everything failed.
|
||||
this._error = "Unable to open the sidebar on this client. Use the back button.";
|
||||
this._update();
|
||||
}
|
||||
@@ -170,114 +125,57 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
height: auto;
|
||||
min-height: 100%;
|
||||
--bcs-accent: #1E88E5;
|
||||
}
|
||||
:host { display:block; min-height:100%; --bcs-accent:#1E88E5; }
|
||||
|
||||
.mobilebar{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
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;
|
||||
}
|
||||
.mobilebar .left, .mobilebar .right { display:flex; align-items:center; gap:8px; }
|
||||
|
||||
.iconbtn{
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 12px;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@media (min-width: 1024px) { .iconbtn.menu { display:none; } }
|
||||
|
||||
/* Hide the menu button on desktop where the sidebar is already visible */
|
||||
@media (min-width: 1024px) {
|
||||
.iconbtn.menu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
.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;
|
||||
margin: 0 auto;
|
||||
padding:16px; max-width:1100px; margin:0 auto;
|
||||
font-family: system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
|
||||
color:var(--primary-text-color);
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.tabs{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:6px; }
|
||||
.tab{
|
||||
border:1px solid var(--divider-color);
|
||||
background:var(--card-background-color);
|
||||
color:var(--primary-text-color);
|
||||
padding: 8px 12px;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
padding:8px 12px; border-radius:999px;
|
||||
cursor:pointer; font-weight:600; font-size:13px;
|
||||
}
|
||||
|
||||
.tab.active{
|
||||
border-color:var(--bcs-accent);
|
||||
box-shadow:0 0 0 2px color-mix(in srgb, var(--bcs-accent) 20%, transparent);
|
||||
}
|
||||
|
||||
button{
|
||||
padding: 9px 12px;
|
||||
border-radius: 12px;
|
||||
padding:9px 12px; border-radius:12px;
|
||||
border:1px solid var(--divider-color);
|
||||
background:var(--card-background-color);
|
||||
color:var(--primary-text-color);
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
cursor:pointer; font-weight:700;
|
||||
}
|
||||
|
||||
button.primary{
|
||||
border-color:var(--bcs-accent);
|
||||
background: color-mix(in srgb, var(--bcs-accent) 16%, var(--card-background-color));
|
||||
@@ -286,71 +184,37 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
.card{
|
||||
border:1px solid var(--divider-color);
|
||||
background:var(--card-background-color);
|
||||
border-radius: 16px;
|
||||
padding: 12px;
|
||||
margin: 10px 0;
|
||||
border-radius:16px; padding:12px; margin:10px 0;
|
||||
}
|
||||
.row{ display:flex; justify-content:space-between; gap:10px; align-items:flex-start; }
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 13px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.muted{ color:var(--secondary-text-color); font-size:13px; margin-top:4px; }
|
||||
.small{ font-size:12px; }
|
||||
|
||||
.badge{
|
||||
border:1px solid var(--divider-color);
|
||||
border-radius: 999px;
|
||||
padding: 2px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
height: fit-content;
|
||||
border-radius:999px; padding:2px 10px;
|
||||
font-size:12px; font-weight:700; height:fit-content;
|
||||
}
|
||||
.badge.custom{ border-color:var(--bcs-accent); color:var(--bcs-accent); }
|
||||
|
||||
.badge.custom {
|
||||
border-color: var(--bcs-accent);
|
||||
color: var(--bcs-accent);
|
||||
}
|
||||
.error{ color:#b00020; white-space:pre-wrap; margin-top:10px; }
|
||||
|
||||
.error {
|
||||
color: #b00020;
|
||||
white-space: pre-wrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
.grid{ display:grid; grid-template-columns:1fr; gap:10px; }
|
||||
.field{ display:grid; gap:6px; }
|
||||
|
||||
input{
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
padding:10px 12px; border-radius:12px;
|
||||
border:1px solid var(--divider-color);
|
||||
background:var(--card-background-color);
|
||||
color:var(--primary-text-color);
|
||||
outline:none;
|
||||
}
|
||||
|
||||
input:focus{
|
||||
border-color:var(--bcs-accent);
|
||||
box-shadow:0 0 0 2px color-mix(in srgb, var(--bcs-accent) 20%, transparent);
|
||||
}
|
||||
|
||||
.small { font-size: 12px; }
|
||||
|
||||
a{ color:var(--bcs-accent); text-decoration:none; }
|
||||
a:hover{ text-decoration:underline; }
|
||||
</style>
|
||||
@@ -364,7 +228,6 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
<div class="s" id="subtitle">BCS — loading…</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<button id="refreshBtn">Refresh</button>
|
||||
</div>
|
||||
@@ -441,9 +304,14 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
? `<span class="badge custom">Custom</span>`
|
||||
: `<span class="badge">Index</span>`;
|
||||
|
||||
const owner = r.owner ? `Owner: ${this._esc(r.owner)}` : "Owner: -";
|
||||
const provider = r.provider ? `Provider: ${this._esc(r.provider)}` : "Provider: -";
|
||||
const desc = r.description || "No description available.";
|
||||
const desc = r.meta_description || r.provider_description || "No description available.";
|
||||
|
||||
const creator = r.owner ? `Creator: ${this._esc(r.owner)}` : "Creator: -";
|
||||
const author = r.meta_author ? `Author: ${this._esc(r.meta_author)}` : null;
|
||||
const maint = r.meta_maintainer ? `Maintainer: ${this._esc(r.meta_maintainer)}` : null;
|
||||
const metaSrc = r.meta_source ? `Meta: ${this._esc(r.meta_source)}` : null;
|
||||
|
||||
const lineBits = [creator, author, maint, metaSrc].filter(Boolean);
|
||||
|
||||
return `
|
||||
<div class="card">
|
||||
@@ -451,7 +319,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
<div>
|
||||
<div><strong>${this._esc(r.name)}</strong></div>
|
||||
<div class="muted">${this._esc(desc)}</div>
|
||||
<div class="muted small">${owner} · ${provider}</div>
|
||||
<div class="muted small">${lineBits.map(x => this._esc(x)).join(" · ")}</div>
|
||||
<div class="muted small"><a href="${this._esc(r.url)}" target="_blank" rel="noreferrer">Open repository</a></div>
|
||||
</div>
|
||||
${badge}
|
||||
|
||||
Reference in New Issue
Block a user