@@ -5,14 +5,23 @@ import 'package:grumpy_annotations/grumpy_annotations.dart';
55import 'package:meta/meta.dart' ;
66import 'package:grumpy/grumpy.dart' ;
77
8+ /// Provides use hooks for watching and accessing data within [UseRepoMixin._onDependenciesReady] .
9+ typedef UseHooks = ({
10+ /// A function that allows you to watch a [Repo] of type [R] managing data of type [S] and
11+ /// returns a tuple containing the data from the repo and the repo itself.
12+ ///
13+ /// Throws a [NoRepoDataError] if the repo's state does not contain data.
14+ Future <(S , R )> Function <S , R extends Repo <S >>() repo,
15+ });
16+
817/// A mixin that provides functionality to watch and use multiple [Repo] instances.
918///
1019/// {@category repo}
11-
1220mixin UseRepoMixin <D , E , L > on LifecycleMixin , LifecycleHooksMixin {
1321 final _subs = < StreamSubscription > [];
1422 final _watchedRepos = < Type , Repo > {};
1523 final _pendingRepoResolutions = < Type , Future <Repo <dynamic >>> {};
24+ final _watchedStreams = < Stream , StreamSubscription > {};
1625
1726 bool _installed = false ;
1827 int _stateChangeVersion = 0 ;
@@ -71,7 +80,7 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
7180 log ('All dependencies are ready. Rebuilding data...' );
7281 nextError = null ;
7382 nextLoading = null ;
74- nextData = await onDependenciesReady ();
83+ nextData = await _onDependenciesReady ();
7584 log ('Dependencies ready, obtained new data.' );
7685 }
7786 } on NoRepoDataError catch (e, st) {
@@ -103,7 +112,7 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
103112 Future <void > _discover () async {
104113 log ('Discovering dependencies...' );
105114 try {
106- final result = await onDependenciesReady ();
115+ final result = await _onDependenciesReady ();
107116
108117 // if we already get data in the discovery phase, store it.
109118 _lastData = result;
@@ -116,6 +125,11 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
116125 _lastError = await onDependencyError (e, st);
117126 // Ignore errors during the initial discovery phase.
118127 // we are just trying to discover repos here.
128+ } finally {
129+ log (
130+ 'Dependency discovery complete. Currently watching ${_watchedRepos .length } repos.' ,
131+ );
132+ await dependenciesChanged ();
119133 }
120134 }
121135
@@ -150,13 +164,17 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
150164 _subs.clear ();
151165 });
152166 onDisposed (_watchedRepos.clear);
167+ onDisposed (_watchedStreams.clear);
153168 }
154169
155170 /// Watches a [Repo] of type [R] managing data of type [S] and
156171 /// returns a tuple containing the data from the repo and the repo itself.
157172 ///
158173 /// Throws a [NoRepoDataError] if the repo's state does not contain data.
159- Future <(S , R )> useRepo <S , R extends Repo <S >>() async {
174+ @Deprecated ('Use the provided use arg in onDependenciesReady instead' )
175+ Future <(S , R )> useRepo <S , R extends Repo <S >>() => _useRepo <S , R >();
176+
177+ Future <(S , R )> _useRepo <S , R extends Repo <S >>() async {
160178 if (! _installed) {
161179 throw StateError (
162180 'UseRepoMixin not installed. Call installUseRepoHooks in the constructor.' ,
@@ -180,7 +198,7 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
180198 return _watchedRepos[R ] as R ;
181199 }
182200
183- log ('Discovered new dependency. Now watching repo of type $ R ' );
201+ log ('Discovered new dependency. Now watching ${ repo . logTag } ' );
184202 _watchedRepos[R ] = repo;
185203
186204 var ignoredInitialReplay = false ;
@@ -207,17 +225,19 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
207225 return (repo.state.requireData, repo);
208226 }
209227
228+ FutureOr <D > _onDependenciesReady () => onDependenciesReady ((repo: _useRepo));
229+
210230 /// A callback function that is called when all watched repositories are ready.
211- /// Call [useRepo] within this function to access repositories required to build the value.
231+ /// Call [use. useRepo] within this function to access repositories required to build the value.
212232 ///
213- /// [onDependenciesReady ] is called whenever any of the watched repositories emit a new state and *all* watched
233+ /// [_onDependenciesReady ] is called whenever any of the watched repositories emit a new state and *all* watched
214234 /// repositories have a state of [RepoDataState] .
215235 ///
216236 /// If this function throws an exception, the error will be handled by [onDependencyError] .
217- FutureOr <D > onDependenciesReady ();
237+ FutureOr <D > onDependenciesReady (UseHooks use );
218238
219239 /// A callback function that is called when any of the watched repositories emit an error state
220- /// or when an exception is thrown during the execution of [onDependenciesReady ] .
240+ /// or when an exception is thrown during the execution of [_onDependenciesReady ] .
221241 ///
222242 /// Takes precedence over [onDependenciesLoading] .
223243 FutureOr <E > onDependencyError (Object error, StackTrace ? stackTrace);
@@ -262,17 +282,6 @@ mixin UseRepoMixin<D, E, L> on LifecycleMixin, LifecycleHooksMixin {
262282 }
263283}
264284
265- /// A typedef for [UseRepoMixin.useRepo] .
266- ///
267- /// **Example:**
268- /// ```dart
269- /// final (user, userRepo) = await useRepo<User, UserRepo>();
270- /// ```
271- ///
272- /// {@category repo}
273-
274- typedef UseRepo = Future <(T , R )> Function <T , R extends Repo <T >>();
275-
276285/// A mixin that provides a deferred repository implementation using [UseRepoMixin] .
277286///
278287/// The [DeferredRepoMixin] allows you to create a repository that builds its state
@@ -298,15 +307,15 @@ mixin DeferredRepoMixin<T> on Repo<T>, UseRepoMixin<void, void, void> {
298307
299308 @mustCallSuper
300309 @override
301- FutureOr <void > onDependenciesReady () async {
302- final data = await build ();
310+ FutureOr <void > onDependenciesReady (UseHooks use ) async {
311+ final data = await build (use );
303312
304313 this .data (data);
305314 }
306315
307316 /// A builder function that constructs the state of this repo of type [T] .
308317 ///
309- /// When implementing this method, you can call [useRepo ] to access other repositories
318+ /// When implementing this method, you can call [UseHooks.repo ] to access other repositories
310319 /// that this repository depends on.
311- FutureOr <T > build ();
320+ FutureOr <T > build (UseHooks use );
312321}
0 commit comments