# Scanner v2 - Funktionsumfang

Gepflegte Liste dessen, was der neue Scanner-Dialog (`Libs/Scanner/V2/`)
tatsächlich kann. Stand der aktuellen Implementierung.

> Abgrenzung: [DESIGN.md](DESIGN.md) = Entscheidungen und Stolperfallen,
> diese Datei = reine Funktionsliste. Bei Änderungen am Dialog hier mitziehen.

## Geräte & Erkennung

- Erkennung von **USB- und Netzwerk-Scannern** über `ICDeviceBrowser`
  (wiederverwendeter `hxScannerManager`). Netzwerk-/AirScan-Geräte kommen über
  Apples ICA-Treiber automatisch dazu - kein eigener Protokollcode.
- **Live-Aktualisierung** der Geräteliste beim An- und Abstecken.
- **Auto-Auswahl bei genau einem Scanner**: Ist nur ein Gerät vorhanden und noch
  nichts gewählt, wird es automatisch verbunden - kein Klick nötig.
- **Geräte-Dropdown** oben im Dialog (keine Seitenleiste): zeigt das aktive Gerät
  und erlaubt das Wechseln. So ist immer klar, von welchem Scanner gescannt wird -
  auch bei nur einem (auto-gewählten) Gerät.
- Platzhalter, wenn keine Scanner gefunden wurden bzw. noch keiner gewählt ist.

## Scan-Quellen

- **Flachbett**, **Dokumenteneinzug** und **Durchlichteinheit** - je nachdem,
  was das Gerät meldet.
- Quellenauswahl wird nur angezeigt, wenn das Gerät mehr als eine bietet.

## Kompakt- und Detail-Ansicht

Der Dialog hat zwei Zustände, umgeschaltet über die **"Details"-Schaltfläche**
(rechts in der Geräte-Zeile, mit Auf-/Zu-Dreieck):

- **Kompakt** zeigt nur das Nötigste: Geräte-Dropdown, eine zentrierte
  Zusammenfassung, wie gescannt wird (Auflösung, Farbmodus, ggf. Quelle,
  Bereichs-/Papiername, Duplex), die Anhängen-Checkbox und den großen Scan-Knopf.
  Wiederkehrende Nutzer scannen so direkt durch (Progressive Disclosure).
- **Detail** zeigt links die Vorschau mit Zuschnitt, rechts eine
  Eigenschaften-Spalte als Formular (rechtsbündige Labels): zuoberst die
  Anhängen-Checkbox, darunter Auflösung, Farbmodus, Quelle, Duplex,
  Bereich/Papierformat und die numerischen Zuschnittsfelder.

Verhalten:

- **Erstöffnung ausgeklappt**: Beim allerersten Start ist die Detailansicht aktiv;
  danach folgt der Dialog der zuletzt gewählten Ansicht (`detailsExpanded`, sticky).
- **Vorschau nur auf Anforderung**: Eine Vorschau (Overview) wird ausschließlich
  per "Vorschau"-Knopf ausgelöst, nie automatisch beim Aufklappen oder Verbinden.
- **Footer = nur der Scan-Knopf**: groß und zentriert, mit RETURN-Symbol als
  sichtbarem Hinweis auf das Tastenkürzel. Der Abbrechen-Knopf (während eines
  Scans) hat dieselbe Größe, damit das Layout nicht springt.
- **Fortschritts-HUD**: Während Vorschau/Scan überdeckt ein leichter Schleier den
  (dann irrelevanten) mittleren Bereich; auf einer Frosted-Karte steht groß, was
  gerade passiert. Der Abbrechen-Knopf im Footer bleibt frei. Derselbe HUD-Look
  trägt auch den "Verbindung herstellen"-Zustand. Keine Inline-Statuszeile mehr.

## Fenster (Größe & Position)

- **Wächst/schrumpft** beim Umschalten: Der `hxScannerV2WindowController` setzt die
  Fenstergröße selbst (SwiftUI kann ein zu großes Fenster nicht zurückschrumpfen).
- **Kompakt** ist ein fester, nicht skalierbarer Panel; **Detail** ist frei
  skalierbar mit Mindestgröße (Inhalt 760x520), damit Vorschau und die 300 pt
  breite Eigenschaften-Spalte immer Platz haben.
