From 140ab58abf21c5d463de2e3917385322b6fa112c Mon Sep 17 00:00:00 2001 From: busslina Date: Tue, 17 Sep 2024 04:12:33 +0200 Subject: [PATCH 01/27] Removed transition and reverese transition durations on BeamPage When BeamPage is BeamPageType.noTransition --- package/lib/src/beam_page.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index 7199fb1..a45f5fb 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -323,6 +323,8 @@ class BeamPage extends Page { opaque: opaque, settings: this, pageBuilder: (context, animation, secondaryAnimation) => child, + transitionDuration: Duration.zero, + reverseTransitionDuration: Duration.zero, ); default: return MaterialPageRoute( From 6c907f74cdf57524b06ae417aece8e47f4c82bb2 Mon Sep 17 00:00:00 2001 From: busslina Date: Tue, 17 Sep 2024 07:14:28 +0200 Subject: [PATCH 02/27] Introducing pinnacle feature --- package/lib/src/beam_stack.dart | 17 ++++++++++++++--- package/lib/src/stack_builders.dart | 11 ++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index aa322f3..c907241 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -453,7 +453,14 @@ class RoutesBeamStack extends BeamStack { }) : super(routeInformation, beamParameters); /// Map of all routes this stack handles. - Map routes; + Map< + Pattern, + dynamic Function( + BuildContext, + BeamState, + Object? data, + bool isPinnacle, + )> routes; /// A wrapper used as [BeamStack.builder]. Widget Function(BuildContext context, Widget navigator)? navBuilder; @@ -489,8 +496,12 @@ class RoutesBeamStack extends BeamStack { ..removeWhere((key, value) => !filteredRoutes.containsKey(key)); final sortedRoutes = routeBuilders.keys.toList() ..sort((a, b) => _compareKeys(a, b)); - final pages = sortedRoutes.map((route) { - final routeElement = routes[route]!(context, state, data); + final sortedRoutesLength = sortedRoutes.length; + final pages = sortedRoutes.indexed.map((indexedRoute) { + final index = indexedRoute.$1; + final route = indexedRoute.$2; + final routeElement = + routes[route]!(context, state, data, index == sortedRoutesLength - 1); if (routeElement is BeamPage) { return routeElement; } else { diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 45fedc3..6dc32e8 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -49,7 +49,16 @@ class RoutesStackBuilder { RoutesStackBuilder({required this.routes, this.builder}); /// List of all routes this builder handles. - final Map routes; + /// + /// isPinnacle is true when the route is the outer/last in the stack. + final Map< + Pattern, + dynamic Function( + BuildContext, + BeamState, + Object?, + bool isPinnacle, + )> routes; /// Used as a [BeamStack.builder]. Widget Function(BuildContext context, Widget navigator)? builder; From d0cc6c164966b57b4f596bb933e48ce4df3bbb6c Mon Sep 17 00:00:00 2001 From: Vicente Date: Wed, 18 Sep 2024 06:08:50 +0200 Subject: [PATCH 03/27] Bulk snapshot --- package/lib/src/beam_page.dart | 77 ++++++++++++++++++++++++++++ package/lib/src/beam_stack.dart | 64 ++++++++++++++++++----- package/lib/src/beamer_delegate.dart | 33 ++++++++++++ package/lib/src/stack_builders.dart | 3 +- 4 files changed, 162 insertions(+), 15 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index a45f5fb..46ff89b 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -1,6 +1,7 @@ import 'package:beamer/beamer.dart'; import 'package:beamer/src/utils.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; /// Types for how to route should be built. @@ -230,6 +231,8 @@ class BeamPage extends Page { /// Defaults to `false`. final bool keepQueryOnPop; + LocalKey get key => super.key!; + @override Route createRoute(BuildContext context) { if (routeBuilder != null) { @@ -335,3 +338,77 @@ class BeamPage extends Page { } } } + +/// Represents the [BeamPage] state inside a [BeamStack]. +/// +/// This is a volatile state, meaning it is not stored. On the contrary, it is +/// regenerated on [BeamerDelegate.build]. +/// +/// Initialy created to inform a page whether is the last (the pinnacle) +/// on the stack. +class BeamPageState { + BeamPageState({ + required this.isPinnacle, + }); + + final bool isPinnacle; + + @override + bool operator ==(Object other) => + other is BeamPageState && isPinnacle == other.isPinnacle; + + @override + int get hashCode => isPinnacle.hashCode; +} + +/// Utility to inform [BeamPageState] to his [BeamPage]. +class BeamPageNotifier extends ValueListenable { + BeamPageNotifier(this.value) { + print('BeamPageNotifier.constructor() -- $_debugLabel'); + } + + final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); + + final _listeners = {}; + + BeamPageState value; + + @override + void addListener(VoidCallback listener) { + _listeners.add(listener); + print( + 'BeamPageNotifier.addListener() -- $_debugLabel -- Count: ${_listeners.length}'); + } + + @override + void removeListener(VoidCallback listener) { + _listeners.remove(listener); + print( + 'BeamPageNotifier.removeListener() -- $_debugLabel -- Count: ${_listeners.length}'); + } + + void notify() { + for (final listener in _listeners) { + listener(); + } + + print( + 'BeamPageNotifier.notify() -- $_debugLabel -- Count: ${_listeners.length}'); + } +} + +/// Utility to get a [BeamPageNotifier]. +/// +/// Needed because [BeamPage] is const and the notifier is not known until +/// the page is created. +// typedef BeamPageNotifierReference = BeamPageNotifier Function(LocalKey); +// typedef BeamPageNotifierReference = BeamPageNotifier Function(); +class BeamPageNotifierReference { + BeamPageNotifierReference(); + + BeamPageNotifier? _notifier; + + late final BeamPageNotifier Function() getNotifier; + + BeamPageNotifier get notifier => _notifier ??= getNotifier(); +} diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index c907241..c13a9a1 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -458,13 +458,22 @@ class RoutesBeamStack extends BeamStack { dynamic Function( BuildContext, BeamState, + // BeamPageNotifier, + BeamPageNotifierReference, Object? data, - bool isPinnacle, )> routes; /// A wrapper used as [BeamStack.builder]. Widget Function(BuildContext context, Widget navigator)? navBuilder; + /// They are regenerated on [buildPages], + /// so they are only valid for one build cycle. + /// + /// The reason for not making them persistent across build cycles is that + /// we can't know the [BeamPage.key] before creating them (see [buildPages]). + final Map _pageNotifiers = {}; + // final List _pageNotifiers = []; + @override Widget builder(BuildContext context, Widget navigator) { return navBuilder?.call(context, navigator) ?? navigator; @@ -496,20 +505,23 @@ class RoutesBeamStack extends BeamStack { ..removeWhere((key, value) => !filteredRoutes.containsKey(key)); final sortedRoutes = routeBuilders.keys.toList() ..sort((a, b) => _compareKeys(a, b)); - final sortedRoutesLength = sortedRoutes.length; - final pages = sortedRoutes.indexed.map((indexedRoute) { - final index = indexedRoute.$1; - final route = indexedRoute.$2; + final pages = sortedRoutes.indexed.map((value) { + final index = value.$1; + final route = value.$2; + final notifierReference = BeamPageNotifierReference(); final routeElement = - routes[route]!(context, state, data, index == sortedRoutesLength - 1); - if (routeElement is BeamPage) { - return routeElement; - } else { - return BeamPage( - key: ValueKey(filteredRoutes[route]), - child: routeElement, - ); - } + routes[route]!(context, state, notifierReference, data); + final page = routeElement is BeamPage + ? routeElement + : BeamPage( + key: ValueKey(filteredRoutes[route]), + child: routeElement, + ); + print('Notifier exists: ${_pageNotifiers.containsKey(page.key)}'); + final notifier = _pageNotifiers[page.key] ??= BeamPageNotifier( + BeamPageState(isPinnacle: index == sortedRoutes.length - 1)); + notifierReference.getNotifier = () => notifier; + return page; }).toList(); return pages; } @@ -609,4 +621,28 @@ class RoutesBeamStack extends BeamStack { return isNotFound ? {} : matched; } + + void notifyPages(List pages) { + // Hidden pages + for (int i = 0; i < pages.length - 1; i++) { + print('Notifying page: ${pages[i].title} -- Is pinnacle: false'); + _pageNotifiers[pages[i].key]! + ..value = BeamPageState(isPinnacle: false) + ..notify(); + } + + // Pinnacle page + print('Notifying page: ${pages.last.title} -- Is pinnacle: true'); + _pageNotifiers[pages.last.key]! + ..value = BeamPageState(isPinnacle: true) + ..notify(); + } + + /// Returns current notifiers and clean them up. + List getPageNotifiers() { + return [..._pageNotifiers.values]; + // final notifiers = [..._pageNotifiers.values]; + // _pageNotifiers.clear(); + // return notifiers; + } } diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index c6a4140..ef18a5a 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -50,6 +50,8 @@ class BeamerDelegate extends RouterDelegate updateListenable?.addListener(_update); } + bool _firstBuild = true; + /// A state of this delegate. This is the `routeInformation` that goes into /// [stackBuilder] to build an appropriate [BeamStack]. /// @@ -60,6 +62,8 @@ class BeamerDelegate extends RouterDelegate final Set _children = {}; + final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); + /// Takes priority over all other siblings, /// i.e. sets itself as active and all other siblings as inactive. void takePriority() { @@ -754,6 +758,12 @@ class BeamerDelegate extends RouterDelegate @override Widget build(BuildContext context) { + final isFirstBuild = this._firstBuild; + _firstBuild = false; + + print( + 'BeamerDelegate.build() -- $_debugLabel -- Is first build: $isFirstBuild'); + _buildInProgress = true; _context = context; @@ -777,9 +787,21 @@ class BeamerDelegate extends RouterDelegate final navigator = Builder( builder: (context) { _setCurrentPages(context); + + // print( + // 'BeamerDelegate.build() -- $_debugLabel -- Builder page length: ${_currentPages.length}'); + _setBrowserTitle(context); buildListener?.call(context, this); + + // Notifying pages + if (!isFirstBuild) { + final count = _notifyCurrentPages(); + print( + 'BeamerDelegate.build() -- $_debugLabel -- Notified pages: $count'); + } + return Navigator( key: navigatorKey, observers: navigatorObservers, @@ -986,6 +1008,17 @@ class BeamerDelegate extends RouterDelegate } } + int _notifyCurrentPages() { + final stack = currentBeamStack; + + if (stack is! RoutesBeamStack) { + return 0; + } + + stack.notifyPages(_currentPages); + return _currentPages.length; + } + void _setBrowserTitle(BuildContext context) { if (active && setBrowserTabTitle) { final String title = _currentPages.last.title ?? diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 6dc32e8..f7e0746 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -56,8 +56,9 @@ class RoutesStackBuilder { dynamic Function( BuildContext, BeamState, + // BeamPageNotifier, + BeamPageNotifierReference, Object?, - bool isPinnacle, )> routes; /// Used as a [BeamStack.builder]. From 618de461f5553e23379c0a08289d9ec2dfae621c Mon Sep 17 00:00:00 2001 From: Vicente Date: Thu, 19 Sep 2024 05:58:11 +0200 Subject: [PATCH 04/27] snapshot --- package/lib/src/beam_page.dart | 8 +++++++- package/lib/src/beam_stack.dart | 18 +++++++++++++++++- package/lib/src/beamer_delegate.dart | 15 ++++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index 46ff89b..b206786 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -363,16 +363,22 @@ class BeamPageState { /// Utility to inform [BeamPageState] to his [BeamPage]. class BeamPageNotifier extends ValueListenable { - BeamPageNotifier(this.value) { + BeamPageNotifier( + this.value, { + required this.parentStackDebugLabel, + }) { print('BeamPageNotifier.constructor() -- $_debugLabel'); } + final String parentStackDebugLabel; final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); final _listeners = {}; BeamPageState value; + String get fullDebugLabel => '$parentStackDebugLabel-$_debugLabel'; + @override void addListener(VoidCallback listener) { _listeners.add(listener); diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index c13a9a1..3707c54 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -95,6 +95,8 @@ abstract class BeamStack create(routeInformation, beamParameters); } + final debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); + late T _state; /// A state of this [BeamStack]. @@ -473,6 +475,7 @@ class RoutesBeamStack extends BeamStack { /// we can't know the [BeamPage.key] before creating them (see [buildPages]). final Map _pageNotifiers = {}; // final List _pageNotifiers = []; + // final Map _pageNotifiers = {}; @override Widget builder(BuildContext context, Widget navigator) { @@ -500,6 +503,8 @@ class RoutesBeamStack extends BeamStack { @override List buildPages(BuildContext context, BeamState state) { + _printCurrentPageNotifiers('buildPages'); + final filteredRoutes = chooseRoutes(state.routeInformation, routes.keys); final routeBuilders = Map.of(routes) ..removeWhere((key, value) => !filteredRoutes.containsKey(key)); @@ -519,7 +524,9 @@ class RoutesBeamStack extends BeamStack { ); print('Notifier exists: ${_pageNotifiers.containsKey(page.key)}'); final notifier = _pageNotifiers[page.key] ??= BeamPageNotifier( - BeamPageState(isPinnacle: index == sortedRoutes.length - 1)); + BeamPageState(isPinnacle: index == sortedRoutes.length - 1), + parentStackDebugLabel: debugLabel, + ); notifierReference.getNotifier = () => notifier; return page; }).toList(); @@ -623,6 +630,8 @@ class RoutesBeamStack extends BeamStack { } void notifyPages(List pages) { + _printCurrentPageNotifiers('notifyPages'); + // Hidden pages for (int i = 0; i < pages.length - 1; i++) { print('Notifying page: ${pages[i].title} -- Is pinnacle: false'); @@ -645,4 +654,11 @@ class RoutesBeamStack extends BeamStack { // _pageNotifiers.clear(); // return notifiers; } + + void _printCurrentPageNotifiers(String debugLabel) { + print('_printCurrentPageNotifiers() -- ${this.debugLabel} -- $debugLabel'); + for (final entry in _pageNotifiers.entries) { + print('LocalKey: ${entry.key}, Notifier: ${entry.value.fullDebugLabel}'); + } + } } diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index ef18a5a..5c27736 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -761,8 +761,10 @@ class BeamerDelegate extends RouterDelegate final isFirstBuild = this._firstBuild; _firstBuild = false; + final current = currentBeamStack; + print( - 'BeamerDelegate.build() -- $_debugLabel -- Is first build: $isFirstBuild'); + 'BeamerDelegate.build() -- I -- $_debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); _buildInProgress = true; _context = context; @@ -786,6 +788,11 @@ class BeamerDelegate extends RouterDelegate final navigator = Builder( builder: (context) { + final current = currentBeamStack; + + print( + 'BeamerDelegate.build() -- II -- $_debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); + _setCurrentPages(context); // print( @@ -999,6 +1006,12 @@ class BeamerDelegate extends RouterDelegate } void _setCurrentPages(BuildContext context) { + final currentBeamStack = this.currentBeamStack; + + if (currentBeamStack is RoutesBeamStack) { + print('_setCurrentPages() -- ${currentBeamStack.debugLabel}'); + } + if (currentBeamStack is NotFound) { _currentPages = [notFoundPage]; } else { From fb86e47b964b39750966df400dabf371d8292e7b Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 07:52:30 +0200 Subject: [PATCH 05/27] snapshot --- package/lib/src/beam_stack.dart | 41 +++++++++++++++++----------- package/lib/src/beamer_delegate.dart | 13 ++++++--- package/lib/src/stack_builders.dart | 11 ++++++-- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 3707c54..470c2f5 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -88,14 +88,17 @@ abstract class BeamStack /// Creates a [BeamStack] with specified properties. /// /// All attributes can be null. - BeamStack([ + BeamStack( + this.debugLabel, [ RouteInformation? routeInformation, BeamParameters? beamParameters, ]) { create(routeInformation, beamParameters); } - final debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); + // final debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); + + final String debugLabel; late T _state; @@ -263,7 +266,7 @@ abstract class BeamStack } /// The history of beaming for this. - List history = []; + final List history = []; /// Adds another [HistoryElement] to [history] list. /// The history element is created from given [state] and [beamParameters]. @@ -396,7 +399,8 @@ abstract class BeamStack class NotFound extends BeamStack { /// Creates a [NotFound] [BeamStack] with /// `RouteInformation(uri: Uri.parse(path)` as its state. - NotFound({String path = '/'}) : super(RouteInformation(uri: Uri.parse(path))); + NotFound({String path = '/'}) + : super('NotFound', RouteInformation(uri: Uri.parse(path))); @override List buildPages(BuildContext context, BeamState state) => []; @@ -409,6 +413,8 @@ class NotFound extends BeamStack { /// /// See [BeamerDelegate.currentBeamStack]. class EmptyBeamStack extends BeamStack { + EmptyBeamStack() : super('EmptyBeamStack'); + @override List buildPages(BuildContext context, BeamState state) => []; @@ -423,7 +429,7 @@ class GuardShowPage extends BeamStack { GuardShowPage( this.routeInformation, this.beamPage, - ) : super(routeInformation); + ) : super('GuardShowPage', routeInformation); /// [RouteInformation] to show in URL final RouteInformation routeInformation; @@ -447,15 +453,18 @@ class RoutesBeamStack extends BeamStack { /// /// [routeInformation] and [routes] are required. RoutesBeamStack({ + required String debugLabel, required RouteInformation routeInformation, Object? data, BeamParameters? beamParameters, required this.routes, this.navBuilder, - }) : super(routeInformation, beamParameters); + }) : super(debugLabel, routeInformation, beamParameters) { + print('RoutesBeamStack.constructor() -- $debugLabel'); + } /// Map of all routes this stack handles. - Map< + final Map< Pattern, dynamic Function( BuildContext, @@ -466,7 +475,7 @@ class RoutesBeamStack extends BeamStack { )> routes; /// A wrapper used as [BeamStack.builder]. - Widget Function(BuildContext context, Widget navigator)? navBuilder; + final Widget Function(BuildContext context, Widget navigator)? navBuilder; /// They are regenerated on [buildPages], /// so they are only valid for one build cycle. @@ -503,7 +512,7 @@ class RoutesBeamStack extends BeamStack { @override List buildPages(BuildContext context, BeamState state) { - _printCurrentPageNotifiers('buildPages'); + // _printCurrentPageNotifiers('buildPages'); final filteredRoutes = chooseRoutes(state.routeInformation, routes.keys); final routeBuilders = Map.of(routes) @@ -630,7 +639,7 @@ class RoutesBeamStack extends BeamStack { } void notifyPages(List pages) { - _printCurrentPageNotifiers('notifyPages'); + // _printCurrentPageNotifiers('notifyPages'); // Hidden pages for (int i = 0; i < pages.length - 1; i++) { @@ -655,10 +664,10 @@ class RoutesBeamStack extends BeamStack { // return notifiers; } - void _printCurrentPageNotifiers(String debugLabel) { - print('_printCurrentPageNotifiers() -- ${this.debugLabel} -- $debugLabel'); - for (final entry in _pageNotifiers.entries) { - print('LocalKey: ${entry.key}, Notifier: ${entry.value.fullDebugLabel}'); - } - } + // void _printCurrentPageNotifiers(String debugLabel) { + // print('_printCurrentPageNotifiers() -- ${this.debugLabel} -- $debugLabel'); + // for (final entry in _pageNotifiers.entries) { + // print('LocalKey: ${entry.key}, Notifier: ${entry.value.fullDebugLabel}'); + // } + // } } diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 5c27736..95a0337 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -17,6 +17,7 @@ class BeamerDelegate extends RouterDelegate /// [stackBuilder] is required to process the incoming navigation request. BeamerDelegate({ required this.stackBuilder, + required this.debugLabel, this.initialPath = '/', this.routeListener, this.buildListener, @@ -41,6 +42,8 @@ class BeamerDelegate extends RouterDelegate this.updateParent = true, this.clearBeamingHistoryOn = const {}, }) { + print('BeamerDelegate.constructor() -- $debugLabel'); + _currentBeamParameters = BeamParameters( transitionDelegate: transitionDelegate, ); @@ -62,7 +65,9 @@ class BeamerDelegate extends RouterDelegate final Set _children = {}; - final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); + final String debugLabel; + + // final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); /// Takes priority over all other siblings, /// i.e. sets itself as active and all other siblings as inactive. @@ -764,7 +769,7 @@ class BeamerDelegate extends RouterDelegate final current = currentBeamStack; print( - 'BeamerDelegate.build() -- I -- $_debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); + 'BeamerDelegate.build() -- I -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); _buildInProgress = true; _context = context; @@ -791,7 +796,7 @@ class BeamerDelegate extends RouterDelegate final current = currentBeamStack; print( - 'BeamerDelegate.build() -- II -- $_debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); + 'BeamerDelegate.build() -- II -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); _setCurrentPages(context); @@ -806,7 +811,7 @@ class BeamerDelegate extends RouterDelegate if (!isFirstBuild) { final count = _notifyCurrentPages(); print( - 'BeamerDelegate.build() -- $_debugLabel -- Notified pages: $count'); + 'BeamerDelegate.build() -- $debugLabel -- Notified pages: $count'); } return Navigator( diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index f7e0746..e549ada 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -46,7 +46,13 @@ class RoutesStackBuilder { /// Creates a [RoutesStackBuilder] with specified properties. /// /// [routes] are required to build pages from. - RoutesStackBuilder({required this.routes, this.builder}); + RoutesStackBuilder({ + required this.debugLabel, + required this.routes, + this.builder, + }); + + final String debugLabel; /// List of all routes this builder handles. /// @@ -62,7 +68,7 @@ class RoutesStackBuilder { )> routes; /// Used as a [BeamStack.builder]. - Widget Function(BuildContext context, Widget navigator)? builder; + final Widget Function(BuildContext context, Widget navigator)? builder; /// Makes this callable as [StackBuilder]. /// @@ -74,6 +80,7 @@ class RoutesStackBuilder { final matched = RoutesBeamStack.chooseRoutes(routeInformation, routes.keys); if (matched.isNotEmpty) { return RoutesBeamStack( + debugLabel: '$debugLabel -- ${DateTime.now().millisecondsSinceEpoch}', routeInformation: routeInformation, routes: routes, navBuilder: builder, From 0c79fc2e6d1554553c437872ae65a8cda97f86ac Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 08:12:00 +0200 Subject: [PATCH 06/27] snapshot --- package/lib/src/beam_stack.dart | 3 ++- package/lib/src/beamer_delegate.dart | 15 ++++++++++++--- package/lib/src/stack_builders.dart | 3 +++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 470c2f5..83c64e4 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -454,13 +454,14 @@ class RoutesBeamStack extends BeamStack { /// [routeInformation] and [routes] are required. RoutesBeamStack({ required String debugLabel, + required String creationReason, required RouteInformation routeInformation, Object? data, BeamParameters? beamParameters, required this.routes, this.navBuilder, }) : super(debugLabel, routeInformation, beamParameters) { - print('RoutesBeamStack.constructor() -- $debugLabel'); + print('RoutesBeamStack.constructor() -- $debugLabel -- $creationReason'); } /// Map of all routes this stack handles. diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 95a0337..2dc0307 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -435,6 +435,7 @@ class BeamerDelegate extends RouterDelegate _beamStackCandidate = stackBuilder( this.configuration.copyWith(), _currentBeamParameters, + 'update', ); } @@ -1005,6 +1006,7 @@ class BeamerDelegate extends RouterDelegate _beamStackCandidate = stackBuilder( RouteInformation(uri: Uri.parse(notFoundRedirectNamed!)), _currentBeamParameters.copyWith(), + '_handleNotFoundRedirect', ); } _updateFromBeamStackCandidate(); @@ -1097,8 +1099,11 @@ class BeamerDelegate extends RouterDelegate void _initializeChild() { final parentConfiguration = _parent!.configuration.copyWith(); if (initializeFromParent) { - _beamStackCandidate = - stackBuilder(parentConfiguration, _currentBeamParameters); + _beamStackCandidate = stackBuilder( + parentConfiguration, + _currentBeamParameters, + '_initializeChild', + ); } // If this couldn't handle parents configuration, @@ -1128,7 +1133,11 @@ class BeamerDelegate extends RouterDelegate // Updates only if it can handle the configuration void _updateFromParent({bool rebuild = true}) { final parentConfiguration = _parent!.configuration.copyWith(); - final beamStack = stackBuilder(parentConfiguration, _currentBeamParameters); + final beamStack = stackBuilder( + parentConfiguration, + _currentBeamParameters, + '_updateFromParent', + ); if (beamStack is! NotFound) { update( diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index e549ada..177a0ec 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -7,6 +7,7 @@ import 'package:beamer/src/utils.dart'; typedef StackBuilder = BeamStack Function( RouteInformation, BeamParameters?, + String creationReason, ); /// A pre-made builder to be used for [BeamerDelegate.stackBuilder]. @@ -76,11 +77,13 @@ class RoutesStackBuilder { BeamStack call( RouteInformation routeInformation, BeamParameters? beamParameters, + String creationReason, ) { final matched = RoutesBeamStack.chooseRoutes(routeInformation, routes.keys); if (matched.isNotEmpty) { return RoutesBeamStack( debugLabel: '$debugLabel -- ${DateTime.now().millisecondsSinceEpoch}', + creationReason: creationReason, routeInformation: routeInformation, routes: routes, navBuilder: builder, From 98236f59be8f05a0b441d77a6b1c6249d2e5b91b Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 08:33:51 +0200 Subject: [PATCH 07/27] snapshot --- package/lib/src/beam_stack.dart | 17 ++++++++++------- package/lib/src/beamer_delegate.dart | 24 +++++++++++++++--------- package/lib/src/stack_builders.dart | 3 +++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 83c64e4..2d5ddf0 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -453,6 +453,7 @@ class RoutesBeamStack extends BeamStack { /// /// [routeInformation] and [routes] are required. RoutesBeamStack({ + required this.parent, required String debugLabel, required String creationReason, required RouteInformation routeInformation, @@ -461,9 +462,11 @@ class RoutesBeamStack extends BeamStack { required this.routes, this.navBuilder, }) : super(debugLabel, routeInformation, beamParameters) { - print('RoutesBeamStack.constructor() -- $debugLabel -- $creationReason'); + // print('RoutesBeamStack.constructor() -- $debugLabel -- $creationReason'); } + final BeamerDelegate parent; + /// Map of all routes this stack handles. final Map< Pattern, @@ -483,7 +486,7 @@ class RoutesBeamStack extends BeamStack { /// /// The reason for not making them persistent across build cycles is that /// we can't know the [BeamPage.key] before creating them (see [buildPages]). - final Map _pageNotifiers = {}; + // final Map _pageNotifiers = {}; // final List _pageNotifiers = []; // final Map _pageNotifiers = {}; @@ -532,8 +535,8 @@ class RoutesBeamStack extends BeamStack { key: ValueKey(filteredRoutes[route]), child: routeElement, ); - print('Notifier exists: ${_pageNotifiers.containsKey(page.key)}'); - final notifier = _pageNotifiers[page.key] ??= BeamPageNotifier( + print('Notifier exists: ${parent.pageNotifiers.containsKey(page.key)}'); + final notifier = parent.pageNotifiers[page.key] ??= BeamPageNotifier( BeamPageState(isPinnacle: index == sortedRoutes.length - 1), parentStackDebugLabel: debugLabel, ); @@ -645,21 +648,21 @@ class RoutesBeamStack extends BeamStack { // Hidden pages for (int i = 0; i < pages.length - 1; i++) { print('Notifying page: ${pages[i].title} -- Is pinnacle: false'); - _pageNotifiers[pages[i].key]! + parent.pageNotifiers[pages[i].key]! ..value = BeamPageState(isPinnacle: false) ..notify(); } // Pinnacle page print('Notifying page: ${pages.last.title} -- Is pinnacle: true'); - _pageNotifiers[pages.last.key]! + parent.pageNotifiers[pages.last.key]! ..value = BeamPageState(isPinnacle: true) ..notify(); } /// Returns current notifiers and clean them up. List getPageNotifiers() { - return [..._pageNotifiers.values]; + return [...parent.pageNotifiers.values]; // final notifiers = [..._pageNotifiers.values]; // _pageNotifiers.clear(); // return notifiers; diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 2dc0307..6cd9434 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -42,7 +42,7 @@ class BeamerDelegate extends RouterDelegate this.updateParent = true, this.clearBeamingHistoryOn = const {}, }) { - print('BeamerDelegate.constructor() -- $debugLabel'); + // print('BeamerDelegate.constructor() -- $debugLabel'); _currentBeamParameters = BeamParameters( transitionDelegate: transitionDelegate, @@ -53,6 +53,8 @@ class BeamerDelegate extends RouterDelegate updateListenable?.addListener(_update); } + final Map pageNotifiers = {}; + bool _firstBuild = true; /// A state of this delegate. This is the `routeInformation` that goes into @@ -433,6 +435,7 @@ class BeamerDelegate extends RouterDelegate if (buildBeamStack) { // build a BeamStack from configuration _beamStackCandidate = stackBuilder( + this, this.configuration.copyWith(), _currentBeamParameters, 'update', @@ -767,10 +770,10 @@ class BeamerDelegate extends RouterDelegate final isFirstBuild = this._firstBuild; _firstBuild = false; - final current = currentBeamStack; + // final current = currentBeamStack; - print( - 'BeamerDelegate.build() -- I -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); + // print( + // 'BeamerDelegate.build() -- I -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); _buildInProgress = true; _context = context; @@ -794,10 +797,10 @@ class BeamerDelegate extends RouterDelegate final navigator = Builder( builder: (context) { - final current = currentBeamStack; + // final current = currentBeamStack; - print( - 'BeamerDelegate.build() -- II -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); + // print( + // 'BeamerDelegate.build() -- II -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); _setCurrentPages(context); @@ -811,8 +814,8 @@ class BeamerDelegate extends RouterDelegate // Notifying pages if (!isFirstBuild) { final count = _notifyCurrentPages(); - print( - 'BeamerDelegate.build() -- $debugLabel -- Notified pages: $count'); + // print( + // 'BeamerDelegate.build() -- $debugLabel -- Notified pages: $count'); } return Navigator( @@ -1004,6 +1007,7 @@ class BeamerDelegate extends RouterDelegate _beamStackCandidate = notFoundRedirect!; } else if (notFoundRedirectNamed != null) { _beamStackCandidate = stackBuilder( + this, RouteInformation(uri: Uri.parse(notFoundRedirectNamed!)), _currentBeamParameters.copyWith(), '_handleNotFoundRedirect', @@ -1100,6 +1104,7 @@ class BeamerDelegate extends RouterDelegate final parentConfiguration = _parent!.configuration.copyWith(); if (initializeFromParent) { _beamStackCandidate = stackBuilder( + this, parentConfiguration, _currentBeamParameters, '_initializeChild', @@ -1134,6 +1139,7 @@ class BeamerDelegate extends RouterDelegate void _updateFromParent({bool rebuild = true}) { final parentConfiguration = _parent!.configuration.copyWith(); final beamStack = stackBuilder( + this, parentConfiguration, _currentBeamParameters, '_updateFromParent', diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 177a0ec..72ae01e 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -5,6 +5,7 @@ import 'package:beamer/src/utils.dart'; /// A convenience typedef for [BeamerDelegate.stackBuilder]. typedef StackBuilder = BeamStack Function( + BeamerDelegate parent, RouteInformation, BeamParameters?, String creationReason, @@ -75,6 +76,7 @@ class RoutesStackBuilder { /// /// Returns [RoutesBeamStack] configured with chosen routes from [routes] or [NotFound]. BeamStack call( + BeamerDelegate parent, RouteInformation routeInformation, BeamParameters? beamParameters, String creationReason, @@ -82,6 +84,7 @@ class RoutesStackBuilder { final matched = RoutesBeamStack.chooseRoutes(routeInformation, routes.keys); if (matched.isNotEmpty) { return RoutesBeamStack( + parent: parent, debugLabel: '$debugLabel -- ${DateTime.now().millisecondsSinceEpoch}', creationReason: creationReason, routeInformation: routeInformation, From d375756919b6f8864816296552f60c7f8ce1287c Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 08:52:18 +0200 Subject: [PATCH 08/27] snapshot --- package/lib/src/beam_stack.dart | 35 ---------------------- package/lib/src/beamer_delegate.dart | 45 +++++++++++++++------------- 2 files changed, 25 insertions(+), 55 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 2d5ddf0..f88fead 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -516,8 +516,6 @@ class RoutesBeamStack extends BeamStack { @override List buildPages(BuildContext context, BeamState state) { - // _printCurrentPageNotifiers('buildPages'); - final filteredRoutes = chooseRoutes(state.routeInformation, routes.keys); final routeBuilders = Map.of(routes) ..removeWhere((key, value) => !filteredRoutes.containsKey(key)); @@ -641,37 +639,4 @@ class RoutesBeamStack extends BeamStack { return isNotFound ? {} : matched; } - - void notifyPages(List pages) { - // _printCurrentPageNotifiers('notifyPages'); - - // Hidden pages - for (int i = 0; i < pages.length - 1; i++) { - print('Notifying page: ${pages[i].title} -- Is pinnacle: false'); - parent.pageNotifiers[pages[i].key]! - ..value = BeamPageState(isPinnacle: false) - ..notify(); - } - - // Pinnacle page - print('Notifying page: ${pages.last.title} -- Is pinnacle: true'); - parent.pageNotifiers[pages.last.key]! - ..value = BeamPageState(isPinnacle: true) - ..notify(); - } - - /// Returns current notifiers and clean them up. - List getPageNotifiers() { - return [...parent.pageNotifiers.values]; - // final notifiers = [..._pageNotifiers.values]; - // _pageNotifiers.clear(); - // return notifiers; - } - - // void _printCurrentPageNotifiers(String debugLabel) { - // print('_printCurrentPageNotifiers() -- ${this.debugLabel} -- $debugLabel'); - // for (final entry in _pageNotifiers.entries) { - // print('LocalKey: ${entry.key}, Notifier: ${entry.value.fullDebugLabel}'); - // } - // } } diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 6cd9434..1578dab 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -770,11 +770,6 @@ class BeamerDelegate extends RouterDelegate final isFirstBuild = this._firstBuild; _firstBuild = false; - // final current = currentBeamStack; - - // print( - // 'BeamerDelegate.build() -- I -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); - _buildInProgress = true; _context = context; @@ -797,25 +792,17 @@ class BeamerDelegate extends RouterDelegate final navigator = Builder( builder: (context) { - // final current = currentBeamStack; - - // print( - // 'BeamerDelegate.build() -- II -- $debugLabel -- ${current.debugLabel} -- Is first build: $isFirstBuild -- Type: ${current.runtimeType}'); - _setCurrentPages(context); - // print( - // 'BeamerDelegate.build() -- $_debugLabel -- Builder page length: ${_currentPages.length}'); - _setBrowserTitle(context); buildListener?.call(context, this); + _printCurrentPageNotifiers(); + // Notifying pages if (!isFirstBuild) { - final count = _notifyCurrentPages(); - // print( - // 'BeamerDelegate.build() -- $debugLabel -- Notified pages: $count'); + _notifyCurrentPages(); } return Navigator( @@ -1032,15 +1019,33 @@ class BeamerDelegate extends RouterDelegate } } - int _notifyCurrentPages() { + void _notifyCurrentPages() { final stack = currentBeamStack; if (stack is! RoutesBeamStack) { - return 0; + return; + } + + // Hidden pages + for (int i = 0; i < _currentPages.length - 1; i++) { + print('Notifying page: ${_currentPages[i].title} -- Is pinnacle: false'); + pageNotifiers[_currentPages[i].key]! + ..value = BeamPageState(isPinnacle: false) + ..notify(); } - stack.notifyPages(_currentPages); - return _currentPages.length; + // Pinnacle page + print('Notifying page: ${_currentPages.last.title} -- Is pinnacle: true'); + pageNotifiers[_currentPages.last.key]! + ..value = BeamPageState(isPinnacle: true) + ..notify(); + } + + void _printCurrentPageNotifiers() { + print('_printCurrentPageNotifiers()'); + for (final entry in pageNotifiers.entries) { + print('LocalKey: ${entry.key}, Notifier: ${entry.value.fullDebugLabel}'); + } } void _setBrowserTitle(BuildContext context) { From 10cc87a26be3d5a83347ce66035f833e499236f5 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 09:02:16 +0200 Subject: [PATCH 09/27] snapshot --- package/lib/src/stack_builders.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 72ae01e..e24bd27 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -64,7 +64,6 @@ class RoutesStackBuilder { dynamic Function( BuildContext, BeamState, - // BeamPageNotifier, BeamPageNotifierReference, Object?, )> routes; From 1548d3087a81eb0ec960dc4a18942e85a43a3fd2 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 09:16:59 +0200 Subject: [PATCH 10/27] snapshot --- package/lib/src/beam_page.dart | 8 ++++++++ package/lib/src/beam_stack.dart | 1 + package/lib/src/beamer_delegate.dart | 11 +++++++++++ 3 files changed, 20 insertions(+) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index b206786..b52a2fc 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -418,3 +418,11 @@ class BeamPageNotifierReference { BeamPageNotifier get notifier => _notifier ??= getNotifier(); } + +class BeamPageStateChangeNotifier extends ValueListenable + with ChangeNotifier { + BeamPageStateChangeNotifier(this.value); + + @override + BeamPageState value; +} diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index f88fead..d37feec 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -541,6 +541,7 @@ class RoutesBeamStack extends BeamStack { notifierReference.getNotifier = () => notifier; return page; }).toList(); + return pages; } diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 1578dab..aee635a 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -1012,13 +1012,24 @@ class BeamerDelegate extends RouterDelegate if (currentBeamStack is NotFound) { _currentPages = [notFoundPage]; + pageNotifiers.clear(); } else { _currentPages = _currentBeamParameters.stacked ? currentBeamStack.buildPages(context, currentBeamStack.state) : [currentBeamStack.buildPages(context, currentBeamStack.state).last]; + _purgePageNotifiers(); } } + /// Purging outdated page notifiers. + void _purgePageNotifiers() { + final currentPagesKeys = _currentPages.map((page) => page.key); + print('_purgePageNotifiers() -- 1 -- ${pageNotifiers.length}'); + pageNotifiers + .removeWhere((key, pageNotifier) => !currentPagesKeys.contains(key)); + print('_purgePageNotifiers() -- 2 -- ${pageNotifiers.length}'); + } + void _notifyCurrentPages() { final stack = currentBeamStack; From 03e17f79eb4e2c8dedc728ebf2ab54ee9df2e716 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:22:58 +0200 Subject: [PATCH 11/27] snapshot --- package/lib/src/beam_page.dart | 87 ++++++++++++++-------------- package/lib/src/beam_stack.dart | 26 ++++++--- package/lib/src/beamer_delegate.dart | 8 +-- package/lib/src/stack_builders.dart | 3 +- 4 files changed, 68 insertions(+), 56 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index b52a2fc..16b9f9b 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -55,6 +55,7 @@ class BeamPage extends Page { this.fullScreenDialog = false, this.opaque = true, this.keepQueryOnPop = false, + this.stateChangeNotifier, }) : super(key: key, name: name); /// A [BeamPage] to be the default for [BeamerDelegate.notFoundPage]. @@ -233,6 +234,8 @@ class BeamPage extends Page { LocalKey get key => super.key!; + final BeamPageStateNotifier? stateChangeNotifier; + @override Route createRoute(BuildContext context) { if (routeBuilder != null) { @@ -361,47 +364,46 @@ class BeamPageState { int get hashCode => isPinnacle.hashCode; } -/// Utility to inform [BeamPageState] to his [BeamPage]. -class BeamPageNotifier extends ValueListenable { - BeamPageNotifier( - this.value, { - required this.parentStackDebugLabel, - }) { - print('BeamPageNotifier.constructor() -- $_debugLabel'); - } +// class BeamPageNotifier extends ValueListenable { +// BeamPageNotifier( +// this.value, { +// required this.parentStackDebugLabel, +// }) { +// print('BeamPageNotifier.constructor() -- $_debugLabel'); +// } - final String parentStackDebugLabel; - final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); +// final String parentStackDebugLabel; +// final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); - final _listeners = {}; +// final _listeners = {}; - BeamPageState value; +// BeamPageState value; - String get fullDebugLabel => '$parentStackDebugLabel-$_debugLabel'; +// String get fullDebugLabel => '$parentStackDebugLabel-$_debugLabel'; - @override - void addListener(VoidCallback listener) { - _listeners.add(listener); - print( - 'BeamPageNotifier.addListener() -- $_debugLabel -- Count: ${_listeners.length}'); - } +// @override +// void addListener(VoidCallback listener) { +// _listeners.add(listener); +// print( +// 'BeamPageNotifier.addListener() -- $_debugLabel -- Count: ${_listeners.length}'); +// } - @override - void removeListener(VoidCallback listener) { - _listeners.remove(listener); - print( - 'BeamPageNotifier.removeListener() -- $_debugLabel -- Count: ${_listeners.length}'); - } +// @override +// void removeListener(VoidCallback listener) { +// _listeners.remove(listener); +// print( +// 'BeamPageNotifier.removeListener() -- $_debugLabel -- Count: ${_listeners.length}'); +// } - void notify() { - for (final listener in _listeners) { - listener(); - } +// void notify() { +// for (final listener in _listeners) { +// listener(); +// } - print( - 'BeamPageNotifier.notify() -- $_debugLabel -- Count: ${_listeners.length}'); - } -} +// print( +// 'BeamPageNotifier.notify() -- $_debugLabel -- Count: ${_listeners.length}'); +// } +// } /// Utility to get a [BeamPageNotifier]. /// @@ -409,20 +411,21 @@ class BeamPageNotifier extends ValueListenable { /// the page is created. // typedef BeamPageNotifierReference = BeamPageNotifier Function(LocalKey); // typedef BeamPageNotifierReference = BeamPageNotifier Function(); -class BeamPageNotifierReference { - BeamPageNotifierReference(); +// class BeamPageNotifierReference { +// BeamPageNotifierReference(); - BeamPageNotifier? _notifier; +// BeamPageNotifier? _notifier; - late final BeamPageNotifier Function() getNotifier; +// late final BeamPageNotifier Function() getNotifier; - BeamPageNotifier get notifier => _notifier ??= getNotifier(); -} +// BeamPageNotifier get notifier => _notifier ??= getNotifier(); +// } -class BeamPageStateChangeNotifier extends ValueListenable +/// Utility to inform [BeamPageState] to his [BeamPage]. +class BeamPageStateNotifier extends ValueListenable with ChangeNotifier { - BeamPageStateChangeNotifier(this.value); + BeamPageStateNotifier(); @override - BeamPageState value; + late BeamPageState value; } diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index d37feec..98cb909 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -474,7 +474,8 @@ class RoutesBeamStack extends BeamStack { BuildContext, BeamState, // BeamPageNotifier, - BeamPageNotifierReference, + // BeamPageNotifierReference, + // BeamPageStateNotifier, Object? data, )> routes; @@ -524,9 +525,10 @@ class RoutesBeamStack extends BeamStack { final pages = sortedRoutes.indexed.map((value) { final index = value.$1; final route = value.$2; - final notifierReference = BeamPageNotifierReference(); - final routeElement = - routes[route]!(context, state, notifierReference, data); + // final notifierReference = BeamPageNotifierReference(); + // final routeElement = + // routes[route]!(context, state, notifierReference, data); + final routeElement = routes[route]!(context, state, data); final page = routeElement is BeamPage ? routeElement : BeamPage( @@ -534,11 +536,17 @@ class RoutesBeamStack extends BeamStack { child: routeElement, ); print('Notifier exists: ${parent.pageNotifiers.containsKey(page.key)}'); - final notifier = parent.pageNotifiers[page.key] ??= BeamPageNotifier( - BeamPageState(isPinnacle: index == sortedRoutes.length - 1), - parentStackDebugLabel: debugLabel, - ); - notifierReference.getNotifier = () => notifier; + final stateChangeNotifier = page.stateChangeNotifier; + if (stateChangeNotifier != null) { + parent.pageNotifiers[page.key] = stateChangeNotifier; + stateChangeNotifier.value = + BeamPageState(isPinnacle: index == sortedRoutes.length - 1); + } + // final notifier = parent.pageNotifiers[page.key] ??= BeamPageNotifier( + // BeamPageState(isPinnacle: index == sortedRoutes.length - 1), + // parentStackDebugLabel: debugLabel, + // ); + // notifierReference.getNotifier = () => notifier; return page; }).toList(); diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index aee635a..d67805b 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -53,7 +53,7 @@ class BeamerDelegate extends RouterDelegate updateListenable?.addListener(_update); } - final Map pageNotifiers = {}; + final Map pageNotifiers = {}; bool _firstBuild = true; @@ -1042,20 +1042,20 @@ class BeamerDelegate extends RouterDelegate print('Notifying page: ${_currentPages[i].title} -- Is pinnacle: false'); pageNotifiers[_currentPages[i].key]! ..value = BeamPageState(isPinnacle: false) - ..notify(); + ..notifyListeners(); } // Pinnacle page print('Notifying page: ${_currentPages.last.title} -- Is pinnacle: true'); pageNotifiers[_currentPages.last.key]! ..value = BeamPageState(isPinnacle: true) - ..notify(); + ..notifyListeners(); } void _printCurrentPageNotifiers() { print('_printCurrentPageNotifiers()'); for (final entry in pageNotifiers.entries) { - print('LocalKey: ${entry.key}, Notifier: ${entry.value.fullDebugLabel}'); + print('LocalKey: ${entry.key}'); } } diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index e24bd27..16589c8 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -64,7 +64,8 @@ class RoutesStackBuilder { dynamic Function( BuildContext, BeamState, - BeamPageNotifierReference, + // BeamPageNotifierReference, + // BeamPageStateNotifier, Object?, )> routes; From e494ca6be979a9c0392ecbdcad718ad35a2b7559 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:32:54 +0200 Subject: [PATCH 12/27] snapshot --- package/lib/src/beam_page.dart | 57 ---------------------------- package/lib/src/beam_stack.dart | 31 ++++----------- package/lib/src/beamer_delegate.dart | 30 ++------------- package/lib/src/stack_builders.dart | 4 -- 4 files changed, 10 insertions(+), 112 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index 16b9f9b..b400536 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -364,63 +364,6 @@ class BeamPageState { int get hashCode => isPinnacle.hashCode; } -// class BeamPageNotifier extends ValueListenable { -// BeamPageNotifier( -// this.value, { -// required this.parentStackDebugLabel, -// }) { -// print('BeamPageNotifier.constructor() -- $_debugLabel'); -// } - -// final String parentStackDebugLabel; -// final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); - -// final _listeners = {}; - -// BeamPageState value; - -// String get fullDebugLabel => '$parentStackDebugLabel-$_debugLabel'; - -// @override -// void addListener(VoidCallback listener) { -// _listeners.add(listener); -// print( -// 'BeamPageNotifier.addListener() -- $_debugLabel -- Count: ${_listeners.length}'); -// } - -// @override -// void removeListener(VoidCallback listener) { -// _listeners.remove(listener); -// print( -// 'BeamPageNotifier.removeListener() -- $_debugLabel -- Count: ${_listeners.length}'); -// } - -// void notify() { -// for (final listener in _listeners) { -// listener(); -// } - -// print( -// 'BeamPageNotifier.notify() -- $_debugLabel -- Count: ${_listeners.length}'); -// } -// } - -/// Utility to get a [BeamPageNotifier]. -/// -/// Needed because [BeamPage] is const and the notifier is not known until -/// the page is created. -// typedef BeamPageNotifierReference = BeamPageNotifier Function(LocalKey); -// typedef BeamPageNotifierReference = BeamPageNotifier Function(); -// class BeamPageNotifierReference { -// BeamPageNotifierReference(); - -// BeamPageNotifier? _notifier; - -// late final BeamPageNotifier Function() getNotifier; - -// BeamPageNotifier get notifier => _notifier ??= getNotifier(); -// } - /// Utility to inform [BeamPageState] to his [BeamPage]. class BeamPageStateNotifier extends ValueListenable with ChangeNotifier { diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 98cb909..e27d789 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -88,18 +88,13 @@ abstract class BeamStack /// Creates a [BeamStack] with specified properties. /// /// All attributes can be null. - BeamStack( - this.debugLabel, [ + BeamStack([ RouteInformation? routeInformation, BeamParameters? beamParameters, ]) { create(routeInformation, beamParameters); } - // final debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); - - final String debugLabel; - late T _state; /// A state of this [BeamStack]. @@ -399,8 +394,7 @@ abstract class BeamStack class NotFound extends BeamStack { /// Creates a [NotFound] [BeamStack] with /// `RouteInformation(uri: Uri.parse(path)` as its state. - NotFound({String path = '/'}) - : super('NotFound', RouteInformation(uri: Uri.parse(path))); + NotFound({String path = '/'}) : super(RouteInformation(uri: Uri.parse(path))); @override List buildPages(BuildContext context, BeamState state) => []; @@ -413,8 +407,6 @@ class NotFound extends BeamStack { /// /// See [BeamerDelegate.currentBeamStack]. class EmptyBeamStack extends BeamStack { - EmptyBeamStack() : super('EmptyBeamStack'); - @override List buildPages(BuildContext context, BeamState state) => []; @@ -429,7 +421,7 @@ class GuardShowPage extends BeamStack { GuardShowPage( this.routeInformation, this.beamPage, - ) : super('GuardShowPage', routeInformation); + ) : super(routeInformation); /// [RouteInformation] to show in URL final RouteInformation routeInformation; @@ -454,16 +446,13 @@ class RoutesBeamStack extends BeamStack { /// [routeInformation] and [routes] are required. RoutesBeamStack({ required this.parent, - required String debugLabel, required String creationReason, required RouteInformation routeInformation, Object? data, BeamParameters? beamParameters, required this.routes, this.navBuilder, - }) : super(debugLabel, routeInformation, beamParameters) { - // print('RoutesBeamStack.constructor() -- $debugLabel -- $creationReason'); - } + }) : super(routeInformation, beamParameters); final BeamerDelegate parent; @@ -525,9 +514,6 @@ class RoutesBeamStack extends BeamStack { final pages = sortedRoutes.indexed.map((value) { final index = value.$1; final route = value.$2; - // final notifierReference = BeamPageNotifierReference(); - // final routeElement = - // routes[route]!(context, state, notifierReference, data); final routeElement = routes[route]!(context, state, data); final page = routeElement is BeamPage ? routeElement @@ -535,18 +521,15 @@ class RoutesBeamStack extends BeamStack { key: ValueKey(filteredRoutes[route]), child: routeElement, ); - print('Notifier exists: ${parent.pageNotifiers.containsKey(page.key)}'); + + // Initializing page state final stateChangeNotifier = page.stateChangeNotifier; if (stateChangeNotifier != null) { parent.pageNotifiers[page.key] = stateChangeNotifier; stateChangeNotifier.value = BeamPageState(isPinnacle: index == sortedRoutes.length - 1); } - // final notifier = parent.pageNotifiers[page.key] ??= BeamPageNotifier( - // BeamPageState(isPinnacle: index == sortedRoutes.length - 1), - // parentStackDebugLabel: debugLabel, - // ); - // notifierReference.getNotifier = () => notifier; + return page; }).toList(); diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index d67805b..ebf6531 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -17,7 +17,6 @@ class BeamerDelegate extends RouterDelegate /// [stackBuilder] is required to process the incoming navigation request. BeamerDelegate({ required this.stackBuilder, - required this.debugLabel, this.initialPath = '/', this.routeListener, this.buildListener, @@ -42,8 +41,6 @@ class BeamerDelegate extends RouterDelegate this.updateParent = true, this.clearBeamingHistoryOn = const {}, }) { - // print('BeamerDelegate.constructor() -- $debugLabel'); - _currentBeamParameters = BeamParameters( transitionDelegate: transitionDelegate, ); @@ -67,10 +64,6 @@ class BeamerDelegate extends RouterDelegate final Set _children = {}; - final String debugLabel; - - // final _debugLabel = DateTime.now().millisecondsSinceEpoch.toString(); - /// Takes priority over all other siblings, /// i.e. sets itself as active and all other siblings as inactive. void takePriority() { @@ -798,8 +791,6 @@ class BeamerDelegate extends RouterDelegate buildListener?.call(context, this); - _printCurrentPageNotifiers(); - // Notifying pages if (!isFirstBuild) { _notifyCurrentPages(); @@ -1006,10 +997,6 @@ class BeamerDelegate extends RouterDelegate void _setCurrentPages(BuildContext context) { final currentBeamStack = this.currentBeamStack; - if (currentBeamStack is RoutesBeamStack) { - print('_setCurrentPages() -- ${currentBeamStack.debugLabel}'); - } - if (currentBeamStack is NotFound) { _currentPages = [notFoundPage]; pageNotifiers.clear(); @@ -1017,17 +1004,15 @@ class BeamerDelegate extends RouterDelegate _currentPages = _currentBeamParameters.stacked ? currentBeamStack.buildPages(context, currentBeamStack.state) : [currentBeamStack.buildPages(context, currentBeamStack.state).last]; - _purgePageNotifiers(); + _purgePageStateNotifiers(); } } - /// Purging outdated page notifiers. - void _purgePageNotifiers() { + /// Purges outdated page state notifiers. + void _purgePageStateNotifiers() { final currentPagesKeys = _currentPages.map((page) => page.key); - print('_purgePageNotifiers() -- 1 -- ${pageNotifiers.length}'); pageNotifiers .removeWhere((key, pageNotifier) => !currentPagesKeys.contains(key)); - print('_purgePageNotifiers() -- 2 -- ${pageNotifiers.length}'); } void _notifyCurrentPages() { @@ -1039,26 +1024,17 @@ class BeamerDelegate extends RouterDelegate // Hidden pages for (int i = 0; i < _currentPages.length - 1; i++) { - print('Notifying page: ${_currentPages[i].title} -- Is pinnacle: false'); pageNotifiers[_currentPages[i].key]! ..value = BeamPageState(isPinnacle: false) ..notifyListeners(); } // Pinnacle page - print('Notifying page: ${_currentPages.last.title} -- Is pinnacle: true'); pageNotifiers[_currentPages.last.key]! ..value = BeamPageState(isPinnacle: true) ..notifyListeners(); } - void _printCurrentPageNotifiers() { - print('_printCurrentPageNotifiers()'); - for (final entry in pageNotifiers.entries) { - print('LocalKey: ${entry.key}'); - } - } - void _setBrowserTitle(BuildContext context) { if (active && setBrowserTabTitle) { final String title = _currentPages.last.title ?? diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 16589c8..939e9e4 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -49,13 +49,10 @@ class RoutesStackBuilder { /// /// [routes] are required to build pages from. RoutesStackBuilder({ - required this.debugLabel, required this.routes, this.builder, }); - final String debugLabel; - /// List of all routes this builder handles. /// /// isPinnacle is true when the route is the outer/last in the stack. @@ -85,7 +82,6 @@ class RoutesStackBuilder { if (matched.isNotEmpty) { return RoutesBeamStack( parent: parent, - debugLabel: '$debugLabel -- ${DateTime.now().millisecondsSinceEpoch}', creationReason: creationReason, routeInformation: routeInformation, routes: routes, From acb11ee729c6504a58a0655bc8645c07282278c7 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:36:33 +0200 Subject: [PATCH 13/27] snapshot --- package/lib/src/beam_stack.dart | 1 - package/lib/src/stack_builders.dart | 2 -- 2 files changed, 3 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index e27d789..b9d7971 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -446,7 +446,6 @@ class RoutesBeamStack extends BeamStack { /// [routeInformation] and [routes] are required. RoutesBeamStack({ required this.parent, - required String creationReason, required RouteInformation routeInformation, Object? data, BeamParameters? beamParameters, diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 939e9e4..b6900db 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -76,13 +76,11 @@ class RoutesStackBuilder { BeamerDelegate parent, RouteInformation routeInformation, BeamParameters? beamParameters, - String creationReason, ) { final matched = RoutesBeamStack.chooseRoutes(routeInformation, routes.keys); if (matched.isNotEmpty) { return RoutesBeamStack( parent: parent, - creationReason: creationReason, routeInformation: routeInformation, routes: routes, navBuilder: builder, From 058474e0e4b5537a1c2e2fdf97bebdb171aa0ecc Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:37:29 +0200 Subject: [PATCH 14/27] snapshot --- package/lib/src/beam_stack.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index b9d7971..774dcd6 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -461,9 +461,6 @@ class RoutesBeamStack extends BeamStack { dynamic Function( BuildContext, BeamState, - // BeamPageNotifier, - // BeamPageNotifierReference, - // BeamPageStateNotifier, Object? data, )> routes; From 19737bc9993d7ddacc87e10a449126674fc07452 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:37:57 +0200 Subject: [PATCH 15/27] snapshot --- package/lib/src/beam_stack.dart | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 774dcd6..be9b599 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -456,13 +456,8 @@ class RoutesBeamStack extends BeamStack { final BeamerDelegate parent; /// Map of all routes this stack handles. - final Map< - Pattern, - dynamic Function( - BuildContext, - BeamState, - Object? data, - )> routes; + final Map + routes; /// A wrapper used as [BeamStack.builder]. final Widget Function(BuildContext context, Widget navigator)? navBuilder; From f638d098e3b71bb57933adbe8270a3d1a862544e Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:39:21 +0200 Subject: [PATCH 16/27] snapshot --- package/lib/src/beam_stack.dart | 9 --------- package/lib/src/beamer_delegate.dart | 5 +++++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index be9b599..86bbef0 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -462,15 +462,6 @@ class RoutesBeamStack extends BeamStack { /// A wrapper used as [BeamStack.builder]. final Widget Function(BuildContext context, Widget navigator)? navBuilder; - /// They are regenerated on [buildPages], - /// so they are only valid for one build cycle. - /// - /// The reason for not making them persistent across build cycles is that - /// we can't know the [BeamPage.key] before creating them (see [buildPages]). - // final Map _pageNotifiers = {}; - // final List _pageNotifiers = []; - // final Map _pageNotifiers = {}; - @override Widget builder(BuildContext context, Widget navigator) { return navBuilder?.call(context, navigator) ?? navigator; diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index ebf6531..bc71bc1 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -50,6 +50,11 @@ class BeamerDelegate extends RouterDelegate updateListenable?.addListener(_update); } + /// They are regenerated on [buildPages], + /// so they are only valid for one build cycle. + /// + /// The reason for not making them persistent across build cycles is that + /// we can't know the [BeamPage.key] before creating them (see [buildPages]). final Map pageNotifiers = {}; bool _firstBuild = true; From 46e0926ae67e4aa63aa3a97fd1f8cef4355a0ec7 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:41:18 +0200 Subject: [PATCH 17/27] snapshot --- package/lib/src/beam_stack.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 86bbef0..07f1baa 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -507,9 +507,8 @@ class RoutesBeamStack extends BeamStack { // Initializing page state final stateChangeNotifier = page.stateChangeNotifier; if (stateChangeNotifier != null) { - parent.pageNotifiers[page.key] = stateChangeNotifier; - stateChangeNotifier.value = - BeamPageState(isPinnacle: index == sortedRoutes.length - 1); + parent.pageNotifiers[page.key] = stateChangeNotifier + ..value = BeamPageState(isPinnacle: index == sortedRoutes.length - 1); } return page; From e074f8201699c1afced1601bd2182c8931811c67 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:42:40 +0200 Subject: [PATCH 18/27] snapshot --- package/lib/src/beamer_delegate.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index bc71bc1..ebf6531 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -50,11 +50,6 @@ class BeamerDelegate extends RouterDelegate updateListenable?.addListener(_update); } - /// They are regenerated on [buildPages], - /// so they are only valid for one build cycle. - /// - /// The reason for not making them persistent across build cycles is that - /// we can't know the [BeamPage.key] before creating them (see [buildPages]). final Map pageNotifiers = {}; bool _firstBuild = true; From db9979c694e4181ecf58338046eefe5341deba85 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:43:48 +0200 Subject: [PATCH 19/27] snapshot --- package/lib/src/beamer_delegate.dart | 4 ---- package/lib/src/stack_builders.dart | 1 - 2 files changed, 5 deletions(-) diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index ebf6531..944700e 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -431,7 +431,6 @@ class BeamerDelegate extends RouterDelegate this, this.configuration.copyWith(), _currentBeamParameters, - 'update', ); } @@ -988,7 +987,6 @@ class BeamerDelegate extends RouterDelegate this, RouteInformation(uri: Uri.parse(notFoundRedirectNamed!)), _currentBeamParameters.copyWith(), - '_handleNotFoundRedirect', ); } _updateFromBeamStackCandidate(); @@ -1099,7 +1097,6 @@ class BeamerDelegate extends RouterDelegate this, parentConfiguration, _currentBeamParameters, - '_initializeChild', ); } @@ -1134,7 +1131,6 @@ class BeamerDelegate extends RouterDelegate this, parentConfiguration, _currentBeamParameters, - '_updateFromParent', ); if (beamStack is! NotFound) { diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index b6900db..94092b7 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -8,7 +8,6 @@ typedef StackBuilder = BeamStack Function( BeamerDelegate parent, RouteInformation, BeamParameters?, - String creationReason, ); /// A pre-made builder to be used for [BeamerDelegate.stackBuilder]. From 34ab0f2a71be2b5851a742e8ca0b9762b51dee04 Mon Sep 17 00:00:00 2001 From: busslina Date: Thu, 19 Sep 2024 10:47:47 +0200 Subject: [PATCH 20/27] snapshot --- package/lib/src/beamer_delegate.dart | 8 ++------ package/lib/src/stack_builders.dart | 18 ++++-------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 944700e..a7b634c 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -785,7 +785,6 @@ class BeamerDelegate extends RouterDelegate final navigator = Builder( builder: (context) { _setCurrentPages(context); - _setBrowserTitle(context); buildListener?.call(context, this); @@ -1093,11 +1092,8 @@ class BeamerDelegate extends RouterDelegate void _initializeChild() { final parentConfiguration = _parent!.configuration.copyWith(); if (initializeFromParent) { - _beamStackCandidate = stackBuilder( - this, - parentConfiguration, - _currentBeamParameters, - ); + _beamStackCandidate = + stackBuilder(this, parentConfiguration, _currentBeamParameters); } // If this couldn't handle parents configuration, diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 94092b7..845265d 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -47,30 +47,20 @@ class RoutesStackBuilder { /// Creates a [RoutesStackBuilder] with specified properties. /// /// [routes] are required to build pages from. - RoutesStackBuilder({ - required this.routes, - this.builder, - }); + RoutesStackBuilder({required this.routes, this.builder}); /// List of all routes this builder handles. /// /// isPinnacle is true when the route is the outer/last in the stack. - final Map< - Pattern, - dynamic Function( - BuildContext, - BeamState, - // BeamPageNotifierReference, - // BeamPageStateNotifier, - Object?, - )> routes; + final Map routes; /// Used as a [BeamStack.builder]. final Widget Function(BuildContext context, Widget navigator)? builder; /// Makes this callable as [StackBuilder]. /// - /// Returns [RoutesBeamStack] configured with chosen routes from [routes] or [NotFound]. + /// Returns [RoutesBeamStack] configured with chosen routes from [routes] + /// or [NotFound]. BeamStack call( BeamerDelegate parent, RouteInformation routeInformation, From 753980b5935fea70a05b1301fc3687aa00e60c7f Mon Sep 17 00:00:00 2001 From: Vicente Date: Thu, 19 Sep 2024 20:07:52 +0200 Subject: [PATCH 21/27] snapshot --- package/lib/src/stack_builders.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/package/lib/src/stack_builders.dart b/package/lib/src/stack_builders.dart index 845265d..0f513f6 100644 --- a/package/lib/src/stack_builders.dart +++ b/package/lib/src/stack_builders.dart @@ -50,8 +50,6 @@ class RoutesStackBuilder { RoutesStackBuilder({required this.routes, this.builder}); /// List of all routes this builder handles. - /// - /// isPinnacle is true when the route is the outer/last in the stack. final Map routes; /// Used as a [BeamStack.builder]. From 90e20651cb92c5f4604bf0421b9a25b8e30d882b Mon Sep 17 00:00:00 2001 From: busslina Date: Fri, 20 Sep 2024 09:11:55 +0200 Subject: [PATCH 22/27] snapshot --- package/lib/src/beam_page.dart | 21 ++++++++++++++++++++- package/lib/src/beam_stack.dart | 26 +++++++++++++------------- package/lib/src/beamer_delegate.dart | 15 ++++++++++++++- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index b400536..32e0861 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -37,7 +37,7 @@ enum BeamPageType { } /// A wrapper for screens in a navigation stack. -class BeamPage extends Page { +class BeamPage extends Page { /// Creates a [BeamPage] with specified properties. /// /// [child] is required and typically represents a screen of the app. @@ -56,6 +56,7 @@ class BeamPage extends Page { this.opaque = true, this.keepQueryOnPop = false, this.stateChangeNotifier, + this.info, }) : super(key: key, name: name); /// A [BeamPage] to be the default for [BeamerDelegate.notFoundPage]. @@ -236,6 +237,8 @@ class BeamPage extends Page { final BeamPageStateNotifier? stateChangeNotifier; + final T? info; + @override Route createRoute(BuildContext context) { if (routeBuilder != null) { @@ -372,3 +375,19 @@ class BeamPageStateNotifier extends ValueListenable @override late BeamPageState value; } + +/// Represents specific page related information. +/// +/// Not represents state. +mixin class BeamPageInfo { + const BeamPageInfo(); +} + +/// Utility to inform the current [BeamPageInfo] of [BeamerDelegate]. +class BeamPageInfoNotifier extends ValueListenable + with ChangeNotifier { + BeamPageInfoNotifier(); + + @override + late T? value; +} diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index 07f1baa..a6337a6 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -83,8 +83,8 @@ class HistoryElement { /// * keeping a [state] that provides the link between the first 2 /// /// Extend this class to define your stacks to which you can then beam to. -abstract class BeamStack - extends ChangeNotifier { +abstract class BeamStack extends ChangeNotifier { /// Creates a [BeamStack] with specified properties. /// /// All attributes can be null. @@ -367,7 +367,7 @@ abstract class BeamStack /// /// [context] can be useful while building the pages. /// It will also contain anything injected via [builder]. - List buildPages(BuildContext context, T state); + List> buildPages(BuildContext context, T state); /// Guards that will be executing [BeamGuard.check] when this gets beamed to. /// @@ -391,7 +391,7 @@ abstract class BeamStack } /// Default stack to choose if requested URI doesn't parse to any stack. -class NotFound extends BeamStack { +class NotFound extends BeamStack { /// Creates a [NotFound] [BeamStack] with /// `RouteInformation(uri: Uri.parse(path)` as its state. NotFound({String path = '/'}) : super(RouteInformation(uri: Uri.parse(path))); @@ -406,7 +406,7 @@ class NotFound extends BeamStack { /// Empty stack used to initialize a non-nullable BeamStack variable. /// /// See [BeamerDelegate.currentBeamStack]. -class EmptyBeamStack extends BeamStack { +class EmptyBeamStack extends BeamStack { @override List buildPages(BuildContext context, BeamState state) => []; @@ -415,7 +415,7 @@ class EmptyBeamStack extends BeamStack { } /// A specific single-page [BeamStack] for [BeamGuard.showPage] -class GuardShowPage extends BeamStack { +class GuardShowPage extends BeamStack { /// Creates a [GuardShowPage] [BeamStack] with /// `RouteInformation(uri: Uri.parse(path)` as its state. GuardShowPage( @@ -440,7 +440,7 @@ class GuardShowPage extends BeamStack { /// A beam stack for [RoutesStackBuilder], but can be used freely. /// /// Useful when needing a simple beam stack with a single or few pages. -class RoutesBeamStack extends BeamStack { +class RoutesBeamStack extends BeamStack { /// Creates a [RoutesBeamStack] with specified properties. /// /// [routeInformation] and [routes] are required. @@ -453,7 +453,7 @@ class RoutesBeamStack extends BeamStack { this.navBuilder, }) : super(routeInformation, beamParameters); - final BeamerDelegate parent; + final BeamerDelegate parent; /// Map of all routes this stack handles. final Map @@ -487,19 +487,19 @@ class RoutesBeamStack extends BeamStack { List get pathPatterns => routes.keys.toList(); @override - List buildPages(BuildContext context, BeamState state) { + List> buildPages(BuildContext context, BeamState state) { final filteredRoutes = chooseRoutes(state.routeInformation, routes.keys); final routeBuilders = Map.of(routes) ..removeWhere((key, value) => !filteredRoutes.containsKey(key)); final sortedRoutes = routeBuilders.keys.toList() ..sort((a, b) => _compareKeys(a, b)); - final pages = sortedRoutes.indexed.map((value) { + final pages = sortedRoutes.indexed.map>((value) { final index = value.$1; final route = value.$2; final routeElement = routes[route]!(context, state, data); - final page = routeElement is BeamPage - ? routeElement - : BeamPage( + final BeamPage page = routeElement is BeamPage + ? routeElement as BeamPage + : BeamPage( key: ValueKey(filteredRoutes[route]), child: routeElement, ); diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index a7b634c..7823756 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -10,7 +10,8 @@ import 'package:flutter/services.dart'; /// A delegate that is used by the [Router] to build the [Navigator]. /// /// This is "the beamer", the one that does the actual beaming. -class BeamerDelegate extends RouterDelegate +class BeamerDelegate + extends RouterDelegate with ChangeNotifier, PopNavigatorRouterDelegateMixin { /// Creates a [BeamerDelegate] with specified properties. /// @@ -356,6 +357,12 @@ class BeamerDelegate extends RouterDelegate /// to avoid setting URL when the guards have not been run yet. bool _initialConfigurationReady = false; + final pinnaclePageInfoNotifier = BeamPageInfoNotifier(); + + T? _pinnaclePageInfo; + + T? get pinnaclePageInfo => _pinnaclePageInfo; + /// Main method to update the [configuration] of this delegate and its /// [currentBeamStack]. /// @@ -997,12 +1004,18 @@ class BeamerDelegate extends RouterDelegate if (currentBeamStack is NotFound) { _currentPages = [notFoundPage]; pageNotifiers.clear(); + _pinnaclePageInfo = null; } else { _currentPages = _currentBeamParameters.stacked ? currentBeamStack.buildPages(context, currentBeamStack.state) : [currentBeamStack.buildPages(context, currentBeamStack.state).last]; _purgePageStateNotifiers(); + _pinnaclePageInfo = _currentPages.lastOrNull?.info as T?; } + + pinnaclePageInfoNotifier + ..value = _pinnaclePageInfo + ..notifyListeners(); } /// Purges outdated page state notifiers. From 13693f6f9df658d8e0c997727e5f0230403d854f Mon Sep 17 00:00:00 2001 From: Vicente Date: Fri, 20 Sep 2024 21:06:40 +0200 Subject: [PATCH 23/27] snapshot --- package/lib/src/beam_page.dart | 9 +++++++ package/lib/src/beam_stack.dart | 7 +++-- package/lib/src/beamer_delegate.dart | 38 +++++++++++++--------------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index 32e0861..4702a04 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -374,6 +374,15 @@ class BeamPageStateNotifier extends ValueListenable @override late BeamPageState value; + + @override + void notifyListeners({bool ignore = false}) { + if (ignore) { + return; + } + + super.notifyListeners(); + } } /// Represents specific page related information. diff --git a/package/lib/src/beam_stack.dart b/package/lib/src/beam_stack.dart index a6337a6..2999da3 100644 --- a/package/lib/src/beam_stack.dart +++ b/package/lib/src/beam_stack.dart @@ -494,7 +494,7 @@ class RoutesBeamStack extends BeamStack { final sortedRoutes = routeBuilders.keys.toList() ..sort((a, b) => _compareKeys(a, b)); final pages = sortedRoutes.indexed.map>((value) { - final index = value.$1; + // final index = value.$1; final route = value.$2; final routeElement = routes[route]!(context, state, data); final BeamPage page = routeElement is BeamPage @@ -504,11 +504,10 @@ class RoutesBeamStack extends BeamStack { child: routeElement, ); - // Initializing page state + // Storing page state notifier final stateChangeNotifier = page.stateChangeNotifier; if (stateChangeNotifier != null) { - parent.pageNotifiers[page.key] = stateChangeNotifier - ..value = BeamPageState(isPinnacle: index == sortedRoutes.length - 1); + parent.pageStateNotifiers[page.key] = stateChangeNotifier; } return page; diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 7823756..0682a83 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -51,7 +51,7 @@ class BeamerDelegate updateListenable?.addListener(_update); } - final Map pageNotifiers = {}; + final Map pageStateNotifiers = {}; bool _firstBuild = true; @@ -359,9 +359,9 @@ class BeamerDelegate final pinnaclePageInfoNotifier = BeamPageInfoNotifier(); - T? _pinnaclePageInfo; + // T? _pinnaclePageInfo; - T? get pinnaclePageInfo => _pinnaclePageInfo; + // T? get pinnaclePageInfo => _pinnaclePageInfo; /// Main method to update the [configuration] of this delegate and its /// [currentBeamStack]. @@ -796,10 +796,11 @@ class BeamerDelegate buildListener?.call(context, this); - // Notifying pages - if (!isFirstBuild) { - _notifyCurrentPages(); - } + // Notifying pinnacle page info + pinnaclePageInfoNotifier.notifyListeners(); + + // Notifying pages states + _notifyCurrentPagesStates(isFirstBuild: isFirstBuild); return Navigator( key: navigatorKey, @@ -1003,29 +1004,26 @@ class BeamerDelegate if (currentBeamStack is NotFound) { _currentPages = [notFoundPage]; - pageNotifiers.clear(); - _pinnaclePageInfo = null; + pageStateNotifiers.clear(); + pinnaclePageInfoNotifier.value = null; } else { _currentPages = _currentBeamParameters.stacked ? currentBeamStack.buildPages(context, currentBeamStack.state) : [currentBeamStack.buildPages(context, currentBeamStack.state).last]; _purgePageStateNotifiers(); - _pinnaclePageInfo = _currentPages.lastOrNull?.info as T?; + pinnaclePageInfoNotifier.value = _currentPages.lastOrNull?.info as T?; } - - pinnaclePageInfoNotifier - ..value = _pinnaclePageInfo - ..notifyListeners(); } /// Purges outdated page state notifiers. void _purgePageStateNotifiers() { final currentPagesKeys = _currentPages.map((page) => page.key); - pageNotifiers + pageStateNotifiers .removeWhere((key, pageNotifier) => !currentPagesKeys.contains(key)); } - void _notifyCurrentPages() { + /// Notifies current pages [BeamPageState]'s. + void _notifyCurrentPagesStates({required bool isFirstBuild}) { final stack = currentBeamStack; if (stack is! RoutesBeamStack) { @@ -1034,15 +1032,15 @@ class BeamerDelegate // Hidden pages for (int i = 0; i < _currentPages.length - 1; i++) { - pageNotifiers[_currentPages[i].key]! + pageStateNotifiers[_currentPages[i].key]! ..value = BeamPageState(isPinnacle: false) - ..notifyListeners(); + ..notifyListeners(ignore: isFirstBuild); } // Pinnacle page - pageNotifiers[_currentPages.last.key]! + pageStateNotifiers[_currentPages.last.key]! ..value = BeamPageState(isPinnacle: true) - ..notifyListeners(); + ..notifyListeners(ignore: isFirstBuild); } void _setBrowserTitle(BuildContext context) { From ba8802382fea5e6d4f4e8991fa18656831bff1f3 Mon Sep 17 00:00:00 2001 From: Vicente Date: Fri, 20 Sep 2024 21:06:51 +0200 Subject: [PATCH 24/27] snapshot --- package/lib/src/beamer_delegate.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 0682a83..95aa504 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -359,10 +359,6 @@ class BeamerDelegate final pinnaclePageInfoNotifier = BeamPageInfoNotifier(); - // T? _pinnaclePageInfo; - - // T? get pinnaclePageInfo => _pinnaclePageInfo; - /// Main method to update the [configuration] of this delegate and its /// [currentBeamStack]. /// From 017eb2c3498d6bdac64e30968324c63b5ac94926 Mon Sep 17 00:00:00 2001 From: Vicente Date: Tue, 24 Sep 2024 17:41:16 +0200 Subject: [PATCH 25/27] snapshot --- package/lib/src/beam_page.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/package/lib/src/beam_page.dart b/package/lib/src/beam_page.dart index 4702a04..fdf91ca 100644 --- a/package/lib/src/beam_page.dart +++ b/package/lib/src/beam_page.dart @@ -388,9 +388,7 @@ class BeamPageStateNotifier extends ValueListenable /// Represents specific page related information. /// /// Not represents state. -mixin class BeamPageInfo { - const BeamPageInfo(); -} +mixin BeamPageInfo {} /// Utility to inform the current [BeamPageInfo] of [BeamerDelegate]. class BeamPageInfoNotifier extends ValueListenable From 6f6d679619debfdaa514ff6a6d6285d1bbc38b91 Mon Sep 17 00:00:00 2001 From: Vicente Date: Wed, 25 Sep 2024 17:47:10 +0200 Subject: [PATCH 26/27] snapshot --- package/lib/src/beamer_delegate.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 95aa504..13fe25a 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -1028,15 +1028,21 @@ class BeamerDelegate // Hidden pages for (int i = 0; i < _currentPages.length - 1; i++) { - pageStateNotifiers[_currentPages[i].key]! - ..value = BeamPageState(isPinnacle: false) - ..notifyListeners(ignore: isFirstBuild); + final notifier = pageStateNotifiers[_currentPages[i].key]; + if (notifier != null) { + notifier + ..value = BeamPageState(isPinnacle: false) + ..notifyListeners(ignore: isFirstBuild); + } } // Pinnacle page - pageStateNotifiers[_currentPages.last.key]! - ..value = BeamPageState(isPinnacle: true) - ..notifyListeners(ignore: isFirstBuild); + final notifier = pageStateNotifiers[_currentPages.last.key]; + if (notifier != null) { + notifier + ..value = BeamPageState(isPinnacle: true) + ..notifyListeners(ignore: isFirstBuild); + } } void _setBrowserTitle(BuildContext context) { From c5bc8b3bc582431f457d6863909767fa80774aa1 Mon Sep 17 00:00:00 2001 From: Vicente Date: Wed, 25 Sep 2024 17:50:26 +0200 Subject: [PATCH 27/27] snapshot --- package/lib/src/beamer_delegate.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package/lib/src/beamer_delegate.dart b/package/lib/src/beamer_delegate.dart index 13fe25a..9459785 100644 --- a/package/lib/src/beamer_delegate.dart +++ b/package/lib/src/beamer_delegate.dart @@ -17,6 +17,7 @@ class BeamerDelegate /// /// [stackBuilder] is required to process the incoming navigation request. BeamerDelegate({ + required this.debugLabel, required this.stackBuilder, this.initialPath = '/', this.routeListener, @@ -51,6 +52,8 @@ class BeamerDelegate updateListenable?.addListener(_update); } + final String debugLabel; + final Map pageStateNotifiers = {}; bool _firstBuild = true;