mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
feat: adaptive navigation bar (#739)
This commit is contained in:
@@ -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<NavigationDestination> get navDestinations {
|
||||
return AppTab.values.map((e) => e.navDestination).toList();
|
||||
}
|
||||
|
||||
static List<NavigationRailDestination> get navRailDestinations {
|
||||
return AppTab.values.map((e) => e.navRailDestination).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<HomePage>
|
||||
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<HomePage>
|
||||
WakelockPlus.disable();
|
||||
|
||||
_selectIndex.dispose();
|
||||
_isLandscape.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -58,13 +57,6 @@ class _HomePageState extends State<HomePage>
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_isLandscape.value =
|
||||
MediaQuery.of(context).orientation == Orientation.landscape;
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
@@ -102,7 +94,35 @@ class _HomePageState extends State<HomePage>
|
||||
AppProvider.ctx = context;
|
||||
final sysPadding = MediaQuery.of(context).padding;
|
||||
|
||||
return Scaffold(
|
||||
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,
|
||||
@@ -116,42 +136,50 @@ class _HomePageState extends State<HomePage>
|
||||
}
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: ValBuilder(
|
||||
listenable: _isLandscape,
|
||||
builder: (ls) {
|
||||
return Stores.setting.fullScreen.fetch()
|
||||
? UIs.placeholder
|
||||
: ListenableBuilder(
|
||||
listenable: _selectIndex,
|
||||
builder: (_, __) => _buildBottomBar(ls),
|
||||
);
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
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(
|
||||
Widget _buildBottomBar() {
|
||||
return ListenableBuilder(
|
||||
listenable: _selectIndex,
|
||||
builder: (context, child) => NavigationBar(
|
||||
selectedIndex: _selectIndex.value,
|
||||
height: kBottomNavigationBarHeight * (ls ? 0.75 : 1.1),
|
||||
height: kBottomNavigationBarHeight * 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,
|
||||
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<HomePage>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user