diff --git a/lib/data/model/app/tab.dart b/lib/data/model/app/tab.dart index 36a3e2ed..9a0b6243 100644 --- a/lib/data/model/app/tab.dart +++ b/lib/data/model/app/tab.dart @@ -56,7 +56,41 @@ enum AppTab { }; } + NavigationRailDestination get navRailDestination { + return switch (this) { + server => NavigationRailDestination( + icon: const Icon(BoxIcons.bx_server), + label: Text(l10n.server), + selectedIcon: const Icon(BoxIcons.bxs_server), + ), + // settings => NavigationRailDestination( + // icon: const Icon(Icons.settings), + // label: libL10n.setting, + // selectedIcon: const Icon(Icons.settings), + // ), + ssh => const NavigationRailDestination( + icon: Icon(Icons.terminal_outlined), + label: Text('SSH'), + selectedIcon: Icon(Icons.terminal), + ), + snippet => NavigationRailDestination( + icon: const Icon(Icons.code), + label: Text(l10n.snippet), + selectedIcon: const Icon(Icons.code), + ), + file => NavigationRailDestination( + icon: const Icon(Icons.folder_open), + label: Text(libL10n.file), + selectedIcon: const Icon(Icons.folder), + ), + }; + } + static List get navDestinations { return AppTab.values.map((e) => e.navDestination).toList(); } + + static List get navRailDestinations { + return AppTab.values.map((e) => e.navRailDestination).toList(); + } } diff --git a/lib/view/page/home/home.dart b/lib/view/page/home/home.dart index e006d11c..f7a44a25 100644 --- a/lib/view/page/home/home.dart +++ b/lib/view/page/home/home.dart @@ -1,5 +1,6 @@ import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; import 'package:server_box/core/chan.dart'; import 'package:server_box/data/model/app/tab.dart'; import 'package:server_box/data/provider/app.dart'; @@ -26,7 +27,6 @@ class _HomePageState extends State late final PageController _pageController; final _selectIndex = ValueNotifier(0); - final _isLandscape = ValueNotifier(false); bool _switchingPage = false; bool _shouldAuth = false; @@ -40,7 +40,6 @@ class _HomePageState extends State WakelockPlus.disable(); _selectIndex.dispose(); - _isLandscape.dispose(); } @override @@ -58,13 +57,6 @@ class _HomePageState extends State } } - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _isLandscape.value = - MediaQuery.of(context).orientation == Orientation.landscape; - } - @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); @@ -102,56 +94,92 @@ class _HomePageState extends State AppProvider.ctx = context; final sysPadding = MediaQuery.of(context).padding; - return Scaffold( - appBar: _AppBar(sysPadding.top), - body: PageView.builder( - controller: _pageController, - itemCount: AppTab.values.length, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (_, index) => AppTab.values[index].page, - onPageChanged: (value) { - FocusScope.of(context).unfocus(); - if (!_switchingPage) { - _selectIndex.value = value; - } - }, - ), - bottomNavigationBar: ValBuilder( - listenable: _isLandscape, - builder: (ls) { - return Stores.setting.fullScreen.fetch() - ? UIs.placeholder - : ListenableBuilder( - listenable: _selectIndex, - builder: (_, __) => _buildBottomBar(ls), - ); - }, + return ColoredBox( + color: context.theme.colorScheme.surface, + child: AdaptiveLayout( + transitionDuration: const Duration(milliseconds: 250), + primaryNavigation: SlotLayout( + config: { + Breakpoints.medium: SlotLayout.from( + key: const Key('primaryNavigation'), + builder: (context) => _buildRailBar(), + ), + Breakpoints.mediumLarge: SlotLayout.from( + key: const Key('MediumLarge primaryNavigation'), + builder: (context) => _buildRailBar(extended: true), + ), + Breakpoints.large: SlotLayout.from( + key: const Key('Large primaryNavigation'), + builder: (context) => _buildRailBar(extended: true), + ), + Breakpoints.extraLarge: SlotLayout.from( + key: const Key('ExtraLarge primaryNavigation'), + builder: (context) => _buildRailBar(extended: true), + ), + }, + ), + body: SlotLayout( + config: { + Breakpoint.standard(): SlotLayout.from( + key: const Key('body'), + builder: (context) => Scaffold( + appBar: _AppBar(sysPadding.top), + body: PageView.builder( + controller: _pageController, + itemCount: AppTab.values.length, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (_, index) => AppTab.values[index].page, + onPageChanged: (value) { + FocusScope.of(context).unfocus(); + if (!_switchingPage) { + _selectIndex.value = value; + } + }, + ), + ), + ), + }, + ), + bottomNavigation: SlotLayout( + config: { + Breakpoints.small: SlotLayout.from( + key: const Key('bottomNavigation'), + builder: (context) => ListenableBuilder( + listenable: _selectIndex, + builder: (context, child) => _buildBottomBar(), + ), + ), + }, + ), ), ); } - Widget _buildBottomBar(bool ls) { - return NavigationBar( - selectedIndex: _selectIndex.value, - height: kBottomNavigationBarHeight * (ls ? 0.75 : 1.1), - animationDuration: const Duration(milliseconds: 250), - onDestinationSelected: (int index) { - if (_selectIndex.value == index) return; - _selectIndex.value = index; - _switchingPage = true; - _pageController.animateToPage( - index, - duration: const Duration(milliseconds: 677), - curve: Curves.fastLinearToSlowEaseIn, - ); - Future.delayed(const Duration(milliseconds: 677), () { - _switchingPage = false; - }); - }, - labelBehavior: ls - ? NavigationDestinationLabelBehavior.alwaysHide - : NavigationDestinationLabelBehavior.onlyShowSelected, - destinations: AppTab.navDestinations, + Widget _buildBottomBar() { + return ListenableBuilder( + listenable: _selectIndex, + builder: (context, child) => NavigationBar( + selectedIndex: _selectIndex.value, + height: kBottomNavigationBarHeight * 1.1, + animationDuration: const Duration(milliseconds: 250), + onDestinationSelected: _onDestinationSelected, + labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, + destinations: AppTab.navDestinations, + ), + ); + } + + Widget _buildRailBar({bool extended = false}) { + return ListenableBuilder( + listenable: _selectIndex, + builder: (context, child) => AdaptiveScaffold.standardNavigationRail( + extended: extended, + padding: EdgeInsets.zero, + selectedIndex: _selectIndex.value, + destinations: AppTab.navRailDestinations, + onDestinationSelected: _onDestinationSelected, + labelType: extended ? null : NavigationRailLabelType.selected, + ), ); } @@ -207,4 +235,18 @@ class _HomePageState extends State ); } } + + void _onDestinationSelected(int index) { + if (_selectIndex.value == index) return; + _selectIndex.value = index; + _switchingPage = true; + _pageController.animateToPage( + index, + duration: const Duration(milliseconds: 677), + curve: Curves.fastLinearToSlowEaseIn, + ); + Future.delayed(const Duration(milliseconds: 677), () { + _switchingPage = false; + }); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 1f570c38..25eb991c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,7 @@ dependencies: git: url: https://github.com/lppcg/fl_lib ref: v1.0.263 + flutter_adaptive_scaffold: ^0.3.2 dependency_overrides: # webdav_client_plus: