mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
This reverts commit 7d24dad48a.
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { act } from 'react'
|
||||
import { createRoot, type Root } from 'react-dom/client'
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
|
||||
import type { DeveloperPermissionState } from '../../../../shared/developer-permissions-types'
|
||||
import { FULL_DISK_ACCESS_SETTINGS_TARGET_ID } from '@/lib/settings-navigation-types'
|
||||
import { DeveloperPermissionsPane } from './DeveloperPermissionsPane'
|
||||
|
||||
let container: HTMLDivElement
|
||||
let root: Root
|
||||
|
||||
beforeEach(() => {
|
||||
Object.assign(window, {
|
||||
api: {
|
||||
developerPermissions: {
|
||||
getStatus: vi.fn(
|
||||
async (): Promise<DeveloperPermissionState[]> => [
|
||||
{ id: 'full-disk-access', status: 'denied' }
|
||||
]
|
||||
),
|
||||
request: vi.fn()
|
||||
}
|
||||
}
|
||||
})
|
||||
container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
root = createRoot(container)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await act(async () => root.unmount())
|
||||
container.remove()
|
||||
Reflect.deleteProperty(window, 'api')
|
||||
})
|
||||
|
||||
it('highlights the Full Disk Access row for a targeted Settings navigation', async () => {
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<DeveloperPermissionsPane highlightedSettingId={FULL_DISK_ACCESS_SETTINGS_TARGET_ID} />
|
||||
)
|
||||
})
|
||||
|
||||
const row = container.querySelector<HTMLElement>(
|
||||
`[data-settings-section="${FULL_DISK_ACCESS_SETTINGS_TARGET_ID}"]`
|
||||
)
|
||||
expect(row?.dataset.highlighted).toBe('true')
|
||||
expect(row?.className).toContain('data-[highlighted=true]:ring-annotation-highlight/60')
|
||||
|
||||
await act(async () => root.render(<DeveloperPermissionsPane />))
|
||||
expect(row?.dataset.highlighted).toBeUndefined()
|
||||
})
|
||||
@@ -23,10 +23,6 @@ import { Button } from '../ui/button'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
export { getDeveloperPermissionsPaneSearchEntries } from './developer-permissions-search'
|
||||
|
||||
type DeveloperPermissionsPaneProps = {
|
||||
highlightedSettingId?: string | null
|
||||
}
|
||||
|
||||
type PermissionDefinition = {
|
||||
id: DeveloperPermissionId
|
||||
label: string
|
||||
@@ -206,9 +202,7 @@ function statusClass(status: DeveloperPermissionStatus | undefined): string {
|
||||
return 'border-border bg-muted text-muted-foreground'
|
||||
}
|
||||
|
||||
export function DeveloperPermissionsPane({
|
||||
highlightedSettingId = null
|
||||
}: DeveloperPermissionsPaneProps): React.JSX.Element {
|
||||
export function DeveloperPermissionsPane(): React.JSX.Element {
|
||||
const [states, setStates] = useState<DeveloperPermissionState[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [pendingId, setPendingId] = useState<DeveloperPermissionId | null>(null)
|
||||
@@ -346,15 +340,9 @@ export function DeveloperPermissionsPane({
|
||||
{PERMISSIONS.map((permission) => {
|
||||
const status = stateById.get(permission.id)
|
||||
const pending = pendingId === permission.id
|
||||
const settingId = `developer-permissions-${permission.id}`
|
||||
|
||||
return (
|
||||
<div
|
||||
key={permission.id}
|
||||
data-settings-section={settingId}
|
||||
data-highlighted={highlightedSettingId === settingId ? 'true' : undefined}
|
||||
className="flex items-center justify-between gap-4 px-4 py-3 transition-[background-color,box-shadow] duration-500 data-[highlighted=true]:bg-annotation-highlight/10 data-[highlighted=true]:ring-2 data-[highlighted=true]:ring-inset data-[highlighted=true]:ring-annotation-highlight/60 motion-reduce:transition-none"
|
||||
>
|
||||
<div key={permission.id} className="flex items-center justify-between gap-4 px-4 py-3">
|
||||
<div className="flex min-w-0 items-start gap-3">
|
||||
<div className="mt-0.5 text-muted-foreground">{permission.icon}</div>
|
||||
<div className="min-w-0 space-y-1">
|
||||
|
||||
@@ -177,7 +177,6 @@ const SETTINGS_NAV_GROUP_BY_ID = new Map<string, SettingsNavGroupDefinition>(
|
||||
|
||||
const SHORTCUTS_ESCAPE_CONFIRM_TOAST_ID = 'shortcuts-escape-confirm'
|
||||
const SHORTCUTS_ESCAPE_CONFIRM_WINDOW_MS = 2200
|
||||
const SETTINGS_TARGET_HIGHLIGHT_MS = 3_000
|
||||
|
||||
function getSettingsSectionId(
|
||||
pane: SettingsNavTarget,
|
||||
@@ -373,9 +372,6 @@ function Settings(): React.JSX.Element {
|
||||
getInitialMountedSectionIds
|
||||
)
|
||||
const [pendingNavRequestTick, setPendingNavRequestTick] = useState(0)
|
||||
const [highlightedSettingsTargetId, setHighlightedSettingsTargetId] = useState<string | null>(
|
||||
null
|
||||
)
|
||||
const [quickCommandAddIntentSignal, setQuickCommandAddIntentSignal] = useState(0)
|
||||
const [sshHostAddIntentSignal, setSshHostAddIntentSignal] = useState(0)
|
||||
const [remoteServerAddIntentSignal, setRemoteServerAddIntentSignal] = useState(0)
|
||||
@@ -450,17 +446,6 @@ function Settings(): React.JSX.Element {
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!highlightedSettingsTargetId) {
|
||||
return
|
||||
}
|
||||
const timeout = window.setTimeout(
|
||||
() => setHighlightedSettingsTargetId(null),
|
||||
SETTINGS_TARGET_HIGHLIGHT_MS
|
||||
)
|
||||
return () => window.clearTimeout(timeout)
|
||||
}, [highlightedSettingsTargetId])
|
||||
|
||||
const requestFontSuggestions = useCallback((): void => {
|
||||
if (installedFontsLoadedRef.current || installedFontsLoadPromiseRef.current) {
|
||||
return
|
||||
@@ -676,11 +661,6 @@ function Settings(): React.JSX.Element {
|
||||
}
|
||||
pendingNavSectionRef.current = paneSectionId
|
||||
pendingScrollTargetRef.current = settingsNavigationTarget.sectionId ?? paneSectionId
|
||||
setHighlightedSettingsTargetId(
|
||||
settingsNavigationTarget.pane === 'developer-permissions'
|
||||
? (settingsNavigationTarget.sectionId ?? null)
|
||||
: null
|
||||
)
|
||||
// Why: ensure Appearance's nested status-bar section is open before scrolling so the row is visible.
|
||||
if (settingsNavigationTarget.pane === 'appearance') {
|
||||
const accordion = resolveAppearanceAccordionDeepLink(settingsNavigationTarget.sectionId)
|
||||
@@ -1716,9 +1696,7 @@ function Settings(): React.JSX.Element {
|
||||
searchEntries={getSectionSearchEntries('developer-permissions')}
|
||||
>
|
||||
{isSectionMounted('developer-permissions') ? (
|
||||
<DeveloperPermissionsPane
|
||||
highlightedSettingId={highlightedSettingsTargetId}
|
||||
/>
|
||||
<DeveloperPermissionsPane />
|
||||
) : null}
|
||||
</SettingsSection>
|
||||
) : null}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { UI_LANGUAGE_SPANISH } from '../../../shared/ui-language'
|
||||
import { useAppStore } from '@/store'
|
||||
import { usePluginLanguagePackStore } from '@/store/plugin-language-packs'
|
||||
import { i18n } from '@/i18n/i18n'
|
||||
import { FULL_DISK_ACCESS_SETTINGS_TARGET_ID } from '@/lib/settings-navigation-types'
|
||||
import { MacosTccPromptNoticeHost } from './MacosTccPromptNoticeHost'
|
||||
import { useMacosTccPromptNotice } from './useMacosTccPromptNotice'
|
||||
|
||||
@@ -96,7 +95,7 @@ it('isolates plugin language-pack discovery from its parent render path', async
|
||||
expect(subscribeToMacosTccPromptNotice).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('connects the notice to the macOS prompt and keeps it open until closed', async () => {
|
||||
it('keeps the notice open until the user closes it', async () => {
|
||||
useAppStore.setState({
|
||||
settings: { ...getDefaultSettings('/tmp'), uiLanguage: 'en' }
|
||||
})
|
||||
@@ -112,13 +111,6 @@ it('connects the notice to the macOS prompt and keeps it open until closed', asy
|
||||
|
||||
showNotice?.({ promptCount: 1 }, acknowledge)
|
||||
|
||||
expect(toastWarning).toHaveBeenCalledWith(
|
||||
'Seeing “Orca would like to access…”?',
|
||||
expect.objectContaining({
|
||||
description:
|
||||
'That macOS message appears when an agent or terminal tool accesses protected files. macOS names Orca because Orca launched the tool. Grant Full Disk Access to Orca and Orca Helper to reduce future prompts.'
|
||||
})
|
||||
)
|
||||
const options = toastWarning.mock.calls[0]?.[1] as
|
||||
| { duration?: number; onDismiss?: () => void }
|
||||
| undefined
|
||||
@@ -149,9 +141,4 @@ it('acknowledges when opening Settings closes the notice', async () => {
|
||||
| undefined
|
||||
options?.action?.onClick()
|
||||
expect(acknowledge).toHaveBeenCalledOnce()
|
||||
expect(useAppStore.getState().settingsNavigationTarget).toEqual({
|
||||
pane: 'developer-permissions',
|
||||
repoId: null,
|
||||
sectionId: FULL_DISK_ACCESS_SETTINGS_TARGET_ID
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,7 +6,6 @@ import { useAppStore } from '@/store'
|
||||
import { usePluginLanguagePackStore } from '@/store/plugin-language-packs'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { resolveUiLocale } from '@/i18n/supported-languages'
|
||||
import { FULL_DISK_ACCESS_SETTINGS_TARGET_ID } from '@/lib/settings-navigation-types'
|
||||
import {
|
||||
dismissMacosTccPromptNotice,
|
||||
subscribeToMacosTccPromptNotice
|
||||
@@ -42,12 +41,12 @@ export function useMacosTccPromptNotice(): void {
|
||||
toast.warning(
|
||||
translate(
|
||||
'auto.hooks.useMacosTccPromptNotice.title',
|
||||
'Seeing “Orca would like to access…”?'
|
||||
'Reduce repeated macOS file-access prompts'
|
||||
),
|
||||
{
|
||||
description: translate(
|
||||
'auto.hooks.useMacosTccPromptNotice.description',
|
||||
'That macOS message appears when an agent or terminal tool accesses protected files. macOS names Orca because Orca launched the tool. Grant Full Disk Access to Orca and Orca Helper to reduce future prompts.'
|
||||
'macOS attributes file access by your agents and terminal tools to Orca. Granting Full Disk Access reduces these prompts.'
|
||||
),
|
||||
duration: Infinity,
|
||||
onDismiss: acknowledge,
|
||||
@@ -56,11 +55,7 @@ export function useMacosTccPromptNotice(): void {
|
||||
onClick: () => {
|
||||
acknowledge()
|
||||
openSettingsPage()
|
||||
openSettingsTarget({
|
||||
pane: 'developer-permissions',
|
||||
repoId: null,
|
||||
sectionId: FULL_DISK_ACCESS_SETTINGS_TARGET_ID
|
||||
})
|
||||
openSettingsTarget({ pane: 'developer-permissions', repoId: null })
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
|
||||
@@ -826,8 +826,8 @@
|
||||
"pasteTooLarge": "Paste is too large."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "Seeing “Orca would like to access…”?",
|
||||
"description": "That macOS message appears when an agent or terminal tool accesses protected files. macOS names Orca because Orca launched the tool. Grant Full Disk Access to Orca and Orca Helper to reduce future prompts.",
|
||||
"title": "Reduce repeated macOS file-access prompts",
|
||||
"description": "macOS attributes file access by your agents and terminal tools to Orca. Granting Full Disk Access reduces these prompts.",
|
||||
"openSettings": "Open Settings",
|
||||
"dismiss": "Don't show again"
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@ const SETTINGS_NAV_TARGET_SET: ReadonlySet<string> = new Set(SETTINGS_NAV_TARGET
|
||||
const SETTINGS_NAV_INTENT_SET: ReadonlySet<string> = new Set(SETTINGS_NAV_INTENTS)
|
||||
|
||||
export type SettingsNavTarget = (typeof SETTINGS_NAV_TARGETS)[number]
|
||||
export const FULL_DISK_ACCESS_SETTINGS_TARGET_ID = 'developer-permissions-full-disk-access'
|
||||
|
||||
export type SettingsNavigationTarget = {
|
||||
pane: SettingsNavTarget
|
||||
repoId: string | null
|
||||
|
||||
Reference in New Issue
Block a user