[ui]: some settings ui parts
This commit is contained in:
1 parent
64435eeee8
commit
404f1aa737
4 files changed
+311
-65
No files matched your search
@@ -19,7 +19,7 @@
|
||||
.container {
|
||||
margin-top: 0px;
|
||||
margin-left: 0px;
|
||||
background-color: #202020;
|
||||
background: #202020;
|
||||
/* background: url("https://appassets/background.jpg"); */
|
||||
padding: 2px;
|
||||
border-radius: 6px;
|
||||
@@ -27,7 +27,7 @@
|
||||
min-width: 7em;
|
||||
width: fit-content;
|
||||
user-select: none;
|
||||
border: 2px solid #9b9b9b2e;
|
||||
border: 1.5px solid #9b9b9b2e;
|
||||
}
|
||||
|
||||
.row {
|
||||
|
||||
@@ -18,24 +18,44 @@
|
||||
<img src="./assets/MetasequoiaIME.ico" alt="">
|
||||
<span>水杉输入法</span>
|
||||
</div>
|
||||
<div class="item"><span class="icon">⚙️</span> 通用</div>
|
||||
<div class="item active"><span class="icon">🎨</span> 外观</div>
|
||||
<div class="item"><span class="icon input-icon">⌨️</span> 输入</div>
|
||||
<div class="item"><span class="icon">🧩</span> 辅助码</div>
|
||||
<div class="item"><span class="icon">⌘</span> 快捷键</div>
|
||||
<div class="item"><span class="icon">📚</span> 词库</div>
|
||||
<div class="item"><span class="icon">🖼️</span> 皮肤</div>
|
||||
<div class="item"><span class="icon">🎙️</span> 语音打字</div>
|
||||
<div class="item"><span class="icon">🤖</span> AI 辅助</div>
|
||||
<div class="item"><span class="icon">❓</span> 帮助</div>
|
||||
<div class="item"><span class="icon">ℹ️</span> 关于</div>
|
||||
<div class="item"><span class="icon">💬</span> 反馈</div>
|
||||
<div class="item" data-target="general-settings"><span class="icon">⚙️</span> 通用</div>
|
||||
<div class="item active" data-target="appearence-settings"><span class="icon">🎨</span> 外观</div>
|
||||
<div class="item" data-target="input-settings"><span class="icon input-icon">⌨️</span> 输入</div>
|
||||
<div class="item" data-target="helpcode-settings"><span class="icon">🧩</span> 辅助码</div>
|
||||
<div class="item" data-target="shortcut-settings"><span class="icon">⌘</span> 快捷键</div>
|
||||
<div class="item" data-target="dict-settings"><span class="icon">📚</span> 词库</div>
|
||||
<div class="item" data-target="skin-settings"><span class="icon">🖼️</span> 皮肤</div>
|
||||
<div class="item" data-target="voice-settings"><span class="icon">🎙️</span> 语音打字</div>
|
||||
<div class="item" data-target="screenkb-settings"><span class="icon">🖥️</span> 屏幕键盘</div>
|
||||
<div class="item" data-target="tools-settings"><span class="icon">🛠️</span> 实用功能</div>
|
||||
<div class="item" data-target="ai-settings"><span class="icon">🤖</span> AI 辅助</div>
|
||||
<div class="item" data-target="help-settings"><span class="icon">❓</span> 帮助</div>
|
||||
<div class="item" data-target="about-settings"><span class="icon">ℹ️</span> 关于</div>
|
||||
<div class="item" data-target="feedback-settings"><span class="icon">💬</span> 反馈</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<!-- 通用 -->
|
||||
<div class="content" id="general-settings">
|
||||
<div class="content-header"><span>通用</span></div>
|
||||
|
||||
<!-- 悬浮工具栏 toggle -->
|
||||
<div class="section ftb-toggle">
|
||||
<div class="section-header">
|
||||
<div class="section-title">悬浮工具栏</div>
|
||||
<div class="ftb-toggle-btn" id="ftbToggleBtn">
|
||||
<div class="ftb-toggle-knob"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 外观 -->
|
||||
<div class="content active" id="appearence-settings">
|
||||
<div class="content-header"><span>外观</span></div>
|
||||
|
||||
<!-- 候选窗口预览 -->
|
||||
<div class="section candidate-preview">
|
||||
<h2>候选窗口预览</h2>
|
||||
<div class="section-title cand-prev-title">候选窗口预览</div>
|
||||
<div class="candidate-container">
|
||||
<div class="candidate-row">
|
||||
<div class="candidate-text">ni'mf</div>
|
||||
@@ -83,9 +103,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主题模式 -->
|
||||
<div class="section theme">
|
||||
<div class="section-header">
|
||||
<h2>主题模式</h2>
|
||||
<div class="section-title">主题模式(默认)</div>
|
||||
<div class="dropdown">
|
||||
<button class="dropdown-toggle" id="themeBtn">
|
||||
<span>深色</span>
|
||||
@@ -100,47 +121,153 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="section-header arrange-item">
|
||||
<div class="section-title">候选项排列方式</div>
|
||||
<div class="dropdown">
|
||||
<button class="dropdown-toggle" id="arrangeBtn">
|
||||
<span>竖排</span>
|
||||
<div class="arrow">
|
||||
<img src="./assets/arrow.svg" alt="arrow">
|
||||
</div>
|
||||
</button>
|
||||
<div class="dropdown-menu" id="arrangeMenu">
|
||||
<div class="dropdown-item" data-value="horizontal">横排</div>
|
||||
<div class="dropdown-item" data-value="vertical">竖排</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 输入 -->
|
||||
<div class="content" id="input-settings">
|
||||
<div class="content-header"><span>输入</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 辅助码 -->
|
||||
<div class="content" id="helpcode-settings">
|
||||
<div class="content-header"><span>辅助码</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 快捷键 -->
|
||||
<div class="content" id="shortcut-settings">
|
||||
<div class="content-header"><span>快捷键</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 词库 -->
|
||||
<div class="content" id="dict-settings">
|
||||
<div class="content-header"><span>词库</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 皮肤 -->
|
||||
<div class="content" id="skin-settings">
|
||||
<div class="content-header"><span>皮肤</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 语音打字 -->
|
||||
<div class="content" id="voice-settings">
|
||||
<div class="content-header"><span>语音打字</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 屏幕键盘 -->
|
||||
<div class="content" id="screenkb-settings">
|
||||
<div class="content-header"><span>屏幕键盘</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 实用功能 -->
|
||||
<div class="content" id="tools-settings">
|
||||
<div class="content-header"><span>实用功能</span></div>
|
||||
</div>
|
||||
|
||||
<!-- AI 辅助 -->
|
||||
<div class="content" id="ai-settings">
|
||||
<div class="content-header"><span>AI 辅助</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 帮助 -->
|
||||
<div class="content" id="help-settings">
|
||||
<div class="content-header"><span>帮助</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 关于 -->
|
||||
<div class="content" id="about-settings">
|
||||
<div class="content-header"><span>关于</span></div>
|
||||
</div>
|
||||
|
||||
<!-- 反馈 -->
|
||||
<div class="content" id="feedback-settings">
|
||||
<div class="content-header"><span>反馈</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const btn = document.getElementById('themeBtn');
|
||||
const menu = document.getElementById('themeMenu');
|
||||
const dropdown = document.querySelector('.dropdown');
|
||||
const textSpan = btn.querySelector('span');
|
||||
|
||||
// 打开/关闭下拉菜单
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
dropdown.classList.toggle('open');
|
||||
});
|
||||
const sidebarItems = document.querySelectorAll('.sidebar .item');
|
||||
|
||||
// 点击菜单项
|
||||
menu.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', (e) => {
|
||||
const value = item.dataset.value;
|
||||
const text = item.textContent;
|
||||
sidebarItems.forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
document.querySelector('.sidebar .item.active')?.classList.remove('active');
|
||||
item.classList.add('active');
|
||||
|
||||
// 更新按钮文字
|
||||
textSpan.textContent = text;
|
||||
|
||||
// 可选:发送给 webview 通知主题变化
|
||||
if (window.chrome?.webview) {
|
||||
window.chrome.webview.postMessage({ action: "changeTheme", theme: value });
|
||||
}
|
||||
|
||||
// 关闭菜单
|
||||
dropdown.classList.remove('open');
|
||||
document.querySelector('.content.active')?.classList.remove('active');
|
||||
const targetId = item.dataset.target;
|
||||
document.getElementById(targetId)?.classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// 点击其他地方关闭菜单
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!dropdown.contains(e.target)) {
|
||||
dropdown.classList.remove('open');
|
||||
}
|
||||
//
|
||||
// 外观 -> 主题模式(默认)
|
||||
//
|
||||
document.querySelectorAll('.dropdown').forEach(dropdown => {
|
||||
const btn = dropdown.querySelector('.dropdown-toggle');
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
const textSpan = btn.querySelector('span');
|
||||
|
||||
// 打开/关闭菜单
|
||||
btn.addEventListener('click', e => {
|
||||
e.stopPropagation();
|
||||
dropdown.classList.toggle('open');
|
||||
});
|
||||
|
||||
// 点击菜单项
|
||||
menu.querySelectorAll('.dropdown-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
textSpan.textContent = item.textContent;
|
||||
|
||||
// 根据按钮 id 区分动作
|
||||
if (window.chrome?.webview) {
|
||||
if (btn.id === 'themeBtn') {
|
||||
window.chrome.webview.postMessage({ action: "changeTheme", theme: item.dataset.value });
|
||||
} else if (btn.id === 'arrangeBtn') {
|
||||
window.chrome.webview.postMessage({ action: "changeCandidateArrange", arrange: item.dataset.value });
|
||||
}
|
||||
}
|
||||
|
||||
dropdown.classList.remove('open');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 点击空白处关闭所有下拉
|
||||
document.addEventListener('click', () => {
|
||||
document.querySelectorAll('.dropdown').forEach(d => d.classList.remove('open'));
|
||||
});
|
||||
|
||||
//
|
||||
// 外观 -> 候选项排列方式
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// 通用 -> 悬浮工具栏
|
||||
//
|
||||
const toggle = document.getElementById('ftbToggleBtn');
|
||||
toggle.addEventListener('click', () => {
|
||||
toggle.classList.toggle('active');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -44,6 +44,40 @@ body {
|
||||
flex-direction: column;
|
||||
padding: 12px 0;
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
/* 整个滚动条宽度 */
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
/* 滚动条轨道 */
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* 滚动条滑块 */
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(120, 120, 120, 0.4);
|
||||
border-radius: 2px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
/* 滚动条在鼠标悬浮时更亮一些 */
|
||||
.sidebar::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(160, 160, 160, 0.6);
|
||||
}
|
||||
|
||||
/* 深色模式下更暗 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(180, 180, 180, 0.25);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(220, 220, 220, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
@@ -54,6 +88,14 @@ body {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 24px 12px 4px;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.sidebar-header img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
@@ -61,6 +103,11 @@ body {
|
||||
}
|
||||
|
||||
.sidebar-header span {
|
||||
font-weight: 500;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.content-header span {
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
}
|
||||
@@ -97,6 +144,7 @@ body {
|
||||
border-radius: 5px;
|
||||
margin: 2px 8px;
|
||||
color: #e6e6e6;
|
||||
/* font-weight: 450; */
|
||||
}
|
||||
|
||||
.sidebar .item:hover {
|
||||
@@ -112,7 +160,8 @@ body {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sidebar .item.active::before {
|
||||
/* item 左侧的 bar */
|
||||
.sidebar .item::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -2px;
|
||||
@@ -120,12 +169,33 @@ body {
|
||||
height: 50%;
|
||||
border-radius: 3px;
|
||||
background: var(--accent-color);
|
||||
/* 初始收起 */
|
||||
transform: scaleY(0);
|
||||
/* 从中间往上下展开 */
|
||||
transform-origin: center center;
|
||||
/* 动画过渡 */
|
||||
transition: transform 0.25s ease;
|
||||
/* 初始隐藏 */
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.sidebar .item.active::before {
|
||||
transform: scaleY(1);
|
||||
/* 展开 */
|
||||
opacity: 1;
|
||||
/* 渐显 */
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 12px 12px;
|
||||
overflow-y: auto;
|
||||
display: none;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.section {
|
||||
@@ -135,12 +205,13 @@ body {
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 18px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
|
||||
backdrop-filter: blur(10px);
|
||||
/* backdrop-filter: blur(10px); */
|
||||
/* z-index: 0; */
|
||||
}
|
||||
|
||||
.section h2 {
|
||||
.section-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
font-weight: 550;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
@@ -165,6 +236,10 @@ select:focus {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.cand-prev-title {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
width: 100%;
|
||||
accent-color: var(--accent-color);
|
||||
@@ -231,8 +306,19 @@ input[type="range"] {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: #908f8f16;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.arrange-item {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/* 主题模式 */
|
||||
.theme {
|
||||
.theme .ftb-toggle {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
@@ -259,7 +345,6 @@ input[type="range"] {
|
||||
font-size: 14px;
|
||||
padding: 4px 12px;
|
||||
padding-right: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
text-align: left;
|
||||
min-width: 100px;
|
||||
@@ -301,7 +386,6 @@ div.arrow {
|
||||
.dropdown-item {
|
||||
margin: 2px;
|
||||
padding: 4px 8px;
|
||||
cursor: pointer;
|
||||
color: #eee;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
@@ -316,4 +400,39 @@ div.arrow {
|
||||
|
||||
.dropdown.open .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 外观 -> 悬浮工具栏 */
|
||||
.ftb-toggle-btn {
|
||||
position: relative;
|
||||
width: 38px;
|
||||
height: 19px;
|
||||
background: #555;
|
||||
border-radius: 9px;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
transition: background 0.2s ease, border 0.2s ease;
|
||||
}
|
||||
|
||||
.ftb-toggle-knob {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 1px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
transform: translateY(-50%);
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.ftb-toggle-btn.active {
|
||||
background: #8E8CD8;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
.ftb-toggle-btn.active .ftb-toggle-knob {
|
||||
/* 38 - 16 - 1 * 2 = 20 */
|
||||
transform: translate(20px, -50%);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
WS_EX_TOPMOST; //
|
||||
FLOAT scale = GetForegroundWindowScale();
|
||||
|
||||
HWND hwnd = CreateWindowEx( //
|
||||
HWND hwnd_cand = CreateWindowEx( //
|
||||
dwExStyle, //
|
||||
szWindowClass, //
|
||||
lpWindowNameCand, //
|
||||
@@ -90,7 +90,7 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
nullptr //
|
||||
); //
|
||||
|
||||
if (!hwnd)
|
||||
if (!hwnd_cand)
|
||||
{
|
||||
OutputDebugString(fmt::format(L"Call to CreateWindow for candidate window failed!\n").c_str());
|
||||
return 1;
|
||||
@@ -98,15 +98,15 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
else
|
||||
{
|
||||
// Set the window to be fully not transparent
|
||||
SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);
|
||||
SetLayeredWindowAttributes(hwnd_cand, 0, 255, LWA_ALPHA);
|
||||
MARGINS mar = {-1};
|
||||
DwmExtendFrameIntoClientArea(hwnd, &mar);
|
||||
DwmExtendFrameIntoClientArea(hwnd_cand, &mar);
|
||||
}
|
||||
|
||||
::global_hwnd = hwnd;
|
||||
::global_hwnd = hwnd_cand;
|
||||
|
||||
SetWindowPos( //
|
||||
hwnd, //
|
||||
hwnd_cand, //
|
||||
HWND_TOPMOST, //
|
||||
-10000, //
|
||||
-10000, //
|
||||
@@ -116,7 +116,7 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
);
|
||||
|
||||
SetWindowPos( //
|
||||
hwnd, //
|
||||
hwnd_cand, //
|
||||
HWND_TOPMOST, //
|
||||
100, //
|
||||
100, //
|
||||
@@ -197,8 +197,8 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
/* 设置标题栏和窗口区域为 mica 材质 */
|
||||
MARGINS margins = {-1};
|
||||
DwmExtendFrameIntoClientArea(hwnd_settings, &margins);
|
||||
DWM_SYSTEMBACKDROP_TYPE backdrop = DWMSBT_MAINWINDOW; // Mica 背景类型
|
||||
DwmSetWindowAttribute(hwnd_settings, DWMWA_SYSTEMBACKDROP_TYPE, &backdrop, sizeof(backdrop));
|
||||
DWM_SYSTEMBACKDROP_TYPE backdrop_settings = DWMSBT_MAINWINDOW; // Mica 背景类型
|
||||
DwmSetWindowAttribute(hwnd_settings, DWMWA_SYSTEMBACKDROP_TYPE, &backdrop_settings, sizeof(backdrop_settings));
|
||||
|
||||
//
|
||||
// floating toolbar 窗口
|
||||
@@ -231,12 +231,12 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
//
|
||||
// 候选窗口、菜单窗口、settings 窗口、floating toolbar 窗口、floating toolbar hover tip 窗口
|
||||
//
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
ShowWindow(hwnd_cand, SW_SHOW);
|
||||
ShowWindow(hwnd_menu, SW_SHOW);
|
||||
ShowWindow(hwnd_settings, SW_SHOWMINIMIZED);
|
||||
ShowWindow(hwnd_settings, SW_RESTORE);
|
||||
ShowWindow(hwnd_ftb, SW_SHOW);
|
||||
UpdateWindow(hwnd);
|
||||
UpdateWindow(hwnd_cand);
|
||||
UpdateWindow(hwnd_menu);
|
||||
UpdateWindow(hwnd_settings);
|
||||
UpdateWindow(hwnd_ftb);
|
||||
@@ -246,7 +246,7 @@ int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
//
|
||||
PrepareHtmlForWnds();
|
||||
/* 候选框窗口 */
|
||||
InitWebviewCandWnd(hwnd);
|
||||
InitWebviewCandWnd(hwnd_cand);
|
||||
/* 托盘语言区右键菜单窗口 */
|
||||
InitWebviewMenuWnd(hwnd_menu);
|
||||
/* settings 窗口 */
|
||||
|
||||
Reference in new issue
Block a user