Merge branch 'codex/review-1865' into codex/pr-queue-integration
# Conflicts: # CHANGELOG.md # frontend/src/components/Header.jsx
This commit is contained in:
@@ -75,6 +75,9 @@ the frozen-backend fallback mirror it for their toolchains.
|
||||
- MOSS accelerator routing now matches runtime device selection, including native XPU and registered NPU detection (#1830) — thanks @li-lizhe!
|
||||
- Confucius accelerator routing matches device selection, and dots.tts keeps safe CPU precision on non-CUDA accelerators (#1831) — thanks @li-lizhe!
|
||||
- On macOS, the header status dot and kicker no longer render underneath the overlaid traffic lights (#1863) — thanks @psiberfunk!
|
||||
- macOS retains the shared desktop window sizing, resize limits, and file-drop behavior when native chrome is applied (#1865) — thanks @psiberfunk!
|
||||
|
||||
- On macOS, the header no longer shows Windows-style minimize/maximize/close buttons alongside the native traffic lights (#1865) — thanks @psiberfunk!
|
||||
|
||||
|
||||
## [0.5.2] — 2026-09-02
|
||||
|
||||
@@ -190,3 +190,11 @@ Hit a wall? See [docs/install/troubleshooting.md](troubleshooting.md).
|
||||
The in-app error UI (the React error boundary that fires on backend errors)
|
||||
includes an **"Open docs for this error"** button — that button deeplinks
|
||||
back into this docs tree at the right section for the error class.
|
||||
|
||||
### Desktop window chrome
|
||||
|
||||
The main window uses native macOS traffic lights with an overlay title bar;
|
||||
window sizing, resize limits, and application file-drop behavior match the
|
||||
other desktop platforms. The platform configuration repeats the complete window
|
||||
list because Tauri replaces arrays when merging it with the shared config.
|
||||
The capture widget remains a separate borderless window created at runtime.
|
||||
|
||||
@@ -3,10 +3,35 @@
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "VoiceStudio",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"minWidth": 900,
|
||||
"minHeight": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"decorations": true,
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true,
|
||||
"maximized": true,
|
||||
"dragDropEnabled": false,
|
||||
"transparent": true,
|
||||
"backgroundColor": "#1d2021"
|
||||
},
|
||||
{
|
||||
"label": "widget",
|
||||
"title": "Capture",
|
||||
"width": 300,
|
||||
"height": 64,
|
||||
"resizable": false,
|
||||
"fullscreen": false,
|
||||
"transparent": true,
|
||||
"decorations": false,
|
||||
"alwaysOnTop": true,
|
||||
"visible": false,
|
||||
"skipTaskbar": true,
|
||||
"center": true,
|
||||
"create": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -153,12 +153,12 @@ export default function Header({
|
||||
// breadcrumb + wordmark normally sit — the tabs already say where you are,
|
||||
// and two answers to that question in one bar is one too many.
|
||||
const tabsInTitlebar = navStyle === 'tabs';
|
||||
// The macOS platform config enables decorated overlay chrome. Its native
|
||||
// traffic lights provide the same window actions as our custom desktop row.
|
||||
const isDesktop = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;
|
||||
const showWindowControls = isDesktop;
|
||||
// The macOS config replaces the base window with decorated overlay chrome.
|
||||
// Reserve its traffic-light area only inside the desktop webview.
|
||||
const hasMacTrafficLights =
|
||||
isDesktop && typeof navigator !== 'undefined' && /^Mac/.test(navigator.platform || '');
|
||||
const showWindowControls = isDesktop && !hasMacTrafficLights;
|
||||
const { t } = useTranslation();
|
||||
// Sysinfo is subscribed here (not in App via useAppData) so the 5s poll
|
||||
// only re-renders the header chrome, not the whole App tree.
|
||||
|
||||
@@ -22,8 +22,19 @@ const windowActions = vi.hoisted(() => ({
|
||||
|
||||
vi.mock('@tauri-apps/api/window', () => ({ getCurrentWindow: () => windowActions }));
|
||||
|
||||
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(navigator, 'platform');
|
||||
|
||||
function setPlatform(value) {
|
||||
Object.defineProperty(navigator, 'platform', { value, configurable: true });
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
delete window.__TAURI_INTERNALS__;
|
||||
if (originalPlatformDescriptor) {
|
||||
Object.defineProperty(navigator, 'platform', originalPlatformDescriptor);
|
||||
} else {
|
||||
delete navigator.platform;
|
||||
}
|
||||
vi.clearAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
@@ -115,7 +126,8 @@ describe('Header — rail mode (default)', () => {
|
||||
expect(container.textContent).toMatch(/Dub/);
|
||||
});
|
||||
|
||||
it('uses the app header for native window controls', async () => {
|
||||
it('uses the app header for native window controls on Windows/Linux', async () => {
|
||||
setPlatform('Win32');
|
||||
window.__TAURI_INTERNALS__ = {};
|
||||
renderHeader({});
|
||||
|
||||
@@ -126,6 +138,25 @@ describe('Header — rail mode (default)', () => {
|
||||
await waitFor(() => expect(windowActions.toggleMaximize).toHaveBeenCalledOnce());
|
||||
expect(screen.getByTestId('window-controls')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides the custom window controls on macOS — the OS already draws the traffic lights', () => {
|
||||
setPlatform('MacIntel');
|
||||
window.__TAURI_INTERNALS__ = {};
|
||||
renderHeader({});
|
||||
|
||||
expect(screen.queryByTestId('window-controls')).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: 'Minimize window' })).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: 'Close window' })).toBeNull();
|
||||
});
|
||||
|
||||
it.each(['MacIntel', 'Win32', 'Linux x86_64'])(
|
||||
'never offers desktop window actions in a %s browser',
|
||||
(platform) => {
|
||||
setPlatform(platform);
|
||||
renderHeader({});
|
||||
expect(screen.queryByTestId('window-controls')).toBeNull();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('Header — titlebar tabs mode', () => {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const config = (name) =>
|
||||
JSON.parse(fs.readFileSync(path.resolve(import.meta.dirname, '../../src-tauri', name), 'utf8'));
|
||||
const base = config('tauri.conf.json');
|
||||
const mac = config('tauri.macos.conf.json');
|
||||
|
||||
// Tauri uses JSON Merge Patch: platform arrays REPLACE base arrays, they do
|
||||
// not merge individual window objects. Assert the actual replacement policy.
|
||||
describe('macOS effective window configuration', () => {
|
||||
it('preserves every base window and its behavior except native chrome', () => {
|
||||
const windows = mac.app?.windows ?? base.app.windows;
|
||||
expect(windows).toHaveLength(base.app.windows.length);
|
||||
for (const source of base.app.windows) {
|
||||
const effective = windows.find(
|
||||
(window) => (window.label ?? 'main') === (source.label ?? 'main'),
|
||||
);
|
||||
expect(effective).toBeDefined();
|
||||
for (const [key, value] of Object.entries(source)) {
|
||||
if (key === 'decorations' && (source.label ?? 'main') === 'main') continue;
|
||||
expect(effective[key], `${source.label ?? 'main'}.${key}`).toEqual(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('supplies native overlay controls on macOS when custom controls are hidden', () => {
|
||||
const main = mac.app.windows.find((window) => (window.label ?? 'main') === 'main');
|
||||
expect(main.decorations ?? true).toBe(true);
|
||||
expect(main.titleBarStyle).toBe('Overlay');
|
||||
});
|
||||
|
||||
it('preserves the declared macOS version floor', () => {
|
||||
expect(mac.bundle.macOS.minimumSystemVersion).toBe('13.3');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user