Created
November 8, 2024 17:54
-
-
Save caseycrogers/68d4f29a2917dfa59563fc6bf7eecaf0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class ActionLogger extends StatefulWidget implements ActionDetails { | |
| const ActionLogger({ | |
| super.key, | |
| required this.async, | |
| required this.prefix, | |
| required this.name, | |
| required this.parameters, | |
| this.priority = kDefaultButtonPriority, | |
| required this.onError, | |
| required this.builder, | |
| }); | |
| final bool async; | |
| @override | |
| final String? prefix; | |
| @override | |
| final String name; | |
| @override | |
| final Map<String, Object>? parameters; | |
| @override | |
| final int priority; | |
| @override | |
| final void Function(Object error)? onError; | |
| final Widget Function( | |
| BuildContext context, | |
| FutureOr<void> Function(FutureOrCallback?, int) wrap, | |
| ) builder; | |
| @override | |
| State<ActionLogger> createState() => _ActionLoggerState(); | |
| } | |
| class _ActionLoggerState extends State<ActionLogger> { | |
| FutureOr<void>? _actionFuture; | |
| @override | |
| Widget build(BuildContext context) { | |
| final Widget child = widget.builder(context, wrap); | |
| if (!widget.async) { | |
| return child; | |
| } | |
| return Stack( | |
| children: [ | |
| Positioned.fill( | |
| child: Opacity( | |
| opacity: _actionFuture != null ? 1 : 0, | |
| child: Padding( | |
| padding: EdgeInsets.all(context.gutterSmall), | |
| child: const Center( | |
| child: CircularProgressIndicator(), | |
| ), | |
| ), | |
| ), | |
| ), | |
| AnimatedOpacity( | |
| duration: const Duration(milliseconds: 100), | |
| opacity: _actionFuture != null ? 0 : 1, | |
| child: child, | |
| ), | |
| ], | |
| ); | |
| } | |
| Future<void> wrap(FutureOrCallback? action, int priority) async { | |
| if (action == null) { | |
| return; | |
| } | |
| try { | |
| // This could be customized by making it a static method that you set in | |
| // your app's main function. | |
| unawaited(Analytics.instance._logEvent( | |
| priority: priority, | |
| name: widget.prefix == null | |
| ? widget.name | |
| : '${widget.prefix}_${widget.name}', | |
| parameters: widget.parameters, | |
| )); | |
| final FutureOr<void> maybeFuture = action(); | |
| if (maybeFuture is Future<void>) { | |
| _actionFuture = maybeFuture.whenComplete(() { | |
| _actionFuture = null; | |
| if (mounted) { | |
| setState(() {}); | |
| } | |
| }); | |
| setState(() {}); | |
| } else { | |
| return; | |
| } | |
| await _actionFuture; | |
| } catch (error) { | |
| // Wrap this in try catch to ensure that it doesn't replace the original | |
| // error in the event that it throws. | |
| try { | |
| widget.onError?.call(error); | |
| } catch (e, stack) { | |
| FlutterError.onError!( | |
| FlutterErrorDetails( | |
| exception: error, | |
| stack: stack, | |
| ), | |
| ); | |
| } | |
| rethrow; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment