# aura-view: Vorschau der AURA-Dateien

<p align="center"><img src="images/aura-logo.svg" alt="AURA" width="320"></p>

`aura-view` zeigt Dialoge, Screens, Komponenten und `preview`-Blöcke aus `.aura`-Dateien mit dem dynamischen Loader. Das native Werkzeug nutzt `BasicHost`: grauer Hintergrund, Screens auf der ganzen Fläche, Komponenten mit Rand und Dialoge mittig auf einem weißen Rahmen. Theme, Bilder und Schriften lassen sich über Optionen laden.

Argumente erhalten Platzhalter, sofern eine Preview keine Werte vorgibt (`"test-<name>"`, `0`, `false`, `#808080`); Datensätze je Feld und Listen von Datensätzen einen Eintrag. Bei Fehlern bleibt der letzte fehlerfreie Stand sichtbar; Diagnosen nennen Datei, Zeile und Spalte. Die Vorschau führt keinen Anwendungsablauf aus.

## Aufbau: Kern und Host

| Teil | Ort | Aufgabe |
|---|---|---|
| Kern | `libs/aura-preview` (`aura::preview`) | Schattenverzeichnis, Auswahl, Schalter, Bauen über den Loader, Tippen und Prüfen, PNG, Galerie, Server-Protokoll, Fenster, `run()` mit allen Optionen |
| Host | `aura/preview/host.h` | was zur App gehört: Kontext, Gerät(e), Hintergrund, Fläche für Screens und Komponenten, Vordergrund, Rahmen für Dialoge, Optionen und Zustand für den Server, fehlende Übersetzungen |
| `BasicHost` | `libs/aura-preview` | ohne App: grauer Hintergrund, Screens auf der ganzen Fläche, Komponenten mit Rand, Dialoge mittig auf Weiß |

Ein eigenes Vorschauwerkzeug kann `Host` implementieren und seine Factory an `run()` übergeben:

```cpp
int main(int argc, char** argv)
{
	return aura::preview::run(argc, argv, MyHost::create,
		{.name = "my-view"});
}
```

## Aufruf

```bash
build/dev/tools/aura-view/aura-view examples/hello
```

| Option | Wirkung |
|---|---|
| `<dir>` | Verzeichnis mit `.aura`-Dateien, einschließlich Unterordnern. |
| `--dialog <name>` | anzuzeigender Dialog oder Screen; sonst der erste |
| *(ohne Modus)* | Fenster. Gespeicherte Änderungen erscheinen nach höchstens einer halben Sekunde. Klicks lösen die Signale aus, die ins Log gehen. Fehler gehen nach stderr. |
| `--render <file.png>` | rendert einmal und beendet sich (Exit-Code 2 bei Fehlern in den Dateien) |
| `--render-previews <dir> [--compare <refdir>]` | rendert jede Preview als `<dir>/<Gerät>/<Ziel>-<Titel>.png`; mit `--compare` Vergleich mit `<refdir>/<Gerät>`: `DIFF`, `NEU` (keine Referenz) und `WEG` (Referenz ohne Preview) ergeben Exit-Code 1 |
| `--list-devices` | Geräte des Hosts; `BasicHost` bietet ein Gerät namens `default`. |
| `--lint` | Unbekannte `theme.`-Werte: Fehler, Exit-Code 1. Fehlende Übersetzungen: Warnungen, sofern der Host sie meldet. |
| `--server` | Render-Server für die VS-Code-Vorschau (siehe unten) |
| `--device <b>x<h>`, `--assets <dir>`, `--fonts <dir>`, `--theme <datei.json>` | `BasicHost`: Bildschirmgröße (Standard 1280x800), Bilder und Dateien von `source:`, Schriften, `theme.<name>` als JSON (`"#rrggbb"` ist eine Farbe, Zahlen und `true`/`false` als solche, sonst Text) |

## Pixelvergleich

```bash
build/dev/tools/aura-view/aura-view examples/hello --render-previews /tmp/aura-previews
build/dev/tools/aura-view/aura-view examples/hello --render-previews /tmp/aura-previews --compare references
```

