11part of '../base_scope_container.dart' ;
22
3- typedef StateListener <S > = void Function (S scope);
3+ typedef StateListener <S > = void Function (S ? scope);
4+
5+ typedef ScopeStateListener <S > = void Function (ScopeState <S > state);
46
57typedef RemoveStateListener = void Function ();
68
79class ScopeStateHolder <Scope > {
810 final _listeners = LinkedList <Entry <Scope >>();
9- Scope _scope ;
11+ ScopeState < Scope > _state ;
1012
1113 bool _debugCanAddListeners = true ;
1214
13- ScopeStateHolder (Scope state) : _scope = state;
15+ ScopeStateHolder (this ._state);
16+
17+ Scope ? get scope {
18+ final state = this .state;
19+ if (state is ScopeStateAvailable <Scope >) {
20+ return state.scope;
21+ }
22+ return null ;
23+ }
1424
15- Scope get scope => _scope ;
25+ ScopeState < Scope > get state => _state ;
1626
17- void _setScope ( Scope state) {
18- _scope = state;
27+ void _updateState ( ScopeState < Scope > state) {
28+ _state = state;
1929
2030 final errors = < Object > [];
2131 final stackTraces = < StackTrace > [];
@@ -40,6 +50,10 @@ class ScopeStateHolder<Scope> {
4050 /// The [listener] callback will be called immediately on addition and
4151 /// synchronously whenever [state] changes.
4252 ///
53+ /// Note: This method only calls the callback when the state is [ScopeStateAvailable]
54+ /// (passing the scope object) or when the scope is [ScopeStateNone] (passing null).
55+ /// It doesn't trigger for [ScopeStateInitializing] or [ScopeStateDisposing] states.
56+ ///
4357 /// Set [emitImmediately] to true if you want to an immediate execution
4458 /// of the [listener] with the current state.
4559 ///
@@ -50,6 +64,44 @@ class ScopeStateHolder<Scope> {
5064 RemoveStateListener listen (
5165 StateListener <Scope > listener, {
5266 bool emitImmediately = false ,
67+ }) =>
68+ _listen (
69+ (state) {
70+ if (state is ScopeStateAvailable <Scope >) {
71+ listener (state.scope);
72+ } else if (state is ScopeStateNone ) {
73+ listener (null );
74+ }
75+ },
76+ emitImmediately: emitImmediately,
77+ );
78+
79+ /// Subscribes to the state.
80+ ///
81+ /// The [listener] callback will be called immediately on addition and
82+ /// synchronously whenever [state] changes.
83+ ///
84+ /// Note: This method emits on every [ScopeState] change.
85+ ///
86+ /// Set [emitImmediately] to true if you want to an immediate execution
87+ /// of the [listener] with the current state.
88+ ///
89+ /// To remove this [listener] , call the function returned by [listen] .
90+ ///
91+ /// Listeners cannot add other listeners.
92+ /// Adding and removing listeners has a constant time-complexity.
93+ RemoveStateListener listenState (
94+ ScopeStateListener <Scope > listener, {
95+ bool emitImmediately = false ,
96+ }) =>
97+ _listen (
98+ (state) => listener (state),
99+ emitImmediately: emitImmediately,
100+ );
101+
102+ RemoveStateListener _listen (
103+ void Function (ScopeState <Scope > state) listener, {
104+ bool emitImmediately = false ,
53105 }) {
54106 assert (() {
55107 if (! _debugCanAddListeners) {
@@ -64,7 +116,7 @@ class ScopeStateHolder<Scope> {
64116 // Intentionally unsafe call of the listener before adding to the [_listeners]
65117 // so that if there is an exception — we throw it back to consumer
66118 // with an original stacktrace without adding to the [_listeners].
67- listener (scope );
119+ listener (state );
68120 } on Object catch (_) {
69121 rethrow ;
70122 } finally {
@@ -93,7 +145,7 @@ class ScopeStateHolder<Scope> {
93145class Entry <T > extends LinkedListEntry <Entry <T >> {
94146 Entry (this .listener);
95147
96- final StateListener <T > listener;
148+ final ScopeStateListener <T > listener;
97149}
98150
99151/// An error thrown when tried to update the state of a [ScopeStateHolder] ,
0 commit comments