From 25f546670d96fb45348690dfe5101b14d474803f Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 30 Dec 2024 12:37:31 +0800 Subject: [PATCH] #14 making sure that if a stopwatch was running and the application is stopped, all elapsed time is respected on the next app start --- lib/measurement/widget/stop_watch_widget.dart | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/measurement/widget/stop_watch_widget.dart b/lib/measurement/widget/stop_watch_widget.dart index 9934549..1e54dd6 100644 --- a/lib/measurement/widget/stop_watch_widget.dart +++ b/lib/measurement/widget/stop_watch_widget.dart @@ -11,7 +11,6 @@ import 'package:shared_preferences/shared_preferences.dart'; final _logger = getNamedLogger(); class StopWatchWidget extends ConsumerStatefulWidget { - const StopWatchWidget({super.key}); @override @@ -19,7 +18,6 @@ class StopWatchWidget extends ConsumerStatefulWidget { } class StopWatchState extends ConsumerState { - static const _preferencesKey = "measurement.duration.ongoing"; static final _storeFrequency = Duration(seconds: 15); @@ -30,7 +28,6 @@ class StopWatchState extends ConsumerState { Duration _measuredDuration = Duration.zero; bool _running = false; - @override void initState() { super.initState(); @@ -46,13 +43,25 @@ class StopWatchState extends ConsumerState { if (storedDurationMillis == null) { return; } - final storedDuration = Duration(milliseconds: storedDurationMillis); - final running = "y" == storedValue.substring(i + 1); - _logger.fine("found stored duration $storedDuration, running: $running"); + Duration storedDuration = Duration(milliseconds: storedDurationMillis); + + final storedLastMeasurementTimeMillis = int.tryParse(storedValue.substring(i + 1)); + DateTime? storedLastMeasurementTime; + if (storedLastMeasurementTimeMillis != null) { + storedLastMeasurementTime = DateTime.fromMillisecondsSinceEpoch(storedLastMeasurementTimeMillis); + } + _logger.fine("found stored duration $storedDuration, last measurement time: $storedLastMeasurementTime"); setState(() { - _lastMeasurementTime = clockProvider.now(); - _measuredDuration = storedDuration; - _running = running; + final now = clockProvider.now(); + + Duration runInBackgroundDuration = Duration(); + if (storedLastMeasurementTime != null) { + runInBackgroundDuration = now.difference(storedLastMeasurementTime); + } + + _lastMeasurementTime = now; + _measuredDuration = storedDuration + runInBackgroundDuration; + _running = storedLastMeasurementTime != null; _startTimerIfNecessary(); }); }); @@ -62,7 +71,10 @@ class StopWatchState extends ConsumerState { void dispose() { _timer?.cancel(); if (_running && _hasMeasurement()) { - _prefs.setString(_preferencesKey, "${_measuredDuration.inMilliseconds}:y"); + _prefs.setString( + _preferencesKey, + "${_measuredDuration.inMilliseconds}:${clockProvider.now().millisecondsSinceEpoch}", + ); } super.dispose(); } @@ -74,8 +86,9 @@ class StopWatchState extends ConsumerState { _measuredDuration += now.difference(_lastMeasurementTime); _lastMeasurementTime = now; if (now.difference(_lastStoreTime) > _storeFrequency) { - _prefs.setString(_preferencesKey, "${_measuredDuration.inMilliseconds}:y").then((_) { - _logger.fine("stored last stop watch measurement $_measuredDuration"); + final valueToStore = "${_measuredDuration.inMilliseconds}:${now.millisecondsSinceEpoch}"; + _prefs.setString(_preferencesKey, valueToStore).then((_) { + _logger.fine("stored last stop watch measurement: $valueToStore"); _lastStoreTime = now; }); } @@ -87,11 +100,12 @@ class StopWatchState extends ConsumerState { setState(() { _running = !_running; if (_running) { - _lastMeasurementTime = clockProvider.now(); + final now = clockProvider.now(); + _lastMeasurementTime = now; _lastStoreTime = _lastMeasurementTime; - _prefs.setString(_preferencesKey, "${_measuredDuration.inMilliseconds}:y"); + _prefs.setString(_preferencesKey, "${_measuredDuration.inMilliseconds}:${now.millisecondsSinceEpoch}"); } else { - _prefs.setString(_preferencesKey, "${_measuredDuration.inMilliseconds}:n"); + _prefs.setString(_preferencesKey, "${_measuredDuration.inMilliseconds}:"); } if (_running || _hasMeasurement()) { _startTimerIfNecessary(); @@ -161,9 +175,10 @@ class StopWatchState extends ConsumerState { child: GestureDetector( onTap: _toggle, child: AnimatedOpacity( - opacity: - (!_running && _measuredDuration > Duration.zero) - ? (clockProvider.now().millisecond % 1000 < 500) ? 0.0 : 1.0 + opacity: (!_running && _measuredDuration > Duration.zero) + ? (clockProvider.now().millisecond % 1000 < 500) + ? 0.0 + : 1.0 : 1.0, duration: Duration(milliseconds: 200), child: Text( @@ -186,13 +201,12 @@ class StopWatchState extends ConsumerState { ), SizedBox(width: 20), ElevatedButton.icon( - onPressed: _hasMeasurement() ? _saveMeasurement : null, - icon: Icon(Icons.save), - label: Text(AppLocalizations.of(context).textSave) - ), + onPressed: _hasMeasurement() ? _saveMeasurement : null, + icon: Icon(Icons.save), + label: Text(AppLocalizations.of(context).textSave)), ], ) ], ); } -} \ No newline at end of file +}