books
This commit is contained in:
9
lib/navigation/router/menus/menu_scope/menu_history.dart
Normal file
9
lib/navigation/router/menus/menu_scope/menu_history.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
class MenuHistory {
|
||||
final String menuLabel;
|
||||
final String menuPath;
|
||||
|
||||
MenuHistory({
|
||||
required this.menuLabel,
|
||||
required this.menuPath,
|
||||
});
|
||||
}
|
||||
200
lib/navigation/router/menus/menu_scope/menu_scope.dart
Normal file
200
lib/navigation/router/menus/menu_scope/menu_scope.dart
Normal file
@@ -0,0 +1,200 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:toly_menu/toly_menu.dart';
|
||||
|
||||
import '../menu_tree.dart';
|
||||
import 'menu_history.dart';
|
||||
|
||||
class MenuScope extends InheritedNotifier<MenuStore> {
|
||||
const MenuScope({super.key, required super.child, super.notifier});
|
||||
|
||||
static MenuStore of(BuildContext context) {
|
||||
return context.dependOnInheritedWidgetOfExactType<MenuScope>()!.notifier!;
|
||||
}
|
||||
|
||||
static MenuStore read(BuildContext context) {
|
||||
return context.getInheritedWidgetOfExactType<MenuScope>()!.notifier!;
|
||||
}
|
||||
}
|
||||
|
||||
class MenuStore with ChangeNotifier {
|
||||
late MenuState _state;
|
||||
MenuState get state => _state;
|
||||
final GoRouter goRouter;
|
||||
final List<MenuHistory> _history = [];
|
||||
List<MenuHistory> get history => _history;
|
||||
|
||||
MenuStore({
|
||||
List<String> expandMenus = const [],
|
||||
required this.goRouter,
|
||||
required String activeMenu,
|
||||
}) {
|
||||
_state = MenuState(
|
||||
expandMenus: expandMenus,
|
||||
activeMenu: activeMenu,
|
||||
items: rootMenu.children,
|
||||
);
|
||||
|
||||
_history.add(MenuHistory(
|
||||
menuLabel: pathName(activeMenu) ?? activeMenu,
|
||||
menuPath: activeMenu,
|
||||
));
|
||||
goRouter.routerDelegate.addListener(_onRouterChange);
|
||||
}
|
||||
|
||||
MenuNode? get currentNode => queryMenuNodeByPath(
|
||||
MenuNode(
|
||||
path: '',
|
||||
label: '',
|
||||
deep: -1,
|
||||
children: _state.items,
|
||||
),
|
||||
_state.activeMenu);
|
||||
|
||||
String? pathName(String path) => queryMenuNodeByPath(
|
||||
MenuNode(
|
||||
path: '',
|
||||
label: '',
|
||||
deep: -1,
|
||||
children: _state.items,
|
||||
),
|
||||
path)
|
||||
?.label;
|
||||
|
||||
void selectMenuPath(String path) {
|
||||
print("======================selectMenuPath:$path======${_shouldAddHistory}==============");
|
||||
MenuNode root = MenuNode(
|
||||
path: '',
|
||||
label: '',
|
||||
deep: -1,
|
||||
children: _state.items,
|
||||
);
|
||||
List<MenuNode> result = findNodes(root, Uri.parse(path), 0, '/', []);
|
||||
if (result.isNotEmpty) {
|
||||
List<String> expandMenus = [];
|
||||
if (result.length > 1) {
|
||||
expandMenus.addAll(
|
||||
result.sublist(0, result.length - 1).map((e) => e.path).toList());
|
||||
}
|
||||
if(_shouldAddHistory){
|
||||
_history.add(MenuHistory(
|
||||
menuLabel: result.last.label,
|
||||
menuPath: result.last.path,
|
||||
));
|
||||
}else{
|
||||
_shouldAddHistory = true;
|
||||
}
|
||||
|
||||
_state = state.copyWith(
|
||||
activeMenu: result.last.path, expandMenus: expandMenus);
|
||||
}
|
||||
}
|
||||
|
||||
bool _shouldAddHistory = true;
|
||||
void selectHistory(String path) {
|
||||
_shouldAddHistory = false;
|
||||
goRouter.go(path);
|
||||
}
|
||||
|
||||
void closeHistory(MenuHistory history) {
|
||||
int index = _history.indexOf(history);
|
||||
if(_history.length==1){
|
||||
return;
|
||||
}
|
||||
if(state.activeMenu!=history.menuPath){
|
||||
_history.remove(history);
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
MenuHistory nextActiveHistory;
|
||||
if(index==_history.length-1){
|
||||
///
|
||||
nextActiveHistory = _history[_history.length-2];
|
||||
}else{
|
||||
nextActiveHistory = _history[index+1];
|
||||
}
|
||||
_history.remove(history);
|
||||
selectHistory(nextActiveHistory.menuPath);
|
||||
}
|
||||
|
||||
List<MenuNode> findNodes(
|
||||
MenuNode node,
|
||||
Uri uri,
|
||||
int deep,
|
||||
String prefix,
|
||||
List<MenuNode> result,
|
||||
) {
|
||||
List<String> parts = uri.pathSegments;
|
||||
if (deep > parts.length - 1) {
|
||||
return result;
|
||||
}
|
||||
String target = parts[deep];
|
||||
if (node.children.isNotEmpty) {
|
||||
target = prefix + target;
|
||||
List<MenuNode> nodes =
|
||||
node.children.where((e) => e.path == target).toList();
|
||||
bool match = nodes.isNotEmpty;
|
||||
if (match) {
|
||||
MenuNode matched = nodes.first;
|
||||
result.add(matched);
|
||||
String nextPrefix = '${matched.path}/';
|
||||
findNodes(matched, uri, ++deep, nextPrefix, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MenuNode? queryMenuNodeByPath(MenuNode node, String path) {
|
||||
if (node.path == path) {
|
||||
return node;
|
||||
}
|
||||
if (node.children.isNotEmpty) {
|
||||
for (int i = 0; i < node.children.length; i++) {
|
||||
MenuNode? result = queryMenuNodeByPath(node.children[i], path);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void select(MenuNode menu) {
|
||||
if (menu.isLeaf) {
|
||||
_state = state.copyWith(activeMenu: menu.path);
|
||||
goRouter.go(menu.path);
|
||||
_history.add(MenuHistory(
|
||||
menuLabel: menu.label,
|
||||
menuPath: menu.path,
|
||||
));
|
||||
// notifyListeners();
|
||||
} else {
|
||||
List<String> menus = [];
|
||||
String path = menu.path.substring(1);
|
||||
List<String> parts = path.split('/');
|
||||
|
||||
if (parts.isNotEmpty) {
|
||||
String path = '';
|
||||
for (String part in parts) {
|
||||
path += '/$part';
|
||||
menus.add(path);
|
||||
}
|
||||
}
|
||||
if (state.expandMenus.contains(menu.path)) {
|
||||
menus.remove(menu.path);
|
||||
}
|
||||
|
||||
_state = state.copyWith(expandMenus: menus);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void _onRouterChange() {
|
||||
String path =
|
||||
goRouter.routerDelegate.currentConfiguration.last.matchedLocation;
|
||||
if (path != state.activeMenu) {
|
||||
selectMenuPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user