v7
This commit is contained in:
@@ -1,8 +1,17 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'iroute.dart';
|
||||
import '../../../pages/color/color_detail_page.dart';
|
||||
import '../../../pages/color/color_page.dart';
|
||||
import '../../../pages/empty/empty_page.dart';
|
||||
import '../../../pages/settings/settings_page.dart';
|
||||
import '../../../pages/counter/counter_page.dart';
|
||||
import '../../../pages/user/user_page.dart';
|
||||
import '../transition/fade_transition_page.dart';
|
||||
import '../../../pages/color/color_add_page.dart';
|
||||
import 'route_history.dart';
|
||||
|
||||
const List<String> kDestinationsPaths = [
|
||||
'/color',
|
||||
@@ -17,8 +26,65 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
|
||||
String _path = '/color';
|
||||
|
||||
String get path => _path;
|
||||
|
||||
AppRouterDelegate() {
|
||||
// keepAlivePath.add('/color');
|
||||
_histories.add(RouteHistory(path));
|
||||
}
|
||||
|
||||
final List<RouteHistory> _histories = [];
|
||||
final List<RouteHistory> _backHistories = [];
|
||||
|
||||
List<RouteHistory> get histories => _histories.reversed.toList();
|
||||
|
||||
bool get hasHistory => _histories.length > 1;
|
||||
|
||||
bool get hasBackHistory => _backHistories.isNotEmpty;
|
||||
|
||||
/// 历史回退操作
|
||||
/// 将当前顶层移除,并加入 _backHistories 撤销列表
|
||||
/// 并转到前一路径
|
||||
void back() {
|
||||
if (!hasHistory) return;
|
||||
RouteHistory top = _histories.removeLast();
|
||||
_backHistories.add(top);
|
||||
if (_histories.isNotEmpty) {
|
||||
_path = _histories.last.path;
|
||||
if (_histories.last.extra != null) {
|
||||
_pathExtraMap[_path] = _histories.last.extra;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void toHistory(RouteHistory history) {
|
||||
_path = history.path;
|
||||
if (history.extra != null) {
|
||||
_pathExtraMap[_path] = history.extra;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void closeHistory(int index) {
|
||||
_histories.removeAt(index);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void clearHistory() {
|
||||
_histories.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// 撤销回退操作
|
||||
/// 取出回退列表的最后元素,跳转到该路径
|
||||
void revocation() {
|
||||
RouteHistory target = _backHistories.removeLast();
|
||||
_path = target.path;
|
||||
if (target.extra != null) {
|
||||
_pathExtraMap[_path] = target.extra;
|
||||
}
|
||||
_histories.add(target);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
int? get activeIndex {
|
||||
@@ -37,48 +103,58 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
|
||||
|
||||
final List<String> keepAlivePath = [];
|
||||
|
||||
FutureOr<dynamic> changePath(String value,
|
||||
{bool forResult = false, Object? extra, bool keepAlive = false}) {
|
||||
if (forResult) {
|
||||
_completerMap[value] = Completer();
|
||||
}
|
||||
if (keepAlive) {
|
||||
if (keepAlivePath.contains(value)) {
|
||||
keepAlivePath.remove(value);
|
||||
}
|
||||
keepAlivePath.add(value);
|
||||
}
|
||||
if (extra != null) {
|
||||
_pathExtraMap[value] = extra;
|
||||
void setPathKeepLive(String value) {
|
||||
if (keepAlivePath.contains(value)) {
|
||||
keepAlivePath.remove(value);
|
||||
}
|
||||
keepAlivePath.add(value);
|
||||
path = value;
|
||||
if (forResult) {
|
||||
return _completerMap[value]!.future;
|
||||
}
|
||||
}
|
||||
|
||||
void setPathForData(String value, dynamic data) {
|
||||
_pathExtraMap[value] = data;
|
||||
path = value;
|
||||
}
|
||||
|
||||
Future<dynamic> changePathForResult(String value) async {
|
||||
Completer<dynamic> completer = Completer();
|
||||
_completerMap[value] = completer;
|
||||
path = value;
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
set path(String value) {
|
||||
if (_path == value) return;
|
||||
_path = value;
|
||||
/// 将路由加入历史列表
|
||||
_addPathToHistory(value,_pathExtraMap[path]);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _addPathToHistory(String value, Object? extra) {
|
||||
if (_histories.isNotEmpty && value == _histories.last.path) return;
|
||||
_histories.add(RouteHistory(
|
||||
value,
|
||||
extra: _pathExtraMap[path],
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Navigator(
|
||||
onPopPage: _onPopPage,
|
||||
pages: _buildPages(context, path),
|
||||
pages: _buildPages(path),
|
||||
);
|
||||
}
|
||||
|
||||
List<Page> _buildPages(BuildContext context,String path) {
|
||||
List<Page> _buildPages(path) {
|
||||
List<Page> pages = [];
|
||||
List<Page> topPages = _buildPageByPath(context,path);
|
||||
List<Page> topPages = _buildPageByPath(path);
|
||||
|
||||
if (keepAlivePath.isNotEmpty) {
|
||||
for (String alivePath in keepAlivePath) {
|
||||
if (alivePath != path) {
|
||||
pages.addAll(_buildPageByPath(context,alivePath));
|
||||
pages.addAll(_buildPageByPath(alivePath));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,36 +167,64 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
|
||||
return pages;
|
||||
}
|
||||
|
||||
Page? _buildPageByPathFromTree(BuildContext context, String path) {
|
||||
// 1. 根据 path 在 iroute 树中查询节点
|
||||
IRoute? iroute = root.match(path);
|
||||
Object? extra = _pathExtraMap[path];
|
||||
bool keepAlive = keepAlivePath.contains(path);
|
||||
bool forResult = _completerMap.containsKey(path);
|
||||
Page? page;
|
||||
if (iroute != null) {
|
||||
page = iroute.builder?.call(
|
||||
context,
|
||||
IRouteData(
|
||||
uri: Uri.parse(path),
|
||||
extra: extra,
|
||||
keepAlive: keepAlive,
|
||||
forResult: forResult,
|
||||
),
|
||||
);
|
||||
List<Page> _buildPageByPath(String path) {
|
||||
Widget? child;
|
||||
if (path.startsWith('/color')) {
|
||||
return buildColorPages(path);
|
||||
}
|
||||
return page;
|
||||
|
||||
if (path == kDestinationsPaths[1]) {
|
||||
child = const CounterPage();
|
||||
}
|
||||
if (path == kDestinationsPaths[2]) {
|
||||
child = const UserPage();
|
||||
}
|
||||
if (path == kDestinationsPaths[3]) {
|
||||
child = const SettingPage();
|
||||
}
|
||||
return [
|
||||
FadeTransitionPage(
|
||||
key: ValueKey(path),
|
||||
child: child ?? const EmptyPage(),
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
List<Page> _buildPageByPath(BuildContext context,String path) {
|
||||
List<Page> buildColorPages(String path) {
|
||||
List<Page> result = [];
|
||||
Uri uri = Uri.parse(path);
|
||||
String dist = '';
|
||||
for (String segment in uri.pathSegments) {
|
||||
dist += '/$segment';
|
||||
Page? page = _buildPageByPathFromTree(context,dist);
|
||||
if(page!=null){
|
||||
result.add(page);
|
||||
if (segment == 'color') {
|
||||
result.add(const FadeTransitionPage(
|
||||
key: ValueKey('/color'),
|
||||
child: ColorPage(),
|
||||
));
|
||||
}
|
||||
if (segment == 'detail') {
|
||||
final Map<String, String> queryParams = uri.queryParameters;
|
||||
String? selectedColor = queryParams['color'];
|
||||
if (selectedColor != null) {
|
||||
Color color = Color(int.parse(selectedColor, radix: 16));
|
||||
result.add(FadeTransitionPage(
|
||||
key: const ValueKey('/color/detail'),
|
||||
child: ColorDetailPage(color: color),
|
||||
));
|
||||
} else {
|
||||
Color? selectedColor = _pathExtraMap[path];
|
||||
if (selectedColor != null) {
|
||||
result.add(FadeTransitionPage(
|
||||
key: const ValueKey('/color/detail'),
|
||||
child: ColorDetailPage(color: selectedColor),
|
||||
));
|
||||
_pathExtraMap.remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (segment == 'add') {
|
||||
result.add(const FadeTransitionPage(
|
||||
key: ValueKey('/color/add'),
|
||||
child: ColorAddPage(),
|
||||
));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -1,131 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../pages/color/color_add_page.dart';
|
||||
import '../../../pages/color/color_detail_page.dart';
|
||||
import '../../../pages/color/color_page.dart';
|
||||
import '../../../pages/counter/counter_page.dart';
|
||||
import '../../../pages/user/user_page.dart';
|
||||
import '../../../pages/settings/settings_page.dart';
|
||||
import '../transition/fade_transition_page.dart';
|
||||
|
||||
class IRoute {
|
||||
final String path;
|
||||
final IRoutePageBuilder? builder;
|
||||
final List<IRoute> children;
|
||||
|
||||
const IRoute({
|
||||
required this.path,
|
||||
this.children = const [],
|
||||
this.builder,
|
||||
});
|
||||
const IRoute({required this.path, this.children = const []});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'IRoute{path: $path, children: $children}';
|
||||
}
|
||||
|
||||
IRoute? match(String path) {
|
||||
return matchRoute(this, path);
|
||||
List<String> list(){
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
IRoute? matchRoute(IRoute route, String path) {
|
||||
if (route.path == path) {
|
||||
return route;
|
||||
} else {
|
||||
if (route.children.isNotEmpty) {
|
||||
for (int i = 0; i < route.children.length; i++) {
|
||||
IRoute current = route.children[i];
|
||||
IRoute? target = matchRoute(current, path);
|
||||
if (target != null) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
typedef IRoutePageBuilder = Page? Function(
|
||||
BuildContext context, IRouteData data);
|
||||
|
||||
class IRouteData {
|
||||
final Object? extra;
|
||||
final bool forResult;
|
||||
final Uri uri;
|
||||
final bool keepAlive;
|
||||
|
||||
IRouteData({
|
||||
this.extra,
|
||||
required this.uri,
|
||||
this.forResult = false,
|
||||
this.keepAlive = false,
|
||||
});
|
||||
}
|
||||
|
||||
IRoute root = IRoute(path: '/', children: kDestinationsIRoutes);
|
||||
|
||||
List<IRoute> kDestinationsIRoutes = [
|
||||
const List<IRoute> kDestinationsIRoutes = [
|
||||
IRoute(
|
||||
path: '/color',
|
||||
builder: (ctx, data) {
|
||||
return const FadeTransitionPage(
|
||||
key: ValueKey('/color'),
|
||||
child: ColorPage(),
|
||||
);
|
||||
},
|
||||
children: [
|
||||
IRoute(
|
||||
path: '/color/detail',
|
||||
builder: (ctx, data) {
|
||||
final Map<String, String> queryParams = data.uri.queryParameters;
|
||||
String? selectedColor = queryParams['color'];
|
||||
Color color = Colors.black;
|
||||
if (selectedColor != null) {
|
||||
color = Color(int.parse(selectedColor, radix: 16));
|
||||
} else if (data.extra is Color) {
|
||||
color = data.extra as Color;
|
||||
}
|
||||
return FadeTransitionPage(
|
||||
key: const ValueKey('/color/detail'),
|
||||
child: ColorDetailPage(color: color),
|
||||
);
|
||||
},
|
||||
),
|
||||
IRoute(
|
||||
path: '/color/add',
|
||||
builder: (ctx, data) {
|
||||
return const FadeTransitionPage(
|
||||
key: ValueKey('/color/add'),
|
||||
child: ColorAddPage(),
|
||||
);
|
||||
}),
|
||||
IRoute(path: '/color/add'),
|
||||
IRoute(path: '/color/detail'),
|
||||
],
|
||||
),
|
||||
IRoute(
|
||||
path: '/counter',
|
||||
builder: (ctx, data) {
|
||||
return const FadeTransitionPage(
|
||||
key: ValueKey('/counter'),
|
||||
child: CounterPage(),
|
||||
);
|
||||
}),
|
||||
path: '/counter',
|
||||
),
|
||||
IRoute(
|
||||
path: '/user',
|
||||
builder: (ctx, data) {
|
||||
return const FadeTransitionPage(
|
||||
key: ValueKey('/user'),
|
||||
child: UserPage(),
|
||||
);
|
||||
}),
|
||||
path: '/user',
|
||||
),
|
||||
IRoute(
|
||||
path: '/settings',
|
||||
builder: (ctx, data) {
|
||||
return const FadeTransitionPage(
|
||||
key: ValueKey('/settings'),
|
||||
child: SettingPage(),
|
||||
);
|
||||
}),
|
||||
path: '/settings',
|
||||
),
|
||||
];
|
||||
|
||||
6
lib/v6/app/navigation/router/route_history.dart
Normal file
6
lib/v6/app/navigation/router/route_history.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
class RouteHistory{
|
||||
final String path;
|
||||
final Object? extra;
|
||||
|
||||
RouteHistory(this.path, { this.extra});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../router/app_router_delegate.dart';
|
||||
import 'app_navigation_rail.dart';
|
||||
import 'app_top_bar.dart';
|
||||
import 'app_top_bar/app_top_bar.dart';
|
||||
|
||||
class AppNavigation extends StatelessWidget {
|
||||
const AppNavigation({super.key});
|
||||
|
||||
@@ -41,7 +41,7 @@ class _AppNavigationRailState extends State<AppNavigationRail> {
|
||||
),
|
||||
tail: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 6.0),
|
||||
child: Text('V0.0.5',style: TextStyle(color: Colors.white,fontSize: 12),),
|
||||
child: Text('V0.0.6',style: TextStyle(color: Colors.white,fontSize: 12),),
|
||||
),
|
||||
backgroundColor: const Color(0xff3975c6),
|
||||
onDestinationSelected: _onDestinationSelected,
|
||||
@@ -53,9 +53,9 @@ class _AppNavigationRailState extends State<AppNavigationRail> {
|
||||
|
||||
void _onDestinationSelected(int index) {
|
||||
if(index==1){
|
||||
router.changePath(kDestinationsPaths[index],keepAlive: true);
|
||||
router.setPathKeepLive(kDestinationsPaths[index]);
|
||||
}else{
|
||||
router.path = kDestinationsPaths[index];
|
||||
router.path=kDestinationsPaths[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/components/toly_ui/button/hover_icon_button.dart';
|
||||
import '../router/app_router_delegate.dart';
|
||||
import '../../router/app_router_delegate.dart';
|
||||
|
||||
class AppRouterEditor extends StatefulWidget {
|
||||
final ValueChanged<String>? onSubmit;
|
||||
@@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/components/components.dart';
|
||||
import '../router/app_router_delegate.dart';
|
||||
import '../../router/app_router_delegate.dart';
|
||||
import 'app_router_editor.dart';
|
||||
import 'history_view_icon.dart';
|
||||
import 'route_history_button.dart';
|
||||
|
||||
class AppTopBar extends StatelessWidget {
|
||||
const AppTopBar({super.key});
|
||||
@@ -19,11 +21,15 @@ class AppTopBar extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Row(children: [
|
||||
const Spacer(),
|
||||
RouteHistoryButton(),
|
||||
const SizedBox(width: 12,),
|
||||
SizedBox(
|
||||
width: 250,
|
||||
child: AppRouterEditor(
|
||||
onSubmit: (path) => router.path = path,
|
||||
)),
|
||||
const SizedBox(width: 12,),
|
||||
HistoryViewIcon(),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: VerticalDivider(
|
||||
156
lib/v6/app/navigation/views/app_top_bar/history_view_icon.dart
Normal file
156
lib/v6/app/navigation/views/app_top_bar/history_view_icon.dart
Normal file
@@ -0,0 +1,156 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/components/components.dart';
|
||||
import '../../router/app_router_delegate.dart';
|
||||
import '../../router/route_history.dart';
|
||||
import 'app_top_bar.dart';
|
||||
|
||||
class HistoryViewIcon extends StatelessWidget{
|
||||
const HistoryViewIcon({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: PopPanel(
|
||||
offset: const Offset(0, 10),
|
||||
panel: SizedBox(
|
||||
height: 350,
|
||||
child: Column(
|
||||
children: [
|
||||
_buildTopBar(),
|
||||
const Expanded(
|
||||
child:HistoryPanel(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.history,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTopBar() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xffFAFAFC),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
padding:
|
||||
const EdgeInsets.only(top: 10, left: 12, right: 12, bottom: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text(
|
||||
'浏览历史',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Spacer(),
|
||||
TextButton(onPressed: router.clearHistory, child: const Text('清空历史'))
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryItem extends StatefulWidget {
|
||||
final RouteHistory history;
|
||||
final VoidCallback onPressed;
|
||||
final VoidCallback onDelete;
|
||||
|
||||
const HistoryItem({super.key, required this.history, required this.onPressed, required this.onDelete});
|
||||
|
||||
@override
|
||||
State<HistoryItem> createState() => _HistoryItemState();
|
||||
}
|
||||
|
||||
class _HistoryItemState extends State<HistoryItem> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: widget.onPressed,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(widget.history.path),
|
||||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(kRouteLabelMap[widget.history.path]!),
|
||||
],
|
||||
)),
|
||||
GestureDetector(
|
||||
onTap: widget.onDelete,
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
size: 18,
|
||||
color: Color(0xff8E92A9),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryPanel extends StatefulWidget {
|
||||
const HistoryPanel({super.key});
|
||||
|
||||
@override
|
||||
State<HistoryPanel> createState() => _HistoryPanelState();
|
||||
}
|
||||
|
||||
class _HistoryPanelState extends State<HistoryPanel> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
router.addListener(_onChange);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
router.removeListener(_onChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if(router.histories.isEmpty){
|
||||
return const Center(
|
||||
child: Text(
|
||||
'暂无浏览历史记录',
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
itemExtent: 46,
|
||||
itemCount: router.histories.length,
|
||||
itemBuilder: (_, index) =>
|
||||
HistoryItem(
|
||||
onDelete: (){
|
||||
int fixIndex = router.histories.length - 1 - index;
|
||||
router.closeHistory(fixIndex);
|
||||
},
|
||||
onPressed: (){
|
||||
router.toHistory(router.histories[index]);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
history: router.histories[index]),
|
||||
);
|
||||
}
|
||||
|
||||
void _onChange() {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/components/toly_ui/button/hover_icon_button.dart';
|
||||
import '../../router/app_router_delegate.dart';
|
||||
|
||||
class RouteHistoryButton extends StatefulWidget {
|
||||
const RouteHistoryButton({super.key});
|
||||
|
||||
@override
|
||||
State<RouteHistoryButton> createState() => _RouteHistoryButtonState();
|
||||
}
|
||||
|
||||
class _RouteHistoryButtonState extends State<RouteHistoryButton> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
router.addListener(_onChange);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
router.removeListener(_onChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool hasHistory = router.hasHistory;
|
||||
bool hasBackHistory = router.hasBackHistory;
|
||||
Color activeColor = const Color(0xff9195AC);
|
||||
Color inActiveColor = const Color(0xffC7CAD5);
|
||||
Color historyColor = hasHistory?activeColor:inActiveColor;
|
||||
Color backHistoryColor = hasBackHistory?activeColor:inActiveColor;
|
||||
return Wrap(
|
||||
children: [
|
||||
HoverIconButton(
|
||||
size: 20,
|
||||
hoverColor: historyColor,
|
||||
defaultColor: historyColor,
|
||||
icon: CupertinoIcons.arrow_left_circle,
|
||||
onPressed: hasHistory?router.back:null,
|
||||
),
|
||||
const SizedBox(width: 8,),
|
||||
HoverIconButton(
|
||||
size: 20,
|
||||
hoverColor: backHistoryColor,
|
||||
defaultColor: backHistoryColor,
|
||||
icon: CupertinoIcons.arrow_right_circle,
|
||||
onPressed: hasBackHistory?router.revocation:null,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _onChange() {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user