*Opgeschoond 2026-09-19 (van 1924 naar ~800 regels). Afgeronde taken zijn
verwijderd, niet gearchiveerd — ze staan in de git-historie en de blijvende
inzichten in CLAUDE.md. Alles hieronder is open werk. Staat iets er niet
meer in, dan is het klaar of afgewezen — niet opnieuw agenderen.*
Voor een nieuwe sessie: pak een taak uit "Claude — open", zet er meteen
— bezig achter in dit bestand (een echte Edit, niet pas bij het afsluiten;
andere sessies delen deze working directory), en verifieer elke builder-wijziging
met een verse export. Taken onder "Bob — open" niet zelf oppakken.
De app-kant is vrijwel af. Op 2026-09-19 zijn o.a. afgerond: de
header-locatie-keten (Home toont Heel Nederland, provinciepagina de
provincienaam), het adaptive icon, de loginpagina, het drawer-logo, Crashlytics,
"Mijn aanmeldingen", de categoriedropdown op het horeca-overzicht, de
horeca-agenda-entiteiten en de opruimronde. Op 2026-09-20 kwamen daar het dichtgezette API-oppervlak (42 → 22 methodes,
het name-lek weg) en de feature graphic bij. Wat rest is livegang-werk:
Google Play en één doorloop die alleen Bob kan doen.
| # | Taak | Kort |
|---|---|---|
| G0.6 | Play-screenshots | ✅ Nieuwe set van 10 klaar (2026-09-19 avond). Alleen tel-04-horeca.png moet over zodra Show Test Ads uit staat |
| 112 | Restje zoek-stad: lege API-call opruimen | Eigenaar: Bob. SelectStateDropDownComponent → Actions → On Page Load → Conditional Action 5 (gemeenteSelectId is set/non-empty) → TRUE-tak → Action 13, Custom Action drupalRequest met url/sessionName/sessionId/token/body allemaal Unset. Staat sinds 2026-09-20 op disabled; kan weg via ⋮ → Delete Action. Vlak eronder staat Conditional Action 16 (apiGemeenteResultInitalize -> Succeeded) met twee lege takken — mag in dezelfde moeite weg |
| 114 | Opruimen na de filterbalk-ombouw | Eigenaar: Bob. Restjes van taak 113 (afgerond 2026-09-20): (a) component-parameter parameter1 op FilterBalkComponent ontstond automatisch bij Convert to Component en wordt nergens gelezen — mag weg, en daarmee ook de meegegeven waarde op Home en PUitgaanPage; (b) page state zoekOpen op Home is overbodig (de App State-versie stuurt alles); (c) App State zoekActief (Boolean) bestond al vóór deze taak en heeft 0 gebruikers; (d) wegwerp: componenten FilterBalkKanweg en FilterBalkComponentCopy + pagina's homeCopy en PUitgaanPageCopy. Geen van alle blokkeert iets — dart analyze geeft 0 errors |
| # | Taak | Waarom nu |
|---|---|---|
| G | Google Play-checklist G0–G4 | Volledige checklist hieronder |
| 65 | De ingelogde doorloop | Kernfuncties zijn nooit op een release-build getest. Claude kan dit niet (geen wachtwoorden) |
| AdMob | Show Test Ads uit |
App Settings → AdMob. Wacht op de Google-registratie |
| P1-17 | Vertalingen | ✅ Rond voor de app (2026-09-20): 0 van de 218 gerenderde sleutels mist nog Engels. Alleen de vier lege-lijst-teksten op mijnProfiel blijven over — dat zijn parameterwaarden, geen i18n-sleutels |
| Drupal | taak 56-restant · taak 28/109 | Cron-description op "xx days" ✅ gedaan · events zonder categorie gaat via de importer |
| Bij livegang | Schakelaars en opruimklussen | Eigen blok hieronder |
| ✅ AF (Bob 2026-09-20, export-geverifieerd): volgorde is nu slider → banner → filterbalk → lijst | ||
✅ AF (Bob 2026-09-20): Container 65/65/105/105 mét de padding erin, dus de banner krijgt zijn volle 50 resp. 90 dp én de lucht tot de slider blijft |
||
| 121 | 15 verweesde mappen in lib/ opruimen |
Staan lokaal én in git, maar FlutterFlow levert ze niet meer. Twee ervan breken dart analyze. Eigen blok hieronder |
| 120 | 12 hardcoded kleuren aan thematokens binden | ⚠️ Claude kwam er 2026-09-20 niet in: widget-selectie in de tree landt niet in Bob's huidige Chrome-venster. Inventaris mét vindplaatsen staat klaar |
✅ AF (Bob 2026-09-20, export-geverifieerd): READ_CALENDAR/WRITE_CALENDAR én NSCalendarsUsageDescription zijn weg; CAMERA staat er nog (terecht) |
||
| 118 | AdMob EU-consentbericht | ⚠️ Half: de FlutterFlow-toggle staat goed, maar het bericht moet in de AdMob-console gepubliceerd zijn. Eigen blok hieronder |
| 122 | Teksten aanmaakpagina's | ✅ A/B/C af (Claude 2026-09-20, 19 teksten, export-geverifieerd): verkeerde woorden, typefouten, technische veldnamen en het sterretje bij de categoriekeuze. Open blijven D (hints die het label herhalen), E-restje en F (Select... op een NL-pagina) — eigen blok hieronder |
| 123 | mijn_stadsrechten uitbreiden met de keten |
Code staat klaar en is op productie getest. Vervang regels 316-372 van custom.evenementen_aanmaken.inc + cc all. Blokkeert 124 |
| 124-126 | Stadsrechten-cascade op stadsactiviteitAanmaken |
Voorvullen van provincie/gemeente/plaats (124), een crash bij een lege plaatsenlijst (125) en een stille verkeerde plaats bij het wisselen van gemeente (126). Eigen blok hieronder |
| 127 | Kopie-knop op MijnAanmeldingen (clonen) |
Wens Bob 2026-09-20, vóór de livegang. Backend bestaat al; Drupal-patch voor 3 gaten staat klaar en is getest (127-A). App-deel in stappen B t/m F; het activiteitendeel (127-E) deelt de cascade met 124. Eigen blok hieronder |
#
(P2-45b, P2-45c en 76 zijn op 2026-09-19 afgerond en geverifieerd met een verse export — zie de commit van die datum.)
⬜ De vier lege-lijst-teksten op mijnProfiel hebben geen Engelse
vertaling. Een component-parameterwaarde is een letterlijke string, geen
i18n-sleutel, dus er is geen globe. Bewuste keuze (2026-09-20); meepakken bij
de bredere vertaalronde (P1-17), niet los.
⬜ MijnAanmeldingen: de "Gepubliceerd"-tak is nooit met echte data gezien.
Alle testaanmeldingen op devbob staan op status: 0, dus de lijst toont
uitsluitend "Wacht op goedkeuring". De tekst komt kant-en-klaar uit Drupal
(status_label, een ternary op (int) $node->status === 1), dus het risico is
klein — één testnode publiceren en de lijst openen volstaat om dit af te
vinken.
⬜ Optioneel: ingang naar MijnAanmeldingen op Favorieten tab 4. Nu loopt
de enige route via MijnProfiel → Bekijk alles. Dat volstaat; alleen
oppakken als je 'm ook direct vanaf Favorieten wilt kunnen bereiken.
Ideeën die af zijn onderzocht maar bewust wachten. Bob 2026-09-20: eerst live, dan pas kijken of dit überhaupt de moeite is.
Bob's vraag: "ik kan een lijstje domeinen opgeven — maar hoe weet mijn app wat de URL is? een evenement, een horecagelegenheid, een stadspagina?"
Antwoord: Android geeft de VOLLEDIGE URL aan de app, en de app moet die zelf vertalen naar een route. Dat vertalen is het hele werk; het domeinlijstje bepaalt alleen of de app aan de beurt komt.
Daarom NIET uitgaanskrant.com registreren. Twee redenen:
/nl/Noord-Holland/Amsterdam/Bimhuis-Amsterdam). De app kan daar niets mee
zonder Drupal om een vertaling te vragen — een extra endpoint erbij.Wel uitgk.com. Dat is jouw eigen korte domein, het wordt alleen gebruikt door
de deelknop (event_current_widget.dart:414) en door zetInAgenda
(zet_in_agenda.dart:42), en het heeft één voorspelbare vorm: /<nid>.
Het type is met één API-call te bepalen — gemeten 2026-09-20:
flutterflow_events.json?nid= |
flutterflowmobiel_establishment_info.json?nid= |
|
|---|---|---|
| 222338 (event) | 1 rij, mét horecagelegenheidnid=75459 |
0 rijen |
| 75459 (zaak) | 0 rijen | 1 rij |
Dus: één call naar flutterflow_events.json?nid=X; komt er een rij uit, dan is het
een event en heb je de horecaid meteen te pakken (die heeft EventCurrent
als tweede parameter nodig). Nul rijen → behandel als zaak →
HorecagelegenheidCurrent(nid: X). Allebei leeg → Home.
Stadspagina's erbuiten laten. PUitgaanPage wil een plaats-tid, en die staat
in geen enkele URL — dat zou een derde lookup via plaatsen.json vergen voor
weinig winst.
Twee routes om uit te kiezen:
uitgk.com/222338) + een routerpagina in de app.
Mooiste links. Vergt een pagina met een pad-parameter op rootniveau (/:nid),
de API-call hierboven en een conditionele navigatie. ⚠️ Open vraag: kan
FlutterFlow een routePath /:nid op rootniveau aan zonder te botsen met /home,
/favorieten enz.? go_router matcht exacte paden eerst, dus het zou moeten
kunnen — maar dat is niet gemeten. Eén testpagina + een export geeft uitsluitsel.uitgk.com/eventCurrent?nid=..&horecaid=... Dan matcht
go_router het pad meteen en hoeft er in de app niets gebouwd te worden (het
custom scheme werkt al precies zo). Prijs: lange, lelijke deellinks, plus een
redirect-regel op uitgk.com voor wie de app niet heeft.Bob 2026-09-20: naar 2.0. "niet belangrijk voor de livegang, als het überhaupt belangrijk is." Terecht — de deelknop werkt al, hij opent alleen de website in plaats van de app. Pak dit pas op als blijkt dat mensen gedeelde links vaak volgen.
Volgorde-afhankelijkheid, en dus hoe dan ook na de launch:
/.well-known/assetlinks.json op uitgk.com moet de SHA-256 van het
Play-app-signing-certificaat bevatten, en dat certificaat krijg je pas ná de
eerste upload (Play Console → Setup → App integrity). Vóór die tijd is de
verificatie niet af te maken.
Elke tab-tik doet een verse fetch, ook als je terugkeert naar een tab die je al
bezocht hebt; heen-en-weer klikken tussen zes tabs haalt dus zes keer opnieuw op.
Een guard ("sla de fetch over als alleXxx al gevuld is") lost dat op, maar kost
een conditie in vijf actieketens — en juist die dialoog is op deze pagina fragiel.
Alleen doen als het in de praktijk hindert.
*Opgesteld 2026-09-19. Account aangemaakt 2026-09-18 als Organisatie (Digital Force); wacht op verificatie. Vervangt taak 63 (a-i) en punt 2 van "Bob's 7" — die twee niet meer los afwerken. Vink hier af.*
Bevestigd via Google's eigen documentatie, 2026-09-19:
#
flutter_launcher_icons, en een crash op de splash zonder
--include-assets), plus een keystore die er nog niet is
(android/app/build.gradle:80 staat op signingConfigs.debug).
Sub-route: download het AAB in FlutterFlow en upload het handmatig in
Play Console. De directe "publish to Play"-koppeling vergt een Google
Play service-account-JSON; pas doen als handmatig uploaden gaat vervelen.
⚠️ Blijft staan als G4.3: controleer het icoon op het AAB dat je uploadt.~/uk-play-assets/play-teksten.md (gered uit een
vluchtige sessie-scratchpad, 2026-09-19 — stond nergens duurzaam).
⏳ Kan pas ingevoerd worden ná G1.1 (de app moet bestaan in Play Console).--release-build (export mét --include-assets,
flutter_launcher_icons vooraf, x64 voor de AVD's), uitgelogd (pm clear),
Nederlandse app-locale: 6 telefoon (1080x1731), 2x 7" tablet (1200x1812, AVD
tijdelijk op wm size 1200x1920 / density 240), 2x 10" tablet (2560x1456).
Status- én navigatiebalk weggecropt; alle ratio's onder 2:1.
📁 ~/uk-play-assets/screenshots/ + play-screenshots.zip; de oude set staat
in screenshots-oud-2026-09-19-middag/ (Claude gooit niets weg).
Opgelost t.o.v. de eerste set: header toont Heel Nederland i.p.v.
"Amsterdam (gemeente)"; de twee 10"-shots zijn nu echt verschillend (Home +
menu, md5 gecheckt); tel-05-zaak.png is het Bimhuis (nid 75459) mét
gevulde agenda.
🔴 Nog één keer over: tel-04-horeca.png toont nog de AdMob-testadvertentie
(showsTestAd: true in de export). Zodra Show Test Ads uit staat schiet
Claude die ene opnieuw — dat is 2 minuten werk, geen nieuwe build nodig
(deep link horecagelegenhedenOverzichtCurrent?plaats=28695).
🔸 Opgevallen, geen blokker: op de detailpagina's (tel-02-event,
tel-05/06-zaak) toont de header Amsterdam (de default
gemeenteSelectId), terwijl Home Heel Nederland zegt. Voor een event in
Steenwijk oogt dat wat vreemd; als je dat consequent wilt, is dat een aparte
taak op de header-keten.~/uk-play-assets/feature-graphic/DEFINITIEF-feature-graphic-1024x500.png
— 1024×500, RGB zonder alpha, 88 kB; voldoet aan de Play-eisen.
B = het complete app-icoon links als afgeronde tegel op leisteen
(#3E454C), rechts de naam + tagline + oranje accentstreep. Rood op
leisteen geeft het icoon contrast; de twee andere merkkleuren doen de rest.
Variant A (merkelement groot op merkrood) staat ernaast, niet gekozen.
feature.py staat erbij: tekst of kleur wijzigen is één regel + opnieuw
draaien. Rest nog: uploaden bij G3.2.#
com.uitgaanskrant.app — onveranderlijk na de eerste
upload, dus controleer 'm.#
https://uitgaanskrant.com/nl/support/privacybeleid
(anoniem 200, gemeten 2026-09-16).https://uitgaanskrant.com/nl/support/mobieleapp
⚠️ NIET /nl/account-verwijderen — die geeft anoniem 403 en reviewers
openen 'm uitgelogd. Taak 85 heeft de in-app-knop al naar dezelfde URL gezet.INTERNET, CAMERA, READ_EXTERNAL_STORAGE,
WRITE_EXTERNAL_STORAGE, plus via AdMob/Firebase ACCESS_NETWORK_STATE,
WAKE_LOCK, FOREGROUND_SERVICE, AD_ID en drie ACCESS_ADSERVICES_*.
Declareren: Advertising ID → JA (verplicht, AD_ID staat erin),
crashlogs/diagnostiek (Crashlytics), gebruikersnaam/e-mail (login), en
foto's (camera + galerij, voor de aanmaakpagina's). Transport is
versleuteld en verwijdering is mogelijk → beide aanvinken.#
assets/images/app_launcher_icon.png kun je
NIET rechtstreeks uploaden: die is 1900×1900 en 1,1 MB, terwijl Play
exact 512×512 en max 1 MB eist (gemeten 2026-09-20).
✅ Klaargezet: ~/uk-play-assets/play-icon-512.png — 512×512, RGB,
110 kB, LANCZOS-verkleind uit datzelfde bronbestand (dat volledig
ondoorzichtig is, dus er is niets platgeslagen). Gebruik die, en niet
de adaptive foreground.
🔸 Opgevallen, jouw keuze: het woordmerk beslaat maar een smalle strook
van het rode vlak. Op 512 is het scherp, maar in de Play-lijst wordt het
icoon rond de 48 px getoond en dan is "Uitgaanskrant.com" niet meer te
lezen — je ziet dan vooral een rood vlak. Een variant met alleen het
kalendertje groot (of de tekst fors groter) leest daar beter; dat is wel
een ontwerpbesluit, geen fout.#
1.0.0+1
(pubspec.yaml:18). Bij de FlutterFlow-route: App Settings → App Details.flutter_launcher_icons wél? Lokaal
gebouwd draagt het bestand anders het Flutter-vogeltje. Niet aannemen.#
Ja, betaald — en anders dan Google een ABONNEMENT. Google Play is eenmalig $25; het Apple Developer Program kost ~$99 per jaar en moet elk jaar verlengd worden, anders verdwijnt de app uit de App Store. Verifieer het actuele bedrag bij inschrijving.
Wat je al hebt en meeneemt:
Info.plist staan al goed (Camera, PhotoLibrary,
Calendar) — geverifieerd 2026-09-19, precies 3 keys.Wat er nieuw bij komt:
ios/Runner.xcodeproj/project.pbxproj
beweegt mee in elke export.Route wanneer het zover is: FlutterFlow kan ook voor iOS bouwen, dus een Mac is niet strikt nodig. Punt 5 en 6 zijn het echte werk; de rest is administratie.
Verse export bevestigt de body-Column van PUitgaanPage:
[slider (if !zoekOpen), Container > AdBanner, Expanded > FilterBalkComponent,
Expanded > lijst]. Precies de gevraagde volgorde.
Eindstand in de export: Container(height: 65/65/105/105) > Padding(top 15) >
FlutterFlowAdBanner zonder eigen width/height (dus adaptive). De banner houdt
daarmee zijn volle 50 dp op telefoon en 90 dp op tablet over, en de 15 dp lucht
tot de slider — die Bob er bewust in had gezet — blijft staan.
🔸 De zwarte laadtekst van FlutterFlowAdBanner blijft hoger dan de Container en
tekent dus even buiten zijn kader. Inherent aan de gegenereerde widget, niet vanuit
de builder te clippen. De layout beweegt niet meer, en dat was het doel.
Afgerond 2026-09-20 (Claude, in de builder, 19/19 geverifieerd met een verse export). Punt A (gewoon fout), punt B (technische veldnamen) en punt C (het sterretje bij de categoriekeuze) zijn gedaan op béide pagina's:
| was | is nu |
|---|---|
ACT kop "Categorie evenement" |
"Categorie activiteit *" / Category * |
EVT kop "Categorie evenement" |
"Categorie evenement *" / Category * |
| "Selectee..." | "Selecteer..." |
| "Datum eind" (4×) | "Einddatum" / End date |
| "WebsiteURL" (2×) | "Website" |
| "TicketsURL" | "Ticketlink" / Ticket link |
| "Toelichting Entree" (2×) | "Toelichting entree" |
| "Uw Horecagelegenheid" | "Je horecagelegenheid" / Your venue |
EN Zipcde · Organisatsion · Feeprice (2×) |
Zipcode · Organisation · Admission price |
EN Title cityactivity · Title cityactvity |
Activity title · Event title |
Nog open — schrijfkeuzes, bewust bij Bob gelaten:
Text-label
bóven het invoerveld én een labelText én een hintText; staan die alle drie
op hetzelfde woord, dan leest de gebruiker het drie keer. Bob heeft de losse
Text-labels van "Toelichting Entree" en "Entreeprijs" al weggehaald; over
zijn nog de label/hint-paren: ACT Einddatum · Adres · Postcode ·
Entreeprijs, EVT Einddatum · Toelichting entree · Entreeprijs. Een voorbeeld
in de hint doet meer werk dan een herhaling — "bijv. 7,50", "1012 AB".ACT EN Description activity tegenover EVT EN Event description.Select... staat er
nog 4× (ACT xiba4gka, l9f37oxb, ajotnz1f; EVT 2hitlrxa, ht4toe4o) en
Search... 1× (EVT qtnlg7nd), terwijl de categorie-dropdown op ACT wél
"Selecteer..." / "Zoek..." zegt. Mechanisch werk; Claude kan dit oppakken.EVT. De intro zegt "van je
onderneming", de kop en de dropdown zeggen "horecagelegenheid", de
hulpregel zegt "de zaak waar het evenement plaatsvindt". Eén woord kiezen
is een besluit voor Bob, geen opruimklus.stadsactiviteitAanmaken — Drupal-deel · Eigenaar: BobCode staat klaar en is getest (2026-09-20, Claude): vervang in
sites/all/modules/custom/custom.evenementen_aanmaken.inc de regels 316 t/m
372 (docblock t/m sluitende accolade van _custom_mijn_stadsrechten_service())
door de aangeleverde versie. Daarna drush @<alias> cc all.
Waarom: field_town_access mag een term op elk van de drie niveaus van
de town-vocabulary bevatten — plaats (tot 2026-08-27), gemeente (huidige
standaard) of provincie (de widget staat op Max depth 2 en laat dat toe; Bob
geeft ze bewust op provincieniveau, dat scheelt veel werk). De app stopte die tid
rechtstreeks in plaatsen_bij_gemeente, en dat geeft bij provincie én plaats een
lege lijst → zie taak 125.
De nieuwe versie geeft per recht de volledig uitgeklapte keten terug:
niveau · provincie_tid/_titel · gemeente_tid/_titel ·
plaats_tid/_titel · keten ("provincie|gemeente|plaats", ontbrekende delen
leeg) · label (bv. "Noord-Brabant (hele provincie)"). tid, titel,
parent_tid en parent_titel blijven ongewijzigd staan, dus bestaande
consumenten merken niets. Sortering is hiërarchisch i.p.v. alfabetisch op titel.
Getest op productie onder een testnaam, alle drie de niveaus:
| account | recht | keten |
|---|---|---|
| bobcity | 28694 Amsterdam (gemeente) | 28666\|28694\| |
| bobhoreca | 27409 Noord-Brabant (provincie) | 27409\|\| |
| Team Klein Frankrijk | 29912 Zuid-Holland (provincie) | 29912\|\| |
De eerste dropdown in het Waar-blok van stadsactiviteitAanmaken moet de drie
cascade-dropdowns voorvullen tot zover het recht reikt, in plaats van alleen
createGemeenteID te zetten:
| recht | voorvullen | gebruiker kiest nog |
|---|---|---|
| provincie | provincie | gemeente + plaats |
| gemeente | provincie + gemeente | plaats |
| plaats (oud) | alle drie | niets |
Stappen: dropdown-waarde omzetten van $[:].tid naar $[:].keten (label
op $[:].label), plus drie custom functions van één String-argument
(ketenProvincie / ketenGemeente / ketenPlaats → split('|')[n]). Die ene
parameter is bewust: een lookup op de hele respons vraagt een custom function met
meerdere argumenten, en die binding loopt in de Action Flow Editor structureel
vast (zie CLAUDE.md). On Selected → Update Page State voor
createProvincieID/createGemeenteID/createPlaatsID + Set Form Field op de
drie dropdowns.
Een lege Set Form Field-waarde wordt geweigerd ("Value cannot be empty"), dus
voor de lege delen van de keten is Reset Form Fields nodig — wat meteen de
tweede helft van taak 126 afhandelt.
Voorvullen, niet verbergen (besluit Bob 2026-09-20): met verbergen kun je achteraf niet meer wisselen zonder eerst de rechten-dropdown leeg te maken.
stadsactiviteit_aanmaken_widget.dart:1878 doet
(getJsonField(respons, r'$[:].plaatsid', true) as List?)!. getJsonField geeft
bij 0 matches null — ook met isForList: true, want de isEmpty-check
staat ervóór ([flutter_flow_util.dart:356]). Een lege respons [] geeft dus
Null check operator used on a null value; in een release-build een grijs blok
zonder melding.
Treedt nu op bij elke provincie- of plaats-tid in field_town_access, maar staat
los van taak 123/124: ook een gemeente zónder plaatsen in de taxonomie geeft
dezelfde crash. Zelfde patroon staat op de gemeente- en provincie-dropdown
van diezelfde pagina — alle drie langslopen.
Fix: Generate-Dynamic-Children-achtige null-veiligheid via een Predefined Path
op de API-call ($[:], Is List) i.p.v. een JSON Path — dat genereert
(XCall.items(jsonBody)?.toList() ?? []). Recept staat in CLAUDE.md.
createPlaatsID bij het wisselen van gemeente · Eigenaar: nader te bepalenGeen van de vier dropdowns in het Waar-blok reset de onderliggende. Scenario:
kies gemeente A → plaats A₁ (createPlaatsID gezet) → wissel naar gemeente B.
De Plaats-dropdown toont dan weer zijn hint (FlutterFlowDropDown filtert een
waarde die niet in de opties zit weg, [flutter_flow_drop_down.dart:101]), maar
createPlaatsID houdt A₁ vast. De verzendknop blijft dus zichtbaar en je
dient in voor de vorige plaats. Stil, geen foutmelding.
Fix: Reset Form Fields + Update Page State (Reset Value) op de onderliggende
velden in de On-Selected van provincie, gemeente én de rechten-dropdown. Overlapt
met taak 124 — samen oppakken.
MijnAanmeldingen — evenement én activiteit klonenWens Bob (2026-09-20): op elke kaart in Mijn aanmeldingen een knop Kopie. Eén tik opent het aanmaakformulier volledig ingevuld; de gebruiker vult de datum aan, past eventueel iets aan en dient in. Vóór de livegang. Beide types.
De datum komt bewust NIET mee — je kloont juist om hetzelfde op een nieuwe datum te zetten. Dat zit al zo in de kloonbron.
GET /nl/flutterdrup/aanmelding_kloonbron.json?nid=X bestaat en staat aan op
productie (custom.mijn_aanmeldingen.inc:248, resource aanmelding_kloonbron,
operation index). Sessie-geauthenticeerd, met eigenaarscheck (403 op andermans
node, 404 onbekend, 400 bij een ander contenttype). De sleutelnamen zijn met
opzet gelijk aan wat evenementen/create en stadsactiviteiten/create
verwachten — tids en fids, geen weergavewaarden.
Aan de app-kant is nog niets: geen API Call, geen knop, 0 treffers op
kloonbron in een verse export.
Code staat klaar en is op productie getest (2026-09-20, Claude, read-only via
drush php-script — het bestand is niet gewijzigd). Drie gaten, alle drie hard
gemeten:
| # | Gat | Bewijs |
|---|---|---|
| 1 | entree_tid ontbreekt bij een activiteit |
De veldkaart heeft 'entree' => NULL voor activity, maar _custom_stadsactiviteit_create() schrijft wél naar field_act_entree (Bob 2026-08-26, zelfde vocabulary als field_goo_entree). Testnode 222818 heeft field_act_entree = 36197; de kloonbron gaf dat niet terug → dataverlies bij klonen |
| 2 | Geen logo_url/fotos_urls |
De aanmaakpagina toont de preview uit page state createLogoUrl/createFotosUrls. Zonder URL's gaat het beeld wél mee (de fid) maar zie je een leeg previewvak — verwarrend |
| 3 | Geen plaatsketen bij een activiteit | Alleen plaats_tid. De pagina heeft drie cascade-dropdowns (provincie → gemeente → plaats) en kan uit één tid niet afleiden welke provincie/gemeente erbij horen |
De patch staat als kloonbron-patch.inc in het sessie-scratchpad van
2026-09-20; opnieuw te genereren met de beschrijving hieronder. Twee ingrepen in
sites/all/modules/custom/custom.mijn_aanmeldingen.inc:
'entree' => NULL, → 'entree' => 'field_act_entree',_custom_aanmelding_kloonbron()) vervangen door de nieuwe versie. Die voegt
twee helpers toe (_custom_aanm_bestand_urls() en _custom_aanm_keten()) en
geeft extra terug: logo_url, fotos_urls, entree_tid (nu voor beide
types, uit het gedeelde blok), en voor een activiteit provincie_tid,
gemeente_tid en keten.Daarna drush @uitgaanskrant.com cc all.
⚠️ keten heeft bewust exact hetzelfde formaat als taak 123
("provincie|gemeente|plaats", ontbrekende delen leeg). De drie custom functions
uit taak 124 (ketenProvincie / ketenGemeente / ketenPlaats) zijn daardoor
1-op-1 herbruikbaar — bouw ze niet twee keer.
Getest op productie, beide types plus alle randgevallen:
| invoer | keten |
|---|---|
| plaats 28739 (Hoogkarspel) | 28666\|28737\|28739 |
| gemeente 28694 (Amsterdam) | 28666\|28694\| |
| provincie 28666 (Noord-Holland) | 28666\|\| |
NULL / 0 / onbestaande tid |
\|\| (geen crash) |
Gemeten: alle 23 gevulde field_act_state_municipality_tow-waarden staan op
niveau 3 (plaats). Er is dus geen activiteit waarbij plaats_tid en het derde
deel van de keten uiteenlopen — dat randgeval hoeft niet afgevangen te worden.
ℹ️ Niet "repareren": file_create_url() geeft onder drush http://. Dat is
een drush-artefact (geen request-context, $base_url staat op
http://uitgaanskrant.com). Via een echte HTTP-request levert Drupal gewoon
https:// — geverifieerd op flutterflowmobiel_establishment_info. Controleer
het bij de eerste test vanuit de app, maar ga er niet aan sleutelen.
Waarom niet gewoon On Page Load? Een TextField leest zijn Initial Value
tijdens de eerste build; een Backend Call op On Page Load draait in een
addPostFrameCallback, dus daarná. Het veld blijft dan leeg terwijl de data
binnen is. Zelfde valkuil als bij Initial Option Value (staat in CLAUDE.md).
Daarom: de call gebeurt op de knop, vóór de navigatie.
Besluit Bob 2026-09-20: App State, niet page parameters. Eén JSON-veld scheelt de helft van het bindwerk (1 binding bij het vullen i.p.v. 16) en houdt de route schoon.
Nieuw aan te maken:
| wat | waar | details |
|---|---|---|
App State kloonBron |
App Values → State | Type JSON, Is List uit, niet persisted |
API Call AanmeldingKloonbron |
API Calls | GET https://uitgaanskrant.com/nl/flutterdrup/aanmelding_kloonbron.json, header Cookie: [sessionName]=[sessid] (rechte haken!), query nid. Kopieer MijnAanmeldingenCall als voorbeeld |
Custom function kloonTekst |
Custom Code | String kloonTekst(dynamic bron, String sleutel) — non-nullable return, '' bij ontbreken |
Custom function kloonLijst |
Custom Code | List<String> kloonLijst(dynamic bron, String sleutel) — non-nullable, [] bij ontbreken |
// kloonTekst — plat schrijven, geen closures (FlutterFlow's validator
// struikelt over een genest (params) { ... }-patroon).
String kloonTekst(dynamic bron, String sleutel) {
if (bron == null || bron is! Map) return '';
final waarde = bron[sleutel];
if (waarde == null) return '';
return waarde.toString();
}
List<String> kloonLijst(dynamic bron, String sleutel) {
final uit = <String>[];
if (bron == null || bron is! Map) return uit;
final waarde = bron[sleutel];
if (waarde is List) {
for (final item in waarde) {
if (item != null) uit.add(item.toString());
}
}
return uit;
}
⚠️ Return type non-nullable houden. Bij een String? eist FlutterFlow een
"Default Variable Value", en valueOrDefault substitueert die óók bij een lege
string — dan kun je nooit een leeg veld klonen. Geen getJsonField() gebruiken:
die bestaat niet binnen een Custom Function (wel in een Custom Action).
Huidige opbouw van de kaart (mijn_aanmeldingen_widget.dart, itemBuilder):
Padding > Container > Padding > InkWell > Column [logo, titel, datum_start,
status_label]. De hele kaart is één InkWell.
De knop moet buiten die InkWell staan, anders vuurt ook de navigatie naar
EventCurrent. Recept (staat in CLAUDE.md): rechtsklik de InkWell →
Wrap Widget → Column → "+" op die nieuwe Column → de knop. Een TabBar Page
of InkWell accepteert maar één kind, een Column meerdere.
Actieketen op de knop:
AanmeldingKloonbron, nid = $.nid van het loop-item
(aanmeldingItemItem), sessie uit App State.kloonBron = Action Outputs → JSON Body →
No Further Changes. Doe dit in de Action Flow Editor (knop Edit, dan het
|< om de trigger-kolom in te klappen) — in het compacte Actions-paneel
reageert het Value-veld niet.type (Equal to go_out_event):
Navigate To uitgaansevenementAanmaken, page parameter
horecagelegenheidNid = $.horecagelegenheid_nid uit de action output.Navigate To stadsactiviteitAanmaken.⚠️ Conditioneer op de page parameter, niet op $.type van het item: een
JSON-Path-binding krijgt type Json en levert if (getJsonField(...)) op —
een dynamic als bool, die compileert en pas bij runtime crasht. De page
parameter is een gewone String, dus een veilige Single Condition.
Gratis meegenomen: horecagelegenheidNid bestaat al als page parameter en
heeft in horecaVoorselectie() (custom_functions.dart:245) al voorrang op
de automatische voorselectie. Voor evenementen hoeft de horecagelegenheid dus
niet via App State.
14 bindingen. Initial Value = kloonTekst(FFAppState().kloonBron, '<sleutel>').
| kloonbron-sleutel | doel | soort |
|---|---|---|
titel |
textFieldTitel |
Initial Value |
omschrijving |
textFieldOmschrijving |
Initial Value |
entree_prijs |
textFieldEntreeprijs |
Initial Value |
toelichting_entree |
textFieldToelichtingEntree |
Initial Value |
website_url |
textFieldWebsiteURL |
Initial Value |
tickets_url |
textFieldTicketsURL |
Initial Value |
entree_tid |
dropDownEntree |
Initial Option Value + page state createEntreeTid in On Page Load |
categorie_tids |
dropDownCategorieen |
Initial Option Value (kloonLijst) + page state createCategorieTids |
logo_fid / logo_url |
— | page states createLogoFid / createLogoUrl |
fotos_fids / fotos_urls |
— | page states createFotosFids / createFotosUrls |
horecagelegenheid_nid |
page parameter | ✅ gratis, zie 127-C |
| datums | — | bewust leeg |
Waarom een dropdown twee bindingen nodig heeft: de page state wordt gezet in
onChanged, en die vuurt niet bij een voorselectie. Zonder de tweede binding
selecteert de dropdown wél de juiste waarde maar verstuurt de create-actie leeg.
De page states worden pas bij het indienen gelezen, dus die mogen gewoon in On Page Load — daar speelt het timingprobleem niet.
24 bindingen. Tien TextFields (titel, omschrijving, organisator, contact,
adres_straat → Adres, adres_plaats → Plaats, adres_postcode,
entree_prijs, toelichting_entree, website_url), plus entree_tid en
categorie_tids (elk 2), de vier beeld-page-states, en de cascade (3 × 2).
De cascade is precies taak 124. Beide moeten de drie dropdowns voorvullen uit
een keten-string, met dezelfde drie custom functions. Bouw 124 eerst, of bouw ze
samen — anders doe je het werk twee keer.
Hoe de timing hier uitpakt (gemeten in de export):
if (createProvincieID != null && != '')
(stadsactiviteit_aanmaken_widget.dart:1852) en de plaats-dropdown achter
if (createGemeenteID ...) (regel 1991). Die twee bestaan nog niet tijdens
de eerste build, dus hun FormFieldController wordt pas ná On Page Load
aangemaakt — daar is het eerste-build-probleem er dus niet.ketenProvincie(kloonTekst(kloonBron,'keten')).createProvincieID/createGemeenteID/createPlaatsID), want een
voorgeselecteerde dropdown vuurt geen onChanged.ℹ️ gemeenteTid bestaat al als page parameter van deze pagina en heeft voorrang
in gemeenteVoorselectie() — bruikbaar, maar hij zet alleen createGemeenteID en
niet createProvincieID, dus de gemeente-dropdown blijft dan onzichtbaar. Voor
een kloon is de App-State-route via keten dus de volledige oplossing.
kloonBron wissen · Eigenaar: nader te bepalenZonder dit blijft een kloon hangen: wie daarna een vers evenement aanmaakt, krijgt het vorige formulier opnieuw ingevuld.
Zet vóór elke bestaande "nieuw aanmaken"-navigatie een Update App State met
kloonBron op Clear Value (zelfde patroon als de uitlogknop). Vier plekken in
een verse export van 2026-09-20:
| bestand | regel | doel |
|---|---|---|
mijn_profiel_widget.dart |
823 | UitgaansevenementAanmaken |
mijn_profiel_widget.dart |
1317 | StadsactiviteitAanmaken |
mijn_profiel_widget.dart |
1506 | StadsactiviteitAanmaken |
favorieten_widget.dart |
1042 | StadsactiviteitAanmaken |
Dit zijn alle ingangen: de aanmaakpagina's zijn verder nergens vanuit de app bereikbaar (wel via een directe route).
Stap 1-3 leveren al een werkende kloonknop voor evenementen; de knop op een
activiteitenkaart verbergen tot 127-E klaar is, is één Visibility-conditie op de
page parameter type.
status. Juist dát is het scenario: een afgekeurde of nog
wachtende aanmelding opnieuw indienen.logo_url op https:// staat.lib/ · Eigenaar: Bob (Claude verwijdert niets)Gevonden 2026-09-20 bij het committen van de achterstallige working tree. Deze
mappen staan in de projectmap en in git, maar komen niet meer voor in een
verse export — ze zijn ooit in de builder verwijderd of hernoemd, en een export
ruimt de lokale map niet op (bekend patroon, staat in CLAUDE.md).
lib/favorieten_copy lib/kanweg_test_upload
lib/favorieten_copy2 lib/shared/drawer_component_copy
lib/horecagelegenhedenoverzicht/horecagelegenheid_event_tabel_component_copy
lib/kanweg (+ kanweg_header_buttons_component_copy, lib/shared/geen_evenementen_component
kanweg_home_copy, kanweg_horecagelegenheden_overzicht, lib/shared/header_current_copy
kanweghorecagelegenheid_current_copy) lib/uitgaanspaginas/home_copy2
lib/uitgaanspaginas/home_uitgaan_slider_component_copy
lib/uitgaanspaginas/home_uitgaantabel_kaart_component_copy
Waarom het meer is dan rommel: twee ervan geven een harde compile-error.
kanweg/kanweghorecagelegenheid_current_copy en shared/drawer_component_copy
roepen KanwegHorecagelegenhedenOverzichtWidget aan, en lib/index.dart
exporteert die map niet (meer). dart analyze op de projectmap geeft daardoor
2 errors, terwijl een verse export er 0 geeft.
⚠️ Die twee errors stonden al op master vóór de commit van 2026-09-20 — het is dus geen regressie van die commit, maar ze blokkeren wel een lokale build vanuit de projectmap. Voor de release maakt het niets uit zolang je via FlutterFlow Deploy bouwt (dat vertrekt vanuit de cloud-staat, niet vanuit deze map).
Doen, als je de projectmap weer wilt kunnen builden:
cd /home/bob/Projects/ff-app/uitgaanskrant-1qhvtd
git rm -r --cached -q lib/favorieten_copy lib/favorieten_copy2 lib/kanweg lib/kanweg_test_upload lib/shared/drawer_component_copy lib/shared/geen_evenementen_component lib/shared/header_current_copy lib/uitgaanspaginas/home_copy2 lib/uitgaanspaginas/home_uitgaan_slider_component_copy lib/uitgaanspaginas/home_uitgaantabel_kaart_component_copy lib/horecagelegenhedenoverzicht/horecagelegenheid_event_tabel_component_copy
rm -rf lib/favorieten_copy lib/favorieten_copy2 lib/kanweg lib/kanweg_test_upload lib/shared/drawer_component_copy lib/shared/geen_evenementen_component lib/shared/header_current_copy lib/uitgaanspaginas/home_copy2 lib/uitgaanspaginas/home_uitgaan_slider_component_copy lib/uitgaanspaginas/home_uitgaantabel_kaart_component_copy lib/horecagelegenhedenoverzicht/horecagelegenheid_event_tabel_component_copy
fvm dart analyze lib/ | grep -c "^ error -" # hoort 0 te zijn
⚠️ Controleer vóór het uitvoeren dat favorieten_copy2 en header_current_copy
geen veiligheidskopieën zijn die je nog wilt bewaren — ze zitten sinds commit
98f0b74 in de historie, dus je kunt ze altijd terughalen, maar kijk er even naar.
Gemeten op de verse export van 2026-09-20 (dode kopieën uitgefilterd). Dit is de staart van P1-33: daar is destijds het rood opgeruimd, grijs en groen bleven staan.
| kleur | = token | aantal | waar |
|---|---|---|---|
Color(0xFFEEEEEE) |
Alternate | 9 | kaartranden op uitgaansevenementAanmaken (4) en stadsactiviteitAanmaken (5) |
Color(0xFF09B34A) |
Tertiary | 2 | HorecagelegenheidoverzichtKaart + tagCategorieComponent (het groene categorielabel) |
Nu onzichtbaar — de hexwaarden zijn exact gelijk aan de tokens, dus er verandert
niets aan het beeld. Het punt is onderhoud: wijzig je ooit alternate of
tertiary in Theme Settings, dan lopen deze elf plekken niet mee en krijg je twee
tinten door elkaar.
Doen: per widget het kleine kleurblokje vóór de kleurnaam aanklikken (niet de tekst — dan maak je er weer een hex van) → in "Choose a Color" onderaan de lijst Theme Colors → Alternate resp. Tertiary. Sluit met de X, niet met Escape (Escape laat de tree-selectie terugspringen naar de pagina-root).
Vindplaatsen, gemeten op de export van 2026-09-20 — het gaat steeds om de Border color van de kaart-Container om een formuliersectie, niet om de Fill:
| pagina | sectie waar de kaart bij hoort |
|---|---|
uitgaansevenementAanmaken |
intro ("Meld hier een evenement aan…") · zoekveld · "Datum eind" · "Link om kaarten te kopen" |
stadsactiviteitAanmaken |
intro ("Meld hier een activiteit aan…") · zoekveld · "Datum eind" · "Plaats activiteit" · "Website van de activiteit" |
De twee groene (09B34A → Tertiary) zijn wél Fill Colors:
HorecagelegenheidoverzichtKaart en tagCategorieComponent, allebei het
categorielabel.
De 12e kleur slaan we over: Color(0xFFFACFC6) in een gradient op
SliderUitgaanComponentSmallCurrent. Dat is roze, hoort bij géén token, en dat
component heeft nul gebruikers — het staat al op de opruimlijst.
⚠️ Claude kwam hier 2026-09-20 niet doorheen. Navigeren, panelen wisselen en de linkerrail werkten normaal, maar geen enkele klik op een widget-tree-rij selecteerde iets — ook de root niet, in ~10 pogingen op wisselende x/y. Een klik op de chevron ernaast deed wél iets (deselecteerde de root), dus de events komen aan; alleen de rij-selectie niet. Zonder selectie verschijnt het eigenschappen-paneel niet en is er geen kleur te zetten. Bob's venster was toen 1266x952; een breder venster is het eerste om te proberen.
Geen haast, geen blokker — prima klusje voor tussendoor.
Bob heeft Calendar uitgezet in App Settings → Permissions. Verse export bevestigt:
android/app/src/main/AndroidManifest.xml heeft nog vier permissies
(INTERNET, CAMERA, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE) en
ios/Runner/Info.plist nog twee usage descriptions (Camera, PhotoLibrary).
READ_CALENDAR/WRITE_CALENDAR en NSCalendarsUsageDescription zijn weg.
Rest: de agendaknop op EventCurrent één keer testen op een echt toestel
(de AVD's kunnen dit niet). En bij een latere iOS-ronde de permissie terugzetten —
daar gebruikt add_2_calendar wél EventKit.
De app-kant is in orde — main.dart:32 roept adMobRequestConsent() aan en
flutter_flow/admob_util.dart doet de volledige UMP-flow
(requestConsentInfoUpdate → isConsentFormAvailable → ConsentForm.show).
Maar die flow doet niets als er in de AdMob-console geen bericht klaarstaat:
isConsentFormAvailable() geeft dan false en de app slaat het formulier stil
over. Gevolg in de EU: geen geldige toestemming, dus alleen niet-gepersonaliseerde
advertenties (lagere opbrengst), en Google kan de serving beperken.
Doen: AdMob → Privacy & messaging → EU regulations (GDPR) → bericht maken voor de app en op Gepubliceerd zetten. Daarna bij de eerste release-test controleren dat het scherm ook echt verschijnt bij een verse installatie.
⚠️ Niet te verwarren met de FlutterFlow-toggle. Bob liet 2026-09-20 zien dat
App Settings → AdMob → "Show GDPR Consent Dialog at App Launch" aan staat — dat
is de app-kant en die was al goed (die toggle genereert juist de
adMobRequestConsent()-aanroep in main.dart). De ontbrekende helft zit op
admob.google.com, niet in FlutterFlow. Zonder gepubliceerd bericht vraagt de
app netjes om een formulier, krijgt er geen, en gaat stil verder.
🔸 Terzijde uit diezelfde screenshot: Ad content filtering staat op Unset. Dat is AdMob's standaard en prima, maar het loont om er bij G2.5/G2.6 (content rating + doelgroep) bewust een waarde bij te kiezen zodat de advertenties passen bij wat je bij Play aangeeft.
De uitgelogde doorloop is af (2026-09-19, --release, flags=0x0): 0 FATAL,
0 E/flutter, alle iconen renderen, vliegtuigmodus geeft netjes de
VerbindingsBanner, Engels vertaalt. 65a, 65b en 65d zijn opgelost en
export-geverifieerd.
Wat overblijft — en dat is per definitie Bob's stuk, want Claude voert geen wachtwoorden in:
Meenemen in die doorloop (nieuw, 2026-09-20): de gebruikersnaam wordt nu
onthouden na uitloggen. Verwacht gedrag: inloggen → uitloggen → het bovenste
veld op Login staat al ingevuld met wat je de vorige keer typte, het
wachtwoordveld is leeg. Overleeft ook het volledig afsluiten van de app
(persisted). Het kruisje in het veld wist het voor een andere gebruiker.
🔴 De ingelogde doorloop. Nooit op een release-build getest, en het raakt de kernfuncties: inloggen · hartje op een zaakpagina (aan én uit) · Favorieten met inhoud, alle vier de tabs · gemeente volgen · evenement aanmaken tot en met indienen · Mijn profiel inclusief uitloggen. Een Play-reviewer logt straks wél in.
65c · ✅ af (nagemeten 2026-09-19 avond in een verse export): Favorieten toont
uitgelogd nu een uitlegtekst met inlogknop, achter een guard op userSessionid
(sleutel zxbjvxzq). Gebouwd in een andere sessie als taak 107.
65e · "Datum" blijft Nederlands in de Engelse modus — het label komt uit de
valueOrDefault-default 'Datum' en is dus geen vertaalsleutel. Hoort bij P1-17.
Cosmetisch, al bekend: het logo in de drawer staat deels onder de statusbalk op de release-build (op de profile-build van 2026-09-19 is dat niet meer zo — taak 100 zette de padding op 40; opnieuw bekijken bij de volgende release-build).
https://uitgk.com/<nid> (deelknop op EventCurrent en
de tekst in zetInAgenda) redirect naar de juiste pagina op uitgaanskrant.com.
Getest op drie nids, inclusief een horecagelegenheid: 222338 -> "Scott Hamilton
& Rein de Graaff Trio…", 75459 -> "Bimhuis Amsterdam". Eind-URL is een nette
/nl/Noord-Holland/Amsterdam/...-alias./nl/support/mobieleapp (de Support-link in de
drawer én de data-deletion-URL voor Play) en /nl/support/privacybeleid.devbob staat niet meer in de levende app-code (alleen in dode kopieën).Fase 1 én 2 staan op productie en zijn nagemeten. Van 42 naar 22
methodes op endpoint flutterdrup. Het bewezen lek is weg: node/<nid>.json
gaf anoniem 200 met 46 velden inclusief name (de inlognaam van de auteur,
dus user enumeration) en geeft nu 404.
Dicht (404): node/retrieve + relationships/files · file/create +
file/retrieve · taxonomy_term · taxonomy_vocabulary · user/retrieve|create|
delete|logout|token|user_pass_reset|cancel|password_reset|resend_welcome_email ·
system/connect · geocoder · userestablishments.
Blijft aan (22): de app-resources (plaatsen, plaatsen_bij_gemeente,
horecacategorieen, views, de favorieten-, aanmaak- en upload-acties,
mijn_*, categorieen, entreeopties, accountdelete) plus user/login en
user/request_new_password.
Regressiecheck na afloop, devbob én productie: alle vijf views-endpoints 200 ·
plaatsen/plaatsen_bij_gemeente/horecacategorieen 200 · POST user/login.json
401 op onzin · een afbeelding uit een view 200 image/jpeg.
📁 Script: /home/bob/Projects/services-dicht-fase2.php (droogdraai is de default,
doen als argument voert uit). Bewaren voor als er ooit een resource bij komt.
Alleen de vijf app-views geven 200; user_contents, places, _town_tree,
thuis_bezorgen, front_block_go_ca, _for_search_page, establishment_calendar,
flutterfavorietenagenda, _block_go_ca_for_town, block_more_go_out,
latest_photobook en _search_ca_page geven 404.
⚠️ De foutmelding luidt ["Display block_1 on view user_contents could not be
found"] terwijl die view wél een block_1 heeft — dat betekent hier "view staat
niet op de toegestane lijst", niet "display bestaat niet".
Alle vijf nagemeten op de verse export en op productie; niets te doen, hier genoteerd zodat niemand het opnieuw uitzoekt:
~/uitgaanskrant-test.apk met readelf -lW: libapp.so en
libflutter.so zijn 0x10000 (64 KB) uitgelijnd, libdatastore_shared_counter.so
0x4000 (16 KB) — allemaal ≥ 16 KB. ndkVersion 28.2.13676358 dekt dit.36 (android/app/build.gradle:62), ruim boven de Play-eis van 35./nl/support/privacybeleid
(200) noemt AdMob (2x), Crashlytics (3x), Firebase (5x), advertentie (6x) en
verwijderen (8x). Dat is precies wat Play's Data-safety-controle naast je
declaratie legt./nl/user/register
(de knop Account aanmaken op Favorieten) en /nl/user/password. Zelfde val als
bij G2.2, maar hier dus goed.main.dart:32) — of het bericht ook echt
verschijnt hangt af van de AdMob-console, zie taak 118.AdMob: Show Test Ads uitzetten. App Settings → AdMob (niet een vinkje
op het AdBanner-widget — dat paneel heeft alleen Ad Properties en Ad Banner
Dimensions; de export schrijft de projectinstelling per widget uit).
Twee dingen bij het omzetten: (1) reken op lege ruimte i.p.v. advertenties
zolang de app niet gepubliceerd is — AdMob levert dan nauwelijks fills, dat is
normaal; (2) klik daarna niet zelf op je eigen advertenties, dat telt als
ongeldig verkeer. Zodra hij uit staat schiet Claude tel-04-horeca.png opnieuw.
Builder-opruimronde, laatste restanten. Nog in de export: componenten
SliderUitgaanComponentSmallCurrent,
PUitgaantabelKaartComponentOrgineelMetKaartjeerin en
SelectStateDropDownComponentCopy2, de pagina mijnProfielCopy3 (staat alleen
als route in nav.dart, niets navigeert ernaartoe) en de custom function
dISABLEdatumVoorApi. (De laatste twee kopieën ontstonden 2026-09-20 bij het
oefenen op taak 2-4.)
⚠️ Pagina Event: laten staan, dit is een doodlopend spoor. Bob bevestigde
2026-09-20 dat óók hernoemen afketst op "Invalid Action" — verwijderen,
verplaatsen en hernoemen falen dus alle drie, ook in zijn eigen browser.
Nagemeten op de export (2026-09-20): de pagina is onbereikbaar. De enige
verwijzingen zijn de twee die FlutterFlow automatisch voor élke pagina
genereert (index.dart en de route-registratie in nav.dart); er is nergens
een goNamed/pushNamed naartoe. Geen enkele gebruiker komt er dus, behalve
via een handmatige deep link. Kosten van laten staan: één dode route in
nav.dart en ~30 kB in de app. Niet opnieuw agenderen. Moet in de builder, niet met
git rm — anders staat alles na de volgende export terug.
P1-17 · vertalingen: ✅ rond voor de app (2026-09-20). Nagemeten over alle
218 sleutels die in bereikbare widgets gerenderd worden: 0 met gevulde NL en
lege EN. De laatste zes zaten in FilterBalkComponent en zijn ingevuld.
tcyc3idz bestaat niet meer. Blijft over: de vier lege-lijst-teksten op
mijnProfiel, die zijn letterlijke parameterwaarden zonder globe.
⚠️ Tel geen sleutels mee waar EN == NL terwijl dat correct is (Select...,
Website, Facebook, Media, ", " — identiek in beide talen).
Titels met spaties vooraan/achteraan (was P1-47). Bob 2026-09-11: de
impact is te groot, we lopen de namen door bij de livegang. MySQL sorteert op
de rauwe node.title, dus zo'n node valt buiten de alfabetische volgorde
terwijl de JSON schoon oogt (_custom_clean_html poetst ná de query).
Telquery:
drush @prod sqlq "SELECT type, COUNT(*) FROM node WHERE title <> TRIM(BOTH ' ' FROM TRIM(BOTH CHAR(9) FROM TRIM(BOTH CHAR(10) FROM TRIM(BOTH CHAR(13) FROM TRIM(BOTH ' ' FROM title))))) GROUP BY type;"
De fix is een UPDATE met diezelfde geneste TRIM op node én
node_revision, idempotent, met vooraf een sql-dump van die twee tabellen.
URL-aliassen blijven ongemoeid.
Max items + tab 6 (P2-24 A en C) — ✅ opgelost, alle zes de tabs draaien
op filterHorecagelegenheden met .take(1000). Niets meer te doen.
(Afgerond en daarom verwijderd uit dit blok: taak 56 opruim-cron · P1-30
Cloudflare rate limiting · P2-25 debug-cleanup custom.module · de twee dode
KANWEG-API-calls · de opruimronde van 7 dode kopieën.)
Gedaan (export- en toestel-geverifieerd, profile-build op emulator-5554): backups EventCurrentCopy, EvenementHorecagelegenheidCopy, EvenementInfoCopy; event-kaart met logo 96×96 links en EvenementInfo (Expanded) + Maps-knop rechts; de 500 px-Container weg; EvenementHorecagelegenheid zonder tabs: RowLogo (logo 96×96 + ColumnRechts: titel, labels, adres/plaats, telefoon, e-mail), links in een Wrap (Menukaart/Website/Facebook/Instagram/X/"Op Uitgaanskrant.com" met host ervoor), TextInhoud (zaakbeschrijving), foto's, ColumnOpening en ColumnBezorgen met Visibility op openingstijden/bezorgtijden; e-mail leest nu $[:]['e-mail']; drie phone: false-vlaggen weg; telefoon-guard zonder valueOrDefault; Entree-blok alleen bij entreeprijs; roze/rode vulkleuren van Entree/Contact weg; EN-vertalingen "Opening hours"/"On Uitgaanskrant.com".
Nog te doen:
horecaid=157070).
RowLogo (logo 96×96 + titel + categorielabel), de adres-Row [Icon, TextAdres, TextPlaats]
met spacing 6 ("Westerstraat 95 Enkhuizen"), telefoon, e-mail, de links-Wrap
(Menukaart/Website/Facebook/Instagram/X/Twitter/Op Uitgaanskrant.com) en TextInhoud
renderen allemaal goed.
✅ "Contact"-label gefixt (2026-09-19 avond): de Row staat nu op Cross Axis
Alignment start met Items Spacing 8, dus het label lijnt uit met de eerste regel
links i.p.v. tussen de regels te hangen. Export: crossAxisAlignment: start +
.divide(SizedBox(width: 8.0)).ColumnBezorgen mét echte data bekeken en grotendeels opgeknapt (2026-09-19).
Testzaak: nid 157070 (Chinees-Indische restaurant Lotus, Enkhuizen) — die heeft
álle bezorgvelden gevuld (bezorgtijden, bestellink, bezorgkosten, minimaleorder,
bezorgtin, thuisbezorgtbetaalopties, cryptocoins, afhaalopties) én menukaart,
openingstijden, openingstijdenuitzondering en kvk. Route:
uitgaanskrant://uitgaanskrant.com/eventCurrent?nid=214689&horecaid=157070.
Wat er mis was: de sectie toonde elf kale regels zónder één label — "vanaf 17 uur",
"2 euro", "20 euro", "Contant" zonder context, de bestellink als kale URL, geen kop, en
lijstwaarden die aan elkaar plakten ("AfhaalBezorgen", "EnkhuizenBovenkarspel").
Gefixt en op emulator-5554 (profile) geverifieerd: kop "Bezorgen" (i18n jxlwje5u,
dezelfde stijl als "Openingstijden"); labels via Combine Text op Bezorgtijden:,
Bezorgkosten: en Minimale bestelling:; een Visibility-guard op
Textbezorg-minorder (establishmentMinimaleorder is set/non-empty) — die had er géén,
dus met label erbij zou hij anders "Minimale bestelling: null" tonen; en Wrap-spacing 8
op de drie lijsten, zodat de waarden niet meer aan elkaar plakken.TextInhoud heeft nu een kop "Over deze zaak" (EN About this venue, sleutel rko8u7a5, Body Medium 600) in een nieuwe ColumnInhoud met padding-top 8 (2026-09-19 avond, export-geverifieerd).22xoyrqe) staat nu op Menu (2026-09-19 avond).kvk (zaak). Bewust overgeslagen.organisator wordt nu wél getoond (2026-09-19, Bob's besluit, af en op toestel geverifieerd).
Zie het eigen blok hieronder; taak 99 kan hiermee dicht.EventCurrentCopy, EvenementHorecagelegenheidCopy, EvenementInfoCopy) op de P2-7-opruimlijst zetten zodra de nieuwe pagina goedgekeurd is. Claude verwijdert niets.#
Gemeten 2026-09-19 op de export; dit corrigeert een eerdere bewering van Claude
in deze sessie ("tot 60 requests per schermopening"). Die telling was fout: er
staan zes fetchAlleHorecagelegenheden-aanroepen in
horecagelegenheden_overzicht_current_widget.dart, maar ze worden niet samen
uitgevoerd.
addPostFrameCallback) doet er één — tab 0
(horcat 17969, Activiteiten, services_1).onTap: (i) async { [ () async {}, …vijf closures… ][i]() }
— dus per tab-tik precies één fetch, en tab 0 doet niets omdat die al geladen is.Een schermopening kost dus één fetchAlleHorecagelegenheden, en die loopt
door API-pagina's van 100 tot maxPaginas = 10. In Amsterdam heeft tab 0
(Activiteiten) 42 items → één HTTP-request. De 60 uit die eerdere schatting
komt in de praktijk nooit voor.
Gevolg voor de rate limit: 100 requests per 10 s is ruim voldoende; de verhoging naar 200 was niet nodig (schaadt ook niet).
Wat er wél nog te winnen valt, klein: elke tab-tik doet een verse fetch,
ook als je terugkeert naar een tab die je al bezocht hebt. Heen-en-weer klikken
tussen zes tabs haalt dus zes keer opnieuw op. Een guard ("sla de fetch over als
alleXxx al gevuld is") lost dat op, maar kost een conditie in vijf
actieketens — en juist die dialoog is op deze pagina fragiel. Niet gebouwd;
alleen doen als het in de praktijk hindert.
A, C, D en E zijn af (2026-09-19, export-geverifieerd): alle zes de
StaggeredViews draaien op filterHorecagelegenheden(...), .take(25) is weg
(6x .take(1000)), de routes wijzen naar ...Current, en de twee lege
TextField-placeholders zijn opgeruimd. F is geschrapt op Bob's verzoek.
B — categoriedropdown per tab: ✅ af (nagemeten 2026-09-19 avond): de
FlutterFlowDropDown op horecagelegenhedenOverzichtCurrent hangt aan
horcatOptiesVoorTab / horcatLabelsVoorTab met de TabBar-index. Daarmee is P2-24
helemaal rond; dit blok kan weg zodra Bob 'm op het toestel goedkeurt.
Niet oplosbaar, geaccepteerd: FlutterFlow zet op de On Change-trigger van
het zoekveld een EasyDebounce van 2000 ms die nergens instelbaar is. De
lijst ververst dus ~2 s nadat je stopt met typen.
Nagemeten door Claude op productie, 2026-09-19 17:44 (alle zeven displays
volledig gepagineerd, nids naast flutterflow_events gelegd, geclassificeerd op
datum + tijd tegen de >= -2 uur-grens van de master):
| echte toekomstige events | 6.684 |
| bereiken geen enkele tab | 618 (9 %) |
| ... daarvan zonder categorie | 618 — dus 100 % |
| ... daarvan mét categorie | 0 |
Twee dingen die dit uitwijst. (1) De zeven displays dekken alle categorieën correct af — er is geen categorie meer die nergens landt, dus dát deel van taak 28 is klaar. (2) Het hele resterende lek is één oorzaak: een event zonder categorie valt door elk display-filter heen en is in de app dus onvindbaar. Stand 12 sep: 597. Nu: 618. Het loopt dus licht op — de fix van 19 sep werkt kennelijk niet (of alleen voorwaarts, terwijl de bestaande nodes blijven staan).
Voorbeelden (allemaal ruim in de toekomst, dus geen datumkwestie):
222806 Steve 'n' Seagulls (20 dec, Weert) · 222737 Altruism Label Night
(21 nov, Maastricht) · 222703 BRECHTJE Maresa (1 okt, Groningen).
✅ Besluit Bob 2026-09-19: dit is een IMPORT-probleem en wordt bij de importer afgevangen. Geen Drupal-hook of extra display nodig; niet opnieuw agenderen. Wel bij een volgende contentmeting nakijken of het getal daalt (nu 618).
afgewezen alternatief
Voorstel — een default in custom_node_presave(). Die hook draait er al
voor go_out_event (adres/geo/plaats overnemen van de horecagelegenheid); één
blok erbij dat field_category2 vult met een vaste fallback-tid zodra het leeg
is, dekt alle nieuwe imports. De 618 bestaande haal je in één keer mee met een
drush php-eval die diezelfde tid zet en node_save() aanroept.
Wat Claude van Bob nodig heeft: welke tid de fallback moet zijn (een
bestaande categorie, of een nieuwe term "Overig"). De alternatieven — een achtste
display zonder categoriefilter, of de importer aanpassen — kosten meer en geven
een extra tab in de app.
⚠️ Meetles, kostte deze sessie een valse ronde: classificeer op datetime,
niet op datum. Op datum alleen leverde dezelfde meting 30 "bugs" op die in
werkelijkheid gewoon events van vandaag waren die al begonnen waren — precies wat
het >= -2 uur-filter hoort weg te laten. Staat ook al in CLAUDE.md; ik trapte
er alsnog in.
De 403-detectie (2026-09-20) is volledig geverifieerd op code- en serverniveau:
export bevat alle onderdelen, dart analyze 0 errors, en productie antwoordt bij
een ongeldige cookie met 403 ["Toegang geweigerd voor gebruiker anonymous"] —
precies wat drupalRequest detecteert. Alleen nog niet met eigen ogen op een
toestel gezien. Geen aparte build voor starten; meenemen bij de eerstvolgende
keer dat er toch een build draait.
Test in drie stappen (~1 min):
Wis de sessie server-side — vervang <uid> door je eigen uid:
ssh aegir-o1 "drush @uitgaanskrant.com php-eval \"db_delete('sessions')->condition('uid', <uid>)->execute();\""
Ververs Favorieten in de app. Verwacht: rode balk "Je sessie is verlopen. Log opnieuw in." met knop Inloggen, en de pagina klapt naar zijn uitgelogde weergave.
Werkt het niet, dan zit het in laag 2 (VerbindingsBanner), niet in de detectie —
die is hierboven al bewezen. Controleer dan adb logcat | grep "SESSIE VERLOPEN":
staat die regel er wél, dan komt de melding niet door en is het de SnackBar-logica.
Doel: de gebruiker zijn inloggegevens door Android/iOS laten opslaan en invullen, zodat opnieuw inloggen twee tikken kost. De app slaat bewust géén wachtwoord op — dat blijft bij het besturingssysteem.
Context: sessies zijn sinds 2026-09-20 een jaar geldig (zie CLAUDE.md),
dus dit is comfort, geen noodzaak. Los oppakken, niet meeliften op ander werk.
Stap 1 — invullen (FlutterFlow-property, laag risico).
Pagina login, beide TextFormFields:
| veld | herkenbaar aan | Auto Fill Hint |
|---|---|---|
| gebruikersnaam | obscureText: false, regel ~227 in de export |
username |
| wachtwoord | obscureText: !_model.passwordFieldVisibility, regel ~402 |
password |
Zit in Properties Panel → Additional Properties → Auto Fill Hint (toggle
aan, dan de optie kiezen). Kies username en niet email: Drupal 7's
user/login accepteert standaard alleen de gebruikersnaam.
Stap 2 — opslaan aanbieden (custom action, hier zit het risico).
Alleen hints is niet genoeg: het OS vraagt pas "wachtwoord opslaan?" na
TextInput.finishAutofillContext(). FlutterFlow genereert die aanroep niet en
documenteert hem niet. Nieuwe custom action autofillAfronden, zonder
argumenten, aan te hangen ná een geslaagde drupalLogin:
import 'package:flutter/services.dart';
Future autofillAfronden() async {
TextInput.finishAutofillContext();
}
Open vraag: werkt dit zonder een AutofillGroup om beide velden heen?
FlutterFlow genereert die niet zichtbaar, en Android is daar in Flutter
historisch kieskeurig in. Lukt het niet, dan is de enige route een custom widget
dat het hele loginformulier vervangt — dat is een flinke ingreep en waarschijnlijk
niet de moeite waard voor puur comfort.
⚠️ Testen kan NIET op de emulators. De tablet-AVD heet
Medium_Tablet_no-google: geen Play Services, dus geen Google Password Manager.
Dit moet op Bob's fysieke Xiaomi, met een profile-build.
Terugdraaien (per stap, beide onafhankelijk):
autofillHints: uit lib/login/login/login_widget.dart —
controleer met grep -c autofillHints lib/login/login/login_widget.dart,
hoort 0 te zijn.grep -rc finishAutofillContext lib/ hoort 0 te geven.Geen van beide stappen raakt de sessie-afhandeling, drupalLogin of App State,
dus terugdraaien kan niet stukmaken wat nu werkt.
#
launchURL-aanroepen in
levende code hangen achter een guard op de rauwe waarde, niet op een
valueOrDefault.EstablishmentInfo geeft precies één rij per zaak (60 Amsterdamse zaken
getest). De zes $[:].veld-knoppen op de detailpagina leunen daarop; let op
zodra er een multi-value veld aan die view wordt toegevoegd.categorie is op alle zeven flutterflowmobiel1-
displays altijd een lijst (65 records gemeten).SliderUitgaanComponentSmallCurrent negeert zijn eigen
townid/displayid (P1-44-patroon), maar heeft nul gebruikers — geen
impact, alleen niet inzetten zonder dat eerst te repareren.fillColor op de twee aanmaakpagina's is al goed: zowel
stadsactiviteitAanmaken (18 widgets) als uitgaansevenementAanmaken (11)
staat volledig op primaryBackground. Het in CLAUDE.md voorspelde
secondaryBackground-defaultprobleem is dus niet meer aanwezig.$.categorie is op de Home-displays nooit leeg of afwezig (services_1/3/5,
Amsterdam, 25 items elk: altijd een lijst). De .toList() zonder true op
home_uitgaantabel_kaart_component_widget.dart:651 kan daardoor in de praktijk
niet crashen — events zonder categorie halen de displays sowieso niet.EvenementInfo (6 van de 12,
nagemeten en juist), de wees hierboven, en
HorecagelegenheidoverzichtKaart.nid (restant van het verwijderde hartje).node.title, een spatie komt
vóór de A). De eerste kaarten die een gebruiker ziet zijn dus willekeurig.android/ heeft geen ongecommitte
wijzigingen meer en de vastgelegde waarden zijn minSdkVersion
flutter.minSdkVersion (= 24) en tasks.register("clean", Delete) — precies
de moderne variant. Het punt is dus vanzelf beslecht; niemand hoeft hier nog
iets aan te doen.flutterflowmobiel1 opruimen (was taak 46): GESCHRAPT op Bob's verzoek.
services_2 bestaat nog (25 items) maar heet "ongebruikt" en blijft staan
tot een schoonmaakronde.| 09-14 | 09-19 | |
|---|---|---|
unieke events (flutterflow_events) |
16.065 | 17.123 |
| toekomstige events (op datum+tijd) | 6.202 | 6.684 |
| bereiken geen enkele app-tab | 622 (10 %) | 618 (9 %) |
| ... daarvan zonder categorie | 597 | 618 — dus 100 % |
| ... daarvan mét categorie | 25 | 0 |
De displays dekken alle categorieën nu volledig af — er is geen categorie meer die nergens landt. Het hele resterende lek is één oorzaak: een event zonder categorie valt door elk display-filter. Zie het blok bij taak 28/109; Bob vangt dat af bij de importer.
Ouderdomsverdeling (voor de opruim-cron van 180 dagen): 6.728 toekomstig · 8.107 jonger dan 180 dagen · 2.251 tussen 180 en 360 dagen · 14 ouder dan 360. Die 2.251 worden bij de eerstvolgende cronruns opgeruimd; met 1000 per run is dat ~3 dagen.
HTML-entiteiten: titels, adressen en de horeca-agenda zijn schoon (taak 129).
body heeft er nog 41 per 200 records, maar die gaat door de custom widget
FromHTML en rendert dus goed.
⚠️ Meetles: classificeer op datetime, niet op datum. Op datum alleen gaf
dezelfde meting 30 "bugs" die in werkelijkheid events van vandaag waren die al
begonnen waren — precies wat het >= -2 uur-filter hoort weg te laten.
flutterflow_events — bekend, geen impactNid 214439 ("Brocante Markt Klein Frankrijk") komt 14 keer identiek terug
in flutterflow_events; 214441 en 214420 elk 3x, 214367 2x. Op 2026-09-12
onveranderd (18 overtollige rijen op 2025).
✅ Maar het bereikt de app niet. Nagemeten 2026-09-12:
flutterflowmobiel1 heeft géén duplicaten: services_1/2/3/5/7 geven
allemaal evenveel rijen als unieke nids. Node 214439 komt er zelfs
helemaal niet in voor (zijn categorie "Tweedehands markt" valt onder geen
enkele display — dat is taak 28, niet deze).flutterflow_events wordt door de app alléén per nid bevraagd
(EvenementCall.call(nid: ...), vanuit evenement_component en
event_current). Er wordt nergens een lijst uit opgebouwd: de twee
iteraties in dat component lopen over fotoos en categories binnen één
event, niet over de rijen.Gevolg: geen zichtbare schade, geen haast. Het blijft wel iets om te weten:
bouwt er ooit iemand een lijst op deze view, dan komt zo'n node 14x in beeld.
De oorzaak is het klassieke Views-patroon "een veld met meerdere waarden krijgt
een eigen rij" — kijk op node 214439 welk veld 14 waarden heeft en zet
Multiple field settings → Display all values in the same row aan.
Gevraagd bij taak 28/109 ("bij een volgende contentmeting nakijken of het getal
daalt, nu 618"). Voor het eerst geclassificeerd op datum_iso in plaats van
op de Nederlandse datum-string — flutterflow_events levert dat veld sinds
2026-09-19 en is mét display_id=services_1 gewoon pagineerbaar (25/pagina).
| 09-12 | 09-14 | 09-19 | 09-20 | |
|---|---|---|---|---|
| unieke events | — | 16.065 | 17.123 | 16.080 |
| toekomstige events | — | 6.202 | 6.684 | 6.397 |
| bereiken geen enkele tab | 597 | 622 | 618 | 584 (9 %) |
| ... zonder categorie | 597 | 597 | 618 | 584 — 100 % |
| ... mét categorie | — | 25 | 0 | 0 |
Conclusie: 618 → 584, een daling van 34. Het liep eerder op (597 → 618), dus
de importer-aanpak van Bob lijkt te werken. De categorie-dekking van de zeven
displays blijft volledig: er is geen enkel toekomstig event dat wél een categorie
heeft en toch nergens landt. Voorbeelden van de rest: 222806 Steve 'n' Seagulls
(20 dec, Weert) · 222737 Altruism Label Night (21 nov, Maastricht) · 222703
BRECHTJE Maresa (1 okt, Groningen).
Twee bijvangsten:
datum_iso en vallen dus buiten élke
datumclassificatie. Klein, maar het betekent dat ze ook door het
>= -2 uur-filter van de master niet betrouwbaar te plaatsen zijn.services_2 geeft nu 0 rijen (stond in de notities nog op 25). Die display
staat al als "ongebruikt" te boek, dus geen impact — wel goed om te weten vóór
iemand 'm ooit wil hergebruiken.Alles wat buiten de app-code om stil kan zijn verlopen en een Play-inzending of de app zelf zou breken. Alles groen op één na (G3.1, zie daar).
| check | uitkomst |
|---|---|
/nl/support/privacybeleid (G2.1) |
200 anoniem |
/nl/support/mobieleapp (G2.2) |
200 anoniem |
/nl/account-verwijderen |
403 anoniem — daarom terecht NIET de data-deletion-URL |
deel-URL uitgk.com/<nid> |
200 op drie echte toekomstige events, landt op de juiste eventpagina |
| dichtgezet API-oppervlak | node · file · taxonomy_term · system/connect · user/<uid> allemaal 404 |
POST user/login.json met onzin |
401 (niet 404 — de route leeft dus nog) |
| de vijf app-views | alle 200 mét hun display_id |
plaatsen · plaatsen_bij_gemeente · horecacategorieen |
200 |
| Play-screenshots (10) | alle binnen 320-3840 px en ratio ≤ 2:1 |
| feature graphic | exact 1024×500, RGB zonder alpha, 88 kB |
⚠️ Meetval, kostte mij twee rondes: een views-endpoint zónder display_id
geeft 404 ["Display default on view X could not be found"]. Dat lijkt op een
dichtgezette resource maar is gewoon een onvolledige aanroep — roep een view
altijd aan zoals de app 'm aanroept. Idem flutterflow_events met het nid van
een horecagelegenheid: dat geeft terecht [], geen fout.
📌 uitgk.com/222338 uit de oude notitie klopt niet meer — die node bestaat
niet en de forward landt dan op de zaakpagina. Geen bug; test zoiets met een nid
uit een verse flutterflowmobiel1-aanroep.
Verse export + de patroonchecks uit CLAUDE.md. dart analyze op de verse
export: 0 errors. De twee gevonden punten zijn diezelfde dag opgelost en
export-geverifieerd:
Container om
Text-categorie in HorecagelegenheidEventTabelComponentCurrent stond op
Color(0xFF42E31C); nu op het thema-token Tertiary (#09B34A), gelijk aan
elk ander categorielabel. grep -rn "0xFF42E31C" lib/ geeft projectbreed 0.FilterBalkComponent zijn gevuld — Search by title · All · Today ·
Weekend · This week · initial option All. Nagemeten over alle 218
i18n-sleutels die in bereikbare widgets gerenderd worden: 0 met gevulde NL en
lege EN (was 6).
⚠️ Waarom "Weekend" tóch ingevuld moest: een lege en levert bij
getText() een lege string op, dus het chiplabel zou in het Engels
onzichtbaar zijn — EN==NL is hier geen reden om over te slaan.
✅ Het datumfilter blijft in het Engels werken: filterDatumVan/
filterDatumTot matchen op substring en kennen today al; This week bevat
week en All matcht niets (= geen filter). Dat is geverifieerd vóór het
vertalen, want de chip-labeltekst is tegelijk de waarde die in
FFAppState().datumFilter belandt.Blijft open (niet van Claude):
lib/ die de
verse export niet meer produceert. export-code schrijft alleen, verwijdert
nooit. Daardoor geeft dart analyze lokaal 2 errors (in
kanweg/kanweghorecagelegenheid_current_copy en shared/drawer_component_copy,
allebei Undefined name 'KanwegHorecagelegenhedenOverzichtWidget') terwijl de
verse export er 0 heeft. De build valt er niet over — niets importeert die
twee — maar het maakt de standaard "0 errors"-check onbetrouwbaar.
Advies: commit de huidige working tree niet as-is; draai een verse export en
commit die. Claude verwijdert niets — de mappen:
favorieten_copy · favorieten_copy2 · kanweg/ (8 bestanden) ·
kanweg_test_upload · shared/drawer_component_copy ·
shared/geen_evenementen_component · shared/header_current_copy ·
horecagelegenhedenoverzicht/horecagelegenheid_event_tabel_component_copy ·
uitgaanspaginas/home_copy2 · uitgaanspaginas/home_uitgaan_slider_component_copy ·
uitgaanspaginas/home_uitgaantabel_kaart_component_copy.Nagemeten en schoon — niet opnieuw doen:
! ?? in models (0) · getJsonField(...).toList() zonder true (0) ·
lege responsive-tak return 0; (0) · bron/pad-mismatch bij getJsonField (0) ·
ellipsis zonder maxLines (alleen in twee weeskomponenten) ·
ongelezen component-parameters (alleen de drie al bekende) ·
iOS UsageDescription staat op precies 3 · hardcoded kleuren in levende
widgets: alleen nog #09B34A/#EEEEEE (merkkleuren, niet getokeniseerd) en
transparante/schaduwwaarden.
showsTestAd: true staat nog aan — het restant van G0.6 (tel-04-horeca.png)
is dus nog steeds geblokkeerd op de AdMob-schakelaar.