|
@@ -38,57 +38,64 @@ FlutterFlow-imports binnen (getest, compileert met én zonder).
|
|
|
data-call), dus verwaarloosbaar. Een 401/404 telt als bereikbaar; alleen 5xx,
|
|
data-call), dus verwaarloosbaar. Een 401/404 telt als bereikbaar; alleen 5xx,
|
|
|
timeouts en netwerkfouten zetten de vlag. Return Type **Boolean**, geen
|
|
timeouts en netwerkfouten zetten de vlag. Return Type **Boolean**, geen
|
|
|
argumenten.
|
|
argumenten.
|
|
|
-- **Custom Widget `VerbindingsBanner`** — parameters `width` (double, optioneel),
|
|
|
|
|
- `height` (double, optioneel), `tekst` (String, optioneel); alle drie leeg
|
|
|
|
|
- laten volstaat. Toont niets zolang alles goed gaat (`SizedBox.shrink`, neemt
|
|
|
|
|
- geen ruimte in), throttlet de automatische check op **max. 1 per 20 seconden
|
|
|
|
|
- over alle pagina's samen**, en herlaadt bij een geslaagde tik de huidige route
|
|
|
|
|
- zodat de data alsnog binnenkomt.
|
|
|
|
|
|
|
+- **Custom Widget `VerbindingsBanner`** — parameters `width`, `height`, `tekst`
|
|
|
|
|
+ (alle drie optioneel; **leeg laten**). Het widget rendert zelf **niets**
|
|
|
|
|
+ (`SizedBox.shrink`) en toont de melding via de **`ScaffoldMessenger`** over de
|
|
|
|
|
+ pagina heen — daardoor kan het in de vaste-hoogte-header staan zonder iets te
|
|
|
|
|
+ breken. Throttlet de automatische check op **max. 1 per 20 seconden over alle
|
|
|
|
|
+ pagina's samen**, en herlaadt bij een geslaagde tik op "Opnieuw" de huidige
|
|
|
|
|
+ route zodat de data alsnog binnenkomt.
|
|
|
|
|
|
|
|
**Stappen in de builder:**
|
|
**Stappen in de builder:**
|
|
|
1. App Values → App State → `+ Add App State Variable`: naam **`geenVerbinding`**,
|
|
1. App Values → App State → `+ Add App State Variable`: naam **`geenVerbinding`**,
|
|
|
type **Boolean**, initial **false**, **Persisted uit**. Dit moet er zijn vóór
|
|
type **Boolean**, initial **false**, **Persisted uit**. Dit moet er zijn vóór
|
|
|
stap 2, anders kan de action niet opslaan.
|
|
stap 2, anders kan de action niet opslaan.
|
|
|
2. Custom Code → `+` → **Action** → naam `checkVerbinding` → body plakken →
|
|
2. Custom Code → `+` → **Action** → naam `checkVerbinding` → body plakken →
|
|
|
- Return Type Boolean → **Ctrl+S** (zonder die expliciete save haalt het de
|
|
|
|
|
- export niet, ook al staat er "Synced").
|
|
|
|
|
|
|
+ Return Type Boolean → **Ctrl+S**.
|
|
|
3. Custom Code → `+` → **Widget** → naam `VerbindingsBanner` → body plakken →
|
|
3. Custom Code → `+` → **Widget** → naam `VerbindingsBanner` → body plakken →
|
|
|
de drie parameters aanmaken → **Ctrl+S**.
|
|
de drie parameters aanmaken → **Ctrl+S**.
|
|
|
-4. `HeaderButtonsComponent` openen. De banner moet **onder** de bestaande Row
|
|
|
|
|
- met de knoppen, niet ernaast (anders verschuift de hamburger). Zit alles nu
|
|
|
|
|
- in één `Row`: die eerst **Wrap Widget → Column**, dan het widget als tweede
|
|
|
|
|
- kind erin slepen (Build-tab → Elements → zoeken op `VerbindingsBanner`).
|
|
|
|
|
|
|
+4. `HeaderButtonsComponent` openen en het widget **als laatste kind in de
|
|
|
|
|
+ bestaande `Row`** zetten (Build-tab → Elements → zoeken op
|
|
|
|
|
+ `VerbindingsBanner` → naar het canvas slepen). Laat `width`, `height` én
|
|
|
|
|
+ `tekst` **leeg**.
|
|
|
5. Vier pagina's hebben géén `HeaderButtonsComponent`: `mijnProfiel`,
|
|
5. Vier pagina's hebben géén `HeaderButtonsComponent`: `mijnProfiel`,
|
|
|
`wachtwoordVergeten`, `stadsactiviteitAanmaken`, `uitgaansevenementAanmaken`.
|
|
`wachtwoordVergeten`, `stadsactiviteitAanmaken`, `uitgaansevenementAanmaken`.
|
|
|
- Op de twee **aanmaakpagina's** is de banner wel zinvol (een formulier
|
|
|
|
|
- verzenden zonder netwerk) — daar het widget los bovenaan de Column zetten.
|
|
|
|
|
|
|
+ Op de twee **aanmaakpagina's** is de melding wel zinvol — daar het widget
|
|
|
|
|
+ ergens in de bestaande layout zetten (het neemt toch geen ruimte in).
|
|
|
6. Testen: `adb -s <device> shell svc wifi disable` + `svc data disable`, app
|
|
6. Testen: `adb -s <device> shell svc wifi disable` + `svc data disable`, app
|
|
|
herstarten, daarna weer `enable`.
|
|
herstarten, daarna weer `enable`.
|
|
|
|
|
|
|
|
-✅ **Live getest (2026-09-13, telefoon-emulator), alle vier de paden:**
|
|
|
|
|
-1. **online** — geen balk, layout exact als voorheen;
|
|
|
|
|
-2. **offline** — rode balk (`primary`, #9A141D) met wolkje en de tekst
|
|
|
|
|
- "Geen verbinding — tik om het opnieuw te proberen";
|
|
|
|
|
-3. **netwerk terug + tik** — balk verdwijnt **en Home is volledig hersteld**:
|
|
|
|
|
- slider met kaarten, tabs gevuld, zonder herstart;
|
|
|
|
|
-4. **geen nieuwe fouten** — de enige `NoSuchMethodError` in de log stamt van
|
|
|
|
|
- 19:18:57 (de offline start), de tik was om 19:19; de route-herlaad verliep
|
|
|
|
|
- schoon, geen go_router-fouten.
|
|
|
|
|
-Screenshots van alle drie de toestanden staan in de chat.
|
|
|
|
|
-
|
|
|
|
|
-⚠️ **Punt 3 was de reden voor een extra ronde.** In de eerste versie verdween de
|
|
|
|
|
-balk wél maar bleef het scherm leeg — "tik om opnieuw te proberen" beloofde dus
|
|
|
|
|
-meer dan het deed. Daarom herlaadt het widget nu bij een geslaagde tik de
|
|
|
|
|
-huidige route (`context.pushReplacement` op het pad uit `GoRouterState`).
|
|
|
|
|
-**Alleen bij een handmatige tik**, niet bij de automatische check: dat zou een
|
|
|
|
|
-herlaadlus geven omdat de pagina het widget opnieuw opbouwt.
|
|
|
|
|
|
|
+🛑 **Twee valkuilen die 2026-09-13 allebei toegeslagen hebben — lees dit vóór
|
|
|
|
|
+stap 4.**
|
|
|
|
|
+
|
|
|
|
|
+**(a) Wrap de Row NIET in een Column.** Dat was Claude's eerste instructie en hij
|
|
|
|
|
+is fout. De header zit in een `FlexibleSpaceBar.background` met een **vaste
|
|
|
|
|
+hoogte van 74 px**; `Align > Row` krijgt die 74 px netjes opgelegd. Zet je er een
|
|
|
|
|
+`Column` omheen, dan geeft die zijn kinderen **onbegrensde** hoogte op de
|
|
|
|
|
+hoofdas: de knoppen-Row neemt dan zijn natuurlijke ±200 px en je krijgt
|
|
|
|
|
+`A RenderFlex overflowed by 166 pixels`. **Erger nog, en dit meldt niets: de
|
|
|
|
|
+hamburgerknop verdwijnt dan uit de header op alle elf pagina's.** Alleen de
|
|
|
|
|
+overflow staat in de log; de verdwenen knop zie je pas op een screenshot.
|
|
|
|
|
+Omdat het widget geen ruimte inneemt, is een Column ook nergens voor nodig —
|
|
|
|
|
+gewoon in de bestaande Row.
|
|
|
|
|
+
|
|
|
|
|
+**(b) Laat FlutterFlow geen Container met vaste maten om het widget zetten.**
|
|
|
|
|
+De builder vult standaard `width: 200, height: 40` in. Die 40 px eet in een
|
|
|
|
|
+header van 74 px de ruimte van de knoppen op, en op 200 px breedte wrapt de
|
|
|
|
|
+meldingstekst naar meerdere regels. **Maak beide velden leeg.**
|
|
|
|
|
+
|
|
|
|
|
+✅ **Alle drie de paden nagemeten op de emulator met de definitieve opstelling
|
|
|
|
|
+(widget in de Row, geen Container):** offline → **0** render-fouten, hamburger
|
|
|
|
|
+gewoon zichtbaar, rode balk onderin met "Opnieuw"; netwerk terug + tik → balk
|
|
|
|
|
+weg en Home **volledig hersteld** (slider met kaarten, tabs gevuld), opnieuw 0
|
|
|
|
|
+fouten. Screenshots staan in de chat.
|
|
|
|
|
|
|
|
⚠️ **Wat de banner NIET oplost:** het grijze blok op Home blijft staan, want dat
|
|
⚠️ **Wat de banner NIET oplost:** het grijze blok op Home blijft staan, want dat
|
|
|
blok ís de gecrashte widget (bevinding C hieronder). De banner maakt het alleen
|
|
blok ís de gecrashte widget (bevinding C hieronder). De banner maakt het alleen
|
|
|
verklaarbaar in plaats van kapot. De vier crashplekken blijven dus een aparte
|
|
verklaarbaar in plaats van kapot. De vier crashplekken blijven dus een aparte
|
|
|
taak.
|
|
taak.
|
|
|
|
|
|
|
|
-### 🛠 Bevinding C · offline-crash op Home/P-Uitgaan-slider — Eigenaar: Claude — bezig (2026-09-13 19:45)
|
|
|
|
|
|
|
+### 🛠 Bevinding C · offline-crash op Home/P-Uitgaan-slider — Eigenaar: Claude — bezig (2026-09-13 20:10, Bob akkoord)
|
|
|
|
|
|
|
|
Aanpak: geen herbouw naar custom action, maar een **Predefined Path** op de
|
|
Aanpak: geen herbouw naar custom action, maar een **Predefined Path** op de
|
|
|
API-call (`items` = `$[:]`, is-list) en Generate Dynamic Children daaraan
|
|
API-call (`items` = `$[:]`, is-list) en Generate Dynamic Children daaraan
|
|
@@ -97,6 +104,17 @@ null-veilig, in tegenstelling tot `getJsonField(jsonBody, r'$').toList()`.
|
|
|
Plekken: `HomeSliderCall` (Home-slider), `UitgaanSliderCall` (P-Uitgaan-slider),
|
|
Plekken: `HomeSliderCall` (Home-slider), `UitgaanSliderCall` (P-Uitgaan-slider),
|
|
|
`HorecagelegenheidoverzichtCall` (horeca tab 6 — herbinding daar is voor Bob,
|
|
`HorecagelegenheidoverzichtCall` (horeca tab 6 — herbinding daar is voor Bob,
|
|
|
Claude komt niet in dat paneel op die pagina).
|
|
Claude komt niet in dat paneel op die pagina).
|
|
|
|
|
+**Stand 20:05:** de drie `items`-paths staan erin (exportgeverifieerd, 3×
|
|
|
|
|
+`static List? items`), nog nergens gebruikt. De herbinding van Generate Dynamic
|
|
|
|
|
+Children is NIET gedaan — Bob meldde dat hij zelf aan de offline-crash bezig is
|
|
|
|
|
+(verbindingscheck); Bob gaf 20:10 akkoord om dit ernaast te doen.
|
|
|
|
|
+**Terugdraaien bij calamiteit (per component één dialoog):** Carousel
|
|
|
|
|
+selecteren → Generate Dynamic Children (4e icoontje) → Value-icoontje → Set
|
|
|
|
|
+from Variable → de eigen Backend-Query-response (`HomeSlider Response` resp.
|
|
|
|
|
+`UitgaanSlider Response`) → Available Options **"No Further Changes"** →
|
|
|
|
|
+Confirm → Save. Dat is exact de oude binding; nulmeting-export van vóór alle
|
|
|
|
|
+wijzigingen staat in `/tmp/ff-checkN0`. De drie `items`-JSON-paths mogen
|
|
|
|
|
+gewoon blijven staan, die doen ongebruikt niets.
|
|
|
|
|
|
|
|
### 🐞 Nieuw gevonden 2026-09-13 (Claude, code-audit op verse export)
|
|
### 🐞 Nieuw gevonden 2026-09-13 (Claude, code-audit op verse export)
|
|
|
|
|
|