Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions docs/wiki/Admin-Hub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Admin-Hub – Die Werkzeuge

Spezifikation: `docs/design/feature-spec-admin-hub.md` · Milestone:
`docs/design/milestone-v0.7.2.md` · Implementiert in PR #12–#19.

Die Sidebar hat seit v0.7.2 eine Sektion **WERKZEUGE** mit vier Einträgen:

| Tool | Art | Screen |
|---|---|---|
| 🌐 Browser | Launch-Aktion (extern) | – |
| 📝 Quick Notes | Screen-Tool | `lib/layouts/tools/quick_notes.dart` |
| 📁 Dateimanager | Screen-Tool | `lib/layouts/tools/file_manager.dart` |
| 📊 Systemmonitor | Screen-Tool | `lib/layouts/tools/system_monitor.dart` |

---

## Browser (E1)

Klick startet den Browser als **detached Prozess** – die Hub-Section ändert
sich nicht. Fallback-Kette in `lib/services/app_launcher.dart`:

```
brave → brave-browser → xdg-open https://
```

Feedback: still bei Erfolg, Info-Snackbar beim xdg-open-Fallback,
Fehler-Snackbar wenn gar kein Browser gefunden wurde.

## Quick Notes (E2)

Markdown-/Plaintext-Notizen ohne die App zu verlassen.

- **Master-Detail:** Liste links (zuletzt geändert zuerst), Editor rechts
- **Autosave:** debounced 500 ms, kein Speichern-Button
- **Persistenz:** eine `.md` pro Notiz unter
`~/.local/share/linux-assistant/notes/` (respektiert `XDG_DATA_HOME`),
atomare Writes (tmp + rename – kein halber Stand bei Absturz)
- **Löschen:** destructive → Confirm-Dialog
- Titel wird aus der ersten nicht-leeren Zeile abgeleitet
- Service: `lib/services/notes_service.dart` (injizierbar:
`NotesService.test(dir)`)

Bewusst NICHT: Markdown-Preview, Cloud-Sync (v2, Service ist Interface).

## Dateimanager (E4)

Eingebetteter Datei-Browser – kein externer Prozess für die Navigation.

- **Schnellzugriff:** Home, `/`, `/mnt`, Downloads, Desktop (nur existierende)
- **Breadcrumb** + Up-Button + Hidden-Files-Toggle + Refresh
- Zeilen: Icon (Ordner = Akzent), Name, Größe (nur Dateien),
Änderungsdatum, Permissions (`FileStat.modeString`)
- **Öffnen:** `xdg-open` detached
- **Löschen:** Confirm-Dialog **mit vollem Pfad**; Verzeichnisse rekursiv;
Symlinks werden als Links gelöscht (Ziel bleibt)
- **Sicherheit:**
- Symlinks werden nie navigiert (Loop-Gefahr) – Klick öffnet extern
- `/proc`, `/sys`, `/dev`: Warn-Banner, Einträge ausgegraut, Delete
deaktiviert (Policy in `FileBrowserService.isProtected`)
- Größen nur für Dateien beim Listing (Performance)

Service: `lib/services/file_browser_service.dart` (reines dart:io).

Bewusst NICHT: Copy/Move/Rename, Thumbnails, Drag&Drop (v2).

## Systemmonitor (E3)

Der große Bruder der Dashboard-Kacheln: 1-s-Live, pausierbar.

- **Kacheln (HubGrid):** CPU (Sparkline + Per-Core-Balken), RAM (Badge +
Swap), GPU (nur wenn `nvidia-smi` vorhanden), Disks (Worst + Top-3-Balken),
Netzwerk (↓/↑-Raten + Sparkline), Thermal (heißeste Zone + Top-3)
- **Prozess-Tabelle:** Suche, sortierbare Spalten (PID/CPU/RAM/Name),
Beenden-Dialog (Abbrechen / SIGTERM / SIGKILL)
- **Control-Bar:** HaloDot (Live/Pausiert), Pause/Resume, Refresh
- **Sampling-Architektur:** `Ticker`-getrieben statt `Timer` – das
`TickerMode` des Hubs stoppt das Polling automatisch, wenn der Screen
off-screen ist. `/proc`-Reads ohne Fork; einzige Forks pro Tick: `ps` +
`df`; `nvidia-smi` nur alle 5 s
- Parser alle rein & fixture-getestet: `parseProcStat`, `cpuUsageDelta`,
`parseMemInfo`, `parseNetDev`, `parseThermal`, `parseNvidiaSmi`, `parsePs`

Service: `lib/services/system_monitor_service.dart`.

---

