Skip to content

SolixBar-Fork v0.4.3 — Notch-Fix, Design-System, Warnungen, direkter SOLIX-Modus, Graph-Glättung (Review aus #3)#4

Open
itsab1989 wants to merge 54 commits into
Ravaners:mainfrom
itsab1989:review-fixes
Open

SolixBar-Fork v0.4.3 — Notch-Fix, Design-System, Warnungen, direkter SOLIX-Modus, Graph-Glättung (Review aus #3)#4
itsab1989 wants to merge 54 commits into
Ravaners:mainfrom
itsab1989:review-fixes

Conversation

@itsab1989

@itsab1989 itsab1989 commented Jul 11, 2026

Copy link
Copy Markdown

Hallo Ravaners! 👋

Zuerst: Glückwunsch zum 0.4.0-Release mit der portablen SOLIX-Laufzeit — schön zu sehen, dass du portable Pfade, den Schlüsselbund und eine CI unabhängig selbst umgesetzt hast. Damit sind mehrere der ursprünglichen P0-Punkte aus #3 bei dir bereits erledigt. 🎉

Dieser PR ist deshalb kein „bitte alles übernehmen" mehr, sondern der komplette Fork-Stand (v0.4.3) als parallele, gepflegte Linie: alles aus dem Review in #3, weitergeführt über zwei Feedback-Runden. Weil unsere beiden Zweige inzwischen auseinanderlaufen (du hast eigene Wege für Laufzeit & Keychain gewählt), ist das hier eher zum Rosinenpicken gedacht als für einen glatten Merge. Das Issue #3 ordnet jeden Bereich mit Kontext ein; hier ist die Zusammenfassung.


Was der Fork enthält

🩹 Stabilität & Kernfixes

  • Notch-sicheres Statusitem: Das variableLength-Item wurde ~460 pt breit und von macOS hinter der Notch komplett ausgeblendet. Jetzt verdichtet sich die Anzeige stufenweise, statt zu verschwinden — inklusive des Randfalls, dass versteckte Statusitem-Frames Müll liefern (Breite wird über Button→Screen gemessen).
  • Anzeige bleibt bei Fehlern stehen: Ein Netzaussetzer leert die Werte nicht mehr (letzter Snapshot bleibt, als veraltet markiert); HTTP-Fehler werden klar gemeldet; der Decoder toleriert fehlende optionale Felder.
  • Kein Pipe-Deadlock: Große Helfer-Ausgaben (>64 KB) blockierten als vermeintlicher Timeout; jetzt nebenläufig gelesen, mit SIGKILL-Eskalation.
  • Fehler-Backoff: Nach fehlgeschlagenen Abrufen verdoppelt sich der Abstand (max. 30 min) und springt beim ersten Erfolg zurück — kein Dauerfeuer gegen eine tote API.

🔌 Direkter SOLIX-Modus & Datenwege

  • Datenquelle „SOLIX-Konto (direkt)" mit gebündelter, portabler Python-Laufzeit — ohne konfigurierten Befehl und ohne lokale Installation. Zugangsdaten gehen als stdin-JSON an den Helfer (nicht als Umgebungsvariablen, die via ps sichtbar wären); das Passwort liegt ausschließlich im macOS-Schlüsselbund. Wer den früheren Helfer-Befehl nutzte, wird automatisch migriert.
  • Weniger API-Last: Tages-/Gesamtstatistik werden 10 bzw. 15 min gecacht (atomar, Dateirechte 0600); Live-Leistungswerte bleiben frisch. Zustand & Cache liegen im Application-Support-Ordner, nie im signierten Bundle.
  • Hinweis: eine eigenständige Umsetzung neben deiner 0.4.0-Laufzeit — die Idee überschneidet sich, die Details (stdin-Credentials, Caching, Backoff) sind evtl. auch für dich interessant.

🎨 Design-System & Dark Mode

  • Ein zentrales Theme mit semantischen Rollen ersetzt vier parallele Farbwelten und die frühere Farbwahl per Textsuche im gerenderten String (zerbrach bei jeder Textänderung). Netzbezug rot (kostet Geld), Einspeisung violett.
  • Eine Wurzel für viele Dark-Mode-Fehler: dynamicColor.cgColor außerhalb eines Zeichenkontexts löst mit der Prozess-Standard-Appearance auf (weiße Streifen, falsche Farben nach Theme-Wechsel). View-Aufbau läuft jetzt in performAsCurrentDrawingAppearance, das Menü bekommt seine Appearance explizit.

📊 Anzeige & Bedienung

  • Zweizeilige Kompaktanzeige (notch-sicher, Standard): vier Werte auf ~97 pt. Menüleiste und abgedockte Leiste sind zwei unabhängige Anzeigen.
  • Abgedockte Leiste frei verschiebbar, Fensterebene wählbar (vorn/normal/hinten), Schließen-Kreuz nur bei Hover bzw. wenn nicht fixiert.
  • Sortierbare Werte-Listen (Häkchen wählt, Ziehen ordnet) — je Leiste und Ansicht (einzeilig/kompakt) unabhängig.
  • Leistung je PV-Eingang: „PV-Anzeige" wählbar (Gesamt / Einzelwerte / beides), getrennt für Menü-Dashboard, abgedocktes Fenster, Menüleiste und abgedockte Leiste.
  • Dashboard-Kacheln: Werte skalieren auf die verfügbare Breite (kein abgeschnittener Trend-Pfeil); drei/vier PV-Eingänge als 2×2-Raster auf zwei Zeilen.

📈 Verlauf & Graph

  • Demo- und Live-Daten getrennt (Demo verfälscht den echten Graphen nicht), Datei-Speicher, zweistufige Aufbewahrung bis 366 Tage (31 Tage fein, ältere stündlich verdichtet).
  • Gemeinsame Kopfzeile mit Zeitraum-Chips + Legende für Dropdown, abgedocktes Dashboard und großes Verlaufsfenster; Hover-Inspektor mit Wertebox.
  • Optionale Glättung (weiche, auf die Plotfläche geklemmte Kurven — nie scheinbar negative Watt) und je Kurve wählbare Flächenfüllung.
  • Datenexport als CSV oder JSON direkt aus dem Menü (Formatwahl im Speichern-Dialog).

🔔 Warnungen (alle standardmäßig aus)

  • Akku unter Schwelle (mit Hysterese), PV-Einbruch (nachts still), optionales Tagesfenster, einzelne PV-Eingänge (Vergleich mit den Nachbarn und/oder Einbruch gegen die eigene jüngste Erzeugung — erkennt Defekte auch bei mehreren betroffenen Eingängen). Zustellung als macOS-Mitteilung plus ⚠ im Menü.
  • Datenquelle „Demo (Warnungs-Test)": gerafftes Szenario, mit dem alle aktivierten Warnungen in wenigen Minuten real feuern.

💡 Feinschliff

  • Update-Hinweis: tägliche Prüfung der GitHub-Releases, eine Mitteilung pro Version plus Menüpunkt — abschaltbar, installiert nichts.
  • Hilfe-Popover: die Fragezeichen-Knöpfe in den Einstellungen zeigen jetzt ausführliche, verständliche Erklärungen (vorher blieb die Sprechblase leer).
  • Demo-Akku als langsame, realistische Lade-/Entladekurve statt Minuten-Sägezahn.

🏗️ Unterbau

  • Library-Split (SolixBarKit + dünnes Executable) mit 80 Tests (Unit, Prozess-/HTTP-Integration, Render-Snapshots hell/dunkel), läuft ohne Xcode mit reinen Command Line Tools.
  • CI baut ein fertiges, ad-hoc signiertes SolixBar.app, bettet die portable Laufzeit ein, prüft das Bundle (verify_release.sh: Version, Signatur, keine privaten Pfade/Daten, importierbare Module) und erzeugt Releases per v*-Tag mit Auto-Changelog.

Ohne Build ausprobieren: SolixBar-macOS.zip (v0.4.3) — beim ersten Start Rechtsklick → „Öffnen".

Was wir weiterhin nicht testen konnten: den echten Anker-Cloud-Login (kein SOLIX-Gerät bei uns). Der direkte Modus erreicht die Anker-Cloud nachweislich (falsche Zugangsdaten → korrekte Fehlermeldung), aber ein Lauf gegen dein Gerät wäre die letzte Bestätigung.

Kein Druck: Ideen übernehmen, einzelne Dateien portieren oder den PR schließen — alles fein. Tipp: Im Issue #3 steht ein fertiger Prompt für deine Coding-KI, der dir daraus selbst eine Auswahlliste aller Übernahme-Optionen erstellt. Danke für die App! 🙂

🇬🇧 Short version: Congrats on the 0.4.0 portable-runtime release — you independently covered several of the original P0 fixes (portable paths, Keychain, CI), so this PR is now the full v0.4.3 fork as a parallel line to cherry-pick from, not a clean merge. It adds: notch-safe status item, a semantic design system with correct light/dark rendering, a direct SOLIX mode with bundled runtime + stdin credentials + 10/15-min API caching + failure backoff, independent docked/undocked bars, drag-to-reorder lists, per-PV-input display, auto-fitting dashboard tiles, per-source history with 366-day retention, CSV/JSON export, optional graph smoothing and per-curve fills, opt-in warnings plus a warning-test demo mode, update notifications, extensive settings help popovers — on a SolixBarKit split with 80 tests and a CI that builds, verifies and releases the app bundle. Try it without building: v0.4.3 release. The only untested path remains the live Anker cloud login (no hardware on our side).

🤖 Generated with Claude Code

Basti and others added 30 commits July 11, 2026 00:50
Introduces Theme.swift as the single source of truth for value colors
(semantic ColorRole per metric, light/dark adaptive incl. menu bar
luminance detection) plus radius tokens and the .solixRole attributed
string key that will let derived views resolve colors semantically
instead of parsing rendered text.

Deliberate palette change: grid import is now red (cost) instead of
blue, matching the history graph which already drew grid in red.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…and render-snapshot tests

- Executable is now a thin main.swift over the SolixBarKit library so the
  code is testable (SwiftPM cannot test executable targets).
- SnapshotDecoder is lenient now: siteName and updatedAt get defaults,
  minimal JSON payloads decode (was: hard failure without siteName).
- SolixHistoryStore takes injectable UserDefaults for tests.
- RenderTests render dashboard, graph, slim bar, and all settings tabs
  offscreen to PNG (light+dark) for visual verification without screen
  recording permission. Output: .build/renders or $SOLIXBAR_RENDER_DIR.
- .gitignore for build products, packaged app, local work dir.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…snapshot on errors

- Menu bar item now checks its window frame against the screen's notch
  zone (NSScreen auxiliary areas) after every title update and degrades
  the display level stepwise (drop labels -> drop symbols/arrows -> two
  metrics -> minimal) until it no longer overlaps. macOS hides items
  that overlap the notch entirely - with labels+symbols+arrows enabled
  the item was 463pt wide and invisible on notched MacBooks.
- Startup logs item frame and notch zone for diagnosability.
- Credentials/env file moved from a hardcoded path in the original
  author's home directory to ~/Library/Application Support/SolixBar/
  (written 0600); helper command resolves the bundled or repo script
  and passes SOLIXBAR_ENV_FILE. Saving SOLIX login now works on any
  machine.
- run_solix_snapshot.sh is bundle-aware (SOLIXBAR_PYTHON override,
  python3 fallback) and ships in the packaged app.
- A failed refresh keeps the last good snapshot and appends a warning
  indicator instead of blanking the display.
- Tests: env-file roundtrip incl. quoting and 0600 permissions, helper
  command path assertions, display degradation ladder, notch overlap
  predicate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tch check

window.frame of the status bar window is stale/unpositioned right after
a title change; convert the button bounds to screen coordinates instead
and give the menu bar 100ms to relayout. Verified live: full display
degrades level 0->3 and settles at 120pt right of the notch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… file

- CommandSolixDataProvider drains stdout/stderr on background threads
  while the process runs (old code read after exit: >64KB output filled
  the pipe buffer, blocked the command, and surfaced as a bogus
  timeout). Timeout now escalates SIGTERM -> SIGKILL so a stubborn
  command cannot hang the refresh forever. Exit code included in the
  error when stderr is empty.
- URLSolixDataProvider rejects non-2xx responses with a clear message
  instead of a confusing JSON decode error.
- SOLIX password is stored in the macOS Keychain and injected into the
  helper command as an environment variable; the env file on disk no
  longer contains secrets (legacy env passwords still load once).
- History samples are kept per data source in a JSON file in
  Application Support (demo data no longer pollutes the live graph);
  legacy UserDefaults blob migrates to the demo source. Sample cap is
  derived from the refresh interval so the 30-day view can actually
  fill (old hard cap of 2000 = ~7 days at the default interval).
- Tests: pipe deadlock, SIGKILL timeout, stderr propagation, env
  injection, per-source separation, cap math, legacy migration,
  persistence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- macos-14 runner: swift test, universal release build (arm64+x86_64),
  ad-hoc signed SolixBar.app zipped as artifact on every push/PR and
  attached to GitHub releases on v* tags, so the app can be tried
  without a local toolchain. UI render PNGs from the test suite are
  uploaded as a separate artifact for visual review.
- package_app.sh accepts SOLIXBAR_BIN to package release binaries.
- URL provider integration tests against a local http.server: full
  fetch+decode roundtrip and 404 -> clear HTTP error. Together with the
  schema check against scripts/solix_snapshot.py this verifies the data
  contract end-to-end on the app side (live Anker cloud verification
  still requires real hardware).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… template glyph

- Slim bar resolves colors via the .solixRole attribute the menu bar
  formatter now emits; deletes ~180 lines of keyword-matching on
  rendered text that broke with any wording change. Accent gradient is
  a subtle two-stop tint instead of five stacked colors (muddy brown).
- History graph: header/legend drawn above the plot surface, ticks on
  round hours/days with an overlap guard before 'Jetzt/Now', only the
  solar series gets an area fill (overlapping fills mixed into olive),
  percent axis tinted in the battery color to clarify the dual axes,
  legend and tick labels localized, colors from Theme.
- Dropdown graph container had no height constraint and collapsed,
  squeezing the plot over its own header - fixed with a min height.
  Custom-days field only shows when the custom range is selected.
  Metric checkboxes double as a color legend (dot in line color).
- Dashboard: Theme colors incl. red grid-import/violet export, unified
  radius scale (16/12/8), Demo badge so sample data cannot be mistaken
  for real values, 'Online' no longer claimed when status is missing.
- Dark mode: panel backgrounds are now dynamic NSColors and all layer
  colors re-resolve on effective-appearance changes; previously views
  built under light appearance kept light pastel rows with white text.
- Menu bar icon is a cached template bolt glyph per HIG instead of the
  1.5MB PNG downscaled to 18px and reloaded on every menu rebuild.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- AppLogger mirrors to os.Logger (subsystem local.codex.SolixBar) for
  Console.app filtering, keeps the file log with an open handle and
  cached formatter, adds #function context, DecodingError/URLError
  details, and a verboseLogging defaults switch for DEBUG lines.
- Settings: App and Startup tabs merged (Startup held one checkbox),
  live preview debounced so half-typed URLs no longer hit the refresh
  pipeline, mode/appearance popups localized.
- Autostart uses SMAppService and cleans up the legacy LaunchAgent.
- README credentials section reflects the keychain flow; version 0.4.0
  with a bilingual changelog entry; PLAN.md updated with completed
  state and self-check findings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces ae/oe/ue transliterations with ä/ö/ü across code comments,
tooltips, PLAN, and the 0.4.0 changelog entry (historic changelog
entries left untouched). Also normalizes the previously inconsistent
upstream tooltips (e.g. 'Waehlt' vs 'Wählt').

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…p popovers

- Detached dashboard: the panel now IS the window (transparent
  background, hidden titlebar, floating traffic lights, draggable by
  background) - a regular window frame around the edge-hugging rounded
  panel produced visible double corners. Dropdown appearance unchanged.
- New opt-in two-line compact menu bar display (Einstellungen ->
  Menüleiste): two rows of 9pt monospaced values with tiny tinted
  metric glyphs, rendered via an NSImage drawing handler so Theme
  colors still resolve against the actual menu bar appearance. Four
  metrics in ~97pt instead of ~460pt; verified right of the notch at
  full detail. Warning triangle appears when data is stale.
- Help buttons across all settings tabs are now subtle
  questionmark.circle glyphs that open a popover with the help text on
  click (they previously looked clickable but only had hover tooltips).
- Fix: toggling any settings preview reset the notch degradation to
  full width; when macOS had already hidden the item its frame became
  unusable and recovery never ran - the item vanished until restart
  (reproduced from the new app log). Display level now only resets
  when width-relevant options change, and an unusable frame after
  retries is treated as 'hidden behind the notch' and degrades.
- Stale credential wording in tooltips updated to the keychain flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…anel, stacked slim bar

- Stacked menu bar glyphs keep their natural aspect ratio (battery and
  plug symbols were squeezed into squares); same fix for the inline
  symbol attachments in the single-line display.
- History graph: the inner plot box (rounded fill + stroked border +
  full axis rectangle) collided with the outer card's rounded corners;
  now a subtle unbordered tint with only a baseline axis.
- Detached dashboard panel drops its 1px contour in window style (read
  as a dark rim against the wallpaper); the window shadow separates it.
- Slim bar adopts the two-line compact rendering when enabled (about
  half the length) and uses an xmark.circle.fill close button instead
  of a text glyph.
- Env-file test no longer depends on the process working directory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tle slim-bar glyph

- Stacked renderer gains a fixed bright palette for the always-dark
  slim bar (adaptive menu-bar colors resolved to their light-mode
  variants there and were unreadably dark) and a height parameter with
  font capping so the two rows cannot overlap at larger scales.
- Separate settings for the compact display in the menu bar and in the
  detached slim bar; menu bar compact display is now the default
  (information-dense and notch-safe out of the box).
- Slim bar shows the subtle white bolt glyph instead of the bright
  full-color app icon PNG.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Detached slim bar gets its own settings tab: independent metric
  selection (detachedBarMetrics, defaults to the menu bar choice until
  customized), compact toggle, lock, and scale moved there; hint that
  the bar is freely draggable.
- Bar position: relaxed clamping (only a 60pt grab area must stay on
  screen instead of hard edge pinning) plus debounced magnetic snapping
  to screen edges; unified 13pt font across all runs (arrow segments
  were 13.5pt and read as mixed sizes).
- Dashboard: hard 1px card borders removed - depth now comes from the
  tinted surfaces; graph grid lines slightly stronger in both modes;
  fixed a light rim around the graph card in dark mode (stale layer
  color behind the drawn gradient); updated-at label turns orange when
  data is overdue.
- Settings render snapshots follow the new tab order.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ng, full detached-bar customization

- History section rebuilt per UX review: range picker and legend are
  compact clickable chips inside the card (one object instead of three
  stacked control layers; legend chips replace the blue system
  checkboxes that double-signaled next to color dots); inner graph
  header removed (range is named twice above already); custom days
  field shows its unit ('14 Tage').
- Graph: optional fit-to-data (Einstellungen -> App -> Dashboard,
  default on) starts the time axis at the first available sample
  instead of showing mostly empty calendar range; tick steps and label
  format follow the fitted span; baseline axis drawn above the curves
  so zero-valued series no longer swallow it.
- Primary cards: value spans the full card width instead of inheriting
  the icon indent (cards no longer look lopsided).
- All symbol tinting is resolution-independent via a drawing-handler
  NSImage extension - the old lockFocus tinting rasterized at 1x and
  looked blurry on Retina, especially in the scaled slim bar.
- Slim bar text: removed the legacy 1.5pt black stroke and the doubled
  shadow that produced overlapping-looking glyphs on the now-opaque
  dark background.
- Detached bar: independent options for labels, symbols, flow arrows,
  and the app glyph (defaults follow the menu bar until customized).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…header space

- Range chips align to the section title's first baseline (centerY let
  the text baselines visibly drift); legend bullet is smaller with a
  slight baseline offset so it no longer lifts the chip line.
- Primary cards use the standard stat-tile layout: icon vertically
  centered, title and value sharing one left edge - the previous
  full-width value created three competing alignment edges.
- Graph no longer reserves 58pt for its removed inner header; plot sits
  directly under the legend chips.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ip text

Range chips sit top-left with the legend chips directly beneath on the
same leading edge (the baseline coupling to the section title had
pushed the title under the chips). Chips are a small NSButton subclass
with symmetric intrinsic padding - the previous whitespace-padding
trick lost its trailing spaces during rendering, leaving the text
off-center in the capsule. Section title removed; the card is
self-explanatory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… edge)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…both contexts, pixel-based tick collision

