Refactor desktop window management and tray
This commit is contained in:
54
lib/features/window/notifier/window_notifier.dart
Normal file
54
lib/features/window/notifier/window_notifier.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:hiddify/core/app_info/app_info_provider.dart';
|
||||
import 'package:hiddify/core/model/constants.dart';
|
||||
import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:tray_manager/tray_manager.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
part 'window_notifier.g.dart';
|
||||
|
||||
const minimumWindowSize = Size(368, 568);
|
||||
const defaultWindowSize = Size(868, 668);
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class WindowNotifier extends _$WindowNotifier with AppLogger {
|
||||
@override
|
||||
Future<void> build() async {
|
||||
if (!PlatformUtils.isDesktop) return;
|
||||
|
||||
await windowManager.ensureInitialized();
|
||||
await windowManager.setMinimumSize(minimumWindowSize);
|
||||
await windowManager.setSize(defaultWindowSize);
|
||||
|
||||
final appInfo = await ref.watch(appInfoProvider.future);
|
||||
await windowManager
|
||||
.setTitle("${Constants.appName} v${appInfo.presentVersion}");
|
||||
}
|
||||
|
||||
Future<void> open({bool focus = true}) async {
|
||||
await windowManager.show();
|
||||
if (focus) await windowManager.focus();
|
||||
}
|
||||
|
||||
// TODO add option to quit or minimize to tray
|
||||
Future<void> close() async {
|
||||
await windowManager.hide();
|
||||
}
|
||||
|
||||
Future<void> quit() async {
|
||||
await ref
|
||||
.read(connectionNotifierProvider.notifier)
|
||||
.abortConnection()
|
||||
.timeout(const Duration(seconds: 2))
|
||||
.catchError(
|
||||
(e) {
|
||||
loggy.warning("error aborting connection on quit", e);
|
||||
},
|
||||
);
|
||||
await trayManager.destroy();
|
||||
await windowManager.destroy();
|
||||
}
|
||||
}
|
||||
54
lib/features/window/widget/window_wrapper.dart
Normal file
54
lib/features/window/widget/window_wrapper.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/features/window/notifier/window_notifier.dart';
|
||||
import 'package:hiddify/utils/custom_loggers.dart';
|
||||
import 'package:hiddify/utils/platform_utils.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class WindowWrapper extends StatefulHookConsumerWidget {
|
||||
const WindowWrapper(this.child, {super.key});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
ConsumerState<ConsumerStatefulWidget> createState() => _WindowWrapperState();
|
||||
}
|
||||
|
||||
class _WindowWrapperState extends ConsumerState<WindowWrapper>
|
||||
with WindowListener, AppLogger {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ref.watch(windowNotifierProvider);
|
||||
|
||||
return widget.child;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
windowManager.addListener(this);
|
||||
if (PlatformUtils.isDesktop) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await windowManager.setPreventClose(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
windowManager.removeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onWindowClose() async {
|
||||
await ref.read(windowNotifierProvider.notifier).close();
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowFocus() {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user