## Eigenes Werkzeug hinzufügen

Siehe [[Architecture]] → „Screen-Tool-Pattern“ (4 Edits in `hub_shell.dart`).
Konventionen: Hermes-Tokens statt harter Farben, Service injizierbar,
Parser rein, destructive Aktionen mit Confirm.
101 changes: 101 additions & 0 deletions docs/wiki/Architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Architektur

## Schichten-Überblick

```
lib/
├── main.dart Einstieg, Theme, Distro-Farben
├── main_search_loader.dart Lädt Aktionskatalog → öffnet Hub
├── layouts/ Screens
│ ├── hub/ HubShell, DashboardSection, StorageSection, HubGrid
│ ├── tools/ QuickNotesPage, FileManagerPage, SystemMonitorPage
│ ├── main_screen/ MainSearch (Launcher-Suche)
│ ├── linux_health/, security_check/, settings/, … (bestehende Screens)
│ ├── hermes_tokens.dart Hermes Design-Tokens (Fork)
│ └── mint_y.dart / mint_y_tokens.dart Mint-Y-Komponenten + Tokens
├── services/ Logik ohne UI
│ ├── app_launcher.dart E1: Browser-Fallback-Kette
│ ├── notes_service.dart E2: Notizen (atomar, XDG)
│ ├── file_browser_service.dart E4: Verzeichnisse (Protected-Policy)
│ ├── system_monitor_service.dart E3: Parser + Sampling
│ ├── system_stats_service.dart Geteilter 3-s-Poller
│ ├── linux.dart, config_handler.dart, action_entry_list_service.dart, …
├── linux/ System-Zugriff: linux_system, linux_process,
│ linux_filesystem (df-Parser)
├── widgets/hermes/ Hermes-Widgets (Card, StatTile, Sparkline,
│ Badge, HaloDot, NavItem, CopyCommand)
├── models/, enums/, content/, helpers/, l10n/
additional/python/ Helferskripte (Umgebung, Apps, Bookmarks, …)
```

## Die Hub-Shell (zentrales Stück)

`lib/layouts/hub/hub_shell.dart` – persistenter Rahmen: Sidebar, Top-Bar,
Content-Fläche.

**Kernprinzipien:**

1. **Swappen statt Pushen.** Sektionen ersetzen den Content im Frame; der
Navigator wächst nicht. Begründung: Die App-Konvention „zurück = Ziel
erneut pushen“ würde die History unbegrenzt wachsen lassen.
2. **Lazy + Keep-Alive.** Jeder Bereich wird beim ersten Besuch gebaut und
bleibt via `IndexedStack` im Baum (`Map<Object, Widget> _built`).
Scroll-Positionen, Selektionen und Editor-Inhalte überleben Wechsel.
3. **TickerMode pro Bereich.** Animationen/Ticker inaktiver Bereiche
stoppen automatisch – der Systemmonitor nutzt das für sein 1-s-Sampling.
4. **Zwei Navigations-Typen:** `HubSection` (Hauptbereiche) und `HubTool`
(Werkzeuge). Tools sind entweder Launch-Aktionen (`browser` → externer
Prozess, kein Sectionswechsel) oder Screen-Tools (`quickNotes`,
`fileManager`, `systemMonitor` → rendern im Frame, getrackt in
`_screenTool`).

### Screen-Tool-Pattern (neues Werkzeug hinzufügen)

Vier kleine Edits in `hub_shell.dart`:

1. Wert in `enum HubTool` aufnehmen
2. Case in `_iconOfTool` + `_titleOfTool`
3. Case in `_onToolTap` (Screen → `_selectTool`, extern → Launch)
4. Case in `_contentFor` (Screen-Widget zurückgeben)

## Stats-Polling (Performance)

`SystemStatsService` ist ein geteilter 3-s-Poller (CPU, RAM, Disks, Prozesse,
Uptime). Polling läuft nur wenn **alle drei** Bedingungen gelten:

- mindestens ein Subscriber (`acquire()`),
- die sichtbare Section nutzt Stats (`setSectionActive` – Dashboard,
Speicher, Gesundheit, Suche ja; Sicherheit und Tool-Screens nein),
- das Fenster ist sichtbar (`setWindowVisible` via WindowListener +
WidgetsBindingObserver – zwei Signale, weil keines allein auf jedem
Linux-Desktop zuverlässig feuert).

Messung aus Commit `d221d0e`: 4.4 forks/s beim Pollen, 0.10/s idle.

Der Systemmonitor nutzt bewusst **nicht** diesen Service: Er sampled 1-s
über einen `Ticker` (Screen-getrieben) und liest `/proc` direkt.