- The dashboard panel's hardcoded height broke Auto Layout in the menu
  context once the header grew (graph squeezed to nothing in the
  dropdown while the taller detached window still worked); the height
  now comes from fittingSize.
- History header: range chips sit baseline-aligned next to the Verlauf
  title in both docked and undocked views; both contexts covered by
  render snapshots (dashboard-window-*.png).
- Time labels skip regular ticks whose label would collide with the
  clamped 'Jetzt' label - the previous step-fraction buffer missed
  configurations where the edge label gets pulled left.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Editing '14 Tage' in place forced deleting the unit and mis-parsed
reordered input; the field is numeric with a separate 'Tage' label
that shows and hides with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tory spans

- Dashboard rebuilds itself completely on effective-appearance changes
  and a distributed AppleInterfaceThemeChanged observer rebuilds menu,
  detached windows, and title - individual layer refreshes kept missing
  frozen cgColors (white strips between rows after switching to dark).
- Theme.vivid: icon plates and detail values use the bright palette in
  dark mode (dark-tuned accents were hard to see); Theme.hud resolves
  slim-bar colors per appearance.
- Detached slim bar gains a light-mode appearance (light frosted glass,
  label-based colors) instead of being dark in both modes; render
  snapshots cover both.
- Custom range is click-driven (stepper chips + hours/days/weeks unit
  chips): text fields cannot take keyboard focus inside NSMenu, and the
  unit label no longer truncates. Stored value remains days.
