From 68b0d5834de05952e85fc82f7254188d9259a889 Mon Sep 17 00:00:00 2001 From: marco Date: Tue, 28 Jan 2025 15:36:14 +0100 Subject: [PATCH] refactored overlay loading indicator code --- lib/pages/landing_page.dart | 153 +++++++++++++++--------------- lib/services/overlay_service.dart | 47 +++++++++ 2 files changed, 121 insertions(+), 79 deletions(-) create mode 100644 lib/services/overlay_service.dart diff --git a/lib/pages/landing_page.dart b/lib/pages/landing_page.dart index da60de3..98780d1 100644 --- a/lib/pages/landing_page.dart +++ b/lib/pages/landing_page.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import '../model/flood_station.dart'; +import '../services/overlay_service.dart'; import '../widgets/flood_station_list_view.dart'; import '../services/flood_station_provider.dart'; import '../widgets/loading_notifier.dart'; @@ -14,10 +16,14 @@ class LandingPage extends StatefulWidget { State createState() => _LandingPageState(); } -class _LandingPageState extends State { +class _LandingPageState extends State with OverlayService { late FloodStationProvider floodStationProvider; - OverlayEntry? _overlayEntry; - int loadingTimes = 0; + + @override + void dispose() { + super.dispose(); + removeLoadingNotifier(); // Clean up overlay if needed + } @override Widget build(BuildContext context) { @@ -25,91 +31,80 @@ class _LandingPageState extends State { return Column( children: [ StationFilter( - onChanged: (filterText) { - if (filterText.isEmpty) { - floodStationProvider.filtered = false; - setState(() {}); - return; - } - showLoadingNotifier(context: context, message: 'Loading'); - floodStationProvider.loadFilteredStations(filterText); - floodStationProvider.filteredStationsFuture - ?.then((_) => removeLoadingNotifier()); - floodStationProvider.filtered = true; - }, + onChanged: (filterText) => _handleFilterChange(filterText), ), - _shouldShowList() - ? Expanded( - child: FloodStationListView( - stations: floodStationProvider.filtered - ? floodStationProvider.filteredStations - : floodStationProvider.allStations, - onItemTapped: (station) { - floodStationProvider.selectedStation = station; - Navigator.of(context).pushNamed(FloodStationPage.routeName); - }, - ), - ) - : Expanded( - child: Center( - child: ElevatedButton( - onPressed: () { - showLoadingNotifier(context: context, message: 'Loading'); - floodStationProvider - .loadAllStations() - .whenComplete(() => removeLoadingNotifier()); - }, - child: Text('Load all Stations'), - ), - ), - ), + _buildStationList(), ], ); } + Widget _buildStationList() { + if (!_shouldShowList()) { + return Expanded( + child: Center( + child: ElevatedButton( + onPressed: _handleLoadAllStations, + child: const Text('Load all Stations'), + ), + ), + ); + } + + return Expanded( + child: FloodStationListView( + stations: floodStationProvider.filtered + ? floodStationProvider.filteredStations + : floodStationProvider.allStations, + onItemTapped: _navigateToStationDetail, + ), + ); + } + + void _handleFilterChange(String filterText) { + if (filterText.isEmpty) { + floodStationProvider.filtered = false; + setState(() {}); + return; + } + + showLoadingNotifier( + context: context, + message: 'Loading', + onDismiss: () { + floodStationProvider.cancelFilterLoading(); + }, + ); + + floodStationProvider.loadFilteredStations(filterText); + floodStationProvider.filteredStationsFuture + ?.then((_) => removeLoadingNotifier()); + floodStationProvider.filtered = true; + } + + void _handleLoadAllStations() { + showLoadingNotifier( + context: context, + message: 'Loading', + onDismiss: () { + floodStationProvider.cancelFilterLoading(); + }, + ); + + floodStationProvider + .loadAllStations() + .whenComplete(() => removeLoadingNotifier()); + } + + void _navigateToStationDetail(FloodStation station) { + floodStationProvider.selectedStation = station; + Navigator.of(context).pushNamed(FloodStationPage.routeName); + } + bool _shouldShowList() { if (!floodStationProvider.filtered && floodStationProvider.allStations.isNotEmpty) { return true; } - if (floodStationProvider.filtered) { - return true; - } - return false; - } - - Future showLoadingNotifier({ - required BuildContext context, - required String message, - }) async { - if (_overlayEntry != null) return; - OverlayState? overlayState = Overlay.of(context); - _overlayEntry = OverlayEntry( - builder: (c) { - return Positioned( - bottom: 16, - left: 0, - right: 0, - child: Center( - child: LoadingNotifier( - message: 'Loading', - onDismissed: () { - floodStationProvider.cancelFilterLoading(); - removeLoadingNotifier(); - }, - ), - ), - ); - }, - ); - overlayState.insert(_overlayEntry!); - overlayState.setState(() {}); - } - - void removeLoadingNotifier() { - if (_overlayEntry != null) { - _overlayEntry?.remove(); - _overlayEntry = null; - } + return floodStationProvider.filtered; } } diff --git a/lib/services/overlay_service.dart b/lib/services/overlay_service.dart new file mode 100644 index 0000000..492a0fc --- /dev/null +++ b/lib/services/overlay_service.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +import '../widgets/loading_notifier.dart'; + +mixin OverlayService { + OverlayEntry? _overlayEntry; + + Future showLoadingNotifier({ + required BuildContext context, + required String message, + required VoidCallback onDismiss, + }) async { + if (_overlayEntry != null) return; + + final overlayState = Overlay.of(context); + _overlayEntry = OverlayEntry( + builder: (context) => Positioned( + bottom: 85, + left: 0, + right: 0, + child: Center( + child: LoadingNotifier( + message: message, + onDismissed: () { + onDismiss(); + removeLoadingNotifier(); + }, + ), + ), + ), + ); + + overlayState.insert(_overlayEntry!); + // overlayState.setState(() {}); + } + + void removeLoadingNotifier() { + if (_overlayEntry != null) { + _overlayEntry?.remove(); + _overlayEntry = null; + } + } + + void dispose() { + removeLoadingNotifier(); + } +}