## Python-Helferskripte

`additional/python/` wird ins Bundle kopiert. Wichtig:
`get_environment.py` gibt zeilenindizierte Werte aus – die Dart-Seite liest
per Zeilenindex, also **neue Felder nur hinten anhängen** (ID/ID_LIKE kamen
so dazu). Unbekannte Distros fallen über `ID_LIKE` auf ihre Familie zurück
(`Linux.distroFromIdLike`).

## Konfiguration & Persistenz

- `ConfigHandler` – JSON-Config unter `~/.config/linux-assistant/`
- Quick Notes – `~/.local/share/linux-assistant/notes/*.md` (XDG, atomare
Writes: tmp + rename)
- Enum-Werte aus der Config fallen bei unbekannten Einträgen auf Defaults
zurück statt zu werfen (`getEnumFromString`, `getDektopEnumOfString`)

## L10n

`flutter gen-l10n` aus `lib/l10n/*.arb` (de/en). Übergangsweise nutzt die
Werkzeuge-Sektion einen `_tr()`-Helper – Ablösung ist in
`docs/design/admin-hub-followups.md` §2 geplant.

Weiter: [[Admin-Hub]] für die Werkzeuge im Detail, [[Design-System]] für
die visuelle Sprache.
68 changes: 68 additions & 0 deletions docs/wiki/Contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Contributing

## Workflow

1. **Spec zuerst** bei größeren Features (Vorbild:
`docs/design/feature-spec-admin-hub.md`): Verhalten, Implementierung,
Design-Tokens, Scope-Grenzen („bewusst NICHT“), Aufwand/Reihenfolge.
2. **Kleine PRs pro Feature** (E1–E4 waren je ein PR). Jeder PR:
Branch von aktuellem `main`, aussagekräftiger Titel
(`feat(scope): …`, `fix(test): …`, `docs: …`), Beschreibung mit
Verifikations-Schritten.
3. **Merge-Commits** (kein Squash) – die Historie bleibt nachvollziehbar.
4. **Branches nach Merge löschen** (Einzeiler in
`docs/design/admin-hub-followups.md` §4).

> Hinweis: Issues und GitHub-Milestones sind in diesem Repo deaktiviert.
> Tracking passiert als versionierte Doku unter `docs/design/`
> (z. B. `admin-hub-followups.md`, `milestone-v0.7.2.md`).

## Code-Konventionen

- **Tokens statt Hardcodes:** `HermesTokens.of(context)` / `context.mintY`
(nach PR B). Keine neuen `Colors.*`/Hex-Werte in Screens. Bestehende
Verstöße: `docs/design/design-audit-inconsistencies.md`.
- **Screens swappen, nicht pushen:** Neue Hub-Bereiche folgen dem
Screen-Tool-Pattern ([[Architecture]]). Kein `Navigator.push` für
Hub-interne Navigation.
- **Ressourcen-Disziplin:** Kein `Timer` in `build()`; Futures einmal in
`initState` starten; `mounted` nach jedem `await`; Controller/Timer in
`dispose()` aufräumen. Diese Klasse von Bugs hat `d221d0e` aufgeräumt –
nicht wieder einführen.
- **Polling braucht Gating:** Siehe `SystemStatsService`
(Subscriber + Section + Fenster). Screen-eigenes Sampling: `Ticker`
statt `Timer` (TickerMode-Synergien).
- **Shell-outs sparsam:** `/proc` & Co. direkt lesen (File-Read statt
`cat`-Fork). Forks auf dem Hot Path dokumentieren (vgl. Systemmonitor:
`ps` + `df` pro Tick, `nvidia-smi` nur alle 5 s).
- **Destructive Aktionen:** Confirm-Dialog mit dem konkreten Objekt
(Name/voller Pfad), rote Aktion, Guard-Tests im Service.
- **Services testbar:** Injizierbarer Konstruktor; Parser rein & statisch
mit String-Fixtures.
- **Defensive Defaults:** Unbekannte Config-Werte fallen auf Defaults
zurück statt zu werfen.

## Tests

Neue Services/Screens kommen mit Tests ([[Testing]]). Erwartungswerte für
Rechenlogik per Rechnung verifizieren, nicht schätzen.

## L10n

Neue UI-Strings → Keys in `lib/l10n/app_en.arb` + `app_de.arb`, dann
`flutter gen-l10n`. Aktuell gibt es einen `_tr()`-Übergangs-Helper in der
Werkzeuge-Sektion (Ablösung: `admin-hub-followups.md` §2) – bitte keine
neuen `_tr()`-Stellen mehr hinzufügen.

