diff --git a/src/main/services/ThemeService.ts b/src/main/services/ThemeService.ts index 4892ad1..b5791c6 100644 --- a/src/main/services/ThemeService.ts +++ b/src/main/services/ThemeService.ts @@ -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 custom: Record @@ -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 = { + '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[] { diff --git a/src/preload/index.ts b/src/preload/index.ts index b420d3f..8102a3f 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -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) diff --git a/src/preload/types.ts b/src/preload/types.ts index 285eaba..6c9cdaf 100644 --- a/src/preload/types.ts +++ b/src/preload/types.ts @@ -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 custom: Record @@ -38,6 +43,11 @@ export interface electronApi { getThemes: () => Promise> getCurrentTheme: () => Promise> setTheme: (themeId: string) => Promise> + setCustomTheme: (config: { + effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none' + theme: 'auto' | 'dark' | 'light' + radius: 'small' | 'medium' | 'large' + }) => Promise> onThemeChanged: (callback: (theme: themeConfig) => void) => () => void // DB - Student diff --git a/src/renderer/src/assets/main.css b/src/renderer/src/assets/main.css index 37f2d7e..b11421c 100644 --- a/src/renderer/src/assets/main.css +++ b/src/renderer/src/assets/main.css @@ -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); diff --git a/src/renderer/src/components/GlobalSidebar.tsx b/src/renderer/src/components/GlobalSidebar.tsx index 1be547c..adccddc 100644 --- a/src/renderer/src/components/GlobalSidebar.tsx +++ b/src/renderer/src/components/GlobalSidebar.tsx @@ -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} > @@ -121,11 +123,10 @@ export const GlobalSidebar: React.FC = () => {
diff --git a/themes/acrylic-auto.json b/themes/acrylic-auto.json new file mode 100644 index 0000000..e7eefdc --- /dev/null +++ b/themes/acrylic-auto.json @@ -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" + } + } +} diff --git a/themes/acrylic-dark.json b/themes/acrylic-dark.json new file mode 100644 index 0000000..4e86118 --- /dev/null +++ b/themes/acrylic-dark.json @@ -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" + } + } +} diff --git a/themes/acrylic-light.json b/themes/acrylic-light.json new file mode 100644 index 0000000..cd6ddd7 --- /dev/null +++ b/themes/acrylic-light.json @@ -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" + } + } +} diff --git a/themes/custom.json b/themes/custom.json new file mode 100644 index 0000000..f9374db --- /dev/null +++ b/themes/custom.json @@ -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" + } + } +} diff --git a/themes/mica-auto.json b/themes/mica-auto.json new file mode 100644 index 0000000..c462a38 --- /dev/null +++ b/themes/mica-auto.json @@ -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" + } + } +} diff --git a/themes/mica-dark.json b/themes/mica-dark.json new file mode 100644 index 0000000..217bdec --- /dev/null +++ b/themes/mica-dark.json @@ -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" + } + } +} diff --git a/themes/mica-light.json b/themes/mica-light.json new file mode 100644 index 0000000..80f274d --- /dev/null +++ b/themes/mica-light.json @@ -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" + } + } +}