Die Ausgabe liegt unter `default/`. Nur deklarierte Previews werden gerendert; Animationen stehen am Anfang. Nachträglich vom C++-Programm gesetzte Werte fehlen. Referenzbilder nach Änderungen visuell prüfen.

## Ungespeicherte Inhalte

`aura-view` liest nicht direkt aus `<dir>`, sondern aus einer Schattenkopie in `/tmp/aura-view-<pid>`.

- **Inhalt:** Die Kopie besteht aus den Dateien von der Platte. Hat der Editor ungespeicherte Inhalte geschickt, ersetzen diese die jeweilige Datei.
- **Schreiben:** Nur geänderte Dateien werden neu geschrieben.
- **Fehlermeldungen:** Pfade in den Meldungen des Loaders werden auf `<dir>` zurückgerechnet.

So braucht der Loader keine eigene Schnittstelle für Editor-Inhalte.

## Server-Protokoll

Über stdin/stdout läuft JSON, eine Zeile pro Anfrage und eine Zeile pro Antwort, in derselben Reihenfolge. Das Log geht nach stderr.

| Anfrage | Wirkung |
|---|---|
| `{"cmd":"update","file":"/abs/x.aura","text":"…"}` | ungespeicherter Inhalt einer Datei |
| `{"cmd":"revert","file":"/abs/x.aura"}` | wieder die Datei von der Platte (nach Speichern oder Schließen) |
| `{"cmd":"refresh"}` | Dateien auf der Platte haben sich geändert |
| `{"cmd":"select","name":"Hello"}` | anderer Dialog, Screen, Komponente oder Preview (`"Hello: Sample"`) |
| `{"cmd":"set","name":"view","value":"thanks"}` | Zustand, `bool`-, `string`-, `int`- oder `real`-Property des gezeigten Elements, live |
| `{"cmd":"options","largeText":true,"contrast":false,"language":"EN","scale":1}` | Darstellung; `scale` skaliert das PNG |
| `{"cmd":"press","x":160,"y":733,"down":true}` | Finger auf (gedrückter Zustand) bzw. ab (`false`, Tap auf demselben Node) |
| `{"cmd":"move","x":160,"y":600}` | Finger bewegt sich, während er gedrückt ist: `onDrag`, ab 10 px zieht er einen `Scroll` (wie in der App, `aura::ui::InputDriver`) |
| `{"cmd":"tap","x":160,"y":733}` | Tap |
| `{"cmd":"render"}` | PNG auch ohne Änderung |
| `{"cmd":"gallery","file":"/abs/x.aura","scale":0.5}` | `gallery`: die Previews der Datei als PNG (`name`, `title`, `png`); Komponenten auf ihre Fläche zugeschnitten und in Originalgröße, Dialoge und Screens mit `scale` |
| `{"cmd":"inspect","x":160,"y":733}` | die Elemente an dem Punkt, innerstes zuerst: `inspect` mit `file`, `line`, `column`, `type`, `id`, `name` und Rechteck (`x`, `y`, `width`, `height`) |
| `{"cmd":"frame","ms":40}` | Animationen um `ms` weiter (höchstens 1000); PNG, wenn eine lief |

**Felder in jeder Anfrage:** Ein optionales `"id"` kommt in der Antwort zurück.

**Inhalt jeder Antwort:**

