Zoek/vervangen: focus springt per karakter weg + HTML-fout na vervangen #1760

Closed
opened 2026-08-24 07:35:54 +00:00 by brenno · 0 comments
Owner

Wat wordt gevraagd

Twee problemen met zoeken/vervangen in de documenteditor:

  1. Focus springt per karakter weg: tijdens het typen van een zoekterm in de zoekbalk springt de aandacht na ieder karakter naar het document, zodat je je zoekterm niet kunt invullen en in het document begint te editten.
  2. HTML-foutmelding na vervangen: na een vervang-actie sprong de editor opeens met een HTML-foutmelding terug naar de bronmodus.

Onderzoek

Probleem 1: focus springt weg per karakter

De zoekbalk (MarkdownFindBar, lib/widgets/editors/markdown_find_bar.dart) geeft onQueryChanged: _find.setQuery door (lib/widgets/document_editor_screen.dart:767).

FindReplaceSession.setQuery (lib/widgets/editors/find_replace_session.dart:103-106) roept recount(selectFirst: true) aan. recount (regel 133-158) doet twee dingen:

  • tellen van treffers, en
  • onReveal(matches[index]) aanroepen om naar de eerste treffer te springen.

onReveal is _jumpToMatch (document_editor_screen.dart:789-802), dat in bron-modus _controller.selection zet (focus naar de editor) en in visuele modus een setState met _findSelectionSignal++ (signaal naar de Quill-editor om de cursor te verplaatsen).

Elk karakter in het zoekveld trekt dus de focus/cursor naar het document. Er bestaat al een methode refreshWhileTyping (regel 163-175) die wél telt maar níet springt — maar die wordt alleen vanuit _onControllerChanged aangeroepen (typen in het document zelf), niet vanuit het zoekveld.

Probleem 2: HTML-foutmelding na vervangen

replaceCurrent (regel 198-207) en replaceAll (regel 212-225) zetten controller.text op de nieuwe tekst. Dat activeert _onControllerChanged (document_editor_screen.dart:235-261), die markdownRoundTripsVisually(body) controleert (regel 250). Bevat de vervangtekst een constructie die de visuele laag niet aankan (rauwe HTML, ontsnapte leestekens), dan is isVisualEdit false.

De visuele editor (MarkdownNotesEditor) herlaadt bij een externe controller-wijziging de tekst. Komt de nieuwe tekst niet verliesvrij door de Quill-brug, dan valt de editor terug op bewerkbare brontekst met een waarschuwingsregel (MarkdownVisualLimitation.rawHtml → de HTML-foutmelding die de gebruiker zag). De fallback is correct gedrag (de bron bevat nu iets dat niet visueel kan), maar de gebruiker ervaart het als een onverwachte sprong.

Voorgestelde oplossing

Probleem 1

Laat setQuery niet naar de eerste treffer springen tijdens het typen. De kleinste diff: onQueryChanged in _findBar() doorgeven aan een nieuwe methode die refreshWhileTyping-gedrag gebruikt (tellen zonder springen) in plaats van setQuery. Of: setQuery een parameter jump: bool geven die standaard false is bij typen en true bij expliciet openen.

Concreet: in FindReplaceSession een methode onQueryFieldChanged(String) toevoegen die _query zet en refreshWhileTyping() aanroept (tellen, geen onReveal). MarkdownFindBar.onQueryChanged binden aan die methode. setQuery (met sprong) blijft voor open() en programma-aanroepen.

Probleem 2

Dit is grotendeels correct gedrag: een vervanging die HTML introduceert kan niet visueel. Twee verbeteringen:

  1. De fallback-melding specifieker maken: in plaats van alleen "regel N bevat HTML", ook melden dat dit het gevolg is van de zojuist uitgevoerde vervanging, zodat de gebruiker de oorzaak begrijpt.
  2. Optioneel: bij replaceAll vooraf controleren of het resultaat nog visueel rondreist, en zo ja, de gebruiker waarschuwen vóór de actie in plaats van erna te laten terugvallen.

Voorkeur: oplossing 1 (helderdere melding) als kleine diff; oplossing 2 als aanvulling wanneer de vervangtekst expliciet HTML bevat.

Impact

  • Probleem 1 is een puur UX-bug in de zoekbalk; geen wijziging aan de bron of de zoeklogica zelf, alleen aan wanneer er gesprongen wordt.
  • Probleem 2 is een melding-verbetering; de fallback-logica zelf blijft.
