ux(bijsnijden): draaien waarschuwt vooraf dat het het bestand herschrijft #1872

Merged
brenno merged 1 commit from fix/rotatie-niet-destructief into main 2026-08-30 20:36:07 +00:00
Owner

Wat dit is

Het antwoord op de vraag uit de spin-off van #1870kan draaien niet-destructief worden, net als bijsnijden? — plus het enige stuk dat geen beslissing nodig had.

Gedrag verandert hier nog niet. Draaien herschrijft het bestand nog steeds; wat erbij komt is dat de gebruiker het weet vóórdat hij klikt.

Het antwoord: ja, en de keuze is gemaakt

Uitgewerkt in docs/design/IMAGE_ROTATION.md. Drie vormen gewogen; de eigenaar koos optie A.

Wat Formaatwijziging
A (gekozen) draaien schrijft een afgeleide kopie, origineel blijft heel nee
B opgeslagen kwartslagveld, toegepast bij het tekenen ja
C laten zoals het is, en het zeggen nee

A landt in de images/-map van het deck, niet naast het origineel — die indeling bestaat al (asset_staging.dart stageert naar images//media/, copyImagesToProject tilt het bij opslaan naar het project), dus een gedraaide kopie is een gewone deck-asset die meereist in het pakket en het git-vlak. Ernaast schrijven zou een OciDeck-artefact in de fotomap van de gebruiker leggen — hetzelfde soevereiniteitsprobleem in het klein. Een tweede kwartslag wordt opnieuw uit het origineel afgeleid, dus nooit r90.r90.

Waarom niet B, dat het betere model is: het legt de rotatie als dia-commentaar in de .md, en een oudere OciDeck slaat zo'n commentaar over én schrijft het bij opslaan niet terug. Een deck dat langs zo'n lezer komt, komt ongedraaid terug zonder melding. B koopt daarbovenop alleen één foto onder twee hoeken op twee dia's, en daar heeft niemand om gevraagd. Uitwisselbaarheid geeft de doorslag. §7.2 legt ook vast wát de afweging zou heropenen: zodra iemand wél twee hoeken vraagt, komt B — ná A, en met een front-matter-blok in plaats van een commentaar.

Voor de volledigheid, want het is de reden dat B niet gratis is: er ís één schoon invoegpunt, image_viewport_geometry.dart (het Flutter-vrije contract uit #1825 dat Flutter, LaTeX, de hit-testing en de kwaliteitsanalyse allemaal aanroepen). Daar is rotatie een dimensiewissel plus het meedraaien van callout-targets; §5.2 heeft de afbeelding, met de hoeken nagerekend. PDF/PPTX/ODP komen gratis mee — die rasteren SlidePreviewWidget via een RepaintBoundary.

Wat er wél in zit

De waarschuwing boven de draaiknoppen, vóór de klik, in alle 32 talen, met beide feiten: het bestand zelf verandert, en een gedeelde afbeelding draait overal mee. Twee regressietoetsen — ze staat er zodra draaien kan, en ze staat er niet bij een meegeleverde asset waar de knoppen sowieso ontbreken.

En passant: de ontwerpnotitie-index in docs/README.md miste er negen, waaronder IMAGE_CALLOUTS.md — dat een formaatcontract draagt. Aangevuld. De correctienotitie van 22-07 legde dezelfde fout al vast en eindigt met "no test compares the two lists"; dat is nog steeds zo.

Bewaker

§7.1. Soevereiniteit (waarde 3) is de reden dat het stuk bestaat. De botsing is uitwisselbaarheid tegen het rijkere model en valt tegen B uit. Geen van de drie raakt opslag, een afhankelijkheid of uitgaand verkeer. Deze PR zelf raakt het formaat niet.

Toetsing

  • test/image_crop_dialog_test.dart — 21/21 groen, inclusief de twee nieuwe
  • make check-static — groen
  • make check-registrations — groen
  • Elke code-verwijzing in het ontwerpstuk nagelopen tegen de boom, bestanden én symbolen (rotateImageBytes bestaat inderdaad niet meer)

Eén bewering onderweg gecorrigeerd: ik schreef eerst dat image_dedup een identieke afbeelding één keer opslaat. Dat klopt niet — het is een opruimactie in de afbeeldingkiezer die duplicaten vindt, referenties over de decks op schijf telt en op het meest-aangehaalde bestand consolideert. Dat versterkt het punt eerder dan het te verzwakken, maar het stond er verkeerd.

Ook mijn eigen misstap, voor de volledigheid: drie gelijktijdige testruns vochten om build/native_assets/ en lieten een Vulkan-gecompileerde ink_sparkle.frag in build/unit_test_assets achter. Die liet ook een ongewijzigd testbestand vallen — dat was de controle waarmee ik uitsloot dat het aan de wijziging lag.

## Wat dit is Het antwoord op de vraag uit de spin-off van #1870 — **kan draaien niet-destructief worden, net als bijsnijden?** — plus het enige stuk dat geen beslissing nodig had. **Gedrag verandert hier nog niet.** Draaien herschrijft het bestand nog steeds; wat erbij komt is dat de gebruiker het weet vóórdat hij klikt. ## Het antwoord: ja, en de keuze is gemaakt Uitgewerkt in **`docs/design/IMAGE_ROTATION.md`**. Drie vormen gewogen; **de eigenaar koos optie A.** | | Wat | Formaatwijziging | |---|---|---| | **A** *(gekozen)* | draaien schrijft een afgeleide kopie, origineel blijft heel | nee | | B | opgeslagen kwartslagveld, toegepast bij het tekenen | ja | | C | laten zoals het is, en het zeggen | nee | **A landt in de `images/`-map van het deck**, niet naast het origineel — die indeling bestaat al (`asset_staging.dart` stageert naar `images/`/`media/`, `copyImagesToProject` tilt het bij opslaan naar het project), dus een gedraaide kopie is een gewone deck-asset die meereist in het pakket en het git-vlak. Ernaast schrijven zou een OciDeck-artefact in de fotomap van de gebruiker leggen — hetzelfde soevereiniteitsprobleem in het klein. Een tweede kwartslag wordt opnieuw uit het origineel afgeleid, dus nooit `r90.r90`. **Waarom niet B**, dat het betere model is: het legt de rotatie als dia-commentaar in de `.md`, en een oudere OciDeck slaat zo'n commentaar over én schrijft het bij opslaan niet terug. Een deck dat langs zo'n lezer komt, komt ongedraaid terug zonder melding. B koopt daarbovenop alleen één foto onder twee hoeken op twee dia's, en daar heeft niemand om gevraagd. Uitwisselbaarheid geeft de doorslag. §7.2 legt ook vast wát de afweging zou heropenen: zodra iemand wél twee hoeken vraagt, komt B — ná A, en met een front-matter-blok in plaats van een commentaar. Voor de volledigheid, want het is de reden dat B niet gratis is: er ís één schoon invoegpunt, `image_viewport_geometry.dart` (het Flutter-vrije contract uit #1825 dat Flutter, LaTeX, de hit-testing en de kwaliteitsanalyse allemaal aanroepen). Daar is rotatie een dimensiewissel plus het meedraaien van callout-targets; §5.2 heeft de afbeelding, met de hoeken nagerekend. PDF/PPTX/ODP komen gratis mee — die rasteren `SlidePreviewWidget` via een `RepaintBoundary`. ## Wat er wél in zit De waarschuwing boven de draaiknoppen, vóór de klik, in alle 32 talen, met beide feiten: het bestand zelf verandert, en een gedeelde afbeelding draait overal mee. Twee regressietoetsen — ze staat er zodra draaien kan, en ze staat er *niet* bij een meegeleverde asset waar de knoppen sowieso ontbreken. **En passant:** de ontwerpnotitie-index in `docs/README.md` miste er negen, waaronder `IMAGE_CALLOUTS.md` — dat een formaatcontract draagt. Aangevuld. De correctienotitie van 22-07 legde dezelfde fout al vast en eindigt met "no test compares the two lists"; dat is nog steeds zo. ## Bewaker §7.1. Soevereiniteit (waarde 3) is de reden dat het stuk bestaat. De botsing is uitwisselbaarheid tegen het rijkere model en valt tegen B uit. Geen van de drie raakt opslag, een afhankelijkheid of uitgaand verkeer. Deze PR zelf raakt het formaat niet. ## Toetsing - `test/image_crop_dialog_test.dart` — 21/21 groen, inclusief de twee nieuwe - `make check-static` — groen - `make check-registrations` — groen - Elke code-verwijzing in het ontwerpstuk nagelopen tegen de boom, bestanden én symbolen (`rotateImageBytes` bestaat inderdaad niet meer) Eén bewering onderweg gecorrigeerd: ik schreef eerst dat `image_dedup` een identieke afbeelding één keer opslaat. Dat klopt niet — het is een opruimactie in de afbeeldingkiezer die duplicaten *vindt*, referenties over de decks op schijf telt en op het meest-aangehaalde bestand consolideert. Dat versterkt het punt eerder dan het te verzwakken, maar het stond er verkeerd. Ook mijn eigen misstap, voor de volledigheid: drie gelijktijdige testruns vochten om `build/native_assets/` en lieten een Vulkan-gecompileerde `ink_sparkle.frag` in `build/unit_test_assets` achter. Die liet ook een ongewijzigd testbestand vallen — dat was de controle waarmee ik uitsloot dat het aan de wijziging lag.
ux(bijsnijden): draaien waarschuwt vooraf dat het het bestand herschrijft
All checks were successful
scans / scans (pull_request) Successful in 13m11s
static-gate / static-gate (pull_request) Successful in 9m32s
7cd27fa119
Van de drie bewerkingen in het aanpasvenster bewaren slepen en zoomen een
waarde in het deck; draaien herschrijft het afbeeldingsbestand op schijf.
Aan de knoppen is dat verschil niet te zien — dezelfde rij, dezelfde stijl,
één Klaar-knop — en een afbeelding die meer dia's of decks delen draait
overal mee. Er is geen undo en geen kopie.

De dialoog zegt dat nu boven de draaiknoppen, vóórdat er iets is
aangeklikt, in alle 32 talen. Niet als melding achteraf: op dat moment is
het origineel al weg.

Twee regressietoetsen: de waarschuwing staat er zodra draaien kan, en ze
staat er níet bij een meegeleverde asset waar de knoppen sowieso ontbreken
— anders is het ruis in plaats van hulp.

docs/design/IMAGE_ROTATION.md weegt de drie vormen die dit echt kunnen
oplossen. De eigenaar koos optie A: draaien schrijft een afgeleide kopie in
de images/-map van het deck en laat het origineel met rust; een tweede
kwartslag wordt opnieuw uit het origineel afgeleid, dus geen r90.r90. Dat
bouwen volgt apart — deze wijziging verandert het gedrag nog niet.

Waarom niet meteen optie B (een opgeslagen kwartslagveld): dat is het
betere model, maar het legt de rotatie als dia-commentaar in de `.md`, en
een oudere OciDeck slaat zo'n commentaar over én schrijft het bij opslaan
niet terug. Een deck dat langs zo'n lezer komt, komt ongedraaid terug
zonder dat iets het meldt. B koopt daarbovenop alleen één foto onder twee
hoeken op twee dia's, en daar heeft niemand om gevraagd. Uitwisselbaarheid
geeft de doorslag; §7 legt de afweging vast, inclusief wat hem zou heropenen.

En passant: de ontwerpnotitie-index in docs/README.md miste er negen,
waaronder IMAGE_CALLOUTS.md — dat een formaatcontract draagt. De
correctienotitie van 22-07 legde dezelfde fout al vast en eindigt met "no
test compares the two lists"; dat is nog steeds zo.

Poort: image_crop_dialog_test 21/21 groen, make check-static groen, make
check-registrations groen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
brenno merged commit 87ba6bcec4 into main 2026-08-30 20:36:07 +00:00
brenno deleted branch fix/rotatie-niet-destructief 2026-08-30 20:36:13 +00:00
Sign in to join this conversation.
No description provided.