#82: Live-Filter im Verlauf-Tab mit 300-ms-Debounce

Das Suchfeld löst loadOverview() nach 300 ms Tippinaktivität automatisch aus
(PauseTransition). Enter-Taste stoppt den Timer und sucht sofort. So wird die
Tabelle live gefiltert, ohne bei jedem Tastendruck eine DB-Anfrage zu starten.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-05 12:35:30 +02:00
parent beade6ba2e
commit 9f222208c0
@@ -25,7 +25,9 @@ import de.gecheckt.pdf.umbenenner.application.usecase.DefaultHistoryDetailsUseCa
import de.gecheckt.pdf.umbenenner.application.usecase.DefaultHistoryOverviewUseCase.HistoryOverviewResult; import de.gecheckt.pdf.umbenenner.application.usecase.DefaultHistoryOverviewUseCase.HistoryOverviewResult;
import de.gecheckt.pdf.umbenenner.domain.model.DocumentFingerprint; import de.gecheckt.pdf.umbenenner.domain.model.DocumentFingerprint;
import de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus; import de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus;
import javafx.animation.PauseTransition;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.util.Duration;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@@ -60,6 +62,7 @@ import javafx.scene.layout.VBox;
* Zeigt alle jemals verarbeiteten Dokumente aus der SQLite-Datenbank in einer * Zeigt alle jemals verarbeiteten Dokumente aus der SQLite-Datenbank in einer
* zweispaltigen Ansicht: links eine filterbare Dokumentenliste (~55%), * zweispaltigen Ansicht: links eine filterbare Dokumentenliste (~55%),
* rechts ein Detailbereich mit Stammsatz, Versuchstabelle und KI-Begründung (~45%). * rechts ein Detailbereich mit Stammsatz, Versuchstabelle und KI-Begründung (~45%).
* Das Suchfeld ist mit einem 300-ms-Debounce ausgestattet (Live-Filter).
* *
* <h2>Layout</h2> * <h2>Layout</h2>
* <pre> * <pre>
@@ -139,6 +142,12 @@ public final class GuiHistoryTab {
// ---- Zustand -------------------------------------------------------- // ---- Zustand --------------------------------------------------------
private final ExecutorService workerPool; private final ExecutorService workerPool;
/**
* Debounce-Timer für das Suchfeld: löst {@link #loadOverview()} aus, sobald
* 300 ms nach der letzten Texteingabe vergangen sind.
*/
private final PauseTransition searchDebounce = new PauseTransition(Duration.millis(300));
/** /**
* Erzeugt den Historien-Tab. * Erzeugt den Historien-Tab.
* *
@@ -462,9 +471,11 @@ public final class GuiHistoryTab {
private void wireEvents() { private void wireEvents() {
refreshButton.setOnAction(e -> loadOverview()); refreshButton.setOnAction(e -> loadOverview());
// Debounce-artige Aktualisierung bei Texteingabe: direkte Suche bei Enter, // Live-Filter: 300-ms-Debounce bei jeder Texteingabe
// sonst über Fokus-Verlust oder expliziten Aktualisieren-Button searchDebounce.setOnFinished(e -> loadOverview());
searchField.setOnAction(e -> loadOverview()); searchField.textProperty().addListener((obs, old, val) -> searchDebounce.playFromStart());
// Enter-Taste: sofort suchen, Debounce-Timer stoppen
searchField.setOnAction(e -> { searchDebounce.stop(); loadOverview(); });
statusFilterBox.setOnAction(e -> loadOverview()); statusFilterBox.setOnAction(e -> loadOverview());