mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-21 18:19:03 +08:00
feat: 添加 mica-electron 支持实现窗口毛玻璃效果
- 安装 mica-electron 依赖 - 在 WindowManager 中集成 MicaBrowserWindow 和各种效果方法 - 添加窗口主题、效果、圆角等设置选项 - 扩展 settingsSpec 类型支持新的窗口设置
This commit is contained in:
@@ -3,6 +3,39 @@ import { MainContext } from '../context'
|
||||
import { BrowserWindow, shell, screen } from 'electron'
|
||||
import type { BrowserWindowConstructorOptions } from 'electron'
|
||||
|
||||
let micaElectron: typeof import('mica-electron') | null = null
|
||||
let MicaBrowserWindow: any = null
|
||||
let IS_WINDOWS_11 = false
|
||||
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
const micaModule = require('mica-electron')
|
||||
micaElectron = micaModule
|
||||
MicaBrowserWindow = micaModule.MicaBrowserWindow
|
||||
IS_WINDOWS_11 = micaModule.IS_WINDOWS_11
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('mica-electron not available:', error)
|
||||
}
|
||||
|
||||
interface MicaWindow extends BrowserWindow {
|
||||
setMicaEffect(): void
|
||||
setMicaTabbedEffect(): void
|
||||
setMicaAcrylicEffect(): void
|
||||
setAcrylic(): void
|
||||
setBlur(): void
|
||||
setTransparent(): void
|
||||
setDarkTheme(): void
|
||||
setLightTheme(): void
|
||||
setAutoTheme(): void
|
||||
setRoundedCorner(): void
|
||||
setSmallRoundedCorner(): void
|
||||
setSquareCorner(): void
|
||||
setBorderColor(color: string | null): void
|
||||
setCaptionColor(color: string | null): void
|
||||
setTitleTextColor(color: string | null): void
|
||||
}
|
||||
|
||||
export type windowOpenInput = {
|
||||
key: string
|
||||
title?: string
|
||||
@@ -52,7 +85,6 @@ export class WindowManager extends Service {
|
||||
const existing = this.get(input.key)
|
||||
if (existing) {
|
||||
if (input.route) {
|
||||
// Use soft navigation if window exists to prevent reload
|
||||
existing.webContents.send('app:navigate', input.route)
|
||||
}
|
||||
existing.show()
|
||||
@@ -60,12 +92,12 @@ export class WindowManager extends Service {
|
||||
return existing
|
||||
}
|
||||
|
||||
const win = new BrowserWindow({
|
||||
const baseOptions: BrowserWindowConstructorOptions = {
|
||||
width: 900,
|
||||
height: 670,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
frame: false, // Custom title bar
|
||||
frame: false,
|
||||
icon: this.opts.icon,
|
||||
title: input.title,
|
||||
webPreferences: {
|
||||
@@ -73,7 +105,15 @@ export class WindowManager extends Service {
|
||||
sandbox: false
|
||||
},
|
||||
...input.options
|
||||
})
|
||||
}
|
||||
|
||||
let win: BrowserWindow
|
||||
if (MicaBrowserWindow) {
|
||||
win = new MicaBrowserWindow(baseOptions)
|
||||
this.applyMicaEffect(win)
|
||||
} else {
|
||||
win = new BrowserWindow(baseOptions)
|
||||
}
|
||||
|
||||
// Special positioning for global sidebar
|
||||
if (input.key === 'global-sidebar') {
|
||||
@@ -130,6 +170,156 @@ export class WindowManager extends Service {
|
||||
return win
|
||||
}
|
||||
|
||||
private applyMicaEffect(win: BrowserWindow) {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
|
||||
const theme = this.mainCtx.settings.getValue('window_theme')
|
||||
switch (theme) {
|
||||
case 'dark':
|
||||
micaWin.setDarkTheme()
|
||||
break
|
||||
case 'light':
|
||||
micaWin.setLightTheme()
|
||||
break
|
||||
default:
|
||||
micaWin.setAutoTheme()
|
||||
}
|
||||
|
||||
const effect = this.mainCtx.settings.getValue('window_effect')
|
||||
switch (effect) {
|
||||
case 'mica':
|
||||
micaWin.setMicaEffect()
|
||||
break
|
||||
case 'tabbed':
|
||||
micaWin.setMicaTabbedEffect()
|
||||
break
|
||||
case 'acrylic':
|
||||
if (IS_WINDOWS_11) {
|
||||
micaWin.setMicaAcrylicEffect()
|
||||
} else {
|
||||
micaWin.setAcrylic()
|
||||
}
|
||||
break
|
||||
case 'blur':
|
||||
if (!IS_WINDOWS_11) {
|
||||
micaWin.setBlur()
|
||||
}
|
||||
break
|
||||
case 'transparent':
|
||||
if (!IS_WINDOWS_11) {
|
||||
micaWin.setTransparent()
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
const radius = this.mainCtx.settings.getValue('window_radius')
|
||||
switch (radius) {
|
||||
case 'small':
|
||||
micaWin.setSmallRoundedCorner()
|
||||
break
|
||||
case 'square':
|
||||
micaWin.setSquareCorner()
|
||||
break
|
||||
default:
|
||||
micaWin.setRoundedCorner()
|
||||
}
|
||||
}
|
||||
|
||||
public setMicaEffect(win: BrowserWindow, effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none' = 'mica') {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
|
||||
switch (effect) {
|
||||
case 'mica':
|
||||
micaWin.setMicaEffect()
|
||||
break
|
||||
case 'tabbed':
|
||||
micaWin.setMicaTabbedEffect()
|
||||
break
|
||||
case 'acrylic':
|
||||
if (IS_WINDOWS_11) {
|
||||
micaWin.setMicaAcrylicEffect()
|
||||
} else {
|
||||
micaWin.setAcrylic()
|
||||
}
|
||||
break
|
||||
case 'blur':
|
||||
if (!IS_WINDOWS_11) {
|
||||
micaWin.setBlur()
|
||||
}
|
||||
break
|
||||
case 'transparent':
|
||||
if (!IS_WINDOWS_11) {
|
||||
micaWin.setTransparent()
|
||||
}
|
||||
break
|
||||
case 'none':
|
||||
if (IS_WINDOWS_11) {
|
||||
micaWin.setMicaEffect()
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public setMicaTheme(win: BrowserWindow, theme: 'auto' | 'dark' | 'light' = 'auto') {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
|
||||
switch (theme) {
|
||||
case 'dark':
|
||||
micaWin.setDarkTheme()
|
||||
break
|
||||
case 'light':
|
||||
micaWin.setLightTheme()
|
||||
break
|
||||
default:
|
||||
micaWin.setAutoTheme()
|
||||
}
|
||||
}
|
||||
|
||||
public setMicaCorner(win: BrowserWindow, corner: 'rounded' | 'small' | 'square' = 'rounded') {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
|
||||
switch (corner) {
|
||||
case 'small':
|
||||
micaWin.setSmallRoundedCorner()
|
||||
break
|
||||
case 'square':
|
||||
micaWin.setSquareCorner()
|
||||
break
|
||||
default:
|
||||
micaWin.setRoundedCorner()
|
||||
}
|
||||
}
|
||||
|
||||
public setMicaBorderColor(win: BrowserWindow, color: string | null) {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
micaWin.setBorderColor(color)
|
||||
}
|
||||
|
||||
public setMicaCaptionColor(win: BrowserWindow, color: string | null) {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
micaWin.setCaptionColor(color)
|
||||
}
|
||||
|
||||
public setMicaTitleTextColor(win: BrowserWindow, color: string | null) {
|
||||
if (!micaElectron) return
|
||||
const micaWin = win as MicaWindow
|
||||
micaWin.setTitleTextColor(color)
|
||||
}
|
||||
|
||||
public isMicaAvailable(): boolean {
|
||||
return micaElectron !== null
|
||||
}
|
||||
|
||||
public isWindows11(): boolean {
|
||||
return IS_WINDOWS_11
|
||||
}
|
||||
|
||||
public navigate(key: string, route: string) {
|
||||
const win = this.get(key)
|
||||
if (!win) return false
|
||||
@@ -236,7 +426,6 @@ export class WindowManager extends Service {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
if (win) {
|
||||
const bounds = win.getBounds()
|
||||
// Keep right side pinned
|
||||
const newX = bounds.x + (bounds.width - width)
|
||||
win.setBounds({
|
||||
x: newX,
|
||||
@@ -246,5 +435,33 @@ export class WindowManager extends Service {
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.mainCtx.handle('window:mica-effect', (_event, effect: string) => {
|
||||
const win = BrowserWindow.fromWebContents(_event.sender)
|
||||
if (win) {
|
||||
this.setMicaEffect(win, effect as any)
|
||||
}
|
||||
})
|
||||
|
||||
this.mainCtx.handle('window:mica-theme', (_event, theme: string) => {
|
||||
const win = BrowserWindow.fromWebContents(_event.sender)
|
||||
if (win) {
|
||||
this.setMicaTheme(win, theme as any)
|
||||
}
|
||||
})
|
||||
|
||||
this.mainCtx.handle('window:mica-corner', (_event, corner: string) => {
|
||||
const win = BrowserWindow.fromWebContents(_event.sender)
|
||||
if (win) {
|
||||
this.setMicaCorner(win, corner as any)
|
||||
}
|
||||
})
|
||||
|
||||
this.mainCtx.handle('window:mica-info', () => {
|
||||
return {
|
||||
available: this.isMicaAvailable(),
|
||||
isWindows11: this.isWindows11()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user