From abb9dac40aae997d67cfa8a3bfa1f2c8f465b5c5 Mon Sep 17 00:00:00 2001
From: fanlusky <1730976608@qq.com>
Date: Sun, 19 Jul 2026 02:41:23 +0800
Subject: [PATCH] Preliminarily implement the skin section in settings.
---
.../webview2/settings/ime-settings/index.html | 1 +
.../settings/ime-settings/src/main.ts | 1 +
.../ime-settings/src/modules/sidebar.ts | 4 +++
.../settings/ime-settings/src/modules/skin.ts | 18 ++++++++++++
.../ime-settings/src/partials/skin.html | 29 +++++++++++++++++++
.../ime-settings/src/styles/index.css | 1 +
.../ime-settings/src/styles/modules/skin.css | 10 +++++++
.../ime-settings/src/utils/common-utils.ts | 2 +-
8 files changed, 65 insertions(+), 1 deletion(-)
create mode 100644 ui-html/webview2/settings/ime-settings/src/modules/skin.ts
create mode 100644 ui-html/webview2/settings/ime-settings/src/partials/skin.html
create mode 100644 ui-html/webview2/settings/ime-settings/src/styles/modules/skin.css
diff --git a/ui-html/webview2/settings/ime-settings/index.html b/ui-html/webview2/settings/ime-settings/index.html
index 886b6fb2..8ae34f3f 100644
--- a/ui-html/webview2/settings/ime-settings/index.html
+++ b/ui-html/webview2/settings/ime-settings/index.html
@@ -50,6 +50,7 @@
+
diff --git a/ui-html/webview2/settings/ime-settings/src/main.ts b/ui-html/webview2/settings/ime-settings/src/main.ts
index d34900f6..4c4d3a8f 100644
--- a/ui-html/webview2/settings/ime-settings/src/main.ts
+++ b/ui-html/webview2/settings/ime-settings/src/main.ts
@@ -56,6 +56,7 @@ async function initializeApp() {
await loadContent('input');
await loadContent('helpcode');
await loadContent('dict');
+ await loadContent('skin');
await loadContent('voice');
await loadContent('screenkb-settings');
await loadContent('shortcut');
diff --git a/ui-html/webview2/settings/ime-settings/src/modules/sidebar.ts b/ui-html/webview2/settings/ime-settings/src/modules/sidebar.ts
index 7a1241c7..6cd14651 100644
--- a/ui-html/webview2/settings/ime-settings/src/modules/sidebar.ts
+++ b/ui-html/webview2/settings/ime-settings/src/modules/sidebar.ts
@@ -6,6 +6,7 @@ import { setupFloatingToolbar } from './floating-toolbar';
import { setupVoiceInput } from './voice';
import { setupScreenKeyboardSettings } from './screenkb-settings';
import { setupDictionary } from './dict';
+import { setupSkin } from './skin';
// 动态加载内容
export async function loadContent(moduleName: string) {
@@ -31,6 +32,9 @@ export async function loadContent(moduleName: string) {
case 'dict':
setupDictionary();
break;
+ case 'skin':
+ await setupSkin();
+ break;
case 'voice':
setupVoiceInput();
break;
diff --git a/ui-html/webview2/settings/ime-settings/src/modules/skin.ts b/ui-html/webview2/settings/ime-settings/src/modules/skin.ts
new file mode 100644
index 00000000..c0239675
--- /dev/null
+++ b/ui-html/webview2/settings/ime-settings/src/modules/skin.ts
@@ -0,0 +1,18 @@
+import { loadHTML } from '../utils/common-utils';
+import ftbHTML from '../../../../ftb/default.html?raw';
+
+export async function setupSkin(): Promise {
+ const vertical = document.getElementById('skinCandidateVertical');
+ const horizontal = document.getElementById('skinCandidateHorizontal');
+ if (vertical) vertical.innerHTML = await loadHTML('/src/partials/candidate/candidate-wnd-v.html');
+ if (horizontal) horizontal.innerHTML = await loadHTML('/src/partials/candidate/candidate-wnd-h.html');
+
+ const toolbar = document.getElementById('skinToolbarPreview');
+ if (!toolbar) return;
+ const source = new DOMParser().parseFromString(ftbHTML, 'text/html');
+ const statusBar = source.querySelector('.status-bar');
+ if (!statusBar) return;
+ statusBar.querySelectorAll('#en, #fullwidth, #puncEn').forEach((element) => element.remove());
+ statusBar.querySelectorAll('[id]').forEach((element) => element.removeAttribute('id'));
+ toolbar.replaceChildren(statusBar);
+}
diff --git a/ui-html/webview2/settings/ime-settings/src/partials/skin.html b/ui-html/webview2/settings/ime-settings/src/partials/skin.html
new file mode 100644
index 00000000..d85bdaad
--- /dev/null
+++ b/ui-html/webview2/settings/ime-settings/src/partials/skin.html
@@ -0,0 +1,29 @@
+
diff --git a/ui-html/webview2/settings/ime-settings/src/styles/index.css b/ui-html/webview2/settings/ime-settings/src/styles/index.css
index 4b0a1746..52dfe523 100644
--- a/ui-html/webview2/settings/ime-settings/src/styles/index.css
+++ b/ui-html/webview2/settings/ime-settings/src/styles/index.css
@@ -21,6 +21,7 @@
@import './modules/input.css';
@import './modules/helpcode.css';
@import './modules/dict.css';
+@import './modules/skin.css';
@import './modules/voice.css';
@import './modules/screenkb-settings.css';
@import './modules/shortcut.css';
diff --git a/ui-html/webview2/settings/ime-settings/src/styles/modules/skin.css b/ui-html/webview2/settings/ime-settings/src/styles/modules/skin.css
new file mode 100644
index 00000000..9046bd9d
--- /dev/null
+++ b/ui-html/webview2/settings/ime-settings/src/styles/modules/skin.css
@@ -0,0 +1,10 @@
+.skin-theme-card { padding: 0; overflow: hidden; }
+.skin-theme-header { display: flex; align-items: center; justify-content: space-between; padding: 20px 24px; }
+.skin-theme-description { margin-top: 5px; color: #929292; font-size: 13px; }
+.skin-theme-toggle { cursor: default; }
+.skin-preview-list { padding: 9px 0; background: rgba(18, 18, 18, .13); }
+.skin-preview-row { min-width: 0; }
+.skin-preview-stage { display: flex; align-items: flex-start; justify-content: flex-start; min-width: 0; padding: 9px 24px; overflow: hidden; }
+.skin-preview-row .candidate { flex: 0 0 auto; margin-top: 0; transform-origin: left center; }
+.skin-preview-horizontal .container { width: max-content; white-space: nowrap; }
+.skin-preview-toolbar .ftb-preview-host { display: flex; align-items: center; justify-content: flex-start; padding: 0; }
diff --git a/ui-html/webview2/settings/ime-settings/src/utils/common-utils.ts b/ui-html/webview2/settings/ime-settings/src/utils/common-utils.ts
index 4594adbd..3a183f19 100644
--- a/ui-html/webview2/settings/ime-settings/src/utils/common-utils.ts
+++ b/ui-html/webview2/settings/ime-settings/src/utils/common-utils.ts
@@ -20,7 +20,7 @@ export async function loadHTML(url: string): Promise {
// 只显示当前的模块,隐藏其他模块
export function showOnlyCurrentModule(moduleName: string): void {
- const modules = ['floating-toolbar', 'appearance', 'input', 'helpcode', 'dict', 'voice', 'screenkb-settings', 'shortcut'];
+ const modules = ['floating-toolbar', 'appearance', 'input', 'helpcode', 'dict', 'skin', 'voice', 'screenkb-settings', 'shortcut'];
modules.forEach((module: string) => {
if (module === moduleName) {
document.getElementById(module)!.style.display = 'block';