diff --git a/lib/main.dart b/lib/main.dart index f1043e3..3e49343 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -322,6 +322,9 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener { if (!mounted) return; final ud = context.read(); final userCacheSize = await ud.loadAccountCache(); + if (!mounted) return; + final rm = context.read(); + await rm.refreshAvailableRealms(); logging.info('[Users] Loaded local user cache, size: $userCacheSize'); logging.info('[Bootstrap] Everything initialized!'); } catch (err) { diff --git a/lib/providers/navigation.dart b/lib/providers/navigation.dart index 1baf241..37dbde9 100644 --- a/lib/providers/navigation.dart +++ b/lib/providers/navigation.dart @@ -88,7 +88,7 @@ class NavigationProvider extends ChangeNotifier { 'home', 'explore', 'chat', - 'account', + 'realm', ]; List destinations = []; diff --git a/lib/providers/sn_realm.dart b/lib/providers/sn_realm.dart index 87dc1e9..36afda4 100644 --- a/lib/providers/sn_realm.dart +++ b/lib/providers/sn_realm.dart @@ -11,6 +11,13 @@ class SnRealmProvider { } final Map _cache = {}; + List _availableRealms = List.empty(growable: true); + + Future refreshAvailableRealms() async { + _availableRealms = await listAvailableRealms(); + } + + List get availableRealms => _availableRealms; Future> listAvailableRealms() async { final resp = await _sn.client.get('/cgi/id/realms/me/available'); diff --git a/lib/widgets/navigation/app_drawer_navigation.dart b/lib/widgets/navigation/app_drawer_navigation.dart index 58eec5d..015776e 100644 --- a/lib/widgets/navigation/app_drawer_navigation.dart +++ b/lib/widgets/navigation/app_drawer_navigation.dart @@ -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 { void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - context.read().autoDetectIndex(GoRouter.maybeOf(context)); + context + .read() + .autoDetectIndex(GoRouter.maybeOf(context)); }); } @override Widget build(BuildContext context) { + final ua = context.read(); final nav = context.watch(); final cfg = context.watch(); @@ -39,58 +46,101 @@ class _AppNavigationDrawerState extends State { 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), + ], + ), ); }, ); diff --git a/lib/widgets/navigation/app_scaffold.dart b/lib/widgets/navigation/app_scaffold.dart index af99974..00adf33 100644 --- a/lib/widgets/navigation/app_scaffold.dart +++ b/lib/widgets/navigation/app_scaffold.dart @@ -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, ); } }