- Demo mode always synthesizes history over the full selected span with
  day cycles - recorded demo samples only start at first use, so longer
  ranges looked empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n settings, true light slim bar

- History retention extended to 366 days with two tiers: 31 days at
  full resolution, older samples thinned to one per hour - year views
  without multi-megabyte files (test covers thinning and expiry).
  Months added as a custom-range unit.
- GraphControlHeader: one shared chip header (title, range chips,
  legend chips) used by the dashboard dropdown, the detached dashboard,
  and the large history window - the large window loses its segmented
  control, system checkboxes, bare day field, and duplicated inner
  header.
- Custom range duration (value + hours/days/weeks/months unit) moved to
  Settings -> App -> Dashboard where text input works; the dashboard
  keeps only the Eig. chip with a pointer tooltip.
- Slim bar light mode fixed for real: the .hudWindow glass material
  forces dark vibrancy onto all subviews, so HUD colors resolved dark
  on the light fill - .popover material is appearance-adaptive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…appearance

- Root cause of the recurring frozen-color bugs (white gaps between
  dashboard rows in dark mode): dynamicColor.cgColor outside a drawing
  context resolves against the process default appearance (aqua), not
  the app/window appearance - and building a view directly into an
  already-dark window fires no appearance-change event to correct it.
  All view building and chip styling now runs inside
  effectiveAppearance.performAsCurrentDrawingAppearance.
