Gui Fixes

This commit is contained in:
2026-05-19 08:50:19 +02:00
parent 6c2b42784a
commit ed0cff2010
3 changed files with 72 additions and 22 deletions
+22
View File
@@ -12,6 +12,28 @@ dist/
`sternwarte-card.js` lädt `astronomy.browser.min.js` automatisch nach, um Dämmerungszeiten und Mondposition präziser zu berechnen.
## Dämmerungsbalken
Der Dämmerungsbalken in `dist/sternwarte-card.js` arbeitet bewusst nicht nur mit einzelnen Dawn-/Dusk-Zeitpunkten, sondern mit einem lokalen `12:00 → 12:00`-Fenster.
Wichtige Punkte:
- Die Phasen `Tag`, `bürgerliche Dämmerung`, `nautische Dämmerung`, `astronomische Dämmerung` und `Nacht` werden direkt aus der Sonnenhöhe bestimmt.
- Dafür wird das komplette lokale 24-Stunden-Fenster in kleinen Schritten durchgerechnet.
- Diese Logik ist robuster für Sommerfälle, in denen es keine astronomische Nacht mehr gibt.
Marker im Balken:
- `Öffnen geplant` wird grün dargestellt.
- `Schließen geplant` wird rot dargestellt.
- Der Marker `Jetzt` ist bewusst hell/weiß, damit er nicht mit `Schließen` verwechselt wird.
Wichtig für spätere Änderungen:
- Die Balkenachse ist eine Uhrzeitachse `12 → 12`, keine reine Datumsachse.
- Die Marker für `Öffnen geplant` und `Schließen geplant` müssen daher anhand der lokalen Uhrzeit auf diese Achse gelegt werden, nicht anhand eines festen Datumsfensters.
- Wenn die Marker verschwinden, zuerst prüfen, ob versehentlich wieder mit einem echten Zeitfenster statt mit der `12 → 12`-Achse gerechnet wird.
## Für HACS
Dieser Ordner ist als Root eines späteren HACS-Dashboard-Repositorys vorbereitet.
+42 -22
View File
@@ -330,12 +330,29 @@ class SternwarteCard extends HTMLElement {
}
}
_parseEntityDate(rawValue) {
if (!rawValue || rawValue === "unknown" || rawValue === "unavailable") return null;
if (rawValue instanceof Date) {
return Number.isNaN(rawValue.getTime()) ? null : rawValue;
}
if (typeof rawValue !== "string") {
const value = new Date(rawValue);
return Number.isNaN(value.getTime()) ? null : value;
}
const normalized = rawValue.trim().replace(" ", "T");
const hasTimezone = /(?:Z|[+-]\d{2}:\d{2})$/.test(normalized);
const localCandidate = hasTimezone ? normalized : normalized;
const value = new Date(localCandidate);
return Number.isNaN(value.getTime()) ? null : value;
}
_isoForInput(state) {
if (!state || !state.state || state.state === "unknown" || state.state === "unavailable") {
return "";
}
const value = new Date(state.state);
if (Number.isNaN(value.getTime())) return "";
const value = this._parseEntityDate(state.state);
if (!value) return "";
const pad = (n) => String(n).padStart(2, "0");
return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}T${pad(value.getHours())}:${pad(value.getMinutes())}`;
}
@@ -344,8 +361,8 @@ class SternwarteCard extends HTMLElement {
if (!state || !state.state || state.state === "unknown" || state.state === "unavailable") {
return "\u2014";
}
const value = new Date(state.state);
if (Number.isNaN(value.getTime())) return "\u2014";
const value = this._parseEntityDate(state.state);
if (!value) return "\u2014";
const pad = (n) => String(n).padStart(2, "0");
return `${pad(value.getDate())}.${pad(value.getMonth() + 1)}. ${pad(value.getHours())}:${pad(value.getMinutes())}`;
}
@@ -783,13 +800,12 @@ class SternwarteCard extends HTMLElement {
segments.sort((a, b) => a.start - b.start);
const toWindowHour = (state) => {
const toChartHour = (state) => {
if (!state?.state || state.state === "unknown" || state.state === "unavailable") return null;
const value = new Date(state.state);
if (Number.isNaN(value.getTime())) return null;
const hour = (value.getTime() - windowStart.getTime()) / 3600000;
if (hour < 0 || hour > 24) return null;
return hour;
const value = this._parseEntityDate(state.state);
if (!value) return null;
const localHour = value.getHours() + value.getMinutes() / 60 + value.getSeconds() / 3600;
return (localHour - 12 + 24) % 24;
};
return {
@@ -800,8 +816,8 @@ class SternwarteCard extends HTMLElement {
color: segment.color,
})),
markerLeft: `${(nowLocal / 24) * 100}%`,
openMarkerLeft: toWindowHour(this._state(this._scheduleOpenEntityId())),
closeMarkerLeft: toWindowHour(this._state(this._scheduleCloseEntityId())),
openMarkerLeft: toChartHour(this._state(this._scheduleOpenEntityId())),
closeMarkerLeft: toChartHour(this._state(this._scheduleCloseEntityId())),
};
}
@@ -1084,24 +1100,28 @@ class SternwarteCard extends HTMLElement {
position: absolute;
top: -4px;
bottom: -4px;
width: 4px;
width: 3px;
margin-left: -1px;
background: #d32f2f;
box-shadow: 0 0 8px rgba(211, 47, 47, 0.55);
background: rgba(255, 255, 255, 0.95);
box-shadow: 0 0 8px rgba(255, 255, 255, 0.45);
z-index: 5;
}
.astro-marker {
position: absolute;
top: -3px;
bottom: -3px;
width: 4px;
margin-left: -1px;
box-shadow: 0 0 6px rgba(255, 255, 255, 0.25);
top: -4px;
bottom: -4px;
width: 6px;
margin-left: -2px;
border-radius: 999px;
z-index: 4;
}
.astro-marker.open {
background: #4caf50;
background: #20c45a;
box-shadow: 0 0 10px rgba(32, 196, 90, 0.7);
}
.astro-marker.close {
background: #ffb300;
background: #e53935;
box-shadow: 0 0 10px rgba(229, 57, 53, 0.72);
}
.astro-moon-track {
position: absolute;