## Wat wordt gevraagd Twee problemen met zoeken/vervangen in de documenteditor: 1. **Focus springt per karakter weg:** tijdens het typen van een zoekterm in de zoekbalk springt de aandacht na ieder karakter naar het document, zodat je je zoekterm niet kunt invullen en in het document begint te editten. 2. **HTML-foutmelding na vervangen:** na een vervang-actie sprong de editor opeens met een HTML-foutmelding terug naar de bronmodus. ## Onderzoek ### Probleem 1: focus springt weg per karakter De zoekbalk (`MarkdownFindBar`, `lib/widgets/editors/markdown_find_bar.dart`) geeft `onQueryChanged: _find.setQuery` door (`lib/widgets/document_editor_screen.dart:767`). `FindReplaceSession.setQuery` (`lib/widgets/editors/find_replace_session.dart:103-106`) roept `recount(selectFirst: true)` aan. `recount` (regel 133-158) doet twee dingen: - tellen van treffers, en - `onReveal(matches[index])` aanroepen om naar de eerste treffer te springen. `onReveal` is `_jumpToMatch` (`document_editor_screen.dart:789-802`), dat in bron-modus `_controller.selection` zet (focus naar de editor) en in visuele modus een `setState` met `_findSelectionSignal++` (signaal naar de Quill-editor om de cursor te verplaatsen). Elk karakter in het zoekveld trekt dus de focus/cursor naar het document. Er bestaat al een methode `refreshWhileTyping` (regel 163-175) die wél telt maar níet springt — maar die wordt alleen vanuit `_onControllerChanged` aangeroepen (typen in het document zelf), niet vanuit het zoekveld. ### Probleem 2: HTML-foutmelding na vervangen `replaceCurrent` (regel 198-207) en `replaceAll` (regel 212-225) zetten `controller.text` op de nieuwe tekst. Dat activeert `_onControllerChanged` (`document_editor_screen.dart:235-261`), die `markdownRoundTripsVisually(body)` controleert (regel 250). Bevat de vervangtekst een constructie die de visuele laag niet aankan (rauwe HTML, ontsnapte leestekens), dan is `isVisualEdit` false. De visuele editor (`MarkdownNotesEditor`) herlaadt bij een externe controller-wijziging de tekst. Komt de nieuwe tekst niet verliesvrij door de Quill-brug, dan valt de editor terug op bewerkbare brontekst met een waarschuwingsregel (`MarkdownVisualLimitation.rawHtml` → de HTML-foutmelding die de gebruiker zag). De fallback is correct gedrag (de bron bevat nu iets dat niet visueel kan), maar de gebruiker ervaart het als een onverwachte sprong. ## Voorgestelde oplossing ### Probleem 1 Laat `setQuery` niet naar de eerste treffer springen tijdens het typen. De kleinste diff: `onQueryChanged` in `_findBar()` doorgeven aan een nieuwe methode die `refreshWhileTyping`-gedrag gebruikt (tellen zonder springen) in plaats van `setQuery`. Of: `setQuery` een parameter `jump: bool` geven die standaard `false` is bij typen en `true` bij expliciet openen. Concreet: in `FindReplaceSession` een methode `onQueryFieldChanged(String)` toevoegen die `_query` zet en `refreshWhileTyping()` aanroept (tellen, geen `onReveal`). `MarkdownFindBar.onQueryChanged` binden aan die methode. `setQuery` (met sprong) blijft voor `open()` en programma-aanroepen. ### Probleem 2 Dit is grotendeels correct gedrag: een vervanging die HTML introduceert kan niet visueel. Twee verbeteringen: 1. De fallback-melding specifieker maken: in plaats van alleen "regel N bevat HTML", ook melden dat dit het gevolg is van de zojuist uitgevoerde vervanging, zodat de gebruiker de oorzaak begrijpt. 2. Optioneel: bij `replaceAll` vooraf controleren of het resultaat nog visueel rondreist, en zo ja, de gebruiker waarschuwen vóór de actie in plaats van erna te laten terugvallen. Voorkeur: oplossing 1 (helderdere melding) als kleine diff; oplossing 2 als aanvulling wanneer de vervangtekst expliciet HTML bevat. ## Impact - Probleem 1 is een puur UX-bug in de zoekbalk; geen wijziging aan de bron of de zoeklogica zelf, alleen aan wanneer er gesprongen wordt. - Probleem 2 is een melding-verbetering; de fallback-logica zelf blijft.
brenno 2026-08-24 09:03:07 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#1760
No description provided.