From ba25f86ec49e59ad944c1656a37af94ea1517be1 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 9 Oct 2026 10:02:27 -0700 Subject: [PATCH 1/2] fix(desktop): open Folder Access from a focused utility window --- apps/desktop/src/main/menu.test.ts | 13 ++++++++++++- apps/desktop/src/main/menu.ts | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/main/menu.test.ts b/apps/desktop/src/main/menu.test.ts index 2eb8862dc32..ef24d7c38bd 100644 --- a/apps/desktop/src/main/menu.test.ts +++ b/apps/desktop/src/main/menu.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest' vi.mock('electron', () => import('@/test/electron-mock')) -import type { MenuItemConstructorOptions } from 'electron' +import { BrowserWindow, type MenuItemConstructorOptions } from 'electron' import type { ConfigStore } from '@/main/config' import { buildMenuTemplate, type MenuDeps } from '@/main/menu' @@ -45,4 +45,15 @@ describe('buildMenuTemplate', () => { const view = submenu(buildMenuTemplate(makeDeps()), 'View') expect(view.some((item) => item.role === 'toggleDevTools')).toBe(false) }) + + it('anchors Folder Access to a focused utility window instead of dropping the action', () => { + const deps = makeDeps() + const utilityWindow = new BrowserWindow() + vi.mocked(deps.isMainWindow).mockReturnValue(false) + const folderAccess = submenu(buildMenuTemplate(deps), 'File').find( + (item) => item.label === 'Folder Access…' + ) + folderAccess?.click?.({} as never, utilityWindow, {} as never) + expect(deps.openFolderAccess).toHaveBeenCalledWith(utilityWindow) + }) }) diff --git a/apps/desktop/src/main/menu.ts b/apps/desktop/src/main/menu.ts index a88c51de480..b6bfb58fcf7 100644 --- a/apps/desktop/src/main/menu.ts +++ b/apps/desktop/src/main/menu.ts @@ -216,7 +216,7 @@ export function buildMenuTemplate(deps: MenuDeps): MenuItemConstructorOptions[] { label: 'Folder Access…', click: (_item, focusedWindow) => { - const win = focusedMainOrFallback(focusedWindow) + const win = focusedWindowOrMain(focusedWindow) if (win) deps.openFolderAccess(win) }, }, From 8cdfaae6667d5e61c42fb2c538713f75718da5ea Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 9 Oct 2026 10:21:18 -0700 Subject: [PATCH 2/2] test(desktop): cover Folder Access from a utility window in the Electron e2e --- apps/desktop/e2e/local-files.spec.ts | 49 ++++++++++++++++++++++++++++ apps/desktop/src/main/menu.test.ts | 13 +------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/apps/desktop/e2e/local-files.spec.ts b/apps/desktop/e2e/local-files.spec.ts index cfe20ba2244..59e8e60aa4b 100644 --- a/apps/desktop/e2e/local-files.spec.ts +++ b/apps/desktop/e2e/local-files.spec.ts @@ -267,6 +267,55 @@ createRoot(document.getElementById('settings')).render( await expect(prompt.getByRole('button', { name: "Don't allow", exact: true })).toBeVisible() return { prompt, result } } + await test.step('File → Folder Access opens over a focused utility window', async () => { + if (!app) throw new Error('Desktop app is not running') + const serverShown = app.waitForEvent('window', { timeout: 10_000 }) + await app.evaluate(({ Menu }) => { + const item = Menu.getApplicationMenu() + ?.items.flatMap((entry) => entry.submenu?.items ?? []) + .find((entry) => entry.label === 'Server…') + if (!item) throw new Error('Server menu item missing') + item.click() + }) + await expect(await serverShown).toHaveTitle('Sim - Server') + await expect + .poll(() => + app?.evaluate(({ BrowserWindow }) => + BrowserWindow.getAllWindows().some( + (win) => win.webContents.getURL().endsWith('server.html') && win.isVisible() + ) + ) + ) + .toBe(true) + const accessMenu = await app.evaluate(({ BrowserWindow, Menu }) => { + const utility = BrowserWindow.getAllWindows().find((win) => + win.webContents.getURL().endsWith('server.html') + ) + if (!utility) throw new Error('Server window missing') + const item = Menu.getApplicationMenu() + ?.items.flatMap((entry) => entry.submenu?.items ?? []) + .find((entry) => entry.label === 'Folder Access…') + if (!item) throw new Error('Folder Access menu item missing') + const popup = Menu.prototype.popup + let shown: { anchoredToUtility: boolean; items: string[] } | undefined + Menu.prototype.popup = function (this: Electron.Menu, options) { + shown = { + anchoredToUtility: options?.window === utility, + items: this.items.map((entry) => entry.label), + } + } + try { + item.click(undefined, utility) + } finally { + Menu.prototype.popup = popup + } + utility.close() + return shown + }) + expect(accessMenu?.anchoredToUtility).toBe(true) + expect(accessMenu?.items).toContain('Add Folder…') + }) + await test.step('Stop cancels only its own request while chats share a folder prompt', async () => { const sharedFolder = join(root, 'Shared') mkdirSync(sharedFolder) diff --git a/apps/desktop/src/main/menu.test.ts b/apps/desktop/src/main/menu.test.ts index ef24d7c38bd..2eb8862dc32 100644 --- a/apps/desktop/src/main/menu.test.ts +++ b/apps/desktop/src/main/menu.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest' vi.mock('electron', () => import('@/test/electron-mock')) -import { BrowserWindow, type MenuItemConstructorOptions } from 'electron' +import type { MenuItemConstructorOptions } from 'electron' import type { ConfigStore } from '@/main/config' import { buildMenuTemplate, type MenuDeps } from '@/main/menu' @@ -45,15 +45,4 @@ describe('buildMenuTemplate', () => { const view = submenu(buildMenuTemplate(makeDeps()), 'View') expect(view.some((item) => item.role === 'toggleDevTools')).toBe(false) }) - - it('anchors Folder Access to a focused utility window instead of dropping the action', () => { - const deps = makeDeps() - const utilityWindow = new BrowserWindow() - vi.mocked(deps.isMainWindow).mockReturnValue(false) - const folderAccess = submenu(buildMenuTemplate(deps), 'File').find( - (item) => item.label === 'Folder Access…' - ) - folderAccess?.click?.({} as never, utilityWindow, {} as never) - expect(deps.openFolderAccess).toHaveBeenCalledWith(utilityWindow) - }) })