- **Auswahl:** `roots` mit `name`, `type` (`Dialog`, `Screen`, `Component`, `Preview`), `target` (das gezeigte Element), `file`, `line` und `signals`, dazu `current`.
- **Host-Zustand:** Zusätzliche Antwortfelder kommen aus `Host::state()`; `BasicHost` liefert keine Geräteauswahl oder Sprachoptionen.
- **Schalter:** `controls` des gezeigten Elements: `{name, kind: "state", values, value}`, `{name, kind: "bool", value}` bzw. `kind` `"text"`, `"int"`, `"real"`.
- **Theme:** `theme`: jeder `theme.<name>` des Hosts (`Host::themeValues()`) mit seiner Art (`color`, `string`, `bool`, `number`) für die Vervollständigung; `themeColors`: die Farben als `#aarrggbb` (für die Farbfelder im Editor). Gesetzte Werte gelten je Element, bis `aura-view` endet.
- **Darstellung:** `width`, `height`. Host-spezifische Optionen gehen über `Host::setOptions()`; `BasicHost` implementiert keine Sprach- oder Barrierefreiheitsoptionen.
- **Fehler und Signale:** `diagnostics` mit `file`, `line`, `column` und `message`. `signals` enthält die seit der letzten Antwort ausgelösten Signale mit Namen und Argumenten als AURA-Literale. Gibt es `error`, war die Anfrage selbst fehlerhaft.
- **Bild:** `png` als Base64, wenn sich das Bild geändert hat.
- **Animationen:** `animating` ist `true`, solange eine Animation läuft (`spin`, `pressSink`, Ripple) oder ein `Scroll` nach dem Ziehen nachläuft. Die Zeit vergeht im Server nur mit `frame`; ohne `frame` stehen die Animationen.

Die erste Antwort kommt beim Start ohne Anfrage (`id` ist `null`).

## VS Code

Die Erweiterung `tools/aura-vscode` (ab 0.3.0, Animationen ab 0.4.0, Zustände und Previews ab 0.10.0, Geräte und Seitenleiste ab 0.12.0, Preview-Dropdown und „State …“ ab 0.13.0, Inspektor ab 0.14.0, Werte, Galerie, Farben, Definition und Umbenennen ab 0.15.0) startet `aura-view --server` für `aura.preview.directory` (Standard `app/ui`), wenn die aktive `.aura`-Datei darunter liegt, sonst für ihren eigenen Ordner.

Öffnen: „AURA: Vorschau öffnen“, der Vorschau-Button in der Titelleiste des Editors oder `Ctrl+K V`.