- **Mindestgröße** wird über das `windowWillResize`-Delegate erzwungen (zuverlässig,
  unabhängig von der Hosting-View); `contentMinSize` und `sizingOptions = []` sind
  zusätzlich gesetzt.
- **Snap-back von Position UND Größe**: Für jeden Modus wird das letzte
  Fenster-Frame gemerkt (`ScannerWorkflowPrefs.compactFrame` / `expandedFrame`, auf
  den Bildschirm geklammert) und beim Umschalten, Schließen und erneuten Öffnen
  wiederhergestellt - so springt das Fenster nicht.

## Scan-Parameter (nur Detailmodus)

- **Auflösung** in dpi, aus den vom Gerät gemeldeten Werten.
- **Farbmodus**: Schwarzweiß (1-bit), Graustufen (8-bit), Farbe (RGB 8-bit).
- **Duplex** (beidseitig) bei Einzugsscannern mit Duplex-Unterstützung.

## Vorschau & Bereichsauswahl (nur Flachbett, Detailmodus)

- **Vorschau-Scan** (Overview) als Bild.
- **Auswahlrechteck** per Maus über dem Vorschaubild aufziehen.
- **Numerische Felder** für X / Y / Breite / Höhe, automatisch geklammert auf die
  Bettgröße.
- **Maßeinheit** je nach Locale: Zoll (US) oder Millimeter (sonst); intern immer mm.
- **Papierformat-Presets**: A4, Letter, A5, A6, A3, Legal, Tabloid, Visitenkarte,
  plus "Volle Fläche". Die aktuelle Auswahl wird als passendes Format, "Volle
  Fläche" oder "Benutzerdefiniert" angezeigt.
- **Regel gegen Fehlscans**: Eine Auswahl wird nur verwendet, wenn eine Vorschau
  sichtbar ist **und** die Fläche nicht leer ist - sonst die volle Fläche.
  Ein 0x0-Scan ist konstruktiv ausgeschlossen.

## Scannen

- **Sofortige Verarbeitung**: Jede Scan-Auslösung wird unmittelbar an den Host
  übergeben - kein Sammeln, kein Abschluss-Schritt. Ein Einzugs-Stapel kommt als
  ein Durchlauf, ein Flachbett-Druck als einzelne Seite.
- **Scan-Ziel** als einzelne Checkbox "An aktuelles Dokument anhängen" (Default
  aus). Ist sie an, wird jeder Durchlauf an das aktuell bearbeitete Dokument
  angehängt; ist sie aus, wird aus jedem Durchlauf ein neues Dokument - ein
  Einzugs-Stapel ergibt ein mehrseitiges Dokument, jeder einzelne Flachbett-Druck
  ein eigenes. Die Checkbox ist ausgegraut, wenn der Host kein passendes
  Zieldokument meldet (PDFify: kein aktives Dokument; Receipts: kein Beleg
  ausgewählt).
- **Großer Scan-Auslöser** mit RETURN, Abbrechen auf ESC.
- **Mehrseitiger Einzug**: liefert alle Blätter eines Durchlaufs als ein Batch.
- Ausgabe als **PNG mit korrekten DPI-Metadaten** (`smartDataForPNG`).
- **Abbrechen** eines laufenden Scans oder einer Vorschau.
- **Status-/Fortschrittsanzeige** (Verbinden, Vorschau, Scannen), gezeigt im HUD.
  Live aus den spärlichen ICA-Signalen gespeist: laufender Seitenzähler beim Einzug
  (`didScanToURL:` je Seite) und Aufwärm-Hinweis (`didReceiveStatusInformation`,
  `ICScannerStatusWarmingUp`). Der Aufwärm-Hinweis wird wieder entfernt, sobald
  `ICScannerStatusWarmUpDone` kommt - oder, falls der Treiber das nicht sendet
  (z. B. Canon), per Debounce nach kurzer Ruhe; sonst bliebe "Aufwärmen" den ganzen
  Scan über stehen. Echten Prozent-Fortschritt liefert ICA im `.fileBased`-Modus
  nicht.
- Robuste Fehlerbehandlung: Gerätefehler (auch die, die nur über
  `didEncounterError` kommen) werden als Alert gemeldet, statt zu hängen.
