[Bug] Aanmaken en verwijderen van een app-thema negeren Annuleren #760

Closed
opened 2026-07-23 15:52:04 +00:00 by brenno · 2 comments
Owner

Wat er gebeurt

In Uiterlijk → App-thema staan boven de acht kleurvelden twee knopjes: +
("Kopie maken en aanpassen") en een prullenbak ("Thema verwijderen"). Allebei
doen hun werk onmiddellijk en definitief, terwijl alles eronder pas telt bij
Opslaan.

Gevonden bij het bouwen van #750: ik maakte een kopie om de nieuwe
leesbaarheidsmeting te tonen, drukte daarna op Annuleren, en het profiel stond
er nog steeds.

Reproduceren:

  1. Instellingen → App-thema, druk op +.
  2. Druk op Annuleren.
  3. Open de instellingen opnieuw — "Eigen thema" staat er, en het is bovendien
    het actieve thema geworden.

Waarom dit meer is dan een schoonheidsfoutje

Dit venster heeft een contract, en het staat letterlijk in de code:

lib/widgets/dialogs/settings_dialog.dart:127"…zodat Annuleren de
wijzigingen verwerpt."

:489"pas bij Opslaan telt de lijst, en tot dan mag Annuleren alles
terugdraaien."

De acht kleurvelden houden zich daaraan: die bewerken _appearanceProfile in de
dialoogstatus. De twee knopjes ernaast schrijven rechtstreeks naar de
settingsProvider en roepen _saveAppearanceProfiles() aan — dus naar schijf.

Eén rij, twee soorten gedrag, en een Annuleren-knop onderaan die maar één van
de twee terugdraait. Dat is niet te leren; je moet het een keer meemaken.

Drie bevindingen, in volgorde van zwaarte

1. De prullenbak vraagt niets en is niet terug te draaien.
deleteAppAppearanceProfile (settings_provider.dart:711) verwijdert het
profiel en schrijft dat meteen weg. Geen bevestiging, geen ongedaan maken, geen
Annuleren die helpt. Een zelfgemaakt thema kan er lang in zitten; één klik en
het is weg, en dat is de enige klik die daarvoor nodig is. Dit is de
zwaarste van de drie.

2. De + maakt niet alleen aan, hij schákelt ook.
createAppAppearanceProfile (:673) zet selectedAppAppearanceProfileName op
het nieuwe profiel. De hele app springt dus naar een thema dat de gebruiker nog
niet heeft gemaakt, en dat blijft zo na Annuleren.

3. Na verwijderen kloppen dialoog en instelling niet met elkaar.
De provider zet de selectie op de letterlijke string 'Europa'
(settings_provider.dart:722), terwijl de knop in de bewerker de dialoogstatus
op AppAppearanceProfile.basic zet
(settings_dialog_appearance.dart, de prullenbak-onPressed). Je ziet dus
"Basic" staan terwijl er "Europa" bewaard is — en met Annuleren houd je Europa,
met Opslaan krijg je Basic. Geen van beide is waar je vandaan kwam: het
verwijderen van een kopie van Donker zet je in een licht thema.

Ik liep hier zelf tegenaan: na het opruimen van mijn testprofiel stond de app in
lichte modus, en ik moest Donker met de hand terugzetten.

Richting

Twee routes, en ze sluiten elkaar niet uit.

A — trek de knoppen het contract in. Aanmaken en verwijderen werken op de
dialoogstatus (een lokale lijst plus een "te verwijderen"-verzameling) en landen
pas bij Opslaan, net als de opslagverbindingen — die doen dit al zo, met
_connections. Dan klopt Annuleren voor het hele venster en is bevestiging bij
verwijderen niet eens nodig.

Dit is de nette oplossing en past bij hoe de rest van het venster is gebouwd.

B — laat ze direct blijven, maar zeg dat dan. Een bevestiging bij
verwijderen ("dit kan niet ongedaan worden gemaakt"), en de + die aanmaakt zonder
meteen over te schakelen. Goedkoper, maar het laat de tweedeling in het venster
staan, en dat is nou juist wat de verwarring maakt.

Aanbeveling: A, met de fallback uit bevinding 3 als onderdeel daarvan —
verwijderen hoort terug te vallen op het profiel dat vóór de kopie actief was,
niet op een hardgecodeerde naam.

Wordt het B, dan alsnog de hardgecodeerde 'Europa' weg: dat die string er staat
terwijl de dialoog basic kiest, is op zichzelf een fout, ongeacht welke route.

Kosten

