@@ -2,6 +2,7 @@ import 'dart:io';
22
33import 'package:fluent_ui/fluent_ui.dart' ;
44import 'package:fluentui_system_icons/fluentui_system_icons.dart' as msicons;
5+ import 'package:flutter/gestures.dart' ;
56import 'package:flutter_riverpod/flutter_riverpod.dart' ;
67import 'package:go_router/go_router.dart' ;
78import 'package:win32_registry/win32_registry.dart' ;
@@ -64,6 +65,24 @@ class _AppShellState extends ConsumerState<AppShell> {
6465 r'C:\ProgramData\Microsoft\User Account Pictures\user-192.png' ,
6566 );
6667
68+ void _updateNavigationIndex () {
69+ WidgetsBinding .instance.addPostFrameCallback ((_) {
70+ if (! mounted) return ;
71+ final location = GoRouterState .of (context).uri.toString ();
72+ final RouteMeta ? route = RouteMeta .fromPath (location, allowPrefix: true );
73+ final int ? index = AppRoutes .getPaneIndexFromRoute (route);
74+ if (index != null ) {
75+ ref.read (navigationIndexProvider.notifier).index = index;
76+ }
77+ });
78+ }
79+
80+ @override
81+ void initState () {
82+ _updateNavigationIndex ();
83+ super .initState ();
84+ }
85+
6786 @override
6887 void dispose () {
6988 _searchController.dispose ();
@@ -79,165 +98,170 @@ class _AppShellState extends ConsumerState<AppShell> {
7998
8099 final FluentLocalizations localizations = FluentLocalizations .of (context);
81100
82- return SafeArea (
83- child: NavigationView (
84- key: _viewKey,
85- contentShape: const RoundedRectangleBorder (
86- side: BorderSide (width: 0 , color: Colors .transparent),
87- borderRadius: BorderRadius .only (topLeft: Radius .circular (8.0 )),
88- ),
89- appBar: NavigationAppBar (
90- automaticallyImplyLeading: false ,
91- leading: () {
92- final bool enabled =
93- widget.shellContext != null &&
94- ref.read (appRouterProvider).canPop ();
95- final Null Function ()? onPressed = enabled
96- ? () {
97- context.pop ();
98- WidgetsBinding .instance.addPostFrameCallback ((_) {
99- if (! mounted) return ;
100- final location = GoRouterState .of (context).uri.toString ();
101- final RouteMeta ? route = RouteMeta .fromPath (
102- location,
103- allowPrefix: true ,
104- );
105- final int ? index = AppRoutes .getPaneIndexFromRoute (route);
106- if (index != null ) {
107- ref.read (navigationIndexProvider.notifier).index =
108- index;
109- }
110- });
111- }
112- : null ;
101+ return Listener (
102+ onPointerDown: (PointerDownEvent event) {
103+ if (event.buttons & kBackMouseButton != 0 && context.canPop ()) {
104+ context.pop ();
105+ _updateNavigationIndex ();
106+ }
107+ },
108+ child: SafeArea (
109+ child: NavigationView (
110+ key: _viewKey,
111+ contentShape: const RoundedRectangleBorder (
112+ side: BorderSide (width: 0 , color: Colors .transparent),
113+ borderRadius: BorderRadius .only (topLeft: Radius .circular (8.0 )),
114+ ),
115+ appBar: NavigationAppBar (
116+ automaticallyImplyLeading: false ,
117+ leading: () {
118+ final GoRouter router = ref.read (appRouterProvider);
119+ final List <RouteMatchBase > matches =
120+ router.routerDelegate.currentConfiguration.matches;
121+ final firstMatch = matches.first as ShellRouteMatch ;
113122
114- return NavigationPaneTheme (
115- data: NavigationPaneTheme .of (context).merge (
116- NavigationPaneThemeData (
117- unselectedIconColor: WidgetStateProperty .resolveWith ((
118- states,
119- ) {
120- if (states.isDisabled) {
121- return ButtonThemeData .buttonColor (context, states);
123+ final VoidCallback ? onPressed = firstMatch.matches.length > 1
124+ ? () {
125+ context.pop ();
126+ _updateNavigationIndex ();
122127 }
123- return ButtonThemeData .uncheckedInputColor (
124- FluentTheme .of (context),
128+ : null ;
129+
130+ return NavigationPaneTheme (
131+ data: NavigationPaneTheme .of (context).merge (
132+ NavigationPaneThemeData (
133+ unselectedIconColor: WidgetStateProperty .resolveWith ((
125134 states,
126- ).basedOnLuminance ();
127- }),
135+ ) {
136+ if (states.isDisabled) {
137+ return ButtonThemeData .buttonColor (context, states);
138+ }
139+ return ButtonThemeData .uncheckedInputColor (
140+ FluentTheme .of (context),
141+ states,
142+ ).basedOnLuminance ();
143+ }),
144+ ),
128145 ),
129- ),
130- child: Builder (
131- builder: (context) => PaneItem (
132- icon: const Center (child: Icon (FluentIcons .back, size: 12.0 )),
133- title: Text (localizations.backButtonTooltip),
134- body: const SizedBox .shrink (),
135- enabled: enabled,
136- ).build (context, false , onPressed, displayMode: .compact),
137- ),
138- );
139- }(),
140- title: const Text ('Revision Tool' ),
141- actions: RepaintBoundary (child: WindowCaption ()),
142- ),
143- pane: NavigationPane (
144- size: const NavigationPaneSize (openWidth: 300 ),
145- selected: ref.watch (navigationIndexProvider),
146- onItemPressed: (index) {
147- final RouteMeta route = AppRoutes .navigationRoutes[index];
148- ref.read (navigationIndexProvider.notifier).index = index;
149- context.push (route.path);
150- },
151- displayMode: context.mqSize.width >= 800
152- ? PaneDisplayMode .open
153- : PaneDisplayMode .minimal,
154- header: RepaintBoundary (
155- child: SizedBox (
156- height: 90 ,
157- // height: kOneLineTileHeight,
158- child: Row (
159- children: [
160- const SizedBox (width: 5.0 ),
161- ClipRRect (
162- borderRadius: const BorderRadius .all (Radius .circular (30.0 )),
163- child: Image .file (
164- width: imgXY,
165- height: imgXY,
166- cacheWidth: imgCacheSize,
167- cacheHeight: imgCacheSize,
168- _userImageFile,
146+ child: Builder (
147+ builder: (context) => PaneItem (
148+ icon: const Center (
149+ child: Icon (FluentIcons .back, size: 12.0 ),
169150 ),
170- ),
171- const SizedBox (width: 13.0 ),
172- Column (
173- mainAxisAlignment: .center,
174- crossAxisAlignment: .start,
175- children: [
176- Text (
177- _username ?? 'User' ,
178- style: const TextStyle (
179- fontWeight: FontWeight .w500,
180- fontSize: 14 ,
181- ),
151+ title: Text (localizations.backButtonTooltip),
152+ body: const SizedBox .shrink (),
153+ enabled: onPressed != null ,
154+ ).build (context, false , onPressed, displayMode: .compact),
155+ ),
156+ );
157+ }(),
158+ title: const Text ('Revision Tool' ),
159+ actions: Padding (
160+ padding: const .only (left: 50 ),
161+ child: RepaintBoundary (child: WindowCaption ()),
162+ ),
163+ ),
164+ pane: NavigationPane (
165+ size: const NavigationPaneSize (openWidth: 300 ),
166+ selected: ref.watch (navigationIndexProvider),
167+ onItemPressed: (index) {
168+ if (index == ref.read (navigationIndexProvider)) return ;
169+
170+ final RouteMeta route = AppRoutes .navigationRoutes[index];
171+ ref.read (navigationIndexProvider.notifier).index = index;
172+ context.push (route.path);
173+ },
174+ displayMode: context.mqSize.width >= 800 ? .open : .minimal,
175+ header: RepaintBoundary (
176+ child: SizedBox (
177+ height: 90 ,
178+ // height: kOneLineTileHeight,
179+ child: Row (
180+ children: [
181+ const SizedBox (width: 5.0 ),
182+ ClipRRect (
183+ clipBehavior: .hardEdge,
184+ borderRadius: const BorderRadius .all (
185+ Radius .circular (30.0 ),
182186 ),
183- const Text (
184- 'Proud ReviOS user' ,
185- style : TextStyle (
186- fontSize : 11 ,
187- fontWeight : FontWeight .normal ,
188- ) ,
187+ child : Image . file (
188+ width : imgXY ,
189+ height : imgXY,
190+ cacheWidth : imgCacheSize ,
191+ cacheHeight : imgCacheSize ,
192+ _userImageFile ,
189193 ),
190- ],
191- ),
192- ],
194+ ),
195+ const SizedBox (width: 13.0 ),
196+ Column (
197+ mainAxisAlignment: .center,
198+ crossAxisAlignment: .start,
199+ children: [
200+ Text (
201+ _username ?? 'User' ,
202+ style: const TextStyle (
203+ fontWeight: FontWeight .w500,
204+ fontSize: 14 ,
205+ ),
206+ ),
207+ const Text (
208+ 'Proud ReviOS user' ,
209+ style: TextStyle (
210+ fontSize: 11 ,
211+ fontWeight: FontWeight .normal,
212+ ),
213+ ),
214+ ],
215+ ),
216+ ],
217+ ),
193218 ),
194219 ),
195- ),
196- autoSuggestBox: Padding (
197- padding: const EdgeInsets .symmetric (vertical: 4 ),
198- child: AutoSuggestBox (
199- key: _searchKey,
200- trailingIcon: const Padding (
201- padding: EdgeInsets .only (right: 7.0 , bottom: 2 ),
202- child: Icon (msicons.FluentIcons .search_20_regular),
220+ autoSuggestBox: Padding (
221+ padding: const .symmetric (vertical: 4 ),
222+ child: AutoSuggestBox (
223+ key: _searchKey,
224+ trailingIcon: const Padding (
225+ padding: .only (right: 7.0 , bottom: 2 ),
226+ child: Icon (msicons.FluentIcons .search_20_regular),
227+ ),
228+ focusNode: _searchFocusNode,
229+ controller: _searchController,
230+ placeholder: t.suggestionBoxPlaceholder,
231+ items: _searchItems,
203232 ),
204- focusNode: _searchFocusNode,
205- controller: _searchController,
206- placeholder: t.suggestionBoxPlaceholder,
207- items: _searchItems,
208233 ),
234+ autoSuggestBoxReplacement: const Icon (FluentIcons .search),
235+ items: AppRoutes .mainPaneItems,
236+ footerItems: [
237+ ...AppRoutes .footerPaneItems,
238+ PaneItemSeparator (color: Colors .transparent),
239+ ],
209240 ),
210- autoSuggestBoxReplacement: const Icon (FluentIcons .search),
211- items: AppRoutes .mainPaneItems,
212- footerItems: [
213- ...AppRoutes .footerPaneItems,
214- PaneItemSeparator (color: Colors .transparent),
215- ],
216- ),
217- paneBodyBuilder: (item, child) {
218- final String ? name = item? .key is ValueKey
219- ? (item! .key! as ValueKey ).value.toString ()
220- : null ;
221- return FocusTraversalGroup (
222- key: ValueKey ('body$name ' ),
223- child: Builder (
224- builder: (context) => Column (
225- children: [
226- if (NavigationView .of (context).displayMode ==
227- PaneDisplayMode .minimal)
228- const Padding (
229- padding: EdgeInsets .only (left: 13 ),
230- child: PageHeaderBreadcrumbs (),
231- )
232- else
233- const PageHeaderBreadcrumbs (),
234- Expanded (child: widget.child),
235- ],
241+ paneBodyBuilder: (item, child) {
242+ final String ? name = item? .key is ValueKey
243+ ? (item! .key! as ValueKey ).value.toString ()
244+ : null ;
245+ return FocusTraversalGroup (
246+ key: ValueKey ('body$name ' ),
247+ child: Builder (
248+ builder: (context) => Column (
249+ children: [
250+ if (NavigationView .of (context).displayMode == .minimal)
251+ const Padding (
252+ padding: EdgeInsets .only (left: 13 ),
253+ child: PageHeaderBreadcrumbs (),
254+ )
255+ else
256+ const PageHeaderBreadcrumbs (),
257+ Expanded (child: widget.child),
258+ ],
259+ ),
236260 ),
237- ),
238- );
239- } ,
240- onOpenSearch : () => _searchFocusNode. requestFocus ( ),
261+ );
262+ },
263+ onOpenSearch : () => _searchFocusNode. requestFocus () ,
264+ ),
241265 ),
242266 );
243267 }
0 commit comments