// Automatic FlutterFlow imports import '/backend/schema/structs/index.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'index.dart'; // Imports other custom widgets import '/custom_code/actions/index.dart'; // Imports custom actions import '/flutter_flow/custom_functions.dart'; // Imports custom functions import 'package:flutter/material.dart'; // Begin custom widget code // DO NOT REMOVE OR MODIFY THE CODE ABOVE! // ⬇⬇⬇ PLAK VANAF HIER ⬇⬇⬇ // (deze import mag, maar is niet strikt nodig: go_router komt hier ook // via de FlutterFlow-imports binnen — getest 2026-09-13) import 'package:go_router/go_router.dart'; /// Balkje dat zichzelf toont zodra de server onbereikbaar is. /// /// Waarom een custom widget en geen Text met een Visibility-conditie: de /// widgets in dit project lezen App State via de singleton `FFAppState()`, /// niet via `context.watch`. Een gewone conditie zou dus pas opnieuw /// evalueren als er toevallig iets anders een rebuild veroorzaakt. Dit /// widget luistert zelf naar FFAppState en verschijnt daardoor direct. class VerbindingsBanner extends StatefulWidget { const VerbindingsBanner({ super.key, this.width, this.height, this.tekst, }); final double? width; final double? height; final String? tekst; @override State createState() => _VerbindingsBannerState(); } class _VerbindingsBannerState extends State { // Gedeeld over alle instanties: bij het doorklikken tussen pagina's wordt // niet bij elke opbouw opnieuw een verzoek gedaan. static DateTime? _laatsteCheck; static const Duration _minimaalTussenChecks = Duration(seconds: 20); bool _bezig = false; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => _checkIndienNodig()); } Future _checkIndienNodig() async { final vorige = _laatsteCheck; if (vorige != null && DateTime.now().difference(vorige) < _minimaalTussenChecks) { return; } await _check(herlaadBijHerstel: false); } /// [herlaadBijHerstel] staat alleen aan bij een tik van de gebruiker. /// Automatisch herladen zou een lus opleveren: de pagina bouwt het widget /// opnieuw op, dat checkt weer, enzovoort. Future _check({bool herlaadBijHerstel = true}) async { if (_bezig) return; if (mounted) setState(() => _bezig = true); _laatsteCheck = DateTime.now(); bool bereikbaar = false; try { bereikbaar = await checkVerbinding(); } finally { if (mounted) setState(() => _bezig = false); } if (bereikbaar && herlaadBijHerstel && mounted) { // De FutureBuilders op deze pagina zijn al klaar met een mislukte // respons; alleen de balk weghalen laat een leeg scherm achter. // Daarom de huidige route opnieuw opbouwen, zodat de data alsnog laadt. final huidigePad = GoRouterState.of(context).uri.toString(); context.pushReplacement(huidigePad); } } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: FFAppState(), builder: (context, _) { if (!FFAppState().geenVerbinding) { // Neemt geen ruimte in zolang alles in orde is. return const SizedBox.shrink(); } return Material( color: Colors.transparent, child: InkWell( onTap: () => _check(), child: Container( width: widget.width ?? double.infinity, height: widget.height, color: FlutterFlowTheme.of(context).primary, padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), child: Row( mainAxisSize: MainAxisSize.max, children: [ const Icon(Icons.cloud_off, color: Colors.white, size: 18.0), const SizedBox(width: 8.0), Expanded( child: Text( widget.tekst ?? 'Geen verbinding — tik om het opnieuw te proberen', style: const TextStyle( color: Colors.white, fontSize: 13.0, ), ), ), if (_bezig) const SizedBox( width: 14.0, height: 14.0, child: CircularProgressIndicator( strokeWidth: 2.0, color: Colors.white, ), ), ], ), ), ), ); }, ); } }