1212
1313// ignore_for_file: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
1414
15- import 'dart:math' as math;
16- import 'dart:ui' ;
17-
1815import 'package:df_pwa_utils/df_pwa_utils.dart' ;
1916import 'package:df_widgets/_common.dart' ;
20- import 'package:flutter/material.dart' ;
2117
2218import '_src.g.dart' ;
2319
@@ -42,6 +38,8 @@ class RouteController {
4238 final RouteState Function () fallbackRouteState;
4339 RouteState ? _requestedRouteState;
4440
41+ AnimationEffect nextEffect = NoEffect ();
42+
4543 //
4644 //
4745 //
@@ -52,13 +50,12 @@ class RouteController {
5250 required this .fallbackRouteState,
5351 required this .builders,
5452 }) {
53+ platformNavigator.addStateCallback (pushUri);
54+ // Set all the builder output to SizedBox.shrink.
55+ resetState ();
5556 _requestedRouteState = getNavigatorRouteState ();
5657 final routeState = initialRouteState? .call () ?? _requestedRouteState ?? fallbackRouteState ();
57- for (final builder in builders) {
58- _widgetCache[builder.routeState] = SizedBox .shrink (key: builder.routeState.key);
59- }
60- platformNavigator.addStateCallback (pushUri);
61- push (routeState, shouldAnimate: false );
58+ push (routeState);
6259 }
6360
6461 //
@@ -108,7 +105,7 @@ class RouteController {
108105 final builder = _getBuilderByPath (routeState.uri);
109106 if (builder == null ) continue ;
110107 if (_widgetCache[routeState] is SizedBox ) continue ;
111- _widgetCache[routeState] = SizedBox .shrink (key: _widgetCache[ routeState] ? .key);
108+ _widgetCache[routeState] = SizedBox .shrink (key: routeState.key);
112109 _pRouteState.notifyListeners ();
113110 }
114111 }
@@ -118,20 +115,34 @@ class RouteController {
118115 //
119116
120117 void clearCache () {
121- removeStatesFromCache (_widgetCache.keys);
118+ for (final builder in builders) {
119+ _widgetCache[builder.routeState] = SizedBox .shrink (key: builder.routeState.key);
120+ }
121+ }
122+
123+ //
124+ //
125+ //
126+
127+ void resetState () {
128+ clearCache ();
129+ final routeStates = builders
130+ .where ((builder) => builder.shouldPrebuild)
131+ .map ((e) => e.routeState);
132+ addStatesToCache (routeStates);
122133 }
123134
124135 //
125136 //
126137 //
127138
128- // void resetCache( ) {
129- // clearCache( );
130- // final routeStates = builders
131- // .where(( builder) => builder.shouldPrebuild)
132- // .map((e) => e. routeState);
133- // cacheStates(routeStates);
134- // }
139+ void _maybeRemoveStaleRoute ( RouteState routeState ) {
140+ final builder = _getBuilderByPath (routeState.uri );
141+ if (builder == null ) return ;
142+ if ( ! builder.shouldPreserve) {
143+ _widgetCache[routeState] = SizedBox . shrink (key : routeState.key );
144+ }
145+ }
135146
136147 //
137148 //
@@ -159,8 +170,9 @@ class RouteController {
159170 RouteState <TExtra > routeState, {
160171 RouteState ? errorFallback,
161172 RouteState ? fallback,
162- bool shouldAnimate = true ,
173+ AnimationEffect ? animationEffect ,
163174 }) {
175+ nextEffect = animationEffect ?? routeState.animationEffect ?? NoEffect ();
164176 print ('PUSHING!!!' );
165177 final uri = routeState.uri;
166178 final skipCurrent = routeState.skipCurrent;
@@ -198,20 +210,16 @@ class RouteController {
198210 return ;
199211 }
200212 platformNavigator.pushState (uri);
213+
201214 _prevRouteState = _pRouteState.value;
215+
216+ // Remove the previous route state from the cache if it is stale.
217+
202218 _pRouteState.value = routeState;
203219 addStatesToCache ([routeState]);
204220
205- globalKey.currentState? .setControllerValues (shouldAnimate ? 0.0 : 1 .0 );
221+ globalKey.currentState? .setControllerValues (0 .0 );
206222 globalKey.currentState? .forward ();
207-
208- //controller.startAnimation();
209- // final shouldAnimate = routeState.shouldAnimate;
210- // if (shouldAnimate) {
211- // Future.microtask(() {
212- // _controller.reset();
213- // });
214- // }
215223 }
216224
217225 //
@@ -249,7 +257,10 @@ class RouteController {
249257 Widget buildScreen (BuildContext context, RouteState routeState) {
250258 return AnimationEffectBuilder (
251259 key: globalKey,
252- effects: [FadeEffect ()],
260+ effects: [nextEffect],
261+ onComplete: () {
262+ _maybeRemoveStaleRoute (_prevRouteState);
263+ },
253264 builder: (context, results) {
254265 final layerEffects = results.map ((e) => e.data).toList ()[0 ];
255266 return PrioritizedIndexedStack (
@@ -287,6 +298,7 @@ class RouteController {
287298 }
288299}
289300
301+ // Assuming AnimationEffect and AnimationLayerEffect are defined as in the provided code
290302abstract class AnimationEffect {
291303 final Duration duration;
292304 final Curve curve;
@@ -305,8 +317,14 @@ class LayerEffectResult {
305317class AnimationEffectBuilder extends StatefulWidget {
306318 final List <AnimationEffect > effects;
307319 final Widget Function (BuildContext context, List <LayerEffectResult > results) builder;
320+ final VoidCallback ? onComplete; // New callback parameter
308321
309- const AnimationEffectBuilder ({super .key, required this .effects, required this .builder});
322+ const AnimationEffectBuilder ({
323+ super .key,
324+ required this .effects,
325+ required this .builder,
326+ this .onComplete,
327+ });
310328
311329 @override
312330 AnimationEffectBuilderState createState () => AnimationEffectBuilderState ();
@@ -316,23 +334,27 @@ class AnimationEffectBuilderState extends State<AnimationEffectBuilder>
316334 with TickerProviderStateMixin {
317335 late List <AnimationController > controllers;
318336 late List <Animation <double >> animations;
337+ bool _hasTriggeredCompletion = false ; // Track if callback has been triggered
319338
320339 void setControllerValues (double value) {
321340 for (final controller in controllers) {
322341 controller.value = value;
323342 }
343+ _hasTriggeredCompletion = false ; // Reset completion state
324344 }
325345
326346 void forwardControllers () {
327347 for (final controller in controllers) {
328348 controller.forward ();
329349 }
350+ _hasTriggeredCompletion = false ; // Reset completion state
330351 }
331352
332353 void reverseControllers () {
333354 for (final controller in controllers) {
334355 controller.reverse ();
335356 }
357+ _hasTriggeredCompletion = false ; // Reset completion state
336358 }
337359
338360 @override
@@ -344,7 +366,14 @@ class AnimationEffectBuilderState extends State<AnimationEffectBuilder>
344366 void _initializeAnimations () {
345367 controllers =
346368 widget.effects.map ((config) {
347- return AnimationController (vsync: this , duration: config.duration, value: 1.0 );
369+ final controller = AnimationController (
370+ vsync: this ,
371+ duration: config.duration,
372+ value: 1.0 ,
373+ );
374+ // Add status listener to track completion
375+ controller.addStatusListener (_handleAnimationStatus);
376+ return controller;
348377 }).toList ();
349378 animations =
350379 widget.effects.asMap ().entries.map ((entry) {
@@ -354,11 +383,25 @@ class AnimationEffectBuilderState extends State<AnimationEffectBuilder>
354383 }).toList ();
355384 }
356385
386+ void _handleAnimationStatus (AnimationStatus status) {
387+ // Check if all controllers are completed
388+ if (status == AnimationStatus .completed && ! _hasTriggeredCompletion) {
389+ final allCompleted = controllers.every (
390+ (controller) => controller.status == AnimationStatus .completed,
391+ );
392+ if (allCompleted) {
393+ widget.onComplete? .call ();
394+ _hasTriggeredCompletion = true ; // Prevent multiple triggers
395+ }
396+ }
397+ }
398+
357399 @override
358400 void didUpdateWidget (AnimationEffectBuilder oldWidget) {
359401 super .didUpdateWidget (oldWidget);
360402 if (widget.effects.length != oldWidget.effects.length) {
361403 for (var controller in controllers) {
404+ controller.removeStatusListener (_handleAnimationStatus);
362405 controller.dispose ();
363406 }
364407 _initializeAnimations ();
@@ -372,11 +415,13 @@ class AnimationEffectBuilderState extends State<AnimationEffectBuilder>
372415 }
373416 }
374417 }
418+ _hasTriggeredCompletion = false ; // Reset completion state on widget update
375419 }
376420
377421 @override
378422 void dispose () {
379423 for (final controller in controllers) {
424+ controller.removeStatusListener (_handleAnimationStatus);
380425 controller.dispose ();
381426 }
382427 super .dispose ();
@@ -386,12 +431,14 @@ class AnimationEffectBuilderState extends State<AnimationEffectBuilder>
386431 for (final controller in controllers) {
387432 controller.value = 0.0 ;
388433 }
434+ _hasTriggeredCompletion = false ; // Reset completion state
389435 }
390436
391437 void forward () {
392438 for (final controller in controllers) {
393439 controller.forward ();
394440 }
441+ _hasTriggeredCompletion = false ; // Reset completion state
395442 }
396443
397444 @override
0 commit comments