mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
style: 完成所有文件的lint
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
logEvent,
|
||||
} from 'src/services/analytics/index.js'
|
||||
import { Box, Link, Text, useInput } from '@anthropic/ink'
|
||||
} from 'src/services/analytics/index.js';
|
||||
import { Box, Link, Text, useInput } from '@anthropic/ink';
|
||||
import {
|
||||
type AccountSettings,
|
||||
calculateShouldShowGrove,
|
||||
@@ -12,22 +12,17 @@ import {
|
||||
getGroveSettings,
|
||||
markGroveNoticeViewed,
|
||||
updateGroveSettings,
|
||||
} from '../../services/api/grove.js'
|
||||
import { Select } from '../CustomSelect/index.js'
|
||||
import { Byline, Dialog, KeyboardShortcutHint } from '@anthropic/ink'
|
||||
} from '../../services/api/grove.js';
|
||||
import { Select } from '../CustomSelect/index.js';
|
||||
import { Byline, Dialog, KeyboardShortcutHint } from '@anthropic/ink';
|
||||
|
||||
export type GroveDecision =
|
||||
| 'accept_opt_in'
|
||||
| 'accept_opt_out'
|
||||
| 'defer'
|
||||
| 'escape'
|
||||
| 'skip_rendering'
|
||||
export type GroveDecision = 'accept_opt_in' | 'accept_opt_out' | 'defer' | 'escape' | 'skip_rendering';
|
||||
|
||||
type Props = {
|
||||
showIfAlreadyViewed: boolean
|
||||
location: 'settings' | 'policy_update_modal' | 'onboarding'
|
||||
onDone(decision: GroveDecision): void
|
||||
}
|
||||
showIfAlreadyViewed: boolean;
|
||||
location: 'settings' | 'policy_update_modal' | 'onboarding';
|
||||
onDone(decision: GroveDecision): void;
|
||||
};
|
||||
|
||||
const NEW_TERMS_ASCII = ` _____________
|
||||
| \\ \\
|
||||
@@ -39,15 +34,14 @@ const NEW_TERMS_ASCII = ` _____________
|
||||
| ---------- |
|
||||
| ---------- |
|
||||
| |
|
||||
|______________|`
|
||||
|______________|`;
|
||||
|
||||
function GracePeriodContentBody(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<Text>
|
||||
An update to our Consumer Terms and Privacy Policy will take effect on{' '}
|
||||
<Text bold>October 8, 2025</Text>. You can accept the updated terms
|
||||
today.
|
||||
An update to our Consumer Terms and Privacy Policy will take effect on <Text bold>October 8, 2025</Text>. You
|
||||
can accept the updated terms today.
|
||||
</Text>
|
||||
|
||||
<Box flexDirection="column">
|
||||
@@ -58,12 +52,8 @@ function GracePeriodContentBody(): React.ReactNode {
|
||||
<Text>· </Text>
|
||||
<Text bold>You can help improve Claude </Text>
|
||||
<Text>
|
||||
— Allow the use of your chats and coding sessions to train and
|
||||
improve Anthropic AI models. Change anytime in your Privacy
|
||||
Settings (
|
||||
<Link
|
||||
url={'https://claude.ai/settings/data-privacy-controls'}
|
||||
></Link>
|
||||
— Allow the use of your chats and coding sessions to train and improve Anthropic AI models. Change anytime
|
||||
in your Privacy Settings (<Link url={'https://claude.ai/settings/data-privacy-controls'}></Link>
|
||||
).
|
||||
</Text>
|
||||
</Text>
|
||||
@@ -73,24 +63,19 @@ function GracePeriodContentBody(): React.ReactNode {
|
||||
<Text>· </Text>
|
||||
<Text bold>Updates to data retention </Text>
|
||||
<Text>
|
||||
— To help us improve our AI models and safety protections,
|
||||
we're extending data retention to 5 years.
|
||||
— To help us improve our AI models and safety protections, we're extending data retention to 5 years.
|
||||
</Text>
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Text>
|
||||
Learn more (
|
||||
<Link
|
||||
url={'https://www.anthropic.com/news/updates-to-our-consumer-terms'}
|
||||
></Link>
|
||||
) or read the updated Consumer Terms (
|
||||
<Link url={'https://anthropic.com/legal/terms'}></Link>) and Privacy
|
||||
Policy (<Link url={'https://anthropic.com/legal/privacy'}></Link>)
|
||||
Learn more (<Link url={'https://www.anthropic.com/news/updates-to-our-consumer-terms'}></Link>) or read the
|
||||
updated Consumer Terms (<Link url={'https://anthropic.com/legal/terms'}></Link>) and Privacy Policy (
|
||||
<Link url={'https://anthropic.com/legal/privacy'}></Link>)
|
||||
</Text>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function PostGracePeriodContentBody(): React.ReactNode {
|
||||
@@ -104,8 +89,8 @@ function PostGracePeriodContentBody(): React.ReactNode {
|
||||
<Box flexDirection="column">
|
||||
<Text bold>Help improve Claude</Text>
|
||||
<Text>
|
||||
Allow the use of your chats and coding sessions to train and improve
|
||||
Anthropic AI models. You can change this anytime in Privacy Settings
|
||||
Allow the use of your chats and coding sessions to train and improve Anthropic AI models. You can change
|
||||
this anytime in Privacy Settings
|
||||
</Text>
|
||||
<Link url={'https://claude.ai/settings/data-privacy-controls'}></Link>
|
||||
</Box>
|
||||
@@ -113,122 +98,101 @@ function PostGracePeriodContentBody(): React.ReactNode {
|
||||
<Box flexDirection="column">
|
||||
<Text bold>How this affects data retention</Text>
|
||||
<Text>
|
||||
Turning ON the improve Claude setting extends data retention from 30
|
||||
days to 5 years. Turning it OFF keeps the default 30-day data
|
||||
retention. Delete data anytime.
|
||||
Turning ON the improve Claude setting extends data retention from 30 days to 5 years. Turning it OFF keeps
|
||||
the default 30-day data retention. Delete data anytime.
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Text>
|
||||
Learn more (
|
||||
<Link
|
||||
url={'https://www.anthropic.com/news/updates-to-our-consumer-terms'}
|
||||
></Link>
|
||||
) or read the updated Consumer Terms (
|
||||
<Link url={'https://anthropic.com/legal/terms'}></Link>) and Privacy
|
||||
Policy (<Link url={'https://anthropic.com/legal/privacy'}></Link>)
|
||||
Learn more (<Link url={'https://www.anthropic.com/news/updates-to-our-consumer-terms'}></Link>) or read the
|
||||
updated Consumer Terms (<Link url={'https://anthropic.com/legal/terms'}></Link>) and Privacy Policy (
|
||||
<Link url={'https://anthropic.com/legal/privacy'}></Link>)
|
||||
</Text>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function GroveDialog({
|
||||
showIfAlreadyViewed,
|
||||
location,
|
||||
onDone,
|
||||
}: Props): React.ReactNode {
|
||||
const [shouldShowDialog, setShouldShowDialog] = useState<boolean | null>(null)
|
||||
const [groveConfig, setGroveConfig] = useState<GroveConfig | null>(null)
|
||||
export function GroveDialog({ showIfAlreadyViewed, location, onDone }: Props): React.ReactNode {
|
||||
const [shouldShowDialog, setShouldShowDialog] = useState<boolean | null>(null);
|
||||
const [groveConfig, setGroveConfig] = useState<GroveConfig | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
async function checkGroveSettings() {
|
||||
const [settingsResult, configResult] = await Promise.all([
|
||||
getGroveSettings(),
|
||||
getGroveNoticeConfig(),
|
||||
])
|
||||
const [settingsResult, configResult] = await Promise.all([getGroveSettings(), getGroveNoticeConfig()]);
|
||||
|
||||
// Extract config data if successful, otherwise null
|
||||
const config = configResult.success ? configResult.data : null
|
||||
setGroveConfig(config)
|
||||
const config = configResult.success ? configResult.data : null;
|
||||
setGroveConfig(config);
|
||||
|
||||
// Determine if we should show the dialog (returns false on API failure)
|
||||
const shouldShow = calculateShouldShowGrove(
|
||||
settingsResult,
|
||||
configResult,
|
||||
showIfAlreadyViewed,
|
||||
)
|
||||
const shouldShow = calculateShouldShowGrove(settingsResult, configResult, showIfAlreadyViewed);
|
||||
|
||||
setShouldShowDialog(shouldShow)
|
||||
setShouldShowDialog(shouldShow);
|
||||
// If we shouldn't show the dialog, immediately call onDone
|
||||
if (!shouldShow) {
|
||||
onDone('skip_rendering')
|
||||
return
|
||||
onDone('skip_rendering');
|
||||
return;
|
||||
}
|
||||
// Mark as viewed every time we show the dialog (for reminder frequency tracking)
|
||||
void markGroveNoticeViewed()
|
||||
void markGroveNoticeViewed();
|
||||
// Log that the Grove policy dialog was shown
|
||||
logEvent('tengu_grove_policy_viewed', {
|
||||
location:
|
||||
location as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
dismissable:
|
||||
config?.notice_is_grace_period as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
location: location as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
dismissable: config?.notice_is_grace_period as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
});
|
||||
}
|
||||
|
||||
void checkGroveSettings()
|
||||
}, [showIfAlreadyViewed, location, onDone])
|
||||
void checkGroveSettings();
|
||||
}, [showIfAlreadyViewed, location, onDone]);
|
||||
|
||||
// Loading state
|
||||
if (shouldShowDialog === null) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
// User has already set preferences, don't show dialog
|
||||
if (!shouldShowDialog) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
async function onChange(
|
||||
value: 'accept_opt_in' | 'accept_opt_out' | 'defer' | 'escape',
|
||||
) {
|
||||
async function onChange(value: 'accept_opt_in' | 'accept_opt_out' | 'defer' | 'escape') {
|
||||
switch (value) {
|
||||
case 'accept_opt_in': {
|
||||
await updateGroveSettings(true)
|
||||
await updateGroveSettings(true);
|
||||
logEvent('tengu_grove_policy_submitted', {
|
||||
state: true,
|
||||
dismissable:
|
||||
groveConfig?.notice_is_grace_period as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
break
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'accept_opt_out': {
|
||||
await updateGroveSettings(false)
|
||||
await updateGroveSettings(false);
|
||||
logEvent('tengu_grove_policy_submitted', {
|
||||
state: false,
|
||||
dismissable:
|
||||
groveConfig?.notice_is_grace_period as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
break
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'defer':
|
||||
logEvent('tengu_grove_policy_dismissed', {
|
||||
state: true,
|
||||
})
|
||||
break
|
||||
});
|
||||
break;
|
||||
case 'escape':
|
||||
logEvent('tengu_grove_policy_escaped', {})
|
||||
break
|
||||
logEvent('tengu_grove_policy_escaped', {});
|
||||
break;
|
||||
}
|
||||
|
||||
onDone(value)
|
||||
onDone(value);
|
||||
}
|
||||
|
||||
const acceptOptions = groveConfig?.domain_excluded
|
||||
? [
|
||||
{
|
||||
label:
|
||||
'Accept terms · Help improve Claude: OFF (for emails with your domain)',
|
||||
label: 'Accept terms · Help improve Claude: OFF (for emails with your domain)',
|
||||
value: 'accept_opt_out',
|
||||
},
|
||||
]
|
||||
@@ -241,14 +205,14 @@ export function GroveDialog({
|
||||
label: 'Accept terms · Help improve Claude: OFF',
|
||||
value: 'accept_opt_out',
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
function handleCancel(): void {
|
||||
if (groveConfig?.notice_is_grace_period) {
|
||||
void onChange('defer')
|
||||
return
|
||||
void onChange('defer');
|
||||
return;
|
||||
}
|
||||
void onChange('escape')
|
||||
void onChange('escape');
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -269,11 +233,7 @@ export function GroveDialog({
|
||||
>
|
||||
<Box flexDirection="row">
|
||||
<Box flexDirection="column" gap={1} flexGrow={1}>
|
||||
{groveConfig?.notice_is_grace_period ? (
|
||||
<GracePeriodContentBody />
|
||||
) : (
|
||||
<PostGracePeriodContentBody />
|
||||
)}
|
||||
{groveConfig?.notice_is_grace_period ? <GracePeriodContentBody /> : <PostGracePeriodContentBody />}
|
||||
</Box>
|
||||
<Box flexShrink={0}>
|
||||
<Text color="professionalBlue">{NEW_TERMS_ASCII}</Text>
|
||||
@@ -290,53 +250,47 @@ export function GroveDialog({
|
||||
options={[
|
||||
...acceptOptions,
|
||||
// Only show "Not now" if in grace period
|
||||
...(groveConfig?.notice_is_grace_period
|
||||
? [{ label: 'Not now', value: 'defer' }]
|
||||
: []),
|
||||
...(groveConfig?.notice_is_grace_period ? [{ label: 'Not now', value: 'defer' }] : []),
|
||||
]}
|
||||
onChange={value =>
|
||||
onChange(value as 'accept_opt_in' | 'accept_opt_out' | 'defer')
|
||||
}
|
||||
onChange={value => onChange(value as 'accept_opt_in' | 'accept_opt_out' | 'defer')}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
</Box>
|
||||
</Dialog>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
type PrivacySettingsDialogProps = {
|
||||
settings: AccountSettings
|
||||
domainExcluded?: boolean
|
||||
onDone(): void
|
||||
}
|
||||
settings: AccountSettings;
|
||||
domainExcluded?: boolean;
|
||||
onDone(): void;
|
||||
};
|
||||
|
||||
export function PrivacySettingsDialog({
|
||||
settings,
|
||||
domainExcluded,
|
||||
onDone,
|
||||
}: PrivacySettingsDialogProps): React.ReactNode {
|
||||
const [groveEnabled, setGroveEnabled] = useState(settings.grove_enabled)
|
||||
const [groveEnabled, setGroveEnabled] = useState(settings.grove_enabled);
|
||||
|
||||
React.useEffect(() => {
|
||||
logEvent('tengu_grove_privacy_settings_viewed', {})
|
||||
}, [])
|
||||
logEvent('tengu_grove_privacy_settings_viewed', {});
|
||||
}, []);
|
||||
|
||||
useInput(async (input, key) => {
|
||||
// Toggle the setting when enter/tab/space is pressed
|
||||
if (!domainExcluded && (key.tab || key.return || input === ' ')) {
|
||||
const newValue = !groveEnabled
|
||||
setGroveEnabled(newValue)
|
||||
await updateGroveSettings(newValue)
|
||||
const newValue = !groveEnabled;
|
||||
setGroveEnabled(newValue);
|
||||
await updateGroveSettings(newValue);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let valueComponent = <Text color="error">false</Text>
|
||||
let valueComponent = <Text color="error">false</Text>;
|
||||
if (domainExcluded) {
|
||||
valueComponent = (
|
||||
<Text color="error">false (for emails with your domain)</Text>
|
||||
)
|
||||
valueComponent = <Text color="error">false (for emails with your domain)</Text>;
|
||||
} else if (groveEnabled) {
|
||||
valueComponent = <Text color="success">true</Text>
|
||||
valueComponent = <Text color="success">true</Text>;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -369,5 +323,5 @@ export function PrivacySettingsDialog({
|
||||
<Box>{valueComponent}</Box>
|
||||
</Box>
|
||||
</Dialog>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user