From 177a22df59f355bf2952ee0452b220168ff0bcdf Mon Sep 17 00:00:00 2001
From: GyDi <zzzgydi@gmail.com>
Date: Sat, 22 Jul 2023 10:58:16 +0800
Subject: [PATCH] feat: save window size and position

---
 src-tauri/src/config/verge.rs  |  6 ++++
 src-tauri/src/core/tray.rs     |  2 ++
 src-tauri/src/main.rs          | 15 +++++++++
 src-tauri/src/utils/resolve.rs | 59 +++++++++++++++++++++++++++-------
 4 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs
index edd6616..be16c85 100644
--- a/src-tauri/src/config/verge.rs
+++ b/src-tauri/src/config/verge.rs
@@ -79,6 +79,10 @@ pub struct IVerge {
 
     /// proxy 页面布局 列数
     pub proxy_layout_column: Option<i32>,
+
+    /// window size and position
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub window_size_position: Option<Vec<f64>>,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
@@ -174,6 +178,8 @@ impl IVerge {
         patch!(enable_builtin_enhanced);
         patch!(proxy_layout_column);
         patch!(enable_clash_fields);
+
+        patch!(window_size_position);
     }
 
     /// 在初始化前尝试拿到单例端口的值
diff --git a/src-tauri/src/core/tray.rs b/src-tauri/src/core/tray.rs
index ab5d61b..0398735 100644
--- a/src-tauri/src/core/tray.rs
+++ b/src-tauri/src/core/tray.rs
@@ -141,6 +141,8 @@ impl Tray {
                 "restart_clash" => feat::restart_clash_core(),
                 "restart_app" => api::process::restart(&app_handle.env()),
                 "quit" => {
+                    let _ = resolve::save_window_size_position(app_handle);
+
                     resolve::resolve_reset();
                     api::process::kill_children();
                     app_handle.exit(0);
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 6d0f79e..a5d2efa 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -109,6 +109,8 @@ fn main() -> std::io::Result<()> {
                 match event {
                     tauri::WindowEvent::CloseRequested { api, .. } => {
                         api.prevent_close();
+                        let _ = resolve::save_window_size_position(&app_handle);
+
                         app_handle.get_window("main").map(|win| {
                             let _ = win.hide();
                         });
@@ -117,6 +119,19 @@ fn main() -> std::io::Result<()> {
                 }
             }
         }
+        #[cfg(not(target_os = "macos"))]
+        tauri::RunEvent::WindowEvent { label, event, .. } => {
+            use tauri::Manager;
+
+            if label == "main" {
+                match event {
+                    tauri::WindowEvent::CloseRequested { .. } => {
+                        let _ = resolve::save_window_size_position(&app_handle);
+                    }
+                    _ => {}
+                }
+            }
+        }
         _ => {}
     });
 
diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs
index f926293..d7ac245 100644
--- a/src-tauri/src/utils/resolve.rs
+++ b/src-tauri/src/utils/resolve.rs
@@ -1,6 +1,6 @@
-use crate::config::Config;
 use crate::log_err;
-use crate::{core::*, utils::init, utils::server};
+use crate::{config::Config, core::*, utils::init, utils::server};
+use anyhow::Result;
 use tauri::{App, AppHandle, Manager};
 
 /// handle something when start app
@@ -49,16 +49,39 @@ pub fn create_window(app_handle: &AppHandle) {
         return;
     }
 
-    let builder = tauri::window::WindowBuilder::new(
+    let mut builder = tauri::window::WindowBuilder::new(
         app_handle,
         "main".to_string(),
         tauri::WindowUrl::App("index.html".into()),
     )
     .title("Clash Verge")
-    .center()
     .fullscreen(false)
     .min_inner_size(600.0, 520.0);
 
+    match Config::verge().latest().window_size_position.clone() {
+        Some(size_pos) if size_pos.len() == 4 => {
+            let size = (size_pos[0], size_pos[1]);
+            let pos = (size_pos[2], size_pos[3]);
+            builder = builder.inner_size(size.0, size.1).position(pos.0, pos.1);
+        }
+        _ => {
+            #[cfg(target_os = "windows")]
+            {
+                builder = builder.inner_size(800.0, 636.0).center();
+            }
+
+            #[cfg(target_os = "macos")]
+            {
+                builder = builder.inner_size(800.0, 642.0).center();
+            }
+
+            #[cfg(target_os = "linux")]
+            {
+                builder = builder.inner_size(800.0, 642.0).center();
+            }
+        }
+    };
+
     #[cfg(target_os = "windows")]
     {
         use std::time::Duration;
@@ -68,7 +91,6 @@ pub fn create_window(app_handle: &AppHandle) {
         match builder
             .decorations(false)
             .transparent(true)
-            .inner_size(800.0, 636.0)
             .visible(false)
             .build()
         {
@@ -96,15 +118,30 @@ pub fn create_window(app_handle: &AppHandle) {
     #[cfg(target_os = "macos")]
     crate::log_err!(builder
         .decorations(true)
-        .inner_size(800.0, 642.0)
         .hidden_title(true)
         .title_bar_style(tauri::TitleBarStyle::Overlay)
         .build());
 
     #[cfg(target_os = "linux")]
-    crate::log_err!(builder
-        .decorations(true)
-        .transparent(false)
-        .inner_size(800.0, 642.0)
-        .build());
+    crate::log_err!(builder.decorations(true).transparent(false).build());
+}
+
+/// save window size and position
+pub fn save_window_size_position(app_handle: &AppHandle) -> Result<()> {
+    let win = app_handle
+        .get_window("main")
+        .ok_or(anyhow::anyhow!("failed to get window"))?;
+
+    let scale = win.scale_factor()?;
+    let size = win.inner_size()?;
+    let size = size.to_logical::<f64>(scale);
+    let pos = win.outer_position()?;
+    let pos = pos.to_logical::<f64>(scale);
+
+    let verge = Config::verge();
+    let mut verge = verge.latest();
+    verge.window_size_position = Some(vec![size.width, size.height, pos.x, pos.y]);
+    verge.save_file()?;
+
+    Ok(())
 }
-- 
GitLab