show timer for actionable snackbar
This commit is contained in:
parent
c4e44183b0
commit
da1acfcb92
1 changed files with 70 additions and 2 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
|
@ -14,10 +15,14 @@ mixin FeedbackMixin {
|
||||||
|
|
||||||
// provide the messenger if feedback happens as the widget is disposed
|
// provide the messenger if feedback happens as the widget is disposed
|
||||||
void showFeedbackWithMessenger(ScaffoldMessengerState messenger, String message, [SnackBarAction? action]) {
|
void showFeedbackWithMessenger(ScaffoldMessengerState messenger, String message, [SnackBarAction? action]) {
|
||||||
|
final duration = action != null ? Durations.opToastActionDisplay : Durations.opToastDisplay;
|
||||||
messenger.showSnackBar(SnackBar(
|
messenger.showSnackBar(SnackBar(
|
||||||
content: Text(message),
|
content: _FeedbackMessage(
|
||||||
|
message: message,
|
||||||
|
duration: action != null ? duration : null,
|
||||||
|
),
|
||||||
action: action,
|
action: action,
|
||||||
duration: action != null ? Durations.opToastActionDisplay : Durations.opToastDisplay,
|
duration: duration,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,3 +141,66 @@ class _ReportOverlayState<T> extends State<ReportOverlay<T>> with SingleTickerPr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _FeedbackMessage extends StatefulWidget {
|
||||||
|
final String message;
|
||||||
|
final Duration? duration;
|
||||||
|
|
||||||
|
const _FeedbackMessage({
|
||||||
|
Key? key,
|
||||||
|
required this.message,
|
||||||
|
this.duration,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_FeedbackMessageState createState() => _FeedbackMessageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FeedbackMessageState extends State<_FeedbackMessage> {
|
||||||
|
late int _totalSecs, _elapsedSecs = 0;
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
final duration = widget.duration;
|
||||||
|
if (duration != null) {
|
||||||
|
_totalSecs = duration.inSeconds;
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
|
||||||
|
setState(() => _elapsedSecs++);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_timer?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final text = Text(widget.message);
|
||||||
|
final duration = widget.duration;
|
||||||
|
return duration == null
|
||||||
|
? text
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: text),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
CircularPercentIndicator(
|
||||||
|
percent: (_elapsedSecs.toDouble() / (_totalSecs - 1)).clamp(0.0, 1.0),
|
||||||
|
lineWidth: 2,
|
||||||
|
radius: 32,
|
||||||
|
backgroundColor: Theme.of(context).accentColor,
|
||||||
|
progressColor: Colors.grey,
|
||||||
|
animation: true,
|
||||||
|
animationDuration: 1000,
|
||||||
|
center: Text('${_totalSecs - _elapsedSecs}'),
|
||||||
|
animateFromLastPercent: true,
|
||||||
|
reverse: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue