Drawer navigation

This commit is contained in:
LittleSheep 2024-07-12 11:39:44 +08:00
parent a6d8e2e311
commit 3b1b6ec8d6
10 changed files with 93 additions and 58 deletions

View File

@ -19,6 +19,7 @@ import 'package:solian/providers/content/realm.dart';
import 'package:solian/providers/friend.dart';
import 'package:solian/providers/account_status.dart';
import 'package:solian/router.dart';
import 'package:solian/shells/root_shell.dart';
import 'package:solian/shells/system_shell.dart';
import 'package:solian/theme.dart';
import 'package:solian/translations.dart';
@ -87,8 +88,10 @@ class SolianApp extends StatelessWidget {
onInit: () => _initializeProviders(context),
builder: (context, child) {
return SystemShell(
child: ScaffoldMessenger(
child: child ?? const SizedBox(),
child: RootShell(
child: ScaffoldMessenger(
child: child ?? const SizedBox(),
),
),
);
},

View File

@ -20,7 +20,6 @@ import 'package:solian/screens/realms/realm_view.dart';
import 'package:solian/screens/feed.dart';
import 'package:solian/screens/posts/post_editor.dart';
import 'package:solian/shells/basic_shell.dart';
import 'package:solian/shells/root_shell.dart';
import 'package:solian/shells/title_shell.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
@ -28,18 +27,10 @@ import 'package:solian/widgets/sidebar/empty_placeholder.dart';
abstract class AppRouter {
static GoRouter instance = GoRouter(
routes: [
ShellRoute(
builder: (context, state, child) => RootShell(
state: state,
child: child,
),
routes: [
_feedRoute,
_chatRoute,
_realmRoute,
_accountRoute,
],
),
_feedRoute,
_chatRoute,
_realmRoute,
_accountRoute,
],
);
@ -232,7 +223,7 @@ abstract class AppRouter {
name: 'account',
builder: (context, state) => SolianTheme.isExtraLargeScreen(context)
? const EmptyPagePlaceholder()
: const AccountScreen(),
: TitleShell(state: state, child: const AccountScreen()),
),
GoRoute(
path: '/account/friend',

View File

@ -87,7 +87,7 @@ class _AccountScreenState extends State<AccountScreen> {
return ListView(
children: [
const AccountHeading().paddingOnly(bottom: 8, top: 16),
const AccountHeading().paddingOnly(bottom: 8, top: 8),
...(actionItems.map(
(x) => ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 34),

View File

@ -12,6 +12,7 @@ import 'package:solian/widgets/app_bar_title.dart';
import 'package:solian/widgets/channel/channel_list.dart';
import 'package:solian/widgets/chat/call/chat_call_indicator.dart';
import 'package:solian/widgets/current_state_action.dart';
import 'package:solian/widgets/drawer_button.dart' as drawer;
class ChatScreen extends StatefulWidget {
const ChatScreen({super.key});
@ -94,7 +95,7 @@ class _ChatScreenState extends State<ChatScreen> {
title: AppBarTitle('chat'.tr),
centerTitle: false,
floating: true,
titleSpacing: SolianTheme.titleSpacing(context),
leading: const drawer.DrawerButton(),
toolbarHeight: SolianTheme.toolbarHeight(context),
actions: [
const BackgroundStateWidget(),
@ -191,7 +192,8 @@ class _ChatScreenState extends State<ChatScreen> {
child: RefreshIndicator(
onRefresh: () => getChannels(),
child: ChannelListWidget(
channels: _channels.where((x) => x.type == 1).toList(),
channels:
_channels.where((x) => x.type == 1).toList(),
selfId: _accountId ?? 0,
noCategory: true,
),

View File

@ -11,6 +11,7 @@ import 'package:solian/theme.dart';
import 'package:solian/widgets/app_bar_title.dart';
import 'package:solian/widgets/current_state_action.dart';
import 'package:solian/widgets/feed/feed_list.dart';
import 'package:solian/widgets/drawer_button.dart' as drawer;
class FeedScreen extends StatefulWidget {
const FeedScreen({super.key});
@ -62,8 +63,8 @@ class _FeedScreenState extends State<FeedScreen> {
title: AppBarTitle('feed'.tr),
centerTitle: false,
floating: true,
titleSpacing: SolianTheme.titleSpacing(context),
toolbarHeight: SolianTheme.toolbarHeight(context),
leading: const drawer.DrawerButton(),
actions: [
const BackgroundStateWidget(),
const NotificationButton(),

View File

@ -11,6 +11,7 @@ import 'package:solian/theme.dart';
import 'package:solian/widgets/account/signin_required_overlay.dart';
import 'package:solian/widgets/app_bar_title.dart';
import 'package:solian/widgets/current_state_action.dart';
import 'package:solian/widgets/drawer_button.dart' as drawer;
class RealmListScreen extends StatefulWidget {
const RealmListScreen({super.key});
@ -79,7 +80,7 @@ class _RealmListScreenState extends State<RealmListScreen> {
title: AppBarTitle('realm'.tr),
centerTitle: false,
floating: true,
titleSpacing: SolianTheme.titleSpacing(context),
leading: const drawer.DrawerButton(),
toolbarHeight: SolianTheme.toolbarHeight(context),
actions: [
const BackgroundStateWidget(),

View File

@ -1,36 +1,33 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:go_router/go_router.dart';
import 'package:solian/router.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/navigation/app_navigation.dart';
import 'package:solian/widgets/navigation/app_navigation_bottom_bar.dart';
import 'package:solian/widgets/navigation/app_navigation_drawer.dart';
import 'package:solian/widgets/navigation/app_navigation_rail.dart';
final GlobalKey<ScaffoldState> rootScaffoldKey = GlobalKey<ScaffoldState>();
class RootShell extends StatelessWidget {
final bool showSidebar;
final bool showNavigation;
final bool? showBottomNavigation;
final GoRouterState state;
final Widget child;
const RootShell({
super.key,
required this.state,
required this.child,
this.showSidebar = true,
this.showNavigation = true,
this.showBottomNavigation,
});
void closeDrawer() {
rootScaffoldKey.currentState!.closeDrawer();
}
@override
Widget build(BuildContext context) {
final routeName = AppRouter
.instance.routerDelegate.currentConfiguration.lastOrNull?.route.name;
final showBottom = showBottomNavigation ??
AppNavigation.destinationPages.contains(routeName);
return Scaffold(
key: rootScaffoldKey,
drawer: const AppNavigationDrawer(),
body: SolianTheme.isLargeScreen(context)
? Row(
children: [
@ -40,24 +37,7 @@ class RootShell extends StatelessWidget {
Expanded(child: child),
],
)
: Stack(
children: [
child,
Positioned(
bottom: 0,
left: 0,
right: 0,
child: const AppNavigationBottomBar()
.animate(target: showBottom ? 0 : 1)
.slideY(
duration: 250.ms,
begin: 0,
end: 1,
curve: Curves.easeInToLinear,
),
),
],
),
: child,
);
}
}

View File

@ -4,7 +4,8 @@ import 'package:go_router/go_router.dart';
import 'package:solian/router.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/app_bar_title.dart';
import 'package:solian/widgets/prev_page.dart';
import 'package:solian/widgets/prev_page.dart' as prev;
import 'package:solian/widgets/drawer_button.dart' as drawer;
class TitleShell extends StatelessWidget {
final bool showAppBar;
@ -25,12 +26,14 @@ class TitleShell extends StatelessWidget {
return Scaffold(
appBar: showAppBar
? AppBar(
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
centerTitle: false,
toolbarHeight: SolianTheme.toolbarHeight(context),
leading: canPop ? const PrevPageButton() : null,
automaticallyImplyLeading: false,
)
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
centerTitle: false,
toolbarHeight: SolianTheme.toolbarHeight(context),
leading: canPop
? const prev.PrevPageButton()
: const drawer.DrawerButton(),
automaticallyImplyLeading: false,
)
: null,
body: child,
);

View File

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import 'package:solian/shells/root_shell.dart';
class DrawerButton extends StatelessWidget {
const DrawerButton({super.key});
void openDrawer() {
rootScaffoldKey.currentState!.openDrawer();
}
@override
Widget build(BuildContext context) {
return IconButton(
icon: const Icon(Icons.menu),
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
onPressed: openDrawer,
);
}
}

View File

@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:solian/router.dart';
import 'package:solian/shells/root_shell.dart';
import 'package:solian/widgets/navigation/app_navigation.dart';
class AppNavigationDrawer extends StatefulWidget {
const AppNavigationDrawer({super.key});
@override
State<AppNavigationDrawer> createState() => _AppNavigationDrawerState();
}
class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return NavigationDrawer(
selectedIndex: _selectedIndex,
onDestinationSelected: (idx) {
setState(() => _selectedIndex = idx);
AppRouter.instance.goNamed(AppNavigation.destinations[idx].page);
rootScaffoldKey.currentState!.closeDrawer();
},
children: [
...AppNavigation.destinations.map(
(e) => NavigationDrawerDestination(
icon: e.icon,
label: Text(e.label),
),
)
],
);
}
}