diff --git a/src/renderer/src/components/shared/MacFolderAccessFixDialog.test.tsx b/src/renderer/src/components/shared/MacFolderAccessFixDialog.test.tsx
index 1705076d27d..37511ce4432 100644
--- a/src/renderer/src/components/shared/MacFolderAccessFixDialog.test.tsx
+++ b/src/renderer/src/components/shared/MacFolderAccessFixDialog.test.tsx
@@ -30,13 +30,12 @@ function restartButton(): HTMLElement {
return screen.getByRole('button', { name: /^Restart/ })
}
-/** Scoped to the footer: DialogContent's own dismiss X carries the same accessible name. */
-function footerCloseButton(): HTMLElement {
+function footerButton(name: string): HTMLElement {
const footer = screen.getByRole('dialog').querySelector('[data-slot="dialog-footer"]')
if (!(footer instanceof HTMLElement)) {
throw new Error('dialog footer did not render')
}
- return within(footer).getByRole('button', { name: 'Close' })
+ return within(footer).getByRole('button', { name })
}
beforeEach(() => {
@@ -83,27 +82,28 @@ describe('MacFolderAccessFixDialog', () => {
expect(restartButton().hasAttribute('disabled')).toBe(false)
})
- it('opens step one and blocks Restart when Orca itself is denied', () => {
+ it('makes System Settings the only action when Orca itself is denied', () => {
openWith(false)
render()
- expect(screen.getByRole('button', { name: 'Open System Settings' })).toBeTruthy()
- expect(restartButton().hasAttribute('disabled')).toBe(true)
+ expect(footerButton('Open System Settings')).toBeTruthy()
+ expect(screen.queryByRole('button', { name: /^Restart/ })).toBeNull()
})
// An unanswered probe must not accuse the user of a missing grant, but the pane stays reachable.
- it('keeps both steps available when the probe could not answer', () => {
+ it('keeps both actions and says so when the probe could not answer', () => {
openWith(null)
render()
- expect(screen.getByRole('button', { name: 'Open System Settings' })).toBeTruthy()
+ expect(footerButton('Open System Settings')).toBeTruthy()
expect(restartButton().hasAttribute('disabled')).toBe(false)
+ expect(screen.getByText(/Orca couldn’t check this/)).toBeTruthy()
})
it('flips step one to done when a later poll reports the grant landed', async () => {
openWith(false)
render()
- expect(restartButton().hasAttribute('disabled')).toBe(true)
+ expect(screen.queryByRole('button', { name: /^Restart/ })).toBeNull()
act(() => {
useMacFolderAccessFixStore.getState().observeMismatch({
@@ -171,7 +171,9 @@ describe('MacFolderAccessFixDialog', () => {
await waitFor(() => {
expect(
- screen.getByText('Done. Terminals opened in your Documents folder can read it now.')
+ screen.getByText(
+ 'Terminal service restarted. Terminals in your Documents folder should work now.'
+ )
).toBeTruthy()
})
expect(screen.queryByRole('button', { name: /^Restart/ })).toBeNull()
@@ -209,11 +211,11 @@ describe('MacFolderAccessFixDialog', () => {
expect(restartButton().hasAttribute('disabled')).toBe(false)
})
- it('closes on Close', async () => {
+ it('closes on Cancel', async () => {
openWith(true)
render()
- await userEvent.click(footerCloseButton())
+ await userEvent.click(footerButton('Cancel'))
expect(useMacFolderAccessFixStore.getState().open).toBe(false)
})
diff --git a/src/renderer/src/components/shared/MacFolderAccessFixDialog.tsx b/src/renderer/src/components/shared/MacFolderAccessFixDialog.tsx
index 3910eb9b951..b799653ad3c 100644
--- a/src/renderer/src/components/shared/MacFolderAccessFixDialog.tsx
+++ b/src/renderer/src/components/shared/MacFolderAccessFixDialog.tsx
@@ -23,13 +23,11 @@ type RestartState = 'idle' | 'busy' | 'done' | 'failed'
function Step({
done,
label,
- helper,
- action
+ helper
}: {
done: boolean
label: string
helper?: string
- action?: React.ReactNode
}): React.JSX.Element {
return (
@@ -38,10 +36,9 @@ function Step({
) : (
)}
-
+
{label}
{helper ? {helper} : null}
- {action}
)
@@ -49,38 +46,29 @@ function Step({
function FixSteps({
mismatch,
- restartState,
- onOpenSettings,
- onRestart
+ restartState
}: {
mismatch: PtyManagementFolderAccessMismatch
restartState: RestartState
- onOpenSettings: () => void
- onRestart: () => void
}): React.JSX.Element {
- // Why `!== false`: a probe that could not answer must not accuse the user of a missing grant.
- const allowed = mismatch.restartWillHelp !== false
- const busy = restartState === 'busy'
return (
<>
- {translate(
- 'auto.components.shared.MacFolderAccessFixDialog.openSystemSettings',
- 'Open System Settings'
- )}
-
- )
+ helper={
+ // Why only when unanswered: a probe that could not answer must not accuse the user of a
+ // missing grant, but it must say why the step is left to them.
+ mismatch.restartWillHelp === null
+ ? translate(
+ 'auto.components.shared.MacFolderAccessFixDialog.stepAllowUnknown',
+ 'Orca couldn’t check this. Skip it if Orca is already allowed.'
+ )
+ : undefined
}
/>
- {busy ? : null}
- {busy
- ? translate(
- 'auto.components.shared.MacFolderAccessFixDialog.restarting',
- 'Restarting…'
- )
- : translate('auto.components.shared.MacFolderAccessFixDialog.restart', 'Restart')}
-
- }
/>
{restartState === 'failed' ? (
@@ -118,6 +95,65 @@ function FixSteps({
)
}
+/** The footer carries the active step's one action, so the steps stay a checklist. */
+function FixFooter({
+ mismatch,
+ restartState,
+ onCancel,
+ onOpenSettings,
+ onRestart
+}: {
+ mismatch: PtyManagementFolderAccessMismatch
+ restartState: RestartState
+ onCancel: () => void
+ onOpenSettings: () => void
+ onRestart: () => void
+}): React.JSX.Element {
+ const busy = restartState === 'busy'
+ const openSettingsLabel = translate(
+ 'auto.components.shared.MacFolderAccessFixDialog.openSystemSettings',
+ 'Open System Settings'
+ )
+ if (restartState === 'done') {
+ return (
+
+ )
+ }
+ if (mismatch.restartWillHelp === false) {
+ return (
+ <>
+
+
+ >
+ )
+ }
+ return (
+ <>
+ {mismatch.restartWillHelp === null ? (
+
+ ) : (
+
+ )}
+
+ >
+ )
+}
+
/**
* The remedy for a daemon macOS refuses a folder to (STA-7948), raised from the folder-access
* toast. Two steps, because a restart alone only works once Orca itself is allowed again — which
@@ -209,22 +245,21 @@ export function MacFolderAccessFixDialog(): React.JSX.Element | null {
{translate(
'auto.components.shared.MacFolderAccessFixDialog.done',
- 'Done. Terminals opened in your {{folder}} can read it now.',
+ 'Terminal service restarted. Terminals in your {{folder}} should work now.',
{ folder }
)}
) : (
-
+ )}
+
+ void onRestart()}
/>
- )}
-
-
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index 6dd8141d3c4..5f8958f0cd2 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -6414,8 +6414,10 @@
"restartFailed": "Restart failed. Try again from Settings → Terminal → Manage Sessions.",
"title": "Fix access to your {{folder}}",
"lead": "macOS is blocking Orca’s terminal service from this folder.",
- "done": "Done. Terminals opened in your {{folder}} can read it now.",
- "close": "Close"
+ "done": "Terminal service restarted. Terminals in your {{folder}} should work now.",
+ "close": "Close",
+ "cancel": "Cancel",
+ "stepAllowUnknown": "Orca couldn’t check this. Skip it if Orca is already allowed."
},
"macFolderAccessFolderName": {
"documents": "Documents folder",