2024-04-30 23:38:49 +08:00
|
|
|
import 'dart:io';
|
|
|
|
|
|
2024-10-27 16:59:23 +08:00
|
|
|
import 'package:fl_clash/common/common.dart';
|
2025-10-14 15:13:52 +08:00
|
|
|
import 'package:fl_clash/models/config.dart';
|
2024-04-30 23:38:49 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2024-12-06 22:35:28 +08:00
|
|
|
import 'package:screen_retriever/screen_retriever.dart';
|
2024-04-30 23:38:49 +08:00
|
|
|
import 'package:window_manager/window_manager.dart';
|
|
|
|
|
|
|
|
|
|
class Window {
|
2025-12-16 11:23:09 +08:00
|
|
|
static Window? _instance;
|
|
|
|
|
|
|
|
|
|
Window._internal();
|
|
|
|
|
|
|
|
|
|
factory Window() {
|
|
|
|
|
_instance ??= Window._internal();
|
|
|
|
|
return _instance!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> init(int version, WindowProps props) async {
|
2024-12-03 21:47:12 +08:00
|
|
|
final acquire = await singleInstanceLock.acquire();
|
|
|
|
|
if (!acquire) {
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
2025-06-07 01:48:34 +08:00
|
|
|
if (system.isWindows) {
|
|
|
|
|
protocol.register('clash');
|
|
|
|
|
protocol.register('clashmeta');
|
|
|
|
|
protocol.register('flclash');
|
|
|
|
|
}
|
2024-04-30 23:38:49 +08:00
|
|
|
await windowManager.ensureInitialized();
|
2025-10-14 15:13:52 +08:00
|
|
|
// kDebugMode ? Size(680, 580) :
|
2024-07-15 22:06:09 +08:00
|
|
|
WindowOptions windowOptions = WindowOptions(
|
2025-10-14 15:13:52 +08:00
|
|
|
size: props.size,
|
2025-03-12 17:15:31 +08:00
|
|
|
minimumSize: const Size(380, 400),
|
2024-04-30 23:38:49 +08:00
|
|
|
);
|
2025-06-07 01:48:34 +08:00
|
|
|
if (!system.isMacOS || version > 10) {
|
2024-09-08 21:21:21 +08:00
|
|
|
await windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
2025-02-09 18:39:38 +08:00
|
|
|
}
|
2025-10-14 15:13:52 +08:00
|
|
|
await windowManager.setMaximizable(false);
|
|
|
|
|
await _windowPosition(props);
|
|
|
|
|
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
|
|
|
|
await windowManager.setPreventClose(true);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _windowPosition(WindowProps props) async {
|
2025-06-07 01:48:34 +08:00
|
|
|
if (!system.isMacOS) {
|
2024-12-06 22:35:28 +08:00
|
|
|
final left = props.left ?? 0;
|
|
|
|
|
final top = props.top ?? 0;
|
|
|
|
|
final right = left + props.width;
|
|
|
|
|
final bottom = top + props.height;
|
|
|
|
|
if (left == 0 && top == 0) {
|
|
|
|
|
await windowManager.setAlignment(Alignment.center);
|
|
|
|
|
} else {
|
|
|
|
|
final displays = await screenRetriever.getAllDisplays();
|
2025-07-31 17:09:18 +08:00
|
|
|
final isPositionValid = displays.any((display) {
|
|
|
|
|
final displayBounds = Rect.fromLTWH(
|
|
|
|
|
display.visiblePosition!.dx,
|
|
|
|
|
display.visiblePosition!.dy,
|
|
|
|
|
display.size.width,
|
|
|
|
|
display.size.height,
|
2024-12-06 22:35:28 +08:00
|
|
|
);
|
2025-07-31 17:09:18 +08:00
|
|
|
return displayBounds.contains(Offset(left, top)) ||
|
|
|
|
|
displayBounds.contains(Offset(right, bottom));
|
|
|
|
|
});
|
|
|
|
|
if (isPositionValid) {
|
|
|
|
|
await windowManager.setPosition(Offset(left, top));
|
2024-12-06 22:35:28 +08:00
|
|
|
}
|
|
|
|
|
}
|
2024-09-08 21:21:21 +08:00
|
|
|
}
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
Future<void> show() async {
|
2025-02-09 18:39:38 +08:00
|
|
|
render?.resume();
|
2024-04-30 23:38:49 +08:00
|
|
|
await windowManager.show();
|
|
|
|
|
await windowManager.focus();
|
2024-09-08 21:21:21 +08:00
|
|
|
await windowManager.setSkipTaskbar(false);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-12 17:15:31 +08:00
|
|
|
Future<bool> get isVisible async {
|
|
|
|
|
final value = await windowManager.isVisible();
|
2025-06-07 01:48:34 +08:00
|
|
|
commonPrint.log('window visible check: $value');
|
2025-03-12 17:15:31 +08:00
|
|
|
return value;
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
Future<void> close() async {
|
2025-12-16 11:23:09 +08:00
|
|
|
await windowManager.close();
|
2024-04-30 23:38:49 +08:00
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
Future<void> hide() async {
|
2025-02-09 18:39:38 +08:00
|
|
|
render?.pause();
|
2024-04-30 23:38:49 +08:00
|
|
|
await windowManager.hide();
|
2024-09-08 21:21:21 +08:00
|
|
|
await windowManager.setSkipTaskbar(true);
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final window = system.isDesktop ? Window() : null;
|