Route A: schatting een dag. Het patroon bestaat al (_connections en het
stijlprofiel doen precies dit), dus het is vooral zorgvuldig werk plus tests op
Annuleren-na-aanmaken en Annuleren-na-verwijderen. Eén nieuwe l10n.d('…') als
er tóch een bevestiging komt (× 31 talen). Geen afhankelijkheid, geen
SBOM-gevolg.

Route B: een dagdeel, plus één of twee nieuwe teksten voor de bevestiging.

Randgevallen die een test verdienen

  • Annuleren na + — het profiel hoort weg te zijn, en het actieve thema
    onveranderd.
  • Annuleren na verwijderen — het profiel hoort er nog te zijn.
  • Het actieve thema verwijderen — waar val je op terug, en zien dialoog en
    instelling hetzelfde?
  • Een ingebouwd thema is niet te verwijderen (de knop staat uit via editable);
    dat mag niet stilletjes veranderen.
## Wat er gebeurt In *Uiterlijk → App-thema* staan boven de acht kleurvelden twee knopjes: **+** ("Kopie maken en aanpassen") en een **prullenbak** ("Thema verwijderen"). Allebei doen hun werk **onmiddellijk en definitief**, terwijl alles eronder pas telt bij Opslaan. Gevonden bij het bouwen van #750: ik maakte een kopie om de nieuwe leesbaarheidsmeting te tonen, drukte daarna op *Annuleren*, en het profiel stond er nog steeds. Reproduceren: 1. *Instellingen → App-thema*, druk op **+**. 2. Druk op **Annuleren**. 3. Open de instellingen opnieuw — "Eigen thema" staat er, en het is bovendien het actieve thema geworden. ## Waarom dit meer is dan een schoonheidsfoutje Dit venster heeft een contract, en het staat letterlijk in de code: > `lib/widgets/dialogs/settings_dialog.dart:127` — *"…zodat Annuleren de > wijzigingen verwerpt."* > > `:489` — *"pas bij Opslaan telt de lijst, en tot dan mag Annuleren alles > terugdraaien."* De acht kleurvelden houden zich daaraan: die bewerken `_appearanceProfile` in de dialoogstatus. De twee knopjes ernaast schrijven rechtstreeks naar de `settingsProvider` en roepen `_saveAppearanceProfiles()` aan — dus naar schijf. Eén rij, twee soorten gedrag, en een *Annuleren*-knop onderaan die maar één van de twee terugdraait. Dat is niet te leren; je moet het een keer meemaken. ## Drie bevindingen, in volgorde van zwaarte **1. De prullenbak vraagt niets en is niet terug te draaien.** `deleteAppAppearanceProfile` (`settings_provider.dart:711`) verwijdert het profiel en schrijft dat meteen weg. Geen bevestiging, geen ongedaan maken, geen *Annuleren* die helpt. Een zelfgemaakt thema kan er lang in zitten; één klik en het is weg, en dat is de enige klik die daarvoor nodig is. Dit is de zwaarste van de drie. **2. De + maakt niet alleen aan, hij schákelt ook.** `createAppAppearanceProfile` (`:673`) zet `selectedAppAppearanceProfileName` op het nieuwe profiel. De hele app springt dus naar een thema dat de gebruiker nog niet heeft gemaakt, en dat blijft zo na *Annuleren*. **3. Na verwijderen kloppen dialoog en instelling niet met elkaar.** De provider zet de selectie op de letterlijke string `'Europa'` (`settings_provider.dart:722`), terwijl de knop in de bewerker de dialoogstatus op `AppAppearanceProfile.basic` zet (`settings_dialog_appearance.dart`, de prullenbak-`onPressed`). Je ziet dus "Basic" staan terwijl er "Europa" bewaard is — en met *Annuleren* houd je Europa, met *Opslaan* krijg je Basic. Geen van beide is waar je vandaan kwam: het verwijderen van een kopie van *Donker* zet je in een licht thema. Ik liep hier zelf tegenaan: na het opruimen van mijn testprofiel stond de app in lichte modus, en ik moest *Donker* met de hand terugzetten. ## Richting Twee routes, en ze sluiten elkaar niet uit. **A — trek de knoppen het contract in.** Aanmaken en verwijderen werken op de dialoogstatus (een lokale lijst plus een "te verwijderen"-verzameling) en landen pas bij Opslaan, net als de opslagverbindingen — die doen dit al zo, met `_connections`. Dan klopt *Annuleren* voor het hele venster en is bevestiging bij verwijderen niet eens nodig. Dit is de nette oplossing en past bij hoe de rest van het venster is gebouwd. **B — laat ze direct blijven, maar zeg dat dan.** Een bevestiging bij verwijderen ("dit kan niet ongedaan worden gemaakt"), en de + die aanmaakt zonder meteen over te schakelen. Goedkoper, maar het laat de tweedeling in het venster staan, en dat is nou juist wat de verwarring maakt. Aanbeveling: **A**, met de fallback uit bevinding 3 als onderdeel daarvan — verwijderen hoort terug te vallen op het profiel dat vóór de kopie actief was, niet op een hardgecodeerde naam. Wordt het B, dan alsnog de hardgecodeerde `'Europa'` weg: dat die string er staat terwijl de dialoog `basic` kiest, is op zichzelf een fout, ongeacht welke route. ## Kosten Route A: schatting een dag. Het patroon bestaat al (`_connections` en het stijlprofiel doen precies dit), dus het is vooral zorgvuldig werk plus tests op Annuleren-na-aanmaken en Annuleren-na-verwijderen. Eén nieuwe `l10n.d('…')` als er tóch een bevestiging komt (× 31 talen). Geen afhankelijkheid, geen SBOM-gevolg. Route B: een dagdeel, plus één of twee nieuwe teksten voor de bevestiging. ## Randgevallen die een test verdienen - *Annuleren* na **+** — het profiel hoort weg te zijn, en het actieve thema onveranderd. - *Annuleren* na verwijderen — het profiel hoort er nog te zijn. - Het actieve thema verwijderen — waar val je op terug, en zien dialoog en instelling hetzelfde? - Een ingebouwd thema is niet te verwijderen (de knop staat uit via `editable`); dat mag niet stilletjes veranderen.
Author
Owner