- NSMenu does not inherit NSApp.appearance: the dropdown stayed light
  when the app theme was forced dark; the status menu now adopts the
  app appearance explicitly (nil when following the system).
- Theme.hud uses the same bestMatch condition as the slim bar
  background so text and background can never disagree again (pastel
  colors on the light bar).
- Primary card icon plates use Theme.vivid like the detail rows (the
  battery circle had low contrast in dark mode).
- The Eig. chip shows the configured duration (e.g. '17 Tage') when the
  custom range is active.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…int)

Since the borderless pass the details container background served no
purpose; in dark mode its lighter gray showed through the 8pt gaps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ght)

The window shadow separates the bar from the desktop; the 1px border
only added a hard rim in both modes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Basti and others added 6 commits July 11, 2026 04:22
…is detached

Legacy behavior replaced the status item with a bare 'Online' dot once
the slim bar was undocked. Since both displays are independently
configurable now (own metrics, compact mode, labels/symbols/arrows),
the status item always renders its own configuration; the dead
detached-status title path is removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n-displacing refresh

- CenteredTextFieldCell had zero references since the custom-days field
  moved to Settings.
- Menu items say 'Abgedockte Leiste anzeigen/ausblenden' - the old
  'Menüleiste abdocken' wording described the era when the bar replaced
  the menu bar display.
