// 澶栧3璁剧疆鎸佷箙鍖?(W-CFG-01~03): %APPDATA%\com.iboard.app\shell-config.json // - 涓庡墠绔处鍙?鏈嶅姟绔棤鍏? 绂荤嚎鍙敤; // - 瀛楁缂哄け/鎹熷潖鏃跺洖閫€榛樿鍊?(serde(default) + 瀹芥澗鍔犺浇); // - 鍐欏叆閲囩敤 涓存椂鏂囦欢 + 鏇挎崲 鐨勫師瀛愯涔夈€? use serde::{Deserialize, Serialize}; use std::path::Path; pub const FILE_NAME: &str = "shell-config.json"; /// 璁捐鍩哄噯灏哄 (绉诲姩绔竷灞€鍙e緞): 绐楀彛姣斾緥閿佹涓?405:720 pub const DESIGN_WIDTH: f64 = 405.0; pub const DESIGN_HEIGHT: f64 = 720.0; /// 窗口宽度可配置范围 (逻辑像素); 高度由比例推导, 不接受单独配置 pub const WIDTH_MIN: f64 = 242.0; pub const WIDTH_MAX: f64 = 620.0; /// 鎸夐攣瀹氭瘮渚嬬敱瀹藉害鎺ㄥ楂樺害 (鍞竴灏哄鍏ュ彛) pub fn height_for_width(width: f64) -> f64 { let w = width.clamp(WIDTH_MIN, WIDTH_MAX); (w * DESIGN_HEIGHT / DESIGN_WIDTH).round() } /// 鍚搁檮杈?(W-SNP-01: 鍥涜竟) #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(rename_all = "lowercase")] pub enum Edge { #[default] Left, Right, Top, Bottom, } impl Edge { pub fn css(&self) -> &'static str { match self { Edge::Left => "left", Edge::Right => "right", Edge::Top => "top", Edge::Bottom => "bottom", } } } /// 涓荤獥鍙h蹇?(W-WIN-07): 灏哄涓洪€昏緫鍍忕礌 (DPI 绋冲畾), 浣嶇疆涓虹墿鐞嗗儚绱?(鍔犺浇鏃舵牎楠屽す鍙? #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default)] pub struct WindowCfg { pub width: f64, pub height: f64, pub x: Option, pub y: Option, } impl Default for WindowCfg { fn default() -> Self { // 323x574 = 405:720 姣斾緥 (0.797x of 405x720, 2026-10-26 鏀惧ぇ 12%) Self { width: 323.0, height: height_for_width(323.0), x: None, y: None } } } /// 鎮诞鐞冨仠闈?(W-SNP-02/12): 杈?+ 娌胯竟浣嶇疆 (鎮诞鐞冧腑蹇? 鐗╃悊鍍忕礌) #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default)] pub struct DockCfg { pub edge: Edge, pub offset: i32, } impl Default for DockCfg { fn default() -> Self { Self { edge: Edge::Left, offset: 360 } } } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default)] pub struct ShellConfig { /// 鍚搁檮鎬诲紑鍏?(W-SNP-09, 榛樿寮€鍚? pub snap_enabled: bool, pub window: WindowCfg, pub dock: DockCfg, /// 绐楀彛瀹藉害 (閫昏緫鍍忕礌) 鈥斺€?**鍞竴灏哄閰嶇疆椤?*銆? /// 楂樺害鎸?405:720 閿佸畾姣斾緥鑷姩鎺ㄥ, 鏃犻渶涔熸棤娉曞崟鐙厤缃? /// 鐣欑┖鏃跺洖钀藉埌 window.width銆? #[serde(default)] pub window_width: Option, /// 閰嶇疆缁撴瀯鐗堟湰: 0 = 鏃х増 (绐楀彛灏哄鎸?405x720 鍙e緞淇濆瓨), /// 1 = 鏁翠綋缂╁皬 30% (288 鍙e緞), 2 = 鏀惧ぇ 12% (323 鍙e緞) + 鍗曞€煎搴﹂厤缃€? /// load 鏃跺仛涓€娆℃€ц縼绉汇€? /// 娉ㄦ剰蹇呴』鐢ㄥ瓧娈电骇 serde(default) (u8 鈫?0): 瀹瑰櫒绾?default 浼氬彇 /// ShellConfig::default() 鐨?2, 鏃ч厤缃枃浠跺氨姘歌繙涓嶈縼绉讳簡銆? #[serde(default)] pub cfg_version: u8, } impl Default for ShellConfig { fn default() -> Self { Self { snap_enabled: true, window: WindowCfg::default(), dock: DockCfg::default(), window_width: Some(WindowCfg::default().width), cfg_version: 2, } } } /// 杩佺Щ鍓嶇殑绐楀彛瀹藉害 (鏃у彛寰?, 渚?load 浣跨敤 impl WindowCfg { /// 搴旂敤閿佸畾姣斾緥: 瀹藉害澶瑰彇鍒板悎娉曡寖鍥? 楂樺害鐢卞搴︽帹瀵?(蹇界暐瀛樼洏楂樺害) pub(crate) fn normalize(&mut self) { self.width = self.width.clamp(WIDTH_MIN, WIDTH_MAX); self.height = height_for_width(self.width); } } impl ShellConfig { pub fn load(dir: &Path) -> ShellConfig { let path = dir.join(FILE_NAME); let mut cfg = match std::fs::read_to_string(&path) { Ok(text) => match serde_json::from_str::(&text) { Ok(cfg) => cfg, Err(_) => ShellConfig::default(), // 鍐欏潖 JSON 鈫?榛樿鍊?(W-CFG-03) }, Err(_) => ShellConfig::default(), }; // 一次性迁移 if cfg.cfg_version < 1 { // v0 (405 鍙e緞) 鈫?v1: 鏁翠綋缂╁皬 30% cfg.window.width = (cfg.window.width * 0.7).max(216.0); cfg.window.height = (cfg.window.height * 0.7).max(384.0); cfg.cfg_version = 1; } if cfg.cfg_version < 2 { // v1 (288 口径) -> v2: 放大 12% (323 口径), 引入单值宽度配置 cfg.window.width = (cfg.window.width * 1.12).max(WIDTH_MIN); cfg.window.height = height_for_width(cfg.window.width); cfg.cfg_version = 2; } // 鍗曞€煎搴︿紭鍏? 楂樺害涓€寰嬫寜閿佸畾姣斾緥鎺ㄥ (蹇界暐瀛樼洏楂樺害) if let Some(w) = cfg.window_width { cfg.window.width = w; } cfg.window.normalize(); cfg.window_width = Some(cfg.window.width); cfg.save(dir); cfg } pub fn save(&self, dir: &Path) { let path = dir.join(FILE_NAME); let tmp = dir.join(format!("{FILE_NAME}.tmp")); let text = match serde_json::to_string_pretty(self) { Ok(t) => t, Err(_) => return, }; if std::fs::write(&tmp, text).is_ok() { // Windows 上 rename 不能覆盖已存在文件, 先移除 let _ = std::fs::remove_file(&path); let _ = std::fs::rename(&tmp, &path); } // 鍐欏け璐ヤ繚鎸侀潤榛?(W-CFG-04): 杩愯涓殑澶栧3涓嶅彈褰卞搷 } }