- **Verbindungsfehler inline**: Scheitert das Verbinden/Öffnen eines Geräts,
  zeigt das Detail-Pane einen verständlichen Fehlertext mit "Erneut
  versuchen"-Button (`connectionError` + `retryConnect()`) statt eines
  Dauerspinners. Die kryptischen ImageCaptureCore-Codes (`-9921`, `-9925/-9926`
  in Benutzung, `-9945` fehlender Treiber, ...) werden in `ScanError` auf
  handlungsorientierte Klartext-Meldungen abgebildet.
- **Auto-Retry beim Öffnen**: `ICAScanDevice.open()` wiederholt transiente
  Session-Fehler (`-9921/-9923/-9927/-9958`) mit kurzem Backoff selbsttätig
  (400/900/1800 ms), wartet dazwischen den `requestCloseSession()`-Abschluss ab.
  Netzwerk-Scanner (WLAN, eSCL/Bonjour) verschlafen sonst die erste Sitzung -
  Apples Image Capture macht dasselbe. Nicht-transiente Fehler (in Benutzung,
  Treiber fehlt) werden sofort gemeldet.

## Persistenz (pro Gerät)

- Zuletzt genutzte **Auflösung, Farbmodus, Duplex und Auswahlbereich** werden je
  Scanner (über `persistentIDString`) gespeichert und beim Wiederverbinden
  desselben Geräts wiederhergestellt. Wiederhergestellte Werte werden gegen die
  aktuellen Fähigkeiten des Geräts geprüft.
- **Scan-Ziel**: "An aktuelles Dokument anhängen" wird bewusst **nicht** gemerkt
  und startet jede Sitzung neu auf "neues Dokument", um versehentliches Scannen in
  ein veraltetes Dokument zu vermeiden.

## ScanSnap-Hinweis

- ScanSnap-Scanner (Fujitsu/PFU) werden **nicht** über ImageCaptureCore gesteuert:
  Die ScanSnap-App besitzt das Gerät und liefert fertige Scans per Drag&Drop bzw.
  Watch-Folder in den Import. Der Alt-Dialog hängte dafür einen Fake-Geräteeintrag
  in die Liste - das täuschte ein steuerbares Gerät vor. Der v2-Dialog macht das
  bewusst nicht.
- Stattdessen: Ist die ScanSnap-Software installiert (`ScanSnapSupport.isInstalled`,
  Bundle-IDs `com.fujitsu.pfu.ScanSnapHome` / `jp.co.pfu.ScanSnap.V10L10`), erscheint
  unten im Dialog ein **schmaler Hinweis-Streifen**: "ScanSnap öffnen" (startet die
  App), ein Hilfe-Link (`scanSnapHelpURL()` je App) und ein Schließen-Knopf.
- **Einmalig wegklickbar**: Nach dem Ausblenden bleibt der Streifen dauerhaft weg
  (`ScannerWorkflowPrefs.scanSnapHintDismissed`) - ein Pointer, kein Dauer-Nag.

## Integration & Verhalten

- **Drop-in Window-Controller** (`hxScannerV2WindowController`) mit derselben
  Schnittstelle wie der Alt-Dialog (`hxScannerDelegate`, `showWindow(_:)`,
  `window`). Ergebnis bevorzugt über `handleScannedPages(_:destination:)` (Batch +
  Ziel); Hosts ohne diese Methode bekommen weiter `handleScanData(_:)` je Seite.
- **Sauberer Teardown** beim Schließen und sauberer Zustand beim erneuten Öffnen.
- Auf macOS 14+ Standard; Alt-Dialog bleibt als Opt-out
  (`UseLegacyScannerDialog`).

## Plattform & Technik

- **macOS 14+**, SwiftUI-UI in einem `NSWindowController` gehostet.
- `ICScannerDevice` direkt angesteuert, **eigene Session-Verwaltung**.
- **File-based Transfer** in ein Sandbox-Temp-Verzeichnis (kein Rechte-Prompt,
  auto-Cleanup).

## Lokalisierung

- Deutsch und Englisch vorhanden. Weitere Sprachen sind noch offen (siehe PLAN).
