Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 83 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# Result Command

**Result Command** is a lightweight package that brings the **Command Pattern** to Flutter, allowing you to encapsulate actions, track their execution state, and manage results with clarity. Perfect for simplifying complex workflows, ensuring robust error handling, and keeping your UI reactive.
Expand All @@ -10,8 +9,10 @@
1. **Encapsulation**: Wrap your business logic into reusable commands.
2. **State Tracking**: Automatically manage states like `Idle`, `Running`, `Success`, `Failure`, and `Cancelled`.
3. **Error Handling**: Centralize how you handle successes and failures using the intuitive `Result` API.
4. **Cancellation Support**: Cancel long-running tasks when needed.
5. **UI Integration**: React to command state changes directly in your Flutter widgets.
4. **State History**: Track state transitions with optional metadata.
5. **Timeout Support**: Specify execution time limits for commands.
6. **Cancellation Support**: Cancel long-running tasks when needed.
7. **UI Integration**: React to command state changes directly in your Flutter widgets.

---

Expand All @@ -22,6 +23,7 @@ At its core, **Result Command** lets you define reusable actions (commands) that
- **Executes an action** (e.g., API call, user input validation).
- **Tracks its state** (`Idle`, `Running`, etc.).
- **Notifies listeners** when the state changes.
- **Maintains a history** of states and transitions.
- **Returns a result** (`Success` or `Failure`) using the `Result` API.

---
Expand Down Expand Up @@ -52,6 +54,30 @@ The state updates automatically as the command executes:
- Use `addListener` for manual handling.
- Use `ValueListenableBuilder` to bind the state to your UI.

## State History (`CommandHistory`)

Each command tracks a configurable history of its states, useful for debugging, auditing, and behavioral analysis.

### Configuring the History

Set the maximum length of the history when creating a command:

```dart
final command = Command0<String>(
() async => const Success('Done'),
maxHistoryLength: 5,
);
```

### Accessing the History

Access the history with `stateHistory`:

```dart
final history = command.stateHistory;
history.forEach(print);
```

---

## Getters for State Checks
Expand Down Expand Up @@ -116,7 +142,26 @@ fetchGreetingCommand.execute();

---

### Example 2: Command with Arguments
### Example 2: Simple Command with Timeout

Commands now support a timeout for execution:

```dart
final fetchGreetingCommand = Command0<String>(
() async {
await Future.delayed(Duration(seconds: 5)); // Simulating a delay.
return Success('Hello, World!');
},
);

fetchGreetingCommand.execute(timeout: Duration(seconds: 2)).catchError((error) {
print('Error: $error'); // "Error: Command timed out"
});
```

---

### Example 3: Command with Arguments

Pass input to your command's action:
```dart
Expand Down Expand Up @@ -145,7 +190,7 @@ calculateSquareCommand.execute(4);

---

### Example 3: Binding State to the UI
### Example 4: Binding State to the UI

Use `ValueListenableBuilder` to update the UI automatically:
```dart
Expand Down Expand Up @@ -184,7 +229,7 @@ Widget build(BuildContext context) {

---

### Example 4: Cancellation
### Example 5: Cancellation

Cancel long-running commands gracefully:
```dart
Expand Down Expand Up @@ -212,6 +257,37 @@ Future.delayed(Duration(seconds: 3), () {

---

### Example 6: Using Stream

Using Stream to Monitor State Changes:
```dart

final command = Command0<String>(
() async {
await Future.delayed(Duration(seconds: 2));
return Result.success("Action completed successfully");
},
);

command.stateStream.listen((state) {
if (state is IdleCommand) {
print("Command is idle.");
} else if (state is RunningCommand) {
print("Command is running.");
} else if (state is SuccessCommand<String>) {
print("Command succeeded with result: ${state.value}");
} else if (state is FailureCommand<String>) {
print("Command failed with error: ${state.error}");
} else if (state is CancelledCommand) {
print("Command was cancelled.");
}
});

command.execute();
```

---

## Benefits for Your Team

- **Simplified Collaboration**: Encapsulation makes it easier for teams to work independently on UI and business logic.
Expand Down Expand Up @@ -240,4 +316,4 @@ Future.delayed(Duration(seconds: 3), () {

We’d love your help in improving **Result Command**! Feel free to report issues, suggest features, or submit pull requests.

---
---
112 changes: 75 additions & 37 deletions coverage/lcov.info
Original file line number Diff line number Diff line change
@@ -1,42 +1,80 @@
SF:lib/src/command.dart
DA:40,1
DA:48,1
DA:49,1
DA:55,0
DA:56,0
DA:57,0
DA:58,0
DA:63,1
DA:64,2
DA:65,1
SF:lib\src\command.dart
DA:17,1
DA:21,1
DA:23,1
DA:25,4
DA:38,1
DA:39,1
DA:43,1
DA:44,2
DA:47,1
DA:48,2
DA:49,4
DA:50,2
DA:63,3
DA:66,1
DA:72,0
DA:73,0
DA:82,1
DA:83,2
DA:84,2
DA:88,1
DA:91,0
DA:94,1
DA:95,1
DA:96,1
DA:97,2
DA:98,1
DA:110,2
DA:67,2
DA:68,2
DA:69,1
DA:73,1
DA:75,2
DA:76,1
DA:90,2
DA:91,1
DA:92,3
DA:98,3
DA:100,3
DA:102,3
DA:104,3
DA:106,3
DA:108,1
DA:109,1
DA:115,1
DA:116,1
DA:117,4
DA:126,2
DA:118,2
DA:120,3
DA:124,2
DA:125,1
DA:132,1
DA:133,4
DA:142,0
DA:149,0
DA:150,0
DA:156,1
DA:161,1
DA:166,0
DA:133,2
DA:134,1
DA:144,1
DA:145,1
DA:148,3
DA:154,3
DA:155,2
DA:156,2
DA:159,1
DA:163,4
DA:164,3
DA:169,1
DA:170,1
DA:171,1
DA:177,0
DA:186,1
LF:38
LH:26
DA:172,1
DA:173,1
DA:183,1
DA:184,6
DA:187,1
DA:188,2
DA:189,1
DA:199,1
DA:200,1
DA:203,1
DA:204,4
DA:214,1
DA:215,1
DA:218,1
DA:219,4
DA:229,1
DA:230,1
DA:234,1
DA:235,4
DA:241,1
DA:246,1
DA:251,1
DA:256,1
DA:262,1
DA:271,1
LF:76
LH:76
end_of_record
Loading