From 20953493c45cadd0b4bbe975c4c928f7db066ff5 Mon Sep 17 00:00:00 2001
From: wael <2287560043@qq.com>
Date: Sat, 1 Aug 2026 20:03:29 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=B9macos=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E6=B5=85=E8=89=B2=E5=92=8C=E6=B7=B1=E8=89=B2=E6=A8=A1=E5=BC=8F?=
=?UTF-8?q?=E5=88=87=E6=8D=A2=E6=A8=A1=E5=9E=8B=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src-tauri/src/core/setup/mod.rs | 3 -
src/App.vue | 56 ++++++++++++++++++-
src/locales/en-US.json | 2 +
src/locales/pt-BR.json | 2 +
src/locales/vi-VN.json | 2 +
src/locales/zh-CN.json | 2 +
src/locales/zh-TW.json | 2 +
.../general/components/theme-mode/index.vue | 30 +---------
.../preference/components/model/index.vue | 31 +++++++++-
src/stores/model.ts | 6 ++
10 files changed, 101 insertions(+), 35 deletions(-)
diff --git a/src-tauri/src/core/setup/mod.rs b/src-tauri/src/core/setup/mod.rs
index d761c7a81..eb15a45fd 100644
--- a/src-tauri/src/core/setup/mod.rs
+++ b/src-tauri/src/core/setup/mod.rs
@@ -17,8 +17,5 @@ pub fn default(
main_window: WebviewWindow,
preference_window: WebviewWindow,
) {
- #[cfg(debug_assertions)]
- main_window.open_devtools();
-
platform(app_handle, main_window.clone(), preference_window.clone());
}
diff --git a/src/App.vue b/src/App.vue
index 321c4fb60..45f022f1e 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -7,7 +7,7 @@ import { useEventListener } from '@vueuse/core'
import { ConfigProvider, theme } from 'antdv-next'
import { isString } from 'es-toolkit'
import isURL from 'is-url'
-import { onMounted, watch } from 'vue'
+import { onMounted, onUnmounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { RouterView } from 'vue-router'
@@ -31,6 +31,35 @@ const appWindow = getCurrentWebviewWindow()
const { isRestored, restoreState } = useWindowState()
const { darkAlgorithm, defaultAlgorithm } = theme
const { locale } = useI18n()
+const themeReady = ref(false)
+let unlistenTheme: (() => void) | undefined
+
+function applyThemeModel(isDark: boolean) {
+ if (appWindow.label !== 'main') return
+ if (generalStore.appearance.theme !== 'auto') return
+
+ const modelId = isDark ? modelStore.darkModelId : modelStore.lightModelId
+ const model = modelStore.models.find(item => item.id === modelId)
+
+ if (!model || model.id === modelStore.currentModel?.id) return
+
+ modelStore.modelReady = false
+ modelStore.currentModel = model
+}
+
+function applyResolvedTheme(isDark: boolean) {
+ generalStore.appearance.isDark = isDark
+ document.documentElement.classList.toggle('dark', isDark)
+ applyThemeModel(isDark)
+}
+
+async function applyTheme(value: 'auto' | 'light' | 'dark') {
+ const nextTheme = value === 'auto' ? null : value
+
+ await appWindow.setTheme(nextTheme)
+
+ applyResolvedTheme((nextTheme ?? (await appWindow.theme())) === 'dark')
+}
onMounted(async () => {
await appStore.$tauri.start()
@@ -42,7 +71,30 @@ onMounted(async () => {
await generalStore.$tauri.start()
await generalStore.init()
await shortcutStore.$tauri.start()
+
+ themeReady.value = true
+ await applyTheme(generalStore.appearance.theme)
await restoreState()
+
+ unlistenTheme = await appWindow.onThemeChanged(({ payload }) => {
+ if (generalStore.appearance.theme !== 'auto') return
+
+ applyResolvedTheme(payload === 'dark')
+ })
+})
+
+onUnmounted(() => unlistenTheme?.())
+
+watch(() => generalStore.appearance.theme, (value) => {
+ if (!themeReady.value) return
+
+ applyTheme(value)
+})
+
+watch([() => modelStore.lightModelId, () => modelStore.darkModelId], () => {
+ if (!themeReady.value) return
+
+ applyThemeModel(generalStore.appearance.isDark)
})
watch(() => generalStore.appearance.language, (value) => {
@@ -62,7 +114,7 @@ useTauriListen(LISTEN_KEY.HIDE_WINDOW, ({ payload }) => {
})
useEventListener('unhandledrejection', ({ reason }) => {
- const message = isString(reason) ? reason : JSON.stringify(reason)
+ const message = isString(reason) ? reason : reason instanceof Error ? `${reason.name}: ${reason.message}\n${reason.stack ?? ''}` : JSON.stringify(reason)
error(message)
})
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 15172d14e..57252c727 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -97,6 +97,8 @@
"clickOrDragToImport": "Click or drag here to import"
},
"tooltips": {
+ "lightModel": "Use in light mode (click again to clear)",
+ "darkModel": "Use in dark mode (click again to clear)",
"createModel": "Create Model",
"convertModel": "Convert Model",
"moreModels": "More Models"
diff --git a/src/locales/pt-BR.json b/src/locales/pt-BR.json
index d1c10fb15..ce0eb028b 100644
--- a/src/locales/pt-BR.json
+++ b/src/locales/pt-BR.json
@@ -97,6 +97,8 @@
"clickOrDragToImport": "Clique ou arraste para importar"
},
"tooltips": {
+ "lightModel": "Usar no modo claro (clique novamente para limpar)",
+ "darkModel": "Usar no modo escuro (clique novamente para limpar)",
"createModel": "Criar modelo",
"convertModel": "Converter modelo",
"moreModels": "Mais modelos"
diff --git a/src/locales/vi-VN.json b/src/locales/vi-VN.json
index fd32d4e5a..9174e32fe 100644
--- a/src/locales/vi-VN.json
+++ b/src/locales/vi-VN.json
@@ -97,6 +97,8 @@
"clickOrDragToImport": "Nhấp hoặc kéo tệp vào đây"
},
"tooltips": {
+ "lightModel": "Dùng ở chế độ sáng (nhấp lại để bỏ chọn)",
+ "darkModel": "Dùng ở chế độ tối (nhấp lại để bỏ chọn)",
"createModel": "Tạo mô hình",
"convertModel": "Chuyển đổi mô hình",
"moreModels": "Khám phá mô hình khác"
diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json
index e1a3e4dcc..c35e56167 100644
--- a/src/locales/zh-CN.json
+++ b/src/locales/zh-CN.json
@@ -97,6 +97,8 @@
"clickOrDragToImport": "点击或拖动至此区域导入"
},
"tooltips": {
+ "lightModel": "设为浅色模式桌宠(再次点击取消)",
+ "darkModel": "设为深色模式桌宠(再次点击取消)",
"createModel": "制作模型",
"convertModel": "转换模型",
"moreModels": "更多模型"
diff --git a/src/locales/zh-TW.json b/src/locales/zh-TW.json
index db82dd4b9..c97e97f70 100644
--- a/src/locales/zh-TW.json
+++ b/src/locales/zh-TW.json
@@ -97,6 +97,8 @@
"clickOrDragToImport": "點擊或拖曳至此區域匯入"
},
"tooltips": {
+ "lightModel": "設為淺色模式桌寵(再次點擊取消)",
+ "darkModel": "設為深色模式桌寵(再次點擊取消)",
"createModel": "製作模型",
"convertModel": "轉換模型",
"moreModels": "更多模型"
diff --git a/src/pages/preference/components/general/components/theme-mode/index.vue b/src/pages/preference/components/general/components/theme-mode/index.vue
index c07ef3426..8b25c0049 100644
--- a/src/pages/preference/components/general/components/theme-mode/index.vue
+++ b/src/pages/preference/components/general/components/theme-mode/index.vue
@@ -1,7 +1,6 @@
diff --git a/src/pages/preference/components/model/index.vue b/src/pages/preference/components/model/index.vue
index eb1da4028..da1ce2b18 100644
--- a/src/pages/preference/components/model/index.vue
+++ b/src/pages/preference/components/model/index.vue
@@ -3,7 +3,7 @@ import { convertFileSrc } from '@tauri-apps/api/core'
import { remove } from '@tauri-apps/plugin-fs'
import { revealItemInDir } from '@tauri-apps/plugin-opener'
import { useElementSize } from '@vueuse/core'
-import { Card, Masonry, message, Popconfirm } from 'antdv-next'
+import { Card, Masonry, message, Popconfirm, Tooltip } from 'antdv-next'
import { computed, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
@@ -43,6 +43,14 @@ function handleToggle(nextModel: Model) {
modelStore.currentModel = nextModel
}
+function handleThemeModel(model: Model, theme: 'light' | 'dark') {
+ if (theme === 'light') {
+ modelStore.lightModelId = modelStore.lightModelId === model.id ? null : model.id
+ } else {
+ modelStore.darkModelId = modelStore.darkModelId === model.id ? null : model.id
+ }
+}
+
async function handleDelete(item: Model) {
const { id, path } = item
@@ -55,6 +63,9 @@ async function handleDelete(item: Model) {
} finally {
modelStore.models = modelStore.models.filter(item => item.id !== id)
+ if (modelStore.lightModelId === id) modelStore.lightModelId = null
+ if (modelStore.darkModelId === id) modelStore.darkModelId = null
+
if (id === modelStore.currentModel?.id) {
modelStore.currentModel = modelStore.models[0]
}
@@ -102,6 +113,24 @@ async function handleDelete(item: Model) {
@click.stop="openBehaviorModal = true"
/>
+
+
+
+
+
+
+
+
{
const modelReady = ref(true)
const models = ref([])
const currentModel = ref()
+ const lightModelId = ref(null)
+ const darkModelId = ref(null)
const supportKeys = reactive>({})
const pressedKeys = reactive>({})
const currentMotions = ref>([])
@@ -49,6 +51,8 @@ export const useModelStore = defineStore('model', () => {
const matched = find(nextModels, { id: currentModel.value?.id })
currentModel.value = matched ?? nextModels[0]
+ if (!nextModels.some(item => item.id === lightModelId.value)) lightModelId.value = null
+ if (!nextModels.some(item => item.id === darkModelId.value)) darkModelId.value = null
models.value = nextModels
}
@@ -57,6 +61,8 @@ export const useModelStore = defineStore('model', () => {
modelReady,
models,
currentModel,
+ lightModelId,
+ darkModelId,
supportKeys,
pressedKeys,
currentMotions,