Skip to content

Commit

Permalink
fixing internal _isExecuting propagation
Browse files Browse the repository at this point in the history
  • Loading branch information
escamoteur committed Nov 27, 2024
1 parent c02096f commit 512ed73
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
19 changes: 14 additions & 5 deletions lib/flutter_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ abstract class Command<TParam, TResult> extends CustomValueNotifier<TResult> {
: null);
});

/// forward busy states to the `isExecuting` Listenable
_commandResult.listen((x, _) => _isExecuting.value = x.isExecuting);
// /// forward busy states to the `isExecuting` Listenable
// _commandResult.listen((x, _) => _isExecuting.value = x.isExecuting);

/// Merge the external execution restricting with the internal
/// isExecuting which also blocks execution if true
Expand All @@ -208,6 +208,12 @@ abstract class Command<TParam, TResult> extends CustomValueNotifier<TResult> {
_isExecuting,
(restriction, isExecuting) => !restriction && !isExecuting,
) as ValueNotifier<bool>;

/// decouple the async isExecuting from the sync isExecuting
/// so that _canExecute will update immediately
_isExecuting.listen((busy, _) {
_isExecutingAsync.value = busy;
});
}

/// Calls the wrapped handler function with an optional input parameter
Expand Down Expand Up @@ -351,7 +357,7 @@ abstract class Command<TParam, TResult> extends CustomValueNotifier<TResult> {

/// `ValueListenable` that changes its value on any change of the execution
/// state change of the command
ValueListenable<bool> get isExecuting => _isExecuting;
ValueListenable<bool> get isExecuting => _isExecutingAsync;

/// `ValueListenable<bool>` that changes its value on any change of the current
/// executability state of the command. Meaning if the command can be executed or not.
Expand Down Expand Up @@ -447,8 +453,10 @@ abstract class Command<TParam, TResult> extends CustomValueNotifier<TResult> {
/// properties we make them private and only publish their `ValueListenable`
/// interface via getters.
late CustomValueNotifier<CommandResult<TParam?, TResult>> _commandResult;
final CustomValueNotifier<bool> _isExecuting =
final CustomValueNotifier<bool> _isExecutingAsync =
CustomValueNotifier<bool>(false, asyncNotification: true);
final CustomValueNotifier<bool> _isExecuting =
CustomValueNotifier<bool>(false);
late ValueNotifier<bool> _canExecute;
late final ValueListenable<bool>? _restriction;
final CustomValueNotifier<CommandError<TParam>?> _errors =
Expand All @@ -475,6 +483,7 @@ abstract class Command<TParam, TResult> extends CustomValueNotifier<TResult> {
_commandResult.dispose();
_canExecute.dispose();
_isExecuting.dispose();
_isExecutingAsync.dispose();
_errors.dispose();
if (!(_futureCompleter?.isCompleted ?? true)) {
_futureCompleter!.complete(null);
Expand Down Expand Up @@ -550,7 +559,7 @@ abstract class Command<TParam, TResult> extends CustomValueNotifier<TResult> {
}

bool get _hasLocalErrorHandler =>
_commandResult.listenerCount >= 3 || _errors.hasListeners;
_commandResult.listenerCount >= 2 || _errors.hasListeners;

void _handleErrorFiltered(
TParam? param, Object error, StackTrace stackTrace) {
Expand Down
8 changes: 6 additions & 2 deletions test/flutter_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,9 @@ void main() {
throw CustomException('Exception From Command');
},
initialValue: 'Initial Value',
);
)..errors.listen((error, _) {
print('Error: $error');
});
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
Expand Down Expand Up @@ -1345,7 +1347,9 @@ void main() {
throw CustomException('Exception From Command');
},
initialValue: 'Initial Value',
);
)..errors.listen((error, _) {
print('Error: $error');
});
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
Expand Down

0 comments on commit 512ed73

Please sign in to comment.