feat(主题): 添加自定义主题和Mica效果支持

实现自定义主题配置功能,支持设置Mica、Acrylic等窗口效果
添加多个预设主题配置文件
修改侧边栏样式以适配透明效果
扩展主题服务以处理自定义主题配置
This commit is contained in:
Linkon
2026-01-20 02:25:45 +08:00
parent 95ee5705f6
commit 32ddc4be46
12 changed files with 297 additions and 12 deletions
+52
View File
@@ -9,6 +9,11 @@ export interface themeConfig {
name: string
id: string
mode: 'light' | 'dark'
mica?: {
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
theme: 'auto' | 'dark' | 'light'
radius: 'small' | 'medium' | 'large'
}
config: {
tdesign: Record<string, string>
custom: Record<string, string>
@@ -78,9 +83,56 @@ export class ThemeService extends Service {
return { success: false, message: 'Permission denied' }
}
this.currentThemeId = themeId
this.applyMicaEffect(themeId)
this.notifyThemeUpdate()
return { success: true }
})
this.mainCtx.handle('theme:set-custom', async (event, config: {
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
theme: 'auto' | 'dark' | 'light'
radius: 'small' | 'medium' | 'large'
}) => {
if (!this.mainCtx.permissions.requirePermission(event, 'admin'))
return { success: false, message: 'Permission denied' }
this.currentThemeId = 'custom'
this.applyMicaConfig(config)
this.notifyThemeUpdate()
return { success: true }
})
}
private applyMicaEffect(themeId: string) {
const theme = this.getThemeById(themeId)
if (!theme?.mica) return
this.applyMicaConfig(theme.mica)
}
private applyMicaConfig(config: {
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
theme: 'auto' | 'dark' | 'light'
radius: 'small' | 'medium' | 'large'
}) {
const radiusMap: Record<string, 'rounded' | 'small' | 'square'> = {
'small': 'small',
'medium': 'rounded',
'large': 'rounded'
}
const windows = BrowserWindow.getAllWindows()
for (const win of windows) {
if (win.isDestroyed()) continue
this.mainCtx.windows.setMicaEffect(win, config.effect)
this.mainCtx.windows.setMicaTheme(win, config.theme)
this.mainCtx.windows.setMicaCorner(win, radiusMap[config.radius] || 'rounded')
}
this.mainCtx.settings.setValue('window_effect', config.effect)
this.mainCtx.settings.setValue('window_theme', config.theme)
this.mainCtx.settings.setValue('window_radius', radiusMap[config.radius] || 'rounded')
}
private getThemeList(): themeConfig[] {
+5
View File
@@ -7,6 +7,11 @@ const api = {
getThemes: () => ipcRenderer.invoke('theme:list'),
getCurrentTheme: () => ipcRenderer.invoke('theme:current'),
setTheme: (themeId: string) => ipcRenderer.invoke('theme:set', themeId),
setCustomTheme: (config: {
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
theme: 'auto' | 'dark' | 'light'
radius: 'small' | 'medium' | 'large'
}) => ipcRenderer.invoke('theme:set-custom', config),
onThemeChanged: (callback: (theme: themeConfig) => void) => {
const subscription = (_event: any, theme: themeConfig) => callback(theme)
ipcRenderer.on('theme:updated', subscription)
+10
View File
@@ -11,6 +11,11 @@ export interface themeConfig {
name: string
id: string
mode: 'light' | 'dark'
mica?: {
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
theme: 'auto' | 'dark' | 'light'
radius: 'small' | 'medium' | 'large'
}
config: {
tdesign: Record<string, string>
custom: Record<string, string>
@@ -38,6 +43,11 @@ export interface electronApi {
getThemes: () => Promise<ipcResponse<themeConfig[]>>
getCurrentTheme: () => Promise<ipcResponse<themeConfig>>
setTheme: (themeId: string) => Promise<ipcResponse<void>>
setCustomTheme: (config: {
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
theme: 'auto' | 'dark' | 'light'
radius: 'small' | 'medium' | 'large'
}) => Promise<ipcResponse<void>>
onThemeChanged: (callback: (theme: themeConfig) => void) => () => void
// DB - Student
+5 -5
View File
@@ -99,10 +99,10 @@ html[theme-mode='dark'] .ss-sidebar .t-menu__item.t-is-active svg:not([fill='non
/* Global Sidebar Toggle Button */
.global-sidebar-toggle {
width: 24px;
height: 60px;
background-color: var(--ss-card-bg);
border-radius: 8px 0 0 8px;
width: 100vw;
height: 100vh;
background-color: var(--ss-bg-color);
border-radius: 0px 0 0 0px;
display: flex;
align-items: center;
justify-content: center;
@@ -126,7 +126,7 @@ html[theme-mode='dark'] .ss-sidebar .t-menu__item.t-is-active svg:not([fill='non
.sidebar-content-area {
display: flex;
flex-direction: column;
backgroundColor: var(--ss-card-bg);
background-color: var(--ss-card-bg);
border-radius: 12px 0 0 12px;
box-shadow: -4px 0 16px rgba(0,0,0,0.15);
border: 1px solid var(--ss-border-color);
@@ -55,10 +55,11 @@ export const GlobalSidebar: React.FC = () => {
// 1. 先隐藏三角
setShowToggle(false)
// 2. 稍后扩大窗口
setTimeout(() => {
if ((window as any).api) {
const width = Math.round(84 * zoom)
const width = Math.round(60 * zoom)
const height = Math.round(300 * zoom)
;(window as any).api.windowResize(width, height)
}
@@ -77,7 +78,7 @@ export const GlobalSidebar: React.FC = () => {
setTimeout(() => {
if ((window as any).api) {
const width = Math.round(24 * zoom)
const height = Math.round(300 * zoom)
const height = Math.round(58 * zoom)
;(window as any).api.windowResize(width, height)
}
// 3. 最后重新显示三角(等待透明度动画完成)
@@ -99,7 +100,7 @@ export const GlobalSidebar: React.FC = () => {
width: `84px`,
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
justifyContent: 'flex-start',
overflow: 'hidden',
background: 'transparent'
}}
@@ -110,9 +111,10 @@ export const GlobalSidebar: React.FC = () => {
className={`global-sidebar-toggle ${!showToggle ? 'hidden' : ''}`}
style={{
willChange: 'opacity, transform',
width: `24px`,
height: `60px`
width: `${!expanded ? '100vw' : '0px'}`,
height: `100vh`
}}
hidden={!expanded}
>
<ChevronLeftIcon />
</div>
@@ -121,11 +123,10 @@ export const GlobalSidebar: React.FC = () => {
<div
className={`sidebar-content-area ${expanded ? 'visible' : 'hidden'}`}
style={{
backgroundColor: 'var(--ss-card-bg)',
backgroundColor: 'var(--ss-bg-color)',
height: 'fit-content',
willChange: 'opacity, transform',
width: `60px`,
padding: `12px 8px`,
gap: `12px`
}}
>
+31
View File
@@ -0,0 +1,31 @@
{
"name": "Acrylic-自动",
"id": "acrylic-auto",
"mode": "light",
"mica": {
"effect": "acrylic",
"theme": "auto",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#0052D9",
"warningColor": "#E37318",
"errorColor": "#D32029",
"successColor": "#248232"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(255, 255, 255, 0.85)",
"--ss-text-main": "#1a1a1a",
"--ss-text-secondary": "#5e5e5e",
"--ss-border-color": "rgba(0, 0, 0, 0.08)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.9)",
"--ss-item-hover": "rgba(0, 0, 0, 0.04)",
"--ss-sidebar-text": "#1a1a1a",
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.06)",
"--ss-sidebar-active-text": "#1a1a1a"
}
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"name": "Acrylic-深色",
"id": "acrylic-dark",
"mode": "dark",
"mica": {
"effect": "acrylic",
"theme": "dark",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#4C8BF5",
"warningColor": "#E37318",
"errorColor": "#D54941",
"successColor": "#2BA471"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(30, 30, 30, 0.85)",
"--ss-text-main": "#e0e0e0",
"--ss-text-secondary": "#a0a0a0",
"--ss-border-color": "rgba(255, 255, 255, 0.08)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(30, 30, 30, 0.9)",
"--ss-item-hover": "rgba(255, 255, 255, 0.04)",
"--ss-sidebar-text": "#e0e0e0",
"--ss-sidebar-active-bg": "rgba(255, 255, 255, 0.06)",
"--ss-sidebar-active-text": "#e0e0e0"
}
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"name": "Acrylic-浅色",
"id": "acrylic-light",
"mode": "light",
"mica": {
"effect": "acrylic",
"theme": "light",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#0052D9",
"warningColor": "#E37318",
"errorColor": "#D32029",
"successColor": "#248232"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(255, 255, 255, 0.85)",
"--ss-text-main": "#1a1a1a",
"--ss-text-secondary": "#5e5e5e",
"--ss-border-color": "rgba(0, 0, 0, 0.08)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.9)",
"--ss-item-hover": "rgba(0, 0, 0, 0.04)",
"--ss-sidebar-text": "#1a1a1a",
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.06)",
"--ss-sidebar-active-text": "#1a1a1a"
}
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"name": "自定义",
"id": "custom",
"mode": "light",
"mica": {
"effect": "mica",
"theme": "auto",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#0052D9",
"warningColor": "#E37318",
"errorColor": "#D32029",
"successColor": "#248232"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(255, 255, 255, 0.7)",
"--ss-text-main": "#1a1a1a",
"--ss-text-secondary": "#5e5e5e",
"--ss-border-color": "rgba(0, 0, 0, 0.1)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.85)",
"--ss-item-hover": "rgba(0, 0, 0, 0.05)",
"--ss-sidebar-text": "#1a1a1a",
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.08)",
"--ss-sidebar-active-text": "#1a1a1a"
}
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"name": "Mica-自动",
"id": "mica-auto",
"mode": "light",
"mica": {
"effect": "mica",
"theme": "auto",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#0052D9",
"warningColor": "#E37318",
"errorColor": "#D32029",
"successColor": "#248232"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(255, 255, 255, 0.7)",
"--ss-text-main": "#1a1a1a",
"--ss-text-secondary": "#5e5e5e",
"--ss-border-color": "rgba(0, 0, 0, 0.1)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.85)",
"--ss-item-hover": "rgba(0, 0, 0, 0.05)",
"--ss-sidebar-text": "#1a1a1a",
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.08)",
"--ss-sidebar-active-text": "#1a1a1a"
}
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"name": "Mica-深色",
"id": "mica-dark",
"mode": "dark",
"mica": {
"effect": "mica",
"theme": "dark",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#4C8BF5",
"warningColor": "#E37318",
"errorColor": "#D54941",
"successColor": "#2BA471"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(30, 30, 30, 0.7)",
"--ss-text-main": "#e0e0e0",
"--ss-text-secondary": "#a0a0a0",
"--ss-border-color": "rgba(255, 255, 255, 0.1)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(30, 30, 30, 0.85)",
"--ss-item-hover": "rgba(255, 255, 255, 0.05)",
"--ss-sidebar-text": "#e0e0e0",
"--ss-sidebar-active-bg": "rgba(255, 255, 255, 0.08)",
"--ss-sidebar-active-text": "#e0e0e0"
}
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"name": "Mica-浅色",
"id": "mica-light",
"mode": "light",
"mica": {
"effect": "mica",
"theme": "light",
"radius": "medium"
},
"config": {
"tdesign": {
"brandColor": "#0052D9",
"warningColor": "#E37318",
"errorColor": "#D32029",
"successColor": "#248232"
},
"custom": {
"--ss-bg-color": "transparent",
"--ss-card-bg": "rgba(255, 255, 255, 0.7)",
"--ss-text-main": "#1a1a1a",
"--ss-text-secondary": "#5e5e5e",
"--ss-border-color": "rgba(0, 0, 0, 0.1)",
"--ss-header-bg": "transparent",
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.85)",
"--ss-item-hover": "rgba(0, 0, 0, 0.05)",
"--ss-sidebar-text": "#1a1a1a",
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.08)",
"--ss-sidebar-active-text": "#1a1a1a"
}
}
}