💄 New navigation draft (skip ci)

This commit is contained in:
LittleSheep 2025-03-22 12:48:55 +08:00
parent 152872db65
commit f356e08f79
5 changed files with 108 additions and 55 deletions

View File

@ -322,6 +322,9 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
if (!mounted) return;
final ud = context.read<UserDirectoryProvider>();
final userCacheSize = await ud.loadAccountCache();
if (!mounted) return;
final rm = context.read<SnRealmProvider>();
await rm.refreshAvailableRealms();
logging.info('[Users] Loaded local user cache, size: $userCacheSize');
logging.info('[Bootstrap] Everything initialized!');
} catch (err) {

View File

@ -88,7 +88,7 @@ class NavigationProvider extends ChangeNotifier {
'home',
'explore',
'chat',
'account',
'realm',
];
List<AppNavDestination> destinations = [];

View File

@ -11,6 +11,13 @@ class SnRealmProvider {
}
final Map<String, SnRealm> _cache = {};
List<SnRealm> _availableRealms = List.empty(growable: true);
Future<void> refreshAvailableRealms() async {
_availableRealms = await listAvailableRealms();
}
List<SnRealm> get availableRealms => _availableRealms;
Future<List<SnRealm>> listAvailableRealms() async {
final resp = await _sn.client.get('/cgi/id/realms/me/available');

View File

@ -4,11 +4,15 @@ import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/navigation.dart';
import 'package:surface/providers/userinfo.dart';
import 'package:surface/widgets/account/account_image.dart';
import 'package:surface/widgets/version_label.dart';
class AppNavigationDrawer extends StatefulWidget {
@ -25,12 +29,15 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<NavigationProvider>().autoDetectIndex(GoRouter.maybeOf(context));
context
.read<NavigationProvider>()
.autoDetectIndex(GoRouter.maybeOf(context));
});
}
@override
Widget build(BuildContext context) {
final ua = context.read<UserProvider>();
final nav = context.watch<NavigationProvider>();
final cfg = context.watch<ConfigProvider>();
@ -39,58 +46,101 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
return ListenableBuilder(
listenable: nav,
builder: (context, _) {
final destinations = [
...nav.destinations.where((ele) => ele.isPinned),
...nav.destinations.where((ele) => !ele.isPinned),
];
return NavigationDrawer(
return Drawer(
elevation: widget.elevation,
backgroundColor: backgroundColor,
selectedIndex: nav.currentIndex,
children: [
if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS) && !cfg.drawerIsExpanded)
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).dividerColor,
width: 1 / MediaQuery.of(context).devicePixelRatio,
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!kIsWeb &&
(Platform.isWindows ||
Platform.isLinux ||
Platform.isMacOS) &&
!cfg.drawerIsExpanded)
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).dividerColor,
width: 1 / MediaQuery.of(context).devicePixelRatio,
),
),
),
child: WindowTitleBarBox(),
),
child: WindowTitleBarBox(),
Gap(MediaQuery.of(context).padding.top),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Solar Network').bold(),
AppVersionLabel(),
],
).padding(
horizontal: 32,
vertical: 12,
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Solar Network').bold(),
AppVersionLabel(),
],
).padding(
horizontal: 32,
vertical: 12,
),
...destinations.where((ele) => ele.isPinned).map((ele) {
return NavigationDrawerDestination(
icon: ele.icon,
label: Text(ele.label).tr(),
);
}),
const Divider(),
...destinations.where((ele) => !ele.isPinned).map((ele) {
return NavigationDrawerDestination(
icon: ele.icon,
label: Text(ele.label).tr(),
);
}),
],
onDestinationSelected: (idx) {
nav.setIndex(idx);
GoRouter.of(context).goNamed(destinations[idx].screen);
Scaffold.of(context).closeDrawer();
},
Expanded(
child: ListView(),
),
Row(
spacing: 8,
children: nav.destinations.where((ele) => ele.isPinned).map(
(ele) {
return Expanded(
child: IconButton.filledTonal(
icon: ele.icon,
color: Theme.of(context).colorScheme.onPrimaryContainer,
onPressed: () {
GoRouter.of(context).goNamed(ele.screen);
Scaffold.of(context).closeDrawer();
},
),
);
},
).toList(),
).padding(horizontal: 16),
Align(
alignment: Alignment.bottomCenter,
child: ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 24),
leading: AccountImage(content: ua.user?.avatar),
title: Text(ua.user?.nick ?? 'unknown').tr().fontSize(15),
subtitle:
Text('@${ua.user?.name ?? 'unknown'.tr()}').fontSize(13),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Symbols.notifications, fill: 1),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
onPressed: () {
GoRouter.of(context).pushNamed('notification');
Scaffold.of(context).closeDrawer();
},
),
IconButton(
icon: const Icon(Symbols.settings, fill: 1),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
onPressed: () {
GoRouter.of(context).pushNamed('settings');
Scaffold.of(context).closeDrawer();
},
),
],
),
onTap: () {
GoRouter.of(context).pushNamed('account');
Scaffold.of(context).closeDrawer();
},
),
),
Gap(MediaQuery.of(context).padding.bottom),
],
),
);
},
);

View File

@ -12,7 +12,6 @@ import 'package:surface/providers/config.dart';
import 'package:surface/providers/navigation.dart';
import 'package:surface/widgets/connection_indicator.dart';
import 'package:surface/widgets/navigation/app_background.dart';
import 'package:surface/widgets/navigation/app_bottom_navigation.dart';
import 'package:surface/widgets/navigation/app_drawer_navigation.dart';
import 'package:surface/widgets/navigation/app_rail_navigation.dart';
import 'package:surface/widgets/notify_indicator.dart';
@ -118,10 +117,6 @@ class AppRootScaffold extends StatelessWidget {
.last
.route
.name;
final isShowBottomNavigation =
NavigationProvider.kShowBottomNavScreen.contains(routeName)
? ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE)
: false;
final isPopable = !NavigationProvider.kAllDestination
.map((ele) => ele.screen)
.contains(routeName);
@ -232,8 +227,6 @@ class AppRootScaffold extends StatelessWidget {
),
drawer: !isExpandedDrawer ? AppNavigationDrawer() : null,
drawerEdgeDragWidth: isPopable ? 0 : null,
bottomNavigationBar:
isShowBottomNavigation ? AppBottomNavigationBar() : null,
);
}
}