Bisher fand der IP-Scan Geräte nur per ICMP-Ping; ein Windows-PC mit aktiver
Firewall (Ping blockiert, Ports offen) fiel komplett durch. Kein Fortschritt
während des Laufs, kein Abbrechen, kein Hinweis was gescannt wird.
Nativ (NetDiagScannerPlugin.kt):
- Mehrgleisige Suche: gefunden bei Ping ODER Port-Probe ODER ARP-Tabellen-
Eintrag. Runde 1 über alle Adressen, ARP-Abgleich, Runde 2 NUR für die
weiterhin stillen Adressen, ARP erneut abgleichen.
- startIpScan()/cancelIpScan() statt eines einzigen langen ipScan()-Promise:
läuft als Lauf mit Live-Events (ipScanProgress/ipScanFinished), Abbruch
liefert das bis dahin gefundene Teilergebnis statt nichts.
- Eigener limitedParallelism(128)-Dispatcher, damit ein großer Sweep keinen
gleichzeitigen Ping/Monitor/Dauertest ausbremst.
- arpAvailable ehrlich über File.canRead() statt "Tabelle war halt leer".
- mDNS-Budget 4s -> 9s, Discovery/Auflösung entkoppelt (eigene Nachlaufzeit),
discoveryOk meldet einen echten Suchfehler statt stiller 0 Treffer.
App:
- scanner.ts: neue Events onIpScanProgress/onIpScanFinished.
- ipscan.ts: protocolPatch statt direktem Beschreiben von ctx.protocol;
fehlgeschlagener Scan erzeugt jetzt auch eine Messung (Status 2 statt
nichts); "neu"/"nicht mehr erreichbar" als Diagnosefelder.
- ToolDialog: generischer Vorschau-Schritt (tool.preview — Adapter, eigene
IP, Gateway, Adressenzahl; ab >1024 Adressen Bestätigung "Trotzdem
scannen") und Live-Fortschritt (tool.supportsProgress — Fortschrittsbalken,
laufende Trefferliste, Abbrechen). Beide Mechanismen sind generisch für
alle Tools nutzbar, nicht IP-Scan-spezifisch fest verdrahtet.
- DeviceCard zeigt den Fundweg ("via Ping/Port/ARP/mDNS") als Badge.
- Geräteliste numerisch nach IP sortiert (Favoriten weiter zuerst).
Im Emulator getestet (nicht nur Codereview): ICMP per iptables zu einem
Ziel geblockt, nur TCP/22 offen -> Gerät korrekt "via Port" gefunden.
/24 zweimal komplett gescannt: gleiche 4 Geräte, zweiter Lauf ohne "neu".
/20 (4094 Adressen) löst die Bestätigung korrekt aus. Abbrechen mitten im
Lauf liefert sauber ein Teilergebnis. Sync nach Dolibarr per DB-Query
verifiziert.
Dabei zwei echte Bugs gefunden, die reines Codereview nicht gefunden hätte:
Fortschritt zeigte "504 von 254" (Runde 2 zählte im Zähler von Runde 1
weiter), und das native Feld hieß "gefundenVia" statt "foundVia" wie von
der TS-Seite erwartet — der Fundweg kam nie an.
Details: ROADMAP_UMSETZUNG.md Phase 3
Kompletter Umbau (ROADMAP_UMSETZUNG.md Phase 2). Die alte Fassung hatte vier
Probleme, die den Test praktisch wertlos machten: kein festes Intervall (ein
"Messpunkt" dauerte so lange wie das Ziel zufaellig antwortete — Prod #126:
38 Punkte in 300 s statt der ueblichen ~250-300), keine Zeitreihe (nur
Summen), kein Foreground-Service trotz gegenteiliger Doku-Behauptung, kein
Abbruchpfad. Vor allem aber: waehrend der 1-60 Minuten sah man nichts ausser
"Messung laeuft ...".
Nativ (NetDiagScannerPlugin.kt, MonitorService.kt)
StressRun komplett neu: feste Taktung per naechstem Fixpunkt (nextTick +=
intervalSec*1000, kein Zeitverzug ueber eine Stunde), Rohzaehler
(sentTotal/receivedTotal/rttSum/Min/Max) + echte Zeitreihe (Liste aus
{ts,rtt}), Ausfallsegmente werden waehrend des Laufs erkannt und
geschlossen. Laeuft im MonitorService (Foreground, wie der Geraete-Monitor)
— dafuer wurde der Dienst auf eine Job-Registry umgestellt (jobId -> Text),
damit ein gleichzeitig laufender Geraete-Monitor und Dauertest sich beim
Beenden nicht gegenseitig die Benachrichtigung wegnehmen.
Events stressSample (live, pro Probe) und stressFinished (einmalig, Grund
completed/stopped) + getStressStatus zur Wiederaufnahme nach Seitenwechsel.
WICHTIG geloest: laeuft der Test natuerlich aus, waehrend niemand zuhoert
(App im Hintergrund, andere Seite offen), bleibt der Lauf-Eintrag in
stressRuns bestehen (wie monitorRuns) statt sofort geloescht zu werden —
sonst waere das Ergebnis unwiederbringlich weg. Neuer Aufraeum-Call
dismissStressRun.
Nebenbei: der geteilte io-Scope aller Plugin-Methoden lief bisher auf einem
gewoehnlichen Job — eine unbehandelte Exception in EINER Coroutine (z.B.
IP-Scan mit kaputtem Host) haette strukturell alle Geschwister-Coroutinen
mitgerissen, auch einen parallel laufenden Monitor/Dauertest. Jetzt
SupervisorJob + CoroutineExceptionHandler.
Kritischer Bug gefunden UND gefixt (im Emulator, echter Netzausfall-Test):
`.put("rtt", rtt as Any?)` mit Kotlin null wird von org.json.JSONObject
behandelt wie `remove(key)` — der Schluessel verschwindet komplett statt
als JSON null anzukommen. Die App bekam damit `undefined` statt `null` fuer
verlorene Proben; `!== null`-Filter hielten das faelschlich fuer "erhalten".
Ergebnis: ein per Flugmodus ausgeloester echter Ausfall zeigte live "0 %
Verlust" und "NaN ms" bei Min/Max/Oe. Betraf NUR die Live-Anzeige — die
gespeicherte Messung war unabhaengig davon korrekt, weil buildStressResult()
ausschliesslich aus dem nativen Kotlin-Zustand rechnet, nie ueber die
Pro-Probe-JSON-Bruecke. Fix: ueberall explizit JSONObject.NULL statt bloss
`null` (betraf auch die Traceroute-Korrektur aus Phase 1). Zusaetzlich
TS-seitig als zweite Verteidigungslinie `!= null` statt `!== null` (deckt
sowohl null als auch undefined ab).
Neu: gemeinsame Bewertung (tools/rating.ts)
ping.ts und der alte Dauertest bewerteten denselben Netzzustand
unterschiedlich (ping.ts: avgMs>100 -> Rot; Dauertest: nur lossPct/maxMs).
rateLatency() ist jetzt die einzige Stelle: Verlust, Jitter, Latenz nach
Zielklasse (LAN/WLAN/WAN) UND eine eigene Regel "jeder Ausfall > 5 s = Rot"
unabhaengig vom Gesamt-Verlustprozentsatz. ping.ts umgestellt, unveraendertes
Verhalten fuer die bisherigen Schwellen (inkl. Jitter>10ms, das beim
Portieren fast uebersehen wurde).
Neue Route statt Dialog (routes/protokoll/[id]/stresstest/)
Wie IP-Test/WLAN/Monitor eine eigene Seite statt des blockierenden
Werkzeug-Dialogs. Einrichtung (Ziel leer=Gateway, Dauer, Takt) mit
Vorlaufprobe wie zuvor in stresstest.ts. Laufend: grosse Live-Zahl mit
Ampelfarbe (rateLatency), Fortschrittsbalken mit Restzeit, Streifendiagramm
(StressChart.svelte, live rollierendes 120s-Fenster), Zaehler
gesendet/verloren/Ø/Min/Max, offener-Ausfall-Banner, Ereignisliste mit
Uhrzeit ("Ausfall — wieder da nach 16 s"), Abbrechen. Abgeschlossene Laeufe
darunter aufklappbar mit demselben Diagramm (kompletter Verlauf statt
Fenster). stresstest.ts (Tool-Registry-Eintrag) ist jetzt nur noch
Namens-Lookup fuer die Messungen-Liste, run() wirft bewusst einen Fehler,
falls doch noch etwas den alten Weg aufruft.
Sicherheitsnetz gegen verpasste Events (lib/stresstest.ts)
Ein natuerlich beendeter Test, waehrend niemand auf der Stresstest-Seite
ist, verpasst dort das stressFinished-Event. Die Hauptprotokollseite prueft
deshalb beim Oeffnen zusaetzlich per resumeFinishedStressSessions() nach
(praktisch immer besucht, bevor ein Protokoll abgeschlossen wird) und
traegt das Ergebnis nach. Bekannter Rest-Fall (dokumentiert): verlaesst der
Techniker das Protokoll komplett ohne eine der beiden Seiten noch einmal zu
oeffnen, bleibt der fertige Lauf bis zum naechsten Besuch liegen.
Ergebnis-Speicherung: Zeitreihe in 1-Minuten-Buckets + Ausfallsegmente +
laengster Ausfall als Measurement (tool=stresstest, sync-faehig) — Ausfaelle
werden beim Abschliessen mit dem nativen (autoritativen) Ergebnis abgeglichen,
nicht nur mit der lokal live mitgefuehrten Kopie.
Getestet im Emulator (Pixel 6 / Android 14):
- 1-Minuten-Lauf komplett bei ausgeschaltetem Display durchgelaufen
(Foreground-Service haelt den Prozess), automatischer Abschluss + Toast
- Echter Netzausfall per Flugmodus (15s) waehrend laufendem 5-Minuten-Test:
korrekt 23,2%/16,7% Verlust, Min/Max ohne NaN, Ereignisliste mit exakter
Uhrzeit und Dauer — nach dem NULL-Fix verifiziert
- Abbrechen-Pfad: sofortiger Stopp, korrektes Teil-Ergebnis
- Wiederaufnahme: laufender Test nach APK-Neuinstallation (Prozess-Kill)
korrekt als beendet erkannt
- gradle compileDebugKotlin ok, svelte-check 0 Fehler
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Vier Werkzeuge haben nachweislich Unsinn ins Kundenprotokoll geschrieben. Belege
sind echte Prod-Messungen; jeder Fix wurde im Emulator gegen den passenden
Fehlerfall nachgestellt.
SNMP (Snmp.kt, snmp.ts)
Snmp.get lieferte bei JEDEM Problem null -> "-" -> parseInt("-")||0 -> 0.
Ein Switch, der gar nicht antwortet, stand damit als "0 Fehler" in Gruen im
Kunden-PDF (Prod #95/#96). Neu: Ergebnistyp Value/Timeout/Failure statt
String?, Request-ID- und error-status-Pruefung, v2c-Ausnahmen (0x80/0x81/0x82)
erkannt, ein Wiederholversuch bei Timeout. Das Werkzeug meldet jetzt
"nicht messbar" statt Zahlen zu erfinden.
Test: SNMP gegen einen Host ohne Agent -> status 3 "keine SNMP-Antwort".
Traceroute (pingWithTtl, traceroute.ts)
Der Fallback-Regex \((\d+\.\d+\.\d+\.\d+)\) traf IMMER zuerst die ping-Kopfzeile
"PING 8.8.8.8 (8.8.8.8) ...". Ein stummer Hop wurde dadurch als Ziel ausgegeben
und der Trace beendet — daher "2 Hops bis 8.8.8.8, beide 0 ms" (Prod #13).
Zwischen-Hops liefern zudem nie ein time=, die Zeit war strukturell 0.
Neu: Kopfzeile verworfen, zeilenweise geparst, Reverse-DNS-Antworten erkannt,
RTT selbst per nanoTime gestoppt, 3 Proben je TTL, waitFor(3s)+destroyForcibly,
"keine Antwort" ist null und nicht 0, Bewertung haengt an "Ziel erreicht".
Test: 8.8.8.8 -> 1 Hop mit echten 13,3 ms (statt 0 ms);
192.0.2.1 -> status 3, alle Hops "* (keine Antwort)" statt gruen.
Ping (measurePing, ping.ts)
Kein WifiLock, keine Aufwaermproben: zwischen den Proben schlief das Funkmodul
ein, die Aufwachzeit landete in der Messung — 296 ms zum LAN-Gateway bei 0 %
Verlust und rotem Status (Prod #4). WAKE_LOCK fehlte im Manifest, weshalb
WifiLock.acquire() eine SecurityException warf, die ein leerer catch schluckte.
Neu: WAKE_LOCK im Manifest, WifiLock (LOW_LATENCY) + PARTIAL_WAKE_LOCK um jede
Messung, 2 verworfene Aufwaermproben, Median und Messaufschlag (avg-min)
zusaetzlich ausgewiesen, Verlust als Kommazahl statt Ganzzahl-Division,
Bewertung auf den Median statt den Mittelwert, "keine Antwort" != "0 ms".
Test: 20 Proben -> Median 0,3 ms, Messaufschlag 0,1 ms, Verfahren dokumentiert.
Durchsatz (measureThroughput, iperf.ts)
Kein soTimeout: nahm die Gegenstelle an, ohne zu senden, blockierte read()
unbegrenzt und das Werkzeug-Fenster hing dauerhaft auf "Messung laeuft ...".
Neu: soTimeout 4 s je Phase, harter withTimeout-Guard, Ist-Zeit statt
angenommener halber Dauer, measured-Flag — ohne uebertragene Bytes gibt es
kein rotes "0 Mbit/s" mehr, sondern "nicht messbar".
Test: Gegenstelle nimmt an und schweigt -> Ergebnis nach 30 s statt Dauerhaenger.
Netzerkennung (firstLocalIpv4, getLocalSubnet, hostsInSubnet)
firstLocalIpv4() gab bei fehlendem Netz hart "192.168.1.1" zurueck; zusammen mit
dem Praefix-Fallback /24 entstand das Phantom-Netz 192.168.1.0/24, das auch noch
ins Protokoll geschrieben wurde. Der Fehlerzweig in ipscan.ts konnte deshalb nie
greifen. Neu: "" statt Phantom-IP, Link-Local uebersprungen, getLocalSubnet
meldet einen Fehler, DHCP-Fallback nur bei WLAN-Transport (sonst wurde bei
gestecktem USB-RJ45 die Maske aus dem WLAN genommen), unlesbares CIDR-Praefix
wird abgelehnt statt still durch /24 ersetzt.
Test: Flugmodus -> "Kein Netzbereich — WLAN/LAN nicht aktiv?" statt Phantom-Netz.
Stresstest-Ziel (stresstest.ts)
Vorgabe 192.168.1.1 im Kundennetz 192.168.178.0/24 -> 5 Minuten ins Leere
gemessen, Ergebnis "100 % Verlust" rot im Protokoll (Prod #126). Neu: kein
fester Vorgabewert, leer = Gateway des aktiven Adapters, und eine Vorlaufprobe
bricht ab, bevor minutenlang gegen ein totes Ziel gemessen wird.
Test: Ziel 192.168.1.1 -> nach 7 s "antwortet nicht — Test nicht gestartet"
(vorher: 60 s Messung mit rotem 100-%-Ergebnis).
Neue Bewertung "nicht messbar" (MeasureStatus 3)
Bisher gab es nur ok/warn/fail. Ein Test, der gar nicht durchgefuehrt werden
konnte, musste sich als eines davon ausgeben — meist als Gruen. Status 3 wird
neutral grau dargestellt (Messkarte und Geraetekarte) und ist keine Aussage
ueber das Kundennetz.
Geprueft: gradle compileDebugKotlin ok, svelte-check 0 Fehler (2 vorbestehende
Warnungen), alle sieben Faelle im Emulator (Pixel 6 / Android 14) durchgespielt
und die Ergebnisse in der Datenbank gegengelesen statt am Bildschirm geraten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Auge-Symbol im Passwortfeld. Haben alle anderen AWL-Apps seit 06.07.2026; NetDiag
war die letzte ohne. Grund: bei falschem Tastaturlayout tippt man sich sonst blind
fest. Der Typ wird imperativ am Element gesetzt, weil Svelte 5 ein dynamisches
type-Attribut an einem Feld mit bind:value verbietet; type="button" am Schalter ist
Pflicht, sonst schickt er das Formular ab.
- Serveradresse laesst sich in den Einstellungen aendern. Bisher stand sie dort nur
als Text — eine falsche Adresse liess sich nur durch Abmelden korrigieren. Ein
Wechsel meldet bewusst ab, weil das Token nur beim bisherigen Server gilt.
- Login-Fehler bleiben 8 s stehen statt 3 s und zeigen die Servermeldung im Wortlaut.
Bei 429 steht dort die Wartezeit der Brute-Force-Bremse, bei 403 der Grund.
Im Emulator (Pixel 6 / Android 14) gegen das Test-Dolibarr geprueft: Ein- und
Ausblenden des Passworts, Anmeldung ueber awlauth, Auftragsliste, Einstellungen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
IP-Test: USB-RJ45-Adapter in Netzwerkdose stecken und sofort IP-Adresse,
DHCP-Server, Gateway und Link-Geschwindigkeit (10/100/1000 Mbit) ablesen.
Auto-Refresh alle 2 s, Speichern mit optionalem Raum/Dose-Name ins Protokoll.
WLAN-Empfangstracker: Netz auswählen und beim Durchgehen live RSSI verfolgen.
Hybrid-Modus: 500 ms Polling bei verbundenem Netz (kein Scan-Throttling),
~30 s Scan-Sweep bei Fremd-BSSID. Sessions mit Samples, Min/Max/Avg und
Sparkline-Verlauf werden im Protokoll gespeichert.
Ersetzt DHCP-Info-Tool und WLAN-Scan-Tool (eigene Routen /iptest/ + /wifi/).
Kotlin-Plugin: linkInfo(), startWifiScan(), startWifiTrack/stop/status().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Für das Kamera-Problem: mehrere Geräte auswählen und ihre Erreichbarkeit
über längere Zeit überwachen — jeder Ausfall wird mit Uhrzeit protokolliert.
- MonitorService: schlanker Vordergrund-Dienst, hält den Prozess am Leben,
damit die Überwachung bei Display aus / App-Wechsel weiterläuft
- Plugin startMonitor/stopMonitor/getMonitorStatus: pingt die Geräte im
gewählten Intervall, Wechsel erreichbar↔weg erzeugt ein monitorEvent;
WifiLock gegen WLAN-Schlaf, Heads-up-Benachrichtigung bei Ausfall
- Monitor-Seite (protokoll/[id]/monitor): Geräte-Mehrfachauswahl,
Intervallwahl, Live-Ereignisliste, frühere Überwachungen mit Ausfallzahl
- Überwachung läuft beim Verlassen der Seite weiter; Rückkehr nimmt den
Stand wieder auf (getMonitorStatus)
- Manifest: MonitorService + FOREGROUND_SERVICE_DATA_SYNC, POST_NOTIFICATIONS
- Kachel "Geräte-Monitor" im Werkzeuge-Raster
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- "Scan speichern" friert den aktuellen Geräte-Stand als benannten
Snapshot ein (saveScan in protocols.ts, tiefe Kopie)
- Abschnitt "Gespeicherte Scans" auf der Protokollseite: aufklappbare
Liste mit Name, Subnetz, Datum und Gerätezahl; Snapshot zeigt die
damals gefundenen Geräte (DeviceCard read-only)
- Scan löschen per ConfirmDialog
- Snapshots bleiben am Auftrag erhalten, auch über spätere Re-Scans hinweg
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Favoriten-Stern je Gerät; favorisierte Geräte werden in der Liste oben
einsortiert. Favorit + eigener Name bleiben im Protokoll erhalten, auch
ohne gespeicherten Scan-Snapshot
- Gerät umbenennen (customName) über neuen TextPromptDialog
- toggleFavorite / renameDevice in protocols.ts
- TextPromptDialog + ConfirmDialog: schlanke Modal-Komponenten als Ersatz
für die verbotenen Browser-prompt()/confirm(); melden sich als Overlay an
(Hardware-Backbutton schließt sie)
- Protokoll-Löschen nutzt jetzt ConfirmDialog statt confirm()
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Resume: jede Navigation wird gemerkt; nach App-Neustart (oder wenn Android
den Prozess beim App-Wechsel beendet hat) öffnet die App wieder genau dort,
wo der Benutzer war — inklusive offenem Protokoll
- Protokoll wird beim Verlassen der Seite (Back-Tap/Navigation) und beim
Wechsel in den Hintergrund automatisch gesichert — auch Eingaben, die noch
nicht per onblur gespeichert wurden, gehen nicht mehr verloren
- Hardware-Backbutton schließt einen offenen Werkzeug-Dialog, statt gleich
die Seite zu verlassen (neue Overlay-Registry overlay.svelte.ts)
- backButton.svelte.ts: PluginListenerHandle korrekt aus @capacitor/core
importiert (war fälschlich @capacitor/app — Svelte-Check-Fehler behoben)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- NetBIOS-Namensabfrage (UDP 137) je Host integriert
- mdnsScan: neue Plugin-Methode, mDNS/Bonjour via NsdManager — findet
Drucker, Kameras, Chromecast, AirPlay; liefert Namen + Diensttypen
- Quick-Port-Probe (22/80/443/554/9100 …) speist eine deviceType-Heuristik
(Kamera, Drucker, Router, Switch, NAS, Wallbox, Server …)
- OUI-Vendor-Tabelle von 6 auf ~150 kuratierte Einträge erweitert
- ipscan.ts führt IP-Scan + mDNS pro IP zusammen, mDNS-only-Geräte ergänzt
- neue DeviceCard-Komponente: zeigt Geräteart-Badge, offene Ports,
mDNS-Dienste, mac, NetBIOS-Name; ersetzt die Inline-Geräteliste
- upsertDevice überschreibt vorhandene Daten nicht mehr mit undefined
(Favorit/eigener Name bleiben bei magerem Re-Scan erhalten)
- Manifest: CHANGE_WIFI_MULTICAST_STATE für die mDNS-Suche
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Auftragsliste sortiert Aufträge mit lokalen Protokollen/Scans nach oben
(lokale updatedAt), da Dolibarr-tms bei reiner App-Tätigkeit unverändert
bleibt; Standard wieder "nur aktive Aufträge"
- Datumszeile zeigt "zuletzt bearb." aus lokalem Protokoll, sonst Server-tms
- Protokollzähler-Badge berücksichtigt auch lokale (noch nicht gesyncte) Protokolle
- types.ts: neue optionale Felder für kommende Geräte-Features
(Device: isFavorite/customName/openPorts/netbiosName/mdnsName/mdnsServices;
neu SavedScan, MonitorEvent, DeviceMonitorSession; Protocol.savedScans/monitorSessions)
- db.ts: normalizeProtocol ergänzt fehlende Arrays beim Laden alter Protokolle
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ersetzt den Browser-Umweg (window.open) durch einen echten In-App-Installer:
das native Plugin lädt die APK streamend herunter (Fortschritts-Events
updateProgress 0–100 %), prüft die Installationsberechtigung (Android 8+)
und öffnet den Paketinstaller über den vorhandenen FileProvider.
Versionsvergleich jetzt numerisch (YYYYMMDD-HHMM) statt lexikografisch.
Banner ist schließbar; Einstellungsseite zeigt separaten Fortschrittsbalken.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Der Updater fragte die private Forgejo-Registry direkt ab -> 403/CORS ->
catch -> 'App ist aktuell'. Er hat NIE wirklich geprueft.
- updater.ts: geht jetzt ueber update.php (eigener, authentifizierter
Endpoint, CORS-frei). checkForUpdate() verschluckt Fehler NICHT mehr,
sondern wirft mit Klartext-Grund.
- Einstellungen: 'Auf Update pruefen' zeigt bei Fehler die echte Meldung
('Update-Pruefung fehlgeschlagen: <Grund>') statt falschem 'aktuell'.
- +layout: Start-Pruefung still (nur Banner bei Erfolg, kein Fehler-Toast).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Damit App-Fehler (Scan/Sync) ohne Kabel nachvollziehbar sind:
- debuglog.svelte.ts: faengt window.error, unhandledrejection und console.*
in einem Ringpuffer ab, gespiegelt in Preferences (ueberlebt Neustart)
- Auto-Upload zum neuen Endpoint applog.php (gedrosselt, best effort);
ToolDialog- und Sync-Fehler werden explizit mitgeloggt
- Seite Einstellungen -> Debug-Log: Eintraege ansehen, manuell senden, leeren
- initDebugLog() zuerst in +layout onMount, damit Startfehler erfasst werden
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NetDiagScannerPlugin.kt (latente Bugs, erst durch aktivierten Kotlin-Compiler sichtbar):
- traceroute: hop.first/.second -> hop.ip/.ms (Hop ist data class, kein Pair)
- startStressTest: getInteger() liefert Int?, mit '?: 0' abgesichert
Titelleiste klebte an der Statusleiste / war oben abgeschnitten:
- safe-top/safe-bottom enthalten jetzt den Basis-Innenabstand via calc() --
sonst ueberschreibt die unlayered CSS-Klasse das padding von Tailwind py-*
- Header/Toast/Update-Banner/Login auf pb-*/px-* statt py-*/p-* umgestellt
Siehe KB #551.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auftragsliste: Kundenname + Adresse sind jetzt die Überschrift, die
Auftragsnummer nur noch Kleingedrucktes — Aufträge sind so ohne
Nummer-im-Kopf wiederzufinden. Auftragsnotiz wird mit angezeigt.
IP-Scanner: ist kein Netzbereich angegeben, nutzt das Tool den im
Protokoll hinterlegten; ist auch der leer, fragt es den aktiven
WLAN-/LAN-Adapter ab und scannt dessen Subnetz. Der ermittelte
Netzbereich wird ins Protokoll übernommen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>