소스 검색

TASKS.md: P1-7 bijgewerkt (Tab 1 laad-crash + drupalRequest-crash gefixt en geverifieerd, Tab 3 anonieme-API-call-bug gevonden, tekst-overflow + ontbrekend header/UX-login-indicator genoteerd) + nieuwe login-crash afgerond; CLAUDE.md: JDK/Gradle-snap-update-patroon, Action-Flow-Editor per-tab-actions + Copy-Action-Chain-dubbele-variabele-valkuil, drupalRequest-return-contract-wijziging

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
bob 4 주 전
부모
커밋
4a12ffd1ad
2개의 변경된 파일188개의 추가작업 그리고 17개의 파일을 삭제
  1. 74 0
      CLAUDE.md
  2. 114 17
      TASKS.md

+ 74 - 0
CLAUDE.md

@@ -241,6 +241,26 @@ export PATH="/home/bob/fvm/bin:$HOME/.pub-cache/bin:$PATH" && /home/bob/Projects
 - **De `export PATH=...` prefix is verplicht** — Bash draait
   niet-interactief, `~/.bashrc` wordt niet geladen. Zonder prefix
   faalt het script stil ("fvm: command not found" — geen harde error).
+- **Gradle-build faalt plots met `Error resolving plugin [id:
+  'dev.flutter.flutter-plugin-loader' ...] > <versienummer>` +
+  een "restricted method"-warning erboven: check eerst welke Java
+  Flutter gebruikt, niet de code.** Bevestigd 2026-08-17: Android
+  Studio update zichzelf via snap automatisch, en de nieuwste
+  snap-revisie bundelt een steeds nieuwere JBR (ingebouwde Java) —
+  Flutter kiest bij het bouwen altijd "de JDK van de nieuwste Android
+  Studio-installatie" als eerste prioriteit. Gradle 8.12 (dit project)
+  kan niet overweg met Java 24+, en het versienummer achteraan die
+  foutmelding is precies de Java-versie van die nieuwe JBR (bv.
+  `25.0.2`) — een afgekapte/vervormde foutmelding, geen echte
+  plugin-versie-mismatch. **Vaste fix, één keer nodig, overleeft een
+  export (globale Flutter-CLI-instelling, geen projectbestand):**
+  ```
+  fvm flutter config --jdk-dir=/usr/lib/jvm/java-17-openjdk-amd64
+  ```
+  (systeem-Java 17 is stabiel, geen snap-auto-update-risico). Check bij
+  twijfel welke JDK's beschikbaar zijn met
+  `ls /snap/android-studio/*/jbr/bin/java` (elke revisie los te
+  aanroepen met `-version`) en `readlink -f /snap/android-studio/current`.
 - Interactief script (device-run + hot-restart-loop) → Bash met
   `run_in_background: true`. Volg tot minimaal "All done!" én
   idealiter een succesvolle app-launch (`Launching lib/main.dart...`,
@@ -741,6 +761,44 @@ her-select van de node bevestigt de opgeslagen waarde.
   met een "voeg widget toe"-knop — het is gewoon de bestaande
   tab-label-node, aanklikbaar als elke andere tree-rij.
 
+**Per-tab "On Tap"-logica van een `TabBar` (bv. data ophalen bij het
+wisselen van tab) leeft op de individuele `Tab`-node, niet op de
+`TabBar` zelf.** Gevonden 2026-08-17: de `TabBar`-node heeft zelf ook
+een Actions-tab met een "Action Flow Editor", maar díe biedt alleen
+generieke gestures (On Double Tap/On Long Press/On Tab Change) — leeg
+tenzij je het zelf instelt. De bestaande, al werkende per-tab-fetch
+zat in werkelijkheid op elke losse `Tab`-node (bv. `TabPersAgenda`) se­
+lecteren → Actions-tab → "On Tap: N actions". FlutterFlow bundelt deze
+losse per-tab-acties in de export tot één `onTap: (i) async { [...][i]() }`
+op de gegenereerde `TabBar`. **Praktisch gevolg:** zo'n per-tab-actie
+vuurt **nooit** voor de al-actieve standaardtab bij page-load (`onTap`
+reageert alleen op een echte tik) — heb je ook data nodig zodra de
+pagina opent, voeg dan **apart** een "On Page Load"-trigger toe op de
+Scaffold (zelfde als bij een gewone pagina) met dezelfde actieketen.
+- **Snelste manier om die actieketen te dupliceren: rechtsklik op de
+  eerste actie van de bestaande per-tab-flow → "Copy Action Chain" →
+  ga naar de nieuwe On-Page-Load-flow → "Paste Action(s)".** Werkt
+  betrouwbaar, maar **let op deze valkuil:** als de gekopieerde
+  actieketen een Custom Action met een "Action Output Variable Name"
+  bevat (bv. `drupalRequest`'s resultaat), plakt FlutterFlow die
+  variabele met **exact dezelfde naam** als een **nieuw, apart**
+  model-veld — dat geeft in de export een echte Dart-compile-error
+  ("`X` is already declared in this scope", 2x gedeclareerd in
+  `..._model.dart`). Build faalt dan pas bij de eerstvolgende
+  `flutter run`/`export-code`, niet zichtbaar in de builder-UI zelf
+  (geen foutmelding daar). **Fix meteen ná het plakken:** open de
+  geplakte Custom-Action-node → scroll (of klap "method"/eerste
+  argument dicht om ruimte te maken, zie de rechterpaneel-clipping-
+  notitie hieronder) naar **"Action Output Variable Name"** → geef 'm
+  een unieke naam → ga naar de vólgende actie in dezelfde geplakte
+  keten die deze variabele gebruikt (bv. een "Update Page State") →
+  klik het Value-veld → potlood-icoon → Source **"Action Outputs"** →
+  kies de net-hernoemde variabele opnieuw (de oude referentie blijft
+  anders naar de verwijderde/foutieve naam wijzen). **Altijd
+  verifiëren met een verse export + `flutter analyze`** vóór je
+  opnieuw deployt — dit patroon is 2x in dezelfde sessie misgegaan
+  voordat de fix duidelijk was.
+
 **Meerdere acties na elkaar op één trigger (bv. eerst App State
 opruimen, dán navigeren) instellen via de "Action Flow Editor", niet
 door in het compacte Actions-paneel te blijven scrollen.** Na de eerste
@@ -1096,6 +1154,22 @@ exacte veldnaam+type-specificatie (kost hem seconden per veld).
   `itemCount: 0` op, niet per se de `null`-jsonBody-crash die hier de
   kern van het probleem was.
 
+- **Custom action `drupalRequest` (`lib/custom_code/actions/drupal_request.dart`)
+  geeft sinds 2026-08-17 bij elke fout (non-2xx, timeout, exception)
+  een lege `[]` terug, niet meer een `{'success': false, ...}`-map.**
+  Root cause was een crash op Favorieten (zie `TASKS.md`): aanroepende
+  widget-code doet altijd blind `.toList()` op het resultaat, en
+  `.toList()` op een Map bestaat niet (`NoSuchMethodError`). Er bleek
+  nergens in de app een consument die de oude `success`/`statusCode`/
+  `body`-velden van de foutmap daadwerkelijk uitlas (gecheckt vóór de
+  wijziging), dus dit is veilig gewijzigd voor alle 3 huidige
+  gebruiksplekken (`favorieten_widget.dart` x2, `lib/kanweg/`). **Bij
+  een nieuwe aanroep van `drupalRequest` toevoegen:** ga ervan uit dat
+  je bij een fout een lege lijst terugkrijgt, geen foutdetails — wil je
+  die wél (bv. om een eigen foutmelding te tonen), dan moet de
+  functie-contract opnieuw aangepast worden en alle bestaande
+  aanroepers gecontroleerd.
+
 - **API-call `cache: true` werkt functioneel correct** — `ApiCallOptions`
   (`lib/backend/api_requests/api_manager.dart`) `extends Equatable` met
   `params`/`headers` in de `props`-lijst, dus de in-memory `_apiCache`

+ 114 - 17
TASKS.md

@@ -1,6 +1,25 @@
 # Uitgaanskrant — takenlijst
 
-**Deze sessie (2026-08-17, zelfstandig, code-only — geen browser-tab-
+**Deze sessie (2026-08-17 avond, live pair-sessie met Bob op
+emulator-5554):** begon met een Gradle-buildfout bij Bob's eigen
+`ff-run-fvm.sh`-run — root cause: Android Studio was diezelfde dag
+automatisch geüpdatet naar een snap-revisie met **Java 25** als
+ingebouwde JBR, en Gradle 8.12 (dit project) kan daar niet mee overweg.
+Fix: `fvm flutter config --jdk-dir=/usr/lib/jvm/java-17-openjdk-amd64`
+(globale Flutter-CLI-instelling, geen projectbestand — overleeft een
+export). Zie ook `CLAUDE.md` voor het herbruikbare patroon. Daarna
+login getest en **2 nieuwe crash-bugs gevonden + gefixt** (zie de
+afgeronde blokken bij P1-18 en P1-7 hieronder) en een 3e, nog niet
+gefixte bug gevonden op Favorieten-tab 3 (zie P1-7 "Nog open").
+**Belangrijk voor de volgende sessie:** ik heb tijdens het redeployen
+zelf 2x een bouwfout veroorzaakt (dubbele variabele-declaratie na
+"Copy Action Chain") — beide keren zelf gevonden via `flutter analyze`
+vóór het Bob bereikte, maar zie de nieuwe `CLAUDE.md`-notitie over dit
+patroon vóórdat je dit trucje nog eens gebruikt.
+
+---
+
+**Vorige sessie (2026-08-17 overdag, zelfstandig, code-only — geen browser-tab-
 groep gevonden bij sessiestart, dus aangenomen dat Bob niet actief
 achter zijn scherm zat en geen builder-UI geprobeerd):** begonnen met
 `ff-session-check.sh` (schoon) + een verse `flutterflow export-code`
@@ -600,6 +619,35 @@ Het losse debug-dialoogje (AlertDialog "melding" met de rauwe JSON) is
 blijven staan — niet meegenomen in deze fix, kan later nog opgeruimd
 worden als cosmetische bijvangst. Uit deze lijst verwijderd.)*
 
+*(Nieuwe, andere login-crash gevonden + afgerond 2026-08-17 avond —
+Claude, builder + live logcat-diagnose op emulator-5554. Dit was géén
+regressie van P1-18 hierboven, maar een nog niet eerder gevonden
+tweede bug op dezelfde knop: ná een geslaagde `drupalLogin`-aanroep
+haalde de knop's "Inloggen"-actie **nogmaals** en **overbodig** de
+sessievelden uit het resultaat via losse JSON-Path-bindingen
+(`$.user.uid`, `$.user.name`, `$.user.mail`) — maar `drupalLogin`
+retourneert die velden plat (`uid`/`name`/`mail`, geen `user`-object),
+dus alle drie gaven `null`. Voor de 2 String-velden onschuldig
+(`null.toString()` → tekst "null"), maar `userUid` is `int`-getypeerd
+in App State → een `null` daarin toekennen crashte de app **stil**
+(geen rode foutmelding, gewoon geen "Succesvol ingelogd!"-melding en
+geen reactie op de knop) vóórdat de succes-snackbar ooit getoond kon
+worden. **Root cause was sowieso overbodige code:** `drupalLogin`
+(`lib/custom_code/actions/drupal_login.dart`) zet deze velden al zelf
+correct en veilig in App State (met `int.tryParse(...) ?? 0` voor
+uid) vóórdat het resultaat teruggegeven wordt. **Fix:** de 6
+redundante "Update App State"-acties op de knop's on-tap-flow
+(Action Flow Editor) volledig verwijderd — de knop doet nu alleen nog
+`drupalLogin` aanroepen en op basis van `resultDrupalLogin != null`
+de juiste snackbar tonen. Bevestigd via verse export
+(`login_widget.dart` bevat de `getJsonField(..., $.user.*)`-blokken
+niet meer) en live op emulator-5554 (inloggen met gebruikersnaam geeft
+nu de "Succesvol ingelogd!"-snackbar). **Bijvangst, zelfde diagnose:**
+inloggen met e-mailadres i.p.v. gebruikersnaam geeft terecht "Inloggen
+mislukt" — Drupal's `user/login.json` accepteert kennelijk geen
+e-mailadres als username. Geen bug, maar wel een open feature-vraag
+aan Bob als e-mail-login gewenst is.)*
+
 *(P1-1 volledig afgerond 2026-08-10 avond — Bob, builder, alle 4
 sub-punten bevestigd via verse export: `HomeUitgaanSliderComponent`
 (= P0-1), `PUitgaanSliderComponent`, `EvenementComponent`,
@@ -984,20 +1032,68 @@ lokale/UI-kant + look&feel oppakken zolang die niet op Drupal wacht.
      wijziging, geen quick win.
   Geen van beide is deze sessie uitgevoerd (buiten scope voor
   code-only werk, en vraagt eerst een ontwerpkeuze van Bob).
-- **Tab 1 "Persoonlijke agenda"** (events in favoriete gemeente(n)) —
-  **uitgezocht (2026-08-14, Claude, code-audit): geen nieuwe Drupal-call
-  nodig, bestaande calls volstaan al.** `UitgaanstabelCall`/
-  `UitgaanSliderCall` (`api_calls.dart`) accepteren allebei al een
-  `townid`-parameter (nu gebruikt door `PUitgaantabelKaartComponent`/
-  `PUitgaanSliderComponent` voor de huidige gekozen gemeente) — exact
-  wat hier nodig is. Bouwplan: loop over `favorieteGemeenteIds` (App
-  State, al gevuld zodra Tab 2 ooit favorieten heeft) en roep
-  `UitgaanstabelCall` per gemeente-id aan, resultaten samenvoegen tot
-  1 lijst (of simpeler: hergebruik `PUitgaantabelKaartComponent` als los
-  blok per favoriete gemeente, met een kopje erboven = gemeentenaam).
-  Geen Drupal-wijziging nodig — wel afhankelijk van Tab 2's
-  favoriet-toggle-UI (zie hierboven), want zonder die blijft
-  `favorieteGemeenteIds` altijd leeg.
+- **Tab 1 "Persoonlijke agenda" — bleek al gebouwd (niet door deze
+  lijst gedekt, `TASKS.md` liep achter), en kreeg 2026-08-17 avond
+  2 bugfixes (Claude, builder, bevestigd via verse export +
+  `flutter analyze` + live op emulator-5554):**
+  1. De data-fetch (`drupalRequest` POST naar
+     `.../favorieten_agenda.json`) hing aan de `TabBar`'s `onTap`
+     op de `Tab`-node zelf (zie `CLAUDE.md`) — die vuurt alléén bij
+     een echte tik, dus **nooit** voor de al-actieve standaardtab bij
+     page-load. Fix: Scaffold's eigen **"On Page Load"**-trigger
+     toegevoegd met dezelfde actieketen (via rechtsklik op de
+     bestaande `TabPersAgenda`-Tab-node → Actions → "Copy Action
+     Chain" → nieuwe On-Page-Load-trigger → "Paste Action(s)") — let
+     op de `CLAUDE.md`-notitie over de dubbele-variabele-valkuil die
+     dit trucje veroorzaakt, dat moest ik zelf nog corrigeren.
+  2. Los daarvan crashte de pagina stil (`NoSuchMethodError: Map heeft
+     geen 'toList'`) zodra de call een niet-2xx-respons kreeg, omdat
+     de custom action `drupalRequest`
+     (`lib/custom_code/actions/drupal_request.dart`) bij een fout een
+     `{'success': false, ...}`-Map teruggaf terwijl de aanroepende
+     code altijd blind `.toList()` erop aanriep. Fix: alle 3
+     foutpaden in `drupal_request.dart` (non-2xx, timeout, exception)
+     geven nu `[]` terug i.p.v. een map — bevestigd via verse export.
+     **Live bevestigd:** `favorieten_agenda.json` geeft momenteel nog
+     een **404** terug (Bob kijkt hier zelf naar, zie boven) — de tab
+     blijft nu netjes leeg i.p.v. te crashen.
+- **Nieuw gevonden, nog niet gefixt (2026-08-17 avond, Claude,
+  code-audit): Tab 3 "Favoriete Gelegenheden" roept zijn API-call
+  altijd anoniem aan.** [favorieten_widget.dart:362](lib/favorieten/favorieten_widget.dart:362)
+  — `FavorietenAgendaCall.call()` wordt zonder argumenten aangeroepen,
+  terwijl de call zelf `sessionName`/`sessionId`-parameters verwacht
+  die in de Cookie-header horen
+  (`'{{session_name}}={{sessid}}'` in `api_calls.dart:34`). Zonder die
+  twee gaat de aanroep altijd **zonder sessie** naar Drupal → een
+  ListTile met letterlijk **"null"** als titel i.p.v. de favoriete
+  horeca-gelegenheden, ook als je wél bent ingelogd. **Fix (builder):**
+  ListView selecteren → Backend Query-icoon (database) →
+  `FavorietenAgenda`-call openklappen → `sessionName` = Set from
+  Variable → `FFAppState().userSessionname`, `sessionId` = Set from
+  Variable → `FFAppState().userSessionid`.
+- **Nieuw gevonden, cosmetisch (2026-08-17 avond): tekst-overflow op
+  Tab 2 en Tab 3's beschrijvingsregel.** De `Text`-widgets "De
+  gemeentes die je hebt gemarkeerd..." (key `o7pt2vls`,
+  [favorieten_widget.dart:332](lib/favorieten/favorieten_widget.dart:332))
+  en de vergelijkbare op Tab 3 lopen zichtbaar van het scherm af (geen
+  wrap, geen horizontale padding op de omringende `Column`).
+- **Nieuw gevonden, structureel (2026-08-17 avond): de hele
+  Favorieten-pagina mist een header/drawer.** Geen "☰"-menu, geen
+  terugknop — de pagina begint direct bij de `TabBar`, enige uitweg is
+  Android's systeem-terugknop. Bovendien zijn alle 4 tab-labels
+  afgekapt op telefoonformaat ("Persoon…", "Favoriete…" x2,
+  "Gebruike…") — de `TabBar` is te smal voor 4 volledige labels.
+  Vraagt een structurele aanpassing (Scaffold met AppBar/Drawer zoals
+  andere pagina's, of kortere tab-labels/kleiner lettertype), geen
+  quick fix.
+- **Nieuw gevonden, UX-gat (2026-08-17 avond): nergens in de app is
+  zichtbaar dát je bent ingelogd**, behalve als je zelf naar
+  Favorieten-tab 4 navigeert. De drawer's "Mijn Account"-item opent
+  altijd het kale login-formulier, ook met een actieve sessie — geen
+  check op `FFAppState().userSessionid`. Sluit aan bij Bob's eigen
+  wens (2026-08-17): gebruikersnaam + uitlog-knop + link naar
+  Favorieten zichtbaar maken zodra ingelogd, bv. in de drawer i.p.v.
+  het statische "Login"/"Mijn Account"-item.
 - **"Gebruiker"-tab, "Uitloggen"-knop afgerond (2026-08-15, Claude,
   builder, bevestigd via verse export + `flutter analyze`: 0 errors).**
   `favorieten_widget.dart` heeft nu een 4e tab "Gebruiker" (via TabBar's
@@ -1008,10 +1104,11 @@ lokale/UI-kant + look&feel oppakken zolang die niet op Drupal wacht.
   `userMail`), Action 2 = Navigate To Login met "Allow Back Navigation"
   uit (genereert `context.goNamed(...)` i.p.v. `pushNamed`, dus geen
   terugknop-pad naar de net-verlaten sessie). **Nog open, zelfde
-  tab:** "Wachtwoord wijzigen" en "Account verwijderen" (zie Bob's
+  tab:** geen gebruikersnaam zichtbaar (zie UX-gat hierboven),
+  "Wachtwoord wijzigen" en "Account verwijderen" (zie Bob's
   beslissing 3 hieronder — account verwijderen heeft mogelijk
   AVG-implicaties aan Drupal-kant en is een App-Store-vereiste, zie
-  daar) — deze twee zijn niet meegenomen, eigen vervolgtaak.
+  daar) — deze zijn niet meegenomen, eigen vervolgtaak.
 - **Open vraag aan Bob (blokkeert de Drupal-sync van favorieten):**
   bestaat er al een Drupal-endpoint om een favoriet (horeca of gemeente)
   toe te voegen/verwijderen voor een ingelogde gebruiker (bv.