- A running refresh no longer swaps the status item text for the
  spinner (the item visibly jumped in width every five minutes); the
  loading indicator only shows before the first values arrive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… single-instance, settings semantics

- MenuBarFormatter extracted from StatusController (~470 lines out;
  controller down to ~770): the whole title/stacked/symbol/color
  pipeline is now reusable. Dead code removed along the way
  (energyFlowArrow chain and its four color helpers were never called).
- Metric names centralized in MetricLocalization extensions - replaces
  four drifting switch blocks. A real String Catalog follows the system
  locale and would fight the in-app language toggle, so the pair model
  stays (documented).
- Settings: live preview of the menu bar readout (light+dark strips,
  demo data, same engine as the app) updates with every option change;
  closing with unsaved changes asks Save/Discard/Cancel; interval and
  custom-range fields validate via NumberFormatter.
- Dashboard: trend arrows vs the previous refresh on all watt/percent
  values (small thresholds to hide noise).
- Large history window: hover inspector with vertical guide and a value
  box (time, battery, solar, grid) following the cursor.
- Single-instance guard: a second launch activates the running instance
  and exits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tric cleanup

- Fensterebene wählbar für Slim-Bar und abgedocktes Dashboard (vorn/normal/hinten), live bei Vorschau/Speichern
- Slim-Bar-Schließen-Button nur noch bei Hover sichtbar (Platz bleibt reserviert)
- "Farbige Werte" und "Flussrichtung" getrennt schaltbar, je Leiste unabhängig; ohne Farben keine .solixRole-Tags, damit die Slim-Bar nicht doch koloriert
- Sammel-Metrik "Energiefluss" entfernt (zeigte dieselben Pfeile/Begriffe wie die Pfeil-Option doppelt); Migration schaltet Betroffenen die Pfeil-Option ein
- Kompaktanzeige respektiert Flussrichtung (↓/↑/←/→ vor den Werten) und zeigt Status
- Render-Tests: echtes Verlaufsfenster statt nackter Graph-View, Slim-Bar pro Appearance neu aufgebaut über Desktop-Verlauf, Trend-Pfeile im Dashboard-Render

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… Diagramm) inkl. Generator

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eerraum rechts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Basti and others added 18 commits July 11, 2026 07:53
…herigen Tag

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…0.4.1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ältere history.json-Dateien bleiben lesbar (Optionals decodieren als nil).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re Fensterebene

