Full Code of marcglasberg/async_redux for AI

master 8adc3bb8e7d7 cached
232 files
2.0 MB
548.5k tokens
2771 symbols
1 requests
Download .txt
Showing preview only (2,194K chars total). Download the full file or copy to clipboard to get everything.
Repository: marcglasberg/async_redux
Branch: master
Commit: 8adc3bb8e7d7
Files: 232
Total size: 2.0 MB

Directory structure:
gitextract_bzwe_hyt/

├── .claude/
│   ├── settings.local.json
│   └── skills/
│       ├── asyncredux-abort-dispatch/
│       │   └── SKILL.md
│       ├── asyncredux-action-status/
│       │   └── SKILL.md
│       ├── asyncredux-actions-no-state-change/
│       │   └── SKILL.md
│       ├── asyncredux-async-actions/
│       │   └── SKILL.md
│       ├── asyncredux-base-action/
│       │   └── SKILL.md
│       ├── asyncredux-before-after/
│       │   └── SKILL.md
│       ├── asyncredux-check-internet-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-connector-pattern/
│       │   └── SKILL.md
│       ├── asyncredux-debounce-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-debugging/
│       │   └── SKILL.md
│       ├── asyncredux-dependency-injection/
│       │   └── SKILL.md
│       ├── asyncredux-dispatching-actions/
│       │   └── SKILL.md
│       ├── asyncredux-error-handling/
│       │   └── SKILL.md
│       ├── asyncredux-events/
│       │   └── SKILL.md
│       ├── asyncredux-flutter-hooks/
│       │   └── SKILL.md
│       ├── asyncredux-navigation/
│       │   └── SKILL.md
│       ├── asyncredux-nonreentrant-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-observers/
│       │   └── SKILL.md
│       ├── asyncredux-optimistic-update-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-persistence/
│       │   └── SKILL.md
│       ├── asyncredux-provider-integration/
│       │   └── SKILL.md
│       ├── asyncredux-retry-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-selectors/
│       │   └── SKILL.md
│       ├── asyncredux-setup/
│       │   └── SKILL.md
│       ├── asyncredux-state-access/
│       │   └── SKILL.md
│       ├── asyncredux-state-design/
│       │   └── SKILL.md
│       ├── asyncredux-streams-timers/
│       │   └── SKILL.md
│       ├── asyncredux-sync-actions/
│       │   └── SKILL.md
│       ├── asyncredux-testing-basics/
│       │   └── SKILL.md
│       ├── asyncredux-testing-view-models/
│       │   └── SKILL.md
│       ├── asyncredux-testing-wait-methods/
│       │   └── SKILL.md
│       ├── asyncredux-throttle-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-undo-redo/
│       │   └── SKILL.md
│       ├── asyncredux-user-exceptions/
│       │   └── SKILL.md
│       ├── asyncredux-wait-condition/
│       │   └── SKILL.md
│       └── asyncredux-wait-fail-succeed/
│           └── SKILL.md
├── .github/
│   ├── copilot-instructions.md
│   └── workflows/
│       └── test.yaml
├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── context_select_patterns.md
├── example/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── analysis_options.yaml
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle.kts
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   └── AndroidManifest.xml
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── com/
│   │   │       │   │       └── example/
│   │   │       │   │           └── example/
│   │   │       │   │               └── MainActivity.kt
│   │   │       │   └── res/
│   │   │       │       ├── drawable/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── drawable-v21/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── values/
│   │   │       │       │   └── styles.xml
│   │   │       │       └── values-night/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle.kts
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   └── settings.gradle.kts
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── LaunchImage.imageset/
│   │   │   │       ├── Contents.json
│   │   │   │       └── README.md
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── Info.plist
│   │   │   └── Runner-Bridging-Header.h
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   ├── Runner.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   └── xcshareddata/
│   │   │       ├── IDEWorkspaceChecks.plist
│   │   │       └── WorkspaceSettings.xcsettings
│   │   └── RunnerTests/
│   │       └── RunnerTests.swift
│   ├── lib/
│   │   ├── main.dart
│   │   ├── main_before_and_after.dart
│   │   ├── main_dependency_injection.dart
│   │   ├── main_event.dart
│   │   ├── main_event_2.dart
│   │   ├── main_infinite_scroll.dart
│   │   ├── main_is_waiting_works_when_multiple_actions.dart
│   │   ├── main_navigate.dart
│   │   ├── main_optimistic_command.dart
│   │   ├── main_optimistic_sync.dart
│   │   ├── main_optimistic_sync_with_push.dart
│   │   ├── main_polling.dart
│   │   ├── main_select.dart
│   │   ├── main_select_2.dart
│   │   ├── main_show_error_dialog.dart
│   │   ├── main_show_spinner.dart
│   │   ├── main_wait_action_advanced_1.dart
│   │   ├── main_wait_action_advanced_2.dart
│   │   ├── main_wait_action_simple.dart
│   │   └── store_connector_examples/
│   │       ├── README.md
│   │       ├── main_async__store_connector.dart
│   │       ├── main_async_base_factory__store_connector.dart.dart
│   │       ├── main_environment__store_connector.dart
│   │       ├── main_event__store_connector.dart
│   │       ├── main_extension_vs_store_connector.dart
│   │       ├── main_infinite_scroll__store_connector.dart
│   │       ├── main_is_waiting_works_when_multiple_actions__store_connector.dart
│   │       ├── main_is_waiting_works_when_state_unchanged__store_connector.dart
│   │       ├── main_navigate__store_connector.dart
│   │       ├── main_null_viewmodel__connector.dart
│   │       ├── main_should_update_model__store_connector.dart
│   │       ├── main_spinner__store_connector.dart
│   │       ├── main_static_view_model__store_connector.dart
│   │       ├── main_sync__store_connector.dart
│   │       ├── main_wait_action_advanced_1__store_connector.dart
│   │       ├── main_wait_action_advanced_2__store_connector.dart
│   │       └── main_wait_action_simple__store_connector.dart
│   ├── pubspec.yaml
│   ├── web/
│   │   ├── index.html
│   │   └── manifest.json
│   └── windows/
│       ├── .gitignore
│       ├── CMakeLists.txt
│       ├── flutter/
│       │   ├── CMakeLists.txt
│       │   ├── generated_plugin_registrant.cc
│       │   ├── generated_plugin_registrant.h
│       │   └── generated_plugins.cmake
│       └── runner/
│           ├── CMakeLists.txt
│           ├── Runner.rc
│           ├── flutter_window.cpp
│           ├── flutter_window.h
│           ├── main.cpp
│           ├── resource.h
│           ├── runner.exe.manifest
│           ├── utils.cpp
│           ├── utils.h
│           ├── win32_window.cpp
│           └── win32_window.h
├── lib/
│   ├── async_redux.dart
│   ├── local_json_persist.dart
│   ├── local_persist.dart
│   └── src/
│       ├── action_mixins.dart
│       ├── action_observer.dart
│       ├── advanced_user_exception.dart
│       ├── cache.dart
│       ├── cloud_sync.dart
│       ├── connection_exception.dart
│       ├── connector_tester.dart
│       ├── error_observer.dart
│       ├── event_redux.dart
│       ├── global_wrap_error.dart
│       ├── local_json_persist.dart
│       ├── local_persist.dart
│       ├── log.dart
│       ├── mock_build_context.dart
│       ├── mock_store.dart
│       ├── model_observer.dart
│       ├── navigate_action.dart
│       ├── persistor.dart
│       ├── process_persistence.dart
│       ├── redux_action.dart
│       ├── show_dialog_super.dart
│       ├── state_observer.dart
│       ├── store.dart
│       ├── store_exception.dart
│       ├── store_provider_and_connector.dart
│       ├── store_tester.dart
│       ├── test_info.dart
│       ├── user_exception_dialog.dart
│       ├── view_model.dart
│       ├── wait.dart
│       ├── wait_action.dart
│       └── wrap_reduce.dart
├── mixin_compatibility.md
├── pubspec.yaml
└── test/
    ├── abort_dispatch_test.dart
    ├── action_initial_state_test.dart
    ├── action_status_test.dart
    ├── action_to_string_test.dart
    ├── action_wrap_reduce2_test.dart
    ├── action_wrap_reduce_test.dart
    ├── after_throws_test.dart
    ├── before_reduce_after_order_test.dart
    ├── before_throwing_errors_test.dart
    ├── cache_test.dart
    ├── check_internet_mixin_test.dart
    ├── context_environment_test.dart
    ├── context_event_test.dart
    ├── context_select_advanced_test.dart
    ├── context_select_test.dart
    ├── context_state_test.dart
    ├── debounce_mixin_test.dart
    ├── dispatch_and_wait_all_actions_test.dart
    ├── dispatch_and_wait_test.dart
    ├── dispatch_sync_test.dart
    ├── dispatch_test.dart
    ├── event_redux_test.dart
    ├── failed_action_test.dart
    ├── fresh_mixin_test.dart
    ├── local_json_persist_test.dart
    ├── local_persist_test.dart
    ├── mock_build_context_test.dart
    ├── mock_store_test.dart
    ├── model_observer_test.dart
    ├── navigate_action_test.dart
    ├── non_reentrant_test.dart
    ├── optimistic_command_mixin_test.dart
    ├── optimistic_sync_test.dart
    ├── optimistic_sync_with_push_test.dart
    ├── persistence_test.dart
    ├── polling_mixin_test.dart
    ├── props_test.dart
    ├── reducer_future_or_test.dart
    ├── retry_mixin_test.dart
    ├── server_push_init_test.dart
    ├── server_push_test.dart
    ├── store_connector_test.dart
    ├── store_observer_test.dart
    ├── store_provider_test.dart
    ├── store_tester_test.dart
    ├── store_wait_action_test.dart
    ├── store_wrap_reduce_test.dart
    ├── sync_async_test.dart
    ├── test_utils.dart
    ├── throttle_mixin_test.dart
    ├── user_exception_test.dart
    ├── view_model_test.dart
    └── wait_action_test.dart

================================================
FILE CONTENTS
================================================

================================================
FILE: .claude/settings.local.json
================================================
{
  "permissions": {
    "allow": [
      "Bash(flutter test:*)",
      "Bash(flutter analyze:*)",
      "Bash(dart test:*)",
      "WebFetch(domain:asyncredux.com)",
      "WebFetch(domain:pub.dev)",
      "WebFetch(domain:raw.githubusercontent.com)",
      "WebFetch(domain:github.com)",
      "Bash(curl:*)",
      "Bash(ls:*)",
      "mcp__dart__pub_dev_search",
      "mcp__dart__pub",
      "mcp__dart__analyze_files",
      "mcp__dart__run_tests"
    ],
    "deny": [],
    "ask": []
  }
}


================================================
FILE: .claude/skills/asyncredux-abort-dispatch/SKILL.md
================================================
---
name: asyncredux-abort-dispatch
description: Stops an AsyncRedux (Flutter) action from dispatching. Use only when the user mentions abortDispatch(), or explicitly asks to abort or prevent dispatch under certain conditions.
---

# AsyncRedux Aborting the Dispatch

## What is abortDispatch()?

The `abortDispatch()` method is an optional method on `ReduxAction` that lets you
conditionally prevent an action from executing. When this method returns `true`, the
entire action is skipped—`before()`, `reduce()`, and `after()` will NOT run, and state
remains unchanged.

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() {
    // Return true to abort, false to proceed
    return someCondition;
  }

  @override
  AppState? reduce() {
    // Only runs if abortDispatch() returned false
    return state.copy(/* ... */);
  }
}
```

## Basic Usage

The simplest use case is checking a condition before allowing the action to proceed:

```dart
class LoadUserProfile extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;

  @override
  Future<AppState?> reduce() async {
    // Only runs if user is logged in
    final profile = await api.fetchProfile(state.user!.id);
    return state.copy(profile: profile);
  }
}
```

## Action Lifecycle with abortDispatch()

When `abortDispatch()` returns `true`, the complete action lifecycle is skipped:

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.shouldSkip;  // If true:

  @override
  void before() {
    // NOT called when aborted
  }

  @override
  AppState? reduce() {
    // NOT called when aborted
  }

  @override
  void after() {
    // NOT called when aborted
  }
}
```

This differs from throwing an error in `before()`, which would still cause `after()` to
run.

## Authentication Guard Pattern

A common pattern is creating a base action that requires authentication:

```dart
/// Base action that requires an authenticated user
abstract class AuthenticatedAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;
}

/// Actions extending this will only run when user is logged in
class FetchUserOrders extends AuthenticatedAction {
  @override
  Future<AppState?> reduce() async {
    // Safe to use state.user! here - abortDispatch ensures it's not null
    final orders = await api.getOrders(state.user!.id);
    return state.copy(orders: orders);
  }
}

class UpdateUserSettings extends AuthenticatedAction {
  final Settings newSettings;
  UpdateUserSettings(this.newSettings);

  @override
  Future<AppState?> reduce() async {
    await api.updateSettings(state.user!.id, newSettings);
    return state.copy(settings: newSettings);
  }
}
```

## Creating Base Actions with Abort Logic

You can combine multiple abort conditions in a base action:

```dart
abstract class AppAction extends ReduxAction<AppState> {
  // Override in subclasses to add action-specific abort logic
  bool shouldAbort() => false;

  @override
  bool abortDispatch() {
    // Global abort conditions
    if (state.isMaintenanceMode) return true;
    if (state.isAppLocked) return true;

    // Action-specific abort conditions
    return shouldAbort();
  }
}

class RefreshData extends AppAction {
  @override
  bool shouldAbort() {
    // Don't refresh if data is still fresh
    return state.lastRefresh != null &&
        DateTime.now().difference(state.lastRefresh!) < Duration(minutes: 5);
  }

  @override
  Future<AppState?> reduce() async {
    final data = await api.fetchData();
    return state.copy(data: data, lastRefresh: DateTime.now());
  }
}
```

## Role-Based Authorization

Use `abortDispatch()` to implement role-based access control:

```dart
abstract class AdminAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user?.role != UserRole.admin;
}

class DeleteAllUsers extends AdminAction {
  @override
  Future<AppState?> reduce() async {
    // Only admins can reach this code
    await api.deleteAllUsers();
    return state.copy(users: []);
  }
}
```

## Conditional Feature Actions

Prevent actions when features are disabled:

```dart
class UsePremiumFeature extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => !state.user!.isPremium;

  @override
  AppState? reduce() {
    // Premium-only functionality
    return state.copy(/* ... */);
  }
}
```

## Built-in Mixin: AbortWhenNoInternet

AsyncRedux provides `AbortWhenNoInternet`, a mixin that silently aborts actions when
there's no internet connection:

```dart
class FetchLatestNews extends AppAction with AbortWhenNoInternet {
  @override
  Future<AppState?> reduce() async {
    // Only runs if internet is available
    final news = await api.fetchNews();
    return state.copy(news: news);
  }
}
```

Key characteristics of `AbortWhenNoInternet`:

- No error dialogs are shown
- No exceptions are thrown
- The action is silently cancelled
- Only checks if device internet is on/off (not server availability)

Compare with `CheckInternet` which shows an error dialog instead of silently aborting.

## abortDispatch() vs Throwing in before()

Choose the right approach for your use case:

| Approach                       | `after()` runs? | Shows error?           | Use when             |
|--------------------------------|-----------------|------------------------|----------------------|
| `abortDispatch()` returns true | No              | No                     | Silently skip action |
| Throw in `before()`            | Yes             | Yes (if UserException) | Show error to user   |

```dart
// Silent abort - user doesn't know action was skipped
class SilentRefresh extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.isOffline;
  // ...
}

// Visible error - user sees message
class ExplicitRefresh extends ReduxAction<AppState> {
  @override
  void before() {
    if (state.isOffline) {
      throw UserException('Cannot refresh while offline');
    }
  }
  // ...
}
```

## When to Use abortDispatch()

**Good use cases:**

- Authentication guards (action requires logged-in user)
- Authorization checks (action requires specific role/permission)
- Feature flags (action only for premium users)
- Freshness checks (don't refetch if data is recent)
- Maintenance mode (disable certain actions globally)
- Idempotency (skip if action's effect already applied)

**Consider alternatives when:**

- You want the user to see an error message (throw `UserException` in `before()`)
- You need cleanup code to run (use `before()` + `after()` pattern)
- You're implementing rate limiting (use `Throttle` or `Debounce` mixins)
- You're preventing duplicate dispatches (use `NonReentrant` mixin)

## Complete Example

```dart
// Base action with common abort logic
abstract class AppAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() {
    // Global maintenance mode check
    if (state.maintenanceMode) return true;
    return false;
  }
}

// Authenticated action that also checks maintenance mode
abstract class AuthenticatedAction extends AppAction {
  @override
  bool abortDispatch() {
    // Check parent conditions first
    if (super.abortDispatch()) return true;
    // Then check authentication
    return state.currentUser == null;
  }
}

// Admin action with full authorization chain
abstract class AdminAction extends AuthenticatedAction {
  @override
  bool abortDispatch() {
    if (super.abortDispatch()) return true;
    return state.currentUser?.role != UserRole.admin;
  }
}

// Concrete action using the hierarchy
class BanUser extends AdminAction {
  final String userId;
  BanUser(this.userId);

  @override
  Future<AppState?> reduce() async {
    // Only reaches here if:
    // 1. Not in maintenance mode
    // 2. User is logged in
    // 3. User is an admin
    await api.banUser(userId);
    return state.copy(
      users: state.users.where((u) => u.id != userId).toList(),
    );
  }
}
```

## Important Notes

- `abortDispatch()` is checked before `before()`, `reduce()`, and `after()`
- When aborted, no state changes occur
- The action is silently skipped—no errors are thrown or logged by default
- Use this feature judiciously; the documentation warns it's "a powerful feature" that
  should only be used "if you are sure it is the right solution"

## References

URLs from the documentation:

- https://asyncredux.com/flutter/advanced-actions/aborting-the-dispatch
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/advanced-actions/action-status
- https://asyncredux.com/flutter/advanced-actions/control-mixins
- https://asyncredux.com/flutter/advanced-actions/internet-mixins
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/basics/action-simplification


================================================
FILE: .claude/skills/asyncredux-action-status/SKILL.md
================================================
---
name: asyncredux-action-status
description: Checks an AsyncRedux (Flutter) action's completion status using ActionStatus right after the dispatch returns. Use only when you need to know whether an action completed, whether it failed with an error, what error it produced, or how to navigate based on success or failure.
---

# ActionStatus in AsyncRedux

The `ActionStatus` object provides information about whether an action completed successfully or encountered errors. It is returned by `dispatchAndWait()` and related methods.

## Getting ActionStatus

Use `dispatchAndWait()` to get the status after an action completes:

```dart
var status = await dispatchAndWait(MyAction());
```

From within an action, you can also use:

```dart
var status = await dispatchAndWait(SomeOtherAction());
```

## ActionStatus Properties

### Completion Status

- **`isCompleted`**: Returns `true` if the action has finished executing (whether successful or failed)
- **`isCompletedOk`**: Returns `true` if the action finished without errors in both `before()` and `reduce()` methods
- **`isCompletedFailed`**: Returns `true` if the action encountered errors (opposite of `isCompletedOk`)

### Error Information

- **`originalError`**: The error originally thrown by `before()` or `reduce()`, before any modification
- **`wrappedError`**: The error after processing by the action's `wrapError()` method

### Execution Tracking

These properties track which lifecycle methods have completed:

- **`hasFinishedMethodBefore`**: Returns `true` if the `before()` method completed
- **`hasFinishedMethodReduce`**: Returns `true` if the `reduce()` method completed
- **`hasFinishedMethodAfter`**: Returns `true` if the `after()` method completed

Note: The execution tracking properties are primarily meant for testing and debugging. In production code, focus on `isCompletedOk` and `isCompletedFailed`.

## Common Use Cases

### Conditional Navigation After Success

The most common production use is checking if an action succeeded before navigating:

```dart
// In a widget callback
Future<void> _onSavePressed() async {
  var status = await context.dispatchAndWait(SaveFormAction());
  if (status.isCompletedOk) {
    Navigator.pop(context);
  }
}
```

Another example with push navigation:

```dart
Future<void> _onLoginPressed() async {
  var status = await context.dispatchAndWait(LoginAction(
    email: emailController.text,
    password: passwordController.text,
  ));

  if (status.isCompletedOk) {
    Navigator.pushReplacementNamed(context, '/home');
  }
  // If failed, the error will be shown via UserExceptionDialog
}
```

### Testing Action Errors

Use ActionStatus to verify that actions throw expected errors:

```dart
test('MyAction fails with invalid input', () async {
  var store = Store<AppState>(initialState: AppState.initial());

  var status = await store.dispatchAndWait(MyAction(value: -1));

  expect(status.isCompletedFailed, isTrue);
  expect(status.wrappedError, isA<UserException>());
  expect((status.wrappedError as UserException).msg, "Value must be positive");
});
```

### Testing Action Success

```dart
test('SaveAction completes successfully', () async {
  var store = Store<AppState>(initialState: AppState.initial());

  var status = await store.dispatchAndWait(SaveAction(data: validData));

  expect(status.isCompletedOk, isTrue);
  expect(store.state.saved, isTrue);
});
```

### Checking Original vs Wrapped Error

When your action uses `wrapError()` to transform errors, you can inspect both:

```dart
class MyAction extends AppAction {
  @override
  Future<AppState?> reduce() async {
    throw Exception('Network error');
  }

  @override
  Object? wrapError(Object error, StackTrace stackTrace) {
    return UserException('Could not save. Please try again.');
  }
}

// In test:
var status = await store.dispatchAndWait(MyAction());
expect(status.originalError, isA<Exception>()); // The original Exception
expect(status.wrappedError, isA<UserException>()); // The wrapped UserException
```

## Action Lifecycle and Status

The action lifecycle runs in this order:

1. `before()` - Runs first, can be used for preconditions
2. `reduce()` - Runs second (only if `before()` succeeded)
3. `after()` - Runs last, always executes (like a finally block)

The `isCompletedOk` property is `true` only if both `before()` and `reduce()` completed without errors. Note that errors in `after()` do not affect `isCompletedOk`.

If `before()` throws an error, `reduce()` will not run, but `after()` will still execute.

## Best Practices

1. **Use state changes for UI updates**: In production, prefer checking state changes rather than action status. Reserve ActionStatus for cases where you need to perform side effects (like navigation) based on success/failure.

2. **Use `isCompletedOk` for navigation**: The common pattern is to navigate only after an action succeeds:
   ```dart
   if (status.isCompletedOk) Navigator.pop(context);
   ```

3. **Use `wrappedError` in tests**: When testing error handling, check `wrappedError` to see what the user will actually see (after `wrapError()` processing).

4. **Use `originalError` for debugging**: When you need to see the underlying error before any transformation, use `originalError`.

## References

URLs from the documentation:
- https://asyncredux.com/flutter/advanced-actions/action-status
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/failed-actions
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/miscellaneous/navigation
- https://asyncredux.com/flutter/testing/store-tester
- https://asyncredux.com/flutter/testing/dispatch-wait-and-expect
- https://asyncredux.com/flutter/testing/testing-user-exceptions


================================================
FILE: .claude/skills/asyncredux-actions-no-state-change/SKILL.md
================================================
---
name: asyncredux-actions-no-state-change
description: Creates AsyncRedux (Flutter) actions that return null from reduce() to not change the state. Such actions can still do side effects, dispatch other actions, or do nothing. 
---

# Actions That Don't Change State

In AsyncRedux, returning a new state from reducers is **optional**. When you don't need to
modify the application state, return `null` to keep the current state unchanged.

## Basic Pattern

Return `null` from `reduce()` when no state modification is needed:

```dart
class MyAction extends ReduxAction<AppState> {
  AppState? reduce() {
    // Perform side effects here
    return null; // State remains unchanged
  }
}
```

## Conditional State Updates

Only update state when certain conditions are met:

```dart
class GetAmount extends ReduxAction<AppState> {
  Future<AppState?> reduce() async {
    int amount = await getAmount();
    if (amount == 0)
      return null; // No change needed
    else
      return state.copy(counter: state.counter + amount);
  }
}
```

## Coordinating Other Actions

Actions that dispatch other actions but don't modify state directly:

```dart
class InitAction extends ReduxAction<AppState> {
  AppState? reduce() {
    dispatch(ReadDatabaseAction());
    dispatch(StartTimersAction());
    dispatch(TurnOnListenersAction());
    return null; // This action doesn't change state itself
  }
}
```

## Triggering External Services

Call external services without modifying app state:

```dart
class SendNotification extends ReduxAction<AppState> {
  final String message;
  SendNotification(this.message);

  Future<AppState?> reduce() async {
    await notificationService.send(message);
    return null;
  }
}
```

## Navigation Actions

Trigger navigation as a side effect:

```dart
class GoToSettings extends ReduxAction<AppState> {
  AppState? reduce() {
    dispatch(NavigateAction.pushNamed('/settings'));
    return null;
  }
}
```

## Key Points

1. Actions that do return a new state can **also** do side effects and dispatch other actions.
2. **Return type matters**: Use `AppState?` for sync, `Future<AppState?>` for async
3. **Null means no change**: The store keeps its current state

## References

URLs from the documentation:

- https://asyncredux.com/flutter/basics/changing-state-is-optional
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/basics/sync-actions
- https://asyncredux.com/flutter/basics/async-actions
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer


================================================
FILE: .claude/skills/asyncredux-async-actions/SKILL.md
================================================
---
name: asyncredux-async-actions
description: Creates AsyncRedux (Flutter) asynchronous actions for API calls, database operations, and other async work. 
---

# AsyncRedux Async Actions

## Basic Async Action Structure

An action becomes asynchronous when its `reduce()` method returns `Future<AppState?>`
instead of `AppState?`. Use this for database access, API calls, file operations, or any
work requiring `await`.

```dart
class FetchUser extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    final user = await api.fetchUser();
    return state.copy(user: user);
  }
}
```

Unlike traditional Redux requiring middleware, AsyncRedux makes it simple: return a
`Future` and it works.

## Critical Rule: Every Path Must Have await

If the action is async (returns a Future) and changes the state (returns a non-null
state), the framework requires that,  **all execution paths contain at least
one `await`**. Never declare `Future<AppState?>` if you don't actually await something.

### Valid Patterns

```dart
// Simple async with await
Future<AppState?> reduce() async {
  final data = await fetchData();
  return state.copy(data: data);
}

// Using microtask (minimum valid await)
Future<AppState?> reduce() async {
  await microtask;
  return state.copy(timestamp: DateTime.now());
}

// Conditional - both paths have await
Future<AppState?> reduce() async {
  if (state.needsRefresh) {
    return await fetchAndUpdate();
  }
  else return await validateCurrent();
}

// Always returns null
Future<AppState?> reduce() async {
  if (state.needsRefresh) {
    await fetchAndUpdate();
  }  
  
  return null;
}
```

### Invalid Patterns (Will Cause Issues)

```dart
// WRONG: No await at all
Future<AppState?> reduce() async {
  return state.copy(counter: state.counter + 1);
}

// WRONG: await only on some paths
Future<AppState?> reduce() async {
  if (condition) {
    return await fetchData();
  }
  return state; // No await on this path!
}

// WRONG: Calling async function without await
Future<AppState?> reduce() async {
  someAsyncFunction(); // Not awaited
  return state;
}
```

## Using assertUncompletedFuture()

For complex reducers with multiple code paths, add `assertUncompletedFuture()` before the
final return. This catches violations at runtime during development:

```dart
class ComplexAction extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    if (state.cacheValid) {
      // Complex logic that might accidentally skip await
      return processCache();
    }

    final data = await fetchFromServer();
    final processed = transform(data);

    assertUncompletedFuture(); // Validates at least one await occurred
    return state.copy(data: processed);
  }
}
```

## State Changes During Async Operations

The `state` getter can change after every `await` because other actions may modify state
while yours is waiting:

```dart
class AsyncAction extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    print(state.counter); // e.g., 5

    await someSlowOperation();

    // state.counter might now be different (e.g., 10)
    // if another action modified it during the await
    print(state.counter);

    return state.copy(counter: state.counter + 1);
  }
}
```

### Using initialState for Comparison

Use `initialState` to access the state as it was when the action was dispatched (never
changes):

```dart
class SafeIncrement extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    final originalCounter = initialState.counter;

    await validateWithServer();

    // Check if state changed while we were waiting
    if (state.counter != originalCounter) {
      // State was modified by another action
      return null; // Abort our change
    }

    return state.copy(counter: state.counter + 1);
  }
}
```

## Dispatching Async Actions

### Fire and Forget

Use `dispatch()` when you don't need to wait for completion:

```dart
context.dispatch(FetchUser());
// Returns immediately, action runs in background
```

### Wait for Completion

Use `dispatchAndWait()` to await the action's completion:

```dart
await context.dispatchAndWait(FetchUser());
// Continues only after action finishes AND state changes
print('User loaded: ${context.state.user.name}');
```

### Dispatch Multiple in Parallel

```dart
// Fire all, don't wait
context.dispatchAll([FetchUser(), FetchSettings(), FetchNotifications()]);

// Fire all and wait for all to complete
await context.dispatchAndWaitAll([FetchUser(), FetchSettings()]);
```

## Showing Loading States

Use `isWaiting()` to show spinners while async actions run:

```dart
Widget build(BuildContext context) {
  if (context.isWaiting(FetchUser)) return CircularProgressIndicator();  
  else return Text('Hello, ${context.state.user.name}');
}
```

## Error Handling

Throw `UserException` for user-facing errors:

```dart
class FetchUser extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    final response = await api.fetchUser();

    if (response.statusCode == 404) 
      throw UserException('User not found.');    

    if (response.statusCode != 200) 
      throw UserException('Failed to load user. Please try again.');    

    return state.copy(user: response.data);
  }
}
```

Check for failures in widgets:

```dart
Widget build(BuildContext context) {
  if (context.isFailed(FetchUser)) {
    return Text('Error: ${context.exceptionFor(FetchUser)?.message}');
  }
  // ...
}
```

## Complete Example

```dart
// Async action with proper error handling
class LoadProducts extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    try {
      final products = await api.fetchProducts();
      return state.copy(products: products, productsLoaded: true);
    } catch (e) {
      throw UserException('Could not load products. Check your connection.');
    }
  }
}

// Widget showing all three states
Widget build(BuildContext context) {
  // Loading state
  if (context.isWaiting(LoadProducts)) {
    return Center(child: CircularProgressIndicator());
  }

  // Error state
  if (context.isFailed(LoadProducts)) {
    return Center(
      child: Column(
        children: [
          Text(context.exceptionFor(LoadProducts)?.message ?? 'Error'),
          ElevatedButton(
            onPressed: () => context.dispatch(LoadProducts()),
            child: Text('Retry'),
          ),
        ],
      ),
    );
  }

  // Success state
  return ListView.builder(
    itemCount: context.state.products.length,
    itemBuilder: (_, i) => ProductTile(context.state.products[i]),
  );
}
```

## Return Type Warning

Never return `FutureOr<AppState?>` directly. AsyncRedux must know if the action is sync or
async:

```dart
// CORRECT
Future<AppState?> reduce() async { ... }

// CORRECT
AppState? reduce() { ... }

// WRONG - throws StoreException
FutureOr<AppState?> reduce() { ... }
```

## References

URLs from the documentation:

- https://asyncredux.com/flutter/basics/async-actions
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/basics/failed-actions
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/wait-fail-succeed


================================================
FILE: .claude/skills/asyncredux-base-action/SKILL.md
================================================
---
name: asyncredux-base-action
description: Create a custom base action class for your app. Covers adding getter shortcuts to state parts, adding selector methods, implementing shared wrapError logic, and establishing project-wide action conventions.
---

# Creating a Custom Base Action Class

Every AsyncRedux application should define an abstract base action class that all actions
extend. This provides a central place for:

- Convenient getter shortcuts to state parts
- Selector methods for common queries
- Shared error handling logic
- Type-safe environment access
- Project-wide conventions

## Basic Base Action Setup

Create an abstract class extending `ReduxAction<AppState>`.
The recomended name is `AppAction`, in file `app_action.dart`:

```dart
abstract class AppAction extends ReduxAction<AppState> {
  // All your actions will extend this class
}
```

Then extend `AppAction` instead of `ReduxAction<AppState>` in all your actions:

```dart
class IncrementCounter extends AppAction {
  @override
  AppState reduce() => state.copy(counter: state.counter + 1);
}
```

## Adding Getter Shortcuts to State Parts

When your state has nested objects, add getters to simplify access:

```dart
abstract class AppAction extends ReduxAction<AppState> {
  // Shortcuts to nested state parts
  User get user => state.user;
  Settings get settings => state.settings;
  IList<Todo> get todos => state.todos;
  Cart get cart => state.cart;
}
```

Now actions can write cleaner code:

```dart
class UpdateUserName extends AppAction {
  final String name;
  UpdateUserName(this.name);

  @override
  AppState reduce() {
    // Instead of: state.user.name
    // You can write: user.name
    return state.copy(user: user.copy(name: name));
  }
}
```

## Adding Selector Methods

For common data lookups, add selector methods directly to your base action:

```dart
abstract class AppAction extends ReduxAction<AppState> {
  // Getters for state parts
  User get user => state.user;
  IList<Item> get items => state.items;

  // Selector methods
  Item? findItemById(String id) =>
      items.firstWhereOrNull((item) => item.id == id);

  List<Item> get completedItems =>
      items.where((item) => item.isCompleted).toList();

  bool get isLoggedIn => user.isAuthenticated;
}
```

Actions can then use these selectors:

```dart
class MarkItemComplete extends AppAction {
  final String itemId;
  MarkItemComplete(this.itemId);

  @override
  AppState reduce() {
    final item = findItemById(itemId);
    if (item == null) return null; // No change

    return state.copy(
      items: items.replaceFirstWhere(
        (i) => i.id == itemId,
        item.copy(isCompleted: true),
      ),
    );
  }
}
```

### Using a Separate Selector Class

For most applications, it's better to use instead a dedicated selector class to keep the
base action clean:

```dart
class ActionSelect {
  final AppState state;
  ActionSelect(this.state);

  Item? findById(String id) =>
      state.items.firstWhereOrNull((item) => item.id == id);

  List<Item> get completed =>
      state.items.where((item) => item.isCompleted).toList();

  List<Item> get pending =>
      state.items.where((item) => !item.isCompleted).toList();
}

abstract class AppAction extends ReduxAction<AppState> {
  ActionSelect get select => ActionSelect(state);
}
```

These namespaces selectors under `select`, enabling IDE autocompletion:

```dart
class ProcessItem extends AppAction {
  final String itemId;
  ProcessItem(this.itemId);

  @override
  AppState reduce() {
    // IDE autocomplete shows: select.findById, select.completed, etc.
    final item = select.findById(itemId);
    // ...
  }
}
```

## Type-Safe Environment Access

For dependency injection, override the `env` getter in your base action:

```dart
class Environment {
  final ApiClient api;
  final AuthService auth;
  final AnalyticsService analytics;

  Environment({
    required this.api,
    required this.auth,
    required this.analytics,
  });
}

abstract class AppAction extends ReduxAction<AppState> {
  // Type-safe access to environment
  @override
  Environment get env => super.env as Environment;

  // Convenience getters for common services
  ApiClient get api => env.api;
  AuthService get auth => env.auth;
}
```

Actions can then use services directly:

```dart
class FetchUserProfile extends AppAction {
  @override
  Future<AppState?> reduce() async {
    // Uses the api getter from base action
    final profile = await api.getUserProfile();
    return state.copy(user: profile);
  }
}
```

## References

URLs from the documentation:

- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/advanced-actions/action-selectors
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/wrapping-the-reducer
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/aborting-the-dispatch
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/basics/state
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/miscellaneous/business-logic
- https://asyncredux.com/flutter/miscellaneous/dependency-injection


================================================
FILE: .claude/skills/asyncredux-before-after/SKILL.md
================================================
---
name: asyncredux-before-after
description: Implement action lifecycle methods `before()` and `after()`. Covers running precondition checks, showing/hiding modal barriers, cleanup logic in `after()`, and understanding that `after()` always runs (like a finally block).
---

# AsyncRedux Before and After Methods

## Action Lifecycle Overview

Every `ReduxAction` has three lifecycle methods that execute in order:

1. `before()` - Runs first, before the reducer
2. `reduce()` - The main reducer (required)
3. `after()` - Runs last, always executes

Only `reduce()` is required. The `before()` and `after()` methods are optional hooks for managing side effects.

## The before() Method

The `before()` method executes before the reducer runs. It can be synchronous or asynchronous.

### Synchronous before()

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  void before() {
    // Runs synchronously before reduce()
    print('Action starting');
  }

  @override
  AppState? reduce() {
    return state.copy(counter: state.counter + 1);
  }
}
```

### Asynchronous before()

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  Future<void> before() async {
    // Runs asynchronously before reduce()
    await validatePermissions();
  }

  @override
  Future<AppState?> reduce() async {
    final data = await fetchData();
    return state.copy(data: data);
  }
}
```

### Precondition Checks in before()

If `before()` throws an error, `reduce()` will NOT run. This makes it ideal for validation:

```dart
class FetchUserData extends ReduxAction<AppState> {
  @override
  Future<void> before() async {
    if (!await hasInternetConnection()) {
      throw UserException('No internet connection');
    }
  }

  @override
  Future<AppState?> reduce() async {
    // Only runs if before() completed without error
    final user = await api.fetchUser();
    return state.copy(user: user);
  }
}
```

### Common before() Use Cases

- Validate preconditions (authentication, permissions)
- Check network connectivity
- Show loading indicators or modal barriers
- Log action start for analytics
- Dispatch prerequisite actions

## The after() Method

The `after()` method executes after the reducer completes. Its key property: **it always runs, even if `before()` or `reduce()` throws an error**. This makes it similar to a `finally` block.

### Basic after()

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  AppState? reduce() {
    return state.copy(counter: state.counter + 1);
  }

  @override
  void after() {
    // Always runs, regardless of success or failure
    print('Action completed');
  }
}
```

### Guaranteed Cleanup

Because `after()` always runs, it's perfect for cleanup operations:

```dart
class SaveDocument extends ReduxAction<AppState> {
  @override
  Future<void> before() async {
    dispatch(ShowSavingIndicatorAction(true));
  }

  @override
  Future<AppState?> reduce() async {
    await api.saveDocument(state.document);
    return state.copy(lastSaved: DateTime.now());
  }

  @override
  void after() {
    // Hides indicator even if save fails
    dispatch(ShowSavingIndicatorAction(false));
  }
}
```

### Important: Never Throw from after()

The `after()` method should never throw errors. Any exception thrown from `after()` will appear asynchronously in the console and cannot be caught normally:

```dart
// WRONG - Don't throw in after()
@override
void after() {
  if (someCondition) {
    throw Exception('This will cause problems');
  }
}

// CORRECT - Handle errors gracefully
@override
void after() {
  try {
    cleanup();
  } catch (e) {
    // Log but don't throw
    logger.error('Cleanup failed: $e');
  }
}
```

### Common after() Use Cases

- Hide loading indicators or modal barriers
- Close database connections or file handles
- Release temporary resources
- Log action completion for analytics
- Dispatch follow-up actions

## Modal Barrier Pattern

A common pattern is showing a modal barrier (blocking overlay) during async operations:

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    String description = await read(Uri.http("numbersapi.com", "${state.counter}"));
    return state.copy(description: description);
  }

  @override
  void before() => dispatch(BarrierAction(true));

  @override
  void after() => dispatch(BarrierAction(false));
}
```

The `BarrierAction` would update state to show/hide a loading overlay:

```dart
class BarrierAction extends ReduxAction<AppState> {
  final bool show;
  BarrierAction(this.show);

  @override
  AppState reduce() => state.copy(showBarrier: show);
}
```

## Creating Reusable Mixins

For patterns you use repeatedly, create a mixin:

```dart
mixin Barrier on ReduxAction<AppState> {
  @override
  void before() {
    super.before();
    dispatch(BarrierAction(true));
  }

  @override
  void after() {
    dispatch(BarrierAction(false));
    super.after();
  }
}
```

Then apply it to any action:

```dart
class FetchData extends ReduxAction<AppState> with Barrier {
  @override
  Future<AppState?> reduce() async {
    // Barrier shown automatically before this runs
    final data = await api.fetchData();
    return state.copy(data: data);
    // Barrier hidden automatically after (even on error)
  }
}
```

### Multiple Mixins

You can combine multiple mixins:

```dart
class ImportantAction extends ReduxAction<AppState> with Barrier, NonReentrant {
  @override
  Future<AppState?> reduce() async {
    // Has both modal barrier AND prevents duplicate dispatches
    return state;
  }
}
```

## Error Handling Flow

Understanding how errors interact with the lifecycle:

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  Future<void> before() async {
    // If this throws, reduce() is skipped, after() still runs
  }

  @override
  Future<AppState?> reduce() async {
    // If this throws, state is not changed, after() still runs
  }

  @override
  void after() {
    // ALWAYS runs regardless of errors above
  }
}
```

### Checking What Completed

Use `ActionStatus` to determine which methods finished:

```dart
var status = await dispatchAndWait(MyAction());

if (status.hasFinishedMethodBefore) {
  print('before() completed');
}

if (status.hasFinishedMethodReduce) {
  print('reduce() completed');
}

if (status.hasFinishedMethodAfter) {
  print('after() completed');
}

if (status.isCompletedOk) {
  print('Both before() and reduce() completed without errors');
}

if (status.isCompletedFailed) {
  print('Error: ${status.originalError}');
}
```

## Relationship with abortDispatch()

If `abortDispatch()` returns `true`, none of the lifecycle methods run:

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;

  @override
  void before() {
    // Skipped if abortDispatch() returns true
  }

  @override
  AppState? reduce() {
    // Skipped if abortDispatch() returns true
  }

  @override
  void after() {
    // Skipped if abortDispatch() returns true
  }
}
```

## Complete Example

```dart
class SubmitForm extends ReduxAction<AppState> {
  final String formData;
  SubmitForm(this.formData);

  @override
  Future<void> before() async {
    // Validate preconditions
    if (state.user == null) {
      throw UserException('Please log in first');
    }

    if (!await checkInternetConnection()) {
      throw UserException('No internet connection');
    }

    // Show loading state
    dispatch(SetSubmittingAction(true));
  }

  @override
  Future<AppState?> reduce() async {
    final result = await api.submitForm(formData);
    return state.copy(
      lastSubmission: result,
      submissionCount: state.submissionCount + 1,
    );
  }

  @override
  void after() {
    // Always hide loading state, even on error
    dispatch(SetSubmittingAction(false));

    // Log completion
    analytics.log('form_submitted');
  }
}
```

## Built-in Mixins Using before() and after()

Several AsyncRedux mixins use these methods internally:

| Mixin | Uses before() | Uses after() | Purpose |
|-------|--------------|--------------|---------|
| `CheckInternet` | Yes | No | Verifies connectivity, shows dialog if offline |
| `AbortWhenNoInternet` | Yes | No | Silently aborts if offline |
| `Throttle` | No | Yes | Limits execution frequency |
| `NonReentrant` | Yes | Yes | Prevents duplicate dispatches |
| `Retry` | No | Yes | Retries on failure |
| `Debounce` | No | No | Waits for input pause (uses `wrapReduce`) |

When using these mixins, be aware that they may already override `before()` or `after()`. Call `super.before()` and `super.after()` if you need to combine behaviors.

## References

URLs from the documentation:
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/action-status
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/aborting-the-dispatch
- https://asyncredux.com/flutter/advanced-actions/wrapping-the-reducer


================================================
FILE: .claude/skills/asyncredux-check-internet-mixin/SKILL.md
================================================
---
name: asyncredux-check-internet-mixin
description: Add the CheckInternet mixin to ensure network connectivity before action execution. Covers automatic error dialogs, combining with NoDialog for custom UI handling, and AbortWhenNoInternet for silent abort.
---

# CheckInternet Mixin

The `CheckInternet` mixin verifies device connectivity before an action executes. If there's no internet connection, the action aborts and displays a dialog with the message: "There is no Internet. Please, verify your connection."

## Basic Usage

```dart
class LoadText extends AppAction with CheckInternet {

  Future<AppState?> reduce() async {
    var response = await http.get('https://api.example.com/text');
    return state.copy(text: response.body);
  }
}
```

The mixin works by overriding the `before()` method. If the device lacks connectivity, it throws a `UserException` which triggers the standard error dialog.

## Customizing the Error Message

Override `connectionException()` to return a custom `UserException`:

```dart
class LoadText extends AppAction with CheckInternet {

  @override
  UserException connectionException(UserException error) {
    return UserException('Unable to load data. Check your connection.');
  }

  Future<AppState?> reduce() async {
    var response = await http.get('https://api.example.com/text');
    return state.copy(text: response.body);
  }
}
```

## NoDialog Modifier

Use `NoDialog` alongside `CheckInternet` to suppress the automatic error dialog. This allows you to handle connectivity failures in your widgets using `isFailed()` and `exceptionFor()`:

```dart
class LoadText extends AppAction with CheckInternet, NoDialog {

  Future<AppState?> reduce() async {
    var response = await http.get('https://api.example.com/text');
    return state.copy(text: response.body);
  }
}
```

Then handle the error in your widget:

```dart
Widget build(BuildContext context) {
  if (context.isWaiting(LoadText)) {
    return CircularProgressIndicator();
  }

  if (context.isFailed(LoadText)) {
    var exception = context.exceptionFor(LoadText);
    return Text('Error: ${exception?.message}');
  }

  return Text(context.state.text);
}
```

## AbortWhenNoInternet

Use `AbortWhenNoInternet` for silent failure when offline. The action aborts without throwing errors or displaying dialogs—as if it had never been dispatched:

```dart
class RefreshData extends AppAction with AbortWhenNoInternet {

  Future<AppState?> reduce() async {
    var response = await http.get('https://api.example.com/data');
    return state.copy(data: response.body);
  }
}
```

This is useful for background refreshes or non-critical operations where user notification isn't needed.

## UnlimitedRetryCheckInternet

This mixin combines three capabilities: internet verification, unlimited retry with exponential backoff, and non-reentrant behavior. It's ideal for essential operations like loading startup data:

```dart
class LoadAppStartupData extends AppAction with UnlimitedRetryCheckInternet {

  Future<AppState?> reduce() async {
    var response = await http.get('https://api.example.com/startup');
    return state.copy(startupData: response.body);
  }
}
```

Default retry parameters:
- Initial delay: 350ms
- Multiplier: 2
- Maximum delay with internet: 5 seconds
- Maximum delay without internet: 1 second

Track retry attempts via the `attempts` getter and customize logging through `printRetries()`.

## Mixin Compatibility

Important compatibility rules:
- `CheckInternet` and `AbortWhenNoInternet` are **incompatible** with each other
- Neither `CheckInternet` nor `AbortWhenNoInternet` can be combined with `UnlimitedRetryCheckInternet`
- `CheckInternet` works well with `Retry`, `NonReentrant`, `Throttle`, `Debounce`, and optimistic mixins

## Testing Internet Connectivity

Two methods for simulating connectivity in tests:

**Per-action simulation** - Override `internetOnOffSimulation` within specific actions:

```dart
class LoadText extends AppAction with CheckInternet {
  @override
  bool? get internetOnOffSimulation => false; // Simulate offline

  Future<AppState?> reduce() async {
    // ...
  }
}
```

**Global simulation** - Set `forceInternetOnOffSimulation` on the store:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
);
store.forceInternetOnOffSimulation = false; // All actions see no internet
```

## Limitations

These mixins only detect device connectivity status. They cannot verify:
- Internet provider functionality
- Server availability
- API endpoint reachability

For server-specific connectivity checks, implement additional validation in your action's `reduce()` method or `before()` method.

## References

URLs from the documentation:
- https://asyncredux.com/flutter/advanced-actions/internet-mixins
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/aborting-the-dispatch
- https://asyncredux.com/flutter/basics/failed-actions
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/control-mixins
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/basics/wait-fail-succeed
- https://asyncredux.com/flutter/testing/mocking


================================================
FILE: .claude/skills/asyncredux-connector-pattern/SKILL.md
================================================
---
name: asyncredux-connector-pattern
description: Implement the Connector pattern for separating smart and dumb widgets. Covers creating StoreConnector widgets, implementing VmFactory and Vm classes, building view-models, and optimizing rebuilds with view-model equality.
---

## Overview

The connector pattern separates store access logic from UI presentation. Instead of widgets directly accessing the store via `context.state` and `context.dispatch()`, a "smart" connector widget extracts store data and passes it to a "dumb" presentational widget through constructor parameters.

## Why Use the Connector Pattern?

1. **Testing simplification** - Test UI widgets without creating a Redux store by passing mock data
2. **Separation of concerns** - UI widgets focus on appearance; connectors handle business logic
3. **Reusability** - Presentational widgets function independently of Redux
4. **Code clarity** - Widget code is not cluttered with state access and transformation logic
5. **Optimized rebuilds** - Only rebuild when the view-model changes

## The Three Components

### 1. ViewModel (Vm)

Contains only the data the UI widget requires. Extends `Vm` and lists equality fields:

```dart
class CounterViewModel extends Vm {
  final int counter;
  final String description;
  final VoidCallback onIncrement;

  CounterViewModel({
    required this.counter,
    required this.description,
    required this.onIncrement,
  }) : super(equals: [counter, description]);
}
```

The `equals` list tells AsyncRedux which fields to compare when deciding whether to rebuild. Callbacks (like `onIncrement`) should NOT be included in `equals`.

### 2. VmFactory

Transforms store state into a view-model. Extends `VmFactory` and implements `fromStore()`:

```dart
class CounterFactory extends VmFactory<AppState, CounterConnector, CounterViewModel> {
  CounterFactory(connector) : super(connector);

  @override
  CounterViewModel fromStore() => CounterViewModel(
    counter: state.counter,
    description: state.description,
    onIncrement: () => dispatch(IncrementAction()),
  );
}
```

The factory has access to:
- `state` - The store state when the factory was created
- `dispatch()` - To dispatch actions from callbacks
- `dispatchSync()` - For synchronous dispatch
- `connector` - Reference to the parent connector widget

### 3. StoreConnector

Bridges the store and UI widget:

```dart
class CounterConnector extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, CounterViewModel>(
      vm: () => CounterFactory(this),
      builder: (BuildContext context, CounterViewModel vm) => CounterWidget(
        counter: vm.counter,
        description: vm.description,
        onIncrement: vm.onIncrement,
      ),
    );
  }
}
```

The "dumb" widget receives data through constructor parameters:

```dart
class CounterWidget extends StatelessWidget {
  final int counter;
  final String description;
  final VoidCallback onIncrement;

  const CounterWidget({
    required this.counter,
    required this.description,
    required this.onIncrement,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('$counter'),
        Text(description),
        ElevatedButton(
          onPressed: onIncrement,
          child: Text('Increment'),
        ),
      ],
    );
  }
}
```

## Rebuild Optimization

Each time an action changes the store state, `StoreConnector` compares the new view-model with the previous one. It only rebuilds if they differ (based on the `equals` list).

To prevent rebuilds even when state changes, use `notify: false`:

```dart
dispatch(MyAction(), notify: false);
```

## Advanced Factory Techniques

### Accessing Connector Properties

Pass data from the connector widget to the factory:

```dart
class UserConnector extends StatelessWidget {
  final int userId;
  const UserConnector({required this.userId});

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, UserViewModel>(
      vm: () => UserFactory(this),
      builder: (context, vm) => UserWidget(user: vm.user),
    );
  }
}

class UserFactory extends VmFactory<AppState, UserConnector, UserViewModel> {
  UserFactory(connector) : super(connector);

  @override
  UserViewModel fromStore() => UserViewModel(
    // Access connector.userId here
    user: state.users.firstWhere((u) => u.id == connector.userId),
  );
}
```

### state vs currentState()

Inside the factory:
- `state` - The state when the factory was created (final, won't change)
- `currentState()` - The current store state at the moment of the call

These usually match, but diverge in callbacks after `dispatchSync()`:

```dart
@override
UserViewModel fromStore() => UserViewModel(
  onSave: () {
    dispatchSync(SaveAction());
    // state still has old value
    // currentState() has new value after SaveAction
  },
);
```

### Using the vm Getter in Callbacks

Access already-computed view-model fields in callbacks to avoid redundant calculations:

```dart
@override
UserViewModel fromStore() => UserViewModel(
  name: state.user.name,
  onSave: () {
    // Use vm.name instead of recalculating from state
    print('Saving user: ${vm.name}');
    dispatch(SaveAction(vm.name));
  },
);
```

**Note:** The `vm` getter is only available after `fromStore()` completes. Use it in callbacks, not during view-model construction.

### Base Factory Pattern

Create a base factory to reduce boilerplate:

```dart
abstract class BaseFactory<T extends StatelessWidget, Model extends Vm>
    extends VmFactory<AppState, T, Model> {
  BaseFactory(T connector) : super(connector);

  // Common getters
  User get user => state.user;
  Settings get settings => state.settings;
}

class MyFactory extends BaseFactory<MyConnector, MyViewModel> {
  MyFactory(connector) : super(connector);

  @override
  MyViewModel fromStore() => MyViewModel(
    user: user,  // Uses inherited getter
  );
}
```

## Nullable View-Models

When you cannot generate a valid view-model (e.g., data still loading), return null:

```dart
class HomeConnector extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, HomeViewModel?>(  // Nullable type
      vm: () => HomeFactory(this),
      builder: (BuildContext context, HomeViewModel? vm) {  // Nullable param
        return (vm == null)
          ? Text("User not logged in")
          : HomePage(user: vm.user);
      },
    );
  }
}

class HomeFactory extends VmFactory<AppState, HomeConnector, HomeViewModel?> {
  HomeFactory(connector) : super(connector);

  @override
  HomeViewModel? fromStore() {  // Nullable return
    return (state.user == null)
      ? null
      : HomeViewModel(user: state.user!);
  }
}
```

## Migrating from flutter_redux

If migrating from `flutter_redux`, you can use the `converter` parameter instead of `vm`:

```dart
class MyConnector extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, ViewModel>(
      converter: (store) => ViewModel.fromStore(store),
      builder: (context, vm) => MyWidget(name: vm.name),
    );
  }
}

class ViewModel extends Vm {
  final String name;
  final VoidCallback onSave;

  ViewModel({required this.name, required this.onSave})
    : super(equals: [name]);

  static ViewModel fromStore(Store<AppState> store) {
    return ViewModel(
      name: store.state.name,
      onSave: () => store.dispatch(SaveAction()),
    );
  }
}
```

Note: `vm` and `converter` are mutually exclusive. The `vm` approach is recommended for new code.

## Debugging Rebuilds

To observe when connectors rebuild, pass a `modelObserver` to the store:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  modelObserver: DefaultModelObserver(),
);
```

Add `debug: this` to StoreConnector for connector type names in logs:

```dart
StoreConnector<AppState, ViewModel>(
  debug: this,
  vm: () => Factory(this),
  builder: (context, vm) => MyWidget(vm: vm),
);
```

Override `toString()` in your ViewModel for custom diagnostic output:

```dart
class MyViewModel extends Vm {
  final int counter;
  MyViewModel({required this.counter}) : super(equals: [counter]);

  @override
  String toString() => 'MyViewModel{counter: $counter}';
}
```

Console output shows rebuild information:
```
Model D:1 R:1 = Rebuild:true, Connector:MyWidgetConnector, Model:MyViewModel{counter: 5}
```

## Testing View-Models

Use `Vm.createFrom()` to test view-models in isolation:

```dart
test('view-model properties', () {
  var store = Store<AppState>(initialState: AppState(name: "Mary"));
  var vm = Vm.createFrom(store, MyFactory());

  expect(vm.name, "Mary");
});

test('view-model callbacks dispatch actions', () async {
  var store = Store<AppState>(initialState: AppState(name: "Mary"));
  var vm = Vm.createFrom(store, MyFactory());

  vm.onChangeName("Bill");
  await store.waitActionType(ChangeNameAction);
  expect(store.state.name, "Bill");
});
```

**Important:** `Vm.createFrom()` can only be called once per factory instance. Create a new factory for each test.

## Complete Example

```dart
// State
class AppState {
  final int counter;
  final String description;
  AppState({required this.counter, required this.description});
  AppState copy({int? counter, String? description}) => AppState(
    counter: counter ?? this.counter,
    description: description ?? this.description,
  );
}

// Action
class IncrementAction extends ReduxAction<AppState> {
  @override
  AppState reduce() => state.copy(counter: state.counter + 1);
}

// View-Model
class CounterViewModel extends Vm {
  final int counter;
  final String description;
  final VoidCallback onIncrement;

  CounterViewModel({
    required this.counter,
    required this.description,
    required this.onIncrement,
  }) : super(equals: [counter, description]);
}

// Factory
class CounterFactory extends VmFactory<AppState, CounterConnector, CounterViewModel> {
  CounterFactory(connector) : super(connector);

  @override
  CounterViewModel fromStore() => CounterViewModel(
    counter: state.counter,
    description: state.description,
    onIncrement: () => dispatch(IncrementAction()),
  );
}

// Connector (Smart Widget)
class CounterConnector extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, CounterViewModel>(
      vm: () => CounterFactory(this),
      builder: (context, vm) => CounterWidget(
        counter: vm.counter,
        description: vm.description,
        onIncrement: vm.onIncrement,
      ),
    );
  }
}

// Presentational Widget (Dumb Widget)
class CounterWidget extends StatelessWidget {
  final int counter;
  final String description;
  final VoidCallback onIncrement;

  const CounterWidget({
    required this.counter,
    required this.description,
    required this.onIncrement,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('$counter', style: TextStyle(fontSize: 48)),
        Text(description),
        SizedBox(height: 20),
        ElevatedButton(
          onPressed: onIncrement,
          child: Text('Increment'),
        ),
      ],
    );
  }
}
```

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/connector/connector-pattern
- https://asyncredux.com/flutter/connector/store-connector
- https://asyncredux.com/flutter/connector/advanced-view-model
- https://asyncredux.com/flutter/connector/cannot-generate-view-model
- https://asyncredux.com/flutter/connector/migrating-from-flutter-redux
- https://asyncredux.com/flutter/testing/testing-the-view-model
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/miscellaneous/observing-rebuilds


================================================
FILE: .claude/skills/asyncredux-debounce-mixin/SKILL.md
================================================
---
name: asyncredux-debounce-mixin
description: Add the Debounce mixin to wait for user input pauses before acting. Covers setting the `debounce` duration, implementing search-as-you-type, and avoiding excessive API calls during rapid input.
---

# Debounce Mixin

The `Debounce` mixin delays action execution until after a period of inactivity. Each new dispatch resets the timer, so the action only runs once dispatching stops for the specified duration. This is ideal for search-as-you-type functionality and avoiding excessive API calls during rapid user input.

## Basic Usage

Add the `Debounce` mixin to your action class:

```dart
class SearchText extends AppAction with Debounce {
  final String searchTerm;
  SearchText(this.searchTerm);

  Future<AppState?> reduce() async {
    var response = await http.get(
      Uri.parse('https://example.com/?q=${Uri.encodeComponent(searchTerm)}')
    );
    return state.copy(searchResult: response.body);
  }
}
```

When the user types quickly, each keystroke dispatches `SearchText`. The mixin delays execution, and each new dispatch resets the timer. The API call only happens once the user stops typing for the debounce period.

## Setting the Debounce Duration

The default debounce period is **333 milliseconds**. Override the `debounce` getter to customize:

```dart
class SearchText extends AppAction with Debounce {
  final String searchTerm;
  SearchText(this.searchTerm);

  // Wait 1 second of inactivity before executing
  int get debounce => 1000;

  Future<AppState?> reduce() async {
    var response = await http.get(
      Uri.parse('https://example.com/?q=${Uri.encodeComponent(searchTerm)}')
    );
    return state.copy(searchResult: response.body);
  }
}
```

## Custom Lock Builder

By default, all instances of a debounced action share the same lock. Override `lockBuilder()` to create independent debounce periods for different action instances:

```dart
class SearchField extends AppAction with Debounce {
  final String fieldId;
  final String searchTerm;
  SearchField(this.fieldId, this.searchTerm);

  // Each fieldId gets its own independent debounce timer
  Object? lockBuilder() => fieldId;

  Future<AppState?> reduce() async {
    // Search logic here
  }
}
```

This enables multiple search fields to operate independently, each with their own debounce timer.

## Debounce vs Throttle

These two mixins serve different purposes:

| Mixin | Behavior | Best For |
|-------|----------|----------|
| **Throttle** | Runs immediately on first dispatch, then blocks subsequent dispatches for the period | Rate-limiting actions that should execute right away (e.g., refresh button) |
| **Debounce** | Waits for quiet time, only runs after dispatches stop | Waiting for user to finish input (e.g., search-as-you-type) |

**Throttle**: "Execute now, then wait before allowing again"
**Debounce**: "Wait until activity stops, then execute"

## Mixin Compatibility

Debounce **can** be combined with:
- `CheckInternet`
- `NoDialog`
- `AbortWhenNoInternet`
- `NonReentrant`
- `Fresh`
- `Throttle`

Debounce **cannot** be combined with:
- `Retry`
- `UnlimitedRetries`
- `UnlimitedRetryCheckInternet`
- `OptimisticCommand`
- `OptimisticSync`
- `OptimisticSyncWithPush`
- `ServerPush`

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/control-mixins
- https://asyncredux.com/flutter/advanced-actions/control-mixins#debounce
- https://asyncredux.com/flutter/advanced-actions/control-mixins#throttle
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/basics/async-actions
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/basics/events
- https://asyncredux.com/flutter/advanced-actions/action-mixins#compatibility


================================================
FILE: .claude/skills/asyncredux-debugging/SKILL.md
================================================
---
name: asyncredux-debugging
description: Debug AsyncRedux applications effectively. Covers printing state with store.state, checking actionsInProgress(), using ConsoleActionObserver, StateObserver for state change tracking, and tracking dispatchCount/reduceCount.
---

# Debugging AsyncRedux Applications

AsyncRedux provides several tools for debugging and monitoring your application's state, actions, and behavior during development.

## Inspecting Store State

Access the current state directly from the store:

```dart
// Direct state access
print(store.state);

// Access specific parts
print(store.state.user.name);
print(store.state.cart.items);
```

## Tracking Actions in Progress

Use `actionsInProgress()` to see which actions are currently being processed:

```dart
// Returns an unmodifiable Set of actions currently running
Set<ReduxAction<AppState>> inProgress = store.actionsInProgress();

// Check if any actions are running
if (inProgress.isEmpty) {
  print('No actions in progress');
} else {
  for (var action in inProgress) {
    print('Running: ${action.runtimeType}');
  }
}

// Get a copy of actions in progress
Set<ReduxAction<AppState>> copy = store.copyActionsInProgress();

// Check if specific actions match
bool matches = store.actionsInProgressEqualTo(expectedSet);
```

## Dispatch and Reduce Counts

Track how many actions have been dispatched and how many state reductions have occurred:

```dart
// Total actions dispatched since store creation
print('Dispatch count: ${store.dispatchCount}');

// Total state reductions performed
print('Reduce count: ${store.reduceCount}');
```

These counters are useful for:
- Verifying actions dispatched during tests
- Detecting unexpected dispatches
- Performance monitoring

## Console Action Observer

The built-in `ConsoleActionObserver` prints dispatched actions to the console with color formatting:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  // Only enable in debug mode
  actionObservers: kReleaseMode ? null : [ConsoleActionObserver()],
);
```

Console output example:
```
I/flutter (15304): | Action MyAction
I/flutter (15304): | Action LoadUserAction(user32)
```

Actions appear in yellow (default) or green (for `WaitAction` and `NavigateAction`).

### Customizing Action Output

Override `toString()` in your actions to display additional information:

```dart
class LoginAction extends AppAction {
  final String username;
  LoginAction(this.username);

  @override
  Future<AppState?> reduce() async {
    // ...
  }

  @override
  String toString() => 'LoginAction(username: $username)';
}
```

### Custom Color Scheme

Customize the color scheme by modifying the static `color` callback:

```dart
ConsoleActionObserver.color = (action) {
  if (action is ErrorAction) return ConsoleActionObserver.red;
  if (action is NetworkAction) return ConsoleActionObserver.blue;
  return ConsoleActionObserver.yellow;
};
```

Available colors: `white`, `red`, `blue`, `yellow`, `green`, `grey`, `dark`.

## StateObserver for State Change Logging

Create a `StateObserver` to log state changes:

```dart
class DebugStateObserver implements StateObserver<AppState> {
  @override
  void observe(
    ReduxAction<AppState> action,
    AppState prevState,
    AppState newState,
    Object? error,
    int dispatchCount,
  ) {
    final changed = !identical(prevState, newState);

    print('--- Action #$dispatchCount: ${action.runtimeType} ---');
    print('State changed: $changed');

    if (changed) {
      // Log specific state changes
      if (prevState.user != newState.user) {
        print('  User changed: ${prevState.user} -> ${newState.user}');
      }
      if (prevState.counter != newState.counter) {
        print('  Counter changed: ${prevState.counter} -> ${newState.counter}');
      }
    }

    if (error != null) {
      print('  Error: $error');
    }
  }
}

// Configure store
var store = Store<AppState>(
  initialState: AppState.initialState(),
  stateObservers: kDebugMode ? [DebugStateObserver()] : null,
);
```

### Detecting State Changes

Use `identical()` to check if state actually changed:

```dart
bool stateChanged = !identical(prevState, newState);
```

This is efficient because AsyncRedux uses immutable state - if the reference is the same, no change occurred.

## Custom ActionObserver for Detailed Logging

Create an `ActionObserver` for detailed dispatch tracking:

```dart
class DetailedActionObserver implements ActionObserver<AppState> {
  final Map<ReduxAction, DateTime> _startTimes = {};

  @override
  void observe(
    ReduxAction<AppState> action,
    int dispatchCount, {
    required bool ini,
  }) {
    if (ini) {
      // Action started
      _startTimes[action] = DateTime.now();
      print('[START #$dispatchCount] ${action.runtimeType}');
    } else {
      // Action finished
      final startTime = _startTimes.remove(action);
      if (startTime != null) {
        final duration = DateTime.now().difference(startTime);
        print('[END #$dispatchCount] ${action.runtimeType} (${duration.inMilliseconds}ms)');
      } else {
        print('[END #$dispatchCount] ${action.runtimeType}');
      }
    }
  }
}
```

## Debugging Widget Rebuilds

Use `ModelObserver` with `DefaultModelObserver` to track which widgets rebuild:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  modelObserver: DefaultModelObserver(),
);
```

Output format:
```
Model D:1 R:1 = Rebuild:true, Connector:MyWidgetConnector, Model:MyViewModel{data}.
Model D:2 R:2 = Rebuild:false, Connector:MyWidgetConnector, Model:MyViewModel{data}.
```

- `D`: Dispatch count
- `R`: Rebuild count
- `Rebuild`: Whether widget actually rebuilt
- `Connector`: The StoreConnector type
- `Model`: ViewModel with state summary

Enable detailed output by passing `debug: this` to StoreConnector:

```dart
StoreConnector<AppState, MyViewModel>(
  debug: this, // Enables connector name in output
  converter: (store) => MyViewModel.fromStore(store),
  builder: (context, vm) => MyWidget(vm),
)
```

## Checking Action Status in Widgets

Use context extensions to check action states:

```dart
Widget build(BuildContext context) {
  // Check if action is currently running
  if (context.isWaiting(LoadDataAction)) {
    return CircularProgressIndicator();
  }

  // Check if action failed
  if (context.isFailed(LoadDataAction)) {
    var exception = context.exceptionFor(LoadDataAction);
    return Text('Error: ${exception?.message}');
  }

  return Text('Data: ${context.state.data}');
}
```

## Waiting for Conditions in Tests

Use store wait methods for test debugging:

```dart
// Wait until state meets a condition
await store.waitCondition((state) => state.isLoaded);

// Wait for specific action types to complete
await store.waitAllActionTypes([LoadUserAction, LoadSettingsAction]);

// Wait for all actions to complete (empty list = wait for all)
await store.waitAllActions([]);

// Wait for action condition with access to actions in progress
await store.waitActionCondition((actionsInProgress, triggerAction) {
  return actionsInProgress.isEmpty;
});
```

## Complete Debug Setup Example

```dart
void main() {
  final store = Store<AppState>(
    initialState: AppState.initialState(),
    // Action logging (debug only)
    actionObservers: kDebugMode
        ? [ConsoleActionObserver(), DetailedActionObserver()]
        : null,
    // State change logging (debug only)
    stateObservers: kDebugMode
        ? [DebugStateObserver()]
        : null,
    // Widget rebuild tracking (debug only)
    modelObserver: kDebugMode ? DefaultModelObserver() : null,
    // Error observer (always enabled)
    errorObserver: MyErrorObserver(),
  );

  // Debug print initial state
  if (kDebugMode) {
    print('Initial state: ${store.state}');
    print('Dispatch count: ${store.dispatchCount}');
  }

  runApp(StoreProvider<AppState>(
    store: store,
    child: MyApp(),
  ));
}
```

## Debugging Tips

1. **Print state in actions**: Use `print(state)` in your reducer to see state at that moment
2. **Check initialState**: Access `action.initialState` to see state when action was dispatched (vs current `state`)
3. **Use action status**: Check `action.status.isCompletedOk` or `action.status.originalError` after dispatch
4. **Conditional logging**: Use `kDebugMode` from `package:flutter/foundation.dart` to disable in production
5. **Override toString**: Implement `toString()` on actions and state classes for better debug output

## References

URLs from the documentation:
- https://asyncredux.com/flutter/miscellaneous/logging
- https://asyncredux.com/flutter/miscellaneous/metrics
- https://asyncredux.com/flutter/miscellaneous/observing-rebuilds
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/wait-fail-succeed
- https://asyncredux.com/flutter/advanced-actions/action-status
- https://asyncredux.com/flutter/testing/dispatch-wait-and-expect


================================================
FILE: .claude/skills/asyncredux-dependency-injection/SKILL.md
================================================
---
name: asyncredux-dependency-injection
description: Inject dependencies into actions using the environment, dependencies, and configuration pattern. Covers creating an Environment enum, a Dependencies class, passing them to the Store, accessing them from actions and widgets, and using dependency injection for testability.
---

# Dependency Injection with Environment, Dependencies, and Configuration

AsyncRedux provides dependency injection through three Store parameters:

- **`environment`**: Specifies if the app is running in production, staging, development, testing, etc. Should be immutable and not change during app execution. Accessible from both actions and widgets.
- **`dependencies`**: A container for injected services (repositories, APIs, etc.), created via a factory that receives the `Store`, so it can vary based on the environment. Usually not accessible from widgets.
- **`configuration`**: For feature flags and other configuration values. Accessible from both actions and widgets.

## Step 1: Define the Environment

Create an enum (or class) specifying the app's running context:

```dart
enum Environment {
  production,
  staging,
  testing;

  bool get isProduction => this == Environment.production;
  bool get isStaging => this == Environment.staging;
  bool get isTesting => this == Environment.testing;
}
```

## Step 2: Define the Dependencies

Create an abstract class with a factory that returns different implementations based on the environment:

```dart
abstract class Dependencies {
  factory Dependencies(Store store) {
    if (store.environment == Environment.production) {
      return DependenciesProduction();
    } else if (store.environment == Environment.staging) {
      return DependenciesStaging();
    } else {
      return DependenciesTesting();
    }
  }

  ApiClient get apiClient;
  AuthService get authService;
  int limit(int value);
}

class DependenciesProduction implements Dependencies {
  @override
  ApiClient get apiClient => RealApiClient();

  @override
  AuthService get authService => FirebaseAuthService();

  @override
  int limit(int value) => min(value, 5);
}

class DependenciesTesting implements Dependencies {
  @override
  ApiClient get apiClient => MockApiClient();

  @override
  AuthService get authService => MockAuthService();

  @override
  int limit(int value) => min(value, 1000); // Higher limit in tests
}
```

## Step 3: Define the Configuration (optional)

```dart
class Config {
  bool isABtestingOn = false;
  bool showAdminConsole = false;
}
```

## Step 4: Pass All Three to the Store

When creating the store, pass the environment, dependencies factory, and configuration factory:

```dart
void main() {
  var store = Store<AppState>(
    initialState: AppState.initialState(),
    environment: Environment.production,
    dependencies: (store) => Dependencies(store),
    configuration: (store) => Config(),
  );

  runApp(
    StoreProvider<AppState>(
      store: store,
      child: MyApp(),
    ),
  );
}
```

The `dependencies` and `configuration` parameters are factories that receive the `Store`, so they can read `store.environment` to vary their behavior.

## Step 5: Access from Actions via a Base Action Class

Define a base action class with typed getters for `dependencies`, `environment`, and `configuration`:

```dart
abstract class Action extends ReduxAction<AppState> {
  Dependencies get dependencies => super.store.dependencies as Dependencies;
  Environment get environment => super.store.environment as Environment;
  Config get config => super.store.configuration as Config;
}
```

Now use them in your actions:

```dart
class FetchUserAction extends Action {
  final String userId;
  FetchUserAction(this.userId);

  @override
  Future<AppState?> reduce() async {
    final user = await dependencies.apiClient.fetchUser(userId);
    return state.copy(user: user);
  }
}

class IncrementAction extends Action {
  final int amount;
  IncrementAction({required this.amount});

  @override
  AppState reduce() {
    int newState = state.counter + amount;
    int limitedState = dependencies.limit(newState);
    return state.copy(counter: limitedState);
  }
}
```

## Step 6: Access from Widgets via BuildContext Extension

Create a `BuildContext` extension. The `environment` and `configuration` are available via `getEnvironment` and `getConfiguration`. Note: `dependencies` should usually NOT be accessed from widgets.

```dart
extension BuildContextExtension on BuildContext {
  AppState get state => getState<AppState>();

  R select<R>(R Function(AppState state) selector) =>
      getSelect<AppState, R>(selector);

  /// Access the environment from widgets (does not trigger rebuilds).
  Environment get environment => getEnvironment<AppState>() as Environment;

  /// Access the configuration from widgets (does not trigger rebuilds).
  Config get config => getConfiguration<AppState>() as Config;
}
```

Use in widgets:

```dart
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final env = context.environment;
    int counter = context.state;

    return Scaffold(
      appBar: AppBar(title: const Text('Dependency Injection Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Use the environment to change the UI.
            Text('Running in ${env}.', textAlign: TextAlign.center),
            Text('$counter', style: const TextStyle(fontSize: 30)),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => dispatch(IncrementAction(amount: 1)),
        child: const Icon(Icons.add),
      ),
    );
  }
}
```

## Step 7 (if using StoreConnector): Access from VmFactory

If you use `StoreConnector`, extend `VmFactory` with typed getters:

```dart
abstract class AppFactory<T extends Widget?, Model extends Vm>
    extends VmFactory<AppState, T, Model> {
  AppFactory([T? connector]) : super(connector);

  Dependencies get dependencies => store.dependencies as Dependencies;
  Environment get environment => store.environment as Environment;
  Config get config => store.configuration as Config;
}
```

## Testing with Different Environments

The pattern makes testing straightforward by injecting test implementations:

```dart
void main() {
  group('IncrementAction', () {
    test('increments counter with test dependencies', () async {
      var store = Store<AppState>(
        initialState: AppState(counter: 0),
        environment: Environment.testing,
        dependencies: (store) => Dependencies(store), // Returns DependenciesTesting
      );

      await store.dispatchAndWait(IncrementAction(amount: 5));

      // DependenciesTesting has limit of 1000, so value is 5
      expect(store.state.counter, 5);
    });

    test('production dependencies limit counter', () async {
      var store = Store<AppState>(
        initialState: AppState(counter: 3),
        environment: Environment.production,
        dependencies: (store) => Dependencies(store), // Returns DependenciesProduction
      );

      await store.dispatchAndWait(IncrementAction(amount: 10));

      // DependenciesProduction limits to 5
      expect(store.state.counter, 5);
    });
  });
}
```

## Complete Working Example

```dart
import 'dart:math';
import 'package:async_redux/async_redux.dart';
import 'package:flutter/material.dart';

late Store<int> store;

void main() {
  store = Store<int>(
    initialState: 0,
    environment: Environment.production,
    dependencies: (store) => Dependencies(store),
  );
  runApp(MyApp());
}

enum Environment {
  production,
  staging,
  testing;

  bool get isProduction => this == Environment.production;
  bool get isStaging => this == Environment.staging;
  bool get isTesting => this == Environment.testing;
}

abstract class Dependencies {
  factory Dependencies(Store store) {
    if (store.environment == Environment.production) {
      return DependenciesProduction();
    } else if (store.environment == Environment.staging) {
      return DependenciesStaging();
    } else {
      return DependenciesTesting();
    }
  }

  int limit(int value);
}

class DependenciesProduction implements Dependencies {
  @override
  int limit(int value) => min(value, 5);
}

class DependenciesStaging implements Dependencies {
  @override
  int limit(int value) => min(value, 25);
}

class DependenciesTesting implements Dependencies {
  @override
  int limit(int value) => min(value, 1000);
}

abstract class Action extends ReduxAction<int> {
  Dependencies get dependencies => super.store.dependencies as Dependencies;
}

class IncrementAction extends Action {
  final int amount;
  IncrementAction({required this.amount});

  @override
  int reduce() {
    int newState = state + amount;
    int limitedState = dependencies.limit(newState);
    return limitedState;
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreProvider<int>(
      store: store,
      child: MaterialApp(home: MyHomePage()),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final env = context.environment;
    int counter = context.state;

    return Scaffold(
      appBar: AppBar(title: const Text('Dependency Injection Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Running in ${env}.', textAlign: TextAlign.center),
            const Text(
              'You have pushed the button this many times:\n'
              '(limited by the environment)',
              textAlign: TextAlign.center,
            ),
            Text('$counter', style: const TextStyle(fontSize: 30)),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => dispatch(IncrementAction(amount: 1)),
        child: const Icon(Icons.add),
      ),
    );
  }
}

extension BuildContextExtension on BuildContext {
  int get state => getState<int>();
  int read() => getRead<int>();
  R select<R>(R Function(int state) selector) => getSelect<int, R>(selector);
  R? event<R>(Evt<R> Function(int state) selector) => getEvent<int, R>(selector);
  Environment get environment => getEnvironment<int>() as Environment;
}
```

## Key Benefits

- **Separation of concerns**: `environment` identifies the running context, `dependencies` provides services, `configuration` holds feature flags
- **Testability**: Swap implementations by changing the environment, without changing action code
- **Type safety**: Typed getters in base action class provide compile-time checking
- **Factory pattern**: The `dependencies` and `configuration` factories receive the `Store`, allowing them to vary based on `environment`
- **Scoped dependencies**: Each store instance has its own environment/dependencies/configuration, preventing test contamination

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/miscellaneous/dependency-injection
- https://asyncredux.com/flutter/testing/mocking
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/connector/store-connector
- https://asyncredux.com/flutter/testing/store-tester
- https://asyncredux.com/flutter/testing/dispatch-wait-and-expect
- https://github.com/marcglasberg/async_redux/blob/master/example/lib/main_dependency_injection.dart


================================================
FILE: .claude/skills/asyncredux-dispatching-actions/SKILL.md
================================================
---
name: asyncredux-dispatching-actions
description: Dispatch actions using all available methods: `dispatch()`, `dispatchAndWait()`, `dispatchAll()`, `dispatchAndWaitAll()`, and `dispatchSync()`. Covers dispatching from widgets via context extensions and from within other actions.
---

# Dispatching Actions

The foundational principle of AsyncRedux: **the only way to change the application state is by dispatching actions.** You can dispatch from widgets (via context extensions) or from within other actions.

## Five Dispatch Methods

### 1. dispatch()

The standard method that returns immediately. For synchronous actions, state updates before return; for async actions, the process begins and completes later.

```dart
dispatch(MyAction());
```

### 2. dispatchAndWait()

Returns a `Future` that completes when the action finishes and state changes, regardless of whether the action is sync or async. Returns an `ActionStatus` object.

```dart
var status = await dispatchAndWait(MyAction());
if (status.isCompletedOk) {
  Navigator.pop(context);
}
```

### 3. dispatchAll()

Dispatches multiple actions in parallel, returning the list of dispatched actions.

```dart
dispatchAll([BuyAction('IBM'), SellAction('TSLA')]);
```

### 4. dispatchAndWaitAll()

Dispatches actions in parallel and waits for all to complete.

```dart
await dispatchAndWaitAll([
  BuyAction('IBM'),
  SellAction('TSLA'),
]);
```

### 5. dispatchSync()

Like `dispatch()` but throws a `StoreException` if the action is asynchronous. Use when synchronous execution is mandatory.

```dart
dispatchSync(MyAction());
```

## Dispatching from Widgets

All dispatch methods are available as `BuildContext` extensions:

```dart
context.dispatch(Action());
context.dispatchAll([Action1(), Action2()]);
await context.dispatchAndWait(Action());
await context.dispatchAndWaitAll([Action1(), Action2()]);
context.dispatchSync(Action());
```

Example button implementation:

```dart
ElevatedButton(
  onPressed: () => context.dispatch(Increment()),
  child: Text('Increment'),
)
```

For async dispatch in callbacks:

```dart
ElevatedButton(
  onPressed: () async {
    var status = await context.dispatchAndWait(SaveAction());
    if (status.isCompletedOk) {
      Navigator.pop(context);
    }
  },
  child: Text('Save'),
)
```

## Dispatching from Within Actions

All dispatch methods are available inside actions via the `ReduxAction` base class:

```dart
class MyAction extends ReduxAction<AppState> {
  Future<AppState?> reduce() async {
    // Dispatch another action and wait for it
    await dispatchAndWait(LoadDataAction());

    // Dispatch without waiting
    dispatch(LogAction('Data loaded'));

    return state.copy(loaded: true);
  }
}
```

### Dispatching in before() and after()

You can dispatch actions in the `before()` and `after()` lifecycle methods:

```dart
class MyAction extends ReduxAction<AppState> {
  Future<AppState?> reduce() async {
    String description = await fetchData();
    return state.copy(description: description);
  }

  void before() => dispatch(BarrierAction(true));
  void after() => dispatch(BarrierAction(false));
}
```

## ActionStatus

The `dispatchAndWait()` method returns an `ActionStatus` object with useful properties:

```dart
var status = await dispatchAndWait(MyAction());

// Check completion state
status.isCompleted;       // Action finished executing
status.isCompletedOk;     // Completed without errors
status.isCompletedFailed; // Completed with errors

// Access error information
status.originalError;     // Error thrown by before/reduce
status.wrappedError;      // Error after wrapError() processing

// Check method completion
status.hasFinishedMethodBefore;
status.hasFinishedMethodReduce;
status.hasFinishedMethodAfter;
```

You can also access status directly from the action instance:

```dart
var action = MyAction();
await dispatchAndWait(action);
print(action.status.isCompletedOk);
```

## The notify Parameter

Dispatch methods accept an optional `notify` parameter (default `true`) that controls whether widgets rebuild on state changes:

```dart
// Dispatch without triggering widget rebuilds
dispatch(MyAction(), notify: false);
```

## Summary Table

| Method | Returns | Waits? | Use Case |
|--------|---------|--------|----------|
| `dispatch()` | `void` | No | Fire and forget |
| `dispatchAndWait()` | `Future<ActionStatus>` | Yes | Need to know when done |
| `dispatchAll()` | `List<ReduxAction>` | No | Multiple parallel actions |
| `dispatchAndWaitAll()` | `Future<void>` | Yes | Wait for all parallel actions |
| `dispatchSync()` | `void` | N/A | Enforce sync execution |

## References

URLs from the documentation:
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/basics/sync-actions
- https://asyncredux.com/flutter/basics/async-actions
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/advanced-actions/action-status
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/testing/dispatch-wait-and-expect
- https://asyncredux.com/flutter/miscellaneous/advanced-waiting


================================================
FILE: .claude/skills/asyncredux-error-handling/SKILL.md
================================================
---
name: asyncredux-error-handling
description: Implement comprehensive error handling for actions. Covers the `wrapError()` method for action-level error wrapping, GlobalWrapError for app-wide error transformation, ErrorObserver for logging/monitoring, and the error handling flow (before → reduce → after).
---

# Error Handling in AsyncRedux

AsyncRedux provides a comprehensive error handling system with multiple layers: action-level wrapping, global error transformation, and error observation for logging/monitoring.

## Error Flow and Action Lifecycle

When errors occur during action execution:

1. If `before()` throws an error, the reducer doesn't execute and state remains unchanged
2. If `reduce()` throws an error, execution halts without state modification
3. The `after()` method **always** runs, even when errors occur (like a `finally` block)

**Processing order:** `wrapError()` → `GlobalWrapError` → `ErrorObserver`

## Throwing Errors from Actions

Actions can throw errors using `throw`. When an error is thrown, the reducer stops and state is not modified:

```dart
class TransferMoney extends AppAction {
  final double amount;
  TransferMoney(this.amount);

  AppState? reduce() {
    if (amount == 0) {
      throw UserException('You cannot transfer zero money.');
    }
    return state.copy(cash: state.cash - amount);
  }
}
```

## UserException for User-Facing Errors

`UserException` is a built-in class for errors that users can understand and potentially fix (not code bugs):

```dart
class SaveUser extends AppAction {
  final String name;
  SaveUser(this.name);

  Future<AppState?> reduce() async {
    if (name.length < 4)
      throw UserException('Name must have 4 letters.');

    await saveUser(name);
    return null;
  }
}
```

When a `UserException` is thrown, it's added to a special error queue in the store and can be displayed via `UserExceptionDialog`.

### Displaying UserExceptions

Wrap your home page with `UserExceptionDialog` below both `StoreProvider` and `MaterialApp`:

```dart
UserExceptionDialog<AppState>(
  onShowUserExceptionDialog: (context, exception) => showDialog(...),
  child: MyHomePage(),
)
```

## Action-Level Error Wrapping with wrapError()

The `wrapError()` method acts as a catch block for entire actions. It receives the original error and stack trace, and must return:
- A modified error (to transform the error)
- `null` (to suppress/disable the error)
- The unchanged error (to pass it through)

```dart
class LogoutAction extends AppAction {
  @override
  Object? wrapError(Object error, StackTrace stackTrace) {
    return LogoutError("Logout failed", cause: error);
  }

  Future<AppState?> reduce() async {
    await authService.logout();
    return state.copy(user: null);
  }
}
```

### Mixin Pattern for Reusable Error Handling

Create mixins for consistent error transformation across multiple actions:

```dart
mixin ShowUserException on AppAction {
  String getErrorMessage();

  @override
  Object? wrapError(Object error, StackTrace stackTrace) {
    return UserException(getErrorMessage()).addCause(error);
  }
}

class LoadDataAction extends AppAction with ShowUserException {
  @override
  String getErrorMessage() => 'Failed to load data. Please try again.';

  Future<AppState?> reduce() async {
    var data = await api.loadData();
    return state.copy(data: data);
  }
}
```

### Suppressing Errors

Return `null` from `wrapError()` to suppress errors without further propagation:

```dart
@override
Object? wrapError(Object error, StackTrace stackTrace) {
  if (error is CancelledException) {
    return null; // Silently ignore cancellation
  }
  return error;
}
```

## Global Error Handling with GlobalWrapError

`GlobalWrapError` processes all action errors centrally. This is useful for transforming third-party library errors (like Firebase or platform exceptions):

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  globalWrapError: MyGlobalWrapError(),
);

class MyGlobalWrapError extends GlobalWrapError {
  @override
  Object? wrap(Object error, StackTrace stackTrace, ReduxAction<AppState> action) {
    // Transform platform exceptions to user-friendly messages
    if (error is PlatformException && error.code == "Error performing get") {
      return UserException('Check your internet connection').addCause(error);
    }

    // Transform Firebase errors
    if (error is FirebaseException) {
      return UserException('Service temporarily unavailable').addCause(error);
    }

    // Pass through all other errors unchanged
    return error;
  }
}
```

Return `null` from `GlobalWrapError.wrap()` to suppress errors globally.

## Error Observation with ErrorObserver

`ErrorObserver` receives all errors with context about the action and store. Use it for logging, monitoring, or analytics:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  errorObserver: MyErrorObserver<AppState>(),
);

class MyErrorObserver<St> implements ErrorObserver<St> {
  @override
  bool observe(
    Object error,
    StackTrace stackTrace,
    ReduxAction<St> action,
    Store<St> store,
  ) {
    // Log the error
    print("Error during ${action.runtimeType}: $error");

    // Send to crash reporting service
    crashlytics.recordError(error, stackTrace);

    // Return true to rethrow, false to swallow
    return true;
  }
}
```

The `observe` method returns:
- `true` to rethrow the error (default behavior)
- `false` to swallow the error silently

## UserExceptionAction for Mid-Action Errors

For showing error feedback while allowing the action to continue (without stopping execution):

```dart
class ConvertAction extends AppAction {
  final String text;
  ConvertAction(this.text);

  Future<AppState?> reduce() async {
    var value = int.tryParse(text);
    if (value == null) {
      // Show error but continue action
      dispatch(UserExceptionAction('Please enter a valid number'));
      return null; // No state change
    }
    return state.copy(counter: value);
  }
}
```

## Checking Action Failure Status

### Using ActionStatus

After dispatching with `dispatchAndWait()`, check the status:

```dart
var status = await store.dispatchAndWait(SaveAction());

if (status.isCompletedOk) {
  Navigator.pop(context);
} else if (status.isCompletedFailed) {
  var error = status.wrappedError;
  print('Save failed: $error');
}
```

**ActionStatus properties:**
- `isCompletedOk`: Action finished without errors
- `isCompletedFailed`: Action encountered errors
- `originalError`: The error as thrown from `before` or `reduce`
- `wrappedError`: The error after transformation by `wrapError()`

### Using isFailed in Widgets

Check action failure state in the UI:

```dart
Widget build(BuildContext context) {
  if (context.isFailed(LoadDataAction)) {
    var exception = context.exceptionFor(LoadDataAction);
    return Column(
      children: [
        Text('Error: ${exception?.message}'),
        ElevatedButton(
          onPressed: () => context.dispatch(LoadDataAction()),
          child: Text('Retry'),
        ),
      ],
    );
  }

  if (context.isWaiting(LoadDataAction)) {
    return CircularProgressIndicator();
  }

  return DataWidget(data: context.state.data);
}
```

The error is cleared automatically when the action is dispatched again.

To manually clear the error:
```dart
context.clearExceptionFor(LoadDataAction);
```

## Testing Error Handling

Test that actions fail with expected errors:

```dart
test('action throws UserException for invalid input', () async {
  var store = Store<AppState>(initialState: AppState.initialState());

  var status = await store.dispatchAndWait(SaveUser('abc')); // too short

  expect(status.isCompletedFailed, isTrue);
  var error = status.wrappedError;
  expect(error, isA<UserException>());
  expect((error as UserException).msg, 'Name must have 4 letters.');
});
```

Test multiple exceptions via the error queue:

```dart
test('multiple actions accumulate errors', () async {
  var store = Store<AppState>(initialState: AppState.initialState());

  await store.dispatchAndWaitAll([
    InvalidAction1(),
    InvalidAction2(),
    InvalidAction3(),
  ]);

  var errors = store.errors;
  expect(errors.length, 3);
  expect(errors[0].msg, 'First error message');
});
```

## Complete Store Setup with Error Handling

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  globalWrapError: MyGlobalWrapError(),
  errorObserver: MyErrorObserver<AppState>(),
  actionObservers: [Log.printer(formatter: Log.verySimpleFormatter)],
);

class MyGlobalWrapError extends GlobalWrapError {
  @override
  Object? wrap(Object error, StackTrace stackTrace, ReduxAction<AppState> action) {
    if (error is SocketException) {
      return UserException('No internet connection').addCause(error);
    }
    return error;
  }
}

class MyErrorObserver<St> implements ErrorObserver<St> {
  @override
  bool observe(Object error, StackTrace stackTrace, ReduxAction<St> action, Store<St> store) {
    // Skip logging UserExceptions (they're expected)
    if (error is! UserException) {
      crashlytics.recordError(error, stackTrace);
    }
    return true;
  }
}
```

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/wrapping-the-reducer
- https://asyncredux.com/flutter/basics/failed-actions
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/testing/testing-user-exceptions
- https://asyncredux.com/flutter/basics/wait-fail-succeed
- https://asyncredux.com/flutter/miscellaneous/logging
- https://asyncredux.com/flutter/advanced-actions/action-status


================================================
FILE: .claude/skills/asyncredux-events/SKILL.md
================================================
---
name: asyncredux-events
description: Use the Event class to interact with Flutter's stateful widgets (TextField, ListView, etc.). Covers creating Event objects in state, consuming events with `context.event()`, scrolling lists, changing text fields, and the event lifecycle.
---

# Events in AsyncRedux

Events are **single-use notifications** used to trigger side effects in widgets. They're designed for controlling native Flutter widgets like `TextField` and `ListView` that manage their own state through controllers.

## When to Use Events

Use events for:
- **Controller actions**: Clearing text, changing text, scrolling lists, focusing inputs
- **One-off UI actions**: Showing dialogs, snackbars, triggering animations
- **Implicit state changes**: Navigation, any action that should happen exactly once

Do NOT use events for:
- Values that need to be read multiple times (use regular state instead)
- Data that should be persisted (events should never be saved to local storage)

## Setup: Add context.event() Extension

Add the `event` method to your BuildContext extension:

```dart
extension BuildContextExtension on BuildContext {
  AppState get state => getState<AppState>();

  R select<R>(R Function(AppState state) selector) =>
    getSelect<AppState, R>(selector);

  // Add this for events:
  R? event<R>(Evt<R> Function(AppState state) selector) =>
    getEvent<AppState, R>(selector);
}
```

## Creating Events

### Boolean Events

For simple triggers that don't carry data:

```dart
// Create an unspent event (will return true once)
var clearTextEvt = Evt();

// Create a spent event (will return false)
var clearTextEvt = Evt.spent();
```

### Typed Events

For events that carry a value:

```dart
// Create an unspent event with a value (will return value once, then null)
var changeTextEvt = Evt<String>("New text");
var scrollToIndexEvt = Evt<int>(42);

// Create a spent event (will return null)
var changeTextEvt = Evt<String>.spent();
```

## Declaring Events in State

Initialize all events as **spent** in your initial state:

```dart
class AppState {
  final Evt clearTextEvt;
  final Evt<String> changeTextEvt;
  final Evt<int> scrollToIndexEvt;

  AppState({
    required this.clearTextEvt,
    required this.changeTextEvt,
    required this.scrollToIndexEvt,
  });

  static AppState initialState() => AppState(
    clearTextEvt: Evt.spent(),
    changeTextEvt: Evt<String>.spent(),
    scrollToIndexEvt: Evt<int>.spent(),
  );

  AppState copy({
    Evt? clearTextEvt,
    Evt<String>? changeTextEvt,
    Evt<int>? scrollToIndexEvt,
  }) => AppState(
    clearTextEvt: clearTextEvt ?? this.clearTextEvt,
    changeTextEvt: changeTextEvt ?? this.changeTextEvt,
    scrollToIndexEvt: scrollToIndexEvt ?? this.scrollToIndexEvt,
  );
}
```

## Dispatching Events from Actions

Actions create **unspent** events and place them in state:

```dart
// Boolean event - triggers clearing the text field
class ClearTextAction extends AppAction {
  AppState reduce() => state.copy(clearTextEvt: Evt());
}

// Typed event - changes the text field to a new value
class ChangeTextAction extends AppAction {
  final String newText;
  ChangeTextAction(this.newText);

  AppState reduce() => state.copy(changeTextEvt: Evt<String>(newText));
}

// Typed event from async operation
class FetchAndSetTextAction extends AppAction {
  Future<AppState> reduce() async {
    String text = await api.fetchText();
    return state.copy(changeTextEvt: Evt<String>(text));
  }
}

// Scroll to a specific index in a ListView
class ScrollToItemAction extends AppAction {
  final int index;
  ScrollToItemAction(this.index);

  AppState reduce() => state.copy(scrollToIndexEvt: Evt<int>(index));
}
```

## Consuming Events in Widgets

Use `context.event()` in the widget's build method. **The event is consumed (marked as spent) immediately when read.**

### TextField Example

```dart
class MyTextField extends StatefulWidget {
  @override
  State<MyTextField> createState() => _MyTextFieldState();
}

class _MyTextFieldState extends State<MyTextField> {
  final controller = TextEditingController();

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Consume the clear event - returns true once, then false
    bool shouldClear = context.event((s) => s.clearTextEvt);
    if (shouldClear) {
      controller.clear();
    }

    // Consume the change event - returns the value once, then null
    String? newText = context.event((s) => s.changeTextEvt);
    if (newText != null) {
      controller.text = newText;
    }

    return TextField(controller: controller);
  }
}
```

### ListView Scrolling Example

```dart
class MyListView extends StatefulWidget {
  @override
  State<MyListView> createState() => _MyListViewState();
}

class _MyListViewState extends State<MyListView> {
  final scrollController = ScrollController();
  final itemHeight = 50.0;

  @override
  void dispose() {
    scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final items = context.select((s) => s.items);

    // Consume the scroll event
    int? scrollToIndex = context.event((s) => s.scrollToIndexEvt);
    if (scrollToIndex != null) {
      // Schedule the scroll after the frame is built
      WidgetsBinding.instance.addPostFrameCallback((_) {
        scrollController.animateTo(
          scrollToIndex * itemHeight,
          duration: Duration(milliseconds: 300),
          curve: Curves.easeOut,
        );
      });
    }

    return ListView.builder(
      controller: scrollController,
      itemCount: items.length,
      itemBuilder: (context, index) => SizedBox(
        height: itemHeight,
        child: Text(items[index]),
      ),
    );
  }
}
```

## Event Lifecycle

1. **Created as spent**: Events start as `Evt.spent()` in initial state
2. **Dispatched as unspent**: Action creates `Evt()` or `Evt<T>(value)` and puts it in state
3. **Widget rebuilds**: State change triggers widget rebuild
4. **Consumed once**: `context.event()` returns the value and marks the event as spent
5. **Returns null/false**: Subsequent reads return `null` (typed) or `false` (boolean)

## Important Rules

### Each Event Can Only Be Consumed by One Widget

If multiple widgets need the same trigger, create separate events:

```dart
class AppState {
  final Evt clearSearchEvt;      // For search field
  final Evt clearCommentsEvt;    // For comments field
  // ...
}
```

### Don't Use Events for Persistent Data

Events are mutable and designed for one-time use. Never persist them to local storage.

### Event Equality Prevents Unnecessary Rebuilds

Events have special equality methods that prevent unnecessary widget rebuilds when used correctly with the selector pattern.

## Advanced: Checking Event Status Without Consuming

Use these methods to check an event's status without consuming it:

```dart
// Check if an event has been consumed
bool consumed = myEvent.isSpent;

// Check if an event is ready to be consumed
bool ready = myEvent.isNotSpent;

// Get the underlying state without consuming
var eventState = myEvent.state;
```

## Advanced: Event.map() for Transformations

Transform an event's value:

```dart
// Map an event to a different type
Evt<String> nameEvt = Evt<int>(42).map((value) => 'Item $value');
```

## Advanced: Consuming from Multiple Event Sources

When you need to consume from multiple possible event sources:

```dart
// Create an event that consumes from first non-spent source
var combined = Event.from([event1, event2, event3]);

// Or use the static method
var value = Event.consumeFrom([event1, event2, event3]);
```

## References

URLs from the documentation:
- https://asyncredux.com/flutter/basics/events
- https://asyncredux.com/flutter/miscellaneous/advanced-events
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/connector/store-connector


================================================
FILE: .claude/skills/asyncredux-flutter-hooks/SKILL.md
================================================
---
name: asyncredux-flutter-hooks
description: Integrate AsyncRedux with the flutter_hooks package. Covers adding flutter_hooks_async_redux, using the useSelector hook, and combining hooks with AsyncRedux state management.
---

## Overview

The `flutter_hooks_async_redux` package provides a hooks-based API for accessing AsyncRedux state. If you prefer functional components with hooks over the widget-based `StoreConnector` pattern, this package lets you use hooks like `useSelector` and `useDispatch` to interact with the Redux store.

## Installation

Add these dependencies to your `pubspec.yaml`:

```yaml
dependencies:
  flutter_hooks: ^0.21.2
  async_redux: ^24.2.2
  flutter_hooks_async_redux: ^3.1.0
```

Then run `flutter pub get`.

## Core Hooks

### useSelector

Selects a part of the state and subscribes to updates. The widget rebuilds when the selected value changes:

```dart
String username = useSelector<AppState, String>((state) => state.username);
```

The `distinct` parameter (default `true`) controls whether the widget rebuilds only when the selected value changes.

### Creating a Custom useAppState Hook

For convenience, define a custom hook that's pre-typed for your state:

```dart
T useAppState<T>(T Function(AppState state) converter, {bool distinct = true}) =>
    useSelector<AppState, T>(converter, distinct: distinct);
```

This simplifies state access throughout your app:

```dart
// Instead of:
String username = useSelector<AppState, String>((state) => state.username);

// Use:
String username = useAppState((state) => state.username);
```

### useDispatch

Dispatches actions that may change the store state. Works with both sync and async actions:

```dart
class MyWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    var dispatch = useDispatch();

    return ElevatedButton(
      onPressed: () => dispatch(IncrementAction()),
      child: Text('Increment'),
    );
  }
}
```

### useDispatchAndWait

Dispatches an action and returns a `Future<ActionStatus>` that resolves when the action completes:

```dart
class MyWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    var dispatchAndWait = useDispatchAndWait();
    var dispatch = useDispatch();

    Future<void> handleSubmit() async {
      // Wait for first action to complete
      await dispatchAndWait(DoThisFirstAction());
      // Then dispatch the second
      dispatch(DoThisSecondAction());
    }

    return ElevatedButton(
      onPressed: handleSubmit,
      child: Text('Submit'),
    );
  }
}
```

You can also check the action status:

```dart
var status = await dispatchAndWait(MyAction());
if (status.isCompletedOk) {
  // Action succeeded
}
```

### useDispatchSync

Enforces synchronous action dispatch. Throws `StoreException` if you attempt to dispatch an async action:

```dart
var dispatchSync = useDispatchSync();
dispatchSync(MySyncAction()); // OK
dispatchSync(MyAsyncAction()); // Throws StoreException
```

## Waiting and Error Hooks

### useIsWaiting

Checks if an async action is currently being processed:

```dart
class MyWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    var dispatch = useDispatch();
    var isLoading = useIsWaiting(LoadDataAction);

    return Column(
      children: [
        if (isLoading) CircularProgressIndicator(),
        ElevatedButton(
          onPressed: () => dispatch(LoadDataAction()),
          child: Text('Load'),
        ),
      ],
    );
  }
}
```

You can check by action type, action instance, or multiple types:

```dart
// By action type
var isWaiting = useIsWaiting(MyAction);

// By action instance
var action = MyAction();
dispatch(action);
var isWaiting = useIsWaiting(action);

// Multiple types - true if ANY are in progress
var isWaiting = useIsWaiting([BuyAction, SellAction]);
```

### useIsFailed

Checks if an action has failed:

```dart
var isFailed = useIsFailed(MyAction);

if (isFailed) {
  return Text('Something went wrong');
}
```

### useExceptionFor

Retrieves the `UserException` from a failed action:

```dart
var exception = useExceptionFor(MyAction);

if (exception != null) {
  return Text(exception.reason ?? 'Unknown error');
}
```

### useClearExceptionFor

Gets a function to clear the exception state for an action:

```dart
var clearExceptionFor = useClearExceptionFor();

// Clear exception when user dismisses error
ElevatedButton(
  onPressed: () => clearExceptionFor(MyAction),
  child: Text('Dismiss'),
)
```

## Complete Example

Here's a full example combining multiple hooks:

```dart
class UserProfileWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    // Select state
    var username = useAppState((state) => state.user.name);
    var email = useAppState((state) => state.user.email);

    // Dispatch hooks
    var dispatch = useDispatch();
    var dispatchAndWait = useDispatchAndWait();

    // Loading and error state
    var isLoading = useIsWaiting(UpdateProfileAction);
    var isFailed = useIsFailed(UpdateProfileAction);
    var exception = useExceptionFor(UpdateProfileAction);
    var clearException = useClearExceptionFor();

    Future<void> handleUpdate() async {
      var status = await dispatchAndWait(UpdateProfileAction());
      if (status.isCompletedOk) {
        // Show success message
      }
    }

    return Column(
      children: [
        Text('Username: $username'),
        Text('Email: $email'),

        if (isLoading)
          CircularProgressIndicator(),

        if (isFailed && exception != null)
          Row(
            children: [
              Text(exception.reason ?? 'Update failed'),
              IconButton(
                icon: Icon(Icons.close),
                onPressed: () => clearException(UpdateProfileAction),
              ),
            ],
          ),

        ElevatedButton(
          onPressed: isLoading ? null : handleUpdate,
          child: Text('Update Profile'),
        ),
      ],
    );
  }
}
```

## Hook Parameters Reference

| Hook | Accepts | Returns |
|------|---------|---------|
| `useSelector<St, T>` | Converter function | Selected value of type T |
| `useDispatch` | None | Dispatch function |
| `useDispatchAndWait` | None | Function returning `Future<ActionStatus>` |
| `useDispatchSync` | None | Sync dispatch function |
| `useIsWaiting` | Action type, instance, or list of types | `bool` |
| `useIsFailed` | Action type, instance, or list of types | `bool` |
| `useExceptionFor` | Action type, instance, or list of types | `UserException?` |
| `useClearExceptionFor` | None | Clear function |

## Hooks vs StoreConnector

Choose hooks when:
- You prefer functional widget patterns
- You're already using `flutter_hooks` in your project
- You want concise state access without view-model boilerplate

Choose `StoreConnector` when:
- You want explicit separation between UI and state logic
- You need the structured view-model pattern for testing
- You're not using hooks elsewhere in your project

Both approaches work well with AsyncRedux - pick the one that fits your team's preferences.

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/other-packages/using-flutter-hooks-package
- https://pub.dev/packages/flutter_hooks_async_redux
- https://github.com/marcglasberg/flutter_hooks_async_redux


================================================
FILE: .claude/skills/asyncredux-navigation/SKILL.md
================================================
---
name: asyncredux-navigation
description: Handle navigation through actions using NavigateAction. Covers setting up the navigator key, dispatching NavigateAction for push/pop/replace, and testing navigation in isolation.
---

# Navigation with NavigateAction

AsyncRedux enables app navigation through action dispatching, making it easier to unit test navigation logic. This approach is optional and currently supports Navigator 1 only.

## Setup

### 1. Create and Register the Navigator Key

Create a global navigator key and register it with NavigateAction during app initialization:

```dart
import 'package:async_redux/async_redux.dart';
import 'package:flutter/material.dart';

final navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  NavigateAction.setNavigatorKey(navigatorKey);
  // ... rest of initialization
  runApp(MyApp());
}
```

### 2. Configure MaterialApp

Pass the same navigator key to your MaterialApp:

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreProvider<AppState>(
      store: store,
      child: MaterialApp(
        routes: {
          '/': (context) => HomePage(),
          '/details': (context) => DetailsPage(),
          '/settings': (context) => SettingsPage(),
        },
        navigatorKey: navigatorKey,
      ),
    );
  }
}
```

## Dispatching Navigation Actions

### Push Operations

```dart
// Push a named route
dispatch(NavigateAction.pushNamed('/details'));

// Push a route with a Route object
dispatch(NavigateAction.push(
  MaterialPageRoute(builder: (context) => DetailsPage()),
));

// Push and replace current route (named)
dispatch(NavigateAction.pushReplacementNamed('/newRoute'));

// Push and replace current route (with Route object)
dispatch(NavigateAction.pushReplacement(
  MaterialPageRoute(builder: (context) => NewPage()),
));

// Pop current route and push a new named route
dispatch(NavigateAction.popAndPushNamed('/otherRoute'));

// Push named route and remove all routes until predicate is true
dispatch(NavigateAction.pushNamedAndRemoveUntil(
  '/home',
  (route) => false, // Removes all routes
));

// Push named route and remove all routes (convenience method)
dispatch(NavigateAction.pushNamedAndRemoveAll('/home'));

// Push route and remove until predicate
dispatch(NavigateAction.pushAndRemoveUntil(
  MaterialPageRoute(builder: (context) => HomePage()),
  (route) => false,
));
```

### Pop Operations

```dart
// Pop the current route
dispatch(NavigateAction.pop());

// Pop with a result value
dispatch(NavigateAction.pop(result: 'some_value'));

// Pop routes until predicate is true
dispatch(NavigateAction.popUntil((route) => route.isFirst));

// Pop until reaching a specific named route
dispatch(NavigateAction.popUntilRouteName('/home'));

// Pop until reaching a specific route
dispatch(NavigateAction.popUntilRoute(someRoute));
```

### Replace Operations

```dart
// Replace a specific route with a new one
dispatch(NavigateAction.replace(
  oldRoute: currentRoute,
  newRoute: MaterialPageRoute(builder: (context) => NewPage()),
));

// Replace the route below the current one
dispatch(NavigateAction.replaceRouteBelow(
  anchorRoute: currentRoute,
  newRoute: MaterialPageRoute(builder: (context) => NewPage()),
));
```

### Remove Operations

```dart
// Remove a specific route
dispatch(NavigateAction.removeRoute(routeToRemove));

// Remove the route below a specific route
dispatch(NavigateAction.removeRouteBelow(anchorRoute));
```

## Complete Example

```dart
import 'package:async_redux/async_redux.dart';
import 'package:flutter/material.dart';

late Store<AppState> store;
final navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  NavigateAction.setNavigatorKey(navigatorKey);
  store = Store<AppState>(initialState: AppState());
  runApp(MyApp());
}

class AppState {}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreProvider<AppState>(
      store: store,
      child: MaterialApp(
        routes: {
          '/': (context) => HomePage(),
          '/details': (context) => DetailsPage(),
        },
        navigatorKey: navigatorKey,
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to Details'),
          onPressed: () => context.dispatch(NavigateAction.pushNamed('/details')),
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Details')),
      body: Center(
        child: ElevatedButton(
          child: Text('Go Back'),
          onPressed: () => context.dispatch(NavigateAction.pop()),
        ),
      ),
    );
  }
}
```

## Getting the Current Route Name

Rather than storing the current route in your app state (which can create complications), access it directly:

```dart
String routeName = NavigateAction.getCurrentNavigatorRouteName(context);
```

## Navigation from Actions

You can dispatch navigation actions from within other actions:

```dart
class LoginAction extends ReduxAction<AppState> {
  final String username;
  final String password;

  LoginAction({required this.username, required this.password});

  @override
  Future<AppState?> reduce() async {
    final user = await api.login(username, password);

    // Navigate to home after successful login
    dispatch(NavigateAction.pushReplacementNamed('/home'));

    return state.copy(user: user);
  }
}
```

## Testing Navigation

NavigateAction enables unit testing of navigation without widget or driver tests:

```dart
test('login navigates to home on success', () async {
  final store = Store<AppState>(initialState: AppState());

  // Capture dispatched actions
  NavigateAction? navigateAction;
  store.actionObservers.add((action, ini, prevState, newState) {
    if (action is NavigateAction) {
      navigateAction = action;
    }
  });

  await store.dispatchAndWait(LoginAction(
    username: 'test',
    password: 'password',
  ));

  // Assert navigation type
  expect(navigateAction!.type, NavigateType.pushReplacementNamed);

  // Assert route name
  expect(
    (navigateAction!.details as NavigatorDetails_PushReplacementNamed).routeName,
    '/home',
  );
});
```

### NavigateType Enum Values

The `NavigateType` enum includes values for all navigation operations:

- `push`, `pushNamed`
- `pop`
- `pushReplacement`, `pushReplacementNamed`
- `popAndPushNamed`
- `pushAndRemoveUntil`, `pushNamedAndRemoveUntil`, `pushNamedAndRemoveAll`
- `popUntil`, `popUntilRouteName`, `popUntilRoute`
- `replace`, `replaceRouteBelow`
- `removeRoute`, `removeRouteBelow`

## Important Notes

- Navigation via AsyncRedux is entirely optional
- Currently supports Navigator 1 only
- For modern navigation packages (like go_router), you'll need to create custom action implementations
- Don't store the current route in your app state; use `getCurrentNavigatorRouteName()` instead

## References

URLs from the documentation:
- https://asyncredux.com/flutter/miscellaneous/navigation
- https://asyncredux.com/flutter/testing/testing-navigation
- https://github.com/marcglasberg/async_redux/blob/master/example/lib/main_navigate.dart
- https://raw.githubusercontent.com/marcglasberg/async_redux/master/lib/src/navigate_action.dart


================================================
FILE: .claude/skills/asyncredux-nonreentrant-mixin/SKILL.md
================================================
---
name: asyncredux-nonreentrant-mixin
description: Add the NonReentrant mixin to prevent an action from dispatching while already in progress. Covers preventing duplicate form submissions, avoiding race conditions, and protecting long-running operations.
---

# NonReentrant Mixin

The `NonReentrant` mixin prevents concurrent execution of the same action type. When an action instance is already running, new dispatches of that same action are silently aborted.

## Basic Usage

Add the `NonReentrant` mixin to any action that should not run concurrently:

```dart
class SaveAction extends AppAction with NonReentrant {
  Future<AppState?> reduce() async {
    await http.put('http://myapi.com/save', body: 'data');
    return null;
  }
}
```

With this mixin:
- If the user clicks "Save" multiple times rapidly, only the first dispatch executes
- Subsequent dispatches while the first is running are silently aborted
- No duplicate API calls or race conditions occur

## How It Works

The `NonReentrant` mixin overrides the `abortDispatch` method. When `abortDispatch()` returns `true`, the action's `before()`, `reduce()`, and `after()` methods will not run, and the state stays unchanged.

By default, checks are based on the action's runtime type - multiple instances of the same action class cannot run simultaneously.

## Common Use Cases

1. **Preventing duplicate form submissions** - Stop users from accidentally submitting forms multiple times
2. **Protecting API calls** - Ensure save/update/delete operations don't fire concurrently
3. **Resource-intensive tasks** - Prevent expensive computations from running in parallel
4. **Avoiding race conditions** - Ensure sequential execution of operations that must not overlap

## Customization

### Allow Different Parameters to Run Concurrently

Override `nonReentrantKeyParams()` to allow actions with different parameters to run in parallel:

```dart
class SaveItemAction extends AppAction with NonReentrant {
  final String itemId;
  SaveItemAction(this.itemId);

  @override
  Object? nonReentrantKeyParams() => itemId;

  Future<AppState?> reduce() async {
    await saveItem(itemId);
    return null;
  }
}
```

With this customization:
- `SaveItemAction('A')` and `SaveItemAction('B')` can run concurrently
- Two `SaveItemAction('A')` dispatches will still block each other

### Share Keys Across Different Action Types

Override `computeNonReentrantKey()` to make different action classes block each other:

```dart
class SaveUserAction extends AppAction with NonReentrant {
  final String orderId;
  SaveUserAction(this.orderId);

  @override
  Object? computeNonReentrantKey() => orderId;

  Future<AppState?> reduce() async { ... }
}

class DeleteUserAction extends AppAction with NonReentrant {
  final String orderId;
  DeleteUserAction(this.orderId);

  @override
  Object? computeNonReentrantKey() => orderId;

  Future<AppState?> reduce() async { ... }
}
```

This prevents `SaveUserAction('123')` and `DeleteUserAction('123')` from running simultaneously - useful when different operations on the same resource must not overlap.

## Combining with Other Mixins

You can combine `NonReentrant` with other compatible mixins:

```dart
class LoadDataAction extends AppAction with CheckInternet, NonReentrant {
  Future<AppState?> reduce() async {
    final data = await fetchData();
    return state.copy(data: data);
  }
}
```

**Incompatible mixins:** `NonReentrant` cannot be combined with:
- `Throttle`
- `UnlimitedRetryCheckInternet`
- Most optimistic update mixins (check the compatibility matrix)

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/advanced-actions/control-mixins
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/aborting-the-dispatch
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/async-actions


================================================
FILE: .claude/skills/asyncredux-observers/SKILL.md
================================================
---
name: asyncredux-observers
description: Set up observers for debugging and monitoring. Covers implementing actionObservers for dispatch logging, stateObserver for state change tracking, combining observers with globalWrapError, and using observers for analytics.
---

# Setting Up Observers for Debugging and Monitoring

AsyncRedux provides several observer types for monitoring actions, state changes, errors, and widget rebuilds. These observers are configured when creating the Store.

## Overview of Observer Types

| Observer Type | Purpose |
|--------------|---------|
| `ActionObserver` | Monitor action dispatch (start and end) |
| `StateObserver` | Monitor state changes after actions |
| `ErrorObserver` | Monitor and handle action errors |
| `ModelObserver` | Monitor widget rebuilds (for StoreConnector) |

## Store Configuration with Observers

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  actionObservers: [ConsoleActionObserver()],
  stateObservers: [MyStateObserver()],
  errorObserver: MyErrorObserver(),
  modelObserver: DefaultModelObserver(),
);
```

## ActionObserver

The `ActionObserver` monitors when actions are dispatched and when they complete. It triggers twice per action: at the start (INI) and at the end (END).

### ActionObserver Abstract Class

```dart
abstract class ActionObserver<St> {
  void observe(
    ReduxAction<St> action,
    int dispatchCount, {
    required bool ini,
  });
}
```

### Parameters

- `action`: The dispatched action instance
- `dispatchCount`: Sequential number of this dispatch
- `ini`: `true` when action starts (INI phase), `false` when it ends (END phase)

### Observation Phases

**INI Phase**: Action dispatch begins. The reducer hasn't modified state yet. Sync reducers may complete during this phase; async reducers start their async process.

**END Phase**: The reducer has finished and returned the new state. State modifications are now observable.

**Important**: Receiving an END observation does not guarantee all effects have finished. Async operations that were not awaited may continue running and dispatch additional actions later.

### Built-in ConsoleActionObserver

AsyncRedux provides `ConsoleActionObserver` for development debugging:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  actionObservers: kReleaseMode ? null : [ConsoleActionObserver()],
);
```

This prints actions in yellow to the console. Override `toString()` in your actions to display additional information:

```dart
class LoadUserAction extends AppAction {
  final String username;
  LoadUserAction(this.username);

  @override
  Future<AppState?> reduce() async {
    // ...
  }

  @override
  String toString() => 'LoadUserAction(username: $username)';
}
```

### Using Log.printer for Formatted Output

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  actionObservers: [Log.printer(formatter: Log.verySimpleFormatter)],
);
```

### Custom ActionObserver Implementation

```dart
class MyActionObserver implements ActionObserver<AppState> {
  @override
  void observe(
    ReduxAction<AppState> action,
    int dispatchCount, {
    required bool ini,
  }) {
    final phase = ini ? 'START' : 'END';
    print('[$phase] Action #$dispatchCount: ${action.runtimeType}');
  }
}
```

## StateObserver

The `StateObserver` is notified of all state changes, allowing you to track, log, or record state history.

### StateObserver Abstract Class

```dart
abstract class StateObserver<St> {
  void observe(
    ReduxAction<St> action,
    St prevState,
    St newState,
    Object? error,
    int dispatchCount,
  );
}
```

### Parameters

- `action`: The action that triggered the change
- `prevState`: State before the reducer executed
- `newState`: State returned by the reducer
- `error`: Null if successful; contains the thrown error otherwise
- `dispatchCount`: Sequential dispatch number

### Detecting State Changes

Compare states using `identical()` to detect actual changes:

```dart
bool stateChanged = !identical(prevState, newState);
```

### Custom StateObserver for Logging

```dart
class StateLogger implements StateObserver<AppState> {
  @override
  void observe(
    ReduxAction<AppState> action,
    AppState prevState,
    AppState newState,
    Object? error,
    int dispatchCount,
  ) {
    final changed = !identical(prevState, newState);
    print('Action #$dispatchCount: ${action.runtimeType}');
    print('  State changed: $changed');
    if (error != null) {
      print('  Error: $error');
    }
  }
}
```

### StateObserver for Undo/Redo

A common use case is recording state history for undo/redo functionality:

```dart
class UndoRedoObserver implements StateObserver<AppState> {
  final List<AppState> _history = [];
  int _currentIndex = -1;
  final int maxHistorySize;

  UndoRedoObserver({this.maxHistorySize = 50});

  bool get canUndo => _currentIndex > 0;
  bool get canRedo => _currentIndex < _history.length - 1;

  @override
  void observe(
    ReduxAction<AppState> action,
    AppState prevState,
    AppState newState,
    Object? error,
    int dispatchCount,
  ) {
    // Skip undo/redo actions to avoid recording navigation
    if (action is UndoAction || action is RedoAction) return;

    // Skip if state didn't change
    if (identical(prevState, newState)) return;

    // Remove "future" states if we're navigating
    if (_currentIndex < _history.length - 1) {
      _history.removeRange(_currentIndex + 1, _history.length);
    }

    // Add new state
    _history.add(newState);
    _currentIndex = _history.length - 1;

    // Enforce max history size
    if (_history.length > maxHistorySize) {
      _history.removeAt(0);
      _currentIndex--;
    }
  }

  AppState? getPreviousState() {
    if (!canUndo) return null;
    _currentIndex--;
    return _history[_currentIndex];
  }

  AppState? getNextState() {
    if (!canRedo) return null;
    _currentIndex++;
    return _history[_currentIndex];
  }
}
```

## ErrorObserver

The `ErrorObserver` monitors all errors thrown by actions and can suppress or allow them to propagate.

### Error Handling Flow

The error handling order is:
1. `wrapError()` (action-level)
2. `GlobalWrapError` (app-level)
3. `ErrorObserver` (monitoring/logging)

### ErrorObserver Implementation

```dart
class MyErrorObserver<St> implements ErrorObserver<St> {
  @override
  bool observe(
    Object error,
    StackTrace stackTrace,
    ReduxAction<St> action,
    Store store,
  ) {
    // Log the error
    print('Error in ${action.runtimeType}: $error');
    print(stackTrace);

    // Send to crash reporting service
    crashReporter.recordError(error, stackTrace, reason: action.runtimeType.toString());

    // Return true to rethrow the error, false to suppress it
    return true;
  }
}
```

### Store Configuration with ErrorObserver

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  errorObserver: MyErrorObserver<AppState>(),
);
```

### Combining with GlobalWrapError

Use `GlobalWrapError` to transform errors before they reach the `ErrorObserver`:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  globalWrapError: MyGlobalWrapError(),
  errorObserver: MyErrorObserver<AppState>(),
);

class MyGlobalWrapError extends GlobalWrapError {
  @override
  Object? wrap(Object error, StackTrace stackTrace, ReduxAction<dynamic> action) {
    // Transform platform errors to user-friendly messages
    if (error is PlatformException) {
      return UserException('Check your internet connection').addCause(error);
    }
    return error;
  }
}
```

## ModelObserver

The `ModelObserver` monitors widget rebuilds when using `StoreConnector`. This is useful for debugging rebuild behavior and ensuring efficient state updates.

### Setup

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  modelObserver: DefaultModelObserver(),
);
```

### Console Output

`DefaultModelObserver` prints rebuild information:

```
Model D:1 R:1 = Rebuild:true, Connector:MyWidgetConnector, Model:MyViewModel{B}.
Model D:2 R:2 = Rebuild:false, Connector:MyWidgetConnector, Model:MyViewModel{B}.
Model D:3 R:3 = Rebuild:true, Connector:MyWidgetConnector, Model:MyViewModel{C}.
```

- `D`: Dispatch count
- `R`: Rebuild count
- `Rebuild`: Whether the widget actually rebuilt
- `Connector`: The StoreConnector type
- `Model`: The ViewModel with current state

### Configuration for Better Output

Pass `debug: this` to `StoreConnector` to enable connector type printing:

```dart
class MyWidgetConnector extends StatelessWidget with StoreConnector<AppState, MyViewModel> {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, MyViewModel>(
      debug: this, // Enable for ModelObserver output
      converter: (store) => MyViewModel.fromStore(store),
      builder: (context, vm) => MyWidget(vm),
    );
  }
}
```

Override `ViewModel.toString()` for custom diagnostic information.

## Using Observers for Analytics

### Metrics Observer Pattern

Create a metrics observer that delegates to action-specific tracking methods:

```dart
abstract class AppAction extends ReduxAction<AppState> {
  /// Override in specific actions to track metrics
  void trackEvent(MetricsService metrics) {}
}

class MetricsObserver implements StateObserver<AppState> {
  final MetricsService metrics;

  MetricsObserver(this.metrics);

  @override
  void observe(
    ReduxAction<AppState> action,
    AppState prevState,
    AppState newState,
    Object? error,
    int dispatchCount,
  ) {
    if (action is AppAction) {
      action.trackEvent(metrics);
    }
  }
}
```

Then override `trackEvent` in specific actions:

```dart
class PurchaseAction extends AppAction {
  final Product product;
  PurchaseAction(this.product);

  @override
  Future<AppState?> reduce() async {
    await purchaseService.buy(product);
    return state.copy(purchases: state.purchases.add(product));
  }

  @override
  void trackEvent(MetricsService metrics) {
    metrics.trackPurchase(productId: product.id, price: product.price);
  }
}
```

### Analytics ActionObserver

Track all dispatched actions for analytics:

```dart
class AnalyticsObserver implements ActionObserver<AppState> {
  final AnalyticsService analytics;

  AnalyticsObserver(this.analytics);

  @override
  void observe(
    ReduxAction<AppState> action,
    int dispatchCount, {
    required bool ini,
  }) {
    // Only track at start (ini) to avoid double-counting
    if (ini) {
      analytics.trackEvent(
        'action_dispatched',
        parameters: {'action_type': action.runtimeType.toString()},
      );
    }
  }
}
```

## Complete Example: Store with All Observers

```dart
// observers.dart
class ConsoleStateObserver implements StateObserver<AppState> {
  @override
  void observe(
    ReduxAction<AppState> action,
    AppState prevState,
    AppState newState,
    Object? error,
    int dispatchCount,
  ) {
    final changed = !identical(prevState, newState);
    print('[$dispatchCount] ${action.runtimeType} - Changed: $changed');
    if (error != null) print('  Error: $error');
  }
}

class CrashReportingErrorObserver implements ErrorObserver<AppState> {
  @override
  bool observe(Object error, StackTrace stackTrace, ReduxAction<AppState> action, Store store) {
    // Don't report UserExceptions (they're expected)
    if (error is! UserException) {
      FirebaseCrashlytics.instance.recordError(error, stackTrace);
    }
    return true; // Rethrow the error
  }
}

// main.dart
void main() {
  final store = Store<AppState>(
    initialState: AppState.initialState(),
    // Only enable console observers in debug mode
    actionObservers: kDebugMode ? [ConsoleActionObserver()] : null,
    stateObservers: kDebugMode ? [ConsoleStateObserver()] : null,
    // Always enable error observer
    errorObserver: CrashReportingErrorObserver(),
    // Transform errors globally
    globalWrapError: MyGlobalWrapError(),
  );

  runApp(StoreProvider<AppState>(
    store: store,
    child: MyApp(),
  ));
}
```

## Multiple Observers

You can use multiple observers of the same type:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  actionObservers: [
    ConsoleActionObserver(),
    AnalyticsObserver(analyticsService),
    PerformanceObserver(),
  ],
  stateObservers: [
    StateLogger(),
    UndoRedoObserver(),
    MetricsObserver(metricsService),
  ],
);
```

All observers will be notified in the order they are listed.

## References

URLs from the documentation:
- https://asyncredux.com/flutter/miscellaneous/logging
- https://asyncredux.com/flutter/miscellaneous/metrics
- https://asyncredux.com/flutter/miscellaneous/observing-rebuilds
- https://asyncredux.com/flutter/miscellaneous/undo-and-redo
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/basics/store


================================================
FILE: .claude/skills/asyncredux-optimistic-update-mixin/SKILL.md
================================================
---
name: asyncredux-optimistic-update-mixin
description: Add the OptimisticUpdate mixin for instant UI feedback before server confirmation. Covers immediate state changes, automatic rollback on failure, and optionally notifying users of rollback.
---

# Optimistic Update Mixins

AsyncRedux provides three optimistic update mixins for different scenarios:

| Mixin | Use Case |
|-------|----------|
| `OptimisticCommand` | One-time operations (create, delete, submit) with rollback |
| `OptimisticSync` | Rapid toggling/interactions with coalescing |
| `OptimisticSyncWithPush` | Real-time server push scenarios with revision tracking |

## OptimisticCommand

Use for one-time server operations where immediate UI feedback matters: creating todos, deleting items, submitting forms, or processing payments.

### Basic Example

Without optimistic updates (user waits for server):

```dart
class SaveTodo extends AppAction {
  final Todo newTodo;
  SaveTodo(this.newTodo);

  Future<AppState?> reduce() async {
    await saveTodo(newTodo);
    var reloadedList = await loadTodoList();
    return state.copy(todoList: reloadedList);
  }
}
```

With OptimisticCommand (instant UI feedback):

```dart
class SaveTodo extends AppAction with OptimisticCommand {
  final Todo newTodo;
  SaveTodo(this.newTodo);

  // Value to apply immediately to UI
  Object? optimisticValue() => newTodo;

  // Extract current value from state (for rollback comparison)
  Object? getValueFromState(AppState state)
    => state.todoList.getById(newTodo.id);

  // Apply value to state and return new state
  AppState applyValueToState(AppState state, Object? value)
    => state.copy(todoList: state.todoList.add(value as Todo));

  // Send to server (retries if using Retry mixin)
  Future<Object?> sendCommandToServer(Object? value) async
    => await saveTodo(newTodo);

  // Optional: reload from server on error
  Future<Object?> reloadFromServer() async
    => await loadTodoList();
}
```

### How Rollback Works

If `sendCommandToServer` fails, the mixin automatically rolls back only if the current state still matches the optimistic value. This avoids undoing newer changes made while the request was in flight.

Override these methods to customize rollback:

```dart
// Determine whether to restore previous state
bool shouldRollback() => true;

// Specify exact state to restore
AppState? rollbackState() => previousState;
```

### Non-Reentrant by Default

OptimisticCommand prevents concurrent execution of the same action. Use `nonReentrantKeyParams()` to allow parallel operations on different items:

```dart
class SaveTodo extends AppAction with OptimisticCommand {
  final String itemId;
  SaveTodo(this.itemId);

  // Allow SaveTodo('A') and SaveTodo('B') to run simultaneously
  // but prevent two SaveTodo('A') from running together
  Object? nonReentrantKeyParams() => itemId;

  // ... rest of implementation
}
```

Check if action is in progress in UI:

```dart
if (context.isWaiting(SaveTodo)) {
  return CircularProgressIndicator();
}
```

### Combining with Other Mixins

- **With Retry**: Only `sendCommandToServer` retries; optimistic UI remains stable
- **With CheckInternet**: No optimistic state applied when offline

## OptimisticSync

Use for rapid user interactions (toggling likes, switches, sliders) where only the final value matters and intermediate states can be discarded.

### Toggle Example

```dart
class ToggleLike extends AppAction with OptimisticSync<AppState, bool> {
  final String itemId;
  ToggleLike(this.itemId);

  // Allow concurrent operations on different items
  Object? optimisticSyncKeyParams() => itemId;

  // Value to apply optimistically (toggle current value)
  bool valueToApply() => !state.items[itemId].liked;

  // Apply optimistic change to state
  AppState applyOptimisticValueToState(AppState state, bool isLiked)
    => state.copy(items: state.items.setLiked(itemId, isLiked));

  // Extract current value from state
  bool getValueFromState(AppState state) => state.items[itemId].liked;

  // Send to server
  Future<Object?> sendValueToServer(Object? value) async
    => await api.setLiked(itemId, value);

  // Optional: Apply server response to state
  AppState? applyServerResponseToState(AppState state, Object serverResponse)
    => state.copy(items: state.items.setLiked(itemId, serverResponse as bool));

  // Optional: Handle completion/errors
  Future<AppState?> onFinish(Object? error) async {
    if (error != null) {
      // Reload from server on failure
      var reloaded = await api.getItem(itemId);
      return state.copy(items: state.items.update(itemId, reloaded));
    }
    return null;
  }
}
```

### How Coalescing Works

Multiple rapid changes are merged into minimal server requests:

1. User taps like button 5 times quickly
2. UI updates instantly each time (toggle, toggle, toggle...)
3. Only **one** server request sends the final state
4. If state changes during in-flight request, a follow-up request sends the new final value

## OptimisticSyncWithPush

Use when your app receives real-time server updates (WebSockets, Firebase) across multiple devices modifying shared data.

### Key Differences from OptimisticSync

- Each local dispatch increments a `localRevision` counter
- Server pushes do NOT increment `localRevision`
- Follow-up logic compares revisions instead of just values
- Stale pushes are automatically ignored

### Implementation

```dart
class ToggleLike extends AppAction with OptimisticSyncWithPush<AppState, bool> {
  final String itemId;
  ToggleLike(this.itemId);

  Object? optimisticSyncKeyParams() => itemId;

  bool valueToApply() => !state.items[itemId].liked;

  AppState applyOptimisticValueToState(AppState state, bool isLiked)
    => state.copy(items: state.items.setLiked(itemId, isLiked));

  bool getValueFromState(AppState state) => state.items[itemId].liked;

  // Read server revision from state
  int? getServerRevisionFromState(Object? key)
    => state.items[key as String].serverRevision;

  AppState? applyServerResponseToState(AppState state, Object serverResponse)
    => state.copy(items: state.items.setLiked(itemId, serverResponse as bool));

  Future<Object?> sendValueToServer(Object? value) async {
    // Get local revision BEFORE await
    int localRev = localRevision();

    var response = await api.setLiked(itemId, value, localRev: localRev);

    // Record server's revision after response
    informServerRevision(response.serverRev);

    return response.liked;
  }
}
```

### ServerPush Mixin

Handle incoming server pushes with automatic stale detection:

```dart
class PushLikeUpdate extends AppAction with ServerPush<AppState> {
  final String itemId;
  final bool liked;
  final int serverRev;

  PushLikeUpdate({
    required this.itemId,
    required this.liked,
    required this.serverRev,
  });

  // Link to corresponding OptimisticSyncWithPush action
  Type associatedAction() => ToggleLike;

  Object? optimisticSyncKeyParams() => itemId;

  int serverRevision() => serverRev;

  int? getServerRevisionFromState(Object? key)
    => state.items[key as String].serverRevision;

  AppState? applyServerPushToState(AppState state, Object? key, int serverRevision)
    => state.copy(
         items: state.items.update(
           key as String,
           (item) => item.copy(liked: liked, serverRevision: serverRevision),
         ),
       );
}
```

If incoming `serverRevision` ≤ current known revision, the push is automatically ignored. This prevents older server states from overwriting newer ones.

### Data Model for Revision Tracking

Store server revisions in your data model:

```dart
class Item {
  final bool liked;
  final int? serverRevision;

  Item({required this.liked, this.serverRevision});

  Item copy({bool? liked, int? serverRevision}) => Item(
    liked: liked ?? this.liked,
    serverRevision: serverRevision ?? this.serverRevision,
  );
}
```

## Notifying Users of Rollback

To notify users when a rollback occurs, use `UserException` in your error handling:

```dart
class SaveTodo extends AppAction with OptimisticCommand {
  // ... required methods ...

  Future<Object?> sendCommandToServer(Object? value) async {
    try {
      return await saveTodo(newTodo);
    } catch (e) {
      // Throw UserException to show dialog after rollback
      throw UserException('Failed to save. Your change was reverted.').addCause(e);
    }
  }
}
```

Or use `onFinish` with OptimisticSync:

```dart
Future<AppState?> onFinish(Object? error) async {
  if (error != null) {
    // Dispatch a notification action
    dispatch(UserExceptionAction('Failed to update. Reverting...'));

    // Reload correct state from server
    var reloaded = await api.getItem(itemId);
    return state.copy(items: state.items.update(itemId, reloaded));
  }
  return null;
}
```

## Choosing the Right Mixin

| Scenario | Mixin |
|----------|-------|
| Create/delete/submit operations | `OptimisticCommand` |
| Toggle switches, like buttons | `OptimisticSync` |
| Sliders, rapid input changes | `OptimisticSync` |
| Multi-device with real-time sync | `OptimisticSyncWithPush` + `ServerPush` |

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/advanced-actions/optimistic-mixins
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/advanced-actions/control-mixins
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/basics/async-actions
- https://asyncredux.com/flutter/basics/failed-actions


================================================
FILE: .claude/skills/asyncredux-persistence/SKILL.md
================================================
---
name: asyncredux-persistence
description: Implement local state persistence using Persistor. Covers creating a custom Persistor class, implementing `readState()`, `persistDifference()`, `deleteState()`, using LocalPersist helper, throttling saves, and pausing/resuming persistence with app lifecycle.
---

## Overview

AsyncRedux provides state persistence by passing a `persistor` object to the Store. This maintains app state on disk, enabling restoration between sessions.

## Store Initialization with Persistor

At startup, read any existing state from disk, create default state if none exists, then initialize the store:

```dart
var persistor = MyPersistor();

var initialState = await persistor.readState();

if (initialState == null) {
  initialState = AppState.initialState();
  await persistor.saveInitialState(initialState);
}

var store = Store<AppState>(
  initialState: initialState,
  persistor: persistor,
);
```

## The Persistor Abstract Class

The `Persistor<St>` base class defines these methods:

```dart
abstract class Persistor<St> {
  /// Read persisted state, or return null if none exists
  Future<St?> readState();

  /// Delete state from disk
  Future<void> deleteState();

  /// Save state changes. Provides both newState and lastPersistedState
  /// so you can compare them and save only the difference.
  Future<void> persistDifference({
    required St? lastPersistedState,
    required St newState
  });

  /// Convenience method for initial saves
  Future<void> saveInitialState(St state) =>
    persistDifference(lastPersistedState: null, newState: state);

  /// Controls save frequency. Return null to disable throttling.
  Duration get throttle => const Duration(seconds: 2);
}
```

## Creating a Custom Persistor

Extend the abstract class and implement the required methods:

```dart
class MyPersistor extends Persistor<AppState> {

  @override
  Future<AppState?> readState() async {
    // Read state from disk (e.g., from SharedPreferences, file, etc.)
    return null;
  }

  @override
  Future<void> deleteState() async {
    // Delete state from disk
  }

  @override
  Future<void> persistDifference({
    required AppState? lastPersistedState,
    required AppState newState,
  }) async {
    // Save state to disk.
    // You can compare lastPersistedState with newState to save only changes.
  }

  @override
  Duration get throttle => const Duration(seconds: 2);
}
```

## Throttling

The `throttle` getter controls how often state is saved. All changes within the throttle window are collected and saved in a single call. The default is 2 seconds.

```dart
// Save at most every 5 seconds
@override
Duration get throttle => const Duration(seconds: 5);

// Disable throttling (save immediately on every change)
@override
Duration? get throttle => null;
```

## Forcing Immediate Save

Dispatch `PersistAction()` to save immediately, bypassing the throttle:

```dart
store.dispatch(PersistAction());
```

## Pausing and Resuming Persistence

Control persistence with these store methods:

```dart
store.pausePersistor();           // Pause saving
store.persistAndPausePersistor(); // Save current state, then pause
store.resumePersistor();          // Resume saving
```

## App Lifecycle Integration

Pause persistence when the app goes to background and resume when it becomes active. Create an `AppLifecycleManager` widget:

```dart
class AppLifecycleManager extends StatefulWidget {
  final Widget child;

  const AppLifecycleManager({
    Key? key,
    required this.child,
  }) : super(key: key);

  @override
  _AppLifecycleManagerState createState() => _AppLifecycleManagerState();
}

class _AppLifecycleManagerState extends State<AppLifecycleManager>
    with WidgetsBindingObserver {

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState lifecycle) {
    store.dispatch(ProcessLifecycleChange_Action(lifecycle));
  }

  @override
  Widget build(BuildContext context) => widget.child;
}
```

Create an action to handle lifecycle changes:

```dart
class ProcessLifecycleChange_Action extends ReduxAction<AppState> {
  final AppLifecycleState lifecycle;

  ProcessLifecycleChange_Action(this.lifecycle);

  @override
  Future<AppState?> reduce() async {
    if (lifecycle == AppLifecycleState.resumed ||
        lifecycle == AppLifecycleState.inactive) {
      store.resumePersistor();
    } else if (lifecycle == AppLifecycleState.paused ||
        lifecycle == AppLifecycleState.detached) {
      store.persistAndPausePersistor();
    } else {
      throw AssertionError(lifecycle);
    }
    return null;
  }
}
```

Wrap your app with the lifecycle manager:

```dart
StoreProvider<AppState>(
  store: store,
  child: AppLifecycleManager(
    child: MaterialApp( ... ),
  ),
)
```

## LocalPersist Helper

The `LocalPersist` class simplifies disk operations for Android/iOS. It works with simple object structures containing only primitives, lists, and maps.

```dart
import 'package:async_redux/local_persist.dart';

// Create instance with a file name
var persist = LocalPersist("myFile");

// Save data
List<Object> simpleObjs = [
  'Hello',
  42,
  true,
  [100, 200, {"name": "John"}],
];
await persist.save(simpleObjs);

// Load data
List<Object> loaded = await persist.load();

// Append data
List<Object> moreObjs = ['more', 'data'];
await persist.save(moreObjs, append: true);

// File operations
int length = await persist.length();
bool exists = await persist.exists();
await persist.delete();

// JSON operations for single objects
await persist.saveJson(simpleObj);
Object? simpleObj = await persist.loadJson();
```

**Note:** `LocalPersist` only supports simple objects. For complex nested structures or custom classes, you need to implement serialization yourself (e.g., using JSON encoding with `toJson`/`fromJson` methods).

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/miscellaneous/persistence
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/miscellaneous/database-and-cloud
- https://asyncredux.com/flutter/intro
- https://asyncredux.com/flutter/testing/mocking
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/about
- https://asyncredux.com/flutter/testing/store-tester
- https://asyncredux.com/flutter/miscellaneous/advanced-waiting


================================================
FILE: .claude/skills/asyncredux-provider-integration/SKILL.md
================================================
---
name: asyncredux-provider-integration
description: Integrate AsyncRedux with the Provider package. Covers using provider_for_redux, the ReduxSelector widget, and choosing between StoreConnector and ReduxSelector approaches.
---

# Provider Integration with AsyncRedux

The `provider_for_redux` package bridges Provider and AsyncRedux, enabling you to use Provider's dependency injection with Redux state management.

## Installation

Add the package to your `pubspec.yaml`:

```yaml
dependencies:
  provider_for_redux: ^8.0.0
```

## Setting Up AsyncReduxProvider

Replace `StoreProvider` with `AsyncReduxProvider` to expose three items to descendant widgets:

- The Redux store (`Store<AppState>`)
- The application state (`AppState`)
- The dispatch method (`Dispatch`)

```dart
import 'package:provider_for_redux/provider_for_redux.dart';

void main() {
  final store = Store<AppState>(initialState: AppState.initial());

  runApp(
    AsyncReduxProvider<AppState>.value(
      value: store,
      child: MaterialApp(home: MyHomePage()),
    ),
  );
}
```

## Accessing State with Provider.of

Access store components directly using standard Provider patterns:

```dart
// Access state (rebuilds on state changes)
final counter = Provider.of<AppState>(context).counter;

// Access dispatch (use listen: false for actions)
Provider.of<Dispatch>(context, listen: false)(IncrementAction());

// Access the store directly
final store = Provider.of<Store<AppState>>(context, listen: false);
```

## ReduxConsumer Widget

`ReduxConsumer` provides store, state, and dispatch in a single builder, simplifying access:

```dart
ReduxConsumer<AppState>(
  builder: (context, store, state, dispatch, child) {
    return Column(
      children: [
        Text('Counter: ${state.counter}'),
        Text('Description: ${state.description}'),
        ElevatedButton(
          onPressed: () => dispatch(IncrementAction()),
          child: Text('Increment'),
        ),
      ],
    );
  },
)
```

## ReduxSelector Widget

`ReduxSelector` prevents unnecessary rebuilds by selecting specific state portions. Only when selected values change does the widget rebuild.

### Using a List (Recommended)

The simplest approach - explicitly list the properties that should trigger rebuilds:

```dart
ReduxSelector<AppState, dynamic>(
  selector: (context, state) => [state.counter, state.description],
  builder: (context, store, state, dispatch, model, child) {
    return Column(
      children: [
        Text('Counter: ${state.counter}'),
        Text('Description: ${state.description}'),
        ElevatedButton(
          onPressed: () => dispatch(IncrementAction()),
          child: Text('Increment'),
        ),
      ],
    );
  },
)
```

### Using a Custom Model

For structured data, use a Tuple or custom class:

```dart
ReduxSelector<AppState, Tuple2<int, String>>(
  selector: (context, state) => Tuple2(state.counter, state.description),
  builder: (context, store, state, dispatch, model, child) {
    return Column(
      children: [
        Text('Counter: ${model.item1}'),
        Text('Description: ${model.item2}'),
        ElevatedButton(
          onPressed: () => dispatch(IncrementAction()),
          child: Text('Increment'),
        ),
      ],
    );
  },
)
```

## Choosing Between StoreConnector and ReduxSelector

Both approaches manage widget rebuilds during state changes, but serve different use cases:

### Use StoreConnector When:

- You want to separate smart (store-aware) and dumb (presentational) widgets
- You need view-models with explicit equality comparison
- You're building reusable UI components that shouldn't know about Redux
- You want to test UI widgets in isolation without a store

```dart
class MyCounterConnector extends StatelessWidget {
  Widget build(BuildContext context) {
    return StoreConnector<AppState, ViewModel>(
      vm: () => Factory(this),
      builder: (context, vm) => MyCounter(
        counter: vm.counter,
        description: vm.description,
        onIncrement: vm.onIncrement,
      ),
    );
  }
}

class ViewModel extends Vm {
  final int counter;
  final String description;
  final VoidCallback onIncrement;

  ViewModel({
    required this.counter,
    required this.description,
    required this.onIncrement,
  }) : super(equals: [counter, description]);
}
```

### Use ReduxSelector When:

- You prefer minimal boilerplate
- Direct store access within a single widget is acceptable
- You want Provider-style dependency injection
- You're integrating with existing Provider-based code

```dart
ReduxSelector<AppState, dynamic>(
  selector: (context, state) => [state.counter, state.description],
  builder: (context, store, state, dispatch, model, child) {
    return MyCounter(
      counter: state.counter,
      description: state.description,
      onIncrement: () => dispatch(IncrementAction()),
    );
  },
)
```

## Migration Strategy

Both Provider and AsyncRedux connectors work simultaneously, enabling gradual migration:

```dart
// Old code using StoreConnector continues to work
class OldFeatureConnector extends StatelessWidget {
  Widget build(BuildContext context) {
    return StoreConnector<AppState, OldViewModel>(
      vm: () => OldFactory(this),
      builder: (context, vm) => OldFeatureWidget(vm: vm),
    );
  }
}

// New code can use ReduxSelector
class NewFeatureWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    return ReduxSelector<AppState, dynamic>(
      selector: (context, state) => [state.newFeature],
      builder: (context, store, state, dispatch, model, child) {
        return NewFeatureContent(feature: state.newFeature);
      },
    );
  }
}
```

This allows you to migrate incrementally without rewriting your entire application.

## Comparison Summary

| Aspect | StoreConnector | ReduxSelector |
|--------|---------------|---------------|
| Boilerplate | More (ViewModel + Factory) | Less (inline selector) |
| Separation | Smart/Dumb widget pattern | Single widget |
| Testing | Easy to test UI in isolation | Requires store setup |
| Provider compatibility | Native AsyncRedux | Full Provider integration |
| Rebuild control | Via ViewModel equality | Via selector list |

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/other-packages/using-the-provider-package
- https://asyncredux.com/flutter/connector/store-connector
- https://asyncredux.com/flutter/connector/connector-pattern
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/miscellaneous/widget-selectors
- https://pub.dev/packages/provider_for_redux
- https://github.com/marcglasberg/provider_for_redux


================================================
FILE: .claude/skills/asyncredux-retry-mixin/SKILL.md
================================================
---
name: asyncredux-retry-mixin
description: Add the Retry mixin for automatic retry with exponential backoff on action failure. Covers using Retry alone for limited retries, combining with UnlimitedRetries for infinite retries, and configuring retry behavior.
---

# Retry Mixin

The `Retry` mixin automatically retries failed actions using exponential backoff. When an error occurs in the `reduce()` method, the action is re-executed with progressively increasing delays between attempts.

## Basic Usage

Add the `Retry` mixin to any action that should automatically retry on failure:

```dart
class LoadDataAction extends AppAction with Retry {
  Future<AppState?> reduce() async {
    var data = await fetchDataFromServer();
    return state.copy(data: data);
  }
}
```

With this mixin:
- If the action fails, it automatically retries up to 3 times (default)
- Each retry waits longer than the previous (exponential backoff)
- If all retries fail, the original error is thrown

## Configuration Parameters

Override these getters to customize retry behavior:

```dart
class LoadDataAction extends AppAction with Retry {

  // Delay before first retry (default: 350ms)
  int get initialDelay => 500;

  // Multiplier for delay growth (default: 2)
  int get multiplier => 2;

  // Maximum retry attempts (default: 3)
  int get maxRetries => 5;

  // Upper limit on delay to prevent excessive waits (default: 5000ms)
  int get maxDelay => 10000;

  Future<AppState?> reduce() async {
    var data = await fetchDataFromServer();
    return state.copy(data: data);
  }
}
```

| Parameter | Default | Purpose |
|-----------|---------|---------|
| `initialDelay` | 350 ms | Waiting period before first retry |
| `multiplier` | 2 | Growth factor for delays between attempts |
| `maxRetries` | 3 | Maximum retry count (total executions = maxRetries + 1) |
| `maxDelay` | 5 sec | Upper limit on delay to prevent excessive waits |

### Retry Sequence Example

With default settings (initialDelay=350ms, multiplier=2, maxRetries=3):

1. **Initial attempt** - Action runs, fails
2. **Wait 350ms** - First retry, fails
3. **Wait 700ms** - Second retry, fails
4. **Wait 1400ms** - Third retry, fails
5. **Error thrown** - All retries exhausted

## Timing Considerations

Retry delays start **after** the reducer finishes, not from when the action was dispatched. If `reduce()` takes 1 second to fail and `initialDelay` is 350ms, the first retry starts 1.35 seconds after the action began.

## Tracking Retry Attempts

Access the `attempts` getter within your action to know which attempt is currently running:

```dart
class LoadDataAction extends AppAction with Retry {
  Future<AppState?> reduce() async {
    print('Attempt ${attempts + 1}'); // 0-indexed, so first attempt is 0

    if (attempts > 0) {
      // Maybe try a different server on retries
      return state.copy(data: await fetchFromBackupServer());
    }

    return state.copy(data: await fetchFromPrimaryServer());
  }
}
```

## Unlimited Retries

Combine `UnlimitedRetries` with `Retry` to retry indefinitely until the action succeeds:

```dart
class CriticalSyncAction extends AppAction with Retry, UnlimitedRetries {
  Future<AppState?> reduce() async {
    await syncCriticalData();
    return state.copy(syncComplete: true);
  }
}
```

This is equivalent to setting `maxRetries` to `-1`.

**Warning:** Using `await dispatchAndWait(action)` with `UnlimitedRetries` may hang indefinitely if the action continues failing. Use with caution and consider whether the action has a realistic chance of eventually succeeding.

## Important Behavior Notes

### Only reduce() Failures Trigger Retry

The `Retry` mixin only retries when errors occur in the `reduce()` method. Failures in the `before()` method do **not** trigger retries - they fail immediately.

```dart
class LoadDataAction extends AppAction with Retry {

  @override
  Future<void> before() async {
    // Errors here will NOT trigger retry - action fails immediately
    await validatePermissions();
  }

  Future<AppState?> reduce() async {
    // Only errors here trigger the retry mechanism
    return state.copy(data: await fetchData());
  }
}
```

### Actions Become Asynchronous

All actions using the `Retry` mixin become asynchronous, regardless of their original synchronous nature. This is because the retry mechanism needs to wait between attempts.

## Combining with NonReentrant (Best Practice)

Most actions using `Retry` should also include the `NonReentrant` mixin to prevent multiple instances from running simultaneously:

```dart
class SaveDataAction extends AppAction with NonReentrant, Retry {
  Future<AppState?> reduce() async {
    await saveToServer();
    return state.copy(saved: true);
  }
}
```

This prevents scenarios where:
- User clicks "Save" multiple times
- Multiple retry sequences run in parallel
- Server receives duplicate or conflicting requests

## Combining with CheckInternet

For network operations, combine `Retry` with `CheckInternet` to ensure connectivity before attempting the action:

```dart
class FetchUserProfile extends AppAction with CheckInternet, Retry {
  Future<AppState?> reduce() async {
    var profile = await api.getUserProfile();
    return state.copy(profile: profile);
  }
}
```

The `CheckInternet` mixin runs first. If there's no connection, the action fails immediately without attempting retries.

## Common Use Cases

### API Calls with Transient Failures

```dart
class FetchProductsAction extends AppAction with Retry {
  int get maxRetries => 3;
  int get initialDelay => 500;

  Future<AppState?> reduce() async {
    var products = await api.getProducts();
    return state.copy(products: products);
  }
}
```

### Critical Sync Operations

```dart
class SyncPendingChanges extends AppAction with Retry, UnlimitedRetries {
  int get initialDelay => 1000;
  int get maxDelay => 30000; // Cap at 30 seconds between retries

  Future<AppState?> reduce() async {
    await syncService.pushPendingChanges();
    return state.copy(hasPendingChanges: false);
  }
}
```

### Payment Processing with Extended Retries

```dart
class ProcessPaymentAction extends AppAction with NonReentrant, Retry {
  final double amount;

  ProcessPaymentAction(this.amount);

  int get maxRetries => 5;
  int get initialDelay => 1000;
  int get multiplier => 2;
  int get maxDelay => 10000;

  Future<AppState?> reduce() async {
    var result = await paymentGateway.process(amount);
    return state.copy(paymentStatus: result.status);
  }
}
```

## Mixin Compatibility

**Compatible with:**
- `CheckInternet`
- `NoDialog`
- `AbortWhenNoInternet`
- `NonReentrant`
- `Throttle`
- `Debounce`

**Can be combined with:**
- `UnlimitedRetries` (enables infinite retries)

## Full Example with All Options

```dart
class RobustApiAction extends AppAction
    with CheckInternet, NonReentrant, Retry {

  // Retry configuration
  int get initialDelay => 500;     // 500ms before first retry
  int get multiplier => 2;          // Double delay each time
  int get maxRetries => 4;          // Try up to 5 times total
  int get maxDelay => 8000;         // Never wait more than 8 seconds

  Future<AppState?> reduce() async {
    if (attempts > 0) {
      print('Retry attempt $attempts');
    }

    var data = await api.fetchCriticalData();
    return state.copy(data: data);
  }
}
```

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/control-mixins
- https://asyncredux.com/flutter/advanced-actions/wrapping-the-reducer
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/basics/async-actions
- https://asyncredux.com/flutter/basics/failed-actions
- https://asyncredux.com/flutter/basics/wait-fail-succeed


================================================
FILE: .claude/skills/asyncredux-selectors/SKILL.md
================================================
---
name: asyncredux-selectors
description: Create and cache selectors for efficient state access. Covers writing selector functions, caching with `cache1` and `cache2`, the reselect pattern, and avoiding repeated computations in widgets.
---

## What Are Selectors?

Selectors are functions that extract specific data from the Redux store state. They provide three key benefits:

1. **Compute derived data** - Transform or filter state into the format your widget needs
2. **Abstract state structure** - Components don't depend on how the state is organized
3. **Enable caching (memoization)** - Avoid unnecessary recalculations

## The Problem: Repeated Computations

When displaying filtered or computed data, without selectors you might write:

```dart
// INEFFICIENT - filters the entire list on every access
state.users.where((user) => user.name.startsWith("A")).toList()[index].name;
```

This filtering operation runs every time the widget rebuilds, even when the data hasn't changed.

## Basic Selector Functions

Create a selector function that performs the computation once:

```dart
List<User> selectUsersStartingWith(AppState state, String text) {
  return state.users.where((user) => user.name.startsWith(text)).toList();
}
```

## Cached Selectors (Reselectors)

For expensive computations, wrap your selector with a cache function. AsyncRedux provides built-in caching utilities.

### Basic Caching Example

```dart
List<User> selectUsersStartingWith(AppState state, {required String text}) =>
    _selectUsersStartingWith(state)(text);

static final _selectUsersStartingWith = cache1state_1param(
  (AppState state) => (String text) =>
      state.users.where((user) => user.name.startsWith(text)).toList()
);
```

### Optimized Caching (State Subset)

For better performance, only depend on the specific state subset that matters:

```dart
List<User> selectUsersStartingWith(AppState state, {required String text}) =>
    _selectUsersStartingWith(state.users)(text);

static final _selectUsersStartingWith = cache1state_1param(
  (List<User> users) => (String text) =>
      users.where((user) => user.name.startsWith(text)).toList()
);
```

This version only recalculates when `state.users` changes, not when any part of `state` changes.

## Available Cache Functions

AsyncRedux provides these caching functions:

| Function | States | Parameters | Use Case |
|----------|--------|------------|----------|
| `cache1state` | 1 | 0 | Simple computed value from one state |
| `cache1state_1param` | 1 | 1 | Filtered/computed value with one param |
| `cache1state_2params` | 1 | 2 | Computation with two parameters |
| `cache1state_0params_x` | 1 | Many | Variable number of parameters |
| `cache2states` | 2 | 0 | Combines two state portions |
| `cache2states_1param` | 2 | 1 | Combines two states with one param |
| `cache2states_2params` | 2 | 2 | Combines two states with two params |
| `cache2states_0params_x` | 2 | Many | Two states, variable params |
| `cache3states` | 3 | 0 | Combines three state portions |
| `cache3states_0params_x` | 3 | Many | Three states, variable params |

The naming convention: `cache[N]state[s]_[M]param[s]` where N = number of states, M = number of parameters.

## Cache Characteristics

- **Multiple cached results** - Maintains separate caches for different parameter combinations
- **Weak-map storage** - Automatically discards cached data when states change or fall out of use
- **Memory efficient** - Won't hold obsolete information

## Action Selectors

Create selectors that actions can use via a dedicated class:

```dart
class ActionSelect {
  final AppState state;
  ActionSelect(this.state);

  List<Item> get items => state.items;
  Item get selectedItem => state.selectedItem;

  Item? findById(int id) =>
      state.items.firstWhereOrNull((item) => item.id == id);

  Item? searchByText(String text) =>
      state.items.firstWhereOrNull((item) => item.text.contains(text));

  int get selectedIndex => state.items.indexOf(state.selectedItem);
}
```

Add a getter in your base action:

```dart
abstract class AppAction extends ReduxAction<AppState> {
  ActionSelect get select => ActionSelect(state);
}
```

Usage in actions:

```dart
class LoadItemAction extends AppAction {
  final int itemId;
  LoadItemAction(this.itemId);

  @override
  AppState? reduce() {
    var item = select.findById(itemId);
    if (item == null) return null;
    return state.copy(selectedItem: item);
  }
}
```

## Widget Selectors

Create a `WidgetSelect` class for organized widget-level selectors:

```dart
class WidgetSelect {
  final BuildContext context;
  WidgetSelect(this.context);

  List<Item> get items => context.select((st) => st.items);
  Item get selectedItem => context.select((st) => st.selectedItem);

  Item? findById(int id) =>
      context.select((st) => st.items.firstWhereOrNull((item) => item.id == id));

  Item? searchByText(String text) =>
      context.select((st) => st.items.firstWhereOrNull((item) => item.text.contains(text)));

  int get selectedIndex =>
      context.select((st) => st.items.indexOf(st.selectedItem));
}
```

Add to your BuildContext extension:

```dart
extension BuildContextExtension on BuildContext {
  AppState get state => getState<AppState>();
  R select<R>(R Function(AppState state) selector) => getSelect<AppState, R>(selector);
  WidgetSelect get selector => WidgetSelect(this);
}
```

Usage in widgets:

```dart
Widget build(BuildContext context) {
  final item = context.selector.findById(42);
  return Text(item?.name ?? 'Not found');
}
```

## Reusing Action Selectors in Widgets

Widget selectors can leverage action selectors to avoid duplication:

```dart
class WidgetSelect {
  final BuildContext context;
  WidgetSelect(this.context);

  Item? findById(int id) =>
      context.select((st) => ActionSelect(st).findById(id));

  Item? searchByText(String text) =>
      context.select((st) => ActionSelect(st).searchByText(text));
}
```

## Important Guidelines

### Avoid context.state Inside Selectors

Never use `context.state` inside selector functions - this defeats selective rebuilding:

```dart
// WRONG - rebuilds on any state change
var items = context.select((state) => context.state.items.where(...));

// CORRECT - only rebuilds when items change
var items = context.select((state) => state.items.where(...));
```

### Never Nest context.select Calls

Nesting `context.select` causes errors:

```dart
// WRONG - will cause errors
var result = context.select((state) =>
  context.select((s) => s.items).where(...)  // Nested select!
);

// CORRECT
var items = context.select((state) => state.items);
var result = items.where(...).toList();
```

## Comparison with External Reselect Package

AsyncRedux's built-in caching differs from the external `reselect` package:

| Feature | AsyncRedux | reselect |
|---------|------------|----------|
| Results per selector | Multiple (different params) | One only |
| Memory on state change | Discards old cache | Retains indefinitely |

## Complete Example: Cached Filtered List

```dart
// Selector with caching
class UserSelectors {
  static List<User> usersStartingWith(AppState state, String prefix) =>
      _usersStartingWith(state.users)(prefix);

  static final _usersStartingWith = cache1state_1param(
    (List<User> users) => (String prefix) =>
        users.where((u) => u.name.startsWith(prefix)).toList()
  );

  static List<User> activeUsers(AppState state) =>
      _activeUsers(state.users);

  static final _activeUsers = cache1state(
    (List<User> users) => users.where((u) => u.isActive).toList()
  );
}

// Usage in widget
Widget build(BuildContext context) {
  var filtered = context.select(
    (state) => UserSelectors.usersStartingWith(state, 'A')
  );
  return ListView.builder(
    itemCount: filtered.length,
    itemBuilder: (_, i) => Text(filtered[i].name),
  );
}
```

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/miscellaneous/cached-selectors
- https://asyncredux.com/flutter/miscellaneous/widget-selectors
- https://asyncredux.com/flutter/advanced-actions/action-selectors
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/connector/store-connector
- https://asyncredux.com/flutter/connector/advanced-view-model


================================================
FILE: .claude/skills/asyncredux-setup/SKILL.md
================================================
---
name: asyncredux-setup
description: Initialize, setup and configure AsyncRedux in a Flutter app. Use it whenever starting a new AsyncRedux project, or when the user requests.
---

# AsyncRedux Setup

## Adding the Dependency

Add AsyncRedux to your `pubspec.yaml`:

```yaml
dependencies:
  async_redux: ^25.6.1
```

Check [pub.dev](https://pub.dev/packages/async_redux) for the latest version.

## Creating the State Class

Create an immutable `AppState` class (in file `app_state.dart`) with:

* `copy()` method
* `==` equals method
* `hashCode` method
* `initialState()` static factory

If the app is new, and you don't have any state yet, create an empty `AppState`:

```dart
@immutable
class AppState {
  AppState();
  static AppState initialState() => AppState();
  AppState copy() => AppState();
  
  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is AppState && runtimeType == other.runtimeType;

  @override
  int get hashCode => 0;
}
```

If there is existing state, create the `AppState` that incorporates that state.
This is an example:

```dart
@immutable
class AppState {
  final String name;
  final int age;
  AppState({required this.name, required this.age});

  static AppState initialState() => AppState(name: "", age: 0);

  AppState copy({String? name, int? age}) => AppState(
    name: name ?? this.name,
    age: age ?? this.age,
  );
  
  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is AppState &&
      runtimeType == other.runtimeType &&
      name == other.name &&
      age == other.age;

  @override
  int get hashCode => Object.hash(name, age);
}

```

All fields must be `final` (immutable). Add additional helper methods as needed:

```dart
AppState withName(String name) => copy(name: name);
AppState withAge(int age) => copy(age: age);
```

## Creating the Store

Find the place where you initialize your app (usually in `main.dart`),
and import your `AppState` class (adapt the path as needed) and the AsyncRedux package:

```dart
import 'app_state.dart'; 
import 'package:async_redux/async_redux.dart';
```

Create the store with your initial state. Note that `PersistorDummy`,
`GlobalWrapErrorDummy`, and `ConsoleActionObserver` are provided by AsyncRedux for basic
setups. In the future these can be replaced with custom implementations as needed.

```dart
late Store store;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Create the persistor, and try to read any previously saved state.
  var persistor = PersistorDummy<AppState>();
  AppState? initialState = await persistor.readState();
  
  // If there is no saved state, create a new empty one and save it.
  if (initialState == null) {
    initialState = AppState.initialState();
    await persistor.saveInitialState(initialState);
  }
    
  // Create the store.
  store = Store<AppState>(
    initialState: initialState,
    persistor: persistor,
    globalWrapError: GlobalWrapErrorDummy(),    
    actionObservers: [ConsoleActionObserver()],
  );

  runApp(...);
}
```

## Wrapping with StoreProvider

Wrap your app with `StoreProvider` to make the store accessible.
Find the root of the widget tree of the app, and add it above `MaterialApp` (or
`CupertinoApp`, adapting as needed). Note you will need to import the `store` too.

```dart
import 'package:async_redux/async_redux.dart';

Widget build(context) {
  return StoreProvider<AppState>(
    store: store,
    child: MaterialApp( ... ),
  );
}
```

## Required Context Extensions

You **must** add this extension to your file containing `AppState` (this is required for
easier state access in widgets):

```dart
extension BuildContextExtension on BuildContext {
  AppState get state => getState<AppState>();

  AppState read() => getRead<AppState>();

  R select<R>(R Function(AppState state) selector) =>
      getSelect<AppState, R>(selector);

  R? event<R>(Evt<R> Function(AppState state) selector) =>
      getEvent<AppState, R>(selector);
}
```

## Required base action

Create file `app_action.dart` with this abstract class extending `ReduxAction<AppState>`:

```dart
/// All actions extend this class.
abstract class AppAction extends ReduxAction<AppState> {

ActionSelect get select => ActionSelect(state);
}

// Dedicated selector class to keep the base action clean.
class ActionSelect {
  final AppState state;
  ActionSelect(this.state);
}
```

## Update CLAUDE.md

Add the following information to the project's `CLAUDE.md`, so that all actions extend
this
base action:

```markdown
## Base Action

All actions should extend `AppAction` instead of `ReduxAction<AppState>`. 
There is a dedicated selector class called `ActionSelect` to keep the base action clean,
by namespacing selectors under `select` and enabling IDE autocompletion. Example:

  ```dart
  class ProcessItem extends AppAction {
    final String itemId;
    ProcessItem(this.itemId);
    
    @override
    AppState reduce() {
      // IDE autocomplete shows: select.findById, select.completed, etc.
      final item = select.findById(itemId);
      // ...
    }
  }
  ```

```


================================================
FILE: .claude/skills/asyncredux-state-access/SKILL.md
================================================
---
name: asyncredux-state-access
description: Access store state in widgets using `context.state`, `context.select()`, and `context.read()`. Covers when to use each method, setting up BuildContext extensions, and optimizing widget rebuilds with selective state access.
---

## BuildContext Extension Setup

To access your application state in widgets, first define a `BuildContext` extension. Add this to your project (typically in a shared file that all widgets can import):

```dart
extension BuildContextExtension on BuildContext {
  AppState get state => getState<AppState>();
  AppState read() => getRead<AppState>();
  R select<R>(R Function(AppState state) selector) => getSelect<AppState, R>(selector);
  R? event<R>(Evt<R> Function(AppState state) selector) => getEvent<AppState, R>(selector);
}
```

Replace `AppState` with your actual state class name.

## The Three State Access Methods

### context.state

Grants access to the entire state object. All widgets that use `context.state` will automatically rebuild whenever the store state changes (any part of it).

```dart
Widget build(BuildContext context) {
  return Text('Counter: ${context.state.counter}');
}
```

### context.select()

Retrieves only specific state portions. This is more efficient as it only rebuilds the widget when the selected part of the state changes.

```dart
Widget build(BuildContext context) {
  var counter = context.select((state) => state.counter);
  return Text('Counter: $counter');
}
```

### context.read()

Retrieves state without triggering rebuilds. Use this in event handlers, `initState`, or anywhere you need to read state once without subscribing to changes.

```dart
void _onButtonPressed() {
  var currentCount = context.read().counter;
  print('Current count is $currentCount');
}
```

## When to Use Each Method

| Method | Use In | Triggers Rebuilds? | Best For |
|--------|--------|-------------------|----------|
| `context.state` | `build` method | Yes, on any state change | Simple widgets or when you need many state properties |
| `context.select()` | `build` method | Only when selected part changes | Performance-sensitive widgets |
| `context.read()` | `initState`, event handlers, callbacks | No | One-time reads, button handlers |

## Accessing Multiple State Properties

When you need several pieces of state, you have two options:

**Option 1: Multiple select calls**

```dart
Widget build(BuildContext context) {
  var name = context.select((state) => state.user.name);
  var email = context.select((state) => state.user.email);
  var itemCount = context.select((state) => state.items.length);
  // Widget rebuilds only if name, email, or itemCount changes
  return Text('$name ($email) - $itemCount items');
}
```

**Option 2: Dart records for combined selection**

```dart
Widget build(BuildContext context) {
  var (name, email) = context.select((state) => (state.user.name, state.user.email));
  return Text('$name ($email)');
}
```

## Additional Context Methods for Action States

Beyond state access, the context extension provides methods for tracking async action progress:

```dart
Widget build(BuildContext context) {
  // Check if an action is currently running
  if (context.isWaiting(LoadDataAction)) {
    return CircularProgressIndicator();
  }

  // Check if an action failed
  if (context.isFailed(LoadDataAction)) {
    var exception = context.exceptionFor(LoadDataAction);
    return Text('Error: ${exception?.message}');
  }

  // Show the data
  return Text('Data: ${context.state.data}');
}
```

Available methods:
- `context.isWaiting(ActionType)` - Returns true if the action is in progress
- `context.isFailed(ActionType)` - Returns true if the action recently failed
- `context.exceptionFor(ActionType)` - Gets the exception from a failed action
- `context.clearExceptionFor(ActionType)` - Manually clears the stored exception

## Widget Selectors Pattern

For complex selection logic, create a `WidgetSelect` class to organize reusable selectors:

```dart
class WidgetSelect {
  final BuildContext context;
  WidgetSelect(this.context);

  // Getter shortcuts
  List<Item> get items => context.select((state) => state.items);
  User get currentUser => context.select((state) => state.user);

  // Custom finder methods
  Item? findById(int id) => context.select(
    (state) => state.items.firstWhereOrNull((item) => item.id == id)
  );

  List<Item> searchByText(String text) => context.select(
    (state) => state.items.where((item) => item.name.contains(text)).toList()
  );
}
```

Add it to your BuildContext extension:

```dart
extension BuildContextExtension on BuildContext {
  AppState get state => getState<AppState>();
  // ... other methods ...
  WidgetSelect get selector => WidgetSelect(this);
}
```

Usage in widgets:

```dart
Widget build(BuildContext context) {
  var user = context.selector.currentUser;
  var item = context.selector.findById(42);
  return Text('${user.name}: ${item?.name}');
}
```

## Important Guidelines

### Avoid context.state inside selectors

Never use `context.state` inside your selector functions. This defeats the purpose of selective rebuilding:

```dart
// WRONG - rebuilds on any state change
var items = context.select((state) => context.state.items.where(...));

// CORRECT - only rebuilds when items change
var items = context.select((state) => state.items.where(...));
```

### Never nest context.select calls

Nesting `context.select` causes errors. Always apply selection at the top level:

```dart
// WRONG - will cause errors
var result = context.select((state) =>
  context.select((s) => s.items).where(...) // Nested select!
);

// CORRECT
var items = context.select((state) => state.items);
var result = items.where(...);
```

## Debugging Rebuilds

To observe when widgets rebuild (useful for performance debugging), use a `ModelObserver`:

```dart
var store = Store<AppState>(
  initialState: AppState.initialState(),
  modelObserver: DefaultModelObserver(),
);
```

The `DefaultModelObserver` logs console output showing:
- Whether a rebuild occurred
- Which connector/widget triggered it
- The view model state

Example output:
```
Model D:1 R:1 = Rebuild:true, Connector:MyWidgetConnector, Model:MyViewModel{counter: 5}
```

## References

URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/miscellaneous/widget-selectors
- https://asyncredux.com/flutter/miscellaneous/observing-rebuilds
- https://asyncredux.com/flutter/miscellaneous/cached-selectors
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/advanced-actions/action-selectors
- https://asyncredux.com/flutter/connector/store-connector
- https://asyncredux.com/flutter/intro
- https://asyncredux.com/flutter/basics/wait-fail-succeed


================================================
FILE: .claude/skills/asyncredux-state-design/SKILL.md
================================================
---
name: asyncredux-state-design
description: Design immutable state classes following AsyncRedux best practices. Includes creating the AppState class with a `copy()` method, defining `initialState()`, composing nested state objects, and optionally using the fast_immutable_collections package for IList, ISet, and IMap.
---

# AsyncRedux State Design

## Core Principle: Immutability

State classes must be immutable—fields cannot be modified after creation. Instead of changing state directly, you create new instances. All fields should be marked `final`.

## Basic State Class Structure

```dart
class AppState {
  final String name;
  final int age;

  AppState({required this.name, required this.age});

  static AppState initialState() => AppState(name: "", age: 0);

  AppState copy({String? name, int? age}) =>
      AppState(
        name: name ?? this.name,
        age: age ?? this.age,
      );
}
```

### Key Components

1. **Final fields** - All state fields must be `final`
2. **`initialState()`** - Static factory method providing default values
3. **`copy()` method** - Creates modified instances without mutating original

## The copy() Method Pattern

The `copy()` method accepts optional parameters for each field. If a parameter is null, it keeps the existing value:

```dart
AppState copy({String? name, int? age}) =>
    AppState(
      name: name ?? this.name,
      age: age ?? this.age,
    );
```

You can also add convenience methods:

```dart
AppState withName(String name) => copy(name: name);
AppState withAge(int age) => copy(age: age);
```

## Nested/Composite State

For complex applications, compose multiple state classes within a single `AppState`:

```dart
class AppState {
  final TodoList todoList;
  final User user;
  final Settings settings;

  AppState({
    required this.todoList,
    required this.user,
    required this.settings,
  });

  static AppState initialState() => AppState(
    todoList: TodoList.initialState(),
    user: User.initialState(),
    settings: Settings.initialState(),
  );

  AppState copy({
    TodoList? todoList,
    User? user,
    Settings? settings,
  }) =>
      AppState(
        todoList: todoList ?? this.todoList,
        user: user ?? this.user,
        settings: settings ?? this.settings,
      );
}
```

Each nested class follows the same pattern:

```dart
class User {
  final String name;
  final String email;

  User({required this.name, required this.email});

  static User initialState() => User(name: "", email: "");

  User copy({String? name, String? email}) =>
      User(
        name: name ?? this.name,
        email: email ?? this.email,
      );
}
```

## Updating Nested State in Actions

```dart
class UpdateUserName extends ReduxAction<AppState> {
  final String name;
  UpdateUserName(this.name);

  @override
  AppState reduce() {
    var newUser = state.user.copy(name: name);
    return state.copy(user: newUser);
  }
}
```

## Using fast_immutable_collections

For lists, sets, and maps, use the `fast_immutable_collections` package (by the same author as AsyncRedux):

```yaml
dependencies:
  fast_immutable_collections: ^10.0.0
```

### IList Example

Use `Iterable` in constructors and copy methods, with `IList.orNull()` for conversion. This lets callers pass any iterable (List, Set, IList) without manual conversion:

```dart
import 'package:fast_immutable_collections/fast_immutable_collections.dart';

class AppState {
  final IList<Todo> todos;

  AppState({
    Iterable<Todo>? todos,
  }) : todos = IList.orNull(todos) ?? const IList.empty();

  static AppState initialState() => AppState();

  AppState copy({Iterable<Todo>? todos}) =>
      AppState(todos: IList.orNull(todos) ?? this.todos);

  // Convenience methods with business logic
  AppState addTodo(Todo todo) => copy(todos: todos.add(todo));
  AppState removeTodo(Todo todo) => copy(todos: todos.remove(todo));
  AppState toggleTodo(int index) => copy(
    todos: todos.replace(index, todos[index].copy(done: !todos[index].done)),
  );
}

// Flexible usage:
var state = AppState();                           // Empty list
var state = AppState(todos: [todo1, todo2]);      // List works
var state = AppState(todos: {todo1, todo2});      // Set works
var state = AppState(todos: existingIList);       // IList reused (no copy)
```

### IMap Example

Use `Map` in constructors and copy methods, with `IMap.orNull()` for conversion:

```dart
class AppState {
  final IMap<String, User> usersById;

  AppState({
    Map<String, User>? usersById,
  }) : usersById = IMap.orNull(usersById) ?? const IMap.empty();

  static AppState initialState() => AppState();

  AppState copy({Map<String, User>? usersById}) =>
      AppState(usersById: IMap.orNull(usersById) ?? this.usersById);

  AppState addUser(User user) => copy(usersById: usersById.add(user.id, user));
  AppState removeUser(String id) => copy(usersById: usersById.remove(id));
}
```

### ISet Example

Use `Iterable` in constructors and copy methods, with `ISet.orNull()` for conversion:

```dart
class AppState {
  final ISet<String> selectedIds;

  AppState({
    Iterable<String>? selectedIds,
  }) : selectedIds = ISet.orNull(selectedIds) ?? const ISet.empty();

  static AppState initialState() => AppState();

  AppState copy({Iterable<String>? selectedIds}) =>
      AppState(selectedIds: ISet.orNull(selectedIds) ?? this.selectedIds);

  AppState toggleSelection(String id) => copy(
    selectedIds: selectedIds.contains(id)
        ? selectedIds.remove(id)
        : selectedIds.add(id),
  );
}
```

## Events in State

For one-time UI interactions (scrolling, text field changes), use `Evt`:

```dart
class AppState {
  final Evt clearTextEvt;
  final Evt<String> changeTextEvt;

  AppState({
    required this.clearTextEvt,
    required this.changeTextEvt,
  });

  static AppState initialState() => AppState(
    clearTextEvt: Evt.spent(),
    changeTextEvt: Evt<String>.spent(),
  );

  AppState copy({
    Evt? clearTextEvt,
    Evt<String>? changeTextEvt,
  }) =>
      AppState(
        clearTextEvt: clearTextEvt ?? this.clearTextEvt,
        changeTextEvt: changeTextEvt ?? this.changeTextEvt,
      );
}
```

Events are initialized as "spent" and become active when replaced with new instances in actions.

## Business Logic in State Classes

AsyncRedux recommends placing business logic in state classes, not in actions or widgets:

```dart
class TodoList {
  final IList<Todo> items;

  TodoList({required this.items});

  // Business logic methods
  int get completedCount => items.where((t) => t.done).length;
  int get pendingCount => items.length - completedCount;
  double get completionRate => items.isEmpty ? 0 : completedCount / items.length;

  IList<Todo> get completed => items.where((t) => t.done).toIList();
  IList<Todo> get pending => items.where((t) => !t.done).toIList();

  TodoList addTodo(Todo todo) => TodoList(items: items.add(todo));
  TodoList removeTodo(Todo todo) => TodoList(items: items.remove(todo));
}
```

Actions become simple orchestrators:

```dart
class AddTodo extends ReduxAction<AppState> {
  final Todo todo;
  AddTodo(this.todo);

  @override
  AppState reduce() => state.copy(
    todoList: state.todoList.addTodo(todo),
  );
}
```

## State Access in Actions

Actions access state through getters:

- **`state`** - Current state (updates after each `await` in async actions)
- **`initialState`** - State when the action was first dispatched (never changes)

```dart
class MyAction extends ReduxAction<AppState> {
  @override
  Future<AppState?> reduce() async {
    var originalValue = initialState.counter; // Preserved
    await someAsyncWork();
    var currentValue = state.counter; // May h
Download .txt
gitextract_bzwe_hyt/

├── .claude/
│   ├── settings.local.json
│   └── skills/
│       ├── asyncredux-abort-dispatch/
│       │   └── SKILL.md
│       ├── asyncredux-action-status/
│       │   └── SKILL.md
│       ├── asyncredux-actions-no-state-change/
│       │   └── SKILL.md
│       ├── asyncredux-async-actions/
│       │   └── SKILL.md
│       ├── asyncredux-base-action/
│       │   └── SKILL.md
│       ├── asyncredux-before-after/
│       │   └── SKILL.md
│       ├── asyncredux-check-internet-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-connector-pattern/
│       │   └── SKILL.md
│       ├── asyncredux-debounce-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-debugging/
│       │   └── SKILL.md
│       ├── asyncredux-dependency-injection/
│       │   └── SKILL.md
│       ├── asyncredux-dispatching-actions/
│       │   └── SKILL.md
│       ├── asyncredux-error-handling/
│       │   └── SKILL.md
│       ├── asyncredux-events/
│       │   └── SKILL.md
│       ├── asyncredux-flutter-hooks/
│       │   └── SKILL.md
│       ├── asyncredux-navigation/
│       │   └── SKILL.md
│       ├── asyncredux-nonreentrant-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-observers/
│       │   └── SKILL.md
│       ├── asyncredux-optimistic-update-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-persistence/
│       │   └── SKILL.md
│       ├── asyncredux-provider-integration/
│       │   └── SKILL.md
│       ├── asyncredux-retry-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-selectors/
│       │   └── SKILL.md
│       ├── asyncredux-setup/
│       │   └── SKILL.md
│       ├── asyncredux-state-access/
│       │   └── SKILL.md
│       ├── asyncredux-state-design/
│       │   └── SKILL.md
│       ├── asyncredux-streams-timers/
│       │   └── SKILL.md
│       ├── asyncredux-sync-actions/
│       │   └── SKILL.md
│       ├── asyncredux-testing-basics/
│       │   └── SKILL.md
│       ├── asyncredux-testing-view-models/
│       │   └── SKILL.md
│       ├── asyncredux-testing-wait-methods/
│       │   └── SKILL.md
│       ├── asyncredux-throttle-mixin/
│       │   └── SKILL.md
│       ├── asyncredux-undo-redo/
│       │   └── SKILL.md
│       ├── asyncredux-user-exceptions/
│       │   └── SKILL.md
│       ├── asyncredux-wait-condition/
│       │   └── SKILL.md
│       └── asyncredux-wait-fail-succeed/
│           └── SKILL.md
├── .github/
│   ├── copilot-instructions.md
│   └── workflows/
│       └── test.yaml
├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── context_select_patterns.md
├── example/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── analysis_options.yaml
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle.kts
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   └── AndroidManifest.xml
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── com/
│   │   │       │   │       └── example/
│   │   │       │   │           └── example/
│   │   │       │   │               └── MainActivity.kt
│   │   │       │   └── res/
│   │   │       │       ├── drawable/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── drawable-v21/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── values/
│   │   │       │       │   └── styles.xml
│   │   │       │       └── values-night/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle.kts
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   └── settings.gradle.kts
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── LaunchImage.imageset/
│   │   │   │       ├── Contents.json
│   │   │   │       └── README.md
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── Info.plist
│   │   │   └── Runner-Bridging-Header.h
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   ├── Runner.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   └── xcshareddata/
│   │   │       ├── IDEWorkspaceChecks.plist
│   │   │       └── WorkspaceSettings.xcsettings
│   │   └── RunnerTests/
│   │       └── RunnerTests.swift
│   ├── lib/
│   │   ├── main.dart
│   │   ├── main_before_and_after.dart
│   │   ├── main_dependency_injection.dart
│   │   ├── main_event.dart
│   │   ├── main_event_2.dart
│   │   ├── main_infinite_scroll.dart
│   │   ├── main_is_waiting_works_when_multiple_actions.dart
│   │   ├── main_navigate.dart
│   │   ├── main_optimistic_command.dart
│   │   ├── main_optimistic_sync.dart
│   │   ├── main_optimistic_sync_with_push.dart
│   │   ├── main_polling.dart
│   │   ├── main_select.dart
│   │   ├── main_select_2.dart
│   │   ├── main_show_error_dialog.dart
│   │   ├── main_show_spinner.dart
│   │   ├── main_wait_action_advanced_1.dart
│   │   ├── main_wait_action_advanced_2.dart
│   │   ├── main_wait_action_simple.dart
│   │   └── store_connector_examples/
│   │       ├── README.md
│   │       ├── main_async__store_connector.dart
│   │       ├── main_async_base_factory__store_connector.dart.dart
│   │       ├── main_environment__store_connector.dart
│   │       ├── main_event__store_connector.dart
│   │       ├── main_extension_vs_store_connector.dart
│   │       ├── main_infinite_scroll__store_connector.dart
│   │       ├── main_is_waiting_works_when_multiple_actions__store_connector.dart
│   │       ├── main_is_waiting_works_when_state_unchanged__store_connector.dart
│   │       ├── main_navigate__store_connector.dart
│   │       ├── main_null_viewmodel__connector.dart
│   │       ├── main_should_update_model__store_connector.dart
│   │       ├── main_spinner__store_connector.dart
│   │       ├── main_static_view_model__store_connector.dart
│   │       ├── main_sync__store_connector.dart
│   │       ├── main_wait_action_advanced_1__store_connector.dart
│   │       ├── main_wait_action_advanced_2__store_connector.dart
│   │       └── main_wait_action_simple__store_connector.dart
│   ├── pubspec.yaml
│   ├── web/
│   │   ├── index.html
│   │   └── manifest.json
│   └── windows/
│       ├── .gitignore
│       ├── CMakeLists.txt
│       ├── flutter/
│       │   ├── CMakeLists.txt
│       │   ├── generated_plugin_registrant.cc
│       │   ├── generated_plugin_registrant.h
│       │   └── generated_plugins.cmake
│       └── runner/
│           ├── CMakeLists.txt
│           ├── Runner.rc
│           ├── flutter_window.cpp
│           ├── flutter_window.h
│           ├── main.cpp
│           ├── resource.h
│           ├── runner.exe.manifest
│           ├── utils.cpp
│           ├── utils.h
│           ├── win32_window.cpp
│           └── win32_window.h
├── lib/
│   ├── async_redux.dart
│   ├── local_json_persist.dart
│   ├── local_persist.dart
│   └── src/
│       ├── action_mixins.dart
│       ├── action_observer.dart
│       ├── advanced_user_exception.dart
│       ├── cache.dart
│       ├── cloud_sync.dart
│       ├── connection_exception.dart
│       ├── connector_tester.dart
│       ├── error_observer.dart
│       ├── event_redux.dart
│       ├── global_wrap_error.dart
│       ├── local_json_persist.dart
│       ├── local_persist.dart
│       ├── log.dart
│       ├── mock_build_context.dart
│       ├── mock_store.dart
│       ├── model_observer.dart
│       ├── navigate_action.dart
│       ├── persistor.dart
│       ├── process_persistence.dart
│       ├── redux_action.dart
│       ├── show_dialog_super.dart
│       ├── state_observer.dart
│       ├── store.dart
│       ├── store_exception.dart
│       ├── store_provider_and_connector.dart
│       ├── store_tester.dart
│       ├── test_info.dart
│       ├── user_exception_dialog.dart
│       ├── view_model.dart
│       ├── wait.dart
│       ├── wait_action.dart
│       └── wrap_reduce.dart
├── mixin_compatibility.md
├── pubspec.yaml
└── test/
    ├── abort_dispatch_test.dart
    ├── action_initial_state_test.dart
    ├── action_status_test.dart
    ├── action_to_string_test.dart
    ├── action_wrap_reduce2_test.dart
    ├── action_wrap_reduce_test.dart
    ├── after_throws_test.dart
    ├── before_reduce_after_order_test.dart
    ├── before_throwing_errors_test.dart
    ├── cache_test.dart
    ├── check_internet_mixin_test.dart
    ├── context_environment_test.dart
    ├── context_event_test.dart
    ├── context_select_advanced_test.dart
    ├── context_select_test.dart
    ├── context_state_test.dart
    ├── debounce_mixin_test.dart
    ├── dispatch_and_wait_all_actions_test.dart
    ├── dispatch_and_wait_test.dart
    ├── dispatch_sync_test.dart
    ├── dispatch_test.dart
    ├── event_redux_test.dart
    ├── failed_action_test.dart
    ├── fresh_mixin_test.dart
    ├── local_json_persist_test.dart
    ├── local_persist_test.dart
    ├── mock_build_context_test.dart
    ├── mock_store_test.dart
    ├── model_observer_test.dart
    ├── navigate_action_test.dart
    ├── non_reentrant_test.dart
    ├── optimistic_command_mixin_test.dart
    ├── optimistic_sync_test.dart
    ├── optimistic_sync_with_push_test.dart
    ├── persistence_test.dart
    ├── polling_mixin_test.dart
    ├── props_test.dart
    ├── reducer_future_or_test.dart
    ├── retry_mixin_test.dart
    ├── server_push_init_test.dart
    ├── server_push_test.dart
    ├── store_connector_test.dart
    ├── store_observer_test.dart
    ├── store_provider_test.dart
    ├── store_tester_test.dart
    ├── store_wait_action_test.dart
    ├── store_wrap_reduce_test.dart
    ├── sync_async_test.dart
    ├── test_utils.dart
    ├── throttle_mixin_test.dart
    ├── user_exception_test.dart
    ├── view_model_test.dart
    └── wait_action_test.dart
Download .txt
Showing preview only (214K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2771 symbols across 127 files)

FILE: example/lib/main.dart
  function main (line 15) | void main()
  class MyApp (line 20) | class MyApp extends StatelessWidget {
    method build (line 22) | Widget build(BuildContext context)
  class IncrementAction (line 31) | class IncrementAction extends ReduxAction<int> {
    method reduce (line 37) | int reduce()
  class MyHomePage (line 42) | class MyHomePage extends StatelessWidget {
    method build (line 46) | Widget build(BuildContext context)
  function read (line 77) | int read()
  function select (line 79) | R select<R>(R Function(int state) selector)

FILE: example/lib/main_before_and_after.dart
  function main (line 23) | void main()
  class AppState (line 30) | @immutable
    method copy (line 42) | AppState copy({int? counter, String? description, bool? waiting})
    method initialState (line 48) | AppState initialState()
  class MyApp (line 65) | class MyApp extends StatelessWidget {
    method build (line 67) | Widget build(BuildContext context)
  class IncrementAndGetDescriptionAction (line 76) | class IncrementAndGetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 81) | Future<AppState> reduce()
    method before (line 99) | void before()
    method after (line 105) | void after()
  class BarrierAction (line 108) | class BarrierAction extends ReduxAction<AppState> {
    method reduce (line 114) | AppState reduce()
  class IncrementAction (line 120) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 127) | AppState reduce()
  class MyHomePage (line 130) | class MyHomePage extends StatelessWidget {
    method build (line 134) | Widget build(BuildContext context)
  function read (line 171) | AppState read()
  function select (line 173) | R select<R>(R Function(AppState state) selector)
  function event (line 176) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_dependency_injection.dart
  function main (line 23) | void main()
  type Environment (line 34) | enum Environment {
  class Dependencies (line 49) | abstract class Dependencies {
    method limit (line 65) | int limit(int value)
  class DependenciesProduction (line 69) | class DependenciesProduction implements Dependencies {
    method limit (line 71) | int limit(int value)
  class DependenciesStaging (line 75) | class DependenciesStaging implements Dependencies {
    method limit (line 77) | int limit(int value)
  class DependenciesTesting (line 81) | class DependenciesTesting implements Dependencies {
    method limit (line 83) | int limit(int value)
  class Action (line 87) | abstract class Action extends ReduxAction<int> {
  class MyApp (line 91) | class MyApp extends StatelessWidget {
    method build (line 93) | Widget build(BuildContext context)
  class IncrementAction (line 104) | class IncrementAction extends Action {
    method reduce (line 110) | int reduce()
  class MyHomePage (line 117) | class MyHomePage extends StatelessWidget {
    method build (line 119) | Widget build(BuildContext context)
  function read (line 153) | int read()
  function select (line 155) | R select<R>(R Function(int state) selector)
  function event (line 157) | R? event<R>(Evt<R> Function(int state) selector)

FILE: example/lib/main_event.dart
  function main (line 24) | void main()
  class AppState (line 31) | @immutable
    method copy (line 45) | AppState copy({
    method initialState (line 58) | AppState initialState()
  class MyApp (line 77) | class MyApp extends StatelessWidget {
    method build (line 79) | Widget build(BuildContext context)
  class ClearTextAction (line 88) | class ClearTextAction extends ReduxAction<AppState> {
    method reduce (line 90) | AppState reduce()
  class BarrierAction (line 94) | abstract class BarrierAction extends ReduxAction<AppState> {
    method before (line 96) | void before()
    method after (line 99) | void after()
  class _WaitAction (line 102) | class _WaitAction extends ReduxAction<AppState> {
    method reduce (line 108) | AppState reduce()
  class ChangeTextAction (line 113) | class ChangeTextAction extends BarrierAction {
    method reduce (line 115) | Future<AppState> reduce()
  class MyHomePage (line 131) | class MyHomePage extends StatefulWidget {
    method createState (line 135) | _MyHomePageState createState()
  class _MyHomePageState (line 138) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 142) | void initState()
    method build (line 148) | Widget build(BuildContext context)
  function read (line 193) | AppState read()
  function select (line 195) | R select<R>(R Function(AppState state) selector)
  function event (line 197) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_event_2.dart
  function main (line 33) | void main()
  class AppState (line 40) | @immutable
    method copy (line 54) | AppState copy({
    method initialState (line 67) | AppState initialState()
  class MyApp (line 86) | class MyApp extends StatelessWidget {
    method build (line 88) | Widget build(BuildContext context)
  class ClearTextAction (line 97) | class ClearTextAction extends ReduxAction<AppState> {
    method reduce (line 99) | AppState reduce()
  class BarrierAction (line 103) | abstract class BarrierAction extends ReduxAction<AppState> {
    method before (line 105) | void before()
    method after (line 108) | void after()
  class _WaitAction (line 111) | class _WaitAction extends ReduxAction<AppState> {
    method reduce (line 117) | AppState reduce()
  class ChangeTextAction (line 122) | class ChangeTextAction extends BarrierAction {
    method reduce (line 124) | Future<AppState> reduce()
  class MyHomePage (line 140) | class MyHomePage extends StatefulWidget {
    method createState (line 144) | _MyHomePageState createState()
  class _MyHomePageState (line 147) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 151) | void initState()
    method didChangeDependencies (line 157) | void didChangeDependencies()
    method build (line 170) | Widget build(BuildContext context)
  function read (line 207) | AppState read()
  function select (line 209) | R select<R>(R Function(AppState state) selector)
  function event (line 212) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_infinite_scroll.dart
  function main (line 24) | void main()
  class AppState (line 34) | @immutable
    method copy (line 40) | AppState copy({List<String>? numTrivia})
    method initialState (line 43) | AppState initialState()
  class MyApp (line 56) | class MyApp extends StatelessWidget {
    method build (line 58) | Widget build(BuildContext context)
  class LoadMoreAction (line 67) | class LoadMoreAction extends ReduxAction<AppState> {
    method reduce (line 69) | Future<AppState> reduce()
  class RefreshAction (line 90) | class RefreshAction extends ReduxAction<AppState> {
    method reduce (line 92) | Future<AppState> reduce()
  class MyHomePage (line 114) | class MyHomePage extends StatefulWidget {
    method createState (line 118) | _MyHomePageState createState()
  class _MyHomePageState (line 121) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 125) | void initState()
    method _scrollListener (line 134) | void _scrollListener()
    method dispose (line 146) | void dispose()
    method build (line 152) | Widget build(BuildContext context)
  function read (line 196) | AppState read()
  function select (line 198) | R select<R>(R Function(AppState state) selector)
  function event (line 201) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_is_waiting_works_when_multiple_actions.dart
  function main (line 33) | void main()
  class MyApp (line 37) | class MyApp extends StatelessWidget {
    method build (line 41) | Widget build(BuildContext context)
  class MyHomePage (line 58) | class MyHomePage extends StatelessWidget {
    method build (line 62) | Widget build(BuildContext context)
  class MyHomePageContent (line 76) | class MyHomePageContent extends StatelessWidget {
    method build (line 92) | Widget build(BuildContext context)
  class AppState (line 142) | class AppState {
    method copy (line 147) | AppState copy({int? counter})
    method toString (line 150) | String toString()
  class IncrementAction (line 155) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 157) | Future<AppState?> reduce()
  class MultiplyAction (line 163) | class MultiplyAction extends ReduxAction<AppState> {
    method reduce (line 165) | Future<AppState?> reduce()
  function read (line 175) | AppState read()
  function select (line 177) | R select<R>(R Function(AppState state) selector)
  function event (line 180) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_navigate.dart
  function main (line 8) | void main()
  class AppState (line 19) | class AppState {}
  class MyApp (line 21) | class MyApp extends StatelessWidget {
    method build (line 23) | Widget build(BuildContext context)
  class Page (line 34) | class Page extends StatelessWidget {
    method build (line 42) | Widget build(BuildContext context)
  class Page1 (line 49) | class Page1 extends StatelessWidget {
    method build (line 51) | Widget build(BuildContext context)
  class Page2 (line 60) | class Page2 extends StatelessWidget {
    method build (line 62) | Widget build(BuildContext context)

FILE: example/lib/main_optimistic_command.dart
  function main (line 42) | void main()
  class AppState (line 50) | class AppState {
    method copy (line 56) | AppState copy({bool? isLiked})
    method toString (line 59) | String toString()
  class SetLike (line 62) | class SetLike extends AppAction {
    method reduce (line 68) | AppState reduce()
    method toString (line 71) | String toString()
  class ToggleLike (line 74) | class ToggleLike extends AppAction with OptimisticCommand<AppState> {
    method optimisticValue (line 76) | Object? optimisticValue()
    method getValueFromState (line 79) | bool getValueFromState(AppState state)
    method applyValueToState (line 82) | AppState applyValueToState(AppState state, Object? value)
    method applyServerResponseToState (line 86) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method sendCommandToServer (line 92) | Future<Object?> sendCommandToServer(Object? value)
    method reloadFromServer (line 97) | Future<Object?> reloadFromServer()
    method toString (line 100) | String toString()
  class MyApp (line 103) | class MyApp extends StatelessWidget {
    method build (line 107) | Widget build(BuildContext context)
  class MyHomePage (line 120) | class MyHomePage extends StatefulWidget {
    method createState (line 124) | State<MyHomePage> createState()
  class _MyHomePageState (line 127) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 131) | void initState()
    method dispose (line 140) | void dispose()
    method build (line 146) | Widget build(BuildContext context)
  class AppAction (line 367) | abstract class AppAction extends ReduxAction<AppState> {}
  class SimulatedServer (line 377) | class SimulatedServer {
    method saveLike (line 406) | Future<bool> saveLike(bool flag)
    method reload (line 421) | Future<bool> reload()
    method simulateExternalChange (line 428) | void simulateExternalChange(bool liked)
    method _interruptibleDelay (line 434) | Future<void> _interruptibleDelay(int milliseconds)

FILE: example/lib/main_optimistic_sync.dart
  function main (line 49) | void main()
  class AppState (line 57) | class AppState {
    method copy (line 63) | AppState copy({bool? isLiked})
    method toString (line 66) | String toString()
  class SetLike (line 69) | class SetLike extends AppAction {
    method reduce (line 75) | AppState reduce()
    method toString (line 78) | String toString()
  class ToggleLike (line 81) | class ToggleLike extends AppAction with OptimisticSync<AppState, bool> {
    method valueToApply (line 83) | bool valueToApply()
    method getValueFromState (line 86) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 89) | AppState applyOptimisticValueToState(
    method applyServerResponseToState (line 94) | AppState applyServerResponseToState(AppState state, Object? serverResp...
    method sendValueToServer (line 100) | Future<bool> sendValueToServer(Object? value)
    method onFinish (line 108) | Future<AppState?> onFinish(Object? error)
    method toString (line 126) | String toString()
  class MyApp (line 129) | class MyApp extends StatelessWidget {
    method build (line 133) | Widget build(BuildContext context)
  class MyHomePage (line 148) | class MyHomePage extends StatefulWidget {
    method createState (line 152) | State<MyHomePage> createState()
  class _MyHomePageState (line 155) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 159) | void initState()
    method dispose (line 168) | void dispose()
    method build (line 174) | Widget build(BuildContext context)
  class AppAction (line 376) | abstract class AppAction extends ReduxAction<AppState> {}
  class SimulatedServer (line 386) | class SimulatedServer {
    method saveLike (line 415) | Future<bool> saveLike(bool flag)
    method reload (line 430) | Future<bool> reload()
    method simulateExternalChange (line 436) | void simulateExternalChange(bool liked)
    method _interruptibleDelay (line 442) | Future<void> _interruptibleDelay(int milliseconds)

FILE: example/lib/main_optimistic_sync_with_push.dart
  function main (line 64) | void main()
  class AppState (line 93) | class AppState {
    method copy (line 107) | AppState copy({bool? isLiked, IMap<String, int>? serverRevisionMap})
    method withServerRevision (line 115) | AppState withServerRevision(Object? key, int revision)
    method getServerRevision (line 123) | int getServerRevision(Object? key)
    method toJson (line 126) | Map<String, dynamic> toJson()
    method toString (line 141) | String toString()
  function _keyToString (line 147) | String _keyToString(Object? key)
  class MyPersistor (line 150) | class MyPersistor extends Persistor<AppState> {
    method readState (line 154) | Future<AppState?> readState()
    method deleteState (line 168) | Future<void> deleteState()
    method persistDifference (line 174) | Future<void> persistDifference({
  class ServerResponse (line 189) | class ServerResponse {
  class PushLikeUpdate (line 205) | class PushLikeUpdate extends AppAction with ServerPush {
    method associatedAction (line 220) | Type associatedAction()
    method pushMetadata (line 223) | PushMetadata pushMetadata()
    method applyServerPushToState (line 239) | AppState? applyServerPushToState(
    method getServerRevisionFromState (line 248) | int getServerRevisionFromState(Object? key)
    method toString (line 251) | String toString()
  class ToggleLike (line 255) | class ToggleLike extends AppAction with OptimisticSyncWithPush<AppState,...
    method valueToApply (line 260) | bool valueToApply()
    method getValueFromState (line 263) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 266) | AppState applyOptimisticValueToState(
    method applyServerResponseToState (line 273) | AppState? applyServerResponseToState(AppState state, Object? serverRes...
    method sendValueToServer (line 282) | Future<bool> sendValueToServer(
    method getServerRevisionFromState (line 306) | int getServerRevisionFromState(Object? key)
    method onFinish (line 310) | Future<AppState?> onFinish(Object? error)
    method toString (line 319) | String toString()
  class ResetAllState (line 323) | class ResetAllState extends AppAction {
    method reduce (line 325) | Future<AppState?> reduce()
  class MyApp (line 337) | class MyApp extends StatelessWidget {
    method build (line 341) | Widget build(BuildContext context)
  class MyHomePage (line 354) | class MyHomePage extends StatefulWidget {
    method createState (line 358) | State<MyHomePage> createState()
  class _MyHomePageState (line 361) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 365) | void initState()
    method dispose (line 374) | void dispose()
    method build (line 380) | Widget build(BuildContext context)
  class AppAction (line 610) | abstract class AppAction extends ReduxAction<AppState> {}
  class SimulatedServer (line 620) | class SimulatedServer {
    method saveLike (line 656) | Future<ServerResponse> saveLike(
    method reload (line 696) | Future<bool> reload()
    method push (line 702) | Future<void> push({
    method simulateExternalChange (line 718) | void simulateExternalChange(bool liked)
    method reset (line 732) | void reset()
    method _interruptibleDelay (line 742) | Future<void> _interruptibleDelay(int milliseconds)

FILE: example/lib/main_polling.dart
  function main (line 28) | void main()
  class AppState (line 37) | @immutable
    method copy (line 49) | AppState copy({double? price, int? fetchCount, bool? isPolling})
    method initialState (line 55) | AppState initialState()
  class MyApp (line 78) | class MyApp extends StatelessWidget {
    method build (line 80) | Widget build(BuildContext context)
  class PollStockPriceAction (line 98) | class PollStockPriceAction extends ReduxAction<AppState> with Polling {
    method createPollingAction (line 108) | ReduxAction<AppState> createPollingAction()
    method before (line 112) | void before()
    method reduce (line 125) | AppState reduce()
  class SetPollingFlagAction (line 139) | class SetPollingFlagAction extends ReduxAction<AppState> {
    method reduce (line 145) | AppState reduce()
  class MyHomePage (line 152) | class MyHomePage extends StatelessWidget {
    method build (line 156) | Widget build(BuildContext context)
  function read (line 285) | AppState read()
  function select (line 287) | R select<R>(R Function(AppState state) selector)

FILE: example/lib/main_select.dart
  function main (line 61) | void main()
  class AppState (line 68) | @immutable
    method copy (line 78) | AppState copy({int? counter, String? character})
    method initialState (line 83) | AppState initialState()
  class MyApp (line 97) | class MyApp extends StatelessWidget {
    method build (line 99) | Widget build(BuildContext context)
  class IncrementAndGetDescriptionAction (line 111) | class IncrementAndGetDescriptionAction extends ReduxAction<AppState>
    method reduce (line 117) | Future<AppState> reduce()
    method wrapError (line 134) | Object? wrapError(error, StackTrace stackTrace)
  class IncrementAction (line 144) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 151) | AppState reduce()
  class MyHomePage (line 157) | class MyHomePage extends StatelessWidget {
    method build (line 161) | Widget build(BuildContext context)
  class CounterWidget (line 187) | class CounterWidget extends StatelessWidget {
    method build (line 191) | Widget build(BuildContext context)
  class DescriptionWidget (line 208) | class DescriptionWidget extends StatelessWidget {
    method build (line 212) | Widget build(BuildContext context)
  class LoadingStatusWidget (line 225) | class LoadingStatusWidget extends StatelessWidget {
    method build (line 229) | Widget build(BuildContext context)
  function read (line 251) | AppState read()
  function select (line 253) | R select<R>(R Function(AppState state) selector)
  function event (line 256) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_select_2.dart
  function read (line 10) | AppState read()
  function select (line 11) | R select<R>(R Function(AppState state) selector)
  function main (line 14) | void main()
  class MyApp (line 19) | class MyApp extends StatelessWidget {
    method build (line 25) | Widget build(BuildContext context)
  class MainScreen (line 38) | class MainScreen extends StatelessWidget {
    method build (line 42) | Widget build(BuildContext context)
  class ContextStateWidget (line 120) | class ContextStateWidget extends StatelessWidget {
    method build (line 124) | Widget build(BuildContext context)
  class ContextReadWidget (line 161) | class ContextReadWidget extends StatelessWidget {
    method build (line 165) | Widget build(BuildContext context)
  class SelectDateWidget (line 202) | class SelectDateWidget extends StatelessWidget {
    method build (line 206) | Widget build(BuildContext context)
  class SelectFlagWidget (line 241) | class SelectFlagWidget extends StatelessWidget {
    method build (line 245) | Widget build(BuildContext context)
  class AppState (line 277) | class AppState {
    method initialState (line 290) | AppState initialState()
    method copyWith (line 297) | AppState copyWith({
    method toString (line 312) | String toString()
  class IncrementNumberAction (line 315) | class IncrementNumberAction extends ReduxAction<AppState> {
    method reduce (line 317) | AppState reduce()
  class AddXToTextAction (line 322) | class AddXToTextAction extends ReduxAction<AppState> {
    method reduce (line 324) | AppState reduce()
  class AddDayToDateAction (line 329) | class AddDayToDateAction extends ReduxAction<AppState> {
    method reduce (line 331) | AppState reduce()
  class ToggleFlagAction (line 336) | class ToggleFlagAction extends ReduxAction<AppState> {
    method reduce (line 338) | AppState reduce()

FILE: example/lib/main_show_error_dialog.dart
  function main (line 11) | void main()
  class AppState (line 18) | @immutable
    method copy (line 24) | AppState copy({String? name})
    method initialState (line 26) | AppState initialState()
  class MyApp (line 40) | class MyApp extends StatelessWidget {
    method build (line 42) | Widget build(BuildContext context)
  class SaveUserAction (line 52) | class SaveUserAction extends ReduxAction<AppState> {
    method reduce (line 58) | AppState reduce()
    method wrapError (line 69) | Object wrapError(error, stackTrace)
  class MyHomePage (line 77) | class MyHomePage extends StatefulWidget {
    method createState (line 81) | _MyHomePageState createState()
  class _MyHomePageState (line 84) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 88) | void initState()
    method build (line 94) | Widget build(BuildContext context)
  function read (line 149) | AppState read()
  function select (line 151) | R select<R>(R Function(AppState state) selector)
  function event (line 154) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_show_spinner.dart
  function main (line 11) | void main()
  class MyApp (line 16) | class MyApp extends StatelessWidget {
    method build (line 18) | Widget build(BuildContext context)
  class HomePage (line 24) | class HomePage extends StatelessWidget {
    method build (line 30) | Widget build(BuildContext context)
  class WaitAndIncrementAction (line 58) | class WaitAndIncrementAction extends ReduxAction<AppState> {
    method reduce (line 60) | Future<AppState?> reduce()
  class CounterWidget (line 69) | class CounterWidget extends StatelessWidget {
    method build (line 71) | Widget build(BuildContext context)
  class AppState (line 85) | class AppState {
    method toString (line 95) | String toString()

FILE: example/lib/main_wait_action_advanced_1.dart
  function main (line 22) | void main()
  class AppState (line 29) | @immutable
    method copy (line 37) | AppState copy({int? counter, Map<int, String>? descriptions, Wait? wait})
    method initialState (line 44) | AppState initialState()
  class MyApp (line 61) | class MyApp extends StatelessWidget {
    method build (line 63) | Widget build(BuildContext context)
  class GetDescriptionAction (line 70) | class GetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 76) | Future<AppState> reduce()
    method before (line 94) | void before()
    method after (line 98) | void after()
  class MyItem (line 101) | class MyItem extends StatelessWidget {
    method build (line 110) | Widget build(BuildContext context)
    method _button (line 131) | MaterialButton _button(BuildContext context)
    method _indexDescription (line 138) | Text _indexDescription(String description)
    method _progressIndicator (line 141) | CircularProgressIndicator _progressIndicator()
  class MyHomePage (line 147) | class MyHomePage extends StatelessWidget {
    method build (line 151) | Widget build(BuildContext context)
  function read (line 175) | AppState read()
  function select (line 177) | R select<R>(R Function(AppState state) selector)
  function event (line 180) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_wait_action_advanced_2.dart
  function main (line 17) | void main()
  class AppState (line 24) | @immutable
    method copy (line 35) | AppState copy({int? counter, Map<int, String>? descriptions, Wait? wait})
    method initialState (line 42) | AppState initialState()
  class MyApp (line 59) | class MyApp extends StatelessWidget {
    method build (line 61) | Widget build(BuildContext context)
  class GetDescriptionAction (line 68) | class GetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 74) | Future<AppState> reduce()
    method before (line 92) | void before()
    method after (line 96) | void after()
  class MyItem (line 99) | class MyItem extends StatelessWidget {
    method build (line 108) | Widget build(BuildContext context)
    method _button (line 129) | MaterialButton _button(BuildContext context)
    method _indexDescription (line 136) | Text _indexDescription(String description)
    method _progressIndicator (line 139) | CircularProgressIndicator _progressIndicator()
  class MyHomePage (line 145) | class MyHomePage extends StatelessWidget {
    method build (line 149) | Widget build(BuildContext context)
  function read (line 173) | AppState read()
  function select (line 175) | R select<R>(R Function(AppState state) selector)
  function event (line 178) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/main_wait_action_simple.dart
  function main (line 37) | void main()
  class AppState (line 44) | @immutable
    method copy (line 57) | AppState copy({int? counter, String? description, Wait? wait})
    method initialState (line 64) | AppState initialState()
  class MyApp (line 83) | class MyApp extends StatelessWidget {
    method build (line 85) | Widget build(BuildContext context)
  function before (line 96) | void before()
  function after (line 100) | void after()
  class IncrementAndGetDescriptionAction (line 103) | class IncrementAndGetDescriptionAction extends ReduxAction<AppState>
    method reduce (line 106) | Future<AppState> reduce()
  class IncrementAction (line 120) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 126) | AppState reduce()
  class MyHomePage (line 129) | class MyHomePage extends StatelessWidget {
    method build (line 133) | Widget build(BuildContext context)
  function read (line 173) | AppState read()
  function select (line 175) | R select<R>(R Function(AppState state) selector)
  function event (line 178) | R? event<R>(Evt<R> Function(AppState state) selector)

FILE: example/lib/store_connector_examples/main_async__store_connector.dart
  function main (line 21) | void main()
  class AppState (line 28) | @immutable
    method copy (line 38) | AppState copy({int? counter, String? description})
    method initialState (line 43) | AppState initialState()
  class MyApp (line 57) | class MyApp extends StatelessWidget {
    method build (line 59) | Widget build(BuildContext context)
  class IncrementAndGetDescriptionAction (line 68) | class IncrementAndGetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 73) | Future<AppState> reduce()
  class IncrementAction (line 91) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 98) | AppState reduce()
  class MyHomePageConnector (line 102) | class MyHomePageConnector extends StatelessWidget {
    method build (line 106) | Widget build(BuildContext context)
  class Factory (line 119) | class Factory extends VmFactory<AppState, MyHomePageConnector, ViewModel> {
    method fromStore (line 123) | ViewModel fromStore()
    method _onIncrement (line 129) | void _onIncrement()
  class ViewModel (line 140) | class ViewModel extends Vm {
  class MyHomePage (line 152) | class MyHomePage extends StatelessWidget {
    method build (line 165) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_async_base_factory__store_connector.dart.dart
  function main (line 26) | void main()
  class AppState (line 33) | @immutable
    method copy (line 43) | AppState copy({int? counter, String? description})
    method initialState (line 48) | AppState initialState()
  class MyApp (line 62) | class MyApp extends StatelessWidget {
    method build (line 64) | Widget build(BuildContext context)
  class IncrementAndGetDescriptionAction (line 73) | class IncrementAndGetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 78) | Future<AppState> reduce()
  class IncrementAction (line 96) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 103) | AppState reduce()
  class MyHomePageConnector (line 107) | class MyHomePageConnector extends StatelessWidget {
    method build (line 111) | Widget build(BuildContext context)
  class BaseFactory (line 123) | abstract class BaseFactory<T extends Widget?, Model extends Vm>
  class Factory (line 129) | class Factory extends BaseFactory<MyHomePageConnector, ViewModel> {
    method fromStore (line 133) | ViewModel fromStore()
    method _onIncrement (line 139) | void _onIncrement()
  class ViewModel (line 150) | class ViewModel extends Vm {
  class MyHomePage (line 162) | class MyHomePage extends StatelessWidget {
    method build (line 175) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_environment__store_connector.dart
  function main (line 23) | void main()
  class Dependencies (line 32) | abstract class Dependencies {
    method incrementer (line 33) | int incrementer(int value, int amount)
    method limit (line 35) | int limit(int value)
  class DependenciesImpl (line 40) | class DependenciesImpl implements Dependencies {
    method incrementer (line 42) | int incrementer(int value, int amount)
    method limit (line 46) | int limit(int value)
  class Action (line 50) | abstract class Action extends ReduxAction<int> {
  class AppFactory (line 56) | abstract class AppFactory<T extends Widget?, Model extends Vm>
  class MyApp (line 63) | class MyApp extends StatelessWidget {
    method build (line 65) | Widget build(BuildContext context)
  class IncrementAction (line 73) | class IncrementAction extends Action {
    method reduce (line 79) | int reduce()
  class MyHomePageConnector (line 88) | class MyHomePageConnector extends StatelessWidget {
    method build (line 92) | Widget build(BuildContext context)
  class Factory (line 105) | class Factory extends AppFactory<MyHomePageConnector, ViewModel> {
    method fromStore (line 109) | ViewModel fromStore()
  class ViewModel (line 117) | class ViewModel extends Vm {
  class MyHomePage (line 127) | class MyHomePage extends StatelessWidget {
    method build (line 138) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_event__store_connector.dart
  function main (line 24) | void main()
  class AppState (line 31) | @immutable
    method copy (line 45) | AppState copy({
    method initialState (line 58) | AppState initialState()
  class MyApp (line 77) | class MyApp extends StatelessWidget {
    method build (line 79) | Widget build(BuildContext context)
  class ClearTextAction (line 88) | class ClearTextAction extends ReduxAction<AppState> {
    method reduce (line 90) | AppState reduce()
  class BarrierAction (line 94) | abstract class BarrierAction extends ReduxAction<AppState> {
    method before (line 96) | void before()
    method after (line 99) | void after()
  class _WaitAction (line 102) | class _WaitAction extends ReduxAction<AppState> {
    method reduce (line 108) | AppState reduce()
  class ChangeTextAction (line 113) | class ChangeTextAction extends BarrierAction {
    method reduce (line 115) | Future<AppState> reduce()
  class MyHomePageConnector (line 132) | class MyHomePageConnector extends StatelessWidget {
    method build (line 136) | Widget build(BuildContext context)
  class Factory (line 151) | class Factory extends VmFactory<AppState, MyHomePageConnector, ViewModel> {
    method fromStore (line 155) | ViewModel fromStore()
  class ViewModel (line 165) | class ViewModel extends Vm {
  class MyHomePage (line 181) | class MyHomePage extends StatefulWidget {
    method createState (line 198) | _MyHomePageState createState()
  class _MyHomePageState (line 201) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 205) | void initState()
    method didUpdateWidget (line 211) | void didUpdateWidget(MyHomePage oldWidget)
    method consumeEvents (line 216) | void consumeEvents()
    method build (line 230) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_extension_vs_store_connector.dart
  function main (line 10) | void main()
  class MyApp (line 15) | class MyApp extends StatelessWidget {
    method build (line 17) | Widget build(BuildContext context)
  class HomePage (line 23) | class HomePage extends StatelessWidget {
    method build (line 29) | Widget build(BuildContext context)
  class IncrementAction (line 51) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 53) | AppState reduce()
  class GetsStateFromStoreConnector (line 61) | class GetsStateFromStoreConnector extends StatelessWidget {
    method build (line 63) | Widget build(BuildContext context)
  class GetsStateFromBuildContextExtension (line 81) | class GetsStateFromBuildContextExtension extends StatelessWidget {
    method build (line 83) | Widget build(BuildContext context)
  class AppState (line 102) | class AppState {
    method toString (line 112) | String toString()

FILE: example/lib/store_connector_examples/main_infinite_scroll__store_connector.dart
  function main (line 22) | void main()
  class AppState (line 32) | @immutable
    method copy (line 38) | AppState copy({List<String>? numTrivia})
    method initialState (line 41) | AppState initialState()
  class MyApp (line 54) | class MyApp extends StatelessWidget {
    method build (line 56) | Widget build(BuildContext context)
  class LoadMoreAction (line 65) | class LoadMoreAction extends ReduxAction<AppState> {
    method reduce (line 67) | Future<AppState> reduce()
  class RefreshAction (line 88) | class RefreshAction extends ReduxAction<AppState> {
    method reduce (line 90) | Future<AppState> reduce()
  class MyHomePageConnector (line 110) | class MyHomePageConnector extends StatelessWidget {
    method build (line 114) | Widget build(BuildContext context)
  class Factory (line 130) | class Factory extends VmFactory<AppState, MyHomePageConnector, ViewModel> {
    method fromStore (line 134) | ViewModel fromStore()
  class ViewModel (line 145) | class ViewModel extends Vm {
  class MyHomePage (line 162) | class MyHomePage extends StatefulWidget {
    method createState (line 177) | _MyHomePageState createState()
  class _MyHomePageState (line 180) | class _MyHomePageState extends State<MyHomePage> {
    method initState (line 184) | void initState()
    method dispose (line 197) | void dispose()
    method build (line 203) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_is_waiting_works_when_multiple_actions__store_connector.dart
  function main (line 21) | void main()
  class MyApp (line 25) | class MyApp extends StatelessWidget {
    method build (line 29) | Widget build(BuildContext context)
  class MyHomePage (line 46) | class MyHomePage extends StatelessWidget {
    method build (line 62) | Widget build(BuildContext context)
  class MyHomePageContent (line 79) | class MyHomePageContent extends StatelessWidget {
    method build (line 95) | Widget build(BuildContext context)
  class AppState (line 145) | class AppState {
    method copy (line 150) | AppState copy({int? counter})
    method toString (line 153) | String toString()
  class CounterVm (line 158) | class CounterVm extends Vm {
  class CounterVmFactory (line 171) | class CounterVmFactory extends VmFactory<AppState, MyHomePage, CounterVm> {
    method fromStore (line 173) | CounterVm fromStore()
  class IncrementAction (line 181) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 183) | Future<AppState?> reduce()
  class MultiplyAction (line 189) | class MultiplyAction extends ReduxAction<AppState> {
    method reduce (line 191) | Future<AppState?> reduce()

FILE: example/lib/store_connector_examples/main_is_waiting_works_when_state_unchanged__store_connector.dart
  function main (line 9) | void main()
  class MyApp (line 13) | class MyApp extends StatelessWidget {
    method build (line 17) | Widget build(BuildContext context)
  class MyHomePage (line 34) | class MyHomePage extends StatelessWidget {
    method build (line 38) | Widget build(BuildContext context)
  class MyHomePageContent (line 54) | class MyHomePageContent extends StatelessWidget {
    method build (line 69) | Widget build(BuildContext context)
  class AppState (line 100) | class AppState {
    method copy (line 105) | AppState copy({int? counter})
    method toString (line 108) | String toString()
  class CounterVm (line 113) | class CounterVm extends Vm {
  class CounterVmFactory (line 128) | class CounterVmFactory extends VmFactory<AppState, MyHomePage, CounterVm> {
    method fromStore (line 130) | CounterVm fromStore()
  class IncrementAction (line 137) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 139) | Future<AppState?> reduce()
  class DoIncrementAction (line 146) | class DoIncrementAction extends ReduxAction<AppState> {
    method reduce (line 148) | AppState? reduce()

FILE: example/lib/store_connector_examples/main_navigate__store_connector.dart
  function main (line 8) | void main()
  class AppState (line 19) | class AppState {}
  class MyApp (line 21) | class MyApp extends StatelessWidget {
    method build (line 23) | Widget build(BuildContext context)
  class Page (line 34) | class Page extends StatelessWidget {
    method build (line 42) | Widget build(BuildContext context)
  class Page1Connector (line 49) | class Page1Connector extends StatelessWidget {
    method build (line 51) | Widget build(BuildContext context)
  class Factory1 (line 64) | class Factory1 extends VmFactory<AppState, Page1Connector, ViewModel1> {
    method fromStore (line 66) | ViewModel1 fromStore()
  class ViewModel1 (line 71) | class ViewModel1 extends Vm {
  class Page2Connector (line 77) | class Page2Connector extends StatelessWidget {
    method build (line 79) | Widget build(BuildContext context)
  class Factory2 (line 92) | class Factory2 extends VmFactory<AppState, Page1Connector, ViewModel2> {
    method fromStore (line 94) | ViewModel2 fromStore()
  class ViewModel2 (line 100) | class ViewModel2 extends Vm {

FILE: example/lib/store_connector_examples/main_null_viewmodel__connector.dart
  function main (line 16) | void main()
  class MyApp (line 21) | class MyApp extends StatelessWidget {
    method build (line 23) | Widget build(BuildContext context)
  class IncrementAction (line 30) | class IncrementAction extends ReduxAction<int> {
    method reduce (line 36) | int reduce()
  class MyHomePageConnector (line 39) | class MyHomePageConnector extends StatelessWidget {
    method build (line 43) | Widget build(BuildContext context)
  class Factory (line 66) | class Factory extends VmFactory<int, MyHomePageConnector, ViewModel> {
    method fromStore (line 71) | ViewModel? fromStore()
  class ViewModel (line 81) | class ViewModel extends Vm {
  class MyHomePage (line 91) | class MyHomePage extends StatelessWidget {
    method build (line 102) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_should_update_model__store_connector.dart
  function main (line 20) | void main()
  class MyApp (line 25) | class MyApp extends StatelessWidget {
    method build (line 27) | Widget build(BuildContext context)
  class IncrementAction (line 35) | class IncrementAction extends ReduxAction<int> {
    method reduce (line 41) | int reduce()
  class MyHomePageConnector (line 44) | class MyHomePageConnector extends StatelessWidget {
    method build (line 48) | Widget build(BuildContext context)
  class Factory (line 64) | class Factory extends VmFactory<int, MyHomePageConnector, ViewModel> {
    method fromStore (line 68) | ViewModel fromStore()
  class ViewModel (line 83) | class ViewModel extends Vm {
  class MyHomePage (line 93) | class MyHomePage extends StatelessWidget {
    method build (line 104) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_spinner__store_connector.dart
  function main (line 11) | void main()
  class MyApp (line 16) | class MyApp extends StatelessWidget {
    method build (line 18) | Widget build(BuildContext context)
  class HomePage (line 28) | class HomePage extends StatelessWidget {
    method build (line 34) | Widget build(BuildContext context)
  class _PlusButtonConnector (line 61) | class _PlusButtonConnector extends StatelessWidget {
    method build (line 63) | Widget build(BuildContext context)
  class _FailWithDialog_ButtonConnector (line 82) | class _FailWithDialog_ButtonConnector extends StatelessWidget {
    method build (line 84) | Widget build(BuildContext context)
  class _FailNoDialog_ButtonConnector (line 103) | class _FailNoDialog_ButtonConnector extends StatelessWidget {
    method build (line 105) | Widget build(BuildContext context)
  class Factory (line 124) | class Factory extends VmFactory<AppState, Widget, ViewModel> {
    method fromStore (line 128) | ViewModel fromStore()
  class ViewModel (line 137) | class ViewModel extends Vm {
  class WaitAndIncrementAction (line 148) | class WaitAndIncrementAction extends ReduxAction<AppState> {
    method reduce (line 150) | Future<AppState?> reduce()
  class FailWithDialogAction (line 160) | class FailWithDialogAction extends ReduxAction<AppState> {
    method reduce (line 162) | Future<AppState?> reduce()
  class FailNoDialogAction (line 169) | class FailNoDialogAction extends ReduxAction<AppState> {
    method reduce (line 171) | Future<AppState?> reduce()
  class CounterWidget (line 177) | class CounterWidget extends StatelessWidget {
    method build (line 179) | Widget build(BuildContext context)
  class AppState (line 191) | class AppState {
    method toString (line 201) | String toString()

FILE: example/lib/store_connector_examples/main_static_view_model__store_connector.dart
  function main (line 21) | void main()
  class MyApp (line 26) | class MyApp extends StatelessWidget {
    method build (line 28) | Widget build(BuildContext context)
  class IncrementAction (line 36) | class IncrementAction extends ReduxAction<int> {
    method reduce (line 42) | int reduce()
  class MyHomePageConnector (line 46) | class MyHomePageConnector extends StatelessWidget {
    method build (line 50) | Widget build(BuildContext context)
  class ViewModel (line 62) | class ViewModel extends Vm {
    method fromStore (line 72) | ViewModel fromStore(Store<int> store)
  class MyHomePage (line 80) | class MyHomePage extends StatelessWidget {
    method build (line 91) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_sync__store_connector.dart
  function main (line 21) | void main()
  class MyApp (line 26) | class MyApp extends StatelessWidget {
    method build (line 28) | Widget build(BuildContext context)
  class IncrementAction (line 36) | class IncrementAction extends ReduxAction<int> {
    method reduce (line 42) | int reduce()
  class MyHomePageConnector (line 50) | class MyHomePageConnector extends StatelessWidget {
    method build (line 54) | Widget build(BuildContext context)
  class Factory (line 66) | class Factory extends VmFactory<int, MyHomePageConnector, ViewModel> {
    method fromStore (line 70) | ViewModel fromStore()
  class ViewModel (line 91) | class ViewModel extends Vm {
  class MyHomePage (line 104) | class MyHomePage extends StatelessWidget {
    method build (line 115) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_wait_action_advanced_1__store_connector.dart
  function main (line 22) | void main()
  class AppState (line 29) | @immutable
    method copy (line 37) | AppState copy({int? counter, Map<int, String>? descriptions, Wait? wait})
    method initialState (line 43) | AppState initialState()
  class MyApp (line 60) | class MyApp extends StatelessWidget {
    method build (line 62) | Widget build(BuildContext context)
  class GetDescriptionAction (line 69) | class GetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 75) | Future<AppState> reduce()
    method before (line 94) | void before()
    method after (line 98) | void after()
  class MyHomePageConnector (line 102) | class MyHomePageConnector extends StatelessWidget {
    method build (line 106) | Widget build(BuildContext context)
  class PageVmFactory (line 118) | class PageVmFactory extends VmFactory<AppState, MyHomePageConnector, Pag...
    method fromStore (line 122) | PageViewModel fromStore()
  class PageViewModel (line 130) | class PageViewModel extends Vm {
  class MyItemConnector (line 141) | class MyItemConnector extends StatelessWidget {
    method build (line 152) | Widget build(BuildContext context)
  class ItemVmFactory (line 166) | class ItemVmFactory extends VmFactory<AppState, MyItemConnector, ItemVie...
    method fromStore (line 170) | ItemViewModel fromStore()
  class ItemViewModel (line 178) | class ItemViewModel extends Vm {
  class MyItem (line 188) | class MyItem extends StatelessWidget {
    method build (line 202) | Widget build(BuildContext context)
    method _button (line 215) | MaterialButton _button()
    method _indexDescription (line 222) | Text _indexDescription()
    method _progressIndicator (line 225) | CircularProgressIndicator _progressIndicator()
  class MyHomePage (line 230) | class MyHomePage extends StatelessWidget {
    method build (line 241) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_wait_action_advanced_2__store_connector.dart
  function main (line 17) | void main()
  class AppState (line 24) | @immutable
    method copy (line 35) | AppState copy({int? counter, Map<int, String>? descriptions, Wait? wait})
    method initialState (line 41) | AppState initialState()
  class MyApp (line 58) | class MyApp extends StatelessWidget {
    method build (line 60) | Widget build(BuildContext context)
  class GetDescriptionAction (line 67) | class GetDescriptionAction extends ReduxAction<AppState> {
    method reduce (line 73) | Future<AppState> reduce()
    method before (line 92) | void before()
    method after (line 96) | void after()
  class MyHomePageConnector (line 100) | class MyHomePageConnector extends StatelessWidget {
    method build (line 104) | Widget build(BuildContext context)
  class PageVmFactory (line 116) | class PageVmFactory extends VmFactory<AppState, MyHomePageConnector, Pag...
    method fromStore (line 120) | PageViewModel fromStore()
  class PageViewModel (line 128) | class PageViewModel extends Vm {
  class MyItemConnector (line 139) | class MyItemConnector extends StatelessWidget {
    method build (line 150) | Widget build(BuildContext context)
  class ItemVmFactory (line 164) | class ItemVmFactory extends VmFactory<AppState, MyItemConnector, ItemVie...
    method fromStore (line 168) | ItemViewModel fromStore()
  class ItemViewModel (line 177) | class ItemViewModel extends Vm {
  class MyItem (line 187) | class MyItem extends StatelessWidget {
    method build (line 201) | Widget build(BuildContext context)
    method _button (line 214) | MaterialButton _button()
    method _indexDescription (line 221) | Text _indexDescription()
    method _progressIndicator (line 224) | CircularProgressIndicator _progressIndicator()
  class MyHomePage (line 229) | class MyHomePage extends StatelessWidget {
    method build (line 240) | Widget build(BuildContext context)

FILE: example/lib/store_connector_examples/main_wait_action_simple__store_connector.dart
  function main (line 37) | void main()
  class AppState (line 44) | @immutable
    method copy (line 57) | AppState copy({int? counter, String? description, Wait? wait})
    method initialState (line 64) | AppState initialState()
  class MyApp (line 83) | class MyApp extends StatelessWidget {
    method build (line 85) | Widget build(BuildContext context)
  function before (line 96) | void before()
  function after (line 100) | void after()
  class IncrementAndGetDescriptionAction (line 103) | class IncrementAndGetDescriptionAction extends ReduxAction<AppState> wit...
    method reduce (line 105) | Future<AppState> reduce()
  class IncrementAction (line 119) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 125) | AppState reduce()
  class MyHomePageConnector (line 129) | class MyHomePageConnector extends StatelessWidget {
    method build (line 133) | Widget build(BuildContext context)
  class Factory (line 147) | class Factory extends VmFactory<AppState, MyHomePageConnector, ViewModel> {
    method fromStore (line 151) | ViewModel fromStore()
  class ViewModel (line 164) | class ViewModel extends Vm {
  class MyHomePage (line 178) | class MyHomePage extends StatelessWidget {
    method build (line 193) | Widget build(BuildContext context)

FILE: example/windows/flutter/generated_plugin_registrant.cc
  function RegisterPlugins (line 11) | void RegisterPlugins(flutter::PluginRegistry* registry) {

FILE: example/windows/runner/flutter_window.cpp
  function LRESULT (line 50) | LRESULT

FILE: example/windows/runner/flutter_window.h
  function class (line 12) | class FlutterWindow : public Win32Window {

FILE: example/windows/runner/main.cpp
  function wWinMain (line 8) | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,

FILE: example/windows/runner/utils.cpp
  function CreateAndAttachConsole (line 10) | void CreateAndAttachConsole() {
  function GetCommandLineArguments (line 24) | std::vector<std::string> GetCommandLineArguments() {
  function Utf8FromUtf16 (line 44) | std::string Utf8FromUtf16(const wchar_t* utf16_string) {

FILE: example/windows/runner/win32_window.cpp
  function Scale (line 36) | int Scale(int source, double scale_factor) {
  function EnableFullDpiSupportIfAvailable (line 42) | void EnableFullDpiSupportIfAvailable(HWND hwnd) {
  class WindowClassRegistrar (line 59) | class WindowClassRegistrar {
    method WindowClassRegistrar (line 64) | static WindowClassRegistrar* GetInstance() {
    method WindowClassRegistrar (line 80) | WindowClassRegistrar() = default;
  function wchar_t (line 89) | const wchar_t* WindowClassRegistrar::GetWindowClass() {
  function LRESULT (line 157) | LRESULT CALLBACK Win32Window::WndProc(HWND const window,
  function LRESULT (line 176) | LRESULT
  function Win32Window (line 236) | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
  function RECT (line 252) | RECT Win32Window::GetClientArea() {
  function HWND (line 258) | HWND Win32Window::GetHandle() {

FILE: example/windows/runner/win32_window.h
  type Size (line 21) | struct Size {

FILE: lib/src/action_mixins.dart
  function connectionException (line 64) | UserException connectionException(List<ConnectivityResult> result)
  function checkConnectivity (line 89) | Future<List<ConnectivityResult>> checkConnectivity()
  function before (line 100) | Future<void> before()
  function _cannot_combine_mixins_CheckInternet_AbortWhenNoInternet_UnlimitedRetryCheckInternet (line 110) | void
  function checkConnectivity (line 200) | Future<List<ConnectivityResult>> checkConnectivity()
  function before (line 211) | Future<void> before()
  function _cannot_combine_mixins_CheckInternet_AbortWhenNoInternet_UnlimitedRetryCheckInternet (line 220) | void
  function nonReentrantKeyParams (line 289) | Object? nonReentrantKeyParams()
  function computeNonReentrantKey (line 316) | Object computeNonReentrantKey()
  function abortDispatch (line 325) | bool abortDispatch()
  function after (line 384) | void after()
  function _cannot_combine_mixins_Fresh_Throttle_NonReentrant_UnlimitedRetryCheckInternet (line 389) | void
  function wrapReduce (line 475) | Future<St?> wrapReduce(Reducer<St> reduce)
  function nextDelay (line 513) | Duration nextDelay()
  function _cannot_combine_mixins_Debounce_Retry_UnlimitedRetryCheckInternet (line 526) | void _cannot_combine_mixins_Debounce_Retry_UnlimitedRetryCheckInternet()
  function _cannot_combine_mixins_Retry_UnlimitedRetryCheckInternet_OptimisticSync_OptimisticSyncWithPush_ServerPush (line 532) | void
  function optimisticValue (line 828) | Object? optimisticValue()
  function applyValueToState (line 839) | St applyValueToState(St state, Object? value)
  function getValueFromState (line 848) | Object? getValueFromState(St state)
  function sendCommandToServer (line 865) | Future<Object?> sendCommandToServer(Object? optimisticValue)
  function applyServerResponseToState (line 882) | St? applyServerResponseToState(St state, Object serverResponse)
  function reloadFromServer (line 893) | Future<Object?> reloadFromServer()
  function rollbackState (line 928) | St? rollbackState({
  function shouldRollback (line 948) | bool shouldRollback({
  function shouldReload (line 998) | bool shouldReload({
  function shouldApplyReload (line 1023) | bool shouldApplyReload({
  function applyReloadResultToState (line 1041) | St? applyReloadResultToState(St state, Object? reloadResult)
  function nonReentrantKeyParams (line 1063) | Object? nonReentrantKeyParams()
  function computeNonReentrantKey (line 1090) | Object computeNonReentrantKey()
  function reduce (line 1093) | Future<St?> reduce()
  function _sendCommandWithRetryIfNeeded (line 1196) | Future<Object?> _sendCommandWithRetryIfNeeded(
  function abortDispatch (line 1234) | bool abortDispatch()
  function after (line 1256) | void after()
  function _cannot_combine_mixins_OptimisticCommand (line 1264) | void _cannot_combine_mixins_OptimisticCommand()
  function _cannot_combine_mixins_UnlimitedRetryCheckInternet_OptimisticCommand_OptimisticSync_OptimisticSyncWithPush_ServerPush (line 1273) | void
  function lockBuilder (line 1439) | Object? lockBuilder()
  function removeLock (line 1448) | void removeLock()
  function removeAllLocks (line 1452) | void removeAllLocks()
  function abortDispatch (line 1455) | bool abortDispatch()
  function _expiringLockFrom (line 1483) | DateTime _expiringLockFrom(DateTime now)
  function _prune (line 1487) | void _prune()
  function after (line 1493) | void after()
  function _cannot_combine_mixins_Fresh_Throttle_NonReentrant_UnlimitedRetryCheckInternet (line 1498) | void
  function lockBuilder (line 1576) | Object? lockBuilder()
  function removeAllLocks (line 1588) | void removeAllLocks()
  function wrapReduce (line 1591) | Future<St?> wrapReduce(Reducer<St> reduce)
  function _cannot_combine_mixins_Debounce_Retry_UnlimitedRetryCheckInternet (line 1617) | void _cannot_combine_mixins_Debounce_Retry_UnlimitedRetryCheckInternet()
  function abortDispatch (line 1664) | bool abortDispatch()
  function printRetries (line 1712) | void printRetries(String message)
  function wrapReduce (line 1715) | Future<St?> wrapReduce(Reducer<St> reduce)
  function nextDelay (line 1763) | Duration nextDelay({required bool hasInternet})
  function checkConnectivity (line 1803) | Future<List<ConnectivityResult>> checkConnectivity()
  function _cannot_combine_mixins_Fresh_Throttle_NonReentrant_UnlimitedRetryCheckInternet (line 1812) | void
  function _cannot_combine_mixins_CheckInternet_AbortWhenNoInternet_UnlimitedRetryCheckInternet (line 1819) | void
  function _cannot_combine_mixins_Debounce_Retry_UnlimitedRetryCheckInternet (line 1825) | void _cannot_combine_mixins_Debounce_Retry_UnlimitedRetryCheckInternet()
  function _cannot_combine_mixins_UnlimitedRetryCheckInternet_OptimisticCommand_OptimisticSync_OptimisticSyncWithPush_ServerPush (line 1831) | void
  function freshKeyParams (line 2114) | Object? freshKeyParams()
  function computeFreshKey (line 2173) | Object computeFreshKey()
  function removeKey (line 2185) | void removeKey()
  function removeAllKeys (line 2195) | void removeAllKeys()
  function abortDispatch (line 2206) | bool abortDispatch()
  function _cannot_combine_mixins_Fresh_Throttle_NonReentrant_UnlimitedRetryCheckInternet (line 2242) | void
  function _expiringKeyFrom (line 2250) | DateTime _expiringKeyFrom(DateTime now)
  function _prune (line 2254) | void _prune()
  function after (line 2260) | void after()
  function _incompatible (line 2282) | void _incompatible<T1, T2>(Object instance)
  function optimisticSyncKeyParams (line 2543) | Object? optimisticSyncKeyParams()
  function computeOptimisticSyncKey (line 2548) | Object computeOptimisticSyncKey()
  function valueToApply (line 2569) | T valueToApply()
  function applyOptimisticValueToState (line 2581) | St applyOptimisticValueToState(St state, T optimisticValue)
  function applyServerResponseToState (line 2598) | St? applyServerResponseToState(St state, Object serverResponse)
  function getValueFromState (line 2613) | T getValueFromState(St state)
  function sendValueToServer (line 2643) | Future<Object?> sendValueToServer(Object? optimisticValue)
  function onFinish (line 2723) | Future<St?> onFinish(Object? error)
  function reduce (line 2726) | Future<St?> reduce()
  function _sendAndFollowUp (line 2764) | Future<void> _sendAndFollowUp(Object? key, T sentValue)
  function _callOnFinish (line 2822) | Future<void> _callOnFinish(Object? error)
  function ifShouldSendAnotherRequest (line 2843) | bool ifShouldSendAnotherRequest({
  function _cannot_combine_mixins_OptimisticSync (line 2867) | void _cannot_combine_mixins_OptimisticSync()
  function _cannot_combine_mixins_UnlimitedRetryCheckInternet_OptimisticCommand_OptimisticSync_OptimisticSyncWithPush_ServerPush (line 2876) | void
  function optimisticSyncKeyParams (line 3091) | Object? optimisticSyncKeyParams()
  function computeOptimisticSyncKey (line 3096) | Object computeOptimisticSyncKey()
  function valueToApply (line 3117) | T valueToApply()
  function applyOptimisticValueToState (line 3129) | St applyOptimisticValueToState(St state, T optimisticValue)
  function applyServerResponseToState (line 3146) | St? applyServerResponseToState(St state, Object serverResponse)
  function getValueFromState (line 3155) | T getValueFromState(St state)
  function sendValueToServer (line 3208) | Future<Object?> sendValueToServer(
  function _localRevision (line 3243) | int _localRevision()
  function getServerRevisionFromState (line 3281) | int getServerRevisionFromState(Object? key)
  function informServerRevision (line 3328) | void informServerRevision(int revision)
  function informServerRevisionAsDateTime (line 3354) | void informServerRevisionAsDateTime(DateTime revision)
  function onFinish (line 3401) | Future<St?> onFinish(Object? error)
  function reduce (line 3404) | Future<St?> reduce()
  function _getEntry (line 3536) | OptimisticSyncWithPushRevisionEntry _getEntry(Object? key)
  function _cannot_combine_mixins_OptimisticSyncWithPush (line 3551) | void _cannot_combine_mixins_OptimisticSyncWithPush()
  function _cannot_combine_mixins_UnlimitedRetryCheckInternet_OptimisticCommand_OptimisticSync_OptimisticSyncWithPush_ServerPush (line 3560) | void
  type PushMetadata (line 3570) | typedef PushMetadata = ({
  function associatedAction (line 3588) | Type associatedAction()
  function optimisticSyncKeyParams (line 3592) | Object? optimisticSyncKeyParams()
  function computeOptimisticSyncKey (line 3596) | Object computeOptimisticSyncKey()
  function pushMetadata (line 3622) | PushMetadata pushMetadata()
  function applyServerPushToState (line 3630) | St? applyServerPushToState(St state, Object? key, int serverRevision)
  function getServerRevisionFromState (line 3635) | int getServerRevisionFromState(Object? key)
  function reduce (line 3638) | St? reduce()
  function _cannot_combine_mixins_ServerPush (line 3710) | void _cannot_combine_mixins_ServerPush()
  function _cannot_combine_mixins_UnlimitedRetryCheckInternet_OptimisticCommand_OptimisticSync_OptimisticSyncWithPush_ServerPush (line 3721) | void
  type Poll (line 3730) | enum Poll {
  function createPollingAction (line 3992) | ReduxAction<St> createPollingAction()
  function pollingKeyParams (line 4009) | Object? pollingKeyParams()
  function computePollingKey (line 4024) | Object computePollingKey()
  function wrapReduce (line 4029) | Future<St?> wrapReduce(Reducer<St> reduce)
  function _scheduleNext (line 4058) | void _scheduleNext(Object key)
  function _cannot_combine_mixins_Polling (line 4067) | void _cannot_combine_mixins_Polling()

FILE: lib/src/action_observer.dart
  class ActionObserver (line 10) | abstract class ActionObserver<St> {
    method observe (line 13) | void observe(
  class ConsoleActionObserver (line 53) | class ConsoleActionObserver<St> extends ActionObserver<St> {
    method observe (line 62) | void observe(ReduxAction<St> action, int dispatchCount, {required bool...

FILE: lib/src/advanced_user_exception.dart
  class AdvancedUserException (line 38) | @immutable
    method addReason (line 113) | UserException addReason(String? reason)
    method mergedWith (line 138) | UserException mergedWith(UserException? anotherUserException)
    method withDialog (line 162) | UserException withDialog(bool ifOpenDialog)
    method withErrorText (line 177) | UserException withErrorText(String? newErrorText)
    method toString (line 190) | String toString()
  function addCause (line 254) | UserException addCause(Object? cause)
  function addCallbacks (line 295) | UserException addCallbacks({
  function addProps (line 352) | UserException addProps(Map<String, dynamic>? moreProps)
  class UserExceptionAction (line 380) | class UserExceptionAction<St> extends ReduxAction<St> {
    method reduce (line 443) | Future<St> reduce()

FILE: lib/src/cache.dart
  function cache1state (line 20) | Result Function() Function(State1) cache1state<Result, State1>(
  function cache1state_1param (line 44) | Result Function(Param1) Function(State1)
  function cache1state_2params (line 71) | Result Function(Param1, Param2) Function(State1)
  function cache2states (line 90) | Result Function() Function(State1, State2) cache2states<Result, State1, ...
  function cache2states_1param (line 114) | Result Function(Param1) Function(State1, State2)
  function cache2states_2params (line 143) | Result Function(Param1, Param2) Function(State1, State2)
  function cache2states_3params (line 172) | Result Function(Param1, Param2, Param3) Function(State1, State2)
  function cache3states (line 191) | Result Function() Function(State1, State2, State3)
  function cache1state_0params_x (line 201) | Result Function() Function(State1, Extra)
  function cache2states_0params_x (line 211) | Result Function() Function(State1, State2, Extra)
  function cache3states_0params_x (line 221) | Result Function() Function(State1, State2, State3, Extra)

FILE: lib/src/cloud_sync.dart
  class CloudSync (line 8) | abstract class CloudSync<St> extends Persistor<St> {}

FILE: lib/src/connection_exception.dart
  class ConnectionException (line 8) | class ConnectionException extends AdvancedUserException {
    method noConnectivityWithRetry (line 18) | ConnectionException noConnectivityWithRetry(
    method addReason (line 51) | UserException addReason(String? reason)
    method mergedWith (line 56) | UserException mergedWith(UserException? anotherUserException)
    method withErrorText (line 61) | UserException withErrorText(String? newErrorText)
    method withDialog (line 69) | UserException withDialog(bool ifOpenDialog)

FILE: lib/src/connector_tester.dart
  class ConnectorTester (line 32) | class ConnectorTester<St, Model> {
    method runOnInit (line 45) | void runOnInit()
    method runOnDispose (line 50) | void runOnDispose()
    method runOnWillChange (line 55) | void runOnWillChange(

FILE: lib/src/error_observer.dart
  class ErrorObserver (line 23) | @Deprecated('Use GlobalErrorObserver instead. This will be removed.')
    method observe (line 40) | bool observe(
  class DevelopmentErrorObserver (line 57) | @Deprecated('Use GlobalErrorObserverForDevelopment instead. This will be...
    method observe (line 60) | bool observe(
  class SwallowErrorObserver (line 83) | @Deprecated('Use SwallowGlobalErrorObserver instead. This will be remove...
    method observe (line 86) | bool observe(

FILE: lib/src/event_redux.dart
  type Evt (line 16) | typedef Evt<T> = Event<T>;
  class Event (line 115) | class Event<T> {
    method consume (line 146) | T? consume()
    method toString (line 177) | String toString()
    method map (line 198) | Event<T> map<T, V>(Event<V> evt, T? Function(V?) mapFunction)
    method consumeFrom (line 233) | T? consumeFrom<T>(Event<T> evt1, Event<T> evt2)
  class EventMultiple (line 319) | class EventMultiple<T> extends Event<T> {
    method consume (line 337) | T? consume()
  class MappedEvent (line 369) | class MappedEvent<V, T> extends Event<T> {
    method consume (line 380) | T? consume()
  class EvtState (line 426) | @immutable

FILE: lib/src/global_wrap_error.dart
  class GlobalWrapError (line 49) | @Deprecated('Use GlobalErrorObserver instead. Check the documentation fo...
    method wrap (line 51) | Object? wrap(
  class GlobalWrapErrorDummy (line 59) | @Deprecated('Use GlobalErrorObserver instead. This will be removed.')
    method wrap (line 62) | Object? wrap(error, stackTrace, action)

FILE: lib/src/local_json_persist.dart
  class LocalJsonPersist (line 48) | class LocalJsonPersist {
    method useAppDocumentsDir (line 128) | Future<void> useAppDocumentsDir()
    method useAppCacheDir (line 132) | Future<void> useAppCacheDir()
    method useAppDownloadsDir (line 136) | Future<void> useAppDownloadsDir()
    method useCustomBaseDirectory (line 141) | Future<void> useCustomBaseDirectory({
    method save (line 150) | Future<File> save(Object? simpleObj)
    method load (line 169) | Future<Object?> load()
    method loadConverting (line 212) | Future<Object?> loadConverting({required bool isList})
    method _readsFromJsonSequenceDbFile (line 237) | Future<Object?> _readsFromJsonSequenceDbFile(bool isList)
    method loadAsObj (line 284) | Future<Map<String, dynamic>?> loadAsObj()
    method loadAsObjConverting (line 294) | Future<Map<String, dynamic>?> loadAsObjConverting()
    method delete (line 305) | Future<bool> delete()
    method length (line 324) | Future<int> length()
    method exists (line 342) | Future<bool> exists()
    method _checkIfFileSystemIsTheSame (line 349) | void _checkIfFileSystemIsTheSame()
    method file (line 354) | Future<File> file()
    method simpleObjsToString (line 369) | String? simpleObjsToString(List<Object?>? simpleObjs)
    method pathName (line 374) | String pathName(
    method _getStringFromEnum (line 387) | String _getStringFromEnum(Object dbName)
    method decodeJson (line 391) | Object? decodeJson(Uint8List bytes)
    method encodeJson (line 401) | Uint8List encodeJson(Object? simpleObj)
    method setFileSystem (line 418) | void setFileSystem(f.FileSystem fileSystem)
    method resetFileSystem (line 422) | void resetFileSystem()

FILE: lib/src/local_persist.dart
  class LocalPersist (line 82) | class LocalPersist {
    method save (line 169) | Future<File> save(List<Object> simpleObjs, {bool append = false})
    method saveJson (line 185) | Future<File> saveJson(Object? simpleObj)
    method load (line 203) | Future<List<Object?>?> load()
    method loadJson (line 228) | Future<Object?>? loadJson()
    method loadAsObj (line 252) | Future<Map<String, dynamic>?> loadAsObj()
    method delete (line 266) | Future<bool> delete()
    method length (line 285) | Future<int> length()
    method exists (line 303) | Future<bool> exists()
    method _checkIfFileSystemIsTheSame (line 310) | void _checkIfFileSystemIsTheSame()
    method file (line 315) | Future<File> file()
    method simpleObjsToString (line 330) | String? simpleObjsToString(List<Object?>? simpleObjs)
    method pathName (line 335) | String pathName(
    method _getStringFromEnum (line 348) | String _getStringFromEnum(Object dbName)
    method useAppDocumentsDir (line 353) | Future<void> useAppDocumentsDir()
    method useAppCacheDir (line 368) | Future<void> useAppCacheDir()
    method useAppDownloadsDir (line 383) | Future<void> useAppDownloadsDir()
    method useCustomBaseDirectory (line 399) | Future<void> useCustomBaseDirectory({
    method encode (line 418) | Uint8List encode(List<Object> simpleObjs)
    method objsToJsons (line 425) | Iterable<String> objsToJsons(List<Object> simpleObjs)
    method jsonsToUint8Lists (line 430) | List<Uint8List> jsonsToUint8Lists(Iterable<String> jsons)
    method concatUint8Lists (line 448) | Uint8List concatUint8Lists(List<Uint8List> chunks)
    method decode (line 452) | List<Object?> decode(Uint8List bytes)
    method decodeJson (line 459) | Object? decodeJson(Uint8List bytes)
    method encodeJson (line 469) | Uint8List encodeJson(Object? simpleObj)
    method bytesToUint8Lists (line 478) | List<Uint8List> bytesToUint8Lists(Uint8List bytes)
    method uint8ListsToJsons (line 491) | Iterable<String> uint8ListsToJsons(Iterable<Uint8List> chunks)
    method toSimpleObjs (line 496) | Iterable<Object?> toSimpleObjs(Iterable<String> jsons)
    method setFileSystem (line 509) | void setFileSystem(f.FileSystem fileSystem)
    method getFileSystem (line 513) | f.FileSystem getFileSystem()
    method resetFileSystem (line 515) | void resetFileSystem()

FILE: lib/src/log.dart
  class Log (line 42) | class Log<St> implements ActionObserver<St> {
    method verySimpleFormatter (line 73) | String verySimpleFormatter(
    method singleLineFormatter (line 83) | String singleLineFormatter(
    method multiLineFormatter (line 94) | String multiLineFormatter(
    method observe (line 109) | void observe(ReduxAction<St> action, int dispatchCount, {required bool...
  type MessageFormatter (line 124) | typedef MessageFormatter<St> = String Function(

FILE: lib/src/mock_build_context.dart
  class MockBuildContext (line 37) | class MockBuildContext extends BuildContext {
    method dependOnInheritedElement (line 52) | InheritedWidget dependOnInheritedElement(InheritedElement ancestor,
    method dependOnInheritedWidgetOfExactType (line 58) | T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>(
    method describeElement (line 64) | DiagnosticsNode describeElement(String name,
    method describeMissingAncestor (line 70) | List<DiagnosticsNode> describeMissingAncestor(
    method describeOwnershipChain (line 76) | DiagnosticsNode describeOwnershipChain(String name)
    method describeWidget (line 81) | DiagnosticsNode describeWidget(String name,
    method dispatchNotification (line 87) | void dispatchNotification(Notification notification)
    method findAncestorRenderObjectOfType (line 92) | T? findAncestorRenderObjectOfType<T extends RenderObject>()
    method findAncestorStateOfType (line 97) | T? findAncestorStateOfType<T extends State<StatefulWidget>>()
    method findAncestorWidgetOfExactType (line 102) | T? findAncestorWidgetOfExactType<T extends Widget>()
    method findRenderObject (line 107) | RenderObject? findRenderObject()
    method findRootAncestorStateOfType (line 112) | T? findRootAncestorStateOfType<T extends State<StatefulWidget>>()
    method getElementForInheritedWidgetOfExactType (line 117) | InheritedElement?
    method getInheritedWidgetOfExactType (line 123) | T? getInheritedWidgetOfExactType<T extends InheritedWidget>()
    method visitAncestorElements (line 138) | void visitAncestorElements(ConditionalElementVisitor visitor)
    method visitChildElements (line 143) | void visitChildElements(ElementVisitor visitor)

FILE: lib/src/mock_store.dart
  class MockStore (line 16) | class MockStore<St> extends Store<St> {
    method addMock (line 74) | MockStore<St> addMock(Type actionType, dynamic mock)
    method addMocks (line 79) | MockStore<St> addMocks(Map<Type, dynamic> mocks)
    method clearMocks (line 84) | MockStore<St> clearMocks()
    method dispatch (line 102) | FutureOr<ActionStatus> dispatch(
    method dispatchAsync (line 115) | Future<ActionStatus> dispatchAsync(ReduxAction<St> action, {bool notif...
    method dispatchAndWait (line 143) | Future<ActionStatus> dispatchAndWait(ReduxAction<St> action, {bool not...
    method dispatchSync (line 160) | ActionStatus dispatchSync(ReduxAction<St> action, {bool notify = true})
    method _getMockedAction (line 168) | ReduxAction<St>? _getMockedAction(ReduxAction<St> action)
  class MockAction (line 223) | abstract class MockAction<St> extends ReduxAction<St> {
    method _setAction (line 228) | void _setAction(ReduxAction<St> action)
  class _GeneralActionSync (line 233) | class _GeneralActionSync<St> extends MockAction<St> {
    method reduce (line 239) | St reduce()
  class _GeneralActionAsync (line 242) | class _GeneralActionAsync<St> extends MockAction<St> {
    method reduce (line 248) | Future<St> reduce()

FILE: lib/src/model_observer.dart
  class ModelObserver (line 13) | abstract class ModelObserver<Model> {
    method observe (line 25) | void observe({
  class DefaultModelObserver (line 51) | class DefaultModelObserver<Model> implements ModelObserver<Model> {
    method observe (line 64) | void observe({

FILE: lib/src/navigate_action.dart
  class NavigateAction (line 26) | class NavigateAction<St> extends ReduxAction<St> {
    method setNavigatorKey (line 31) | void setNavigatorKey(GlobalKey<NavigatorState> navigatorKey)
    method getCurrentNavigatorRouteName (line 36) | String? getCurrentNavigatorRouteName(BuildContext context)
    method reduce (line 54) | St? reduce()
    method toString (line 145) | String toString()
  class NavigatorDetails_Push (line 148) | class NavigatorDetails_Push implements NavigatorDetails {
    method navigate (line 154) | void navigate()
    method toString (line 162) | String toString()
  class NavigatorDetails_Pop (line 165) | class NavigatorDetails_Pop implements NavigatorDetails {
    method navigate (line 171) | void navigate()
    method toString (line 179) | String toString()
  class NavigatorDetails_PopAndPushNamed (line 183) | class NavigatorDetails_PopAndPushNamed implements NavigatorDetails {
    method navigate (line 195) | void navigate()
    method toString (line 207) | String toString()
  class NavigatorDetails_PushNamed (line 212) | class NavigatorDetails_PushNamed implements NavigatorDetails {
    method navigate (line 222) | void navigate()
    method toString (line 231) | String toString()
  class NavigatorDetails_PushReplacementNamed (line 234) | class NavigatorDetails_PushReplacementNamed implements NavigatorDetails {
    method navigate (line 244) | void navigate()
    method toString (line 253) | String toString()
  class NavigatorDetails_PushNamedAndRemoveUntil (line 256) | class NavigatorDetails_PushNamedAndRemoveUntil implements NavigatorDetai...
    method navigate (line 268) | void navigate()
    method toString (line 278) | String toString()
  class NavigatorDetails_PushNamedAndRemoveAll (line 281) | class NavigatorDetails_PushNamedAndRemoveAll implements NavigatorDetails {
    method navigate (line 291) | void navigate()
    method toString (line 301) | String toString()
  class NavigatorDetails_PushReplacement (line 304) | class NavigatorDetails_PushReplacement implements NavigatorDetails {
    method navigate (line 314) | void navigate()
    method toString (line 323) | String toString()
  class NavigatorDetails_PushAndRemoveUntil (line 328) | class NavigatorDetails_PushAndRemoveUntil implements NavigatorDetails {
    method navigate (line 338) | void navigate()
    method toString (line 347) | String toString()
  class NavigatorDetails_Replace (line 352) | class NavigatorDetails_Replace implements NavigatorDetails {
    method navigate (line 362) | void navigate()
    method toString (line 373) | String toString()
  class NavigatorDetails_ReplaceRouteBelow (line 378) | class NavigatorDetails_ReplaceRouteBelow implements NavigatorDetails {
    method navigate (line 388) | void navigate()
    method toString (line 399) | String toString()
  class NavigatorDetails_PopUntil (line 404) | class NavigatorDetails_PopUntil implements NavigatorDetails {
    method navigate (line 410) | void navigate()
    method toString (line 418) | String toString()
  class NavigatorDetails_PopUntilRouteName (line 421) | class NavigatorDetails_PopUntilRouteName implements NavigatorDetails {
    method navigate (line 432) | void navigate()
    method toString (line 445) | String toString()
  class NavigatorDetails_PopUntilRoute (line 448) | class NavigatorDetails_PopUntilRoute implements NavigatorDetails {
    method navigate (line 454) | void navigate()
    method toString (line 463) | String toString()
  class NavigatorDetails_RemoveRoute (line 466) | class NavigatorDetails_RemoveRoute implements NavigatorDetails {
    method navigate (line 472) | void navigate()
    method toString (line 480) | String toString()
  class NavigatorDetails_RemoveRouteBelow (line 483) | class NavigatorDetails_RemoveRouteBelow implements NavigatorDetails {
    method navigate (line 489) | void navigate()
    method toString (line 497) | String toString()
  class NavigatorDetails (line 501) | abstract class NavigatorDetails {
    method navigate (line 502) | void navigate()
  type NavigateType (line 507) | enum NavigateType {
  function toStringOrRuntimeType (line 529) | String toStringOrRuntimeType()

FILE: lib/src/persistor.dart
  class Persistor (line 31) | abstract class Persistor<St> {
    method readState (line 40) | Future<St?> readState()
    method deleteState (line 43) | Future<void> deleteState()
    method persistDifference (line 53) | Future<void> persistDifference({
    method saveInitialState (line 59) | Future<void> saveInitialState(St state)
  class PersistorPrinterDecorator (line 73) | class PersistorPrinterDecorator<St> extends Persistor<St> {
    method readState (line 79) | Future<St?> readState()
    method deleteState (line 85) | Future<void> deleteState()
    method persistDifference (line 91) | Future<void> persistDifference({
    method saveInitialState (line 103) | Future<void> saveInitialState(St state)
  class PersistorDummy (line 114) | class PersistorDummy<T> extends Persistor<T> {
    method readState (line 116) | Future<T?> readState()
    method deleteState (line 119) | Future<void> deleteState()
    method persistDifference (line 122) | Future<void> persistDifference(
    method saveInitialState (line 126) | Future<void> saveInitialState(T state)
  class PersistException (line 132) | class PersistException implements Exception {
    method toString (line 138) | String toString()
  class PersistAction (line 153) | class PersistAction<St> extends ReduxAction<St> {
    method reduce (line 155) | St? reduce()

FILE: lib/src/process_persistence.dart
  class ProcessPersistence (line 10) | class ProcessPersistence<St> {
    method saveInitialState (line 32) | Future<void> saveInitialState(St initialState)
    method readState (line 38) | Future<St?> readState()
    method deleteState (line 45) | Future<void> deleteState()
    method process (line 57) | bool process(
    method _cancelTimer (line 104) | void _cancelTimer()
    method _persist (line 111) | void _persist(DateTime now, newState)
    method pause (line 144) | void pause()
    method persistAndPause (line 162) | void persistAndPause()
    method resume (line 176) | void resume()

FILE: lib/src/redux_action.dart
  class ReduxAction (line 73) | abstract class ReduxAction<St> {
    method setStore (line 80) | void setStore(Store<St> store)
    method prop (line 114) | V prop<V>(Object? key)
    method setProp (line 129) | void setProp(Object? key, Object? value)
    method disposeProps (line 171) | void disposeProps([bool Function({Object? key, Object? value})? predic...
    method disposeProp (line 187) | void disposeProp(Object? keyToDispose)
    method dispatchState (line 269) | ActionStatus dispatchState(St state, {bool notify = true})
    method before (line 370) | FutureOr<void> before()
    method after (line 386) | void after()
    method reduce (line 399) | FutureOr<St?> reduce()
    method wrapReduce (line 430) | FutureOr<St?> wrapReduce(Reducer<St> reduce)
    method wrapError (line 459) | Object? wrapError(Object error, StackTrace stackTrace)
    method abortDispatch (line 486) | bool abortDispatch()
    method isWaiting (line 522) | bool isWaiting(Object actionOrTypeOrList)
    method isFailed (line 527) | bool isFailed(Object actionOrTypeOrList)
    method exceptionFor (line 536) | UserException? exceptionFor(Object actionTypeOrList)
    method clearExceptionFor (line 549) | void clearExceptionFor(Object actionTypeOrList)
    method waitCondition (line 564) | Future<ReduxAction<St>?> waitCondition(
    method waitAllActions (line 590) | Future<void> waitAllActions(List<ReduxAction<St>> actions,
    method assertUncompletedFuture (line 620) | void assertUncompletedFuture()
    method ifWrapReduceOverridden_Sync (line 627) | bool ifWrapReduceOverridden_Sync()
    method ifWrapReduceOverridden_Async (line 630) | bool ifWrapReduceOverridden_Async()
    method ifWrapReduceOverridden (line 633) | bool ifWrapReduceOverridden()
    method isSync (line 639) | bool isSync()
    method runtimeTypeString (line 655) | String runtimeTypeString()
    method toString (line 662) | String toString()
  class AbortDispatchException (line 687) | class AbortDispatchException implements Exception {
  class UpdateStateAction (line 703) | class UpdateStateAction<St> extends ReduxAction<St> {
    method reduce (line 727) | St? reduce()

FILE: lib/src/show_dialog_super.dart
  function showDialogSuper (line 131) | Future<T?> showDialogSuper<T>({
  function showCupertinoDialogSuper (line 248) | Future<T?> showCupertinoDialogSuper<T>({

FILE: lib/src/state_observer.dart
  class StateObserver (line 65) | abstract class StateObserver<St> {
    method observe (line 82) | void observe(

FILE: lib/src/store.dart
  type Reducer (line 20) | typedef Reducer<St> = FutureOr<St?> Function();
  type Dispatch (line 22) | typedef Dispatch<St> = FutureOr<ActionStatus> Function(
  type DispatchSync (line 27) | typedef DispatchSync<St> = ActionStatus Function(
  type DispatchAsync (line 32) | @Deprecated("Use `DispatchAndWait` instead. This will be removed.")
  type DispatchAndWait (line 38) | typedef DispatchAndWait<St> = Future<ActionStatus> Function(
  class Store (line 96) | class Store<St> {
    method prop (line 233) | V prop<V>(Object? key)
    method setProp (line 248) | void setProp(Object? key, Object? value)
    method disposeProps (line 289) | void disposeProps([bool Function({Object? key, Object? value})? predic...
    method disposeProp (line 320) | void disposeProp(Object? keyToDispose)
    method _closeTimerFutureStream (line 326) | bool _closeTimerFutureStream(Object? obj)
    method pausePersistor (line 452) | void pausePersistor()
    method pauseCloudSync (line 465) | void pauseCloudSync()
    method persistAndPausePersistor (line 482) | void persistAndPausePersistor()
    method persistAndPauseCloudSync (line 499) | void persistAndPauseCloudSync()
    method resumePersistor (line 505) | void resumePersistor()
    method resumeCloudSync (line 511) | void resumeCloudSync()
    method saveInitialStateInPersistence (line 516) | Future<void> saveInitialStateInPersistence(St initialState)
    method saveInitialStateInCloud (line 520) | Future<void> saveInitialStateInCloud(St initialState)
    method readStateFromPersistence (line 526) | Future<St?> readStateFromPersistence()
    method readStateFromCloudSync (line 531) | Future<St?> readStateFromCloudSync()
    method deleteStateFromPersistence (line 534) | Future<void> deleteStateFromPersistence()
    method deleteStateFromCloud (line 537) | Future<void> deleteStateFromCloud()
    method getLastPersistedStateFromPersistor (line 540) | St? getLastPersistedStateFromPersistor()
    method getLastPersistedStateFromCloudSync (line 543) | St? getLastPersistedStateFromCloudSync()
    method initTestInfoController (line 546) | void initTestInfoController()
    method initTestInfoPrinter (line 551) | void initTestInfoPrinter(TestInfoPrinter testInfoPrinter)
    method defineState (line 558) | void defineState(St state)
    method waitCondition (line 660) | Future<ReduxAction<St>?> waitCondition(
    method waitActionCondition (line 816) | Future<(Set<ReduxAction<St>>, ReduxAction<St>?)> waitActionCondition(
    method waitAllActions (line 952) | Future<void> waitAllActions(
    method waitActionType (line 1067) | Future<ReduxAction<St>?> waitActionType(
    method waitAllActionTypes (line 1167) | Future<void> waitAllActionTypes(
    method waitAnyActionTypeFinishes (line 1285) | Future<ReduxAction<St>> waitAnyActionTypeFinishes(
    method _addError (line 1311) | void _addError(UserException error)
    method getAndRemoveFirstError (line 1317) | UserException? getAndRemoveFirstError()
    method removeError (line 1357) | void removeError(Object source)
    method shutdown (line 1375) | void shutdown()
    method dispatch (line 1424) | FutureOr<ActionStatus> dispatch(ReduxAction<St> action, {bool notify =...
    method dispatchSync (line 1447) | ActionStatus dispatchSync(ReduxAction<St> action, {bool notify = true})
    method dispatchAndWait (line 1486) | Future<ActionStatus> dispatchAndWait(ReduxAction<St> action, {bool not...
    method dispatchAndWaitAllActions (line 1510) | Future<ActionStatus> dispatchAndWaitAllActions(ReduxAction<St> action,
    method dispatchAll (line 1535) | List<ReduxAction<St>> dispatchAll(List<ReduxAction<St>> actions, {bool...
    method dispatchAndWaitAll (line 1575) | Future<List<ReduxAction<St>>> dispatchAndWaitAll(
    method dispatchAsync (line 1590) | Future<ActionStatus> dispatchAsync(ReduxAction<St> action, {bool notif...
    method _dispatch (line 1593) | FutureOr<ActionStatus> _dispatch(ReduxAction<St> action, {required boo...
    method createTestInfoSnapshot (line 1617) | void createTestInfoSnapshot(
    method _processAction (line 1648) | FutureOr<ActionStatus> _processAction(
    method _calculateIsWaitingIsFailed (line 1661) | void _calculateIsWaitingIsFailed(ReduxAction<St> action)
    method _checkAllActionConditions (line 1695) | void _checkAllActionConditions(ReduxAction<St> triggerAction)
    method _checkAllStateConditions (line 1711) | void _checkAllStateConditions(ReduxAction<St> triggerAction)
    method isWaiting (line 1759) | bool isWaiting(Object actionOrTypeOrList)
    method isFailed (line 1825) | bool isFailed(Object actionOrTypeOrList)
    method exceptionFor (line 1833) | UserException? exceptionFor(Object actionTypeOrList)
    method clearExceptionFor (line 1886) | void clearExceptionFor(Object actionTypeOrList)
    method _processAction_Sync (line 1924) | ActionStatus _processAction_Sync(
    method _processAction_Async (line 1977) | Future<ActionStatus> _processAction_Async(
    method _checkReducerType (line 2029) | void _checkReducerType(FutureOr<St?> Function() reduce)
    method _applyReducer (line 2060) | FutureOr<void> _applyReducer(ReduxAction<St> action, {bool notify = tr...
    method _applyReduceAndWrapReduce (line 2073) | FutureOr<void> _applyReduceAndWrapReduce(ReduxAction<St> action, {bool...
    method _applyReduce (line 2100) | FutureOr<void> _applyReduce(ReduxAction<St> action, {bool notify = true})
    method _registerState (line 2178) | void _registerState(
    method actionsInProgress (line 2217) | Set<ReduxAction<St>> actionsInProgress()
    method copyActionsInProgress (line 2222) | Set<ReduxAction<St>> copyActionsInProgress()
    method actionsInProgressEqualTo (line 2226) | bool actionsInProgressEqualTo(Set<ReduxAction<St>> set)
    method _processError (line 2254) | Object? _processError(
    method _finalize (line 2355) | void _finalize(
    method _after (line 2381) | void _after(ReduxAction<St> action)
    method teardown (line 2403) | Future teardown({St? emptyState})
    method getConnectorTester (line 2433) | ConnectorTester<St, Model> getConnectorTester<Model>(StatelessWidget w...
    method _throws (line 2437) | void _throws(errorMsg, Object? error, StackTrace stackTrace)
  type CompareBy (line 2447) | enum CompareBy { byDeepEquals, byIdentity }
  class ActionStatus (line 2449) | @immutable
    method copy (line 2534) | ActionStatus copy({
    method toString (line 2556) | String toString()
  class _Flag (line 2592) | class _Flag<T> {
  type OptimisticSyncWithPushRevisionEntry (line 2604) | typedef OptimisticSyncWithPushRevisionEntry = ({
  class _InternalMixinProps (line 2624) | class _InternalMixinProps {
    method clear (line 2642) | void clear()
  class GlobalErrorObserver (line 2707) | abstract class GlobalErrorObserver<St> {
    method observe (line 2740) | Object? observe()
    method _init (line 2742) | void _init({
  class GlobalErrorObserverDummy (line 2760) | class GlobalErrorObserverDummy<St> extends GlobalErrorObserver<St> {
    method observe (line 2762) | Object? observe()
  class GlobalErrorObserverForDevelopment (line 2783) | class GlobalErrorObserverForDevelopment<St> extends GlobalErrorObserver<...
    method observe (line 2785) | Object? observe()
  class SwallowGlobalErrorObserver (line 2808) | class SwallowGlobalErrorObserver<St> extends GlobalErrorObserver<St> {
    method observe (line 2810) | Object? observe()

FILE: lib/src/store_exception.dart
  class StoreException (line 5) | class StoreException implements Exception {
    method toString (line 11) | String toString()

FILE: lib/src/store_provider_and_connector.dart
  type StoreConverter (line 16) | typedef StoreConverter<St, Model> = Model Function(Store<St> store);
  type OnInitCallback (line 21) | typedef OnInitCallback<St> = void Function(Store<St> store);
  type OnDisposeCallback (line 26) | typedef OnDisposeCallback<St> = void Function(Store<St> store);
  type ShouldUpdateModel (line 39) | typedef ShouldUpdateModel<St> = bool Function(St state);
  type OnWillChangeCallback (line 47) | typedef OnWillChangeCallback<St, Model> = void Function(
  type OnDidChangeCallback (line 58) | typedef OnDidChangeCallback<St, Model> = void Function(
  type OnInitialBuildCallback (line 65) | typedef OnInitialBuildCallback<St, Model> = void Function(
  type ViewModelBuilder (line 70) | typedef ViewModelBuilder<Model> = Widget Function(
  type SelectorAspect (line 77) | typedef SelectorAspect<St> = bool Function(St? value);
  class SelectorDependency (line 81) | class SelectorDependency<St> {
  class StoreConnectorInterface (line 98) | abstract class StoreConnectorInterface<St, Model> {
  class StoreConnector (line 149) | class StoreConnector<St, Model> extends StatelessWidget
    method build (line 252) | Widget build(BuildContext context)
    method getLatestModel (line 279) | Model getLatestModel(Store store)
  class _StoreStreamListener (line 300) | class _StoreStreamListener<St, Model> extends StatefulWidget {
    method createState (line 335) | State<StatefulWidget> createState()
  class _ConverterError (line 341) | class _ConverterError extends Error {
    method toString (line 355) | String toString()
  class _StoreStreamListenerState (line 363) | class _StoreStreamListenerState<St, Model> //
    method initState (line 379) | void initState()
    method dispose (line 408) | void dispose()
    method didUpdateWidget (line 417) | void didUpdateWidget(_StoreStreamListener<St, Model> oldWidget)
    method _computeLatestModel (line 427) | void _computeLatestModel()
    method _createStream (line 438) | void _createStream()
    method _stateChanged (line 457) | bool _stateChanged(St state)
    method _actionsInProgressHaveChanged (line 467) | bool _actionsInProgressHaveChanged()
    method _shouldUpdateModel (line 484) | bool _shouldUpdateModel(St state)
    method _calculateModel (line 512) | Model? _calculateModel(St state)
    method _whereDistinct (line 516) | bool _whereDistinct(Model? vm)
    method _isDistinct (line 531) | bool _isDistinct(Model? vm)
    method _handleData (line 547) | void _handleData(Model vm, EventSink<Model> sink)
    method _handleError (line 583) | void _handleError(
    method _observeWithTheModelObserver (line 595) | void _observeWithTheModelObserver<Model>({
    method _throws (line 617) | void _throws(errorMsg, Object? error, StackTrace stackTrace)
    method getLatestModel (line 630) | Model getLatestModel(St state)
    method build (line 650) | Widget build(BuildContext context)
  class StoreProvider (line 721) | class StoreProvider<St> extends InheritedWidget {
    method state (line 777) | St state<St>(BuildContext context,
    method _getStoreWithDependency_Untyped (line 810) | Store<St> _getStoreWithDependency_Untyped<St>(BuildContext context,
    method _getStoreNoDependency_Untyped (line 830) | Store<St> _getStoreNoDependency_Untyped<St>(BuildContext context,
    method _typeOf (line 860) | Type _typeOf<T>()
    method dispatch (line 874) | FutureOr<ActionStatus> dispatch<St>(
    method dispatchSync (line 892) | ActionStatus dispatchSync<St>(
    method dispatchAndWait (line 910) | Future<ActionStatus> dispatchAndWait<St>(
    method dispatchAll (line 928) | List<ReduxAction<St>> dispatchAll<St>(
    method dispatchAndWaitAll (line 949) | Future<List<ReduxAction<St>>> dispatchAndWaitAll<St>(
    method waitCondition (line 969) | Future<ReduxAction<St>?> waitCondition<St>(
    method waitAllActions (line 991) | Future<void> waitAllActions<St>(
    method isWaiting (line 1018) | bool isWaiting(
    method isFailed (line 1039) | bool isFailed(
    method exceptionFor (line 1063) | UserException? exceptionFor(
    method clearExceptionFor (line 1084) | void clearExceptionFor(
    method backdoorInheritedWidget (line 1101) | Store<St> backdoorInheritedWidget<St>(BuildContext context,
    method backdoorStaticGlobal (line 1135) | Store<St> backdoorStaticGlobal<St>()
    method backdoorStaticGlobalUntyped (line 1150) | Store backdoorStaticGlobalUntyped()
    method _init (line 1161) | Store<St> _init<St>(Store<St> store)
    method updateShouldNotify (line 1167) | bool updateShouldNotify(StoreProvider<St> oldWidget)
  class _InheritedUntypedDoesNotRebuild (line 1177) | class _InheritedUntypedDoesNotRebuild extends InheritedWidget {
    method updateShouldNotify (line 1191) | bool updateShouldNotify(_InheritedUntypedDoesNotRebuild oldWidget)
  class _WidgetListensOnChange (line 1200) | class _WidgetListensOnChange extends StatefulWidget {
    method createState (line 1207) | _WidgetListensOnChangeState createState()
  class _WidgetListensOnChangeState (line 1210) | class _WidgetListensOnChangeState extends State<_WidgetListensOnChange> {
    method initState (line 1212) | void initState()
    method build (line 1222) | Widget build(BuildContext context)
  class _InheritedUntypedRebuilds (line 1238) | class _InheritedUntypedRebuilds extends InheritedWidget {
    method createElement (line 1250) | _InheritedUntypedRebuildsElement createElement()
    method updateShouldNotify (line 1255) | bool updateShouldNotify(_InheritedUntypedRebuilds oldWidget)
  class _InheritedUntypedRebuildsElement (line 1261) | class _InheritedUntypedRebuildsElement extends InheritedElement {
    method updateDependencies (line 1270) | void updateDependencies(Element dependent, Object? aspect)
    method notifyDependent (line 1346) | void notifyDependent(InheritedWidget oldWidget, Element dependent)
  function _exceptionForWrongStoreType (line 1431) | StoreException _exceptionForWrongStoreType(Type type, {Object? debug})
  function _exceptionForWrongStateType (line 1443) | StoreException _exceptionForWrongStateType(Object? state, Type wrongType)
  function getState (line 1489) | St getState<St>()
  function getRead (line 1525) | St getRead<St>()
  function getEvent (line 1635) | R? getEvent<St, R>(Evt<R> Function(St state) selector, {bool debug = true})
  function getSelect (line 1692) | R getSelect<St, R>(R Function(St state) selector, {bool debug = true})
  function _assertSelect (line 1770) | void _assertSelect(bool debug)
  function _assertEvent (line 1821) | void _assertEvent(bool debug)
  function _typeOf (line 1876) | Type _typeOf<T>()
  function dispatch (line 1893) | FutureOr<ActionStatus> dispatch(ReduxAction<St> action,
  function dispatchAndWait (line 1926) | Future<ActionStatus> dispatchAndWait(ReduxAction<St> action,
  function dispatchAll (line 1948) | List<ReduxAction<St>> dispatchAll<St>(List<ReduxAction<St>> actions,
  function dispatchAndWaitAll (line 1976) | Future<List<ReduxAction<St>>> dispatchAndWaitAll<St>(
  function dispatchSync (line 2002) | ActionStatus dispatchSync(ReduxAction<St> action, {bool notify = true})
  function isWaiting (line 2041) | bool isWaiting(Object actionOrTypeOrList)
  function isFailed (line 2052) | bool isFailed(Object actionOrTypeOrList)
  function exceptionFor (line 2066) | UserException? exceptionFor(Object actionOrTypeOrList)
  function clearExceptionFor (line 2079) | void clearExceptionFor(Object actionOrTypeOrList)
  function getEnvironment (line 2126) | Object? getEnvironment<St>()
  function getConfiguration (line 2174) | Object? getConfiguration<St>()
  function dispatch (line 2220) | FutureOr<ActionStatus> dispatch(ReduxAction<St> action,
  function dispatchAndWait (line 2256) | Future<ActionStatus> dispatchAndWait(ReduxAction<St> action,
  function dispatchAll (line 2281) | List<ReduxAction<St>> dispatchAll<St>(List<ReduxAction<St>> actions,
  function dispatchAndWaitAll (line 2311) | Future<List<ReduxAction<St>>> dispatchAndWaitAll<St>(
  function dispatchSync (line 2339) | ActionStatus dispatchSync(ReduxAction<St> action, {bool notify = true})
  function dispatch (line 2376) | FutureOr<ActionStatus> dispatch(ReduxAction<St> action,
  function dispatchAndWait (line 2412) | Future<ActionStatus> dispatchAndWait(ReduxAction<St> action,
  function dispatchAll (line 2437) | List<ReduxAction<St>> dispatchAll<St>(List<ReduxAction<St>> actions,
  function dispatchAndWaitAll (line 2467) | Future<List<ReduxAction<St>>> dispatchAndWaitAll<St>(
  function dispatchSync (line 2495) | ActionStatus dispatchSync(ReduxAction<St> action, {bool notify = true})

FILE: lib/src/store_tester.dart
  type StateCondition (line 15) | typedef StateCondition<St> = bool Function(TestInfo<St> info);
  class StoreTester (line 21) | class StoreTester<St> {
    method addMock (line 116) | MockStore<St> addMock(Type actionType, dynamic mock)
    method addMocks (line 121) | MockStore<St> addMocks(Map<Type, dynamic> mocks)
    method clearMocks (line 126) | MockStore<St> clearMocks()
    method dispatch (line 131) | FutureOr<ActionStatus> dispatch(ReduxAction<St> action,
    method dispatchSync (line 135) | ActionStatus dispatchSync(ReduxAction<St> action, {bool notify = true})
    method dispatchAsync (line 139) | Future<ActionStatus> dispatchAsync(ReduxAction<St> action,
    method dispatchAndWait (line 143) | Future<ActionStatus> dispatchAndWait(ReduxAction<St> action,
    method dispatchAndWaitGetInfo (line 161) | Future<TestInfo<St>> dispatchAndWaitGetInfo(ReduxAction<St> action)
    method defineState (line 166) | void defineState(St state)
    method dispatchState (line 177) | Future<TestInfo<St>> dispatchState(St state)
    method waitConditionGetLast (line 209) | Future<TestInfo<St>> waitConditionGetLast(
    method waitCondition (line 239) | Future<TestInfoList<St>> waitCondition(
    method waitUntilErrorGetLast (line 297) | Future<TestInfo<St>> waitUntilErrorGetLast({
    method waitUntilError (line 322) | Future<TestInfoList<St>> waitUntilError({
    method wait (line 355) | Future<TestInfo<St>> wait(Type actionType)
    method waitUntil (line 361) | Future<TestInfo<St>> waitUntil(
    method waitUntilAny (line 382) | Future<TestInfo<St>> waitUntilAny(
    method waitUntilAll (line 404) | Future<TestInfoList<St>> waitUntilAll(
    method waitUntilAllGetLast (line 437) | Future<TestInfo<St>> waitUntilAllGetLast(
    method waitUntilAction (line 462) | Future<TestInfo<St>> waitUntilAction(
    method waitAllGetLast (line 495) | Future<TestInfo<St>> waitAllGetLast(
    method waitAllUnorderedGetLast (line 518) | Future<TestInfo<St>> waitAllUnorderedGetLast(
    method waitAll (line 552) | Future<TestInfoList<St>> waitAll(
    method waitAllUnordered (line 643) | Future<TestInfoList<St>> waitAllUnordered(
    method _listen (line 734) | void _listen()
    method _next (line 752) | Future<TestInfo<St>> _next({
    method _completeFuture (line 772) | void _completeFuture(TestInfo<St> reduceInfo)
    method cancel (line 778) | Future cancel()
    method getConnectorTester (line 803) | ConnectorTester<St, Model> getConnectorTester<Model>(
  class TestInfoList (line 809) | class TestInfoList<St> {
    method getIndex (line 820) | TestInfo<St> getIndex(int index)
    method get (line 828) | TestInfo<St>? get(Type actionType, [int n = 1])
    method getAll (line 837) | List<TestInfo<St>> getAll(Type actionType)
    method forEach (line 841) | void forEach(void action(TestInfo<St> element))
    method firstWhere (line 843) | TestInfo<St> firstWhere(
    method lastWhere (line 849) | TestInfo<St> lastWhere(
    method singleWhere (line 855) | TestInfo<St> singleWhere(
    method where (line 861) | Iterable<TestInfo<St>> where(
    method map (line 867) | Iterable<T> map<T>(T f(TestInfo<St> element))
    method toList (line 869) | List<TestInfo<St>> toList({
    method toSet (line 874) | Set<TestInfo<St>> toSet()
    method _add (line 880) | void _add(TestInfo<St> info)
  class StoreExceptionTimeout (line 887) | class StoreExceptionTimeout extends StoreException {
    method addDetail (line 894) | void addDetail(String detail)
    method toString (line 897) | String toString()
  class TestErrorObserver (line 922) | class TestErrorObserver<St> implements ErrorObserver<St> {
    method observe (line 924) | bool observe(
  class _NewStateAction (line 933) | class _NewStateAction<St> extends ReduxAction<St> {
    method reduce (line 939) | St reduce()

FILE: lib/src/test_info.dart
  type TestInfoPrinter (line 5) | typedef TestInfoPrinter = void Function(TestInfo);
  class TestInfo (line 7) | class TestInfo<St> {
    method toString (line 63) | String toString()

FILE: lib/src/user_exception_dialog.dart
  class UserExceptionDialog (line 31) | class UserExceptionDialog<St> extends StatelessWidget {
    method build (line 54) | Widget build(BuildContext context)
  class _UserExceptionDialogWidget (line 76) | class _UserExceptionDialogWidget extends StatefulWidget {
    method _defaultUserExceptionDialog (line 90) | void _defaultUserExceptionDialog(
    method createState (line 180) | _UserExceptionDialogState createState()
  class _UserExceptionDialogState (line 183) | class _UserExceptionDialogState extends State<_UserExceptionDialogWidget> {
    method didUpdateWidget (line 185) | void didUpdateWidget(_UserExceptionDialogWidget oldWidget)
    method build (line 198) | Widget build(BuildContext context)
  class _Factory (line 201) | class _Factory<St> extends VmFactory<St, UserExceptionDialog, _Vm> {
    method fromStore (line 205) | _Vm fromStore()
  class _Vm (line 216) | class _Vm extends Vm {
  type ShowUserExceptionDialog (line 231) | typedef ShowUserExceptionDialog = void Function(

FILE: lib/src/view_model.dart
  class VmEquals (line 15) | abstract class VmEquals<T> {
    method vmEquals (line 16) | bool vmEquals(T other)
  class Vm (line 47) | @immutable
    method createFrom (line 86) | Model createFrom<St, T extends Widget?, Model extends Vm>(
    method _onlyContainFieldsOfAllowedTypes (line 103) | bool _onlyContainFieldsOfAllowedTypes(List equals)
    method _listEquals (line 124) | bool _listEquals<T>(List<T>? list1, List<T>? list2)
    method toString (line 152) | String toString()
  class VmFactory (line 189) | abstract class VmFactory<St, T extends Widget?, Model extends Vm> {
    method fromStore (line 193) | Model? fromStore()
    method _setStore (line 260) | void _setStore(St state, Store store)
    method prop (line 280) | V prop<V>(Object? key)
    method setProp (line 293) | void setProp(Object? key, Object? value)
    method currentState (line 297) | St currentState()
    method isWaiting (line 397) | bool isWaiting(Object actionOrTypeOrList)
    method isFailed (line 402) | bool isFailed(Object actionOrTypeOrList)
    method exceptionFor (line 411) | UserException? exceptionFor(Object actionTypeOrList)
    method clearExceptionFor (line 423) | void clearExceptionFor(Object actionTypeOrList)
    method waitCondition (line 437) | Future<ReduxAction<St>?> waitCondition(
    method waitAllActions (line 462) | Future<void> waitAllActions(List<ReduxAction<St>> actions,
    method getAndRemoveFirstError (line 471) | UserException? getAndRemoveFirstError()
  function internalsVmFactoryFromStore (line 475) | Vm? internalsVmFactoryFromStore(
  function internalsVmFactoryInject (line 483) | void internalsVmFactoryInject<St>(

FILE: lib/src/wait.dart
  type WaitOperation (line 6) | enum WaitOperation { add, remove, clear }
  class Wait (line 30) | @immutable
    method add (line 54) | Wait add({required Object? flag, Object? ref})
    method remove (line 67) | Wait remove({required Object? flag, Object? ref})
    method process (line 88) | Wait process(
    method isWaiting (line 109) | bool isWaiting(Object? flag, {Object? ref})
    method isWaitingForType (line 135) | bool isWaitingForType<T>()
    method clear (line 140) | Wait clear({Object? flag})
    method clearWhere (line 150) | void clearWhere(
    method _deepCopy (line 157) | Map<Object?, Set<Object?>> _deepCopy()

FILE: lib/src/wait_action.dart
  class WaitAction (line 44) | class WaitAction<St> extends ReduxAction<St> {
    method reduce (line 185) | St? reduce()
    method toString (line 197) | String toString()
  type WaitReducer (line 202) | typedef WaitReducer<St> = St? Function(
  function toStringLimited (line 212) | String toStringLimited()

FILE: lib/src/wrap_reduce.dart
  class WrapReduce (line 40) | abstract class WrapReduce<St> {
    method ifShouldProcess (line 42) | bool ifShouldProcess()
    method process (line 44) | St process({
    method wrapReduce (line 49) | Reducer<St> wrapReduce(

FILE: test/abort_dispatch_test.dart
  function main (line 10) | void main()
  class ActionA (line 106) | class ActionA extends ReduxAction<String> {
    method abortDispatch (line 112) | bool abortDispatch()
    method before (line 115) | void before()
    method reduce (line 120) | String reduce()
    method after (line 126) | void after()
  class ActionB (line 131) | class ActionB extends ReduxAction<String> {
    method abortDispatch (line 133) | bool abortDispatch()
    method before (line 136) | void before()
    method reduce (line 141) | String reduce()
    method after (line 147) | void after()
  class State (line 152) | class State {
    method toString (line 158) | String toString()
  class Increment (line 161) | class Increment extends ReduxAction<State> {
    method abortDispatch (line 167) | bool abortDispatch()
    method reduce (line 170) | State reduce()

FILE: test/action_initial_state_test.dart
  class State (line 5) | class State {
    method toString (line 11) | String toString()
  class ChangeAction (line 14) | class ChangeAction extends ReduxAction<State> {
    method reduce (line 20) | State reduce()
  class IncrementSync (line 23) | class IncrementSync extends ReduxAction<State> {
    method before (line 27) | void before()
    method reduce (line 36) | State reduce()
    method after (line 46) | void after()
  class IncrementAsync (line 55) | class IncrementAsync extends ReduxAction<State> {
    method before (line 59) | Future<void> before()
    method reduce (line 68) | Future<State> reduce()
    method after (line 78) | void after()
  function main (line 87) | void main()

FILE: test/action_status_test.dart
  type When (line 11) | enum When { before, reduce, after }
  function main (line 16) | void main()
  class MyAction (line 213) | class MyAction extends ReduxAction<String> {
    method before (line 219) | void before()
    method reduce (line 225) | String reduce()
    method after (line 232) | void after()
  class MyActionWithWrapError (line 238) | class MyActionWithWrapError extends ReduxAction<String> {
    method before (line 244) | void before()
    method reduce (line 250) | String reduce()
    method after (line 257) | void after()
    method wrapError (line 263) | Object? wrapError(Object error, StackTrace stackTrace)
  class MyAbortAction (line 266) | class MyAbortAction extends ReduxAction<String> {
    method abortDispatch (line 268) | bool abortDispatch()
    method reduce (line 271) | String reduce()
  class MyGlobalWrapError (line 274) | class MyGlobalWrapError<St> implements GlobalWrapError<St> {
    method wrap (line 276) | Object? wrap(error, stackTrace, action)

FILE: test/action_to_string_test.dart
  function main (line 9) | void main()

FILE: test/action_wrap_reduce2_test.dart
  function main (line 6) | void main()
  class BaseAction (line 63) | abstract class BaseAction<St> {
    method reduce (line 66) | FutureOr<St?> reduce()
    method wrapReduce (line 68) | FutureOr<St?> wrapReduce(Reducer<St> reduce)
    method ifWrapReduceOverridden_Sync (line 72) | bool ifWrapReduceOverridden_Sync()
    method ifWrapReduceOverridden_Async (line 74) | bool ifWrapReduceOverridden_Async()
    method ifWrapReduceOverridden (line 77) | bool ifWrapReduceOverridden()
  class ActionNullableX (line 82) | class ActionNullableX extends BaseAction<int> {
    method reduce (line 84) | int? reduce()
    method wrapReduce (line 87) | Future<int?> wrapReduce(Reducer<int> reduce)
  class ActionX (line 94) | class ActionX extends BaseAction<int> {
    method reduce (line 96) | int? reduce()
    method wrapReduce (line 99) | Future<int> wrapReduce(Reducer<int> reduce)
  class ActionNullableY (line 106) | class ActionNullableY extends BaseAction<int> {
    method reduce (line 108) | int reduce()
    method wrapReduce (line 111) | int? wrapReduce(Reducer<int> reduce)
  class ActionY (line 118) | class ActionY extends BaseAction<int> {
    method reduce (line 120) | int reduce()
    method wrapReduce (line 123) | int wrapReduce(Reducer<int> reduce)
  class ActionZ (line 130) | class ActionZ extends BaseAction<int> {
    method reduce (line 132) | FutureOr<int?> reduce()

FILE: test/action_wrap_reduce_test.dart
  function main (line 4) | void main()
  class State (line 22) | class State {
  class IncrementReduceSyncNoBeforeNoWrap (line 28) | class IncrementReduceSyncNoBeforeNoWrap extends ReduxAction<State> {
    method reduce (line 30) | State reduce()
  class IncrementReduceAsyncNoBeforeNoWrap (line 33) | class IncrementReduceAsyncNoBeforeNoWrap extends ReduxAction<State> {
    method reduce (line 35) | Future<State> reduce()
  class IncrementReduceSyncBeforeSyncNoWrap (line 40) | class IncrementReduceSyncBeforeSyncNoWrap extends ReduxAction<State> {
    method before (line 42) | void before()
    method reduce (line 45) | State reduce()
  class IncrementReduceSyncBeforeAsyncNoWrap (line 48) | class IncrementReduceSyncBeforeAsyncNoWrap extends ReduxAction<State> {
    method before (line 50) | Future<void> before()
    method reduce (line 55) | State reduce()
  class IncrementReduceSyncNoBeforeWrapSync (line 58) | class IncrementReduceSyncNoBeforeWrapSync extends ReduxAction<State> {
    method reduce (line 60) | State reduce()
    method wrapReduce (line 63) | State? wrapReduce(Reducer<State> reduce)
  class IncrementReduceSyncNoBeforeWrapSync2 (line 68) | class IncrementReduceSyncNoBeforeWrapSync2 extends ReduxAction<State> {
    method reduce (line 70) | State reduce()
    method wrapReduce (line 73) | State wrapReduce(Reducer<State> reduce)
  class IncrementReduceSyncNoBeforeWrapSync3 (line 78) | class IncrementReduceSyncNoBeforeWrapSync3 extends ReduxAction<State> {
    method reduce (line 80) | State reduce()
    method wrapReduce (line 83) | State wrapReduce(Reducer<State> reduce)
  class IncrementReduceSyncNoBeforeWrapAsync (line 88) | class IncrementReduceSyncNoBeforeWrapAsync extends ReduxAction<State> {
    method reduce (line 90) | State reduce()
    method wrapReduce (line 93) | Future<State?> wrapReduce(Reducer<State> reduce)
  class IncrementReduceSyncNoBeforeWrapAsync2 (line 99) | class IncrementReduceSyncNoBeforeWrapAsync2 extends ReduxAction<State> {
    method reduce (line 101) | State reduce()
    method wrapReduce (line 104) | Future<State> wrapReduce(Reducer<State> reduce)
  class IncrementReduceSyncNoBeforeWrapAsync3 (line 109) | class IncrementReduceSyncNoBeforeWrapAsync3 extends ReduxAction<State> {
    method reduce (line 111) | State reduce()
    method wrapReduce (line 114) | Future<State> wrapReduce(Reducer<State> reduce)

FILE: test/after_throws_test.dart
  function main (line 14) | void main()
  class ActionA (line 53) | class ActionA extends ReduxAction<String> {
    method before (line 55) | void before()
    method reduce (line 60) | String reduce()
    method after (line 66) | void after()

FILE: test/before_reduce_after_order_test.dart
  function main (line 9) | void main()
  class ActionA (line 160) | class ActionA extends ReduxAction<String> {
    method before (line 162) | void before()
    method reduce (line 167) | String reduce()
    method after (line 173) | void after()
  class ActionB (line 178) | class ActionB extends ReduxAction<String> {
    method before (line 180) | void before()
    method reduce (line 185) | Future<String> reduce()
    method after (line 193) | void after()
  class ActionC (line 198) | class ActionC extends ReduxAction<String> {
    method before (line 200) | Future<void> before()
    method reduce (line 205) | String reduce()
    method after (line 211) | void after()
  class ActionD (line 216) | class ActionD extends ReduxAction<String> {
    method before (line 218) | Future<void> before()
    method reduce (line 225) | String reduce()
    method after (line 231) | void after()
  class ActionE (line 236) | class ActionE extends ReduxAction<String> {
    method before (line 238) | void before()
    method reduce (line 243) | String reduce()
    method after (line 249) | void after()
  class ActionF (line 256) | class ActionF extends ReduxAction<String> {
    method before (line 258) | void before()
    method reduce (line 263) | Future<String> reduce()
    method after (line 271) | void after()

FILE: test/before_throwing_errors_test.dart
  function main (line 13) | void main()
  class ActionBeforeFutureOr (line 146) | class ActionBeforeFutureOr extends ReduxAction<String> {
    method before (line 148) | FutureOr<void> before()
    method reduce (line 153) | String reduce()
  class ActionSyncBeforeThrowsError (line 158) | class ActionSyncBeforeThrowsError extends ReduxAction<String> {
    method before (line 160) | void before()
    method reduce (line 165) | String reduce()
  class ActionAsyncBeforeThrowsError (line 170) | class ActionAsyncBeforeThrowsError extends ReduxAction<String> {
    method before (line 172) | Future<void> before()
    method reduce (line 178) | String reduce()
  class ActionAsyncBeforeThrowsErrorAsync (line 183) | class ActionAsyncBeforeThrowsErrorAsync extends ReduxAction<String> {
    method before (line 185) | Future<void> before()
    method reduce (line 191) | String reduce()
  class ActionB (line 196) | class ActionB extends ReduxAction<String> {
    method reduce (line 198) | String reduce()
  class ActionC (line 203) | class ActionC extends ReduxAction<String> {
    method reduce (line 205) | String reduce()
  class ActionSyncBeforeThrowsErrorWithWrapError (line 210) | class ActionSyncBeforeThrowsErrorWithWrapError extends ReduxAction<Strin...
    method before (line 212) | void before()
    method reduce (line 217) | String reduce()
    method wrapError (line 222) | Object? wrapError(Object error, StackTrace stackTrace)
  class ActionAsyncBeforeThrowsErrorWithWrapError (line 227) | class ActionAsyncBeforeThrowsErrorWithWrapError extends ReduxAction<Stri...
    method before (line 229) | Future<void> before()
    method reduce (line 235) | String reduce()
    method wrapError (line 240) | Object? wrapError(Object error, StackTrace stackTrace)
  class ActionAsyncBeforeThrowsErrorAsyncWithWrapError (line 245) | class ActionAsyncBeforeThrowsErrorAsyncWithWrapError extends ReduxAction...
    method before (line 247) | Future<void> before()
    method reduce (line 253) | String reduce()
    method wrapError (line 258) | Object? wrapError(Object error, StackTrace stackTrace)
  class ActionWithBeforeAndReducerThatThrowsErrorWithWrapError (line 261) | class ActionWithBeforeAndReducerThatThrowsErrorWithWrapError extends Red...
    method before (line 263) | void before()
    method reduce (line 266) | Future<String> reduce()
    method wrapError (line 272) | Object? wrapError(Object error, StackTrace stackTrace)
  class WrappedError (line 275) | class WrappedError {
    method toString (line 281) | String toString()

FILE: test/cache_test.dart
  function main (line 4) | void main()

FILE: test/check_internet_mixin_test.dart
  function main (line 3) | void main()

FILE: test/context_environment_test.dart
  function main (line 8) | void main()
  function select (line 271) | R select<R>(R Function(AppState state) selector)
  class TestEnvironment (line 277) | class TestEnvironment {
  class AppState (line 285) | class AppState {
    method copyWith (line 290) | AppState copyWith({int? counter})
  class IncrementAction (line 305) | class IncrementAction extends ReduxAction<AppState> {
    method reduce (line 307) | AppState reduce()

FILE: test/context_event_test.dart
  function main (line 8) | void main()
  function read (line 685) | AppState read()
  function select (line 686) | R select<R>(R Function(AppState state) selector)
  function event (line 688) | R? event<R>(Evt<R> Function(AppState state) selector)
  class AppState (line 693) | class AppState {
    method copyWith (line 704) | AppState copyWith({
  class AppStateWithIntEvent (line 729) | class AppStateWithIntEvent {
    method copyWith (line 735) | AppStateWithIntEvent copyWith({Event<int>? numberEvt, int? counter})
  class AppStateWithListEvent (line 754) | class AppStateWithListEvent {
    method copyWith (line 760) | AppStateWithListEvent copyWith({Event<List<String>>? itemsEvt, int? co...
  class AppStateWithTwoEvents (line 779) | class AppStateWithTwoEvents {
    method copyWith (line 790) | AppStateWithTwoEvents copyWith({
  class AppStateWithMappedEvent (line 815) | class AppStateWithMappedEvent {
    method copyWith (line 826) | AppStateWithMappedEvent copyWith({
  class ClearTextAction (line 851) | class ClearTextAction extends ReduxAction<AppState> {
    method reduce (line 853) | AppState reduce()
  class ChangeTextAction (line 858) | class ChangeTextAction extends ReduxAction<AppState> {
    method reduce (line 863) | AppState reduce()
  class IncrementCounterAction (line 868) | class IncrementCounterAction extends ReduxAction<AppState> {
    method reduce (line 870) | AppState reduce()
  class SetNumberAction (line 875) | class SetNumberAction extends ReduxAction<AppStateWithIntEvent> {
    method reduce (line 880) | AppStateWithIntEvent reduce()
  class SetItemsAction (line 885) | class SetItemsAction extends ReduxAction<AppStateWithListEvent> {
    method reduce (line 890) | AppStateWithListEvent reduce()
  class SetEvent1Action (line 895) | class SetEvent1Action extends ReduxAction<AppStateWithTwoEvents> {
    method reduce (line 900) | AppStateWithTwoEvents reduce()
  class SetEvent2Action (line 905) | class SetEvent2Action extends ReduxAction<AppStateWithTwoEvents> {
    method reduce (line 910) | AppStateWithTwoEvents reduce()
  class IncrementCounter2Action (line 915) | class IncrementCounter2Action extends ReduxAction<AppStateWithTwoEvents> {
    method reduce (line 917) | AppStateWithTwoEvents reduce()
  class SetIndexAction (line 922) | class SetIndexAction extends ReduxAction<AppStateWithMappedEvent> {
    method reduce (line 927) | AppStateWithMappedEvent reduce()
  class IncrementCounter3Action (line 932) | class IncrementCounter3Action extends ReduxAction<AppStateWithMappedEven...
    method reduce (line 934) | AppStateWithMappedEvent reduce()

FILE: test/context_select_advanced_test.dart
  function main (line 9) | void main()
  function read (line 462) | AppState read()
  function select (line 463) | R select<R>(R Function(AppState state) selector)
  function event (line 464) | R? event<R>(Evt<R> Function(AppState state) selector)
  class AppState (line 468) | class AppState {
    method copyWith (line 481) | AppState copyWith({
  class User (line 509) | class User {
    method copyWith (line 516) | User copyWith({String? name, int? age, String? email})
  class Settings (line 537) | class Settings {
    method copyWith (line 543) | Settings copyWith({bool? darkMode, String? language})
  class UpdateUserNameAction (line 563) | class UpdateUserNameAction extends ReduxAction<AppState> {
    method reduce (line 568) | AppState reduce()
  class UpdateUserAgeAction (line 573) | class UpdateUserAgeAction extends ReduxAction<AppState> {
    method reduce (line 578) | AppState reduce()
  class IncrementCounterAction (line 583) | class IncrementCounterAction extends ReduxAction<AppState> {
    method reduce (line 585) | AppState reduce()
  class AddItemAction (line 590) | class AddItemAction extends ReduxAction<AppState> {
    method reduce (line 595) | AppState reduce()
  class ToggleDarkModeAction (line 600) | class ToggleDarkModeAction extends ReduxAction<AppState> {
    method reduce (line 602) | AppState reduce()
  class SelectTestWidget (line 610) | class SelectTestWidget extends StatefulWidget {
    method createState (line 621) | State<SelectTestWidget> createState()
  class _SelectTestWidgetState (line 624) | class _SelectTestWidgetState extends State<SelectTestWidget> {
    method build (line 628) | Widget build(BuildContext context)
  class UserNameWidget (line 666) | class UserNameWidget extends StatelessWidget {
    method build (line 672) | Widget build(BuildContext context)
  class UserAgeWidget (line 679) | class UserAgeWidget extends StatelessWidget {
    method build (line 685) | Widget build(BuildContext context)
  class CounterWidget (line 692) | class CounterWidget extends StatelessWidget {
    method build (line 698) | Widget build(BuildContext context)
  class ItemsCountWidget (line 705) | class ItemsCountWidget extends StatelessWidget {
    method build (line 711) | Widget build(BuildContext context)
  class DarkModeWidget (line 718) | class DarkModeWidget extends StatelessWidget {
    method build (line 724) | Widget build(BuildContext context)
  class MultiSelectWidget (line 732) | class MultiSelectWidget extends StatelessWidget {
    method build (line 738) | Widget build(BuildContext context)
  class ComputedSelectWidget (line 756) | class ComputedSelectWidget extends StatelessWidget {
    method build (line 762) | Widget build(BuildContext context)
  class ListSelectWidget (line 777) | class ListSelectWidget extends StatelessWidget {
    method build (line 783) | Widget build(BuildContext context)

FILE: test/context_select_test.dart
  function main (line 7) | void main()
  function select (line 238) | R select<R>(R Function(TestState state) selector)
  class TestState (line 243) | class TestState {
    method copyWith (line 254) | TestState copyWith({
    method toString (line 267) | String toString()
  class IncrementAction (line 284) | class IncrementAction extends ReduxAction<TestState> {
    method reduce (line 286) | TestState reduce()
  class ChangeTextAction (line 289) | class ChangeTextAction extends ReduxAction<TestState> {
    method reduce (line 295) | TestState reduce()
  class ToggleFlagAction (line 298) | class ToggleFlagAction extends ReduxAction<TestState> {
    method reduce (line 300) | TestState reduce()
  class CounterSelectWidget (line 305) | class CounterSelectWidget extends StatelessWidget {
    method build (line 312) | Widget build(BuildContext context)
  class FlagSelectWidget (line 328) | class FlagSelectWidget extends StatelessWidget {
    method build (line 334) | Widget build(BuildContext context)
  class RegularStateWidget (line 350) | class RegularStateWidget extends StatelessWidget {
    method build (line 357) | Widget build(BuildContext context)

FILE: test/context_state_test.dart
  function main (line 8) | void main()
  function read (line 461) | AppState read()
  function select (line 463) | R select<R>(R Function(AppState state) selector)
  class AppState (line 468) | class AppState {
    method copyWith (line 479) | AppState copyWith({
  class ChangeNameAction (line 505) | class ChangeNameAction extends ReduxAction<AppState> {
    method reduce (line 511) | AppState reduce()
  class IncrementCounterAction (line 516) | class IncrementCounterAction extends ReduxAction<AppState> {
    method reduce (line 518) | AppState reduce()
  class ToggleFlagAction (line 523) | class ToggleFlagAction extends ReduxAction<AppState> {
    method reduce (line 525) | AppState reduce()
  class InitStateTestWidget (line 531) | class InitStateTestWidget extends StatefulWidget {
    method createState (line 540) | State<InitStateTestWidget> createState()
  class _InitStateTestWidgetState (line 543) | class _InitStateTestWidgetState extends State<InitStateTestWidget> {
    method initState (line 545) | void initState()
    method build (line 551) | Widget build(BuildContext context)

FILE: test/debounce_mixin_test.dart
  function main (line 5) | void main()
  class AppState (line 134) | class AppState {
    method copy (line 139) | AppState copy({int? count})
    method toString (line 142) | String toString()
  class DebounceAction (line 146) | class DebounceAction extends ReduxAction<AppState> with Debounce {
    method reduce (line 151) | AppState reduce()
  class DebounceAction1 (line 157) | class DebounceAction1 extends ReduxAction<AppState> with Debounce {
    method reduce (line 162) | AppState reduce()
  class DebounceAction2 (line 167) | class DebounceAction2 extends ReduxAction<AppState> with Debounce {
    method reduce (line 172) | AppState reduce()
  class DebounceActionA (line 178) | class DebounceActionA extends ReduxAction<AppState> with Debounce {
    method reduce (line 183) | AppState reduce()
  class DebounceActionB (line 188) | class DebounceActionB extends ReduxAction<AppState> with Debounce {
    method reduce (line 193) | AppState reduce()
  class DebounceActionAsync (line 201) | class DebounceActionAsync extends ReduxAction<AppState> with Debounce {
    method reduce (line 206) | Future<AppState> reduce()
  class DebounceAction1Async (line 213) | class DebounceAction1Async extends ReduxAction<AppState> with Debounce {
    method reduce (line 218) | Future<AppState> reduce()
  class DebounceAction2Async (line 224) | class DebounceAction2Async extends ReduxAction<AppState> with Debounce {
    method reduce (line 229) | Future<AppState> reduce()
  class DebounceActionAAsync (line 236) | class DebounceActionAAsync extends ReduxAction<AppState> with Debounce {
    method reduce (line 241) | Future<AppState> reduce()
  class DebounceActionBAsync (line 247) | class DebounceActionBAsync extends ReduxAction<AppState> with Debounce {
    method reduce (line 252) | Future<AppState> reduce()

FILE: test/dispatch_and_wait_all_actions_test.dart
  function main (line 5) | void main()
  class State (line 48) | class State {
  class IncrementSync (line 54) | class IncrementSync extends ReduxAction<State> {
    method reduce (line 56) | State reduce()
  class IncrementAsync (line 59) | class IncrementAsync extends ReduxAction<State> {
    method reduce (line 61) | Future<State> reduce()
  class DispatchMultipleActions (line 67) | class DispatchMultipleActions extends ReduxAction<State> {
    method reduce (line 69) | Future<State> reduce()

FILE: test/dispatch_and_wait_test.dart
  function main (line 5) | void main()
  class State (line 283) | class State {
  class IncrementSync (line 289) | class IncrementSync extends ReduxAction<State> {
    method reduce (line 291) | State reduce()
  class IncrementAsync (line 296) | class IncrementAsync extends ReduxAction<State> {
    method reduce (line 298) | Future<State> reduce()
  class IncrementSyncBeforeFails (line 304) | class IncrementSyncBeforeFails extends ReduxAction<State> {
    method before (line 306) | void before()
    method reduce (line 311) | State reduce()
  class IncrementSyncReduceFails (line 316) | class IncrementSyncReduceFails extends ReduxAction<State> {
    method reduce (line 318) | State reduce()
  class IncrementSyncAfterFails (line 323) | class IncrementSyncAfterFails extends ReduxAction<State> {
    method reduce (line 325) | State reduce()
    method after (line 330) | void after()
  class IncrementAsyncBeforeFails (line 335) | class IncrementAsyncBeforeFails extends ReduxAction<State> {
    method before (line 337) | Future<void> before()
    method reduce (line 342) | Future<State> reduce()
  class IncrementAsyncReduceFails (line 348) | class IncrementAsyncReduceFails extends ReduxAction<State> {
    method reduce (line 350) | Future<State> reduce()
  class IncrementAsyncAfterFails (line 356) | class IncrementAsyncAfterFails extends ReduxAction<State> {
    method reduce (line 358) | Future<State> reduce()
    method after (line 364) | Future<void> after()

FILE: test/dispatch_sync_test.dart
  function main (line 5) | void main()
  class State (line 29) | class State {
  class IncrementSync (line 35) | class IncrementSync extends ReduxAction<State> {
    method reduce (line 37) | State reduce()
  class IncrementAsyncBefore (line 40) | class IncrementAsyncBefore extends ReduxAction<State> {
    method before (line 42) | Future<void> before()
    method reduce (line 47) | State reduce()
  class IncrementAsyncReduce (line 50) | class IncrementAsyncReduce extends ReduxAction<State> {
    method reduce (line 52) | Future<State> reduce()
  class IncrementAsyncBeforeReduce (line 57) | class IncrementAsyncBeforeReduce extends ReduxAction<State> {
    method before (line 59) | Future<void> before()
    method reduce (line 64) | Future<State> reduce()

FILE: test/dispatch_test.dart
  function main (line 5) | void main()
  class State (line 65) | class State {
  class IncrementSync (line 71) | class IncrementSync extends ReduxAction<State> {
    method reduce (line 73) | State reduce()
  class IncrementAsync (line 78) | class IncrementAsync extends ReduxAction<State> {
    method reduce (line 80) | Future<State> reduce()

FILE: test/event_redux_test.dart
  function main (line 4) | void main()

FILE: test/failed_action_test.dart
  function main (line 5) | void main()
  class State (line 106) | class State {
  class SyncActionThatFails (line 112) | class SyncActionThatFails extends ReduxAction<State> {
    method reduce (line 118) | State? reduce()
  class AsyncActionThatFails (line 124) | class AsyncActionThatFails extends ReduxAction<State> {
    method reduce (line 130) | Future<State?> reduce()

FILE: test/fresh_mixin_test.dart
  function main (line 5) | void main()
  class AppState (line 1367) | class AppState {
    method copy (line 1372) | AppState copy({int? count})
    method toString (line 1375) | String toString()
  class FreshAction (line 1379) | class FreshAction extends ReduxAction<AppState> with Fresh {
    method reduce (line 1402) | AppState reduce()
  class FreshAction2 (line 1417) | class FreshAction2 extends ReduxAction<AppState> with Fresh {
    method reduce (line 1422) | AppState reduce()
  class FreshActionSharedKey1 (line 1428) | class FreshActionSharedKey1 extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1433) | Object computeFreshKey()
    method reduce (line 1436) | AppState reduce()
  class FreshActionSharedKey2 (line 1441) | class FreshActionSharedKey2 extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1446) | Object computeFreshKey()
    method reduce (line 1449) | AppState reduce()
  class FreshActionSharedKey2Fails (line 1454) | class FreshActionSharedKey2Fails extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1459) | Object computeFreshKey()
    method reduce (line 1462) | AppState reduce()
  class FreshActionWithParams (line 1468) | class FreshActionWithParams extends ReduxAction<AppState> with Fresh {
    method freshKeyParams (line 1477) | Object? freshKeyParams()
    method reduce (line 1480) | AppState reduce()
  class FreshActionConcurrentSlow (line 1486) | class FreshActionConcurrentSlow extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1501) | Object computeFreshKey()
    method reduce (line 1504) | Future<AppState> reduce()
  class FreshActionConcurrentFast (line 1516) | class FreshActionConcurrentFast extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1525) | Object computeFreshKey()
    method reduce (line 1528) | AppState reduce()
  class FreshActionConcurrentSlowIgnoreFresh (line 1537) | class FreshActionConcurrentSlowIgnoreFresh extends ReduxAction<AppState>
    method computeFreshKey (line 1556) | Object computeFreshKey()
    method reduce (line 1559) | Future<AppState> reduce()
  class OuterActionNested (line 1573) | class OuterActionNested extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1578) | Object computeFreshKey()
    method reduce (line 1584) | Future<AppState> reduce()
  class OverrideAction (line 1594) | class OverrideAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1599) | Object computeFreshKey()
    method reduce (line 1605) | AppState reduce()
  class CheckAction (line 1612) | class CheckAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1617) | Object computeFreshKey()
    method reduce (line 1623) | AppState reduce()
  class FreshWithThrottleAction (line 1630) | class FreshWithThrottleAction extends ReduxAction<AppState>
    method reduce (line 1642) | AppState reduce()
  class FreshWithNonReentrantAction (line 1648) | class FreshWithNonReentrantAction extends ReduxAction<AppState>
    method reduce (line 1657) | AppState reduce()
  class FreshWithUnlimitedRetryAction (line 1663) | class FreshWithUnlimitedRetryAction extends ReduxAction<AppState>
    method reduce (line 1672) | AppState reduce()
  class ThrottleWithNonReentrantAction (line 1678) | class ThrottleWithNonReentrantAction extends ReduxAction<AppState>
    method reduce (line 1687) | AppState reduce()
  class ThrottleWithUnlimitedRetryAction (line 1693) | class ThrottleWithUnlimitedRetryAction extends ReduxAction<AppState>
    method reduce (line 1702) | AppState reduce()
  class NonReentrantWithUnlimitedRetryAction (line 1708) | class NonReentrantWithUnlimitedRetryAction extends ReduxAction<AppState>
    method reduce (line 1714) | AppState reduce()
  class CheckInternetWithAbortWhenNoInternetAction (line 1720) | class CheckInternetWithAbortWhenNoInternetAction extends ReduxAction<App...
    method reduce (line 1726) | AppState reduce()
  class CheckInternetWithUnlimitedRetryAction (line 1732) | class CheckInternetWithUnlimitedRetryAction extends ReduxAction<AppState>
    method reduce (line 1738) | AppState reduce()
  class AbortWhenNoInternetWithUnlimitedRetryAction (line 1744) | class AbortWhenNoInternetWithUnlimitedRetryAction extends ReduxAction<Ap...
    method reduce (line 1750) | AppState reduce()
  class RapidTestActionSlow (line 1759) | class RapidTestActionSlow extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1768) | Object computeFreshKey()
    method reduce (line 1771) | Future<AppState> reduce()
  class RapidTestActionFast (line 1780) | class RapidTestActionFast extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1785) | Object computeFreshKey()
    method reduce (line 1791) | AppState reduce()
  class RapidTestActionCheck (line 1796) | class RapidTestActionCheck extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1801) | Object computeFreshKey()
    method reduce (line 1804) | AppState reduce()
  class TripleNestOuterAction (line 1813) | class TripleNestOuterAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1828) | Object computeFreshKey()
    method reduce (line 1831) | Future<AppState?> reduce()
  class TripleNestMiddleAction (line 1848) | class TripleNestMiddleAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1861) | Object computeFreshKey()
    method reduce (line 1867) | Future<AppState?> reduce()
  class TripleNestInnerAction (line 1881) | class TripleNestInnerAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1890) | Object computeFreshKey()
    method reduce (line 1896) | AppState reduce()
  class TripleNestCheckAction (line 1904) | class TripleNestCheckAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1909) | Object computeFreshKey()
    method reduce (line 1912) | AppState reduce()
  class RestoreTestActionA (line 1921) | class RestoreTestActionA extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1926) | Object computeFreshKey()
    method reduce (line 1929) | AppState reduce()
  class RestoreTestActionB (line 1934) | class RestoreTestActionB extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1939) | Object computeFreshKey()
    method reduce (line 1942) | AppState reduce()
  class RestoreTestActionC (line 1948) | class RestoreTestActionC extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1953) | Object computeFreshKey()
    method reduce (line 1956) | AppState reduce()
  class SequentialFailAction (line 1965) | class SequentialFailAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1974) | Object computeFreshKey()
    method reduce (line 1977) | AppState reduce()
  class SequentialSucceedAction (line 1982) | class SequentialSucceedAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 1987) | Object computeFreshKey()
    method reduce (line 1990) | AppState reduce()
  class OuterNormalInnerIgnoreFreshAction (line 1999) | class OuterNormalInnerIgnoreFreshAction extends ReduxAction<AppState>
    method computeFreshKey (line 2005) | Object computeFreshKey()
    method reduce (line 2008) | Future<AppState?> reduce()
  class InnerIgnoreFreshFailAction (line 2018) | class InnerIgnoreFreshFailAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 2023) | Object computeFreshKey()
    method reduce (line 2029) | AppState reduce()
  class OuterNormalCheckAction (line 2034) | class OuterNormalCheckAction extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 2039) | Object computeFreshKey()
    method reduce (line 2042) | AppState reduce()
  class ConcurrentIgnoreFreshAction (line 2051) | class ConcurrentIgnoreFreshAction extends ReduxAction<AppState> with Fre...
    method computeFreshKey (line 2066) | Object computeFreshKey()
    method reduce (line 2072) | Future<AppState> reduce()
  class ConcurrentIgnoreFreshCheck (line 2081) | class ConcurrentIgnoreFreshCheck extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 2086) | Object computeFreshKey()
    method reduce (line 2089) | AppState reduce()
  class AbortTestActionA (line 2098) | class AbortTestActionA extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 2103) | Object computeFreshKey()
    method reduce (line 2106) | AppState reduce()
  class AbortTestActionB (line 2111) | class AbortTestActionB extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 2116) | Object computeFreshKey()
    method reduce (line 2120) | AppState reduce()
  class AbortTestActionCheck (line 2125) | class AbortTestActionCheck extends ReduxAction<AppState> with Fresh {
    method computeFreshKey (line 2130) | Object computeFreshKey()
    method reduce (line 2133) | AppState reduce()

FILE: test/local_json_persist_test.dart
  type files (line 14) | enum files { abcd, xyzk }
  function main (line 16) | void main()

FILE: test/local_persist_test.dart
  type files (line 13) | enum files { abc, xyz }
  function main (line 15) | void main()

FILE: test/mock_build_context_test.dart
  function main (line 5) | void main()
  class AppState (line 234) | class AppState {
    method copy (line 245) | AppState copy({
  function read (line 273) | AppState read()
  function select (line 275) | R select<R>(R Function(AppState state) selector)
  function event (line 278) | R? event<R>(Evt<R> Function(AppState state) selector)
  class ChangeName (line 285) | class ChangeName extends ReduxAction<AppState> {
    method reduce (line 291) | AppState reduce()
  class ChangeAge (line 295) | class ChangeAge extends ReduxAction<AppState> {
    method reduce (line 301) | AppState reduce()
  class WaitAndChangeAge (line 305) | class WaitAndChangeAge extends ReduxAction<AppState> {
    method reduce (line 311) | Future<AppState> reduce()
  class DuplicateAge (line 318) | class DuplicateAge extends ReduxAction<AppState> {
    method reduce (line 320) | AppState reduce()
  class ChangeNameWithEvent (line 324) | class ChangeNameWithEvent extends ReduxAction<AppState> {
    method reduce (line 330) | AppState reduce()
  class MyWidget (line 337) | class MyWidget extends StatelessWidget {
    method build (line 364) | Widget build(BuildContext context)
  class MyConnector (line 381) | class MyConnector extends StatelessWidget {
    method build (line 383) | Widget build(BuildContext context)
  class TestEnvironment (line 412) | class TestEnvironment {

FILE: test/mock_store_test.dart
  class AppState (line 5) | @immutable
  class MyAction (line 12) | class MyAction extends ReduxAction<AppState> {
    method reduce (line 18) | AppState reduce()
  class MyAction1 (line 21) | class MyAction1 extends MyAction {
  class MyAction2 (line 25) | class MyAction2 extends MyAction {
  class MyAction3 (line 29) | class MyAction3 extends MyAction {
  class MyAction4 (line 33) | class MyAction4 extends MyAction {
  class MyAction5 (line 37) | class MyAction5 extends MyAction {
  class MyMockAction (line 41) | class MyMockAction extends MockAction<AppState> {
    method reduce (line 43) | AppState reduce()
  function main (line 46) | void main()
  function createMockStoreTester (line 47) | StoreTester<AppState> createMockStoreTester()

FILE: test/model_observer_test.dart
  function main (line 5) | void main()
  class _TestApp (line 76) | class _TestApp extends StatelessWidget {
    method build (line 82) | Widget build(BuildContext context)
  class _StateTest (line 85) | @immutable
  class _MyWidgetConnector (line 93) | class _MyWidgetConnector extends StatelessWidget {
    method build (line 97) | Widget build(BuildContext context)
  class _MyAction (line 104) | class _MyAction extends ReduxAction<_StateTest> {
    method reduce (line 111) | _StateTest reduce()

FILE: test/navigate_action_test.dart
  class AppState (line 15) | class AppState {}
  class MyApp (line 17) | class MyApp extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)
  class MyPage (line 31) | class MyPage extends StatelessWidget {
    method build (line 35) | Widget build(BuildContext context)
  function main (line 79) | void main()

FILE: test/non_reentrant_test.dart
  function main (line 5) | void main()
  class State (line 314) | class State {
    method toString (line 320) | String toString()
  class NonReentrantSyncActionCallsItself (line 323) | class NonReentrantSyncActionCallsItself extends ReduxAction<State>
    method reduce (line 326) | State reduce()
  class NonReentrantAsyncActionCallsItself (line 332) | class NonReentrantAsyncActionCallsItself extends ReduxAction<State>
    method reduce (line 335) | Future<State> reduce()
  class NonReentrantAsyncAction (line 341) | class NonReentrantAsyncAction extends ReduxAction<State> with NonReentra...
    method reduce (line 348) | Future<State> reduce()
  class NonReentrantFailingAction (line 355) | class NonReentrantFailingAction extends ReduxAction<State> with NonReent...
    method reduce (line 357) | Future<State> reduce()
  class NonReentrantWithParams (line 364) | class NonReentrantWithParams extends ReduxAction<State> with NonReentrant {
    method nonReentrantKeyParams (line 372) | Object? nonReentrantKeyParams()
    method reduce (line 375) | Future<State> reduce()
  class NonReentrantWithParamsFails (line 382) | class NonReentrantWithParamsFails extends ReduxAction<State> with NonRee...
    method nonReentrantKeyParams (line 388) | Object? nonReentrantKeyParams()
    method reduce (line 391) | Future<State> reduce()
  class NonReentrantSharedKey1 (line 398) | class NonReentrantSharedKey1 extends ReduxAction<State> with NonReentrant {
    method computeNonReentrantKey (line 405) | Object computeNonReentrantKey()
    method reduce (line 408) | Future<State> reduce()
  class NonReentrantSharedKey2 (line 415) | class NonReentrantSharedKey2 extends ReduxAction<State> with NonReentrant {
    method computeNonReentrantKey (line 422) | Object computeNonReentrantKey()
    method reduce (line 425) | Future<State> reduce()

FILE: test/optimistic_command_mixin_test.dart
  function main (line 5) | void main()
  class AppState (line 1260) | class AppState {
    method copy (line 1265) | AppState copy({List<String>? items})
    method toString (line 1268) | String toString()
  class SaveItemAction (line 1276) | class SaveItemAction extends ReduxAction<AppState>
    method optimisticValue (line 1284) | Object? optimisticValue()
    method getValueFromState (line 1287) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1290) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1297) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1302) | Future<Object?> reloadFromServer()
    method shouldReload (line 1308) | bool shouldReload({
  class SaveItemActionThatFails (line 1319) | class SaveItemActionThatFails extends ReduxAction<AppState>
    method optimisticValue (line 1327) | Object? optimisticValue()
    method getValueFromState (line 1330) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1333) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1337) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1344) | Future<Object?> reloadFromServer()
  class SaveItemActionThatFailsWithStateLog (line 1350) | class SaveItemActionThatFailsWithStateLog extends ReduxAction<AppState>
    method optimisticValue (line 1358) | Object? optimisticValue()
    method getValueFromState (line 1361) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1364) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1371) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1377) | Future<Object?> reloadFromServer()
  class SaveItemActionThatFailsAfterStateChange (line 1384) | class SaveItemActionThatFailsAfterStateChange extends ReduxAction<AppState>
    method optimisticValue (line 1394) | Object? optimisticValue()
    method getValueFromState (line 1397) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1400) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1413) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1422) | Future<Object?> reloadFromServer()
  class ChangeStateAction (line 1428) | class ChangeStateAction extends ReduxAction<AppState> {
    method reduce (line 1430) | AppState reduce()
  class SaveItemActionWithoutReload (line 1434) | class SaveItemActionWithoutReload extends ReduxAction<AppState>
    method optimisticValue (line 1442) | Object? optimisticValue()
    method getValueFromState (line 1445) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1448) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1455) | Future<void> sendCommandToServer(Object? newValue)
  class SaveItemActionWithoutReloadThatFails (line 1463) | class SaveItemActionWithoutReloadThatFails extends ReduxAction<AppState>
    method optimisticValue (line 1471) | Object? optimisticValue()
    method getValueFromState (line 1474) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1477) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1484) | Future<void> sendCommandToServer(Object? newValue)
  class SaveItemActionWithRetryNoReload (line 1493) | class SaveItemActionWithRetryNoReload extends ReduxAction<AppState>
    method optimisticValue (line 1509) | Object? optimisticValue()
    method getValueFromState (line 1512) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1515) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1522) | Future<void> sendCommandToServer(Object? newValue)
  class SaveItemActionWithRetry (line 1534) | class SaveItemActionWithRetry extends ReduxAction<AppState>
    method optimisticValue (line 1550) | Object? optimisticValue()
    method getValueFromState (line 1553) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1556) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1563) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1572) | Future<Object?> reloadFromServer()
    method shouldReload (line 1578) | bool shouldReload({
  class SaveItemActionWithRetryThatAlwaysFails (line 1589) | class SaveItemActionWithRetryThatAlwaysFails extends ReduxAction<AppState>
    method optimisticValue (line 1603) | Object? optimisticValue()
    method getValueFromState (line 1606) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1609) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1616) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1622) | Future<Object?> reloadFromServer()
  class SaveItemActionWithCustomRollback (line 1632) | class SaveItemActionWithCustomRollback extends ReduxAction<AppState>
    method optimisticValue (line 1641) | Object? optimisticValue()
    method getValueFromState (line 1644) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1647) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1654) | Future<void> sendCommandToServer(Object? newValue)
    method rollbackState (line 1660) | AppState? rollbackState({
  class SaveItemActionWithRollbackReturningNull (line 1677) | class SaveItemActionWithRollbackReturningNull extends ReduxAction<AppState>
    method optimisticValue (line 1685) | Object? optimisticValue()
    method getValueFromState (line 1688) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1691) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1698) | Future<void> sendCommandToServer(Object? newValue)
    method rollbackState (line 1704) | AppState? rollbackState({
  class SaveItemActionWithAlwaysRollback (line 1717) | class SaveItemActionWithAlwaysRollback extends ReduxAction<AppState>
    method optimisticValue (line 1726) | Object? optimisticValue()
    method getValueFromState (line 1729) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1732) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1739) | Future<void> sendCommandToServer(Object? newValue)
    method shouldRollback (line 1748) | bool shouldRollback({
  class SaveItemActionWithNeverRollback (line 1762) | class SaveItemActionWithNeverRollback extends ReduxAction<AppState>
    method optimisticValue (line 1770) | Object? optimisticValue()
    method getValueFromState (line 1773) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1776) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1783) | Future<void> sendCommandToServer(Object? newValue)
    method shouldRollback (line 1789) | bool shouldRollback({
  class SaveItemActionWithConditionalRollback (line 1803) | class SaveItemActionWithConditionalRollback extends ReduxAction<AppState>
    method optimisticValue (line 1813) | Object? optimisticValue()
    method getValueFromState (line 1816) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1819) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1826) | Future<void> sendCommandToServer(Object? newValue)
    method shouldRollback (line 1836) | bool shouldRollback({
  class SaveItemActionWithConditionalReload (line 1853) | class SaveItemActionWithConditionalReload extends ReduxAction<AppState>
    method optimisticValue (line 1863) | Object? optimisticValue()
    method getValueFromState (line 1866) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1869) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1876) | Future<void> sendCommandToServer(Object? newValue)
    method shouldReload (line 1882) | bool shouldReload({
    method reloadFromServer (line 1894) | Future<Object?> reloadFromServer()
  class SaveItemActionWithConditionalApplyReload (line 1901) | class SaveItemActionWithConditionalApplyReload extends ReduxAction<AppSt...
    method optimisticValue (line 1915) | Object? optimisticValue()
    method getValueFromState (line 1918) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1921) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1928) | Future<void> sendCommandToServer(Object? newValue)
    method shouldApplyReload (line 1933) | bool shouldApplyReload({
    method reloadFromServer (line 1946) | Future<Object?> reloadFromServer()
    method shouldReload (line 1956) | bool shouldReload({
  class SaveItemActionWithCustomApplyReload (line 1967) | class SaveItemActionWithCustomApplyReload extends ReduxAction<AppState>
    method optimisticValue (line 1975) | Object? optimisticValue()
    method getValueFromState (line 1978) | Object? getValueFromState(AppState state)
    method applyValueToState (line 1981) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 1988) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 1993) | Future<Object?> reloadFromServer()
    method applyReloadResultToState (line 2002) | AppState? applyReloadResultToState(AppState state, Object? reloadResult)
    method shouldReload (line 2011) | bool shouldReload({
  class SaveItemActionWithApplyReloadReturningNull (line 2022) | class SaveItemActionWithApplyReloadReturningNull extends ReduxAction<App...
    method optimisticValue (line 2031) | Object? optimisticValue()
    method getValueFromState (line 2034) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2037) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2044) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 2049) | Future<Object?> reloadFromServer()
    method applyReloadResultToState (line 2055) | AppState? applyReloadResultToState(AppState state, Object? reloadResult)
    method shouldReload (line 2061) | bool shouldReload({
  class SaveItemActionWithReloadThatThrows (line 2076) | class SaveItemActionWithReloadThatThrows extends ReduxAction<AppState>
    method optimisticValue (line 2083) | Object? optimisticValue()
    method getValueFromState (line 2086) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2089) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2093) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 2099) | Future<Object?> reloadFromServer()
    method shouldReload (line 2104) | bool shouldReload({
  class SaveItemActionWithBothCommandAndReloadThatThrow (line 2115) | class SaveItemActionWithBothCommandAndReloadThatThrow
    method optimisticValue (line 2122) | Object? optimisticValue()
    method getValueFromState (line 2125) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2128) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2132) | Future<void> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 2138) | Future<Object?> reloadFromServer()
  class SaveItemActionWithShouldReloadFalseOnError (line 2144) | class SaveItemActionWithShouldReloadFalseOnError extends ReduxAction<App...
    method optimisticValue (line 2152) | Object? optimisticValue()
    method getValueFromState (line 2155) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2158) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2162) | Future<void> sendCommandToServer(Object? newValue)
    method shouldReload (line 2168) | bool shouldReload({
    method reloadFromServer (line 2180) | Future<Object?> reloadFromServer()
  class SaveItemActionWithShouldApplyReloadFalseOnError (line 2187) | class SaveItemActionWithShouldApplyReloadFalseOnError
    method optimisticValue (line 2195) | Object? optimisticValue()
    method getValueFromState (line 2198) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2201) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2205) | Future<void> sendCommandToServer(Object? newValue)
    method shouldApplyReload (line 2211) | bool shouldApplyReload({
    method reloadFromServer (line 2224) | Future<Object?> reloadFromServer()
  class SaveItemActionCaptureLastAppliedOnError (line 2231) | class SaveItemActionCaptureLastAppliedOnError extends ReduxAction<AppState>
    method optimisticValue (line 2240) | Object? optimisticValue()
    method getValueFromState (line 2243) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2246) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2250) | Future<void> sendCommandToServer(Object? newValue)
    method shouldReload (line 2256) | bool shouldReload({
  class SaveItemActionCaptureLastAppliedOnSuccess (line 2271) | class SaveItemActionCaptureLastAppliedOnSuccess extends ReduxAction<AppS...
    method optimisticValue (line 2281) | Object? optimisticValue()
    method getValueFromState (line 2288) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2291) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2295) | Future<void> sendCommandToServer(Object? newValue)
    method shouldReload (line 2301) | bool shouldReload({
  class SaveItemActionWithOptimisticValueCounter (line 2316) | class SaveItemActionWithOptimisticValueCounter extends ReduxAction<AppSt...
    method optimisticValue (line 2336) | Object? optimisticValue()
    method getValueFromState (line 2342) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2345) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2349) | Future<void> sendCommandToServer(Object? newValue)
  class SaveItemActionCheckIdentity (line 2361) | class SaveItemActionCheckIdentity extends ReduxAction<AppState>
    method optimisticValue (line 2370) | Object? optimisticValue()
    method getValueFromState (line 2377) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2380) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2384) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandSlowAction (line 2397) | class OptimisticCommandSlowAction extends ReduxAction<AppState>
    method optimisticValue (line 2405) | Object? optimisticValue()
    method getValueFromState (line 2408) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2411) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2415) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandFailingAction (line 2423) | class OptimisticCommandFailingAction extends ReduxAction<AppState>
    method optimisticValue (line 2426) | Object? optimisticValue()
    method getValueFromState (line 2429) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2432) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2436) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandWithParams (line 2445) | class OptimisticCommandWithParams extends ReduxAction<AppState>
    method nonReentrantKeyParams (line 2455) | Object? nonReentrantKeyParams()
    method optimisticValue (line 2458) | Object? optimisticValue()
    method getValueFromState (line 2461) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2464) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2468) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandWithParamsThatFails (line 2476) | class OptimisticCommandWithParamsThatFails extends ReduxAction<AppState>
    method nonReentrantKeyParams (line 2483) | Object? nonReentrantKeyParams()
    method optimisticValue (line 2486) | Object? optimisticValue()
    method getValueFromState (line 2489) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2492) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2496) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandSharedKey1 (line 2505) | class OptimisticCommandSharedKey1 extends ReduxAction<AppState>
    method computeNonReentrantKey (line 2513) | Object computeNonReentrantKey()
    method optimisticValue (line 2516) | Object? optimisticValue()
    method getValueFromState (line 2519) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2522) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2526) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandSharedKey2 (line 2534) | class OptimisticCommandSharedKey2 extends ReduxAction<AppState>
    method computeNonReentrantKey (line 2542) | Object computeNonReentrantKey()
    method optimisticValue (line 2545) | Object? optimisticValue()
    method getValueFromState (line 2548) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2551) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2555) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandWithNonReentrant (line 2563) | class OptimisticCommandWithNonReentrant extends ReduxAction<AppState>
    method optimisticValue (line 2570) | Object? optimisticValue()
    method getValueFromState (line 2573) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2576) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2580) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandWithThrottle (line 2586) | class OptimisticCommandWithThrottle extends ReduxAction<AppState>
    method optimisticValue (line 2593) | Object? optimisticValue()
    method getValueFromState (line 2596) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2599) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2603) | Future<void> sendCommandToServer(Object? newValue)
  class OptimisticCommandWithFresh (line 2609) | class OptimisticCommandWithFresh extends ReduxAction<AppState>
    method optimisticValue (line 2616) | Object? optimisticValue()
    method getValueFromState (line 2619) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2622) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2626) | Future<Object?> sendCommandToServer(Object? newValue)
  class SaveItemActionWithDefaultShouldReloadOnSuccess (line 2638) | class SaveItemActionWithDefaultShouldReloadOnSuccess
    method optimisticValue (line 2647) | Object? optimisticValue()
    method getValueFromState (line 2650) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2653) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2660) | Future<Object?> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 2666) | Future<Object?> reloadFromServer()
  class SaveItemActionWithDefaultShouldReloadOnFailure (line 2676) | class SaveItemActionWithDefaultShouldReloadOnFailure
    method optimisticValue (line 2685) | Object? optimisticValue()
    method getValueFromState (line 2688) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2691) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2698) | Future<Object?> sendCommandToServer(Object? newValue)
    method reloadFromServer (line 2704) | Future<Object?> reloadFromServer()
  class SaveItemActionWithServerResponse (line 2717) | class SaveItemActionWithServerResponse extends ReduxAction<AppState>
    method optimisticValue (line 2727) | Object? optimisticValue()
    method getValueFromState (line 2730) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2733) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2740) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2747) | AppState? applyServerResponseToState(AppState state, Object serverResp...
  class SaveItemActionWithNullServerResponse (line 2757) | class SaveItemActionWithNullServerResponse extends ReduxAction<AppState>
    method optimisticValue (line 2766) | Object? optimisticValue()
    method getValueFromState (line 2769) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2772) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2779) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2785) | AppState? applyServerResponseToState(AppState state, Object serverResp...
  class SaveItemActionWithServerResponseReturningNull (line 2792) | class SaveItemActionWithServerResponseReturningNull
    method optimisticValue (line 2801) | Object? optimisticValue()
    method getValueFromState (line 2804) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2807) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2814) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2820) | AppState? applyServerResponseToState(AppState state, Object serverResp...
  class SaveItemActionWithServerResponseAndReload (line 2827) | class SaveItemActionWithServerResponseAndReload extends ReduxAction<AppS...
    method optimisticValue (line 2836) | Object? optimisticValue()
    method getValueFromState (line 2839) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2842) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2849) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2855) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method reloadFromServer (line 2861) | Future<Object?> reloadFromServer()
    method shouldReload (line 2867) | bool shouldReload({
  class SaveItemActionWithServerResponseThatFails (line 2878) | class SaveItemActionWithServerResponseThatFails extends ReduxAction<AppS...
    method optimisticValue (line 2887) | Object? optimisticValue()
    method getValueFromState (line 2890) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2893) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2900) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2906) | AppState? applyServerResponseToState(AppState state, Object serverResp...
  class SaveItemActionWithRetryAndServerResponse (line 2913) | class SaveItemActionWithRetryAndServerResponse extends ReduxAction<AppSt...
    method optimisticValue (line 2931) | Object? optimisticValue()
    method getValueFromState (line 2934) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2937) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2944) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2955) | AppState? applyServerResponseToState(AppState state, Object serverResp...
  class SaveItemActionWithServerResponseTransformation (line 2962) | class SaveItemActionWithServerResponseTransformation
    method optimisticValue (line 2970) | Object? optimisticValue()
    method getValueFromState (line 2973) | Object? getValueFromState(AppState state)
    method applyValueToState (line 2976) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 2983) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 2994) | AppState? applyServerResponseToState(AppState state, Object serverResp...
  class SaveItemActionWithDefaultShouldReloadAndServerResponse (line 3006) | class SaveItemActionWithDefaultShouldReloadAndServerResponse
    method optimisticValue (line 3016) | Object? optimisticValue()
    method getValueFromState (line 3019) | Object? getValueFromState(AppState state)
    method applyValueToState (line 3022) | AppState applyValueToState(AppState state, Object? value)
    method sendCommandToServer (line 3029) | Future<Object?> sendCommandToServer(Object? newValue)
    method applyServerResponseToState (line 3036) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method reloadFromServer (line 3042) | Future<Object?> reloadFromServer()

FILE: test/optimistic_sync_test.dart
  function main (line 7) | void main()
  class AppState (line 747) | class AppState {
    method copy (line 758) | AppState copy({bool? liked, Map<String, bool>? items, int? count})
    method toString (line 766) | String toString()
  class ToggleLikeAction (line 780) | class ToggleLikeAction extends ReduxAction<AppState>
    method valueToApply (line 783) | bool valueToApply()
    method getValueFromState (line 786) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 789) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 793) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 797) | Future<Object?> sendValueToServer(Object? value)
    method onFinish (line 816) | Future<AppState?> onFinish(Object? error)
  class ToggleLikeItemAction (line 823) | class ToggleLikeItemAction extends ReduxAction<AppState>
    method optimisticSyncKeyParams (line 830) | Object? optimisticSyncKeyParams()
    method valueToApply (line 833) | bool valueToApply()
    method getValueFromState (line 836) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 839) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 846) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 853) | Future<Object?> sendValueToServer(Object? value)
    method onFinish (line 865) | Future<AppState?> onFinish(Object? error)
  class ServerResponseAction (line 873) | class ServerResponseAction extends ReduxAction<AppState>
    method valueToApply (line 880) | int valueToApply()
    method getValueFromState (line 883) | int getValueFromState(AppState state)
    method applyOptimisticValueToState (line 886) | AppState applyOptimisticValueToState(state, int optimisticValueToApply)
    method applyServerResponseToState (line 890) | AppState? applyServerResponseToState(state, Object serverResponse)
    method sendValueToServer (line 896) | Future<Object?> sendValueToServer(Object? value)
    method onFinish (line 908) | Future<AppState?> onFinish(Object? error)
  class IgnoreServerResponseAction (line 915) | class IgnoreServerResponseAction extends ReduxAction<AppState>
    method valueToApply (line 922) | int valueToApply()
    method getValueFromState (line 925) | int getValueFromState(AppState state)
    method applyOptimisticValueToState (line 928) | AppState applyOptimisticValueToState(state, int optimisticValueToApply)
    method applyServerResponseToState (line 932) | AppState? applyServerResponseToState(state, Object serverResponse)
    method sendValueToServer (line 938) | Future<Object?> sendValueToServer(Object? value)
    method onFinish (line 945) | Future<AppState?> onFinish(Object? error)
  class SharedKeyAction1 (line 952) | class SharedKeyAction1 extends ReduxAction<AppState>
    method computeOptimisticSyncKey (line 955) | Object computeOptimisticSyncKey()
    method valueToApply (line 958) | int valueToApply()
    method getValueFromState (line 961) | int getValueFromState(AppState state)
    method applyOptimisticValueToState (line 964) | AppState applyOptimisticValueToState(state, int optimisticValueToApply)
    method applyServerResponseToState (line 968) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 972) | Future<Object?> sendValueToServer(Object? value)
  class SharedKeyAction2 (line 982) | class SharedKeyAction2 extends ReduxAction<AppState>
    method computeOptimisticSyncKey (line 985) | Object computeOptimisticSyncKey()
    method valueToApply (line 988) | int valueToApply()
    method getValueFromState (line 991) | int getValueFromState(AppState state)
    method applyOptimisticValueToState (line 994) | AppState applyOptimisticValueToState(state, int optimisticValueToApply)
    method applyServerResponseToState (line 998) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1002) | Future<Object?> sendValueToServer(Object? value)
  class OptimisticSyncWithNonReentrantAction (line 1015) | class OptimisticSyncWithNonReentrantAction extends ReduxAction<AppState>
    method valueToApply (line 1021) | bool valueToApply()
    method getValueFromState (line 1024) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 1027) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 1031) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1035) | Future<Object?> sendValueToServer(Object? value)
  class OptimisticSyncWithThrottleAction (line 1038) | class OptimisticSyncWithThrottleAction extends ReduxAction<AppState>
    method valueToApply (line 1044) | bool valueToApply()
    method getValueFromState (line 1047) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 1050) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 1054) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1058) | Future<Object?> sendValueToServer(Object? value)
  class OptimisticSyncWithDebounceAction (line 1061) | class OptimisticSyncWithDebounceAction extends ReduxAction<AppState>
    method valueToApply (line 1067) | bool valueToApply()
    method getValueFromState (line 1070) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 1073) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 1077) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1081) | Future<Object?> sendValueToServer(Object? value)
  class OptimisticSyncWithFreshAction (line 1084) | class OptimisticSyncWithFreshAction extends ReduxAction<AppState>
    method valueToApply (line 1090) | bool valueToApply()
    method getValueFromState (line 1093) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 1096) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 1100) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1104) | Future<Object?> sendValueToServer(Object? value)
  class OptimisticSyncWithUnlimitedRetryCheckInternetAction (line 1107) | class OptimisticSyncWithUnlimitedRetryCheckInternetAction
    method valueToApply (line 1114) | bool valueToApply()
    method getValueFromState (line 1117) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 1120) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 1124) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1128) | Future<Object?> sendValueToServer(Object? value)
  class OptimisticSyncWithUnlimitedRetriesAction (line 1131) | class OptimisticSyncWithUnlimitedRetriesAction extends ReduxAction<AppSt...
    method valueToApply (line 1139) | bool valueToApply()
    method getValueFromState (line 1142) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 1145) | AppState applyOptimisticValueToState(state, bool optimisticValueToApply)
    method applyServerResponseToState (line 1149) | AppState applyServerResponseToState(state, Object? serverResponse)
    method sendValueToServer (line 1153) | Future<Object?> sendValueToServer(Object? value)
  class SimulatePushAction (line 1197) | class SimulatePushAction extends ReduxAction<AppState> {
    method reduce (line 1203) | AppState reduce()

FILE: test/optimistic_sync_with_push_test.dart
  function main (line 19) | void main()
  class AppState (line 513) | class AppState {
    method copy (line 526) | AppState copy({
    method toString (line 540) | String toString()
  function resetTestState (line 553) | void resetTestState()
  class ToggleLikeActionNoRevisions (line 564) | class ToggleLikeActionNoRevisions extends ReduxAction<AppState>
    method valueToApply (line 567) | bool valueToApply()
    method getValueFromState (line 570) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 573) | AppState applyOptimisticValueToState(state, bool optimisticValue)
    method applyServerResponseToState (line 577) | AppState? applyServerResponseToState(state, Object serverResponse)
    method sendValueToServer (line 581) | Future<Object?> sendValueToServer(
    method onFinish (line 600) | Future<AppState?> onFinish(Object? error)
    method getServerRevisionFromState (line 606) | int getServerRevisionFromState(Object? key)
  class ToggleLikeActionWithRevisions (line 616) | class ToggleLikeActionWithRevisions extends ReduxAction<AppState>
    method valueToApply (line 621) | bool valueToApply()
    method getValueFromState (line 624) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 627) | AppState applyOptimisticValueToState(state, bool optimisticValue)
    method applyServerResponseToState (line 631) | AppState? applyServerResponseToState(state, Object serverResponse)
    method sendValueToServer (line 639) | Future<Object?> sendValueToServer(
    method onFinish (line 665) | Future<AppState?> onFinish(Object? error)
    method getServerRevisionFromState (line 671) | int getServerRevisionFromState(Object? key)
  class SimulatePushWithRevisionAction (line 679) | class SimulatePushWithRevisionAction extends ReduxAction<AppState>
    method associatedAction (line 694) | Type associatedAction()
    method pushMetadata (line 697) | PushMetadata pushMetadata()
    method applyServerPushToState (line 704) | AppState? applyServerPushToState(
    method getServerRevisionFromState (line 710) | int getServerRevisionFromState(Object? key)

FILE: test/persistence_test.dart
  function main (line 7) | void main()
  function duration (line 12) | Duration duration(int value)
  function setupPersistorAndLocalDb (line 17) | Future<void> setupPersistorAndLocalDb({
  function createStoreTester (line 27) | Future<StoreTester<AppState>> createStoreTester()
  function printResults (line 44) | void printResults(List<Object> results)
  function writeStateAndDb (line 719) | String writeStateAndDb(StoreTester<AppState> storeTester, LocalDb localDb)
  class AppState (line 724) | @immutable
    method initialState (line 732) | AppState initialState()
    method copy (line 736) | AppState copy({
    method toString (line 742) | String toString()
  class Id (line 753) | class Id {
    method toString (line 759) | String toString()
  class LocalDb (line 770) | abstract class LocalDb<T> {
    method getDb (line 780) | T getDb(String? name)
    method init (line 788) | Future<void> init(Iterable<String> dbNames)
    method createDatabases (line 793) | Future<void> createDatabases()
    method deleteDatabases (line 795) | Future<void> deleteDatabases()
    method save (line 797) | Future<void> save({
    method get (line 803) | Object? get({
    method getOrThrow (line 810) | Object? getOrThrow({
  class NotFound (line 817) | class NotFound {
  class SavedInfo (line 823) | class SavedInfo {
    method toString (line 831) | String toString()
  class LocalDbInMemory (line 847) | class LocalDbInMemory extends LocalDb<List<SavedInfo>> {
    method init (line 853) | Future<void> init(Iterable<String> dbNames)
    method createDatabases (line 864) | Future<void> createDatabases()
    method deleteDatabases (line 867) | Future<void> deleteDatabases()
    method save (line 870) | Future<void> save({
    method get (line 888) | Object? get({
    method getOrThrow (line 914) | Object? getOrThrow({
  class MyPersistor (line 935) | class MyPersistor implements Persistor<AppState> {
    method init (line 955) | Future<void> init()
    method saveInitialState (line 960) | Future<void> saveInitialState(AppState? state)
    method persistDifference (line 968) | Future<void> persistDifference({
    method readState (line 982) | Future<AppState?> readState()
    method deleteState (line 990) | Future<void> deleteState()
  class ChangeNameAction (line 995) | class ChangeNameAction extends ReduxAction<AppState> {
    method reduce (line 1001) | AppState reduce()
  class X (line 1004) | class X {
    method printValue (line 1007) | void printValue(int v)

FILE: test/polling_mixin_test.dart
  function main (line 6) | void main()
  class AppState (line 1090) | class AppState {
    method copy (line 1095) | AppState copy({int? count})
    method toString (line 1098) | String toString()
  class SimplePollAction (line 1105) | class SimplePollAction extends ReduxAction<AppState> with Polling {
    method createPollingAction (line 1115) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1119) | AppState reduce()
  class PollActionA (line 1126) | class PollActionA extends ReduxAction<AppState> with Polling {
    method createPollingAction (line 1136) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1139) | AppState reduce()
  class PollActionB (line 1142) | class PollActionB extends ReduxAction<AppState> with Polling {
    method createPollingAction (line 1152) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1155) | AppState reduce()
  class ParamPollAction (line 1162) | class ParamPollAction extends ReduxAction<AppState> with Polling {
    method pollingKeyParams (line 1173) | Object? pollingKeyParams()
    method createPollingAction (line 1176) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1180) | AppState reduce()
  class TupleParamPollAction (line 1187) | class TupleParamPollAction extends ReduxAction<AppState> with Polling {
    method pollingKeyParams (line 1199) | Object? pollingKeyParams()
    method createPollingAction (line 1202) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1206) | AppState reduce()
  class SharedKeyActionA (line 1213) | class SharedKeyActionA extends ReduxAction<AppState> with Polling {
    method computePollingKey (line 1223) | Object computePollingKey()
    method createPollingAction (line 1226) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1230) | AppState reduce()
  class SharedKeyActionB (line 1233) | class SharedKeyActionB extends ReduxAction<AppState> with Polling {
    method computePollingKey (line 1243) | Object computePollingKey()
    method createPollingAction (line 1246) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1250) | AppState reduce()
  class SingleAction (line 1257) | class SingleAction extends ReduxAction<AppState> with Polling {
    method createPollingAction (line 1267) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1270) | AppState reduce()
  class ControllerAction (line 1277) | class ControllerAction extends ReduxAction<AppState> with Polling {
    method createPollingAction (line 1287) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1290) | AppState reduce()
  class WorkerAction (line 1293) | class WorkerAction extends ReduxAction<AppState> {
    method reduce (line 1295) | AppState reduce()
  class PollingWithRetryAction (line 1303) | class PollingWithRetryAction extends ReduxAction<AppState>
    method createPollingAction (line 1317) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1321) | AppState reduce()
  class PollingWithUnlimitedRetriesAction (line 1325) | class PollingWithUnlimitedRetriesAction extends ReduxAction<AppState>
    method createPollingAction (line 1340) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1344) | AppState reduce()
  class PollingWithDebounceAction (line 1348) | class PollingWithDebounceAction extends ReduxAction<AppState>
    method createPollingAction (line 1362) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1366) | AppState reduce()
  class PollingWithUnlimitedRetryCheckInternetAction (line 1370) | class PollingWithUnlimitedRetryCheckInternetAction
    method createPollingAction (line 1385) | ReduxAction<AppState> createPollingAction()
    method reduce (line 1389) | AppState reduce()
  class PollingWithOptimisticCommandAction (line 1393) | class PollingWithOptimisticCommandAction extends ReduxAction<AppState>
    method createPollingAction (line 1407) | ReduxAction<AppState> createPollingAction()
    method optimisticValue (line 1411) | Object? optimisticValue()
    method applyValueToState (line 1414) | AppState applyValueToState(AppState state, Object? value)
    method getValueFromState (line 1417) | Object? getValueFromState(AppState state)
    method sendCommandToServer (line 1420) | Future<Object?> sendCommandToServer(Object? optimisticValue)
    method reduce (line 1423) | Future<AppState?> reduce()
  class PollingWithOptimisticSyncAction (line 1427) | class PollingWithOptimisticSyncAction extends ReduxAction<AppState>
    method createPollingAction (line 1441) | ReduxAction<AppState> createPollingAction()
    method valueToApply (line 1445) | int valueToApply()
    method applyOptimisticValueToState (line 1448) | AppState applyOptimisticValueToState(AppState state, int optimisticValue)
    method applyServerResponseToState (line 1452) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method getValueFromState (line 1456) | int getValueFromState(AppState state)
    method sendValueToServer (line 1459) | Future<Object?> sendValueToServer(Object? optimisticValue)
    method reduce (line 1462) | Future<AppState?> reduce()
  class PollingWithOptimisticSyncWithPushAction (line 1466) | class PollingWithOptimisticSyncWithPushAction extends ReduxAction<AppState>
    method createPollingAction (line 1480) | ReduxAction<AppState> createPollingAction()
    method valueToApply (line 1484) | int valueToApply()
    method applyOptimisticValueToState (line 1487) | AppState applyOptimisticValueToState(AppState state, int optimisticValue)
    method applyServerResponseToState (line 1491) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method getValueFromState (line 1495) | int getValueFromState(AppState state)
    method getServerRevisionFromState (line 1498) | int getServerRevisionFromState(Object? key)
    method sendValueToServer (line 1501) | Future<Object?> sendValueToServer(
    method reduce (line 1509) | Future<AppState?> reduce()
  class PollingWithServerPushAction (line 1513) | class PollingWithServerPushAction extends ReduxAction<AppState>
    method createPollingAction (line 1527) | ReduxAction<AppState> createPollingAction()
    method associatedAction (line 1531) | Type associatedAction()
    method pushMetadata (line 1534) | PushMetadata pushMetadata()
    method applyServerPushToState (line 1538) | AppState? applyServerPushToState(
    method getServerRevisionFromState (line 1543) | int getServerRevisionFromState(Object? key)
    method reduce (line 1546) | AppState reduce()

FILE: test/props_test.dart
  function main (line 6) | void main()
  class ManagedTimer (line 107) | class ManagedTimer implements Timer {
    method cancel (line 116) | void cancel()

FILE: test/reducer_future_or_test.dart
  function main (line 21) | void main()
  class ActionNull (line 160) | class ActionNull extends ReduxAction<AppState> {
    method reduce (line 162) | Null reduce()
  class ActionA (line 168) | class ActionA extends ReduxAction<AppState> {
    method reduce (line 170) | AppState reduce()
  class ActionB (line 176) | class ActionB extends ReduxAction<AppState> {
    method reduce (line 178) | AppState? reduce()
  class ActionC (line 184) | class ActionC extends ReduxAction<AppState> {
    method reduce (line 186) | Future<AppState> reduce()
  class ActionD (line 192) | class ActionD extends ReduxAction<AppState> {
    method reduce (line 194) | Future<AppState?> reduce()
  class ActionE (line 200) | class ActionE extends ReduxAction<AppState> {
    method reduce (line 202) | Future<AppState>? reduce()
  class ActionF (line 208) | class ActionF extends ReduxAction<AppState> {
    method reduce (line 210) | Future<AppState?>? reduce()
  class ActionG (line 216) | class ActionG extends ReduxAction<AppState> {
    method reduce (line 218) | FutureOr<AppState> reduce()
  class ActionH (line 224) | class ActionH extends ReduxAction<AppState> {
    method reduce (line 226) | FutureOr<AppState?> reduce()
  class ActionI (line 232) | class ActionI extends ReduxAction<AppState> {
    method reduce (line 234) | FutureOr<AppState>? reduce()
  class ActionJ (line 240) | class ActionJ extends ReduxAction<AppState> {
    method reduce (line 242) | FutureOr<AppState?>? reduce()
  class AppState (line 247) | @immutable
    method copy (line 253) | AppState copy(String? text)
    method initialState (line 255) | AppState initialState()
    method toString (line 266) | String toString()

FILE: test/retry_mixin_test.dart
  function main (line 5) | void main()
  class State (line 84) | class State {
    method toString (line 90) | String toString()
  class ActionThatRetriesAndSucceeds (line 93) | class ActionThatRetriesAndSucceeds extends ReduxAction<State> with Retry {
    method reduce (line 103) | State reduce()
  class ActionThatRetriesAndFails (line 110) | class ActionThatRetriesAndFails extends ReduxAction<State> with Retry {
    method reduce (line 117) | State reduce()
  class ActionThatRetriesButSucceedsTheFirstTry (line 124) | class ActionThatRetriesButSucceedsTheFirstTry extends ReduxAction<State>...
    method reduce (line 134) | State reduce()
  class ActionThatRetriesUnlimitedAndFails (line 140) | class ActionThatRetriesUnlimitedAndFails extends ReduxAction<State> with...
    method reduce (line 147) | State reduce()

FILE: test/server_push_init_test.dart
  function main (line 7) | void main()
  class SimulatedBackend (line 251) | class SimulatedBackend {
    method applyPush (line 260) | void applyPush(bool value, int rev)
    method receiveValue (line 270) | ({bool value, int serverRevision}) receiveValue(bool value, int localRev)
  class AppState (line 282) | class AppState {
    method copy (line 288) | AppState copy({bool? liked, int? serverRevision})
  class AppStateItems (line 294) | class AppStateItems {
    method copy (line 306) | AppStateItems copy({
    method setLiked (line 315) | AppStateItems setLiked(String id, bool liked)
    method setServerRev (line 318) | AppStateItems setServerRev(String id, int rev)
  function resetTestState (line 337) | void resetTestState()
  class ToggleLikeStableAction (line 352) | class ToggleLikeStableAction extends ReduxAction<AppState>
    method valueToApply (line 355) | bool valueToApply()
    method getValueFromState (line 358) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 361) | AppState applyOptimisticValueToState(AppState state, bool optimisticVa...
    method applyServerResponseToState (line 365) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method sendValueToServer (line 374) | Future<Object?> sendValueToServer(
    method onFinish (line 398) | Future<AppState?> onFinish(Object? error)
    method getServerRevisionFromState (line 407) | int getServerRevisionFromState(Object? key)
  class PushLikeUpdate (line 410) | class PushLikeUpdate extends ReduxAction<AppState> with ServerPush<AppSt...
    method associatedAction (line 424) | Type associatedAction()
    method pushMetadata (line 427) | PushMetadata pushMetadata()
    method applyServerPushToState (line 434) | AppState? applyServerPushToState(
    method getServerRevisionFromState (line 440) | int getServerRevisionFromState(Object? key)
  class PushLikeUpdateNoStateRev (line 445) | class PushLikeUpdateNoStateRev extends ReduxAction<AppState>
    method associatedAction (line 460) | Type associatedAction()
    method pushMetadata (line 463) | PushMetadata pushMetadata()
    method applyServerPushToState (line 470) | AppState? applyServerPushToState(
    method getServerRevisionFromState (line 476) | int getServerRevisionFromState(Object? key)
  class ToggleLikeItemStableAction (line 479) | class ToggleLikeItemStableAction extends ReduxAction<AppStateItems>
    method optimisticSyncKeyParams (line 486) | Object? optimisticSyncKeyParams()
    method valueToApply (line 489) | bool valueToApply()
    method getValueFromState (line 492) | bool getValueFromState(AppStateItems state)
    method applyOptimisticValueToState (line 496) | AppStateItems applyOptimisticValueToState(
    method applyServerResponseToState (line 502) | AppStateItems? applyServerResponseToState(
    method sendValueToServer (line 511) | Future<Object?> sendValueToServer(
    method onFinish (line 545) | Future<AppStateItems?> onFinish(Object? error)
    method getServerRevisionFromState (line 555) | int getServerRevisionFromState(Object? key)
  class PushItemLikeUpdate (line 561) | class PushItemLikeUpdate extends ReduxAction<AppStateItems>
    method associatedAction (line 578) | Type associatedAction()
    method optimisticSyncKeyParams (line 581) | Object? optimisticSyncKeyParams()
    method pushMetadata (line 584) | PushMetadata pushMetadata()
    method applyServerPushToState (line 591) | AppStateItems? applyServerPushToState(
    method getServerRevisionFromState (line 597) | int getServerRevisionFromState(Object? key)
  class PushItemLikeUpdateNoStateRev (line 603) | class PushItemLikeUpdateNoStateRev extends ReduxAction<AppStateItems>
    method associatedAction (line 620) | Type associatedAction()
    method optimisticSyncKeyParams (line 623) | Object? optimisticSyncKeyParams()
    method pushMetadata (line 626) | PushMetadata pushMetadata()
    method applyServerPushToState (line 633) | AppStateItems? applyServerPushToState(
    method getServerRevisionFromState (line 639) | int getServerRevisionFromState(Object? key)

FILE: test/server_push_test.dart
  function main (line 7) | void main()
  class AppState (line 440) | class AppState {
    method copy (line 446) | AppState copy({bool? liked, int? serverRevision})
    method toString (line 452) | String toString()
  class AppStateItems (line 455) | class AppStateItems {
    method copy (line 466) | AppStateItems copy({
    method setLiked (line 475) | AppStateItems setLiked(String id, bool liked)
    method setServerRev (line 478) | AppStateItems setServerRev(String id, int rev)
    method toString (line 482) | String toString()
  function resetTestState (line 495) | void resetTestState()
  class ToggleLikeStableAction (line 506) | class ToggleLikeStableAction extends ReduxAction<AppState>
    method valueToApply (line 511) | bool valueToApply()
    method getValueFromState (line 514) | bool getValueFromState(AppState state)
    method applyOptimisticValueToState (line 517) | AppState applyOptimisticValueToState(AppState state, bool optimisticVa...
    method applyServerResponseToState (line 521) | AppState? applyServerResponseToState(AppState state, Object serverResp...
    method sendValueToServer (line 529) | Future<Object?> sendValueToServer(
    method onFinish (line 54
Condensed preview — 232 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,236K chars).
[
  {
    "path": ".claude/settings.local.json",
    "chars": 497,
    "preview": "{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(flutter test:*)\",\n      \"Bash(flutter analyze:*)\",\n      \"Bash(dart test"
  },
  {
    "path": ".claude/skills/asyncredux-abort-dispatch/SKILL.md",
    "chars": 9011,
    "preview": "---\nname: asyncredux-abort-dispatch\ndescription: Stops an AsyncRedux (Flutter) action from dispatching. Use only when th"
  },
  {
    "path": ".claude/skills/asyncredux-action-status/SKILL.md",
    "chars": 5946,
    "preview": "---\nname: asyncredux-action-status\ndescription: Checks an AsyncRedux (Flutter) action's completion status using ActionSt"
  },
  {
    "path": ".claude/skills/asyncredux-actions-no-state-change/SKILL.md",
    "chars": 2630,
    "preview": "---\nname: asyncredux-actions-no-state-change\ndescription: Creates AsyncRedux (Flutter) actions that return null from red"
  },
  {
    "path": ".claude/skills/asyncredux-async-actions/SKILL.md",
    "chars": 7348,
    "preview": "---\nname: asyncredux-async-actions\ndescription: Creates AsyncRedux (Flutter) asynchronous actions for API calls, databas"
  },
  {
    "path": ".claude/skills/asyncredux-base-action/SKILL.md",
    "chars": 5309,
    "preview": "---\nname: asyncredux-base-action\ndescription: Create a custom base action class for your app. Covers adding getter short"
  },
  {
    "path": ".claude/skills/asyncredux-before-after/SKILL.md",
    "chars": 9241,
    "preview": "---\nname: asyncredux-before-after\ndescription: Implement action lifecycle methods `before()` and `after()`. Covers runni"
  },
  {
    "path": ".claude/skills/asyncredux-check-internet-mixin/SKILL.md",
    "chars": 5384,
    "preview": "---\nname: asyncredux-check-internet-mixin\ndescription: Add the CheckInternet mixin to ensure network connectivity before"
  },
  {
    "path": ".claude/skills/asyncredux-connector-pattern/SKILL.md",
    "chars": 11950,
    "preview": "---\nname: asyncredux-connector-pattern\ndescription: Implement the Connector pattern for separating smart and dumb widget"
  },
  {
    "path": ".claude/skills/asyncredux-debounce-mixin/SKILL.md",
    "chars": 3919,
    "preview": "---\nname: asyncredux-debounce-mixin\ndescription: Add the Debounce mixin to wait for user input pauses before acting. Cov"
  },
  {
    "path": ".claude/skills/asyncredux-debugging/SKILL.md",
    "chars": 9026,
    "preview": "---\nname: asyncredux-debugging\ndescription: Debug AsyncRedux applications effectively. Covers printing state with store."
  },
  {
    "path": ".claude/skills/asyncredux-dependency-injection/SKILL.md",
    "chars": 11599,
    "preview": "---\nname: asyncredux-dependency-injection\ndescription: Inject dependencies into actions using the environment, dependenc"
  },
  {
    "path": ".claude/skills/asyncredux-dispatching-actions/SKILL.md",
    "chars": 5293,
    "preview": "---\nname: asyncredux-dispatching-actions\ndescription: Dispatch actions using all available methods: `dispatch()`, `dispa"
  },
  {
    "path": ".claude/skills/asyncredux-error-handling/SKILL.md",
    "chars": 9863,
    "preview": "---\nname: asyncredux-error-handling\ndescription: Implement comprehensive error handling for actions. Covers the `wrapErr"
  },
  {
    "path": ".claude/skills/asyncredux-events/SKILL.md",
    "chars": 7987,
    "preview": "---\nname: asyncredux-events\ndescription: Use the Event class to interact with Flutter's stateful widgets (TextField, Lis"
  },
  {
    "path": ".claude/skills/asyncredux-flutter-hooks/SKILL.md",
    "chars": 7390,
    "preview": "---\nname: asyncredux-flutter-hooks\ndescription: Integrate AsyncRedux with the flutter_hooks package. Covers adding flutt"
  },
  {
    "path": ".claude/skills/asyncredux-navigation/SKILL.md",
    "chars": 7516,
    "preview": "---\nname: asyncredux-navigation\ndescription: Handle navigation through actions using NavigateAction. Covers setting up t"
  },
  {
    "path": ".claude/skills/asyncredux-nonreentrant-mixin/SKILL.md",
    "chars": 3975,
    "preview": "---\nname: asyncredux-nonreentrant-mixin\ndescription: Add the NonReentrant mixin to prevent an action from dispatching wh"
  },
  {
    "path": ".claude/skills/asyncredux-observers/SKILL.md",
    "chars": 13038,
    "preview": "---\nname: asyncredux-observers\ndescription: Set up observers for debugging and monitoring. Covers implementing actionObs"
  },
  {
    "path": ".claude/skills/asyncredux-optimistic-update-mixin/SKILL.md",
    "chars": 9689,
    "preview": "---\nname: asyncredux-optimistic-update-mixin\ndescription: Add the OptimisticUpdate mixin for instant UI feedback before "
  },
  {
    "path": ".claude/skills/asyncredux-persistence/SKILL.md",
    "chars": 6593,
    "preview": "---\nname: asyncredux-persistence\ndescription: Implement local state persistence using Persistor. Covers creating a custo"
  },
  {
    "path": ".claude/skills/asyncredux-provider-integration/SKILL.md",
    "chars": 6721,
    "preview": "---\nname: asyncredux-provider-integration\ndescription: Integrate AsyncRedux with the Provider package. Covers using prov"
  },
  {
    "path": ".claude/skills/asyncredux-retry-mixin/SKILL.md",
    "chars": 7882,
    "preview": "---\nname: asyncredux-retry-mixin\ndescription: Add the Retry mixin for automatic retry with exponential backoff on action"
  },
  {
    "path": ".claude/skills/asyncredux-selectors/SKILL.md",
    "chars": 8335,
    "preview": "---\nname: asyncredux-selectors\ndescription: Create and cache selectors for efficient state access. Covers writing select"
  },
  {
    "path": ".claude/skills/asyncredux-setup/SKILL.md",
    "chars": 5124,
    "preview": "---\nname: asyncredux-setup\ndescription: Initialize, setup and configure AsyncRedux in a Flutter app. Use it whenever sta"
  },
  {
    "path": ".claude/skills/asyncredux-state-access/SKILL.md",
    "chars": 6853,
    "preview": "---\nname: asyncredux-state-access\ndescription: Access store state in widgets using `context.state`, `context.select()`, "
  },
  {
    "path": ".claude/skills/asyncredux-state-design/SKILL.md",
    "chars": 8955,
    "preview": "---\nname: asyncredux-state-design\ndescription: Design immutable state classes following AsyncRedux best practices. Inclu"
  },
  {
    "path": ".claude/skills/asyncredux-streams-timers/SKILL.md",
    "chars": 8890,
    "preview": "---\nname: asyncredux-streams-timers\ndescription: Manage Streams and Timers with AsyncRedux. Covers creating actions to s"
  },
  {
    "path": ".claude/skills/asyncredux-sync-actions/SKILL.md",
    "chars": 6366,
    "preview": "---\nname: asyncredux-sync-actions\ndescription: Creates AsyncRedux (Flutter) synchronous actions that update state immedi"
  },
  {
    "path": ".claude/skills/asyncredux-testing-basics/SKILL.md",
    "chars": 9658,
    "preview": "---\nname: asyncredux-testing-basics\ndescription: Write unit tests for AsyncRedux actions using the Store directly. Cover"
  },
  {
    "path": ".claude/skills/asyncredux-testing-view-models/SKILL.md",
    "chars": 10887,
    "preview": "---\nname: asyncredux-testing-view-models\ndescription: Test StoreConnector view-models in isolation. Covers creating view"
  },
  {
    "path": ".claude/skills/asyncredux-testing-wait-methods/SKILL.md",
    "chars": 15442,
    "preview": "---\nname: asyncredux-testing-wait-methods\ndescription: Use advanced wait methods for complex test scenarios. Covers `wai"
  },
  {
    "path": ".claude/skills/asyncredux-throttle-mixin/SKILL.md",
    "chars": 6819,
    "preview": "---\nname: asyncredux-throttle-mixin\ndescription: Add the Throttle mixin to prevent actions from running too frequently. "
  },
  {
    "path": ".claude/skills/asyncredux-undo-redo/SKILL.md",
    "chars": 9764,
    "preview": "---\nname: asyncredux-undo-redo\ndescription: Implement undo/redo functionality using state observers. Covers recording st"
  },
  {
    "path": ".claude/skills/asyncredux-user-exceptions/SKILL.md",
    "chars": 7428,
    "preview": "---\nname: asyncredux-user-exceptions\ndescription: Handle user-facing errors with UserException. Covers throwing UserExce"
  },
  {
    "path": ".claude/skills/asyncredux-wait-condition/SKILL.md",
    "chars": 8582,
    "preview": "---\nname: asyncredux-wait-condition\ndescription: Use `waitCondition()` inside actions to pause execution until state mee"
  },
  {
    "path": ".claude/skills/asyncredux-wait-fail-succeed/SKILL.md",
    "chars": 7831,
    "preview": "---\nname: asyncredux-wait-fail-succeed\ndescription: Show loading states and handle action failures in widgets. Covers `i"
  },
  {
    "path": ".github/copilot-instructions.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": ".github/workflows/test.yaml",
    "chars": 329,
    "preview": "name: Build\n\non:\n  push:\n    branches:\n      - master\n      - develop\n  pull_request:\n\njobs:\n  test:\n    name: Run tests"
  },
  {
    "path": ".gitignore",
    "chars": 1655,
    "preview": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.i"
  },
  {
    "path": ".metadata",
    "chars": 309,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 77924,
    "preview": "_Visit\nthe <a href=\"https://github.com/marcglasberg/SameAppDifferentTech/blob/main/MobileAppFlutterRedux/README.md\">\nAsy"
  },
  {
    "path": "LICENSE",
    "chars": 5160,
    "preview": "Async_redux Package License (05 Aug 2019):\nhttps://github.com/marcglasberg/async_redux/blob/master/LICENSE\n\nMIT License\n"
  },
  {
    "path": "README.md",
    "chars": 21755,
    "preview": "<img src=\"https://asyncredux.com/img/platipus_FlutterReact.jpg\">\n\n[![Pub Version](https://img.shields.io/pub/v/async_red"
  },
  {
    "path": "analysis_options.yaml",
    "chars": 6558,
    "preview": "# Specify analysis options.\n#\n# Until there are meta linter rules, each desired lint must be explicitly enabled.\n# See: "
  },
  {
    "path": "context_select_patterns.md",
    "chars": 12543,
    "preview": "# Extension Patterns for AsyncRedux `getSelect`\n\nThis guide demonstrates different extension patterns you can use with\nA"
  },
  {
    "path": "example/.gitignore",
    "chars": 1655,
    "preview": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.i"
  },
  {
    "path": "example/.metadata",
    "chars": 1410,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": "example/README.md",
    "chars": 5067,
    "preview": "# Examples\n\n1. <a href=\"https://github.com/marcglasberg/async_redux/blob/master/example/lib/main.dart\">main</a>\n\n    Thi"
  },
  {
    "path": "example/analysis_options.yaml",
    "chars": 1420,
    "preview": "# This file configures the analyzer, which statically analyzes Dart code to\n# check for errors, warnings, and lints.\n#\n#"
  },
  {
    "path": "example/android/.gitignore",
    "chars": 253,
    "preview": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n.cxx/\n\n# R"
  },
  {
    "path": "example/android/app/build.gradle.kts",
    "chars": 1386,
    "preview": "plugins {\n    id(\"com.android.application\")\n    id(\"kotlin-android\")\n    // The Flutter Gradle Plugin must be applied af"
  },
  {
    "path": "example/android/app/src/debug/AndroidManifest.xml",
    "chars": 378,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- The INTERNET permission is required for d"
  },
  {
    "path": "example/android/app/src/main/AndroidManifest.xml",
    "chars": 2195,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <application\n        android:label=\"example\"\n "
  },
  {
    "path": "example/android/app/src/main/kotlin/com/example/example/MainActivity.kt",
    "chars": 121,
    "preview": "package com.example.example\n\nimport io.flutter.embedding.android.FlutterActivity\n\nclass MainActivity : FlutterActivity()"
  },
  {
    "path": "example/android/app/src/main/res/drawable/launch_background.xml",
    "chars": 434,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
  },
  {
    "path": "example/android/app/src/main/res/drawable-v21/launch_background.xml",
    "chars": 438,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
  },
  {
    "path": "example/android/app/src/main/res/values/styles.xml",
    "chars": 996,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is sta"
  },
  {
    "path": "example/android/app/src/main/res/values-night/styles.xml",
    "chars": 995,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is sta"
  },
  {
    "path": "example/android/app/src/profile/AndroidManifest.xml",
    "chars": 378,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- The INTERNET permission is required for d"
  },
  {
    "path": "example/android/build.gradle.kts",
    "chars": 537,
    "preview": "allprojects {\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\nval newBuildDir: Directory =\n    rootP"
  },
  {
    "path": "example/android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 201,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dist"
  },
  {
    "path": "example/android/gradle.properties",
    "chars": 166,
    "preview": "org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError\nandroid"
  },
  {
    "path": "example/android/settings.gradle.kts",
    "chars": 770,
    "preview": "pluginManagement {\n    val flutterSdkPath =\n        run {\n            val properties = java.util.Properties()\n          "
  },
  {
    "path": "example/ios/.gitignore",
    "chars": 569,
    "preview": "**/dgph\n*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/De"
  },
  {
    "path": "example/ios/Flutter/AppFrameworkInfo.plist",
    "chars": 774,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Flutter/Debug.xcconfig",
    "chars": 30,
    "preview": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example/ios/Flutter/Release.xcconfig",
    "chars": 30,
    "preview": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example/ios/Runner/AppDelegate.swift",
    "chars": 391,
    "preview": "import Flutter\nimport UIKit\n\n@main\n@objc class AppDelegate: FlutterAppDelegate {\n  override func application(\n    _ appl"
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 2519,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n   "
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "chars": 391,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n  "
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "chars": 336,
    "preview": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in"
  },
  {
    "path": "example/ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "chars": 2377,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "example/ios/Runner/Base.lproj/Main.storyboard",
    "chars": 1605,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "example/ios/Runner/Info.plist",
    "chars": 1641,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner/Runner-Bridging-Header.h",
    "chars": 38,
    "preview": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.pbxproj",
    "chars": 23648,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "chars": 3833,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1510\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "example/ios/Runner.xcworkspace/contents.xcworkspacedata",
    "chars": 152,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/RunnerTests/RunnerTests.swift",
    "chars": 285,
    "preview": "import Flutter\nimport UIKit\nimport XCTest\n\nclass RunnerTests: XCTestCase {\n\n  func testExample() {\n    // If you add cod"
  },
  {
    "path": "example/lib/main.dart",
    "chars": 2488,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Developed by Marcelo Glasberg"
  },
  {
    "path": "example/lib/main_before_and_after.dart",
    "chars": 5618,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_dependency_injection.dart",
    "chars": 4811,
    "preview": "import 'dart:math';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Develope"
  },
  {
    "path": "example/lib/main_event.dart",
    "chars": 5814,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_event_2.dart",
    "chars": 6223,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_infinite_scroll.dart",
    "chars": 5930,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_is_waiting_works_when_multiple_actions.dart",
    "chars": 5023,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n/// This example shows how to sh"
  },
  {
    "path": "example/lib/main_navigate.dart",
    "chars": 1587,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\nlate Store<AppState> store;\n\nfin"
  },
  {
    "path": "example/lib/main_optimistic_command.dart",
    "chars": 16365,
    "preview": "/// This example is meant to demonstrate the [OptimisticCommand] mixin in action.\n/// The screen is split into two halve"
  },
  {
    "path": "example/lib/main_optimistic_sync.dart",
    "chars": 16644,
    "preview": "/// This example is meant to demonstrate the [OptimisticSync] mixin in action.\n/// The screen is split into two halves: "
  },
  {
    "path": "example/lib/main_optimistic_sync_with_push.dart",
    "chars": 26245,
    "preview": "/// This example is meant to demonstrate the [OptimisticSyncWithPush] mixin in\n/// action. The screen is split into two "
  },
  {
    "path": "example/lib/main_polling.dart",
    "chars": 10071,
    "preview": "import 'dart:math';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Develope"
  },
  {
    "path": "example/lib/main_select.dart",
    "chars": 7894,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_select_2.dart",
    "chars": 11434,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "example/lib/main_show_error_dialog.dart",
    "chars": 4755,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "example/lib/main_show_spinner.dart",
    "chars": 2964,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "example/lib/main_wait_action_advanced_1.dart",
    "chars": 5554,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_wait_action_advanced_2.dart",
    "chars": 5326,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/main_wait_action_simple.dart",
    "chars": 5576,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/store_connector_examples/README.md",
    "chars": 9251,
    "preview": "# StoreConnector Examples\n\nThis directory contains examples of how to use the `StoreConnector` widget from\nthe AsyncRedu"
  },
  {
    "path": "example/lib/store_connector_examples/main_async__store_connector.dart",
    "chars": 5562,
    "preview": "import 'dart:async';\nimport 'dart:convert';\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mater"
  },
  {
    "path": "example/lib/store_connector_examples/main_async_base_factory__store_connector.dart.dart",
    "chars": 6045,
    "preview": "import 'dart:async';\nimport 'dart:convert';\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mater"
  },
  {
    "path": "example/lib/store_connector_examples/main_environment__store_connector.dart",
    "chars": 4962,
    "preview": "import 'dart:math';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Develope"
  },
  {
    "path": "example/lib/store_connector_examples/main_event__store_connector.dart",
    "chars": 7149,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/store_connector_examples/main_extension_vs_store_connector.dart",
    "chars": 3279,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "example/lib/store_connector_examples/main_infinite_scroll__store_connector.dart",
    "chars": 6431,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/store_connector_examples/main_is_waiting_works_when_multiple_actions__store_connector.dart",
    "chars": 5418,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n/// This example shows how to sh"
  },
  {
    "path": "example/lib/store_connector_examples/main_is_waiting_works_when_state_unchanged__store_connector.dart",
    "chars": 3938,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Developed by Marcelo Glasberg"
  },
  {
    "path": "example/lib/store_connector_examples/main_navigate__store_connector.dart",
    "chars": 2740,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\nlate Store<AppState> store;\n\nfin"
  },
  {
    "path": "example/lib/store_connector_examples/main_null_viewmodel__connector.dart",
    "chars": 3232,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Developed by Marcelo Glasberg"
  },
  {
    "path": "example/lib/store_connector_examples/main_should_update_model__store_connector.dart",
    "chars": 3561,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Developed by Marcelo Glasberg"
  },
  {
    "path": "example/lib/store_connector_examples/main_spinner__store_connector.dart",
    "chars": 6115,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "example/lib/store_connector_examples/main_static_view_model__store_connector.dart",
    "chars": 3137,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Developed by Marcelo Glasberg"
  },
  {
    "path": "example/lib/store_connector_examples/main_sync__store_connector.dart",
    "chars": 4344,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/material.dart';\n\n// Developed by Marcelo Glasberg"
  },
  {
    "path": "example/lib/store_connector_examples/main_wait_action_advanced_1__store_connector.dart",
    "chars": 7479,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/store_connector_examples/main_wait_action_advanced_2__store_connector.dart",
    "chars": 7320,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/lib/store_connector_examples/main_wait_action_simple__store_connector.dart",
    "chars": 6518,
    "preview": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter/mate"
  },
  {
    "path": "example/pubspec.yaml",
    "chars": 410,
    "preview": "name: example\ndescription: Examples for async_redux.\npublish_to: \"none\"\nversion: 1.0.0+1\n\nenvironment:\n  sdk: '>=3.0.0 <"
  },
  {
    "path": "example/web/index.html",
    "chars": 1212,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <!--\n    If you are serving your web app in a path other than the root, change the\n    h"
  },
  {
    "path": "example/web/manifest.json",
    "chars": 910,
    "preview": "{\n    \"name\": \"example\",\n    \"short_name\": \"example\",\n    \"start_url\": \".\",\n    \"display\": \"standalone\",\n    \"background"
  },
  {
    "path": "example/windows/.gitignore",
    "chars": 291,
    "preview": "flutter/ephemeral/\n\n# Visual Studio user-specific files.\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# Visual Studio bu"
  },
  {
    "path": "example/windows/CMakeLists.txt",
    "chars": 4150,
    "preview": "# Project-level configuration.\ncmake_minimum_required(VERSION 3.14)\nproject(example LANGUAGES CXX)\n\n# The name of the ex"
  },
  {
    "path": "example/windows/flutter/CMakeLists.txt",
    "chars": 3742,
    "preview": "# This file controls Flutter-level build steps. It should not be edited.\ncmake_minimum_required(VERSION 3.14)\n\nset(EPHEM"
  },
  {
    "path": "example/windows/flutter/generated_plugin_registrant.cc",
    "chars": 355,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#include \"generated_plugin_registrant.h\"\n\n#include <connect"
  },
  {
    "path": "example/windows/flutter/generated_plugin_registrant.h",
    "chars": 302,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#ifndef GENERATED_PLUGIN_REGISTRANT_\n#define GENERATED_PLUG"
  },
  {
    "path": "example/windows/flutter/generated_plugins.cmake",
    "chars": 763,
    "preview": "#\n# Generated file, do not edit.\n#\n\nlist(APPEND FLUTTER_PLUGIN_LIST\n  connectivity_plus\n)\n\nlist(APPEND FLUTTER_FFI_PLUGI"
  },
  {
    "path": "example/windows/runner/CMakeLists.txt",
    "chars": 1796,
    "preview": "cmake_minimum_required(VERSION 3.14)\nproject(runner LANGUAGES CXX)\n\n# Define the application target. To change its name,"
  },
  {
    "path": "example/windows/runner/Runner.rc",
    "chars": 3025,
    "preview": "// Microsoft Visual C++ generated resource script.\n//\n#pragma code_page(65001)\n#include \"resource.h\"\n\n#define APSTUDIO_R"
  },
  {
    "path": "example/windows/runner/flutter_window.cpp",
    "chars": 2122,
    "preview": "#include \"flutter_window.h\"\n\n#include <optional>\n\n#include \"flutter/generated_plugin_registrant.h\"\n\nFlutterWindow::Flutt"
  },
  {
    "path": "example/windows/runner/flutter_window.h",
    "chars": 928,
    "preview": "#ifndef RUNNER_FLUTTER_WINDOW_H_\n#define RUNNER_FLUTTER_WINDOW_H_\n\n#include <flutter/dart_project.h>\n#include <flutter/f"
  },
  {
    "path": "example/windows/runner/main.cpp",
    "chars": 1260,
    "preview": "#include <flutter/dart_project.h>\n#include <flutter/flutter_view_controller.h>\n#include <windows.h>\n\n#include \"flutter_w"
  },
  {
    "path": "example/windows/runner/resource.h",
    "chars": 432,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Runner.rc\n//\n#define IDI_APP_ICON      "
  },
  {
    "path": "example/windows/runner/runner.exe.manifest",
    "chars": 602,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersi"
  },
  {
    "path": "example/windows/runner/utils.cpp",
    "chars": 1797,
    "preview": "#include \"utils.h\"\n\n#include <flutter_windows.h>\n#include <io.h>\n#include <stdio.h>\n#include <windows.h>\n\n#include <iost"
  },
  {
    "path": "example/windows/runner/utils.h",
    "chars": 672,
    "preview": "#ifndef RUNNER_UTILS_H_\n#define RUNNER_UTILS_H_\n\n#include <string>\n#include <vector>\n\n// Creates a console for the proce"
  },
  {
    "path": "example/windows/runner/win32_window.cpp",
    "chars": 8534,
    "preview": "#include \"win32_window.h\"\n\n#include <dwmapi.h>\n#include <flutter_windows.h>\n\n#include \"resource.h\"\n\nnamespace {\n\n/// Win"
  },
  {
    "path": "example/windows/runner/win32_window.h",
    "chars": 3522,
    "preview": "#ifndef RUNNER_WIN32_WINDOW_H_\n#define RUNNER_WIN32_WINDOW_H_\n\n#include <windows.h>\n\n#include <functional>\n#include <mem"
  },
  {
    "path": "lib/async_redux.dart",
    "chars": 915,
    "preview": "export 'package:async_redux_core/async_redux_core.dart';\n\nexport 'src/action_mixins.dart';\nexport 'src/action_observer.d"
  },
  {
    "path": "lib/local_json_persist.dart",
    "chars": 38,
    "preview": "export 'src/local_json_persist.dart';\n"
  },
  {
    "path": "lib/local_persist.dart",
    "chars": 33,
    "preview": "export 'src/local_persist.dart';\n"
  },
  {
    "path": "lib/src/action_mixins.dart",
    "chars": 152541,
    "preview": "import 'dart:async';\nimport 'dart:math';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:connectivity_pl"
  },
  {
    "path": "lib/src/action_observer.dart",
    "chars": 3686,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/advanced_user_exception.dart",
    "chars": 15407,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/cache.dart",
    "chars": 11413,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/cloud_sync.dart",
    "chars": 427,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/connection_exception.dart",
    "chars": 2717,
    "preview": "import 'package:async_redux/async_redux.dart';\n\n/// The [ConnectionException] is a type of [UserException] that warns th"
  },
  {
    "path": "lib/src/connector_tester.dart",
    "chars": 2058,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/error_observer.dart",
    "chars": 3728,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/event_redux.dart",
    "chars": 16041,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/global_wrap_error.dart",
    "chars": 2975,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/local_json_persist.dart",
    "chars": 14471,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/local_persist.dart",
    "chars": 17209,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/log.dart",
    "chars": 4197,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/mock_build_context.dart",
    "chars": 4340,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/mock_store.dart",
    "chars": 8675,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/model_observer.dart",
    "chars": 3208,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/navigate_action.dart",
    "chars": 13601,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/persistor.dart",
    "chars": 4693,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/process_persistence.dart",
    "chars": 5405,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/redux_action.dart",
    "chars": 31618,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/show_dialog_super.dart",
    "chars": 10714,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/state_observer.dart",
    "chars": 3558,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/store.dart",
    "chars": 113030,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/store_exception.dart",
    "chars": 603,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/store_provider_and_connector.dart",
    "chars": 93773,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/store_tester.dart",
    "chars": 30598,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/test_info.dart",
    "chars": 1892,
    "preview": "import 'dart:collection';\n\nimport 'package:async_redux/async_redux.dart';\n\ntypedef TestInfoPrinter = void Function(TestI"
  },
  {
    "path": "lib/src/user_exception_dialog.dart",
    "chars": 6843,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/view_model.dart",
    "chars": 18226,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "lib/src/wait.dart",
    "chars": 5295,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/wait_action.dart",
    "chars": 6808,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "lib/src/wrap_reduce.dart",
    "chars": 3637,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// Based upon packages "
  },
  {
    "path": "mixin_compatibility.md",
    "chars": 9446,
    "preview": "# Mixin Compatibility Matrix\n\nThis document describes the compatibility between AsyncRedux action mixins.\n\n## Mixins Ove"
  },
  {
    "path": "pubspec.yaml",
    "chars": 980,
    "preview": "name: async_redux\ndescription: The modern version of Redux. State management that's simple to learn and easy to use; Pow"
  },
  {
    "path": "test/abort_dispatch_test.dart",
    "chars": 4275,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:bdd_framework/bdd_framework.dart';\nimport 'package:flutte"
  },
  {
    "path": "test/action_initial_state_test.dart",
    "chars": 3918,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:bdd_framework/bdd_framework.dart';\nimport 'package:flutte"
  },
  {
    "path": "test/action_status_test.dart",
    "chars": 8945,
    "preview": "import 'dart:async';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\n/"
  },
  {
    "path": "test/action_to_string_test.dart",
    "chars": 6062,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material"
  },
  {
    "path": "test/action_wrap_reduce2_test.dart",
    "chars": 4170,
    "preview": "import 'dart:async' show FutureOr;\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter_test/flutter_"
  },
  {
    "path": "test/action_wrap_reduce_test.dart",
    "chars": 2997,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nvoid main() {\n  test('a"
  },
  {
    "path": "test/after_throws_test.dart",
    "chars": 1563,
    "preview": "import 'dart:async';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\n/"
  },
  {
    "path": "test/before_reduce_after_order_test.dart",
    "chars": 6653,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\n// Developed by Marcelo"
  },
  {
    "path": "test/before_throwing_errors_test.dart",
    "chars": 6283,
    "preview": "import 'dart:async';\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\n/"
  },
  {
    "path": "test/cache_test.dart",
    "chars": 10667,
    "preview": "import 'package:async_redux/src/cache.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nvoid main() {\n  var state"
  },
  {
    "path": "test/check_internet_mixin_test.dart",
    "chars": 191,
    "preview": "import 'package:bdd_framework/bdd_framework.dart';\n\nvoid main() {\n  var feature = BddFeature('Check internet actions');\n"
  },
  {
    "path": "test/context_environment_test.dart",
    "chars": 8837,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "test/context_event_test.dart",
    "chars": 27866,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "test/context_select_advanced_test.dart",
    "chars": 23856,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "test/context_select_test.dart",
    "chars": 10270,
    "preview": "// Exploratory test to debug the select() rebuild issue\n\nimport 'package:async_redux/async_redux.dart';\nimport 'package:"
  },
  {
    "path": "test/context_state_test.dart",
    "chars": 15137,
    "preview": "// Developed by Marcelo Glasberg (2019) https://glasberg.dev and https://github.com/marcglasberg\n// For more info: https"
  },
  {
    "path": "test/debounce_mixin_test.dart",
    "chars": 7757,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:bdd_framework/bdd_framework.dart';\nimport 'package:flutte"
  },
  {
    "path": "test/dispatch_and_wait_all_actions_test.dart",
    "chars": 2058,
    "preview": "// File: test/dispatch_and_wait_all_actions_test.dart\nimport 'package:async_redux/async_redux.dart';\nimport 'package:flu"
  },
  {
    "path": "test/dispatch_and_wait_test.dart",
    "chars": 12168,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:bdd_framework/bdd_framework.dart';\nimport 'package:flutte"
  },
  {
    "path": "test/dispatch_sync_test.dart",
    "chars": 1946,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:bdd_framework/bdd_framework.dart';\nimport 'package:flutte"
  },
  {
    "path": "test/dispatch_test.dart",
    "chars": 2606,
    "preview": "import 'package:async_redux/async_redux.dart';\nimport 'package:bdd_framework/bdd_framework.dart';\nimport 'package:flutte"
  }
]

// ... and 32 more files (download for full content)

About this extraction

This page contains the full source code of the marcglasberg/async_redux GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 232 files (2.0 MB), approximately 548.5k tokens, and a symbol index with 2771 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!