Fix Codex OAuth configuration and refine UI controls
This commit is contained in:
1 parent
1acbeb6f0a
commit
2c7030734e
7 files changed
+110
-115
No files matched your search
+23
-17
@@ -14,12 +14,10 @@ import {
|
||||
Languages,
|
||||
LogIn,
|
||||
MessageCircle,
|
||||
Moon,
|
||||
Network,
|
||||
PackageOpen,
|
||||
ServerCog,
|
||||
Settings,
|
||||
Sun,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import appLogo from './assets/logo.jpg';
|
||||
@@ -308,22 +306,30 @@ function AppContent() {
|
||||
</nav>
|
||||
|
||||
<div className="sidebar-bottom">
|
||||
<button
|
||||
type="button"
|
||||
className="sidebar-theme-toggle"
|
||||
aria-label={theme === 'dark' ? t('app.theme.switchToLight') : t('app.theme.switchToDark')}
|
||||
aria-pressed={theme === 'dark'}
|
||||
title={theme === 'dark' ? t('app.theme.switchToLight') : t('app.theme.switchToDark')}
|
||||
onClick={() => setTheme((current) => current === 'dark' ? 'light' : 'dark')}
|
||||
<div
|
||||
className="sidebar-theme-selector"
|
||||
role="group"
|
||||
aria-label={`${t('app.theme.light')} / ${t('app.theme.dark')}`}
|
||||
>
|
||||
{theme === 'dark'
|
||||
? <Moon size={16} aria-hidden="true" />
|
||||
: <Sun size={16} aria-hidden="true" />}
|
||||
<span>{theme === 'dark' ? t('app.theme.dark') : t('app.theme.light')}</span>
|
||||
<i className="theme-switch-track" aria-hidden="true">
|
||||
<b />
|
||||
</i>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={theme === 'light' ? 'active' : ''}
|
||||
aria-pressed={theme === 'light'}
|
||||
title={t('app.theme.switchToLight')}
|
||||
onClick={() => setTheme('light')}
|
||||
>
|
||||
{t('app.theme.light')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={theme === 'dark' ? 'active' : ''}
|
||||
aria-pressed={theme === 'dark'}
|
||||
title={t('app.theme.switchToDark')}
|
||||
onClick={() => setTheme('dark')}
|
||||
>
|
||||
{t('app.theme.dark')}
|
||||
</button>
|
||||
</div>
|
||||
<div ref={languageMenuRef} className="sidebar-language">
|
||||
<button
|
||||
ref={languageButtonRef}
|
||||
|
||||
@@ -445,8 +445,6 @@ export const jaOverrides = {
|
||||
'agents.sessions.repairTitle': '過去のセッションを復元',
|
||||
'agents.sessions.repairDescription': '他の Provider のセッションを現在のセッション Provider に同期します。',
|
||||
'agents.sessions.autoRepair': 'Codex 起動前に過去のセッションを自動復元',
|
||||
'agents.sessions.autoRepairEnabled': '起動前の自動復元を有効にしました。',
|
||||
'agents.sessions.autoRepairDisabled': '起動前の自動復元を無効にしました。',
|
||||
'agents.sessions.settingLoading': '読み込み中',
|
||||
'agents.sessions.settingOn': 'オン',
|
||||
'agents.sessions.settingOff': 'オフ',
|
||||
|
||||
@@ -448,8 +448,6 @@ export const zhCN = {
|
||||
'agents.sessions.repairTitle': '恢复历史会话',
|
||||
'agents.sessions.repairDescription': '将其他渠道的会话同步到当前会话',
|
||||
'agents.sessions.autoRepair': '启动 Codex 前自动恢复历史会话',
|
||||
'agents.sessions.autoRepairEnabled': '已开启启动前自动恢复历史会话。',
|
||||
'agents.sessions.autoRepairDisabled': '已关闭启动前自动恢复历史会话。',
|
||||
'agents.sessions.settingLoading': '读取中',
|
||||
'agents.sessions.settingOn': '已开启',
|
||||
'agents.sessions.settingOff': '已关闭',
|
||||
@@ -1293,8 +1291,6 @@ export const en: Record<MessageKey, string> = {
|
||||
'agents.sessions.repairTitle': 'Restore Historical Sessions',
|
||||
'agents.sessions.repairDescription': 'Sync sessions from other providers to the current session provider.',
|
||||
'agents.sessions.autoRepair': 'Restore historical sessions before launching Codex',
|
||||
'agents.sessions.autoRepairEnabled': 'Automatic restoration before launch is enabled.',
|
||||
'agents.sessions.autoRepairDisabled': 'Automatic restoration before launch is disabled.',
|
||||
'agents.sessions.settingLoading': 'Loading',
|
||||
'agents.sessions.settingOn': 'On',
|
||||
'agents.sessions.settingOff': 'Off',
|
||||
|
||||
@@ -62,6 +62,7 @@ type AgentConfigStatus = {
|
||||
configValid: boolean;
|
||||
configured: boolean;
|
||||
currentModel: string | null;
|
||||
oauthConfiguration: boolean;
|
||||
modificationEnabled: boolean;
|
||||
modificationState: AgentModificationState;
|
||||
backupAvailable: boolean;
|
||||
@@ -509,7 +510,7 @@ export function AgentsPage() {
|
||||
const [closeAppError, setCloseAppError] = useState('');
|
||||
const [closeAppNotice, setCloseAppNotice] = useState('');
|
||||
const [closeAppConfirmOpen, setCloseAppConfirmOpen] = useState(false);
|
||||
const [oauthConfiguration, setOauthConfiguration] = useState(false);
|
||||
const [oauthConfigurationDraft, setOauthConfigurationDraft] = useState<boolean | null>(null);
|
||||
const autoLoadedModelClientRef = useRef<AgentClientId | null>(null);
|
||||
|
||||
const loadStatuses = useCallback(async (forceRefresh = false) => {
|
||||
@@ -620,6 +621,9 @@ export function AgentsPage() {
|
||||
const activeDefinition = agentDefinitions.find((agent) => agent.id === selected)
|
||||
?? agentDefinitions[0];
|
||||
const activeStatus = statuses.find((status) => status.id === selected) ?? null;
|
||||
const oauthConfiguration = oauthConfigurationDraft
|
||||
?? activeStatus?.oauthConfiguration
|
||||
?? false;
|
||||
const savedSelectedModel = modelByClient[selected] ?? '';
|
||||
const selectedModelOption = findAgentModel(models, savedSelectedModel);
|
||||
const selectedModel = selectedModelOption?.name ?? '';
|
||||
@@ -629,11 +633,14 @@ export function AgentsPage() {
|
||||
(target) => target.id === selectedLaunchTargetId,
|
||||
) ?? activeLaunchTargets[0] ?? null;
|
||||
const appliedModel = activeStatus?.appliedModel ?? activeStatus?.currentModel ?? '';
|
||||
const draftChanged = Boolean(
|
||||
const modelDraftChanged = Boolean(
|
||||
selectedModel.trim()
|
||||
&& appliedModel.trim()
|
||||
&& selectedModel.trim() !== appliedModel.trim(),
|
||||
);
|
||||
const oauthConfigurationChanged = selected === 'codex'
|
||||
&& oauthConfiguration !== Boolean(activeStatus?.oauthConfiguration);
|
||||
const draftChanged = modelDraftChanged || oauthConfigurationChanged;
|
||||
const canEnable = Boolean(
|
||||
activeStatus?.supportedPlatform
|
||||
&& activeStatus.installed
|
||||
@@ -730,6 +737,7 @@ export function AgentsPage() {
|
||||
oauthConfiguration,
|
||||
});
|
||||
await reloadStatusesAfterAction();
|
||||
setOauthConfigurationDraft(null);
|
||||
} catch (requestError) {
|
||||
setConfigurationError(String(requestError));
|
||||
} finally {
|
||||
@@ -751,6 +759,7 @@ export function AgentsPage() {
|
||||
});
|
||||
setDefaultConfirmOpen(false);
|
||||
await reloadStatusesAfterAction();
|
||||
setOauthConfigurationDraft(null);
|
||||
} catch (requestError) {
|
||||
setDefaultError(String(requestError));
|
||||
} finally {
|
||||
@@ -767,6 +776,7 @@ export function AgentsPage() {
|
||||
setClearConfirmOpen(false);
|
||||
setClearNotice(t('agents.clear.success'));
|
||||
await reloadStatusesAfterAction();
|
||||
setOauthConfigurationDraft(null);
|
||||
} catch (requestError) {
|
||||
setClearError(String(requestError));
|
||||
} finally {
|
||||
@@ -942,7 +952,7 @@ export function AgentsPage() {
|
||||
<section className="agent-core-setting-section agent-model-section">
|
||||
<div className="agent-section-heading">
|
||||
<div><strong>{t('agents.useModel')}</strong></div>
|
||||
{draftChanged ? <span className="agent-pending-badge">{t('agents.pending')}</span> : null}
|
||||
{modelDraftChanged ? <span className="agent-pending-badge">{t('agents.pending')}</span> : null}
|
||||
</div>
|
||||
<AgentModelPicker
|
||||
models={models}
|
||||
@@ -983,7 +993,7 @@ export function AgentsPage() {
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
checked={oauthConfiguration}
|
||||
onChange={(event) => setOauthConfiguration(event.currentTarget.checked)}
|
||||
onChange={(event) => setOauthConfigurationDraft(event.currentTarget.checked)}
|
||||
disabled={busy}
|
||||
aria-label={t('agents.modify.oauthConfiguration')}
|
||||
/>
|
||||
|
||||
@@ -8,7 +8,6 @@ type RepairOnLaunchSetting = {
|
||||
};
|
||||
|
||||
type StatusMessage = {
|
||||
kind: 'success' | 'error';
|
||||
text: string;
|
||||
};
|
||||
|
||||
@@ -32,7 +31,6 @@ export function CodexSessionAutoRestoreCard() {
|
||||
.catch((error) => {
|
||||
if (!disposed) {
|
||||
setStatus({
|
||||
kind: 'error',
|
||||
text: t('agents.sessions.settingLoadFailed', { error: errorMessage(error) }),
|
||||
});
|
||||
}
|
||||
@@ -53,15 +51,8 @@ export function CodexSessionAutoRestoreCard() {
|
||||
request: { enabled: nextEnabled },
|
||||
});
|
||||
setEnabled(result.enabled);
|
||||
setStatus({
|
||||
kind: 'success',
|
||||
text: result.enabled
|
||||
? t('agents.sessions.autoRepairEnabled')
|
||||
: t('agents.sessions.autoRepairDisabled'),
|
||||
});
|
||||
} catch (error) {
|
||||
setStatus({
|
||||
kind: 'error',
|
||||
text: t('agents.sessions.settingFailed', { error: errorMessage(error) }),
|
||||
});
|
||||
} finally {
|
||||
@@ -102,8 +93,8 @@ export function CodexSessionAutoRestoreCard() {
|
||||
</div>
|
||||
{status ? (
|
||||
<small
|
||||
className={`codex-auto-restore-message ${status.kind}`}
|
||||
role={status.kind === 'error' ? 'alert' : 'status'}
|
||||
className="codex-auto-restore-message error"
|
||||
role="alert"
|
||||
>
|
||||
{status.text}
|
||||
</small>
|
||||
|
||||
+22
-53
@@ -440,71 +440,40 @@ input:focus-visible {
|
||||
border-top: 1px solid var(--theme-e3e1db);
|
||||
}
|
||||
|
||||
.sidebar-theme-toggle {
|
||||
.sidebar-theme-selector {
|
||||
display: grid;
|
||||
grid-template-columns: 18px minmax(0, 1fr) 36px;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 3px;
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
padding: 0 10px;
|
||||
padding: 3px;
|
||||
border: 1px solid var(--theme-d8d4cc);
|
||||
border-radius: 8px;
|
||||
background: var(--theme-fffdf8);
|
||||
color: var(--theme-716b61);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sidebar-theme-toggle:hover {
|
||||
border-color: var(--theme-c7c2b8);
|
||||
.sidebar-theme-selector button {
|
||||
min-width: 0;
|
||||
min-height: 32px;
|
||||
padding: 0 8px;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
background: transparent;
|
||||
color: var(--theme-716b61);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
transition: background 140ms ease, color 140ms ease, box-shadow 140ms ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sidebar-theme-selector button:hover {
|
||||
background: var(--theme-e8e5dc);
|
||||
color: var(--theme-2d2a26);
|
||||
}
|
||||
|
||||
.sidebar-theme-toggle > svg {
|
||||
color: var(--theme-7a746c);
|
||||
}
|
||||
|
||||
.sidebar-theme-toggle > span {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.theme-switch-track {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 36px;
|
||||
height: 20px;
|
||||
border: 1px solid var(--theme-c7c2b8);
|
||||
border-radius: 999px;
|
||||
.sidebar-theme-selector button.active {
|
||||
background: var(--theme-dfdcd4);
|
||||
transition: border-color 160ms ease, background 160ms ease;
|
||||
}
|
||||
|
||||
.theme-switch-track b {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
display: block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: var(--theme-fff);
|
||||
box-shadow: 0 1px 3px rgba(45, 42, 38, 0.24);
|
||||
transition: transform 180ms ease, background 160ms ease;
|
||||
}
|
||||
|
||||
.sidebar-theme-toggle[aria-pressed='true'] .theme-switch-track {
|
||||
border-color: var(--theme-8069ad);
|
||||
background: var(--theme-654f91);
|
||||
}
|
||||
|
||||
.sidebar-theme-toggle[aria-pressed='true'] .theme-switch-track b {
|
||||
transform: translateX(16px);
|
||||
box-shadow: inset 0 0 0 1px var(--theme-d5d2cb);
|
||||
color: var(--theme-2d2a26);
|
||||
}
|
||||
|
||||
.sidebar-language {
|
||||
|
||||
Reference in new issue
Block a user