mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 06:15:51 +00:00
更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)
* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-2): 格式化 commands (79 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-5): 格式化 components其余 + hooks + tools (232 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md - README.md: 大幅重写,更详细版本历史和配置示例 - Run.ps1: 新增 Windows 启动脚本 - TODO.md: 新增包完成清单 - V6.md: 删除(架构重构规划已不适用) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复以前的问题 * fix: 修复 login 面板的问题 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,289 +1,230 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { homedir } from 'os';
|
||||
import React from 'react';
|
||||
import { logEvent } from 'src/services/analytics/index.js';
|
||||
import { setSessionTrustAccepted } from '../../bootstrap/state.js';
|
||||
import type { Command } from '../../commands.js';
|
||||
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js';
|
||||
import { Box, Link, Text } from '../../ink.js';
|
||||
import { useKeybinding } from '../../keybindings/useKeybinding.js';
|
||||
import { getMcpConfigsByScope } from '../../services/mcp/config.js';
|
||||
import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js';
|
||||
import { checkHasTrustDialogAccepted, saveCurrentProjectConfig } from '../../utils/config.js';
|
||||
import { getCwd } from '../../utils/cwd.js';
|
||||
import { getFsImplementation } from '../../utils/fsOperations.js';
|
||||
import { gracefulShutdownSync } from '../../utils/gracefulShutdown.js';
|
||||
import { Select } from '../CustomSelect/index.js';
|
||||
import { PermissionDialog } from '../permissions/PermissionDialog.js';
|
||||
import { getApiKeyHelperSources, getAwsCommandsSources, getBashPermissionSources, getDangerousEnvVarsSources, getGcpCommandsSources, getHooksSources, getOtelHeadersHelperSources } from './utils.js';
|
||||
import { homedir } from 'os'
|
||||
import React from 'react'
|
||||
import { logEvent } from 'src/services/analytics/index.js'
|
||||
import { setSessionTrustAccepted } from '../../bootstrap/state.js'
|
||||
import type { Command } from '../../commands.js'
|
||||
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js'
|
||||
import { Box, Link, Text } from '../../ink.js'
|
||||
import { useKeybinding } from '../../keybindings/useKeybinding.js'
|
||||
import { getMcpConfigsByScope } from '../../services/mcp/config.js'
|
||||
import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js'
|
||||
import {
|
||||
checkHasTrustDialogAccepted,
|
||||
saveCurrentProjectConfig,
|
||||
} from '../../utils/config.js'
|
||||
import { getCwd } from '../../utils/cwd.js'
|
||||
import { getFsImplementation } from '../../utils/fsOperations.js'
|
||||
import { gracefulShutdownSync } from '../../utils/gracefulShutdown.js'
|
||||
import { Select } from '../CustomSelect/index.js'
|
||||
import { PermissionDialog } from '../permissions/PermissionDialog.js'
|
||||
import {
|
||||
getApiKeyHelperSources,
|
||||
getAwsCommandsSources,
|
||||
getBashPermissionSources,
|
||||
getDangerousEnvVarsSources,
|
||||
getGcpCommandsSources,
|
||||
getHooksSources,
|
||||
getOtelHeadersHelperSources,
|
||||
} from './utils.js'
|
||||
|
||||
type Props = {
|
||||
onDone(): void;
|
||||
commands?: Command[];
|
||||
};
|
||||
export function TrustDialog(t0) {
|
||||
const $ = _c(33);
|
||||
const {
|
||||
onDone,
|
||||
commands
|
||||
} = t0;
|
||||
let t1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = getMcpConfigsByScope("project");
|
||||
$[0] = t1;
|
||||
} else {
|
||||
t1 = $[0];
|
||||
onDone(): void
|
||||
commands?: Command[]
|
||||
}
|
||||
|
||||
export function TrustDialog({ onDone, commands }: Props): React.ReactNode {
|
||||
const { servers: projectServers } = getMcpConfigsByScope('project')
|
||||
|
||||
// In all cases, we generally check only the project-level and
|
||||
// project-local-level settings, which we assume that users do not configure
|
||||
// directly compared to user-level settings.
|
||||
|
||||
// Check for MCPs
|
||||
const hasMcpServers = Object.keys(projectServers).length > 0
|
||||
// Check for hooks
|
||||
const hooksSettingSources = getHooksSources()
|
||||
const hasHooks = hooksSettingSources.length > 0
|
||||
// Check whether code execution is allowed in permissions and slash commands
|
||||
const bashSettingSources = getBashPermissionSources()
|
||||
// Check for apiKeyHelper which executes arbitrary commands
|
||||
const apiKeyHelperSources = getApiKeyHelperSources()
|
||||
const hasApiKeyHelper = apiKeyHelperSources.length > 0
|
||||
// Check for AWS commands which execute arbitrary commands
|
||||
const awsCommandsSources = getAwsCommandsSources()
|
||||
const hasAwsCommands = awsCommandsSources.length > 0
|
||||
// Check for GCP commands which execute arbitrary commands
|
||||
const gcpCommandsSources = getGcpCommandsSources()
|
||||
const hasGcpCommands = gcpCommandsSources.length > 0
|
||||
// Check for otelHeadersHelper which executes arbitrary commands
|
||||
const otelHeadersHelperSources = getOtelHeadersHelperSources()
|
||||
const hasOtelHeadersHelper = otelHeadersHelperSources.length > 0
|
||||
// Check for dangerous environment variables (not in SAFE_ENV_VARS)
|
||||
const dangerousEnvVarsSources = getDangerousEnvVarsSources()
|
||||
const hasDangerousEnvVars = dangerousEnvVarsSources.length > 0
|
||||
|
||||
const hasSlashCommandBash =
|
||||
commands?.some(
|
||||
command =>
|
||||
command.type === 'prompt' &&
|
||||
command.loadedFrom === 'commands_DEPRECATED' &&
|
||||
(command.source === 'projectSettings' ||
|
||||
command.source === 'localSettings') &&
|
||||
command.allowedTools?.some(
|
||||
(tool: string) =>
|
||||
tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + '('),
|
||||
),
|
||||
) ?? false
|
||||
|
||||
const hasSkillsBash =
|
||||
commands?.some(
|
||||
command =>
|
||||
command.type === 'prompt' &&
|
||||
(command.loadedFrom === 'skills' || command.loadedFrom === 'plugin') &&
|
||||
(command.source === 'projectSettings' ||
|
||||
command.source === 'localSettings' ||
|
||||
command.source === 'plugin') &&
|
||||
command.allowedTools?.some(
|
||||
(tool: string) =>
|
||||
tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + '('),
|
||||
),
|
||||
) ?? false
|
||||
|
||||
const hasAnyBashExecution =
|
||||
bashSettingSources.length > 0 || hasSlashCommandBash || hasSkillsBash
|
||||
|
||||
const hasTrustDialogAccepted = checkHasTrustDialogAccepted()
|
||||
|
||||
React.useEffect(() => {
|
||||
const isHomeDir = homedir() === getCwd()
|
||||
logEvent('tengu_trust_dialog_shown', {
|
||||
isHomeDir,
|
||||
hasMcpServers,
|
||||
hasHooks,
|
||||
hasBashExecution: hasAnyBashExecution,
|
||||
hasApiKeyHelper,
|
||||
hasAwsCommands,
|
||||
hasGcpCommands,
|
||||
hasOtelHeadersHelper,
|
||||
hasDangerousEnvVars,
|
||||
})
|
||||
}, [
|
||||
hasMcpServers,
|
||||
hasHooks,
|
||||
hasAnyBashExecution,
|
||||
hasApiKeyHelper,
|
||||
hasAwsCommands,
|
||||
hasGcpCommands,
|
||||
hasOtelHeadersHelper,
|
||||
hasDangerousEnvVars,
|
||||
])
|
||||
|
||||
function onChange(value: 'enable_all' | 'exit') {
|
||||
if (value === 'exit') {
|
||||
gracefulShutdownSync(1)
|
||||
return
|
||||
}
|
||||
|
||||
const isHomeDir = homedir() === getCwd()
|
||||
|
||||
logEvent('tengu_trust_dialog_accept', {
|
||||
isHomeDir,
|
||||
hasMcpServers,
|
||||
hasHooks,
|
||||
hasBashExecution: hasAnyBashExecution,
|
||||
hasApiKeyHelper,
|
||||
hasAwsCommands,
|
||||
hasGcpCommands,
|
||||
hasOtelHeadersHelper,
|
||||
hasDangerousEnvVars,
|
||||
})
|
||||
|
||||
if (isHomeDir) {
|
||||
// For home directory, store trust in session memory only (not persisted to disk)
|
||||
// This allows hooks and other trust-requiring features to work during this session
|
||||
// while preserving the security intent of not permanently trusting home dir
|
||||
setSessionTrustAccepted(true)
|
||||
} else {
|
||||
saveCurrentProjectConfig(current => ({
|
||||
...current,
|
||||
hasTrustDialogAccepted: true,
|
||||
}))
|
||||
}
|
||||
|
||||
// Do NOT write MCP server settings here. handleMcpjsonServerApprovals in
|
||||
// interactiveHelpers.tsx runs right after this dialog and shows the per-server approval
|
||||
// UI. Writing enabledMcpjsonServers/enableAllProjectMcpServers here would
|
||||
// mark every server 'approved' and silently skip that dialog. See #15558.
|
||||
|
||||
onDone()
|
||||
}
|
||||
const {
|
||||
servers: projectServers
|
||||
} = t1;
|
||||
let t2;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = Object.keys(projectServers);
|
||||
$[1] = t2;
|
||||
} else {
|
||||
t2 = $[1];
|
||||
}
|
||||
const hasMcpServers = t2.length > 0;
|
||||
let t3;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t3 = getHooksSources();
|
||||
$[2] = t3;
|
||||
} else {
|
||||
t3 = $[2];
|
||||
}
|
||||
const hooksSettingSources = t3;
|
||||
const hasHooks = hooksSettingSources.length > 0;
|
||||
let t4;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t4 = getBashPermissionSources();
|
||||
$[3] = t4;
|
||||
} else {
|
||||
t4 = $[3];
|
||||
}
|
||||
const bashSettingSources = t4;
|
||||
let t5;
|
||||
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t5 = getApiKeyHelperSources();
|
||||
$[4] = t5;
|
||||
} else {
|
||||
t5 = $[4];
|
||||
}
|
||||
const apiKeyHelperSources = t5;
|
||||
const hasApiKeyHelper = apiKeyHelperSources.length > 0;
|
||||
let t6;
|
||||
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t6 = getAwsCommandsSources();
|
||||
$[5] = t6;
|
||||
} else {
|
||||
t6 = $[5];
|
||||
}
|
||||
const awsCommandsSources = t6;
|
||||
const hasAwsCommands = awsCommandsSources.length > 0;
|
||||
let t7;
|
||||
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t7 = getGcpCommandsSources();
|
||||
$[6] = t7;
|
||||
} else {
|
||||
t7 = $[6];
|
||||
}
|
||||
const gcpCommandsSources = t7;
|
||||
const hasGcpCommands = gcpCommandsSources.length > 0;
|
||||
let t8;
|
||||
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t8 = getOtelHeadersHelperSources();
|
||||
$[7] = t8;
|
||||
} else {
|
||||
t8 = $[7];
|
||||
}
|
||||
const otelHeadersHelperSources = t8;
|
||||
const hasOtelHeadersHelper = otelHeadersHelperSources.length > 0;
|
||||
let t9;
|
||||
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t9 = getDangerousEnvVarsSources();
|
||||
$[8] = t9;
|
||||
} else {
|
||||
t9 = $[8];
|
||||
}
|
||||
const dangerousEnvVarsSources = t9;
|
||||
const hasDangerousEnvVars = dangerousEnvVarsSources.length > 0;
|
||||
let t10;
|
||||
if ($[9] !== commands) {
|
||||
t10 = commands?.some(_temp2) ?? false;
|
||||
$[9] = commands;
|
||||
$[10] = t10;
|
||||
} else {
|
||||
t10 = $[10];
|
||||
}
|
||||
const hasSlashCommandBash = t10;
|
||||
let t11;
|
||||
if ($[11] !== commands) {
|
||||
t11 = commands?.some(_temp4) ?? false;
|
||||
$[11] = commands;
|
||||
$[12] = t11;
|
||||
} else {
|
||||
t11 = $[12];
|
||||
}
|
||||
const hasSkillsBash = t11;
|
||||
const hasAnyBashExecution = bashSettingSources.length > 0 || hasSlashCommandBash || hasSkillsBash;
|
||||
const hasTrustDialogAccepted = checkHasTrustDialogAccepted();
|
||||
let t12;
|
||||
let t13;
|
||||
if ($[13] !== hasAnyBashExecution) {
|
||||
t12 = () => {
|
||||
const isHomeDir = homedir() === getCwd();
|
||||
logEvent("tengu_trust_dialog_shown", {
|
||||
isHomeDir,
|
||||
hasMcpServers,
|
||||
hasHooks,
|
||||
hasBashExecution: hasAnyBashExecution,
|
||||
hasApiKeyHelper,
|
||||
hasAwsCommands,
|
||||
hasGcpCommands,
|
||||
hasOtelHeadersHelper,
|
||||
hasDangerousEnvVars
|
||||
});
|
||||
};
|
||||
t13 = [hasMcpServers, hasHooks, hasAnyBashExecution, hasApiKeyHelper, hasAwsCommands, hasGcpCommands, hasOtelHeadersHelper, hasDangerousEnvVars];
|
||||
$[13] = hasAnyBashExecution;
|
||||
$[14] = t12;
|
||||
$[15] = t13;
|
||||
} else {
|
||||
t12 = $[14];
|
||||
t13 = $[15];
|
||||
}
|
||||
React.useEffect(t12, t13);
|
||||
let t14;
|
||||
if ($[16] !== hasAnyBashExecution || $[17] !== onDone) {
|
||||
t14 = function onChange(value) {
|
||||
if (value === "exit") {
|
||||
gracefulShutdownSync(1);
|
||||
return;
|
||||
}
|
||||
const isHomeDir_0 = homedir() === getCwd();
|
||||
logEvent("tengu_trust_dialog_accept", {
|
||||
isHomeDir: isHomeDir_0,
|
||||
hasMcpServers,
|
||||
hasHooks,
|
||||
hasBashExecution: hasAnyBashExecution,
|
||||
hasApiKeyHelper,
|
||||
hasAwsCommands,
|
||||
hasGcpCommands,
|
||||
hasOtelHeadersHelper,
|
||||
hasDangerousEnvVars
|
||||
});
|
||||
if (isHomeDir_0) {
|
||||
setSessionTrustAccepted(true);
|
||||
} else {
|
||||
saveCurrentProjectConfig(_temp5);
|
||||
}
|
||||
onDone();
|
||||
};
|
||||
$[16] = hasAnyBashExecution;
|
||||
$[17] = onDone;
|
||||
$[18] = t14;
|
||||
} else {
|
||||
t14 = $[18];
|
||||
}
|
||||
const onChange = t14;
|
||||
const exitState = useExitOnCtrlCDWithKeybindings(_temp6);
|
||||
let t15;
|
||||
if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t15 = {
|
||||
context: "Confirmation"
|
||||
};
|
||||
$[19] = t15;
|
||||
} else {
|
||||
t15 = $[19];
|
||||
}
|
||||
useKeybinding("confirm:no", _temp7, t15);
|
||||
|
||||
// Default onExit is useApp().exit() → Ink.unmount(), which tears down the
|
||||
// React tree but never calls onDone(). showSetupScreens() in
|
||||
// interactiveHelpers.tsx awaits a Promise that only resolves via onDone,
|
||||
// so the default would hang the await forever. With keybinding
|
||||
// customization enabled, the chokidar watcher (persistent: true) keeps the
|
||||
// event loop alive and the process freezes. Explicitly exit 1 like "No".
|
||||
const exitState = useExitOnCtrlCDWithKeybindings(() =>
|
||||
gracefulShutdownSync(1),
|
||||
)
|
||||
|
||||
// Use configurable keybinding for ESC to cancel/exit
|
||||
useKeybinding(
|
||||
'confirm:no',
|
||||
() => {
|
||||
gracefulShutdownSync(0)
|
||||
},
|
||||
{ context: 'Confirmation' },
|
||||
)
|
||||
|
||||
// Automatically resolve the trust dialog if there is nothing to be shown.
|
||||
if (hasTrustDialogAccepted) {
|
||||
setTimeout(onDone);
|
||||
return null;
|
||||
setTimeout(onDone)
|
||||
return null
|
||||
}
|
||||
let t16;
|
||||
let t17;
|
||||
let t18;
|
||||
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t16 = <Text bold={true}>{getFsImplementation().cwd()}</Text>;
|
||||
t17 = <Text>Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known open source project, or work from your team). If not, take a moment to review what{"'"}s in this folder first.</Text>;
|
||||
t18 = <Text>Claude Code{"'"}ll be able to read, edit, and execute files here.</Text>;
|
||||
$[20] = t16;
|
||||
$[21] = t17;
|
||||
$[22] = t18;
|
||||
} else {
|
||||
t16 = $[20];
|
||||
t17 = $[21];
|
||||
t18 = $[22];
|
||||
}
|
||||
let t19;
|
||||
if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t19 = <Text dimColor={true}><Link url="https://code.claude.com/docs/en/security">Security guide</Link></Text>;
|
||||
$[23] = t19;
|
||||
} else {
|
||||
t19 = $[23];
|
||||
}
|
||||
let t20;
|
||||
if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t20 = [{
|
||||
label: "Yes, I trust this folder",
|
||||
value: "enable_all"
|
||||
}, {
|
||||
label: "No, exit",
|
||||
value: "exit"
|
||||
}];
|
||||
$[24] = t20;
|
||||
} else {
|
||||
t20 = $[24];
|
||||
}
|
||||
let t21;
|
||||
if ($[25] !== onChange) {
|
||||
t21 = <Select options={t20} onChange={value_0 => onChange(value_0 as 'enable_all' | 'exit')} onCancel={() => onChange("exit")} />;
|
||||
$[25] = onChange;
|
||||
$[26] = t21;
|
||||
} else {
|
||||
t21 = $[26];
|
||||
}
|
||||
let t22;
|
||||
if ($[27] !== exitState.keyName || $[28] !== exitState.pending) {
|
||||
t22 = <Text dimColor={true}>{exitState.pending ? <>Press {exitState.keyName} again to exit</> : <>Enter to confirm · Esc to cancel</>}</Text>;
|
||||
$[27] = exitState.keyName;
|
||||
$[28] = exitState.pending;
|
||||
$[29] = t22;
|
||||
} else {
|
||||
t22 = $[29];
|
||||
}
|
||||
let t23;
|
||||
if ($[30] !== t21 || $[31] !== t22) {
|
||||
t23 = <PermissionDialog color="warning" titleColor="warning" title="Accessing workspace:"><Box flexDirection="column" gap={1} paddingTop={1}>{t16}{t17}{t18}{t19}{t21}{t22}</Box></PermissionDialog>;
|
||||
$[30] = t21;
|
||||
$[31] = t22;
|
||||
$[32] = t23;
|
||||
} else {
|
||||
t23 = $[32];
|
||||
}
|
||||
return t23;
|
||||
}
|
||||
function _temp7() {
|
||||
gracefulShutdownSync(0);
|
||||
}
|
||||
function _temp6() {
|
||||
return gracefulShutdownSync(1);
|
||||
}
|
||||
function _temp5(current) {
|
||||
return {
|
||||
...current,
|
||||
hasTrustDialogAccepted: true
|
||||
};
|
||||
}
|
||||
function _temp4(command_0) {
|
||||
return command_0.type === "prompt" && (command_0.loadedFrom === "skills" || command_0.loadedFrom === "plugin") && (command_0.source === "projectSettings" || command_0.source === "localSettings" || command_0.source === "plugin") && command_0.allowedTools?.some(_temp3);
|
||||
}
|
||||
function _temp3(tool_0) {
|
||||
return tool_0 === BASH_TOOL_NAME || tool_0.startsWith(BASH_TOOL_NAME + "(");
|
||||
}
|
||||
function _temp2(command) {
|
||||
return command.type === "prompt" && command.loadedFrom === "commands_DEPRECATED" && (command.source === "projectSettings" || command.source === "localSettings") && command.allowedTools?.some(_temp);
|
||||
}
|
||||
function _temp(tool) {
|
||||
return tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + "(");
|
||||
|
||||
return (
|
||||
<PermissionDialog
|
||||
color="warning"
|
||||
titleColor="warning"
|
||||
title="Accessing workspace:"
|
||||
>
|
||||
<Box flexDirection="column" gap={1} paddingTop={1}>
|
||||
<Text bold>{getFsImplementation().cwd()}</Text>
|
||||
|
||||
<Text>
|
||||
Quick safety check: Is this a project you created or one you trust?
|
||||
(Like your own code, a well-known open source project, or work from
|
||||
your team). If not, take a moment to review what{"'"}s in this folder
|
||||
first.
|
||||
</Text>
|
||||
<Text>
|
||||
Claude Code{"'"}ll be able to read, edit, and execute files here.
|
||||
</Text>
|
||||
|
||||
<Text dimColor>
|
||||
<Link url="https://code.claude.com/docs/en/security">
|
||||
Security guide
|
||||
</Link>
|
||||
</Text>
|
||||
|
||||
<Select
|
||||
options={[
|
||||
{ label: 'Yes, I trust this folder', value: 'enable_all' },
|
||||
{ label: 'No, exit', value: 'exit' },
|
||||
]}
|
||||
onChange={value => onChange(value as 'enable_all' | 'exit')}
|
||||
onCancel={() => onChange('exit')}
|
||||
/>
|
||||
|
||||
<Text dimColor>
|
||||
{exitState.pending ? (
|
||||
<>Press {exitState.keyName} again to exit</>
|
||||
) : (
|
||||
<>Enter to confirm · Esc to cancel</>
|
||||
)}
|
||||
</Text>
|
||||
</Box>
|
||||
</PermissionDialog>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user