- **Live:** Beim Tippen (nach `aura.preview.delay`, Standard 150 ms) gehen die ungespeicherten Inhalte an den Server. Speichern oder Schließen schaltet zurück auf die Platte, und Änderungen auf der Platte lösen `refresh` aus.
- **Auswahl:** Die Vorschau zeigt den Dialog, die Komponente oder die Preview, in der der Cursor steht („Cursor folgen“). Wer in der Auswahlliste etwas anderes wählt, schaltet das Folgen ab. Öffnen oder Wechseln in eine andere `.aura`-Datei schaltet es wieder ein, liegt die Datei in einem anderen Baum, startet `aura-view` dafür neu. „Quelle“ springt zur Definition.
- **Fehler:** Fehler erscheinen als Diagnose im Editor und im Problems-Panel. Die Vorschau zeigt dann den letzten fehlerfreien Stand mit rotem Rand.
- **Werte:** Text- und Zahl-Properties des gezeigten Elements stehen im Menü „Werte“ und ändern sich beim Tippen (nach 250 ms).
- **Galerie:** „Galerie“ zeigt alle Previews der Datei des gezeigten Elements als Kacheln, Komponenten zugeschnitten. Ein Klick zeigt die Preview. Die Kacheln folgen Änderungen an den Dateien und den Optionen.
- **Farben im Editor:** Farben wie `#c3000f` und `#80ffffff` haben ein Farbfeld und den Farbwähler. `theme.mainColor` usw. zeigt ein Feld mit dem Wert aus der laufenden Vorschau (aus dem Host-Theme), der Hover nennt ihn.
- **Gehe zu Definition (F12) und Umbenennen (F2):** Komponenten, Datensätze, Dialoge und Screens im ganzen UI-Baum, IDs in ihrer Wurzel, Properties, Zustände und Signale der Wurzel; auch `label:` an einer Instanz oder `view:` in einer Preview führt zur Deklaration, `line.description` oder `row.tiles` (auch über `repeat`-Variablen) zum Feld des Datensatzes. Umbenennen geht für Komponenten, Datensätze, Dialoge, Screens und IDs; Vorkommen im C++-Code (`views::Name`, `buildName`, `NameArgs`, `->id`) werden gemeldet, nicht geändert.
- **Inspektor:** Mit gedrückter Strg-Taste (Cmd) zeigt die Vorschau das Element unter der Maus mit Rahmen, Typ, ID, Größe und Quelle. Strg+Klick springt zu seiner Stelle in der `.aura`-Datei, bevorzugt in der Datei des gezeigten Elements (eine Komponenten-Instanz dort statt des Inneren der Komponente); eine gezeigte Preview bleibt dabei stehen. Die Herkunft merkt sich der Loader an jedem Knoten (`Node::origin`, nur im dynamischen Modus).
- **Klicks:** Maus gedrückt heißt Finger auf, also gedrückter Zustand. Loslassen ist der Tap. Ausgelöste Signale stehen unter dem Bild.
- **Zustände:** Unter der Leiste stehen die Zustände (Auswahlliste) und `bool`-Properties (Häkchen) des gezeigten Elements; ein Wechsel gilt sofort, ohne Neuaufbau.
- **Geräte und Optionen:** Geräteauswahl, Sprache und Barrierefreiheit benötigen einen eigenen Host. `BasicHost` nimmt seine Größe über `--device` beim Start entgegen.
- **Previews:** Hat das gezeigte Element Previews, wählt man sie im Dropdown „Preview“ neben den Zuständen („Standard“ = mit Platzhaltern). Die Zustände heißen dort „State view“ usw.: Sie schalten einen Wert live um, wie die App; eine Preview setzt einen festen Satz Werte. Die Auswahlliste enthält nur Dialoge, Screens und Komponenten.
- **Optionen:** „Großer Text“ und „Hoher Kontrast“ im Menü „Barrierefreiheit“ (es nennt, was an ist), Sprache und Zoom (Einpassen, 50–200 %, Strg + Mausrad).
- **Seitenleiste:** Das AURA-Icon in der Aktivitätsleiste öffnet die Einstellungen der Vorschau (Gerät, Barrierefreiheit, Sprache, Cursor folgen, Animationen, Neustart).
- **Animationen:** Mit „Abspielen“ fordert die Vorschau Bilder an, solange der Server `animating` meldet: höchstens alle 33 ms, eins nach dem anderen, mit der real vergangenen Zeit (höchstens 100 ms je Bild). Ohne laufende Animation kostet das nichts. „Pause“ hält die Zeit an, auch für `pressSink` beim Klicken. Die Wahl gilt für alle Vorschauen und bleibt erhalten.
- **Neustart:** startet `aura-view` neu, z. B. nach einem Build. Ist der Server abgestürzt, sagt die Vorschau das. Die Ausgabe steht im Kanal „AURA Vorschau“.

Konfiguration für ein natives AURA-Workspace (`settings.json`):

```json
{
  "aura.preview.directory": "${workspaceFolder}/examples/hello",
  "aura.preview.command": "${workspaceFolder}/build/dev/tools/aura-view/aura-view",
  "aura.preview.env": {},
  "aura.preview.args": [],
  "aura.preview.delay": 150
}
```

## Grenzen

- **Zustand der App:** Was die App nach dem Aufbau über IDs setzt (LEDs, markierte Reiter, von C++ gebaute Zeilen und Zellen), fehlt.
- **Animationen:** Es laufen nur die Animationen, die in AURA stehen (`pressSink`, `spin`, `Rive`), nicht die der App (Video, Flyouts). `--render` zeigt den Startzustand.
- **Hintergrund:** Hinter Dialogen liegt der einfache Hintergrund, nicht der Screen, über dem der Dialog in der App öffnet.

### Interaktive Property-Signale

Die Vorschau führt nicht das C++-Programm aus. Ein Signal nach dem Muster
`countChanged(int value)` übernimmt dort seinen einzigen Parameter automatisch in
die mutable Property `count`. Namen und Werttypen müssen übereinstimmen; bei
Zuständen sind nur deklarierte Werte erlaubt. Andere Signale werden wie bisher
angezeigt. Der Wert bleibt bei einem Vorschau-Neuaufbau erhalten.

Inline-Handler wie `onTap: { state.count += 1; }` laufen in Programm, Loader und Vorschau; siehe [Inline-Skripte](inline-scripts.md).
