jintent 3.0.1
jintent: ^3.0.1 copied to clipboard
jintent is a Flutter package that provides an architecture for managing state changes in your application using the concept of intents.
JIntent #
JIntent is a Flutter library for explicit intents, immutable state and one-time UI effects. Controllers manage state; intents perform operations; effect handlers present dialogs, navigation and feedback outside persistent state.
Read the interactive guide (English and Spanish) for the concepts, live demos and the API reference.
Installation #
flutter pub add jintent
Or declare it yourself. Version 3.0.0 requires Flutter 3.29.2 or newer:
dependencies:
jintent: ^3.0.0
Import the public entry point:
import 'package:jintent/jintent.dart';
Optional pieces have their own entry points, so the core stays small:
| Import | Contents |
|---|---|
package:jintent/jintent.dart |
State, intents, controller, effects, dispatchers, JObserver, Either, use cases, mappers |
package:jintent/devtools.dart |
Structured logging, correlation, metrics, debug overlay |
package:jintent/testing.dart |
State and effect recorders, global reset |
package:jintent/widgets.dart |
Controller builder and selector without a provider package |
package:jintent/undo_redo.dart |
Stable undo/redo, observable history and commands |
package:jintent/navigation.dart |
Thin Navigator abstraction |
package:jintent/utils.dart |
Throttler, validation, color and platform helpers |
See undo and redo for local edit history, UI integration, ordering and migration from the legacy experimental import.
Upgrading from 2.x changes state equality, effect failures and disposal behavior. Review the migration guide first.
What's new in 3.0.0 #
- Entry points:
jintent.dartholds only the core; devtools, undo/redo, widgets, navigation, utilities and test helpers moved to their own imports. - Predictable state: updates equal to the current state are skipped, so listeners and observers only see real changes.
- Safer effects: an awaited effect without a listener or handler fails with
StateError, and disposal fails pending results. Effect buffering is opt-in. - Concurrency: droppable and restartable dispatchers, with cooperative
cancellation through
JIntent.cancel. - Observability: composable
JObserverDelegates that also report failed, cancelled and dropped intents, plus richer metrics and overlay. - Also new: stable undo/redo with observable history,
JControllerBuilderandJControllerSelector, and test recorders inpackage:jintent/testing.dart.
Several of these change behavior compared with 2.x. See the full changelog and the migration guide.
Minimal example #
import 'package:jintent/jintent.dart';
class CounterState extends JState {
final int count;
const CounterState({this.count = 0});
@override
CounterState copyWith({int? count}) =>
CounterState(count: count ?? this.count);
@override
List<Object?> get props => [count];
}
class IncrementIntent extends JIntent<CounterState>
with JIntentHelpers<CounterState> {
@override
Future<void> onInvoke() async {
update((state) => state.copyWith(count: state.count + 1));
}
}
class CounterController extends JController<CounterState> {
CounterController() : super(const CounterState());
Future<void> increment() => intent(IncrementIntent());
@override
void onInit() {}
}
Future<void> main() async {
final controller = CounterController();
try {
await controller.increment();
print(controller.currentState.count); // 1
} finally {
controller.dispose();
}
}
Connect the controller directly with JControllerBuilder or
JControllerSelector from package:jintent/widgets.dart, or use your
StateNotifier integration. The widget guide covers ownership,
controller replacement and selecting part of a state. The
example gallery uses the builders in its four focused labs and
Riverpod with JEffectListener in the counter.
Contracts #
JState: include relevant values inprops; return new immutable states. Updates equal to the current state are skipped.JIntent: overrideonInvokeand await its work. One instance cannot run concurrently; it can be reused after completion.JController: dispatches sequentially by default. Return dispatch futures and handle their errors at the UI boundary.onInitruns synchronously from the base constructor, before the subclass constructor body. PasseffectBufferSizeto retain effects emitted before the UI attaches.JEffect: transient UI events. Register each concrete effect type in aJSideEffectHandlerand complete awaited results. A subscription alone does not guarantee completion; configure a timeout for awaited UI work.JObserver: registerJObserverDelegates to observe intents (including failures), state and effects; see observability.- Disposal rejects queued intents and pending effect results; running service calls and handlers need their own cancellation or lifecycle checks.
See effects for registration, failures and timeouts, and error handling for operation boundaries.
Documentation #
- Interactive guide in English and Spanish, with live demos and diagrams.
- Effects and error handling.
- Concurrency strategies: sequential, droppable, restartable and cooperative cancellation.
- Testing: state and effect recorders, global reset.
- Domain helpers: validation and mappers.
- Observability and extension points.
- Migration: upgrading from 2.x to 3.0.0.
- Security policy.
- Changelog: version history.
- Architecture records: ADR-000, ADR-001 and ADR-002 (all accepted).
Contributing #
Discuss substantial changes in an issue and keep pull requests focused. Follow
repository instructions and the task workflow.
For Dart changes, format affected files, run flutter analyze and relevant tests;
before delivering library changes, run flutter test --coverage. Root analysis
excludes the example, which needs separate validation when affected.
Documentation changes require checking references and git diff --check.
See the CI workflow for executable checks and the
code of conduct for community guidelines.
License #
MIT.