diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ad756a..992947f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.17.0 + +- feat: support redirect by NavigatorPushBeginHandle +- feat: support popResult by NavigatorPushEndHandle + ## 4.16.3 - fix: try to fix NavigatorPageView RangeError diff --git a/lib/src/navigator/navigator_types.dart b/lib/src/navigator/navigator_types.dart index 162b3a1..b00cf6e 100644 --- a/lib/src/navigator/navigator_types.dart +++ b/lib/src/navigator/navigator_types.dart @@ -21,6 +21,8 @@ // ignore_for_file: avoid_positional_boolean_parameters +import 'dart:async'; + import 'package:flutter/widgets.dart'; import 'navigator_route.dart'; @@ -65,10 +67,23 @@ typedef NavigatorRoutePushHandle = Future bool animated, }); -/// Signature of push begin/return handler with url. -typedef NavigatorPushHandle = Future Function( +/// Signature of push begin handler with url. +/// +/// return a new url for redirect. +/// +typedef NavigatorPushBeginHandle = Future Function( + String url, { + TParams? params, + String? fromURL, + String? innerURL, +}); + +/// Signature of push end handler. +/// +typedef NavigatorPushEndHandle = Future Function( String url, { TParams? params, String? fromURL, String? innerURL, + TPopParams? popResult, }); diff --git a/lib/src/navigator/thrio_navigator.dart b/lib/src/navigator/thrio_navigator.dart index 9cf4156..916e06d 100644 --- a/lib/src/navigator/thrio_navigator.dart +++ b/lib/src/navigator/thrio_navigator.dart @@ -32,13 +32,14 @@ import 'thrio_navigator_implement.dart'; abstract class ThrioNavigator { /// Register a handle called before push. /// - static VoidCallback registerPushBeginHandle(NavigatorPushHandle handle) => + static VoidCallback registerPushBeginHandle( + NavigatorPushBeginHandle handle) => ThrioNavigatorImplement.shared().registerPushBeginHandle(handle); /// Register a handle called before the push return. /// - static VoidCallback registerPushReturnHandle(NavigatorPushHandle handle) => - ThrioNavigatorImplement.shared().registerPushReturnHandle(handle); + static VoidCallback registerPushEndHandle(NavigatorPushEndHandle handle) => + ThrioNavigatorImplement.shared().registerPushEndHandle(handle); /// Push the page onto the navigation stack. /// diff --git a/lib/src/navigator/thrio_navigator_implement.dart b/lib/src/navigator/thrio_navigator_implement.dart index 9480d14..aaccace 100644 --- a/lib/src/navigator/thrio_navigator_implement.dart +++ b/lib/src/navigator/thrio_navigator_implement.dart @@ -32,7 +32,7 @@ import '../extension/thrio_uri_string.dart'; import '../module/module_anchor.dart'; import '../module/module_types.dart'; import '../module/thrio_module.dart'; -import '../registry/registry_set.dart'; +import '../registry/registry_order_set.dart'; import 'navigator_dialog_route.dart'; import 'navigator_material_app.dart'; import 'navigator_observer_manager.dart'; @@ -111,9 +111,9 @@ class ThrioNavigatorImplement { NavigatorWidgetState? get navigatorState => _stateKey.currentState; - final _pushBeginHandlers = RegistrySet(); + final _pushBeginHandlers = RegistryOrderSet(); - final _pushReturnHandlers = RegistrySet(); + final _pushEndHandlers = RegistryOrderSet(); final poppedResults = {}; @@ -146,11 +146,11 @@ class ThrioNavigatorImplement { _channel.invokeMethod('ready'); } - VoidCallback registerPushBeginHandle(NavigatorPushHandle handle) => + VoidCallback registerPushBeginHandle(NavigatorPushBeginHandle handle) => _pushBeginHandlers.registry(handle); - VoidCallback registerPushReturnHandle(NavigatorPushHandle handle) => - _pushReturnHandlers.registry(handle); + VoidCallback registerPushEndHandle(NavigatorPushEndHandle handle) => + _pushEndHandlers.registry(handle); Future push({ required String url, @@ -160,7 +160,7 @@ class ThrioNavigatorImplement { String? fromURL, String? innerURL, }) async { - await _onPushBeginHandle( + final newURL = await _onPushBeginHandle( url: url, params: params, fromURL: fromURL, @@ -170,7 +170,7 @@ class ThrioNavigatorImplement { final completer = Completer(); final handled = await _pushToHandler( - url: url, + url: newURL, params: params, animated: animated, completer: completer, @@ -182,7 +182,7 @@ class ThrioNavigatorImplement { Future pushFuture() { final resultCompleter = Completer(); _pushToNative( - url: url, + url: newURL, params: params, animated: animated, completer: completer, @@ -201,25 +201,40 @@ class ThrioNavigatorImplement { return completer.future; } - Future _onPushBeginHandle({ + Future _onPushBeginHandle({ required String url, TParams? params, String? fromURL, String? innerURL, }) async { - for (final handle in _pushBeginHandlers) { - await handle(url, params: params, fromURL: fromURL, innerURL: innerURL); + final reversed = _pushBeginHandlers.reversed; + var newURL = url; + for (final handle in reversed) { + final ret = await handle(url, + params: params, fromURL: fromURL, innerURL: innerURL); + if (ret != null) { + newURL = ret; + } } + return newURL; } - Future _onPushReturnHandle({ + Future _onPushReturnHandle({ required String url, TParams? params, String? fromURL, String? innerURL, + TPopParams? popResult, }) async { - for (final handle in _pushReturnHandlers) { - await handle(url, params: params, fromURL: fromURL, innerURL: innerURL); + final reversed = _pushEndHandlers.reversed; + for (final handle in reversed) { + await handle( + url, + params: params, + fromURL: fromURL, + innerURL: innerURL, + popResult: popResult, + ); } } @@ -719,6 +734,7 @@ class ThrioNavigatorImplement { params: params, fromURL: fromURL, innerURL: innerURL, + popResult: value, ); })); diff --git a/lib/src/registry/registry_order_set.dart b/lib/src/registry/registry_order_set.dart new file mode 100644 index 0000000..d6999ba --- /dev/null +++ b/lib/src/registry/registry_order_set.dart @@ -0,0 +1,53 @@ +// The MIT License (MIT) +// +// Copyright (c) 2024 foxsofter +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +import 'dart:collection'; +import 'package:flutter/foundation.dart'; + +class RegistryOrderSet with IterableMixin { + final List _sets = []; + + VoidCallback registry(T value) { + assert(value != null, 'value must not be null.'); + _sets + ..remove(value) + ..add(value); + return () { + _sets.remove(value); + }; + } + + VoidCallback registryAll(Set values) { + assert(values.isNotEmpty, 'values must not be null or empty'); + values.forEach(_sets.remove); + _sets.addAll(values); + return () { + values.forEach(_sets.remove); + }; + } + + void clear() => _sets.clear(); + + @override + Iterator get iterator => _sets.iterator; + + Iterable get reversed => _sets.reversed; +} diff --git a/lib/src/registry/registry_set.dart b/lib/src/registry/registry_set.dart index be76b50..f0348c3 100644 --- a/lib/src/registry/registry_set.dart +++ b/lib/src/registry/registry_set.dart @@ -22,7 +22,6 @@ import 'dart:collection'; import 'package:flutter/foundation.dart'; -// ignore: prefer_mixin class RegistrySet with IterableMixin { final Set _sets = {}; diff --git a/pubspec.yaml b/pubspec.yaml index f938785..c1d2165 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_thrio description: Thrio makes it easy and fast to add flutter to existing mobile applications, and provide a simple and consistent navigator APIs. -version: 4.16.3 +version: 4.17.0 homepage: https://github.com/flutter-thrio/flutter_thrio environment: