Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 4 additions & 17 deletions src/main/windows/ankiWindow.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { BrowserWindow, nativeTheme } from 'electron'
import { BrowserWindow } from 'electron'
import { join } from 'path'
import { is } from '@electron-toolkit/utils'
import { settingsManager } from '../config'
import { applyTitleBarTheme, titleBarOverlayOptions } from './titleBarOverlay'

let ankiWindow: BrowserWindow | null = null
let settingsUnsubscribe: (() => void) | null = null
Expand Down Expand Up @@ -30,7 +31,6 @@ export function createAnkiWindow(notebookId: string, ankiCardId?: string): void
// 根据用户主题设置背景色
const theme = settingsManager.getSettingSync('theme')
const backgroundColor = theme === 'dark' ? '#1a1b1e' : '#fafafa'
const preferDark = nativeTheme.shouldUseDarkColors || theme === 'dark'

// 创建Anki卡片窗口
ankiWindow = new BrowserWindow({
Expand All @@ -43,15 +43,7 @@ export function createAnkiWindow(notebookId: string, ankiCardId?: string): void
titleBarStyle: 'hidden',
// Position macOS traffic lights (window controls)
...(process.platform === 'darwin' ? { trafficLightPosition: { x: 16, y: 16 } } : {}),
...(process.platform !== 'darwin'
? {
titleBarOverlay: {
color: 'rgba(0,0,0,0)',
height: 35,
symbolColor: preferDark ? 'white' : 'black'
}
}
: {}),
...(process.platform !== 'darwin' ? { titleBarOverlay: titleBarOverlayOptions(theme) } : {}),
backgroundColor,
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
Expand Down Expand Up @@ -84,12 +76,7 @@ export function createAnkiWindow(notebookId: string, ankiCardId?: string): void
const newBackgroundColor = newSettings.theme === 'dark' ? '#1a1b1e' : '#fafafa'
ankiWindow.setBackgroundColor(newBackgroundColor)
// 更新 titleBarOverlay 的符号颜色
const newSymbol = newSettings.theme === 'dark' ? 'white' : 'black'
try {
ankiWindow.setTitleBarOverlay({ symbolColor: newSymbol })
} catch {
// 某些平台或旧版本可能不支持 setTitleBarOverlay
}
applyTitleBarTheme(ankiWindow, newSettings.theme)
}
})
.then((unsubscribe) => {
Expand Down
8 changes: 4 additions & 4 deletions src/main/windows/mainWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BrowserWindow, shell } from 'electron'
import { join } from 'path'
import { is } from '@electron-toolkit/utils'
import { settingsManager } from '../config'
import { applyTitleBarTheme, titleBarOverlayOptions } from './titleBarOverlay'

let mainWindow: BrowserWindow | null = null

Expand All @@ -25,9 +26,7 @@ export function createMainWindow(): BrowserWindow {
// Position macOS traffic lights (window controls)
...(process.platform === 'darwin' ? { trafficLightPosition: { x: 16, y: 16 } } : {}),
// expose window controls in Windows/Linux
...(process.platform !== 'darwin'
? { titleBarOverlay: { color: 'rgba(0,0,0,0)', height: 35, symbolColor: 'white' } }
: {}),
...(process.platform !== 'darwin' ? { titleBarOverlay: titleBarOverlayOptions(theme) } : {}),
backgroundColor,
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
Expand All @@ -44,11 +43,12 @@ export function createMainWindow(): BrowserWindow {
return { action: 'deny' }
})

// 监听主题变化,动态更新窗口背景色
// 监听主题变化,动态更新窗口背景色和窗口按钮颜色
settingsManager.onSettingsChangeSync((newSettings) => {
if (mainWindow && !mainWindow.isDestroyed()) {
const newBackgroundColor = newSettings.theme === 'dark' ? '#282c34' : '#fafafa'
mainWindow.setBackgroundColor(newBackgroundColor)
applyTitleBarTheme(mainWindow, newSettings.theme)
}
})

Expand Down
6 changes: 3 additions & 3 deletions src/main/windows/mindMapWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BrowserWindow } from 'electron'
import { join } from 'path'
import { is } from '@electron-toolkit/utils'
import { settingsManager } from '../config'
import { applyTitleBarTheme, titleBarOverlayOptions } from './titleBarOverlay'

let mindMapWindow: BrowserWindow | null = null

