diff --git a/ui/flutter/lib/app/modules/app/controllers/app_controller.dart b/ui/flutter/lib/app/modules/app/controllers/app_controller.dart index 773c430d..1600136e 100644 --- a/ui/flutter/lib/app/modules/app/controllers/app_controller.dart +++ b/ui/flutter/lib/app/modules/app/controllers/app_controller.dart @@ -21,6 +21,7 @@ import '../../../../util/locale_manager.dart'; import '../../../../util/log_util.dart'; import '../../../../util/package_info.dart'; import '../../../../util/util.dart'; +import '../../../../util/window_util.dart' as windows_util; import '../../../routes/app_pages.dart'; const _startConfigNetwork = "start.network"; @@ -123,6 +124,26 @@ class AppController extends GetxController with WindowListener, TrayListener { trayManager.popUpContextMenu(); } + @override + void onWindowMaximize() { + windows_util.saveState(isMaximized: true); + } + + @override + void onWindowUnmaximize() { + windows_util.saveState(isMaximized: false); + } + + final _windowsResizeSave = Util.debounce(() async { + final size = await windowManager.getSize(); + windows_util.saveState(width: size.width, height: size.height); + }, 500); + + @override + void onWindowResize() { + _windowsResizeSave(); + } + Future _initDeepLinks() async { // currently only support android if (!Util.isAndroid()) { diff --git a/ui/flutter/lib/app/modules/create/views/create_view.dart b/ui/flutter/lib/app/modules/create/views/create_view.dart index 3b7da510..f3ec3e2b 100644 --- a/ui/flutter/lib/app/modules/create/views/create_view.dart +++ b/ui/flutter/lib/app/modules/create/views/create_view.dart @@ -4,16 +4,14 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:gopeed/app/modules/history/controller/history_controller.dart'; -import 'package:gopeed/app/modules/history/views/history_view.dart'; import 'package:path/path.dart' as path; import 'package:rounded_loading_button/rounded_loading_button.dart'; + import '../../../../api/api.dart'; import '../../../../api/model/create_task.dart'; import '../../../../api/model/options.dart'; import '../../../../api/model/request.dart'; import '../../../../api/model/resolve_result.dart'; -import '../../../../api/model/resource.dart'; import '../../../../util/input_formatter.dart'; import '../../../../util/message.dart'; import '../../../../util/util.dart'; @@ -21,6 +19,8 @@ import '../../../routes/app_pages.dart'; import '../../../views/directory_selector.dart'; import '../../../views/file_list_view.dart'; import '../../app/controllers/app_controller.dart'; +import '../../history/controller/history_controller.dart'; +import '../../history/views/history_view.dart'; import '../controllers/create_controller.dart'; class CreateView extends GetView { diff --git a/ui/flutter/lib/main.dart b/ui/flutter/lib/main.dart index 060e83f7..f3ce15b5 100644 --- a/ui/flutter/lib/main.dart +++ b/ui/flutter/lib/main.dart @@ -13,6 +13,7 @@ import 'util/log_util.dart'; import 'util/mac_secure_util.dart'; import 'util/package_info.dart'; import 'util/util.dart'; +import 'util/window_util.dart' as windows_util; void main() async { await init(); @@ -25,15 +26,21 @@ Future init() async { WidgetsFlutterBinding.ensureInitialized(); if (Util.isDesktop()) { await windowManager.ensureInitialized(); - const windowOptions = WindowOptions( - size: Size(800, 600), + final windowState = await windows_util.loadState(); + final windowOptions = WindowOptions( + size: Size(windowState.width, windowState.height), center: true, skipTaskbar: false, ); - windowManager.waitUntilReadyToShow(windowOptions, () async { + await windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.show(); await windowManager.focus(); await windowManager.setPreventClose(true); + // windows_manager has a bug where when window to be maximized, it will be unmaximized immediately, so can't implement this feature currently. + // https://github.com/leanflutter/window_manager/issues/412 + // if (windowState.isMaximized) { + // await windowManager.maximize(); + // } }); } diff --git a/ui/flutter/lib/util/util.dart b/ui/flutter/lib/util/util.dart index d808bd3c..821f4fa4 100644 --- a/ui/flutter/lib/util/util.dart +++ b/ui/flutter/lib/util/util.dart @@ -143,4 +143,12 @@ class Util { } return completer.future; } + + static void Function() debounce(Function() fn, int ms) { + Timer? timer; + return () { + timer?.cancel(); + timer = Timer(Duration(milliseconds: ms), fn); + }; + } } diff --git a/ui/flutter/lib/util/window_util.dart b/ui/flutter/lib/util/window_util.dart new file mode 100644 index 00000000..a37c8e7c --- /dev/null +++ b/ui/flutter/lib/util/window_util.dart @@ -0,0 +1,39 @@ +import 'dart:async'; + +import 'package:shared_preferences/shared_preferences.dart'; + +class WindowState { + late bool isMaximized; + late double width; + late double height; + + WindowState(this.isMaximized, this.width, this.height); +} + +const String _windowStateIsMaximized = "window.isMaximized"; +const String _windowStateWidth = "window.width"; +const String _windowStateHeight = "window.height"; + +/// Save window state to storage. +void saveState({bool? isMaximized, double? width, double? height}) async { + final prefs = await SharedPreferences.getInstance(); + if (isMaximized != null) { + await prefs.setBool(_windowStateIsMaximized, isMaximized); + } + if (width != null) { + await prefs.setDouble(_windowStateWidth, width); + } + if (height != null) { + await prefs.setDouble(_windowStateHeight, height); + } +} + +/// Load window state from storage. +Future loadState() async { + final prefs = await SharedPreferences.getInstance(); + return WindowState( + prefs.getBool(_windowStateIsMaximized) ?? false, + prefs.getDouble(_windowStateWidth) ?? 800, + prefs.getDouble(_windowStateHeight) ?? 600, + ); +}