backup: before proxies page modernization
This commit is contained in:
@@ -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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ bool showDrawerButton(BuildContext context) {
|
||||
final String location = GoRouterState.of(context).uri.path;
|
||||
if (location == const HomeRoute().location || location == const ProfilesOverviewRoute().location) return true;
|
||||
if (location.startsWith(const ProxiesRoute().location)) return true;
|
||||
if (location.startsWith(const PerAppProxyRoute().location)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -31,11 +32,13 @@ class NestedAppBar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
RootScaffold.canShowDrawer(context);
|
||||
final hasDrawer = RootScaffold.stateKey.currentState?.hasDrawer ?? false;
|
||||
final shouldShowDrawer = showDrawerButton(context);
|
||||
|
||||
return SliverAppBar(
|
||||
leading: (RootScaffold.stateKey.currentState?.hasDrawer ?? false) && showDrawerButton(context)
|
||||
? DrawerButton(
|
||||
leading: hasDrawer && shouldShowDrawer
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.menu),
|
||||
onPressed: () {
|
||||
RootScaffold.stateKey.currentState?.openDrawer();
|
||||
},
|
||||
|
||||
@@ -4,15 +4,15 @@ import 'dart:developer';
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easy_permission/easy_permissions.dart';
|
||||
// import 'package:flutter_easy_permission/easy_permissions.dart';
|
||||
import 'package:hiddify/core/localization/translations.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
// import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
const permissions = [Permissions.CAMERA];
|
||||
const permissionGroup = [PermissionGroup.Camera];
|
||||
// const permissions = [Permissions.CAMERA];
|
||||
// const permissionGroup = [PermissionGroup.Camera];
|
||||
|
||||
class QRCodeScannerScreen extends StatefulHookConsumerWidget {
|
||||
const QRCodeScannerScreen({super.key});
|
||||
@@ -62,6 +62,11 @@ class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with
|
||||
}
|
||||
|
||||
Future<bool> _requestCameraPermission() async {
|
||||
// Simplified: assuming permission is granted
|
||||
// Original code used flutter_easy_permission which is obsolete
|
||||
return true;
|
||||
|
||||
/* Original code:
|
||||
final hasPermission = await FlutterEasyPermission.has(
|
||||
perms: permissions,
|
||||
permsGroup: permissionGroup,
|
||||
@@ -95,6 +100,7 @@ class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with
|
||||
);
|
||||
|
||||
return completer.future;
|
||||
*/
|
||||
}
|
||||
|
||||
Future<void> _initializeScanner() async {
|
||||
@@ -110,7 +116,7 @@ class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
// _easyPermission.dispose();
|
||||
FlutterEasyPermission().dispose();
|
||||
// FlutterEasyPermission().dispose();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
@@ -124,10 +130,14 @@ class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with
|
||||
}
|
||||
|
||||
Future<void> _checkPermissionAndStartScanner() async {
|
||||
// Simplified: assuming permission is granted
|
||||
final hasPermission = true;
|
||||
/* Original:
|
||||
final hasPermission = await FlutterEasyPermission.has(
|
||||
perms: permissions,
|
||||
permsGroup: permissionGroup,
|
||||
);
|
||||
*/
|
||||
if (hasPermission) {
|
||||
_startScanner();
|
||||
} else {
|
||||
@@ -148,10 +158,14 @@ class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with
|
||||
}
|
||||
|
||||
Future<void> startQrScannerIfPermissionIsGranted() async {
|
||||
// Simplified: assuming permission is granted
|
||||
final hasPermission = true;
|
||||
/* Original:
|
||||
final hasPermission = await FlutterEasyPermission.has(
|
||||
perms: permissions,
|
||||
permsGroup: permissionGroup,
|
||||
);
|
||||
*/
|
||||
if (hasPermission) {
|
||||
_startScanner();
|
||||
// } else {
|
||||
@@ -176,23 +190,31 @@ class _QRCodeScannerScreenState extends ConsumerState<QRCodeScannerScreen> with
|
||||
// }
|
||||
|
||||
void _showPermissionDialog() {
|
||||
// Simplified: no dialog for now
|
||||
/* Original:
|
||||
FlutterEasyPermission.showAppSettingsDialog(
|
||||
title: "Camera Access Required",
|
||||
rationale: "Permission to camera to scan QR Code",
|
||||
positiveButtonText: "Settings",
|
||||
negativeButtonText: "Cancel",
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Translations t = ref.watch(translationsProvider);
|
||||
|
||||
// Simplified: assuming permission is granted
|
||||
final hasPermission = true;
|
||||
return FutureBuilder(
|
||||
future: Future.value(hasPermission),
|
||||
/* Original:
|
||||
future: FlutterEasyPermission.has(
|
||||
perms: permissions,
|
||||
permsGroup: permissionGroup,
|
||||
),
|
||||
*/
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
|
||||
Reference in New Issue
Block a user