Wie Slim-Bar/Dashboard: onClose räumt den Besitzer auf, Zustand überlebt
Neustart, Fensterebene (vorn/normal/hinten) im App-Tab wählbar.
Frame merkt sich macOS per Autosave.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Prüft beim Start und danach täglich die GitHub-Releases. Eine neuere
Version erzeugt genau eine Mitteilung pro Version plus einen dauerhaften
Menüpunkt (Fallback ohne Mitteilungs-Erlaubnis). Abschaltbar im App-Tab.
package_app.sh signiert jetzt ad-hoc wie die CI, sonst zeigt macOS
lokal gebauten Bundles keine Mitteilungen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tion

solix_snapshot.py reicht solar_power_1..4 als pvWatts durch (Solarbank 2/3
melden je nach Modell 2 oder 4 MPPT-Kanäle; Feldnamen laut anker-solix-api,
mangels Hardware unverifiziert). Dashboard zeigt "PV-Eingänge 438 W · 204 W",
abschaltbar im App-Tab. Demo-Modus simuliert zwei Kanäle inkl. eines
Ausfallfensters (Minute 40–45) für die kommende Pro-PV-Warnung.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ro-PV-Eingang

Neue WarningEngine (reine Zustandsmaschine, 8 Szenario-Tests): Akku-Warnung
mit Hysterese (Schwelle+5), PV-Einbruch nur wenn zuvor erzeugt wurde (nachts
still), optionales Tagesfenster, toter MPPT-Kanal während Geschwister liefern.
Zustellung als macOS-Mitteilung plus ⚠-Einträge im Menü solange die Bedingung
anhält. Alles opt-in, neuer Einstellungs-Tab "Warnungen".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"Daten exportieren ..." öffnet einen Speichern-Dialog mit Format-Popup.
CSV: eine Zeile pro Sample (ISO8601-Zeitstempel, leere Zellen für fehlende
Werte, aktueller Snapshot als Abschlusszeile). JSON: hübsch formatiert mit
Quelle, Exportzeitpunkt und aktuellem Snapshot. Exportiert wird die History
der aktiven Datenquelle (bis 366 Tage).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sten

