ReviewOS

also looking at this

stacks/launchpad

Claude/app issues review e7f207

#16
Merged glennmichael123 wants to merge claude/app-issues-review-e7f207 into main
8 files +112 -35
resources/functions/native.tsmodified+11-7
Changes to resources/functions/native.ts
@@ -2,7 +2,7 @@ import { app, appleScript, clipboard, globalShortcuts, nativeWindow, nativeTray,
22import { createExecutor } from './execution'
33import { createApplicationIconLoader } from './application-icons'
44import { clipboardDecision } from './clipboard'
5import { describeScriptFailure } from './applescript'
5import { PermissionError, describeScriptFailure } from './applescript'
66import { contactOpenScript } from './contacts'
77import { eventOpenScript } from './calendar'
88import { createSources } from './sources'
@@ -72,10 +72,14 @@ export async function registerLauncher(show: () => void): Promise<() => void> {
7272export const behavior = { paste: false }
7373
7474const runScript = (source: string) => appleScript.execute(source)
75async function script(source: string | null, refusal: string) {
75/** `app` is the application the script talks to, so a refusal names the Automation switch that has to be on. */
76async function script(source: string | null, app: string, refusal: string) {
7677 if (!source) throw new Error(refusal)
7778 const outcome = await runScript(source)
78 if (!outcome.ok) throw new Error(`${refusal} ${describeScriptFailure('that app', outcome).message}`)
79 if (!outcome.ok) {
80 const { message, permission } = describeScriptFailure(app, outcome)
81 throw new PermissionError(`${refusal} ${message}`, permission)
82 }
7983}
8084
8185/** Type Command V into the app that regains focus when the palette hides. Needs the Accessibility permission. */
@@ -86,7 +90,7 @@ export async function pasteIntoFrontmost(): Promise<void> {
8690 }
8791 // The palette is hiding; wait for macOS to hand focus back before sending the keystroke.
8892 await new Promise(resolve => setTimeout(resolve, 180))
89 await script('tell application "System Events" to keystroke "v" using command down', 'Launchpad could not paste.')
93 await script('tell application "System Events" to keystroke "v" using command down', 'System Events', 'Launchpad could not paste.')
9094}
9195
9296export const execute = createExecutor({
@@ -98,9 +102,9 @@ export const execute = createExecutor({
98102 openUrl: url => shell.openExternal(url),
99103 openPath: path => shell.openPath(path),
100104 }),
101 focusWindow: token => script(windowFocusScript(token), 'Launchpad could not switch to that window.'),
102 openContact: id => script(contactOpenScript(id), 'Launchpad could not open that contact.'),
103 openEvent: uid => script(eventOpenScript(uid), 'Launchpad could not open that event.'),
105 focusWindow: token => script(windowFocusScript(token), 'System Events', 'Launchpad could not switch to that window.'),
106 openContact: id => script(contactOpenScript(id), 'Contacts', 'Launchpad could not open that contact.'),
107 openEvent: uid => script(eventOpenScript(uid), 'Calendar', 'Launchpad could not open that event.'),
104108 expandText: text => expandSnippet(text, { now: new Date(), uuid: () => crypto.randomUUID(), clipboard: () => clipboard.readText().then(value => value ?? '') }),
105109 pasteText: async () => { if (behavior.paste) await pasteIntoFrontmost() },
106110})