mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 09:57:48 +00:00
feat(macos): redesign Full Disk Access toast with prompt count illustration (#41849)
* feat(macos): redesign Full Disk Access toast with prompt count illustration * fix(macos): stack FDA toast actions on narrow cards so the button never overflows
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { defineFixture } from '../../component-fixtures/component-fixture'
|
||||
import { FullDiskAccessNudgeToast } from './FullDiskAccessNudgeToast'
|
||||
|
||||
const noop = (): void => {}
|
||||
|
||||
export const singlePrompt = defineFixture({
|
||||
width: 448,
|
||||
render: () => (
|
||||
<FullDiskAccessNudgeToast
|
||||
promptCount={1}
|
||||
onEnable={noop}
|
||||
onClose={noop}
|
||||
onDontShowAgain={noop}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export const repeatedPrompts = defineFixture({
|
||||
width: 448,
|
||||
render: () => (
|
||||
<FullDiskAccessNudgeToast
|
||||
promptCount={3}
|
||||
onEnable={noop}
|
||||
onClose={noop}
|
||||
onDontShowAgain={noop}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export const narrowWindow = defineFixture({
|
||||
width: 300,
|
||||
render: () => (
|
||||
<FullDiskAccessNudgeToast
|
||||
promptCount={3}
|
||||
onEnable={noop}
|
||||
onClose={noop}
|
||||
onDontShowAgain={noop}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export const mediumWindow = defineFixture({
|
||||
width: 360,
|
||||
render: () => (
|
||||
<FullDiskAccessNudgeToast
|
||||
promptCount={1}
|
||||
onEnable={noop}
|
||||
onClose={noop}
|
||||
onDontShowAgain={noop}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,92 @@
|
||||
import { X } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useTranslate } from '@/i18n/use-translate'
|
||||
|
||||
type FullDiskAccessNudgeToastProps = {
|
||||
promptCount: number
|
||||
onEnable: () => void
|
||||
onClose: () => void
|
||||
onDontShowAgain: () => void
|
||||
}
|
||||
|
||||
function StackedPromptsIllustration({ promptCount }: { promptCount: number }): React.JSX.Element {
|
||||
return (
|
||||
<div className="relative h-[58px] w-[74px] shrink-0" aria-hidden="true">
|
||||
<div className="absolute top-[2px] left-[10px] h-[40px] w-[56px] -rotate-6 rounded-[6px] border border-border bg-muted opacity-40" />
|
||||
<div className="absolute top-[7px] left-[6px] h-[40px] w-[56px] rotate-3 rounded-[6px] border border-border bg-muted opacity-70" />
|
||||
<div className="absolute top-[13px] left-[2px] flex h-[42px] w-[58px] flex-col gap-[5px] rounded-[6px] border border-border bg-background px-[7px] pt-[8px] shadow-xs">
|
||||
<span className="h-[3px] w-[34px] rounded-full bg-muted-foreground/50" />
|
||||
<span className="h-[3px] w-[24px] rounded-full bg-muted-foreground/35" />
|
||||
<span className="absolute right-[5px] bottom-[5px] h-[9px] w-[20px] rounded-full bg-callout-note" />
|
||||
</div>
|
||||
<span className="absolute -top-[2px] -right-[4px] min-w-[20px] rounded-full bg-status-warning px-[6px] py-px text-center text-[10.5px] leading-[15px] font-bold text-black">
|
||||
{promptCount}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function FullDiskAccessNudgeToast({
|
||||
promptCount,
|
||||
onEnable,
|
||||
onClose,
|
||||
onDontShowAgain
|
||||
}: FullDiskAccessNudgeToastProps): React.JSX.Element {
|
||||
const t = useTranslate()
|
||||
const title =
|
||||
promptCount > 1
|
||||
? t(
|
||||
'auto.hooks.useMacosTccPromptNotice.titleMany',
|
||||
'macOS interrupted your agents {{count}}×',
|
||||
{ count: promptCount }
|
||||
)
|
||||
: t('auto.hooks.useMacosTccPromptNotice.titleOne', 'macOS just interrupted an agent')
|
||||
|
||||
return (
|
||||
<div className="@container relative w-[26rem] max-w-full rounded-lg border border-border bg-popover px-3.5 py-3.5 text-popover-foreground shadow-floating">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute top-2 right-2 size-7"
|
||||
data-close-button
|
||||
onClick={onClose}
|
||||
aria-label={t('auto.hooks.useMacosTccPromptNotice.close', 'Close')}
|
||||
>
|
||||
<X className="size-3.5" />
|
||||
</Button>
|
||||
<div className="flex items-center gap-4">
|
||||
<StackedPromptsIllustration promptCount={promptCount} />
|
||||
<div className="min-w-0 space-y-1 pr-6">
|
||||
<div className="text-[13.5px] leading-snug font-semibold">{title}</div>
|
||||
<p className="text-[12.5px] leading-snug text-muted-foreground">
|
||||
{t(
|
||||
'auto.hooks.useMacosTccPromptNotice.subtitle',
|
||||
'Full Disk Access stops these file prompts.'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* Why: on a roomy card, indent by illustration width + gap so the actions start
|
||||
under the title. Below ~22rem of card width (20rem content box) that indent would
|
||||
push the button past the border, so the row drops it and stacks full width. */}
|
||||
<div className="mt-3 flex flex-col items-start gap-y-1.5 @[20rem]:ml-[90px] @[20rem]:flex-row @[20rem]:flex-wrap @[20rem]:items-center @[20rem]:gap-x-2">
|
||||
{/* Why: Button is nowrap/shrink-0 by default; let the label wrap rather than overflow. */}
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="h-auto min-h-8 max-w-full whitespace-normal"
|
||||
onClick={onEnable}
|
||||
>
|
||||
{t('auto.hooks.useMacosTccPromptNotice.enable', 'Turn on Full Disk Access')}
|
||||
</Button>
|
||||
<button
|
||||
type="button"
|
||||
className="text-xs text-muted-foreground underline underline-offset-2 hover:text-foreground"
|
||||
onClick={onDontShowAgain}
|
||||
>
|
||||
{t('auto.hooks.useMacosTccPromptNotice.dismiss', "Don't show again")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+32
-33
@@ -7,8 +7,8 @@ import {
|
||||
usePluginLanguagePackStore,
|
||||
usePluginLanguagePacks
|
||||
} from '@/store/plugins/localization/plugin-language-packs'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { resolveUiLocale } from '@/i18n/supported-languages'
|
||||
import { FullDiskAccessNudgeToast } from '@/components/macos-permissions/FullDiskAccessNudgeToast'
|
||||
import { FULL_DISK_ACCESS_SETTINGS_TARGET_ID } from '@/components/settings/navigation/settings-navigation-types'
|
||||
import {
|
||||
dismissMacosTccPromptNotice,
|
||||
@@ -41,39 +41,38 @@ export function useMacosTccPromptNotice(): void {
|
||||
if (!localeReady) {
|
||||
return
|
||||
}
|
||||
return subscribeToMacosTccPromptNotice(window.api?.macosTccPrompts, (_, acknowledge) => {
|
||||
toast.warning(
|
||||
translate(
|
||||
'auto.hooks.useMacosTccPromptNotice.title',
|
||||
'Seeing “Orca would like to access…” prompts?'
|
||||
),
|
||||
{
|
||||
description: translate(
|
||||
'auto.hooks.useMacosTccPromptNotice.description',
|
||||
'Permission messages from macOS may appear when an agent or terminal tool running in Orca attempts to access protected files. Grant Full Disk Access in Settings to reduce these prompts.'
|
||||
return subscribeToMacosTccPromptNotice(
|
||||
window.api?.macosTccPrompts,
|
||||
({ promptCount }, acknowledge) => {
|
||||
toast.custom(
|
||||
(toastId) => (
|
||||
<FullDiskAccessNudgeToast
|
||||
promptCount={promptCount}
|
||||
onClose={() => toast.dismiss(toastId)}
|
||||
onEnable={() => {
|
||||
acknowledge()
|
||||
openSettingsPage()
|
||||
openSettingsTarget({
|
||||
pane: 'developer-permissions',
|
||||
repoId: null,
|
||||
sectionId: FULL_DISK_ACCESS_SETTINGS_TARGET_ID
|
||||
})
|
||||
toast.dismiss(toastId)
|
||||
}}
|
||||
onDontShowAgain={() => {
|
||||
void dismissMacosTccPromptNotice(window.api?.macosTccPrompts)
|
||||
toast.dismiss(toastId)
|
||||
}}
|
||||
/>
|
||||
),
|
||||
duration: Infinity,
|
||||
onDismiss: acknowledge,
|
||||
action: {
|
||||
label: translate('auto.hooks.useMacosTccPromptNotice.openSettings', 'Open Settings'),
|
||||
onClick: () => {
|
||||
acknowledge()
|
||||
openSettingsPage()
|
||||
openSettingsTarget({
|
||||
pane: 'developer-permissions',
|
||||
repoId: null,
|
||||
sectionId: FULL_DISK_ACCESS_SETTINGS_TARGET_ID
|
||||
})
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
label: translate('auto.hooks.useMacosTccPromptNotice.dismiss', "Don't show again"),
|
||||
onClick: () => {
|
||||
void dismissMacosTccPromptNotice(window.api?.macosTccPrompts)
|
||||
}
|
||||
{
|
||||
duration: Infinity,
|
||||
closeButton: false,
|
||||
unstyled: true,
|
||||
onDismiss: acknowledge
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
}, [localeReady, openSettingsPage, openSettingsTarget])
|
||||
}
|
||||
@@ -2113,9 +2113,6 @@
|
||||
"unreadableSkillSource": "Ein Skill-Ordner hat nicht geantwortet, daher ist dieser Status möglicherweise unvollständig."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "Werden Meldungen wie „Orca would like to access…“ angezeigt?",
|
||||
"description": "Berechtigungsabfragen von macOS können erscheinen, wenn ein in Orca ausgeführter Agent oder ein Terminalwerkzeug auf geschützte Dateien zugreift. In den Einstellungen „Full Disk Access“ gewähren, um diese Abfragen zu reduzieren.",
|
||||
"openSettings": "Einstellungen öffnen",
|
||||
"dismiss": "Nicht mehr anzeigen"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -2652,9 +2652,11 @@
|
||||
"unreadableSkillSource": "A skill folder did not respond, so this status may be incomplete."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "Seeing “Orca would like to access…” prompts?",
|
||||
"description": "Permission messages from macOS may appear when an agent or terminal tool running in Orca attempts to access protected files. Grant Full Disk Access in Settings to reduce these prompts.",
|
||||
"openSettings": "Open Settings",
|
||||
"titleOne": "macOS just interrupted an agent",
|
||||
"titleMany": "macOS interrupted your agents {{count}}×",
|
||||
"subtitle": "Full Disk Access stops these file prompts.",
|
||||
"enable": "Turn on Full Disk Access",
|
||||
"close": "Close",
|
||||
"dismiss": "Don't show again"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -1624,9 +1624,6 @@
|
||||
"pasteTooLarge": "El contenido pegado es demasiado grande."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "¿Ves avisos de “Orca quiere acceder…”?",
|
||||
"description": "Los mensajes de permisos de macOS pueden aparecer cuando un agente o una herramienta de terminal que se ejecuta en Orca intenta acceder a archivos protegidos. Concede acceso total al disco en Ajustes para reducir estos avisos.",
|
||||
"openSettings": "Abrir ajustes",
|
||||
"dismiss": "No volver a mostrar"
|
||||
},
|
||||
"useInstalledAgentSkills": {
|
||||
|
||||
@@ -1894,9 +1894,6 @@
|
||||
"unreadableSkillSource": "Un dossier de skill n'a pas répondu ; cet état peut donc être incomplet."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "Vous voyez des invites « Orca souhaite accéder à… » ?",
|
||||
"description": "Des messages d'autorisation macOS peuvent apparaître quand un agent ou un outil de terminal exécuté dans Orca tente d'accéder à des fichiers protégés. Accordez l'Accès complet au disque dans les paramètres pour réduire ces invites.",
|
||||
"openSettings": "Ouvrir les paramètres",
|
||||
"dismiss": "Ne plus afficher"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -1614,9 +1614,6 @@
|
||||
"pasteTooLarge": "貼り付け内容が大きすぎます。"
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "「Orca がアクセスしようとしています…」という確認が表示されますか?",
|
||||
"description": "Orca で実行中の Agent やターミナルツールが保護されたファイルにアクセスしようとすると、macOS の権限メッセージが表示されることがあります。これらの確認を減らすには、設定でフルディスクアクセスを許可してください。",
|
||||
"openSettings": "設定を開く",
|
||||
"dismiss": "今後表示しない"
|
||||
},
|
||||
"useInstalledAgentSkills": {
|
||||
|
||||
@@ -1614,9 +1614,6 @@
|
||||
"pasteTooLarge": "붙여넣기 내용이 너무 큽니다."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "“Orca에서 접근하려고 합니다…” 권한 요청이 표시되나요?",
|
||||
"description": "Orca에서 실행 중인 에이전트나 터미널 도구가 보호된 파일에 접근하려고 하면 macOS 권한 메시지가 표시될 수 있습니다. 이러한 요청을 줄이려면 설정에서 전체 디스크 접근 권한을 허용하세요.",
|
||||
"openSettings": "설정 열기",
|
||||
"dismiss": "다시 표시하지 않기"
|
||||
},
|
||||
"useInstalledAgentSkills": {
|
||||
|
||||
@@ -2528,9 +2528,6 @@
|
||||
"unreadableSkillSource": "Uma pasta de skill não respondeu, então este status pode estar incompleto."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "Está vendo avisos de “O Orca gostaria de acessar…”?",
|
||||
"description": "Mensagens de permissão do macOS podem aparecer quando um agente ou ferramenta de terminal em execução no Orca tenta acessar arquivos protegidos. Conceda Acesso Total ao Disco em Configurações para reduzir esses avisos.",
|
||||
"openSettings": "Abrir Configurações",
|
||||
"dismiss": "Não mostrar novamente"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -2154,9 +2154,6 @@
|
||||
"unreadableSkillSource": "Папка одного из навыков не ответила, поэтому статус может быть неполным."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "Видите запросы «Orca хочет получить доступ…»?",
|
||||
"description": "macOS может запрашивать разрешения, когда агент или инструмент терминала в Orca обращается к защищённым файлам. Предоставьте полный доступ к диску в настройках, чтобы таких запросов стало меньше.",
|
||||
"openSettings": "Открыть настройки",
|
||||
"dismiss": "Больше не показывать"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -2082,9 +2082,6 @@
|
||||
"unreadableSkillSource": "Bir beceri klasörü yanıt vermediği için durum bilgisi eksik olabilir."
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "“Orca şuna erişmek istiyor…” uyarıları mı görüyorsunuz?",
|
||||
"description": "Orca'da çalışan bir ajan veya terminal aracı korumalı dosyalara erişmeye çalıştığında macOS'tan izin mesajları görünebilir. Bu uyarıları azaltmak için Ayarlar'dan Tam Disk Erişimi verin.",
|
||||
"openSettings": "Ayarları Aç",
|
||||
"dismiss": "Bir daha gösterme"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -2061,9 +2061,6 @@
|
||||
"unreadableSkillSource": "技能資料夾沒有回應,因此此狀態可能不完整。"
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "看到「Orca 想要存取…」提示?",
|
||||
"description": "當 Orca 中執行的代理程式或終端機工具嘗試存取受保護的檔案時,macOS 可能會顯示權限訊息。請在「設定」中授予「完整磁碟存取權」,以減少此類提示。",
|
||||
"openSettings": "開啟設定",
|
||||
"dismiss": "不再顯示"
|
||||
},
|
||||
"useMacTccAttributionSeveredNotice": {
|
||||
|
||||
@@ -1800,9 +1800,6 @@
|
||||
"pasteTooLarge": "粘贴内容过大"
|
||||
},
|
||||
"useMacosTccPromptNotice": {
|
||||
"title": "看到\"Orca 想要访问…\"提示?",
|
||||
"description": "当 Orca 中运行的代理或终端工具尝试访问受保护的文件时,macOS 可能会显示权限信息,请在\"设置\"中授予\"完全磁盘访问权限\",以减少此类提示",
|
||||
"openSettings": "打开设置",
|
||||
"dismiss": "不再显示"
|
||||
},
|
||||
"useInstalledAgentSkills": {
|
||||
|
||||
Reference in New Issue
Block a user