mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 12:34:22 +08:00
fix: 字体选择列表加载不了的问题
feat: 整理项目文件
This commit is contained in:
Binary file not shown.
@@ -1,6 +1,8 @@
|
||||
use parking_lot::RwLock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::collections::BTreeSet;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use tauri::{AppHandle, Emitter, State};
|
||||
|
||||
@@ -158,3 +160,135 @@ pub async fn settings_set(
|
||||
|
||||
Ok(IpcResponse::success(()))
|
||||
}
|
||||
|
||||
fn fallback_font_families() -> Vec<String> {
|
||||
vec![
|
||||
"系统默认".to_string(),
|
||||
"Microsoft YaHei UI".to_string(),
|
||||
"Microsoft YaHei".to_string(),
|
||||
"PingFang SC".to_string(),
|
||||
"Noto Sans CJK SC".to_string(),
|
||||
"Source Han Sans SC".to_string(),
|
||||
"Segoe UI".to_string(),
|
||||
"Arial".to_string(),
|
||||
"Helvetica Neue".to_string(),
|
||||
]
|
||||
}
|
||||
|
||||
fn normalize_font_name(value: &str) -> String {
|
||||
value
|
||||
.trim()
|
||||
.trim_start_matches('@')
|
||||
.replace(" (TrueType)", "")
|
||||
.replace(" (OpenType)", "")
|
||||
.replace(" (All res)", "")
|
||||
.trim()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn query_system_fonts() -> Vec<String> {
|
||||
let output = Command::new("reg")
|
||||
.args([
|
||||
"query",
|
||||
r"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts",
|
||||
])
|
||||
.output();
|
||||
|
||||
let Ok(output) = output else {
|
||||
return Vec::new();
|
||||
};
|
||||
if !output.status.success() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut families = BTreeSet::new();
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
for line in stdout.lines() {
|
||||
if !line.contains("REG_") {
|
||||
continue;
|
||||
}
|
||||
let Some((left, _)) = line.split_once("REG_") else {
|
||||
continue;
|
||||
};
|
||||
let name = normalize_font_name(left);
|
||||
if !name.is_empty() {
|
||||
families.insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
families.into_iter().collect()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn query_system_fonts() -> Vec<String> {
|
||||
let output = Command::new("fc-list").args([":", "family"]).output();
|
||||
let Ok(output) = output else {
|
||||
return Vec::new();
|
||||
};
|
||||
if !output.status.success() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut families = BTreeSet::new();
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
for line in stdout.lines() {
|
||||
for part in line.split(',') {
|
||||
let name = normalize_font_name(part);
|
||||
if !name.is_empty() {
|
||||
families.insert(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
families.into_iter().collect()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn query_system_fonts() -> Vec<String> {
|
||||
let output = Command::new("system_profiler")
|
||||
.args(["SPFontsDataType", "-detailLevel", "mini"])
|
||||
.output();
|
||||
let Ok(output) = output else {
|
||||
return Vec::new();
|
||||
};
|
||||
if !output.status.success() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut families = BTreeSet::new();
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
for line in stdout.lines() {
|
||||
let trimmed = line.trim();
|
||||
if let Some(name) = trimmed.strip_prefix("Full Name:") {
|
||||
let normalized = normalize_font_name(name);
|
||||
if !normalized.is_empty() {
|
||||
families.insert(normalized);
|
||||
}
|
||||
}
|
||||
}
|
||||
families.into_iter().collect()
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "windows", target_os = "linux", target_os = "macos")))]
|
||||
fn query_system_fonts() -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn settings_get_system_fonts() -> Result<IpcResponse<Vec<String>>, String> {
|
||||
let mut fonts = query_system_fonts();
|
||||
if fonts.is_empty() {
|
||||
fonts = fallback_font_families();
|
||||
} else {
|
||||
let mut merged = BTreeSet::new();
|
||||
for item in fallback_font_families() {
|
||||
merged.insert(item);
|
||||
}
|
||||
for item in fonts {
|
||||
merged.insert(item);
|
||||
}
|
||||
fonts = merged.into_iter().collect();
|
||||
}
|
||||
|
||||
Ok(IpcResponse::success(fonts))
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ pub fn run() {
|
||||
settings_get_all,
|
||||
settings_get,
|
||||
settings_set,
|
||||
settings_get_system_fonts,
|
||||
auth_get_status,
|
||||
auth_login,
|
||||
auth_logout,
|
||||
@@ -155,7 +156,11 @@ fn setup_deep_link(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use tauri_plugin_deep_link::DeepLinkExt;
|
||||
|
||||
app.deep_link().on_open_url(move |event| {
|
||||
let url = event.urls().first().map(|u| u.to_string()).unwrap_or_default();
|
||||
let url = event
|
||||
.urls()
|
||||
.first()
|
||||
.map(|u| u.to_string())
|
||||
.unwrap_or_default();
|
||||
if !url.is_empty() {
|
||||
let _ = handle.emit("deep-link://new-url", url);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub struct SettingsSpec {
|
||||
pub window_zoom: f64,
|
||||
pub search_keyboard_layout: String,
|
||||
pub disable_search_keyboard: bool,
|
||||
pub font_family: String,
|
||||
pub themes_custom: JsonValue,
|
||||
pub auto_score_enabled: bool,
|
||||
pub auto_score_rules: JsonValue,
|
||||
@@ -28,6 +29,7 @@ impl Default for SettingsSpec {
|
||||
window_zoom: 1.0,
|
||||
search_keyboard_layout: "qwerty26".to_string(),
|
||||
disable_search_keyboard: false,
|
||||
font_family: "system".to_string(),
|
||||
themes_custom: JsonValue::Array(vec![]),
|
||||
auto_score_enabled: false,
|
||||
auto_score_rules: JsonValue::Array(vec![]),
|
||||
@@ -58,6 +60,7 @@ pub enum SettingsKey {
|
||||
WindowZoom,
|
||||
SearchKeyboardLayout,
|
||||
DisableSearchKeyboard,
|
||||
FontFamily,
|
||||
ThemesCustom,
|
||||
AutoScoreEnabled,
|
||||
AutoScoreRules,
|
||||
@@ -76,6 +79,7 @@ impl SettingsKey {
|
||||
SettingsKey::WindowZoom => "window_zoom",
|
||||
SettingsKey::SearchKeyboardLayout => "search_keyboard_layout",
|
||||
SettingsKey::DisableSearchKeyboard => "disable_search_keyboard",
|
||||
SettingsKey::FontFamily => "font_family",
|
||||
SettingsKey::ThemesCustom => "themes_custom",
|
||||
SettingsKey::AutoScoreEnabled => "auto_score_enabled",
|
||||
SettingsKey::AutoScoreRules => "auto_score_rules",
|
||||
@@ -94,6 +98,7 @@ impl SettingsKey {
|
||||
"window_zoom" => Some(SettingsKey::WindowZoom),
|
||||
"search_keyboard_layout" => Some(SettingsKey::SearchKeyboardLayout),
|
||||
"disable_search_keyboard" => Some(SettingsKey::DisableSearchKeyboard),
|
||||
"font_family" => Some(SettingsKey::FontFamily),
|
||||
"themes_custom" => Some(SettingsKey::ThemesCustom),
|
||||
"auto_score_enabled" => Some(SettingsKey::AutoScoreEnabled),
|
||||
"auto_score_rules" => Some(SettingsKey::AutoScoreRules),
|
||||
@@ -327,6 +332,22 @@ impl SettingsService {
|
||||
},
|
||||
);
|
||||
|
||||
defs.insert(
|
||||
SettingsKey::FontFamily,
|
||||
SettingDefinition {
|
||||
kind: SettingValueKind::String,
|
||||
default_value: SettingsValue::String("system".to_string()),
|
||||
write_permission: PermissionRequirement::Admin,
|
||||
validate: Some(|v| {
|
||||
if let SettingsValue::String(s) = v {
|
||||
!s.trim().is_empty()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
defs.insert(
|
||||
SettingsKey::ThemesCustom,
|
||||
SettingDefinition {
|
||||
@@ -549,6 +570,10 @@ impl SettingsService {
|
||||
SettingsValue::Boolean(b) => b,
|
||||
_ => false,
|
||||
},
|
||||
font_family: match self.get_value(SettingsKey::FontFamily) {
|
||||
SettingsValue::String(s) => s,
|
||||
_ => "system".to_string(),
|
||||
},
|
||||
themes_custom: match self.get_value(SettingsKey::ThemesCustom) {
|
||||
SettingsValue::Json(j) => j,
|
||||
_ => JsonValue::Array(vec![]),
|
||||
|
||||
Reference in New Issue
Block a user