diff --git a/package/CHANGELOG.md b/package/CHANGELOG.md index af5e83fd..2aa8122e 100644 --- a/package/CHANGELOG.md +++ b/package/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.5.2 May 5, 2024 + +- Fix a crash during the first build of `NavigationSheet` with a path that contains multiple routes such as `/a/b/c` (#109) + ## 0.5.1 May 4, 2024 - Re-export `NavigationSheetRoute` that is unintentionally omitted in v0.5.0 (#110) diff --git a/package/lib/src/internal/transition_observer.dart b/package/lib/src/internal/transition_observer.dart index 58914b9b..620d1a7c 100644 --- a/package/lib/src/internal/transition_observer.dart +++ b/package/lib/src/internal/transition_observer.dart @@ -1,6 +1,5 @@ import 'package:flutter/widgets.dart'; -@optionalTypeArgs class TransitionObserver extends NavigatorObserver { final Set _listeners = {}; @@ -58,34 +57,40 @@ mixin TransitionAwareWidgetMixin on StatefulWidget { mixin TransitionAwareStateMixin on State { - Transition? _currentTransition; + Transition? _lastReportedTransition; + Transition? get currentTransition => _lastReportedTransition; - void _setCurrentTransition(Transition? transition) { - if (_currentTransition != transition) { - _currentTransition = transition; - didChangeTransitionState(_currentTransition); + void _notify(Transition? transition) { + if (_lastReportedTransition != transition) { + _lastReportedTransition = transition; + didChangeTransitionState(transition); } } void didChangeTransitionState(Transition? transition); void didPush(ModalRoute route, ModalRoute? previousRoute) { - final currentState = _currentTransition; + final currentState = currentTransition; - if (previousRoute == null) { - _setCurrentTransition(NoTransition(currentRoute: route)); + if (previousRoute == null || route.animation!.isCompleted) { + // There is only one roue in the history stack, or multiple routes + // are pushed at the same time without transition animation. + _notify(NoTransition(currentRoute: route)); } else if (route.isCurrent && currentState is NoTransition) { - _setCurrentTransition(ForwardTransition( + // A new route is pushed on top of the stack with transition animation. + // Then, notify the listener of the beginning of the transition. + _notify(ForwardTransition( originRoute: currentState.currentRoute, destinationRoute: route, animation: route.animation!, )); + // Notify the listener again when the transition is completed. void transitionStatusListener(AnimationStatus status) { if (status == AnimationStatus.completed && !route.offstage) { route.animation!.removeStatusListener(transitionStatusListener); - if (_currentTransition is ForwardTransition) { - _setCurrentTransition(NoTransition(currentRoute: route)); + if (currentTransition is ForwardTransition) { + _notify(NoTransition(currentRoute: route)); } } } @@ -96,16 +101,16 @@ mixin TransitionAwareStateMixin void didPop(ModalRoute route, ModalRoute? previousRoute) { if (previousRoute == null) { - _setCurrentTransition(null); + _notify(null); } else { - _setCurrentTransition(BackwardTransition( + _notify(BackwardTransition( originRoute: route, destinationRoute: previousRoute, animation: route.animation!.drive(Tween(begin: 1, end: 0)), )); route.completed.whenComplete(() { - if (_currentTransition is BackwardTransition) { - _setCurrentTransition(NoTransition(currentRoute: previousRoute)); + if (currentTransition is BackwardTransition) { + _notify(NoTransition(currentRoute: previousRoute)); } }); } @@ -115,7 +120,7 @@ mixin TransitionAwareStateMixin ModalRoute route, ModalRoute? previousRoute, ) { - _setCurrentTransition(UserGestureTransition( + _notify(UserGestureTransition( currentRoute: route, previousRoute: previousRoute!, animation: route.animation!.drive(Tween(begin: 1, end: 0)), @@ -123,8 +128,8 @@ mixin TransitionAwareStateMixin } void didStopUserGesture() { - if (_currentTransition case final UserGestureTransition state) { - _setCurrentTransition(NoTransition( + if (currentTransition case final UserGestureTransition state) { + _notify(NoTransition( currentRoute: state.currentRoute, )); } @@ -142,14 +147,14 @@ mixin TransitionAwareStateMixin if (widget.transitionObserver != oldWidget.transitionObserver) { oldWidget.transitionObserver.unmount(this); widget.transitionObserver.mount(this); - _setCurrentTransition(null); + _notify(null); } } @override void dispose() { widget.transitionObserver.unmount(this); - _setCurrentTransition(null); + _notify(null); super.dispose(); } } diff --git a/package/lib/src/navigation/navigation_sheet.dart b/package/lib/src/navigation/navigation_sheet.dart index 67abe75f..ca71cbe3 100644 --- a/package/lib/src/navigation/navigation_sheet.dart +++ b/package/lib/src/navigation/navigation_sheet.dart @@ -40,7 +40,6 @@ class NavigationSheet extends StatefulWidget with TransitionAwareWidgetMixin { class _NavigationSheetState extends State with TransitionAwareStateMixin, SheetExtentDelegate { final GlobalKey _scopeKey = GlobalKey(); - Transition? _currentTransition; @override void didChangeTransitionState(Transition? transition) { @@ -87,12 +86,11 @@ class _NavigationSheetState extends State }; _scopeKey.currentState?.extent.beginActivity(sheetActivity); - _currentTransition = transition; } @override SheetActivity createIdleActivity() { - return switch (_currentTransition) { + return switch (currentTransition) { NoTransition(:final NavigationSheetRoute currentRoute) => _ProxySheetActivity(entry: currentRoute), _ => IdleSheetActivity(), diff --git a/package/pubspec.yaml b/package/pubspec.yaml index 98d4575d..1148e37e 100644 --- a/package/pubspec.yaml +++ b/package/pubspec.yaml @@ -1,6 +1,6 @@ name: smooth_sheets description: Sheet widgets with smooth motion and great flexibility. Also supports nested navigation in both imperative and declarative ways. -version: 0.5.1 +version: 0.5.2 repository: https://github.com/fujidaiti/smooth_sheets environment: