feat(macos): set traffic-light position via Tauri builder API and sync with zoom

Use Tauri's native `traffic_light_position()` builder method to position
macOS window controls instead of runtime objc2 calls. A global AtomicU32
tracks the current zoom level so newly created windows reflect the latest
zoom. The frontend syncs zoom changes to the backend via a new
`update_traffic_light_position` command.

- Add `traffic_light_position()` to `apply_platform_window_style` builder
- Add `CURRENT_ZOOM` atomic and `traffic_light_position()` helper
- Register `update_traffic_light_position` Tauri command
- Add `syncTrafficLightPosition` in appearance-provider to sync on zoom
  change, mount, and cross-tab storage events
- Consolidate `ensure_windows_undecorated` calls into `post_window_setup`
- Remove dead `on_window_resized` no-op and its Resized event listener

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
xintaofei
2026-04-12 18:11:40 +08:00
parent 883fb64db0
commit 843cf8df19
4 changed files with 77 additions and 15 deletions

View File

@@ -14,6 +14,14 @@ import {
STORAGE_KEY_ZOOM_LEVEL,
} from "@/lib/appearance-script"
function syncTrafficLightPosition(zoom: number) {
if (typeof window === "undefined" || !("__TAURI_INTERNALS__" in window))
return
import("@/lib/tauri").then((t) =>
t.updateTrafficLightPosition(zoom).catch(() => {})
)
}
type AppearanceContextValue = {
themeColor: ThemeColor
setThemeColor: (color: ThemeColor) => void
@@ -73,6 +81,7 @@ export function AppearanceProvider({
const setZoomLevel = useCallback((zoom: ZoomLevel) => {
setZoomLevelState(zoom)
document.documentElement.style.fontSize = `${(16 * zoom) / 100}px`
syncTrafficLightPosition(zoom)
try {
localStorage.setItem(STORAGE_KEY_ZOOM_LEVEL, String(zoom))
} catch {
@@ -80,6 +89,12 @@ export function AppearanceProvider({
}
}, [])
// Sync traffic-light position on mount (initial zoom)
useEffect(() => {
syncTrafficLightPosition(zoomLevel)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
// 跨标签页同步:用户在另一个窗口改了设置时,本窗口实时跟进
useEffect(() => {
const onStorage = (e: StorageEvent) => {
@@ -95,6 +110,7 @@ export function AppearanceProvider({
if ((ZOOM_LEVELS as readonly number[]).includes(zoom)) {
setZoomLevelState(zoom)
document.documentElement.style.fontSize = `${(16 * zoom) / 100}px`
syncTrafficLightPosition(zoom)
}
}
}