backup: before proxies page modernization

This commit is contained in:
Hiddify User
2025-12-26 02:39:35 +03:00
parent 6e73e53fb6
commit 063f2464ee
25 changed files with 1395 additions and 609 deletions

View File

@@ -9,8 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
abstract interface class RootScaffold {
static final stateKey = GlobalKey<ScaffoldState>();
static bool canShowDrawer(BuildContext context) =>
Breakpoints.small.isActive(context);
static bool canShowDrawer(BuildContext context) => Breakpoints.small.isActive(context);
}
class AdaptiveRootScaffold extends HookConsumerWidget {
@@ -26,13 +25,20 @@ class AdaptiveRootScaffold extends HookConsumerWidget {
final destinations = [
NavigationDestination(
icon: const Icon(FluentIcons.power_20_filled),
icon: const Icon(FluentIcons.home_20_regular),
selectedIcon: const Icon(FluentIcons.home_20_filled),
label: t.home.pageTitle,
),
NavigationDestination(
icon: const Icon(FluentIcons.filter_20_filled),
icon: const Icon(FluentIcons.list_20_regular),
selectedIcon: const Icon(FluentIcons.list_20_filled),
label: t.proxies.pageTitle,
),
NavigationDestination(
icon: const Icon(FluentIcons.more_vertical_20_regular),
selectedIcon: const Icon(FluentIcons.more_vertical_20_filled),
label: t.settings.network.excludedDomains.pageTitle,
),
NavigationDestination(
icon: const Icon(FluentIcons.box_edit_20_filled),
label: t.config.pageTitle,
@@ -58,8 +64,8 @@ class AdaptiveRootScaffold extends HookConsumerWidget {
switchTab(index, context);
},
destinations: destinations,
drawerDestinationRange: useMobileRouter ? (2, null) : (0, null),
bottomDestinationRange: (0, 2),
drawerDestinationRange: useMobileRouter ? (3, null) : (0, null),
bottomDestinationRange: (0, 3),
useBottomSheet: useMobileRouter,
sidebarTrailing: const Expanded(
child: Align(
@@ -93,18 +99,14 @@ class _CustomAdaptiveScaffold extends HookConsumerWidget {
final Widget? sidebarTrailing;
final Widget body;
List<NavigationDestination> destinationsSlice((int, int?) range) =>
destinations.sublist(range.$1, range.$2);
List<NavigationDestination> destinationsSlice((int, int?) range) => destinations.sublist(range.$1, range.$2);
int? selectedWithOffset((int, int?) range) {
final index = selectedIndex - range.$1;
return index < 0 || (range.$2 != null && index > (range.$2! - 1))
? null
: index;
return index < 0 || (range.$2 != null && index > (range.$2! - 1)) ? null : index;
}
void selectWithOffset(int index, (int, int?) range) =>
onSelectedIndexChange(index + range.$1);
void selectWithOffset(int index, (int, int?) range) => onSelectedIndexChange(index + range.$1);
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -113,14 +115,67 @@ class _CustomAdaptiveScaffold extends HookConsumerWidget {
drawer: Breakpoints.small.isActive(context)
? Drawer(
width: (MediaQuery.sizeOf(context).width * 0.88).clamp(1, 304),
child: NavigationRail(
extended: true,
selectedIndex: selectedWithOffset(drawerDestinationRange),
destinations: destinationsSlice(drawerDestinationRange)
.map((dest) => AdaptiveScaffold.toRailDestination(dest))
.toList(),
onDestinationSelected: (index) =>
selectWithOffset(index, drawerDestinationRange),
child: Column(
children: [
// Логотип и название приложения
Container(
padding: const EdgeInsets.symmetric(vertical: 32),
child: Column(
children: [
Container(
width: 96,
height: 96,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Theme.of(context).colorScheme.primaryContainer,
),
child: Icon(
Icons.shield_outlined,
size: 56,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(height: 16),
Text(
'Umbrix',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
],
),
),
// Список пунктов меню
Expanded(
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16),
children: [
// Главная
_DrawerMenuItem(
icon: FluentIcons.home_20_regular,
selectedIcon: FluentIcons.home_20_filled,
label: destinationsSlice(drawerDestinationRange)[0].label,
isSelected: selectedWithOffset(drawerDestinationRange) == 0,
onTap: () => selectWithOffset(0, drawerDestinationRange),
),
// Остальные пункты
...List.generate(
destinationsSlice(drawerDestinationRange).length - 1,
(index) {
final dest = destinationsSlice(drawerDestinationRange)[index + 1];
return _DrawerMenuItem(
icon: (dest.icon as Icon).icon!,
selectedIcon: dest.selectedIcon != null ? (dest.selectedIcon as Icon).icon! : (dest.icon as Icon).icon!,
label: dest.label,
isSelected: selectedWithOffset(drawerDestinationRange) == index + 1,
onTap: () => selectWithOffset(index + 1, drawerDestinationRange),
);
},
),
],
),
),
],
),
)
: null,
@@ -131,9 +186,7 @@ class _CustomAdaptiveScaffold extends HookConsumerWidget {
key: const Key('primaryNavigation'),
builder: (_) => AdaptiveScaffold.standardNavigationRail(
selectedIndex: selectedIndex,
destinations: destinations
.map((dest) => AdaptiveScaffold.toRailDestination(dest))
.toList(),
destinations: destinations.map((dest) => AdaptiveScaffold.toRailDestination(dest)).toList(),
onDestinationSelected: onSelectedIndexChange,
),
),
@@ -142,9 +195,7 @@ class _CustomAdaptiveScaffold extends HookConsumerWidget {
builder: (_) => AdaptiveScaffold.standardNavigationRail(
extended: true,
selectedIndex: selectedIndex,
destinations: destinations
.map((dest) => AdaptiveScaffold.toRailDestination(dest))
.toList(),
destinations: destinations.map((dest) => AdaptiveScaffold.toRailDestination(dest)).toList(),
onDestinationSelected: onSelectedIndexChange,
trailing: sidebarTrailing,
),
@@ -167,10 +218,52 @@ class _CustomAdaptiveScaffold extends HookConsumerWidget {
? NavigationBar(
selectedIndex: selectedWithOffset(bottomDestinationRange) ?? 0,
destinations: destinationsSlice(bottomDestinationRange),
onDestinationSelected: (index) =>
selectWithOffset(index, bottomDestinationRange),
onDestinationSelected: (index) => selectWithOffset(index, bottomDestinationRange),
)
: null,
);
}
}
class _DrawerMenuItem extends StatelessWidget {
const _DrawerMenuItem({
required this.icon,
required this.selectedIcon,
required this.label,
required this.isSelected,
required this.onTap,
});
final IconData icon;
final IconData selectedIcon;
final String label;
final bool isSelected;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 4),
child: ListTile(
leading: Icon(
isSelected ? selectedIcon : icon,
size: 24,
),
title: Text(
label,
style: TextStyle(
fontSize: 16,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
),
),
selected: isSelected,
selectedTileColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
onTap: onTap,
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
),
);
}
}