## Python-Helfer

`additional/python/get_environment.py` wird **zeilenindiziert** gelesen:
neue Ausgaben nur hinten anhängen, nie dazwischen einfügen.

## Review-Checkliste für PRs

- [ ] `flutter test` lokal grün
- [ ] Keine neuen Hardcode-Farben
- [ ] Destructive Aktionen mit Confirm + Tests
- [ ] Polling/Timer: Gating bzw. dispose vorhanden
- [ ] Docs aktualisiert (Spec/Wiki/Followups), wenn Verhalten sich ändert
70 changes: 70 additions & 0 deletions docs/wiki/Design-System.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Design-System

Referenz: `docs/design/linux-assistant-design-system.md` · Audit:
`docs/design/design-audit-*.md`

## Zwei Ebenen

### Mint-Y (Upstream-Basis)

`lib/layouts/mint_y.dart` + `lib/layouts/mint_y_tokens.dart`: Das klassische
Komponenten-Set der App (MintYPage, MintYButton, MintYTable, …) plus Token-
Definitionen. Distro-Akzente über `MintYAccent` (mint, debian, opensuse,
kde_neon, lmde, zorin, …), gesetzt in `main.dart` anhand der erkannten
Distribution.

### Hermes (Fork-Layer)

`lib/layouts/hermes_tokens.dart` + `lib/widgets/hermes/`: Die visuelle
Sprache des Hubs. Kernideen:

- **Elevation ohne Schatten:** 1-px-Border + Tint statt Drop-Shadow
- **Tint-Triade:** ~8-10 % Hintergrund, ~28 % Border, Vollton als Text
(implementiert in `hermesToneColors`)
- **Akzent-Spine:** 2-px-Balken links markiert Auswahl/aktive Karte
- **Opacity als Hierarchie-Hebel** für Metadaten (kein zweiter Farbton)

## Token-Überblick

| Kategorie | Beispiele |
|---|---|
| Flächen | `t.bg`, `t.surface`, `t.sidebar`, `t.surfaceSubtleHover` |
| Text | `t.strong`, `t.text`, `t.muted`, `t.onAccent` |
| Akzent | `t.accent`, `t.accentHover`, `t.accentBg`, `t.accentText` |
| Semantik | `t.success`, `t.warning`, `t.error`, `t.info` |
| Borders | `t.border`, `t.borderSubtle` |
| Code | `t.codeBg`, `t.codeText`, `HermesTokens.fontMono` |
| Abstände | `HermesTokens.space1…space4`, `radiusSm/Md/Pill`, `spineWidth` |

Zugriff im Code: `final t = HermesTokens.of(context);`

## Widget-Katalog (Hermes)

| Widget | Zweck |
|---|---|
| `HermesCard` | Basis-Fläche (optional `spineColor`, `onTap`) |
| `HermesSectionHeader` | Uppercase-Label + Trennlinie über Kartengruppen |
| `HermesStatTile` | Label + großer Wert + Badge + Visual + Footer |
| `HermesMetaRow` | Kompakte `label — value`-Zeile (tabular figures) |
| `HermesSparkline` | CustomPainter-Linienchart (≤ 60 Punkte, kein fl_chart) |
| `HermesBadge` | Pill mit Tint + optionalem Icon, `dense`-Variante |
| `HermesHaloDot` | 7-px-Statuspunkt mit Halo |
| `HermesNavItem` | Sidebar-Zeile (Hover, selected, collapsed-Rail) |
| `HermesCopyCommand` | Mono-Kommandozeile mit Copy-Button (zeigt, führt nie aus) |

## Regeln (aus dem Design-Audit)

1. **Keine hartcodierten Farben in neuen Screens** – immer Tokens. Bekannte
Alt-Verstöße sind in `design-audit-inconsistencies.md` priorisiert
(z. B. `Colors.grey` Info-Box, `Colors.black54` in power_mode).
2. **Destructive = Confirm-Dialog** mit konkretem Objekt (Name/Pfad), rote
Aktion (`statusDanger`/`t.error`).
3. **Neue Screens bekommen Goldens** – Setup-Stand siehe [[Testing]].
4. Sidebar-Labels: klein, muted, uppercase, letter-spaced (Muster:
„EINGEBUNDENE DATENTRÄGER“).

## Laufende Migration

PR B (#10) migriert Dashboard-Widgets auf die `MintYColors`-ThemeExtension.
Sonderfall aus dem Audit: der Dark-Mode-Mutations-Hack in
`single_bar_chart.dart` muss **ersetzt**, nicht ergänzt werden.
Loading
Loading