Opgepakt. Tak: fix/appthema-annuleren-760. Route A: aanmaken en verwijderen gaan de dialoogstatus in (lokale profielenlijst, landen pas bij Opslaan), verwijderen valt terug op het profiel dat ervóór actief was in plaats van de hardgecodeerde 'Europa', en de vier randgevallen uit het issue krijgen elk een test — eerst rood tegen de huidige code. Verwachte reikwijdte: settings_dialog_appearance.dart, settings_dialog.dart (dialoogstatus + opslaan), settings_provider.dart, en de tests.

Opgepakt. Tak: fix/appthema-annuleren-760. Route A: aanmaken en verwijderen gaan de dialoogstatus in (lokale profielenlijst, landen pas bij Opslaan), verwijderen valt terug op het profiel dat ervóór actief was in plaats van de hardgecodeerde 'Europa', en de vier randgevallen uit het issue krijgen elk een test — eerst rood tegen de huidige code. Verwachte reikwijdte: settings_dialog_appearance.dart, settings_dialog.dart (dialoogstatus + opslaan), settings_provider.dart, en de tests.
Author
Owner

Af, op main: 5a73774 (PR #762), daar geverifieerd. Route A zoals aanbevolen: beide knoppen bewerken de werkkopie van het venster en landen pas bij Opslaan via één setAppAppearanceProfiles; de vier losse schrijfwegen zijn weg. Alle drie de bevindingen gedekt: de prullenbak is tot Opslaan omkeerbaar (waarmee een bevestiging inderdaad niet nodig bleek), de + schakelt niets meer om buiten het venster, en de terugval na verwijderen is het thema dat actief was toen het venster openging — dialoog en instelling kunnen niet meer uiteenlopen, de hardgecodeerde 'Europa' is weg. De vier randgevallen uit het issue hebben elk hun test (plus twee tegenproeven); de vier foutdragende eerst rood gezien. Wat er níét in zat: niets uit het issue. Poort: make check groen, secrets/SAST schoon.

Af, op main: 5a73774 (PR #762), daar geverifieerd. Route A zoals aanbevolen: beide knoppen bewerken de werkkopie van het venster en landen pas bij Opslaan via één setAppAppearanceProfiles; de vier losse schrijfwegen zijn weg. Alle drie de bevindingen gedekt: de prullenbak is tot Opslaan omkeerbaar (waarmee een bevestiging inderdaad niet nodig bleek), de + schakelt niets meer om buiten het venster, en de terugval na verwijderen is het thema dat actief was toen het venster openging — dialoog en instelling kunnen niet meer uiteenlopen, de hardgecodeerde 'Europa' is weg. De vier randgevallen uit het issue hebben elk hun test (plus twee tegenproeven); de vier foutdragende eerst rood gezien. Wat er níét in zat: niets uit het issue. Poort: make check groen, secrets/SAST schoon.
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#760
No description provided.