Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6e8931d
perf(client): reduce remote request and message sync overhead (#11029)
Bil0000 Sep 11, 2026
e1c94f7
fix(web): refresh usage limit countdowns without switching tabs (#11187)
t3-code[bot] Sep 11, 2026
fb52d12
fix(client-runtime): typecheck device hub ticket request on main (#11…
juliusmarminge Sep 11, 2026
2c0e891
feat(settings): add per-project overrides for scopable server setting…
juliusmarminge Sep 11, 2026
8b2c046
feat(web): pick settings environment and project as two selects (#10636)
juliusmarminge Sep 11, 2026
e22040d
feat(settings): edit any scopable setting as a project override (#10639)
juliusmarminge Sep 11, 2026
8bbe2bf
feat(web): float device streams over chat (#11285)
juliusmarminge Sep 11, 2026
18f7254
fix(web): floating preview can use the margins beside the composer (#…
juliusmarminge Sep 11, 2026
e145c5f
perf(client-runtime): speed up message sync on desktop and mobile (#1…
Bil0000 Sep 11, 2026
15c6167
fix(web): use the configured panel shortcut on the PR page (#11292)
Bil0000 Sep 11, 2026
b3ed07f
feat(web): add PR page selections to new draft threads (#11296)
Bil0000 Sep 11, 2026
0eaa18c
feat(web): show recording status on floating previews (#11312)
maria-rcks Sep 11, 2026
095d575
fix(desktop): hold-to-quit no longer strands the quit (#11016)
maria-rcks Sep 11, 2026
4a8ab1b
feat(web): mark projects on another machine in project pickers (#11323)
maria-rcks Sep 11, 2026
8711929
fix(web): show pointer cursors on pull request controls (#11283)
shivamhwp Sep 11, 2026
867eb9b
fix(web): themed panel toggles show their disabled state (#11188)
flamboh Sep 11, 2026
50791a0
fix(web): use branch wording in commit dialogs (#11281)
shivamhwp Sep 11, 2026
cd64ad3
fix(mobile): keep Android file icons on the line with wrapped filenam…
SunkenInTime Sep 11, 2026
a92161a
fix(codex): preserve qualified model ids in selection and generation …
maria-rcks Sep 11, 2026
36668db
feat(desktop): share macOS permission onboarding (#11289)
juliusmarminge Sep 11, 2026
8a2d5f5
fix(test): drain worker broadcasts before restoring browser globals (…
maria-rcks Sep 12, 2026
8461c25
fix(web): disable linked pull requests when none are linked (#11348)
maria-rcks Sep 12, 2026
1f73a89
fix(models): default to astra medium and fable 5.1 medium (#11347)
maria-rcks Sep 12, 2026
4d16e6b
fix(web): align provider settings with shared settings rows (#10571)
maria-rcks Sep 12, 2026
cf1ba3d
feat(settings): configure default permissions for new threads (#11346)
maria-rcks Sep 12, 2026
fd5553f
fix: restore provider history and prompts when rewinding (#11338)
maria-rcks Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions apps/desktop/src/electron/ElectronShell.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MAC_PERMISSION_SETTINGS_URLS } from "../permissions/MacPermission.ts";
import {
REMOTE_CAPABLE_EDITOR_IDS,
remoteSchemeForEditor,
Expand All @@ -10,20 +11,6 @@ import * as Option from "effect/Option";

import * as Electron from "electron";

/**
* Deep links to individual System Settings panes. These are app-fixed, not
* renderer-supplied, so they skip `parseSafeExternalUrl` — which exists to keep
* arbitrary link schemes from reaching the OS handler — and open through their
* own path below. The pane rather than the URL crosses the IPC boundary, so a
* renderer can only ask for one of these known destinations.
*
* Full Disk Access uses the post-Ventura `PrivacySecurity.extension` anchor.
*/
const SYSTEM_SETTINGS_URLS: Record<SystemSettingsPane, string> = {
"full-disk-access":
"x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?Privacy_AllFiles",
};

// Remote open-in-editor deep links (`vscode://vscode-remote/ssh-remote+…`,
// `zed://ssh/<host>/<path>`) must reach the OS handler; every other non-web
// scheme stays blocked.
Expand Down Expand Up @@ -88,7 +75,7 @@ export const make = ElectronShell.of({
}),
openSystemSettings: (pane) =>
Effect.promise(() =>
Electron.shell.openExternal(SYSTEM_SETTINGS_URLS[pane]).then(
Electron.shell.openExternal(MAC_PERMISSION_SETTINGS_URLS[pane]).then(
() => true,
() => false,
),
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/ipc/DesktopIpcHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
getWindowFullscreenState,
openExternal,
openSystemSettings,
checkSystemPermission,
probeRemoteEditors,
pickFolder,
pickProjectFavicon,
Expand Down Expand Up @@ -122,6 +123,7 @@ export const installDesktopIpcHandlers = Effect.fn("desktop.ipc.installHandlers"
yield* ipc.handle(showContextMenu);
yield* ipc.handle(openExternal);
yield* ipc.handle(openSystemSettings);
yield* ipc.handle(checkSystemPermission);
yield* ipc.handle(probeRemoteEditors);
yield* ipc.handle(getUpdateState);
yield* ipc.handle(setUpdateChannel);
Expand Down
4 changes: 4 additions & 0 deletions apps/desktop/src/ipc/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,7 @@ export const PREVIEW_RECORDING_SAVE_CHANNEL = "desktop:preview-recording-save";
export const PREVIEW_RECORDING_FRAME_CHANNEL = "desktop:preview-recording-frame";
export const PREVIEW_STATE_CHANGE_CHANNEL = "desktop:preview-state-change";
export const PREVIEW_POINTER_EVENT_CHANNEL = "desktop:preview-pointer-event";

export const MAC_PERMISSION_HELPER_CHANNEL = "desktop:mac-permission-helper";

export const CHECK_SYSTEM_PERMISSION_CHANNEL = "desktop:check-system-permission";
26 changes: 25 additions & 1 deletion apps/desktop/src/ipc/methods/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ import * as ElectronMenu from "../../electron/ElectronMenu.ts";
import * as ElectronShell from "../../electron/ElectronShell.ts";
import * as ElectronTheme from "../../electron/ElectronTheme.ts";
import * as ElectronWindow from "../../electron/ElectronWindow.ts";
import * as Electron from "electron";
import * as MacPermissions from "../../permissions/MacPermissions.ts";
import { safariPermissionCheck } from "../../preview/BrowserImport/SafariPermission.ts";
import * as IpcChannels from "../channels.ts";
import * as DesktopIpc from "../DesktopIpc.ts";
import {
Expand Down Expand Up @@ -305,7 +308,16 @@ export const openSystemSettings = DesktopIpc.makeIpcMethod({
result: Schema.Boolean,
handler: Effect.fn("desktop.ipc.window.openSystemSettings")(function* (pane) {
const shell = yield* ElectronShell.ElectronShell;
return yield* shell.openSystemSettings(pane);
const environment = yield* DesktopEnvironment.DesktopEnvironment;
if (environment.platform !== "darwin") return false;
const owner = Electron.BrowserWindow.getFocusedWindow();
const opened = yield* shell.openSystemSettings(pane);
if (opened && environment.isPackaged) {
const permissions = yield* MacPermissions.MacPermissions;
const isGranted = yield* safariPermissionCheck;
yield* permissions.showHelper(pane, owner, isGranted);
}
return opened;
}),
});

Expand Down Expand Up @@ -379,3 +391,15 @@ export const pickThemeFiles = DesktopIpc.makeIpcMethod({
});
}),
});

export const checkSystemPermission = DesktopIpc.makeIpcMethod({
channel: IpcChannels.CHECK_SYSTEM_PERMISSION_CHANNEL,
payload: SystemSettingsPaneSchema,
result: Schema.Boolean,
handler: Effect.fn("desktop.ipc.window.checkSystemPermission")(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
if (environment.platform !== "darwin") return false;
const check = yield* safariPermissionCheck;
return yield* Effect.promise(check);
}),
});
17 changes: 17 additions & 0 deletions apps/desktop/src/mac-permission-preload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ipcRenderer } from "electron";
import { MAC_PERMISSION_HELPER_CHANNEL } from "./ipc/channels.ts";

// This preload belongs only to the static permission panel. No general desktop bridge is exposed.
window.addEventListener("DOMContentLoaded", () => {
const send = (action: "drag" | "finder" | "close") =>
ipcRenderer.send(MAC_PERMISSION_HELPER_CHANNEL, action);
document.getElementById("app")?.addEventListener("dragstart", (event) => {
event.preventDefault();
send("drag");
});
document.getElementById("app")?.addEventListener("click", () => send("finder"));
document.getElementById("close")?.addEventListener("click", () => send("close"));
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") send("close");
});
});
2 changes: 2 additions & 0 deletions apps/desktop/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as MacPermissions from "./permissions/MacPermissions.ts";
for (const stream of [process.stdout, process.stderr]) {
stream.on("error", (err: NodeJS.ErrnoException) => {
if (err.code !== "EPIPE") throw err;
Expand Down Expand Up @@ -133,6 +134,7 @@ const electronLayer = Layer.mergeAll(
);

const desktopFoundationLayer = Layer.mergeAll(
MacPermissions.layer,
DesktopState.layer,
DesktopShutdown.layer,
DesktopAppSettings.layer,
Expand Down
15 changes: 15 additions & 0 deletions apps/desktop/src/permissions/MacPermission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const MAC_PERMISSION_SETTINGS_URLS = {
"screen-recording":
"x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",
accessibility: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility",
"full-disk-access":
"x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?Privacy_AllFiles",
};

export type MacPermission = keyof typeof MAC_PERMISSION_SETTINGS_URLS;

export const MAC_PERMISSION_TITLES: Record<MacPermission, string> = {
"screen-recording": "Screen Recording",
accessibility: "Accessibility",
"full-disk-access": "Full Disk Access",
};
Loading
Loading