mirror of
https://github.com/ILoveBingLu/CipherTalk.git
synced 2026-05-21 20:13:03 +08:00
fix: 按原生 overlay 实际占位修复 Windows 独立窗口标题栏重叠并升级到 4.1.6
This commit is contained in:
+28
-6
@@ -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?.()
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Vendored
+22
@@ -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 {}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user