part of '../async_action_button.dart'; class _AsyncMixin extends StatefulWidget { final AsyncActionCallback? onPressed; final AsyncActionController? controller; final AsyncErrorBuilder? errorBuilder; final void Function(String message)? onError; final VoidCallback? onSuccess; final bool showInlineError; final Widget Function(BuildContext context, bool busy, VoidCallback? handler) builder; const _AsyncMixin({ required this.onPressed, required this.builder, this.controller, this.errorBuilder, this.onError, this.onSuccess, this.showInlineError = false, }); @override State<_AsyncMixin> createState() => _AsyncMixinState(); } class _AsyncMixinState extends State<_AsyncMixin> { AsyncActionController? _own; AsyncActionController get _controller => widget.controller ?? (_own ??= AsyncActionController()); @override void initState() { super.initState(); _controller.addListener(_onControllerChange); } @override void didUpdateWidget(covariant _AsyncMixin oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.controller != widget.controller) { (oldWidget.controller ?? _own)?.removeListener(_onControllerChange); _controller.addListener(_onControllerChange); } } @override void dispose() { _controller.removeListener(_onControllerChange); _own?.dispose(); super.dispose(); } void _onControllerChange() { if (mounted) setState(() {}); } Future _trigger() async { final action = widget.onPressed; if (action == null) return; final success = await _controller.run( action, errorBuilder: widget.errorBuilder, ); if (!mounted) return; if (success) { Haptics.success(); widget.onSuccess?.call(); } else if (_controller.error != null) { Haptics.error(); widget.onError?.call(_controller.error!); } } @override Widget build(BuildContext context) { final busy = _controller.busy; final child = widget.builder( context, busy, busy || widget.onPressed == null ? null : _trigger, ); if (!widget.showInlineError) return child; return _InlineErrorWrapper(controller: _controller, child: child); } } class _InlineErrorWrapper extends StatelessWidget { final AsyncActionController controller; final Widget child; const _InlineErrorWrapper({required this.controller, required this.child}); @override Widget build(BuildContext context) { return AnimatedBuilder( animation: controller, builder: (context, _) { final err = controller.error; return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ child, if (err != null) ...[ const SizedBox(height: 8), Semantics( liveRegion: true, container: true, child: Text( err, textAlign: TextAlign.center, style: _asyncErrorTextStyle(context), ), ), ], ], ); }, ); } }