Die 3×3-Häkchen-Raster weichen sortierbaren Listen: Häkchen wählt aus,
Ziehen ordnet. Einzeilige und Kompaktansicht haben je Leiste eigene Listen;
die Kompakt-Liste folgt der einzeiligen, bis sie per Checkbox entkoppelt
wird (leeres Array = folgt, wie beim bestehenden abgedockt→angedockt-
Fallback). Reihenfolge wird beim Speichern nicht mehr auf die Standard-
Reihenfolge normalisiert. Leisten-Tabs zweispaltig (Liste links,
Darstellung rechts), Metrik-Tooltips zentral in MetricLocalization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
package_app.sh schreibt CFBundleShortVersionString aus der VERSION-Datei
und die Build-Nummer aus dem Commit-Zähler; CI verweigert Release-Tags,
die nicht zur VERSION passen. CHANGELOG 0.4.1/0.4.2 nachgetragen,
PLAN.md Phase 7 dokumentiert, Render-Test kennt den Warnungen-Tab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Dropdown-Graph nach Einstellungsänderung

Neue Optionen (je getrennt): PV-Kachel im Dashboard sowie PV-Wert in
Menüleiste und abgedockter Leiste zeigen die Eingänge einzeln
("438 · 204 W") statt der Summe — wirkt jeweils auf einzeilige und
Kompaktansicht; die separate Dashboard-Zeile von vorhin entfällt dafür.

Fix: Beim ersten Einblenden nach einer Einstellungsänderung baut sich das
Dropdown-Dashboard wegen des Appearance-Wechsels neu auf — jetzt mit
erzwungenem Layout-Pass und Höhen-Abgleich, und bei erzwungener
Appearance bekommt die View sie schon beim Bau (kein Neuaufbau nötig).
Vorher blieb der Graph gelegentlich unsichtbar bis zum zweiten Öffnen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…raph-Linien beim ersten Menü-Öffnen

PV-Anzeige als Popup statt Checkbox: Gesamtwert, Einzelwerte oder
Gesamt + Einzelwerte — getrennt für Dashboard (Beides = Summe in der
Kachel + Einzelwerte-Zeile), Menüleiste und abgedockte Leiste. Die
kurzlebigen Bool-Keys aus der Testphase werden als Fallback gelesen.

Fix (Ursache per App-Log gefunden): Die Einblende-Animation der
Graph-Linien lief im Default-Runloop-Modus, der während der
Menü-Anzeige pausiert — nach jedem Neuaufbau (Einstellungsänderung)
blieben die Linien beim ersten Öffnen unsichtbar. Timer jetzt in
.common-Modi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ng; Log protokolliert pvWatts

Der feste Ausfall in den Minuten 40-45 wirkte beim normalen Ausprobieren
wie ein Anzeigefehler ("Summe und 0", bis zu 5 Minuten stehend, weil das
Refresh-Intervall 300 s beträgt und die Einstellungs-Vorschau statische
Demo-Werte nutzt). Jetzt fällt Kanal 2 nur noch aus, wenn die Pro-PV-
Warnung eingeschaltet ist. Refresh-Logzeile enthält die Kanalwerte.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ählbar

Menü-Dashboard und abgedocktes Fenster nutzen dieselbe View, hatten aber
nur eine gemeinsame PV-Einstellung. Jetzt eigene Popups: "PV-Anzeige
(Menü)" und "PV-Anzeige (Fenster)"; das Fenster folgt dem Menü, bis es
explizit umgestellt wird.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s-Renders mit Text

Der Offscreen-Render der Settings-Tabs lieferte leere Panes (cacheDisplay
lässt bei Fenster-Inhalten Text und Hintergrund weg) — der Render-Test
geht jetzt über den PDF-Zeichenpfad und liefert vollständige Bilder.
Menüleisten- und Warnungen-Tab als neue Review-Assets veröffentlicht.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st)"

Pro-PV-Warnung hat jetzt zwei zuschaltbare Erkennungswege: Eingang tot
während die Geschwister erzeugen (bisher) und neu "Einbruch je
PV-Eingang" gegen die eigene jüngste Erzeugung — erkennt Defekte auch,
wenn mehrere Eingänge gleichzeitig ausfallen. Gleiche Meldung, einmal
pro Vorfall, Re-Arm bei Erholung.

Neue Datenquelle "Demo (Warnungs-Test)": geraffter Ablauf (Erzeugung →
Akku 16 % → Eingang 2 tot → kompletter Einbruch) mit 30-s-Abruf und
10-fach geraffter Zeit; Szenario startet bei Modus-Aktivierung mit
frischer Warn-Engine. Aktivierte Warnungen feuern real in ~1/2,5/4,5
Minuten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…I-Feinschliff

Direkter SOLIX-Zugriff:
- Neue Datenquelle "SOLIX-Konto (direkt)" mit gebündelter, portabler
  Python-Laufzeit (BundledSolixDataProvider); Zugangsdaten per stdin-JSON,
  Passwort weiterhin nur im Schlüsselbund. Auto-Migration vom Helfer-Befehl.
- Helfer cached Tages-/Gesamtstatistik (10/15 min, atomare 0600-Dateien),
  Zustand/Cache nur noch im Application-Support-Ordner.
- Release-Werkzeuge: prepare_solix_runtime.sh (gepinnte Laufzeit),
  verify_release.sh, package_app.sh bettet Laufzeit ein und strippt die
  Debug-Map; CI bereitet Laufzeit vor und prüft das Bundle.

Robustheit/Anzeige:
- Fehler-Backoff: Abrufabstand verdoppelt sich bei Fehlern (max 30 min),
  Reset bei Erfolg; Einmal-Timer statt festem Takt.
- Unsichtbare Fenster werden nach einem Abruf nicht mehr neu aufgebaut.

Verlaufsgraph:
- Optionale Glättung (Catmull-Rom, auf die Plotfläche geklemmt) und je Kurve
  wählbare Flächenfüllung (App → Dashboard).
- Demo-Akku als langsame Lade-/Entladekurve statt Minuten-Sägezahn.

Dashboard/Einstellungen:
- Kachelwerte skalieren auf die Breite (kein abgeschnittener Trend-Pfeil);
  drei/vier PV-Eingänge als 2×2-Raster auf zwei Zeilen.
- Fragezeichen-Knöpfe zeigen ausführliche Hilfetexte im Popover statt leerer
  Sprechblasen.

80 Tests, alle grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@itsab1989 itsab1989 changed the title Review-Fixes: Notch-Sichtbarkeit, portable Pfade, Keychain, Design-System, Tests + CI (Issue #3) SolixBar-Fork v0.4.3 — Notch-Fix, Design-System, Warnungen, direkter SOLIX-Modus, Graph-Glättung (Review aus #3) Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant