feat(callouts): stap-voor-stap onthullen (#1828) #1836

Merged
brenno merged 6 commits from feat/stepwise-reveal-1828 into main 2026-08-29 06:10:58 +00:00
Owner

Samenvatting

  • Headless PresentationStepPlan (IMAGE_CALLOUTS.md §7) dat de bestaande tijdlijn-stapmodus generaliseert naar een gedeeld plan voor zowel tijdlijn als callout-reveal. Flutter-vrij, puur functie van Slide-data.
  • Callout reveal (reveal: steps): stap 0 toont titel + afbeelding; elke klik onthult één bullet plus al zijn callout-targets atomair. Terug gaat in reverse; een nieuwe dia reset naar stap 0.
  • Migratie van _timelineStep_stepIndex: de presentator houdt één sessie-lokale stap-index; het plan vertaalt die naar wat op elk scherm zichtbaar is (presenter, beamer, auto-advance).
  • Editor-toggle: een SegmentedButton in de callout-editor schakelt tussen "Alles tonen" en "Stap-voor-stap".
  • Statische export flattent: HTML, LaTeX, PDF/PPTX/ODP tonen alles — er is geen stap-status in de export.
  • Accessibility: schermlezer kondigt elke stap aan ("Punt 2/3, 1 markeringen"); onthulde callouts zijn in de accessibility tree, onthulde niet.
  • l10n: 3 nieuwe strings in alle 31 talen via tool/add_l10n.dart.
  • Docs: SOURCE_MAP, CHANGELOG, USER_GUIDE bijgewerkt.

Bewaker

reveal: steps is een front-matter key onder ocideck_callouts: die ander Marp-gereedschap negeert. Het .md blijft leesbaar; de bullets en (A) references zijn gewone tekst. De stap-voor-stap onthulling is een presentatie-gedrag (sessie-only), geen opslagformaat-verandering. Als OciDeck stopt, toont het deck alles — wat de statische export ook doet. Geen botsing van waarden.

Test plan

  • presentation_step_plan_test.dart — alle plan-types, edge cases, equality
  • callout_reveal_test.dart — overlay filter, step sequence (forward/backward/re-entry), atomic reveal, bullet zonder callout, timeline regressie
  • callout_editor_test.dart — reveal toggle bestaat, schakelen emit calloutReveal=steps
  • marp_html_service_callouts_test.dartreveal:steps flatten in HTML export
  • make check groen (10.804 tests, 86.9% dekking)
  • make check-secrets groen (gitleaks + trufflehog)
  • make sast groen (semgrep, 0 findings)
  • CI static-gate groen

Generated with Devin

## Samenvatting - **Headless `PresentationStepPlan`** (IMAGE_CALLOUTS.md §7) dat de bestaande tijdlijn-stapmodus generaliseert naar een gedeeld plan voor zowel tijdlijn als callout-reveal. Flutter-vrij, puur functie van `Slide`-data. - **Callout reveal (`reveal: steps`)**: stap 0 toont titel + afbeelding; elke klik onthult één bullet plus al zijn callout-targets atomair. Terug gaat in reverse; een nieuwe dia reset naar stap 0. - **Migratie van `_timelineStep` → `_stepIndex`**: de presentator houdt één sessie-lokale stap-index; het plan vertaalt die naar wat op elk scherm zichtbaar is (presenter, beamer, auto-advance). - **Editor-toggle**: een SegmentedButton in de callout-editor schakelt tussen "Alles tonen" en "Stap-voor-stap". - **Statische export flattent**: HTML, LaTeX, PDF/PPTX/ODP tonen alles — er is geen stap-status in de export. - **Accessibility**: schermlezer kondigt elke stap aan ("Punt 2/3, 1 markeringen"); onthulde callouts zijn in de accessibility tree, onthulde niet. - **l10n**: 3 nieuwe strings in alle 31 talen via `tool/add_l10n.dart`. - **Docs**: SOURCE_MAP, CHANGELOG, USER_GUIDE bijgewerkt. ### Bewaker `reveal: steps` is een front-matter key onder `ocideck_callouts:` die ander Marp-gereedschap negeert. Het `.md` blijft leesbaar; de bullets en `(A)` references zijn gewone tekst. De stap-voor-stap onthulling is een presentatie-gedrag (sessie-only), geen opslagformaat-verandering. Als OciDeck stopt, toont het deck alles — wat de statische export ook doet. Geen botsing van waarden. ### Test plan - [x] `presentation_step_plan_test.dart` — alle plan-types, edge cases, equality - [x] `callout_reveal_test.dart` — overlay filter, step sequence (forward/backward/re-entry), atomic reveal, bullet zonder callout, timeline regressie - [x] `callout_editor_test.dart` — reveal toggle bestaat, schakelen emit `calloutReveal=steps` - [x] `marp_html_service_callouts_test.dart` — `reveal:steps` flatten in HTML export - [x] `make check` groen (10.804 tests, 86.9% dekking) - [x] `make check-secrets` groen (gitleaks + trufflehog) - [x] `make sast` groen (semgrep, 0 findings) - [ ] CI `static-gate` groen Generated with [Devin](https://devin.ai)
Introduce a Flutter-free PresentationStepPlan that generalises the
timeline-only step state into a shared plan for both timeline stepping
and bullet-callout reveal (IMAGE_CALLOUTS.md §7). The plan is a pure
function of Slide data; the presenter will hold one session-local step
index and the plan translates that into what is visible on each surface.

Three plan types: NoStepPlan (no stepping), TimelineStepPlan (step 0 =
first event, unchanged from current behaviour), CalloutRevealStepPlan
(step 0 = title + image, each click reveals one bullet + its callout
targets atomically).

Tests cover all plan types, edge cases (empty bullets, zero events,
bullets without callouts) and equality.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Migrate the existing timeline-only step state to the headless
PresentationStepPlan without changing timeline behaviour:
- Rename _timelineStep → _stepIndex (session-local, plan-agnostic)
- Replace _slideUsesTimelineSteps/_timelineHasMoreSteps/_timelineRevealedFor
  with plan-based equivalents (_planFor, _planHasMoreSteps,
  _timelineRevealedFor, _calloutRevealedBulletCount)
- Route keyboard next/prev, auto-advance and audience sync through the
  same plan
- Add _announceStep() for screen-reader announcements on step changes

Wire callout reveal (reveal: steps) through the rendering pipeline:
- Add calloutRevealedBulletCount to SlidePreviewWidget
- Filter bullets and callout references in _BulletsImagePreview
- Add revealedReferences filter to CalloutOverlay
- Audience window mirrors the step index and computes reveal counts

The channel message renames timelineStep → stepIndex (audience window
updated accordingly). Static exports are unaffected — they don't pass
step state, so they show everything (flatten).

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Tests for the callout reveal step mode (IMAGE_CALLOUTS.md §7):
- CalloutOverlay revealedReferences filter (null, empty, partial)
- CalloutRevealStepPlan step sequence: forward, backward, re-entry,
  atomic bullet+targets reveal, bullet without callout
- TimelineStepPlan regression (generalisation did not change behaviour)
- HTML export flatten: reveal:steps shows all callouts (static export)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add a SegmentedButton in the callout editor to switch between "Alles
tonen" (show all, default) and "Stap-voor-stap" (step by step). The
choice persists via calloutReveal in the front matter (already wired by
#1824).

Add l10n strings for the new UI labels and the screen-reader
announcements (Stap-voor-stap, Punt, markeringen) across all 31
languages via tool/add_l10n.dart.

Docs:
- SOURCE_MAP: presentation_step_plan.dart entry
- CHANGELOG: development log entry for #1828
- USER_GUIDE: image callouts section with reveal mode explanation

Tests: reveal toggle exists, switching emits calloutReveal=steps.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
chore: raise size baselines for PresentationStepPlan migration (#1828)
All checks were successful
scans / scans (pull_request) Successful in 2m24s
static-gate / static-gate (pull_request) Successful in 6m11s
638e737511
Raise three baselines to accommodate the stepwise reveal wiring:
- slide_preview.dart file: 1044 → 1052 (+8: calloutRevealedBulletCount
  field, doc, constructor param, passing to _BulletsImagePreview, import)
- _FullscreenPresenterState class: 3424 → 3461 (+37: _stepIndex rename,
  _announceStep, plan-based helpers across presenter part files)
- SlidePreviewWidget._buildContent method: 160 → 161 (+1: passing
  calloutRevealedBulletCount to _BulletsImagePreview)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
brenno merged commit 994351d9e0 into main 2026-08-29 06:10:58 +00:00
Sign in to join this conversation.
No description provided.