Skip to content

Commit aafd0d1

Browse files
feat(desktop): drop the command palette snapshot action
The palette path captured the previous app by hiding T3 Code, which needed a second capture target and a window hide/show dance, and it skipped the enabled check, so a fresh install with SnapShots off could trigger the macOS Screen Recording prompt from the palette. The shortcut is the one way in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent fadcd12 commit aafd0d1

10 files changed

Lines changed: 3 additions & 83 deletions

File tree

apps/desktop/src/ipc/DesktopIpcHandlers.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ import {
4848
} from "./methods/window.ts";
4949
import {
5050
acknowledgeSnapShot,
51-
captureWindow,
5251
checkSnapShotShortcut,
5352
dismissSnapShotAnimation,
5453
getSnapShotState,
@@ -88,7 +87,6 @@ export const installDesktopIpcHandlers = Effect.fn("desktop.ipc.installHandlers"
8887
yield* ipc.handle(requestSnapShotPermissions);
8988
yield* ipc.handle(checkSnapShotShortcut);
9089
yield* ipc.handle(setSnapShotShortcutSuppressed);
91-
yield* ipc.handle(captureWindow);
9290
yield* ipc.handle(listPendingSnapShots);
9391
yield* ipc.handle(readSnapShot);
9492
yield* ipc.handle(setSnapShotAnimationDestination);

apps/desktop/src/ipc/channels.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export const GET_SNAP_SHOT_STATE_CHANNEL = "desktop:get-snap-shot-state";
3535
export const CHECK_SNAP_SHOT_SHORTCUT_CHANNEL = "desktop:check-snap-shot-shortcut";
3636
export const SET_SNAP_SHOT_SHORTCUT_SUPPRESSED_CHANNEL =
3737
"desktop:set-snap-shot-shortcut-suppressed";
38-
export const CAPTURE_WINDOW_CHANNEL = "desktop:capture-window";
3938
export const LIST_PENDING_SNAP_SHOTS_CHANNEL = "desktop:list-pending-snap-shots";
4039
export const READ_SNAP_SHOT_CHANNEL = "desktop:read-snap-shot";
4140
export const SET_SNAP_SHOT_ANIMATION_DESTINATION_CHANNEL =

apps/desktop/src/ipc/methods/snapShot.test.ts

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import * as ElectronWindow from "../../electron/ElectronWindow.ts";
99
import * as ElectronDialog from "../../electron/ElectronDialog.ts";
1010
import * as DesktopSnapShot from "../../snapShot/DesktopSnapShot.ts";
1111
import {
12-
captureWindow,
1312
checkSnapShotShortcut,
1413
requestSnapShotPermissions,
1514
setupSnapShot,
@@ -214,36 +213,6 @@ describe("window capture IPC", () => {
214213
}).pipe(Effect.provide(layer));
215214
});
216215

217-
it.effect("uses the manual capture path for a trusted renderer", () => {
218-
let globalCaptures = 0;
219-
let manualCaptures = 0;
220-
const layer = Layer.mergeAll(
221-
Layer.succeed(
222-
ElectronWindow.ElectronWindow,
223-
ElectronWindow.ElectronWindow.of({
224-
main: Effect.succeed(Option.some({ webContents: { id: 7 } })),
225-
} as ElectronWindow.ElectronWindow["Service"]),
226-
),
227-
Layer.succeed(
228-
DesktopSnapShot.DesktopSnapShot,
229-
DesktopSnapShot.DesktopSnapShot.of({
230-
capture: Effect.sync(() => {
231-
globalCaptures += 1;
232-
}),
233-
captureNow: Effect.sync(() => {
234-
manualCaptures += 1;
235-
}),
236-
} as unknown as DesktopSnapShot.DesktopSnapShot["Service"]),
237-
),
238-
);
239-
240-
return Effect.gen(function* () {
241-
yield* captureWindow.handler(undefined, { sender: { id: 7 } });
242-
assert.strictEqual(globalCaptures, 0);
243-
assert.strictEqual(manualCaptures, 1);
244-
}).pipe(Effect.provide(layer));
245-
});
246-
247216
it.effect("forwards the accessibility permission preference from a trusted renderer", () => {
248217
let includeAccessibility: boolean | undefined;
249218
const webContents = { id: 7 };
@@ -273,7 +242,9 @@ describe("window capture IPC", () => {
273242

274243
it.effect("rejects an untrusted renderer at the IPC boundary", () =>
275244
Effect.gen(function* () {
276-
const exit = yield* Effect.exit(captureWindow.handler(undefined, { sender: { id: 8 } }));
245+
const exit = yield* Effect.exit(
246+
requestSnapShotPermissions.handler(false, { sender: { id: 8 } }),
247+
);
277248
assert(Exit.isFailure(exit));
278249
const failure = Cause.findErrorOption(exit.cause);
279250
assert(Option.isSome(failure));

apps/desktop/src/ipc/methods/snapShot.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,6 @@ export const setSnapShotShortcutSuppressed = DesktopIpc.makeIpcMethod({
161161
}),
162162
});
163163

164-
export const captureWindow = DesktopIpc.makeIpcMethod({
165-
channel: IpcChannels.CAPTURE_WINDOW_CHANNEL,
166-
payload: Schema.Void,
167-
result: Schema.Void,
168-
handler: Effect.fn("desktop.ipc.snapShot.capture")(function* (_, event) {
169-
yield* ensureTrustedSnapShotSender(event);
170-
yield* (yield* DesktopSnapShot.DesktopSnapShot).captureNow;
171-
}),
172-
});
173-
174164
export const listPendingSnapShots = DesktopIpc.makeIpcMethod({
175165
channel: IpcChannels.LIST_PENDING_SNAP_SHOTS_CHANNEL,
176166
payload: Schema.Void,

apps/desktop/src/preload.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ contextBridge.exposeInMainWorld("desktopBridge", {
6666
ipcRenderer.invoke(IpcChannels.CHECK_SNAP_SHOT_SHORTCUT_CHANNEL, shortcut),
6767
setSnapShotShortcutSuppressed: (suppressed) =>
6868
ipcRenderer.invoke(IpcChannels.SET_SNAP_SHOT_SHORTCUT_SUPPRESSED_CHANNEL, suppressed),
69-
captureWindow: () => ipcRenderer.invoke(IpcChannels.CAPTURE_WINDOW_CHANNEL),
7069
listPendingSnapShots: () => ipcRenderer.invoke(IpcChannels.LIST_PENDING_SNAP_SHOTS_CHANNEL),
7170
readSnapShot: (id) => ipcRenderer.invoke(IpcChannels.READ_SNAP_SHOT_CHANNEL, id),
7271
setSnapShotAnimationDestination: (destination) =>

apps/web/src/components/CommandPalette.tsx

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
squashAtomCommandFailure,
2525
} from "@t3tools/client-runtime/state/runtime";
2626
import {
27-
type DesktopSnapShotState,
2827
type DesktopWslState,
2928
type EnvironmentId,
3029
type EnvironmentMachineKind,
@@ -40,7 +39,6 @@ import { useLocation, useNavigate, useParams } from "@tanstack/react-router";
4039
import * as Option from "effect/Option";
4140
import {
4241
ArrowLeftIcon,
43-
CameraIcon,
4442
CornerLeftUpIcon,
4543
FileSearchIcon,
4644
FolderIcon,
@@ -85,7 +83,6 @@ import { useEnvironments, usePrimaryEnvironmentId } from "../state/environments"
8583
import { useProjects, useThreadShells } from "../state/entities";
8684
import { useThreadSearch } from "../state/queries";
8785
import { resolveThreadActionProjectRef, startNewThreadFromContext } from "../lib/chatThreadActions";
88-
import { getDesktopSnapShotBridge } from "../lib/desktopSnapShot";
8986
import {
9087
appendBrowsePathSegment,
9188
ensureBrowseDirectoryPath,
@@ -578,8 +575,6 @@ function OpenCommandPaletteDialog(props: {
578575
const pathname = useLocation({ select: (location) => location.pathname });
579576
const { clearOpenIntent, openIntent, openOverlayMode, setOpen } = props;
580577
const [query, setQuery] = useState("");
581-
const snapShotBridge = getDesktopSnapShotBridge();
582-
const [snapShotState, setSnapShotState] = useState<DesktopSnapShotState | null>(null);
583578
const deferredQuery = useDeferredValue(query);
584579
const isActionsOnly = deferredQuery.startsWith(">");
585580
const [highlightedItemValue, setHighlightedItemValue] = useState<string | null>(null);
@@ -697,19 +692,6 @@ function OpenCommandPaletteDialog(props: {
697692
[clientSettings],
698693
);
699694

700-
useEffect(() => {
701-
let active = true;
702-
void snapShotBridge
703-
?.getSnapShotState()
704-
.then((state) => {
705-
if (active) setSnapShotState(state);
706-
})
707-
.catch(() => undefined);
708-
return () => {
709-
active = false;
710-
};
711-
}, [snapShotBridge]);
712-
713695
const environmentLabelById = useMemo(
714696
() =>
715697
new Map(
@@ -1649,19 +1631,6 @@ function OpenCommandPaletteDialog(props: {
16491631
},
16501632
});
16511633

1652-
if (snapShotBridge && snapShotState && snapShotState.mode !== "unavailable") {
1653-
actionItems.push({
1654-
kind: "action",
1655-
value: "action:capture-window",
1656-
searchTerms: ["capture window", "screenshot", "attach", "snap"],
1657-
title: "Take snapshot",
1658-
icon: <CameraIcon className={ITEM_ICON_CLASS} />,
1659-
run: async () => {
1660-
await snapShotBridge.captureWindow().catch(() => undefined);
1661-
},
1662-
});
1663-
}
1664-
16651634
actionItems.push({
16661635
kind: "action",
16671636
value: "action:add-project",

apps/web/src/components/desktop/SnapShotCoordinator.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ describe("window capture failures", () => {
7575
getSnapShotState: vi.fn(),
7676
checkSnapShotShortcut: vi.fn(),
7777
setSnapShotShortcutSuppressed: vi.fn(),
78-
captureWindow: vi.fn(),
7978
listPendingSnapShots: vi.fn(),
8079
readSnapShot: vi.fn(),
8180
acknowledgeSnapShot: vi.fn(),
@@ -157,7 +156,6 @@ describe("window capture delivery", () => {
157156
getSnapShotState: vi.fn(),
158157
checkSnapShotShortcut: vi.fn(),
159158
setSnapShotShortcutSuppressed: vi.fn(async () => undefined),
160-
captureWindow: vi.fn(async () => undefined),
161159
listPendingSnapShots: vi.fn(async () => []),
162160
readSnapShot: vi.fn(async () => ({
163161
id: "12345678-1234-1234-1234-123456789abc",

apps/web/src/lib/desktopSnapShot.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ describe("getDesktopSnapShotBridge", () => {
3131
getSnapShotState: vi.fn(),
3232
checkSnapShotShortcut: vi.fn(),
3333
setSnapShotShortcutSuppressed: vi.fn(),
34-
captureWindow: vi.fn(),
3534
listPendingSnapShots: vi.fn(),
3635
readSnapShot: vi.fn(),
3736
acknowledgeSnapShot: vi.fn(),

apps/web/src/lib/desktopSnapShot.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ type SnapShotMethods =
1818
| "getSnapShotState"
1919
| "checkSnapShotShortcut"
2020
| "setSnapShotShortcutSuppressed"
21-
| "captureWindow"
2221
| "listPendingSnapShots"
2322
| "readSnapShot"
2423
| "acknowledgeSnapShot";
@@ -32,7 +31,6 @@ export function getDesktopSnapShotBridge(): DesktopSnapShotBridge | undefined {
3231
typeof bridge?.getSnapShotState !== "function" ||
3332
typeof bridge.checkSnapShotShortcut !== "function" ||
3433
typeof bridge.setSnapShotShortcutSuppressed !== "function" ||
35-
typeof bridge.captureWindow !== "function" ||
3634
typeof bridge.listPendingSnapShots !== "function" ||
3735
typeof bridge.readSnapShot !== "function" ||
3836
typeof bridge.acknowledgeSnapShot !== "function"

packages/contracts/src/ipc.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,6 @@ export interface DesktopBridge {
12351235
shortcut: SnapShotShortcut,
12361236
) => Promise<DesktopSnapShotShortcutAvailability>;
12371237
setSnapShotShortcutSuppressed?: (suppressed: boolean) => Promise<void>;
1238-
captureWindow?: () => Promise<void>;
12391238
listPendingSnapShots?: () => Promise<readonly DesktopPendingSnapShot[]>;
12401239
readSnapShot?: (id: string) => Promise<DesktopSnapShot>;
12411240
setSnapShotAnimationDestination?: (

0 commit comments

Comments
 (0)