fix: 按原生 overlay 实际占位修复 Windows 独立窗口标题栏重叠并升级到 4.1.6

This commit is contained in:
ILoveBingLu
2026-04-08 20:44:40 +08:00
parent 4ec0af6462
commit ade1e14402
8 changed files with 120 additions and 13 deletions
+28 -6
View File
@@ -36,7 +36,7 @@ import { initTldList } from './utils/linkify'
import LockScreen from './pages/LockScreen'
import { useAuthStore } from './stores/authStore'
import { X, Shield, Loader2 } from 'lucide-react'
import { applyWindowChromeToDocument } from './utils/windowChrome'
import { applyWindowChromeToDocument, syncWindowControlsOverlayToDocument } from './utils/windowChrome'
import './App.scss'
type AppUpdateInfo = {
@@ -122,20 +122,42 @@ function App() {
useEffect(() => {
let cancelled = false
let removeOverlayListeners: (() => void) | undefined
const applyPlatformChrome = (platform?: string) => {
if (cancelled) return
applyWindowChromeToDocument(platform)
const bindPlatformChrome = (platform?: string) => {
const syncPlatformChrome = () => {
if (cancelled) return
applyWindowChromeToDocument(platform)
syncWindowControlsOverlayToDocument(platform)
}
syncPlatformChrome()
const overlay = navigator.windowControlsOverlay
if (!overlay) {
return
}
overlay.addEventListener('geometrychange', syncPlatformChrome)
window.addEventListener('resize', syncPlatformChrome)
removeOverlayListeners = () => {
overlay.removeEventListener('geometrychange', syncPlatformChrome)
window.removeEventListener('resize', syncPlatformChrome)
}
}
void window.electronAPI.app.getPlatformInfo().then((info) => {
applyPlatformChrome(info.platform)
if (cancelled) return
bindPlatformChrome(info.platform)
}).catch(() => {
applyPlatformChrome('win32')
if (cancelled) return
bindPlatformChrome('win32')
})
return () => {
cancelled = true
removeOverlayListeners?.()
}
}, [])
-3
View File
@@ -123,8 +123,6 @@
}
.title-bar.variant-standalone.is-win {
padding-right: calc(var(--window-controls-right-safe) + 8px);
.title-bar-left {
flex: 1;
min-width: 0;
@@ -133,7 +131,6 @@
.title-bar-right {
flex-shrink: 0;
overflow: visible;
margin-right: 4px;
}
.titles {
+22
View File
@@ -0,0 +1,22 @@
interface WindowControlsOverlay extends EventTarget {
readonly visible: boolean
getTitlebarAreaRect(): DOMRect
addEventListener(
type: 'geometrychange',
listener: (this: WindowControlsOverlay, event: Event) => void,
options?: boolean | AddEventListenerOptions
): void
removeEventListener(
type: 'geometrychange',
listener: (this: WindowControlsOverlay, event: Event) => void,
options?: boolean | EventListenerOptions
): void
}
declare global {
interface Navigator {
windowControlsOverlay?: WindowControlsOverlay
}
}
export {}
+57
View File
@@ -6,6 +6,11 @@ type WindowChromeMetrics = {
toolbarGap: string
}
type WindowControlsOverlayPadding = {
left: number
right: number
}
const DEFAULT_PLATFORM: WindowPlatform = 'win32'
const WINDOW_CHROME_HEIGHT = '40px'
@@ -27,6 +32,30 @@ const WINDOW_CHROME_METRICS: Record<WindowPlatform, WindowChromeMetrics> = {
}
}
const WINDOW_CONTROLS_OVERLAY_PADDING: Record<WindowPlatform, WindowControlsOverlayPadding> = {
win32: {
left: 16,
right: 12
},
darwin: {
left: 12,
right: 16
},
linux: {
left: 16,
right: 12
}
}
function parsePixels(value: string) {
const parsed = Number.parseFloat(value)
return Number.isFinite(parsed) ? parsed : 0
}
function toPixels(value: number) {
return `${Math.max(0, Math.round(value))}px`
}
export function normalizeWindowPlatform(platform?: string | null): WindowPlatform {
if (platform === 'darwin' || platform === 'linux' || platform === 'win32') {
return platform
@@ -52,3 +81,31 @@ export function applyWindowChromeToDocument(platform?: string | null, root: HTML
root.style.setProperty('--window-controls-right-safe', metrics.controlsRightSafe)
root.style.setProperty('--window-toolbar-gap', metrics.toolbarGap)
}
export function syncWindowControlsOverlayToDocument(
platform?: string | null,
root: HTMLElement = document.documentElement,
viewportWidth: number = window.innerWidth
) {
const overlay = navigator.windowControlsOverlay
if (!overlay || !overlay.visible || viewportWidth <= 0) {
return false
}
const titlebarAreaRect = overlay.getTitlebarAreaRect()
if (titlebarAreaRect.width <= 0 || titlebarAreaRect.height <= 0) {
return false
}
const normalizedPlatform = normalizeWindowPlatform(platform)
const overlayPadding = WINDOW_CONTROLS_OVERLAY_PADDING[normalizedPlatform]
const controlsRightWidth = Math.max(0, viewportWidth - titlebarAreaRect.x - titlebarAreaRect.width)
const chromeHeight = Math.max(parsePixels(WINDOW_CHROME_HEIGHT), titlebarAreaRect.height)
const controlsLeftSafe = Math.max(overlayPadding.left, titlebarAreaRect.x + overlayPadding.left)
const controlsRightSafe = Math.max(overlayPadding.right, controlsRightWidth + overlayPadding.right)
root.style.setProperty('--window-chrome-height', toPixels(chromeHeight))
root.style.setProperty('--window-controls-left-safe', toPixels(controlsLeftSafe))
root.style.setProperty('--window-controls-right-safe', toPixels(controlsRightSafe))
return true
}