From 333b19ad07ee4a663f67f3baee0ad40e0d575c3d Mon Sep 17 00:00:00 2001 From: Maximilian Betz <Maximilian.Betz@awi.de> Date: Fri, 10 Jun 2022 11:17:05 +0200 Subject: [PATCH] disposing popups when leaving widget. --- lib/configuration.dart | 154 +++++++++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 52 deletions(-) diff --git a/lib/configuration.dart b/lib/configuration.dart index 482e404..f2bfc5c 100644 --- a/lib/configuration.dart +++ b/lib/configuration.dart @@ -20,9 +20,15 @@ class _MyHomePageState extends State<Configuration> { late Future<List<EventType>> futureEventTypes; late Future<List<Device>> futureDevices; late Future<String> futureAuthToken; + + var database = DatabaseInstance(); SensorConnector connector = SensorConnector(); final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); + + late OverlayEntry _overlayEntry; + + bool _initError = false; String _status = ''; TextStyle _statusStyle = const TextStyle(color: Colors.black); @@ -49,21 +55,39 @@ class _MyHomePageState extends State<Configuration> { await file.writeAsString(eventsJson); debugPrint('Stored file at: ' + filepath); - _status = 'Event database dump created: ' + filepath; - _statusStyle = const TextStyle(color: Colors.green); setState(() {}); HapticFeedback.vibrate(); - _showResultPopup(context, _status); + _showResultPopup(context, 'Event database dump created: ' + filepath, + false + ); } } - void _showResultPopup(BuildContext context, String text) async { + + Future<void> _showResultPopup(BuildContext context, String text, bool error) async { // Declaring and Initializing OverlayState // and OverlayEntry objects OverlayState? overlayState = Overlay.of(context); - OverlayEntry overlayEntry; - overlayEntry = OverlayEntry(builder: (context) { + try { + _overlayEntry.remove(); // Allow only one Overlay Popup + }catch(e){ + debugPrint('Overlay already removed, during dispose: ' + e.toString()); + } + _overlayEntry = OverlayEntry(builder: (context) { //: + + Color backGroundColor; + Color textColor; + if (error == true){ + //This is a error message display red! + backGroundColor = Colors.redAccent; + textColor = Colors.black; + } + else { + //This is a normal message display green! + backGroundColor = Colors.greenAccent; + textColor = Colors.black; + } // You can return any widget you like // here to be displayed on the Overlay @@ -75,7 +99,7 @@ class _MyHomePageState extends State<Configuration> { bottom: MediaQuery.of(context).size.height * 0.1, child: Material( borderRadius: BorderRadius.circular(8.0), - color: Colors.blue, + color: backGroundColor, //Some transparency remains child: Container( padding: const EdgeInsets.all(5.0), // Space between Text and Bubble width: MediaQuery.of(context).size.width * 0.95, @@ -85,9 +109,9 @@ class _MyHomePageState extends State<Configuration> { readOnly: true, autofocus: false, enabled: false, - //style: _statusStyle, + style: TextStyle(color: textColor), controller: TextEditingController( - text: _status, + text: text, ), ), ), @@ -98,16 +122,20 @@ class _MyHomePageState extends State<Configuration> { }); // Inserting the OverlayEntry into the Overlay - overlayState?.insert(overlayEntry); + overlayState?.insert(_overlayEntry); // Awaiting for 5 seconds await Future.delayed(const Duration(seconds: 5)); // Removing the OverlayEntry from the Overlay - overlayEntry.remove(); + try { + _overlayEntry.remove(); //NOTE: Is this a quick an dirty or a proper solution? + }catch(e){ + debugPrint('Overlay already removed, during dispose: ' + e.toString()); + } } - Future<void> updateConfiguration() async { + Future<void> updateConfiguration(BuildContext context) async { final EventStoreInstance event = EventStoreInstance(); String token = ''; @@ -133,22 +161,25 @@ class _MyHomePageState extends State<Configuration> { configuration.initialized = true; HapticFeedback.vibrate(); - //TODO: display success user feedback - //TODO: store complete "configuration" - await event.storeToSharedPrefs(); await configuration.storeToSharedPrefs(); debugPrint('Configuration stored!'); - _status = 'Login success, got all EventTypes, loaded Collection Devices & stored configuration for offline usage.'; - _statusStyle = const TextStyle(color: Colors.green); + _showResultPopup(context, + 'Login success, got all EventTypes, loaded Collection Devices & stored configuration for offline usage.', + false + ); setState(() {}); } catch (e) { String errorText = e.toString(); errorText = errorText.substring(10, errorText.length); //Remove 'Exception' from string. - _status = errorText; - _statusStyle = const TextStyle(color: Colors.red); + + _showResultPopup(context, + errorText, + true + ); + setState(() {}); } } @@ -157,11 +188,14 @@ class _MyHomePageState extends State<Configuration> { try { futureCollections = connector.fetchCollections(); await futureCollections; //wait and catch error here! + setState(() {}); + }catch(e){ String errorText = e.toString(); - errorText = errorText.substring(10, errorText.length); //Remove 'Exception' from string. - _status = errorText; - _statusStyle = const TextStyle(color: Colors.red); + errorText = errorText.substring(10, errorText.length); + + _status = errorText; //store errorText globally for pop up message during Widget build + _initError = true; //Trigger popup error display! setState(() {}); } } @@ -172,6 +206,16 @@ class _MyHomePageState extends State<Configuration> { fetchInitData(); } + @override + void dispose() { + try { + _overlayEntry.remove(); + }catch(e){ + debugPrint('Dispose error: ' + e.toString()); + } + super.dispose(); + } + @override Widget build(BuildContext context) { final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); @@ -261,6 +305,12 @@ class _MyHomePageState extends State<Configuration> { } if (snapshot.hasError) { debugPrint('Some error happened'); + + if(_initError == true){ + _initError = false; + //_showResultPopup(context, _status, true); //TODO: opening a popup does not work properly from here. + } + return const CircularProgressIndicator(); } else{ @@ -285,36 +335,36 @@ class _MyHomePageState extends State<Configuration> { ), ), bottomNavigationBar: Container( - margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0), - child:Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, - children: [ - FloatingActionButton.extended( - heroTag: null, - tooltip: 'Export events to local .json file', - icon: const Icon(Icons.download), - label: const Text('Dump Events'), - onPressed: () { - dumpToFile(context); - - //Reset for debug testing only. //Remove in RELEASE Version: - //database.delete(); - //events.reset(); - //configuration.reset(); - }, - ), - FloatingActionButton.extended( - heroTag: null, - tooltip: 'Download corresponding devices and store locally', - icon: const Icon(Icons.save), - label: const Text('Set'), - onPressed: () { - updateConfiguration(); - }, - ), - ], - ), + margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0), + child:Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + FloatingActionButton.extended( + heroTag: null, + tooltip: 'Export events to local .json file', + icon: const Icon(Icons.download), + label: const Text('Dump Events'), + onPressed: () { + dumpToFile(context); + + //Reset for debug testing only. //Remove in RELEASE Version: + //database.delete(); + //events.reset(); + //configuration.reset(); + }, + ), + FloatingActionButton.extended( + heroTag: null, + tooltip: 'Download corresponding devices and store locally', + icon: const Icon(Icons.save), + label: const Text('Set'), + onPressed: () { + updateConfiguration(context); + }, + ), + ], + ) ) ); } -- GitLab