Expand Down Expand Up @@ -41,9 +42,7 @@ export function createMindMapWindow(notebookId: string, mindMapId?: string): voi
titleBarStyle: 'hidden',
// Position macOS traffic lights (window controls)
...(process.platform === 'darwin' ? { trafficLightPosition: { x: 16, y: 16 } } : {}),
...(process.platform !== 'darwin'
? { titleBarOverlay: { color: 'rgba(0,0,0,0)', height: 35, symbolColor: 'white' } }
: {}),
...(process.platform !== 'darwin' ? { titleBarOverlay: titleBarOverlayOptions(theme) } : {}),
backgroundColor,
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
Expand All @@ -64,6 +63,7 @@ export function createMindMapWindow(notebookId: string, mindMapId?: string): voi
if (mindMapWindow && !mindMapWindow.isDestroyed()) {
const newBackgroundColor = newSettings.theme === 'dark' ? '#1a1b1e' : '#fafafa'
mindMapWindow.setBackgroundColor(newBackgroundColor)
applyTitleBarTheme(mindMapWindow, newSettings.theme)
}
})

Expand Down
6 changes: 3 additions & 3 deletions src/main/windows/quizWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BrowserWindow } from 'electron'
import { join } from 'path'
import { is } from '@electron-toolkit/utils'
import { settingsManager } from '../config'
import { applyTitleBarTheme, titleBarOverlayOptions } from './titleBarOverlay'

let quizWindow: BrowserWindow | null = null

Expand Down Expand Up @@ -41,9 +42,7 @@ export function createQuizWindow(notebookId: string, quizId?: string): void {
titleBarStyle: 'hidden',
// Position macOS traffic lights (window controls)
...(process.platform === 'darwin' ? { trafficLightPosition: { x: 16, y: 16 } } : {}),
...(process.platform !== 'darwin'
? { titleBarOverlay: { color: 'rgba(0,0,0,0)', height: 35, symbolColor: 'white' } }
: {}),
...(process.platform !== 'darwin' ? { titleBarOverlay: titleBarOverlayOptions(theme) } : {}),
backgroundColor,
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
Expand All @@ -64,6 +63,7 @@ export function createQuizWindow(notebookId: string, quizId?: string): void {
if (quizWindow && !quizWindow.isDestroyed()) {
const newBackgroundColor = newSettings.theme === 'dark' ? '#1a1b1e' : '#fafafa'
quizWindow.setBackgroundColor(newBackgroundColor)
applyTitleBarTheme(quizWindow, newSettings.theme)
}
})

Expand Down
31 changes: 31 additions & 0 deletions src/main/windows/titleBarOverlay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { BrowserWindow } from 'electron'
import type { AppSettings } from '../config'

/**
* The OS draws the window controls (minimize / maximize / close) on top of our
* custom title bar. The overlay fill is transparent, so the symbol colour has to
* match the renderer: a white symbol on the light `#fafafa` title bar is
* invisible. That is issue #26.
*/
export function titleBarSymbolColor(theme: AppSettings['theme']): 'white' | 'black' {
return theme === 'dark' ? 'white' : 'black'
}

/** `titleBarOverlay` options for the transparent custom title bar (Windows/Linux). */
export function titleBarOverlayOptions(theme: AppSettings['theme']): {
color: string
height: number
symbolColor: 'white' | 'black'
} {
return { color: 'rgba(0,0,0,0)', height: 35, symbolColor: titleBarSymbolColor(theme) }
}

/** Re-colour the window controls after a theme change. macOS has no overlay. */
export function applyTitleBarTheme(window: BrowserWindow, theme: AppSettings['theme']): void {
if (process.platform === 'darwin') return
try {
window.setTitleBarOverlay({ symbolColor: titleBarSymbolColor(theme) })
} catch {
// Older Electron builds may not implement setTitleBarOverlay.
}
}
26 changes: 26 additions & 0 deletions test/titleBarOverlay.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { titleBarOverlayOptions, titleBarSymbolColor } from '../src/main/windows/titleBarOverlay.ts'

/**
* Issue #26: the custom title bar's window controls are drawn by the OS with
* `symbolColor`. In light mode a white symbol sits on the `#fafafa` title bar
* and becomes invisible, so the symbol colour must follow the app theme.
*/
test('window-control symbols are dark in light mode and light in dark mode', () => {
assert.equal(titleBarSymbolColor('light'), 'black')
assert.equal(titleBarSymbolColor('dark'), 'white')
})

test('titleBarOverlay keeps the transparent fill and fixed height', () => {
assert.deepEqual(titleBarOverlayOptions('light'), {
color: 'rgba(0,0,0,0)',
height: 35,
symbolColor: 'black'
})
assert.deepEqual(titleBarOverlayOptions('dark'), {
color: 'rgba(0,0,0,0)',
height: 35,
symbolColor: 'white'
})
})
Loading