Files
umbrix/lib/core/router/app_router.dart
Umbrix Developer 43ab81e8d1 fix: icon permissions and GTK single instance
- Use GTK default flags for single instance
- Fix icon path to absolute /usr/share/icons
- Add postinstall chmod 644 for icon
- Remove Dart-level single instance code
2026-01-17 20:10:04 +03:00

123 lines
3.9 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:umbrix/core/preferences/general_preferences.dart';
import 'package:umbrix/core/router/routes.dart';
import 'package:umbrix/features/deep_link/notifier/deep_link_notifier.dart';
import 'package:umbrix/utils/utils.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
part 'app_router.g.dart';
bool _debugMobileRouter = false;
final useMobileRouter = !PlatformUtils.isDesktop || (kDebugMode && _debugMobileRouter);
final GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
// TODO: test and improve handling of deep link
@riverpod
GoRouter router(RouterRef ref) {
final notifier = ref.watch(routerListenableProvider.notifier);
final deepLink = ref.listen(
deepLinkNotifierProvider,
(_, next) async {
if (next case AsyncData(value: final link?)) {
await ref.state.push(AddProfileRoute(url: link.url).location);
}
},
);
final initialLink = deepLink.read();
String initialLocation = const HomeRoute().location;
if (initialLink case AsyncData(value: final link?)) {
initialLocation = AddProfileRoute(url: link.url).location;
}
return GoRouter(
navigatorKey: rootNavigatorKey,
initialLocation: initialLocation,
debugLogDiagnostics: true,
routes: [
if (useMobileRouter) $mobileWrapperRoute else $desktopWrapperRoute,
$introRoute,
],
refreshListenable: notifier,
redirect: notifier.redirect,
observers: [
SentryNavigatorObserver(),
],
);
}
final tabLocations = [
const HomeRoute().location, // 0: Главная
const ProxiesRoute().location, // 1: Локации
const PerAppProxyRoute().location, // 2: Исключения
const SettingsRoute().location, // 3: Настройки
const AboutRoute().location, // 4: О программе
];
int getCurrentIndex(BuildContext context) {
final String location = GoRouterState.of(context).uri.path;
// Проверяем точное совпадение для главной
if (location == const HomeRoute().location) return 0;
// Проверяем остальные маршруты по порядку
// ВАЖНО: более длинные пути проверяем раньше!
if (location.startsWith(const PerAppProxyRoute().location)) return 2; // /settings/per-app-proxy
if (location.startsWith(const ProxiesRoute().location)) return 1; // /proxies
if (location.startsWith(const SettingsRoute().location)) return 3; // /settings
if (location.startsWith(const AboutRoute().location)) return 4; // /about
return 0;
}
void switchTab(int index, BuildContext context) {
assert(index >= 0 && index < tabLocations.length);
final location = tabLocations[index];
return context.go(location);
}
@riverpod
class RouterListenable extends _$RouterListenable with AppLogger implements Listenable {
VoidCallback? _routerListener;
bool _introCompleted = false;
@override
Future<void> build() async {
_introCompleted = ref.watch(Preferences.introCompleted);
ref.listenSelf((_, __) {
if (state.isLoading) return;
loggy.debug("triggering listener");
_routerListener?.call();
});
}
// ignore: avoid_build_context_in_providers
String? redirect(BuildContext context, GoRouterState state) {
// if (this.state.isLoading || this.state.hasError) return null;
final isIntro = state.uri.path == const IntroRoute().location;
if (!_introCompleted) {
return const IntroRoute().location;
} else if (isIntro) {
return const HomeRoute().location;
}
return null;
}
@override
void addListener(VoidCallback listener) {
_routerListener = listener;
}
@override
void removeListener(VoidCallback listener) {
_routerListener = null;
}
}