Tankstelle zweizeilig und antippbar, Belegkarte ohne toten Knopf (2026.9.4.5)
Sieben Meldungen des Eigentuemers, beide Codebasen. Karte im Einzelbeleg: "Position laedt nicht" und "der Button funktioniert nicht" waren dieselbe Stelle - ohne aufloesbaren Ort malte das Panel einen beliebigen Ausschnitt und liess den Zentrieren-Knopf fuer immer disabled. Beide zeigen jetzt die Auskunft statt einer Karte und unterscheiden dabei "steht nicht im Beleg" von "findet niemand". Dazu ein echter Paritaetsmangel: die App schlug nur station_address nach, das Panel faellt seit jeher auf den Namen zurueck - von 16 Testbelegen tragen vier eine Anschrift. Der Suchbegriff darf Name und Anschrift NICHT zusammensetzen: gemessen findet Nominatim "Pascalstr. 8, 85057 Ingolstadt", mit dem Betreibernamen davor nichts. Jetzt zwei Kandidaten nacheinander (Anschrift, dann Name); fuer den Kartendienst dagegen beides zusammen, weil Apple und Google Betriebsnamen kennen. Tankstelle steht ueber die volle Kachelbreite, zweizeilig (Tankstelle und Strasse / Ort) und fuehrt beim Tippen in den Standard-Kartendienst - Apple Karten auf Apple-Geraeten, sonst Google Maps. Dieselbe Wahl jetzt auch fuer Fahrzeugstandort und Autohaus. SmartDeal-Ersparnis brach um, weil die dt-Spalte 150,00px breit war und ihr Inhalt 150,20px - zwei Zehntel Pixel, Zeile dadurch 44,8 statt 26,4px hoch. Der Regler "Fahrt beenden" schreibt nicht mehr beim Loslassen: derselbe Wert stellt den Schlaf-Timeout des Dongles, das soll bewusst ausgeloest werden. Speichern/Verwerfen erscheinen nur bei echter Aenderung. Share-Erweiterung: an der ausgelieferten .ipa gemessen trug sie 1.0, die App 2026.9.3.3 - iOS registriert eine Erweiterung mit abweichender Versionsnummer nicht, sie fehlt dann im Teilen-Blatt. ios-signieren.sh schreibt die Version jetzt in beide Ziele und liest die fertige .ipa gegen. Zwischenablage: dritter Weg ueber UIPasteboard.itemProviders, und ein fehlender nativer Teil wird als solcher gemeldet statt als "Kein Zugriff". Am Geraet gesetzt: 1003 Network Ping Timeout 0 -> 60 s, 1004 ACK Type TCP/IP -> AVL. Beide liegen bei flespi als pending bereit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
{"version":"2026.9.4.1","sha256":"473807fbe06bc94882a3b53fa76d167a64a15d9470c0a6f993c7042a8bf009b6","bytes":270085,"gebaut":"2026-09-04T00:09:13Z"}
|
||||
{"version":"2026.9.4.5","sha256":"ffea00a94ac842d8b6b233ebd91a1a97252c4b7b6a952c336ca7a6218eceef1e","bytes":270888,"gebaut":"2026-09-04T07:57:27Z"}
|
||||
Binary file not shown.
@@ -644,6 +644,11 @@ function ics(titel, datum, ort, notiz) {
|
||||
let MAP = null, TILE = null, LEAFLET_LADEND = null;
|
||||
// Zielpunkt des Zentrieren-Knopfs im Einzelbeleg (siehe mapBoxMitZentrieren).
|
||||
let BELEG_STATION_POS = null;
|
||||
/* Merker, ob zu EINEM Beleg überhaupt eine Position zu finden war. Der Abruf
|
||||
ist asynchron, die Ansicht aber schon gezeichnet - ohne diesen Merker
|
||||
stünde bei einem erfolglosen Nachschlag dauerhaft eine Karte ohne Nadel da
|
||||
(samt Knopf, der nie scharf wird). `{ id, zustand: "keine" }`, sonst null. */
|
||||
let BELEG_KARTE = null;
|
||||
/* Bewusst themeunabhaengig hell: Kartendienste (Google Maps & Co.) zeigen die
|
||||
Standard-Strassenkarte immer im hellen Stil, weil Strassen, Beschriftungen
|
||||
und Wegfarben darauf lesbar bleiben. Die frueher bei Nacht eingeblendeten
|
||||
@@ -843,18 +848,29 @@ async function initMap() {
|
||||
} else if (route.name === "fill") {
|
||||
BELEG_STATION_POS = null; // gehört zum vorherigen Beleg, sonst zentriert der Knopf falsch
|
||||
const f = FILLS.find((x) => x.tank_id === route.id);
|
||||
const suche = f ? tankstelleSuchtext(f.station_name, f.station_address) : "";
|
||||
if (f && f.station_lat != null) {
|
||||
tankstelleAufKarteZeigen(MAP, { lat: f.station_lat, lon: f.station_lon }, f);
|
||||
} else if (f && (f.station_address || f.station_name)) {
|
||||
/* Ohne Koordinaten die Anschrift vom Beleg nachschlagen. Bis die Antwort
|
||||
da ist, bleibt der neutrale Ausschnitt stehen - und die Karte könnte
|
||||
inzwischen zu einer anderen Ansicht gehören, deshalb vor dem Zeichnen
|
||||
prüfen, ob wir noch auf demselben Beleg sind. */
|
||||
} else if (suche) {
|
||||
/* Ohne Koordinaten die Anschrift vom Beleg nachschlagen - und wenn der
|
||||
Beleg keine trägt, den Namen (dieselbe Reihenfolge wie in der App,
|
||||
tankstelleSuchtext). Bis die Antwort da ist, bleibt der neutrale
|
||||
Ausschnitt stehen - und die Karte könnte inzwischen zu einer anderen
|
||||
Ansicht gehören, deshalb vor dem Zeichnen prüfen, ob wir noch auf
|
||||
demselben Beleg sind. */
|
||||
MAP.setView(kartenMittelpunkt(), 11);
|
||||
const karte = MAP, belegId = route.id;
|
||||
adresseAufloesen(f.station_address || f.station_name).then((pos) => {
|
||||
if (!pos || MAP !== karte || route.name !== "fill" || route.id !== belegId) return;
|
||||
tankstelleAufKarteZeigen(karte, pos, f);
|
||||
tankstellePosition(f.station_name, f.station_address).then((pos) => {
|
||||
if (MAP !== karte || route.name !== "fill" || route.id !== belegId) return;
|
||||
if (pos) return tankstelleAufKarteZeigen(karte, pos, f);
|
||||
/* Kein Treffer: statt eines beliebigen Ausschnitts mit totem
|
||||
Zentrieren-Knopf die ehrliche Auskunft. Genau die beiden Befunde
|
||||
des Eigentümers vom 04.09.2026 - "Map lädt die Position der
|
||||
Tankstelle nicht" und "der Button auf der Map funktioniert nicht"
|
||||
waren dieselbe Stelle: eine Karte ohne Nadel und ein Knopf, der
|
||||
nie scharf wurde. */
|
||||
BELEG_KARTE = { id: belegId, zustand: "keine" };
|
||||
render();
|
||||
});
|
||||
} else {
|
||||
MAP.setView(kartenMittelpunkt(), 11);
|
||||
@@ -1210,6 +1226,81 @@ async function adresseAufloesen(adresse) {
|
||||
return treffer;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------- Tankstelle
|
||||
Anzeige in zwei Zeilen und der Weg in den Kartendienst des Geraets.
|
||||
Wortgleich mit companion-app/src/daten/tankstelle.ts - dort steht die
|
||||
ausfuehrliche Begruendung.
|
||||
|
||||
Kurz: die Anschrift kommt vom Belegparser als "<Strasse>, <PLZ Ort>";
|
||||
geteilt wird am LETZTEN Komma, damit ein Zusatz bei der Strasse bleibt.
|
||||
Erste Zeile Tankstelle und Strasse, zweite Zeile der Ort (Vorgabe des
|
||||
Eigentuemers, 04.09.2026). Ohne Komma bleibt alles in der ersten Zeile -
|
||||
lieber ein langer erster Eintrag als ein erfundener Ort. */
|
||||
function adresseTeilen(adresse) {
|
||||
const roh = (adresse || "").trim();
|
||||
if (!roh) return { strasse: "", ort: "" };
|
||||
const komma = roh.lastIndexOf(",");
|
||||
if (komma < 0) return { strasse: roh, ort: "" };
|
||||
return { strasse: roh.slice(0, komma).trim(), ort: roh.slice(komma + 1).trim() };
|
||||
}
|
||||
|
||||
function tankstelleZeilen(name, adresse) {
|
||||
const { strasse, ort } = adresseTeilen(adresse);
|
||||
const oben = [(name || "").trim(), strasse].filter(Boolean).join(", ");
|
||||
return { oben: oben || "unbekannt", unten: ort };
|
||||
}
|
||||
|
||||
/* Suchbegriffe fuer die Geokodierung, in der Reihenfolge des Versuchs: erst
|
||||
die Anschrift, dann der Name. NICHT beides zusammen - am 04.09.2026
|
||||
gemessen: "Pascalstr. 8, 85057 Ingolstadt" findet Nominatim, mit dem
|
||||
Betreibernamen davor nicht. Der Name ALLEIN ist trotzdem wertvoll
|
||||
("Shell, SOELDEN" findet es), deshalb der zweite Versuch. */
|
||||
function tankstelleKandidaten(name, adresse) {
|
||||
return [(adresse || "").trim(), (name || "").trim()].filter(Boolean);
|
||||
}
|
||||
|
||||
/** Der erste Suchbegriff - leer heisst: der Beleg nennt gar nichts. */
|
||||
function tankstelleSuchtext(name, adresse) {
|
||||
return tankstelleKandidaten(name, adresse)[0] || "";
|
||||
}
|
||||
|
||||
/* Ziel fuer den Kartendienst. Hier gehoeren Name UND Anschrift zusammen:
|
||||
Apple Karten und Google Maps kennen Betriebsnamen und treffen damit die
|
||||
Zapfsaeule statt des Nachbargebaeudes. */
|
||||
function tankstelleZiel(name, adresse) {
|
||||
return [(name || "").trim(), (adresse || "").trim()].filter(Boolean).join(", ");
|
||||
}
|
||||
|
||||
/* Die Kandidaten der Reihe nach nachschlagen, erster Treffer gewinnt. */
|
||||
async function tankstellePosition(name, adresse) {
|
||||
for (const begriff of tankstelleKandidaten(name, adresse)) {
|
||||
const pos = await adresseAufloesen(begriff);
|
||||
if (pos) return pos;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Apple-Geraet? Dort ist Karten der Standarddienst. */
|
||||
function apfelgeraet() {
|
||||
const kennung = `${navigator.userAgent || ""} ${navigator.platform || ""}`;
|
||||
return /iPhone|iPad|iPod|Macintosh|Mac OS X/i.test(kennung);
|
||||
}
|
||||
|
||||
function kartendienstUrl(name, adresse, pos) {
|
||||
const beschriftung = (name || "").trim();
|
||||
const ziel = pos ? `${pos.lat},${pos.lon}` : tankstelleZiel(name, adresse);
|
||||
if (!ziel) return null;
|
||||
if (apfelgeraet()) {
|
||||
const q = pos && beschriftung ? `&q=${encodeURIComponent(beschriftung)}` : "";
|
||||
return `https://maps.apple.com/?daddr=${encodeURIComponent(ziel)}${q}`;
|
||||
}
|
||||
return `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(ziel)}`;
|
||||
}
|
||||
|
||||
function kartendienstUrlZuPunkt(pos) {
|
||||
return pos ? kartendienstUrl(null, null, pos) : null;
|
||||
}
|
||||
|
||||
/* Setzt Nadel und Ausschnitt, sobald die Koordinaten da sind. Getrennt von
|
||||
initMap(), weil der Abruf asynchron ist und die Karte bis dahin schon
|
||||
steht. */
|
||||
@@ -3107,13 +3198,24 @@ function vEinst() {
|
||||
Dieselben Felder gibt es unter Einstellungen → Geräte & Dienste → Audi Dashboard →
|
||||
Konfigurieren.</span>
|
||||
</div>` : ""}
|
||||
<div class="tile"><span class="label">Fahrt beenden</span>
|
||||
${(() => {
|
||||
/* Der Regler schreibt NICHT mehr beim Loslassen. Sein Wert stellt zugleich
|
||||
den Schlaf-Timeout des Dongles - eine Änderung am Fahrzeug, die über zwei
|
||||
Netze geht; die soll bewusst ausgelöst werden und nicht als Nebenwirkung
|
||||
einer Wischgeste entstehen (Vorgabe des Eigentümers, 04.09.2026). Der
|
||||
Knopf erscheint erst, wenn der Regler wirklich woanders steht - ein
|
||||
dauerhaft sichtbarer, meist wirkungsloser Knopf wäre Beiwerk. */
|
||||
const minuten = PAUSENZEIT_ENTWURF ?? CONFIG.pausenzeit;
|
||||
const geaendert = PAUSENZEIT_ENTWURF !== null && PAUSENZEIT_ENTWURF !== CONFIG.pausenzeit;
|
||||
return `<div class="tile"><span class="label">Fahrt beenden</span>
|
||||
<div class="schieber" style="margin-top:14px">
|
||||
<input type="range" min="1" max="60" step="1" value="${CONFIG.pausenzeit}"
|
||||
style="--fuell:${((CONFIG.pausenzeit - 1) / 59) * 100}%" data-pausenzeit
|
||||
<input type="range" min="1" max="60" step="1" value="${minuten}"
|
||||
style="--fuell:${((minuten - 1) / 59) * 100}%" data-pausenzeit
|
||||
aria-label="Minuten bis zum automatischen Fahrtende">
|
||||
<output>${CONFIG.pausenzeit} Min.</output>
|
||||
<output>${minuten} Min.</output>
|
||||
</div>
|
||||
${geaendert ? `<button class="aktion primaer" style="margin-top:14px" data-pausenzeitspeichern>Speichern</button>
|
||||
<button class="aktion" data-pausenzeitverwerfen>Verwerfen</button>` : ""}
|
||||
<span class="label" style="margin-top:14px;color:var(--fg2);letter-spacing:0;
|
||||
text-transform:none;font-size:12.5px;line-height:1.6">
|
||||
Hier können Sie einstellen, wie viele Minuten nach Ausschalten der Zündung die
|
||||
@@ -3121,7 +3223,8 @@ function vEinst() {
|
||||
des Dongles: so lange bleibt er nach dem Abstellen wach und wartet darauf,
|
||||
dass es gleich weitergeht. Danach schläft er — das spart Strom, kostet beim
|
||||
Fortsetzen aber ein paar Sekunden fürs Aufwachen.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
})()}
|
||||
${DONGLE && DONGLE.aktiv ? `<div class="tile"><span class="label">Dongle</span>
|
||||
${DONGLE.stand && DONGLE.stand.fehler
|
||||
? `<span class="label" style="margin-top:8px;color:var(--bad);letter-spacing:0;
|
||||
@@ -3296,6 +3399,11 @@ function vEinst() {
|
||||
|
||||
let nmOffen = false;
|
||||
let einrichtenOffen = false;
|
||||
/* Entwurf des Reglers "Fahrt beenden" (Minuten) - null heisst: nicht angefasst.
|
||||
Er liegt bewusst NEBEN CONFIG.pausenzeit und nicht darin: erst der Knopf
|
||||
"Speichern" uebernimmt ihn, weil derselbe Wert den Schlaf-Timeout des
|
||||
Dongles stellt. Siehe die Kachel in vEinst(). */
|
||||
let PAUSENZEIT_ENTWURF = null;
|
||||
let bildMenuOffen = null;
|
||||
let smartdealPopupOffen = false;
|
||||
// "sommer"|"winter", welcher Reifensatz gerade sein km-Korrektur-Feld offen
|
||||
@@ -4403,6 +4511,48 @@ function vFuel() {
|
||||
${vFuelFormular()}`;
|
||||
}
|
||||
|
||||
/* Karte des Einzelbelegs - oder die Auskunft, dass es zu dieser Tankstelle
|
||||
keine Position gibt. Welches von beidem, entscheidet BELEG_KARTE: den
|
||||
Merker setzt initMap(), sobald der Nachschlag erfolglos zurueckkommt.
|
||||
Deckungsgleich mit TankstellenKarte.tsx in der App, samt der Unterscheidung
|
||||
zwischen "steht nicht im Beleg" und "findet niemand". */
|
||||
function belegKarte(f) {
|
||||
const suche = tankstelleSuchtext(f.station_name, f.station_address);
|
||||
const ohne =
|
||||
!suche || (BELEG_KARTE && BELEG_KARTE.id === f.tank_id && BELEG_KARTE.zustand === "keine");
|
||||
if (!ohne) return mapBoxMitZentrieren();
|
||||
return `<div class="tile"><div class="leer">
|
||||
<strong>Keine Position zur Tankstelle</strong>
|
||||
<p>${
|
||||
suche
|
||||
? "Zu dieser Anschrift ließ sich kein Kartenpunkt finden. Tragen Sie im Beleg unter „Werte bearbeiten“ eine genauere Anschrift ein, dann erscheint die Tankstelle hier."
|
||||
: "Dieser Beleg nennt weder Tankstelle noch Anschrift. Tragen Sie sie unter „Werte bearbeiten“ nach, dann erscheint die Tankstelle hier."
|
||||
}</p>
|
||||
</div></div>`;
|
||||
}
|
||||
|
||||
/* Tankstelle des Belegs: eigene Zeile ueber die volle Kachelbreite statt der
|
||||
engen Wertespalte, zweizeilig und antippbar.
|
||||
|
||||
Vorher eine gewoehnliche .row: Name rechts in der Wertespalte (rows-fest,
|
||||
also 120px), die ganze Anschrift als Kleintext darunter - "Hermann Mogler
|
||||
Mineraloelg. GmbH, Heidenheimerstr.6, 89551 Koenigsbronn" stand dort
|
||||
vier- bis fuenfzeilig. Der Tipp fuehrt jetzt in den Kartendienst des
|
||||
Geraets; ohne Name und ohne Anschrift bleibt es eine stumme Zeile, denn
|
||||
ein Verweis, der nirgendwohin fuehrt, waere schlechter als keiner. */
|
||||
function tankstellenZeile(f) {
|
||||
const { oben, unten } = tankstelleZeilen(f.station_name, f.station_address);
|
||||
const url = kartendienstUrl(f.station_name, f.station_address);
|
||||
const inhalt =
|
||||
`<span class="tankstellenzeile-ort">${esc(oben)}${unten ? `<small>${esc(unten)}</small>` : ""}</span>` +
|
||||
(url ? `<svg class="chev" viewBox="0 0 6 10" aria-hidden="true"><polyline points="1,1 5,5 1,9"/></svg>` : "");
|
||||
return `<div class="row tankstellenzeile"><dt>Tankstelle</dt><dd>${
|
||||
url
|
||||
? `<a href="${esc(url)}" target="_blank" rel="noopener" aria-label="${esc(oben)} in Karten öffnen">${inhalt}</a>`
|
||||
: `<span>${inhalt}</span>`
|
||||
}</dd></div>`;
|
||||
}
|
||||
|
||||
function vFill(id) {
|
||||
const f = FILLS.find((x) => x.tank_id === id);
|
||||
if (!f) return `<div class="tile">Tankvorgang nicht gefunden</div>`;
|
||||
@@ -4420,7 +4570,7 @@ function vFill(id) {
|
||||
}
|
||||
|
||||
return `
|
||||
${mapBoxMitZentrieren()}
|
||||
${belegKarte(f)}
|
||||
<div class="tile flat" style="margin:18px 0 14px">
|
||||
<span class="label">Getankt</span>
|
||||
<div class="fig" style="font-size:52px;margin-top:10px">${f.liters != null ? de(f.liters, 2) : "–"}<span class="unit">l</span></div>
|
||||
@@ -4433,8 +4583,8 @@ function vFill(id) {
|
||||
<div class="row"><dt>Getankte Liter</dt><dd>${f.liters != null ? de(f.liters, 2) + " l" : "–"}</dd></div>
|
||||
<div class="row"><dt>Kosten</dt><dd>${f.fuel_total_eur != null ? eur(f.fuel_total_eur) + " €" : "–"}<small>real, nach Rabatt</small></dd></div>
|
||||
<div class="row"><dt>Preis je Liter</dt><dd>${berechneterPreis != null ? de(berechneterPreis, 2) + " €" : "–"}<small>Kosten ÷ Liter</small></dd></div>
|
||||
${CAR.smartdeal.aktiv && f.discount != null ? `<div class="row"><dt><span class="marke">${markenlogo()} SmartDeal-Ersparnis</span></dt><dd>${eur(f.discount)} €</dd></div>` : ""}
|
||||
<div class="row" style="border-bottom:0"><dt>Tankstelle</dt><dd>${esc(f.station_name || "unbekannt")}<small>${esc(f.station_address || "")}</small></dd></div>
|
||||
${CAR.smartdeal.aktiv && f.discount != null ? `<div class="row row-marke"><dt><span class="marke">${markenlogo()} SmartDeal-Ersparnis</span></dt><dd>${eur(f.discount)} €</dd></div>` : ""}
|
||||
${tankstellenZeile(f)}
|
||||
</dl>
|
||||
${belegFehler && belegFehler.context === f.tank_id ? `<span class="label" style="margin-top:14px;color:var(--red)">${esc(belegFehler.meldung)}</span>` : ""}
|
||||
<button class="aktion" data-tankbearbeiten>Werte bearbeiten</button>
|
||||
@@ -5140,6 +5290,10 @@ const go = (name, id) => {
|
||||
// no-op, falls die Daten längst da sind (datenLaden() rendert dann
|
||||
// ohnehin nichts doppelt Sichtbares).
|
||||
if (!DATEN_GELADEN) datenLaden(false);
|
||||
// Der Merker "zu diesem Beleg gibt es keine Position" gilt nur so lange, wie
|
||||
// man auf ihm steht: nach einer Korrektur der Anschrift soll erneut gesucht
|
||||
// werden, nicht die alte Absage stehen bleiben.
|
||||
BELEG_KARTE = null;
|
||||
// Ein unbestätigter Servicebuch-Entwurf (siehe data-sbneu) verlässt die
|
||||
// Anwendung nie ungespeichert - wird die Eintragsseite ohne Klick auf
|
||||
// "Speichern" verlassen, verwerfen wir ihn hier statt ihn liegen zu lassen
|
||||
@@ -5838,6 +5992,9 @@ function ereignisseVerdrahten() {
|
||||
distanz: w.distanz, kraftstoff: w.kraftstoff,
|
||||
receipt_key: beleg ? beleg.receipt_key : null, receipt_file: beleg ? beleg.receipt_file : null,
|
||||
});
|
||||
// Die Anschrift kann sich gerade geändert haben - dann soll die Karte
|
||||
// erneut suchen statt bei der alten Absage zu bleiben (siehe BELEG_KARTE).
|
||||
BELEG_KARTE = null;
|
||||
tankBearbeitenOffen = false; belegEntwurf = null; belegFehler = null; render(); return;
|
||||
}
|
||||
const belegBtn = e.target.closest("[data-beleg]");
|
||||
@@ -5988,6 +6145,15 @@ function ereignisseVerdrahten() {
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Regler "Fahrt beenden": erst hier wird geschrieben. profilSpeichern()
|
||||
stellt ueber denselben Weg auch den Schlaf-Timeout des Dongles - genau
|
||||
deshalb hat der Regler einen eigenen Knopf bekommen. */
|
||||
if (e.target.closest("[data-pausenzeitspeichern]")) {
|
||||
if (PAUSENZEIT_ENTWURF !== null) CONFIG.pausenzeit = PAUSENZEIT_ENTWURF;
|
||||
PAUSENZEIT_ENTWURF = null;
|
||||
profilSpeichern(); render(); return;
|
||||
}
|
||||
if (e.target.closest("[data-pausenzeitverwerfen]")) { PAUSENZEIT_ENTWURF = null; render(); return; }
|
||||
const satz = e.target.closest("[data-satz]");
|
||||
if (satz) { serviceRufen("reifen_wechseln", { satz: satz.dataset.satz.toLowerCase() }); CAR.reifen.aktiv = satz.dataset.satz; render(); return; }
|
||||
const rfArch = e.target.closest("[data-reifenarchivieren]");
|
||||
@@ -6106,12 +6272,12 @@ function ereignisseVerdrahten() {
|
||||
ROOT.addEventListener("input", (e) => {
|
||||
if (e.target.dataset.pausenzeit !== undefined) {
|
||||
// Beim Ziehen nur die Anzeige und die Fuellung nachziehen, NICHT
|
||||
// render() und nicht speichern: ein Re-Render mitten in der Geste
|
||||
// erzeugt den Regler neu und der Daumen springt aus der Hand.
|
||||
// Gespeichert wird beim Loslassen (change-Zweig weiter unten) -
|
||||
// dieselbe Trennung wie beim Suchfeld direkt darunter.
|
||||
// render(): ein Re-Render mitten in der Geste erzeugt den Regler neu und
|
||||
// der Daumen springt aus der Hand. Dieselbe Trennung wie beim Suchfeld
|
||||
// direkt darunter. Gespeichert wird ueberhaupt nicht mehr hier, sondern
|
||||
// erst auf Knopfdruck (data-pausenzeitspeichern).
|
||||
const minuten = parseInt(e.target.value, 10);
|
||||
CONFIG.pausenzeit = minuten;
|
||||
PAUSENZEIT_ENTWURF = minuten;
|
||||
e.target.style.setProperty("--fuell", (minuten / 60) * 100 + "%");
|
||||
const feld = e.target.parentElement.querySelector("output");
|
||||
if (feld) feld.textContent = minuten === 0 ? "sofort" : minuten + " Min.";
|
||||
@@ -6316,7 +6482,9 @@ function ereignisseVerdrahten() {
|
||||
if (e.target.dataset.oelm !== undefined) { CAR.oel.monate = parseInt(e.target.value, 10); profilSpeichern(); return; }
|
||||
if (e.target.dataset.setupNurpassend !== undefined) { setupNurPassend = e.target.checked; render(); return; }
|
||||
if (e.target.dataset.startbild !== undefined) { CONFIG.startbild = e.target.value; profilSpeichern(); render(); return; }
|
||||
if (e.target.dataset.pausenzeit !== undefined) { CONFIG.pausenzeit = parseInt(e.target.value, 10); profilSpeichern(); return; }
|
||||
// Loslassen: nur den Entwurf festhalten und neu zeichnen, damit der
|
||||
// Speichern-Knopf erscheint. Geschrieben wird erst dort.
|
||||
if (e.target.dataset.pausenzeit !== undefined) { PAUSENZEIT_ENTWURF = parseInt(e.target.value, 10); render(); return; }
|
||||
if (e.target.dataset.svsel !== undefined) { svAuswahl = parseInt(e.target.value, 10); render(); return; }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -427,6 +427,29 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
||||
.row dd { margin: 0; font-size: 14px; color: var(--fg); text-align: right; }
|
||||
.row dd small { display: block; font-size: 12.5px; color: var(--fg3); margin-top: 3px; }
|
||||
.rows-fest dd { min-width: 120px; }
|
||||
|
||||
/* Tankstelle im Einzelbeleg (Vorgabe des Eigentuemers, 04.09.2026).
|
||||
|
||||
Vorher eine gewoehnliche Zeile: Name rechts in der 120px-Wertespalte, die
|
||||
ganze Anschrift als Kleintext darunter - "Hermann Mogler Mineraloelg. GmbH,
|
||||
Heidenheimerstr.6, 89551 Koenigsbronn" stand dort vier- bis fuenfzeilig.
|
||||
Hier bekommt sie die volle Kachelbreite unter der Beschriftung, zwei Zeilen
|
||||
(Tankstelle und Strasse / Ort), und fuehrt beim Tippen in den Kartendienst -
|
||||
deshalb der Chevron rechts. Deckungsgleich mit .dm-tankstellenzeile in der
|
||||
App. */
|
||||
.row.tankstellenzeile { flex-direction: column; align-items: stretch; gap: 4px; border-bottom: 0; }
|
||||
/* flex:0 0 auto hebt .rows-fest dt{flex:0 0 150px} auf: in einer Spalte
|
||||
ist die Flex-Basis die HOEHE - der Titel waere sonst 150px hoch. */
|
||||
.row.tankstellenzeile dt { font-size: 13px; color: var(--fg2); flex: 0 0 auto; }
|
||||
.row.tankstellenzeile dd { min-width: 0; text-align: left; flex: 0 0 auto; }
|
||||
.row.tankstellenzeile dd > a,
|
||||
.row.tankstellenzeile dd > span {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
gap: var(--sp-3); color: inherit; text-decoration: none;
|
||||
}
|
||||
.row.tankstellenzeile dd > a:active { opacity: .6; }
|
||||
.tankstellenzeile-ort { display: block; font-size: 14px; color: var(--fg); line-height: 1.35; min-width: 0; }
|
||||
.tankstellenzeile-ort small { display: block; margin-top: 2px; font-size: 12.5px; color: var(--fg3); }
|
||||
/* .row-fussnote ist mit dem Umbau der Service-Seite auf .termingruppe
|
||||
entfallen (2026-08-18) - dort gibt es keine dt/dd-Spalten mehr, die um
|
||||
Platz konkurrieren. Die beiden Regeln dafuer standen seither ohne
|
||||
@@ -695,7 +718,16 @@ img.carfix.klein { aspect-ratio: auto; height: auto; }
|
||||
.dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--line-strong); }
|
||||
.dots i.on { background: var(--red); }
|
||||
|
||||
.marke { display: inline-flex; align-items: center; gap: 6px; }
|
||||
/* white-space:nowrap: ohne die brach "SmartDeal-Ersparnis" neben dem
|
||||
Markenlogo um. Kein Platzmangel, sondern ein Rundungsfehler - am
|
||||
Einzelbeleg gemessen (04.09.2026, 375px breit): die dt-Spalte war 150,00px
|
||||
breit, ihr eigener Inhalt 150,20px, also rutschte der Text hinter dem Logo
|
||||
in eine zweite Zeile und die Zeile wurde 44,8px statt 26,4px hoch. Die
|
||||
Zeile hat reichlich Platz (307px fuer 150 + 16 + 55), sie darf ihn nur nicht
|
||||
abgeschnitten bekommen - dafuer gibt die Wertespalte in genau dieser Zeile
|
||||
ihre feste Mindestbreite auf (.row-marke). */
|
||||
.marke { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
|
||||
.rows-fest .row-marke dd { min-width: 0; }
|
||||
.marke-logo { display: inline-flex; align-items: center; }
|
||||
/* 19,2px = 16px + 20%. Der Eigentuemer wollte das Markenlogo in JEDER
|
||||
Darstellung um ein Fuenftel groesser; es steht ueberall neben Text der
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
{
|
||||
"domain": "audi_dashboard",
|
||||
"name": "Audi Dashboard",
|
||||
"version": "2026.9.4.1",
|
||||
"version": "2026.9.4.5",
|
||||
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
||||
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
||||
"codeowners": ["@paul"],
|
||||
"codeowners": [
|
||||
"@paul"
|
||||
],
|
||||
"config_flow": true,
|
||||
"integration_type": "service",
|
||||
"single_config_entry": true,
|
||||
"iot_class": "local_polling",
|
||||
"dependencies": ["http", "frontend", "panel_custom", "recorder"],
|
||||
"requirements": ["pypdf>=4.0.0"]
|
||||
"dependencies": [
|
||||
"http",
|
||||
"frontend",
|
||||
"panel_custom",
|
||||
"recorder"
|
||||
],
|
||||
"requirements": [
|
||||
"pypdf>=4.0.0"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user