Skip to content

Commit 49d8062

Browse files
committed
fix(gui): i18n combo effort-none option + avoid ref access during render in codex-auth modal (lint)
1 parent 0de138a commit 49d8062

7 files changed

Lines changed: 14 additions & 2 deletions

File tree

gui/src/components/AddCodexAccountModal.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default function AddCodexAccountModal({
1818
const [copied, setCopied] = useState(false);
1919
const [manualCode, setManualCode] = useState("");
2020
const [manualCodeBusy, setManualCodeBusy] = useState(false);
21+
const [flowId, setFlowId] = useState<string | null>(null);
2122

2223
const aliveRef = useRef(true);
2324
const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
@@ -52,6 +53,7 @@ export default function AddCodexAccountModal({
5253
clearManualCode();
5354
const flowId = flowRef.current;
5455
flowRef.current = null;
56+
setFlowId(null);
5557
setAuthUrl("");
5658
stopPolling();
5759
loginAbortRef.current?.abort();
@@ -71,6 +73,7 @@ export default function AddCodexAccountModal({
7173
loginAbortRef.current = null;
7274
const flowId = flowRef.current;
7375
flowRef.current = null;
76+
setFlowId(null);
7477
if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; }
7578
if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; }
7679
// Cancel in-flight OAuth so a remounted modal cannot race a stale chatgpt scratch slot.
@@ -91,6 +94,7 @@ export default function AddCodexAccountModal({
9194
const startOAuth = useCallback(async (requestedId?: string) => {
9295
clearManualCode();
9396
flowRef.current = null;
97+
setFlowId(null);
9498
const controller = new AbortController();
9599
loginAbortRef.current?.abort();
96100
loginAbortRef.current = controller;
@@ -115,6 +119,7 @@ export default function AddCodexAccountModal({
115119
}
116120
if (data.url) {
117121
flowRef.current = data.flowId ?? null;
122+
setFlowId(data.flowId ?? null);
118123
setAuthUrl(data.url);
119124
setStep("oauth-waiting");
120125
stopPolling();
@@ -130,13 +135,15 @@ export default function AddCodexAccountModal({
130135
stopPolling();
131136
clearManualCode();
132137
flowRef.current = null;
138+
setFlowId(null);
133139
if (!aliveRef.current) return;
134140
onAddedRef.current();
135141
onCloseRef.current();
136142
} else if (st.status === "error" || st.status === "expired") {
137143
stopPolling();
138144
clearManualCode();
139145
flowRef.current = null;
146+
setFlowId(null);
140147
if (aliveRef.current) {
141148
if (!reauthAccountId) setStep("pick");
142149
setError(st.error ?? "Login failed");
@@ -308,7 +315,7 @@ export default function AddCodexAccountModal({
308315
<button
309316
className="btn btn-ghost"
310317
type="button"
311-
disabled={manualCodeBusy || !manualCode.trim() || !flowRef.current}
318+
disabled={manualCodeBusy || !manualCode.trim() || !flowId}
312319
onClick={() => void submitManualCode()}
313320
>
314321
{manualCodeBusy ? t("prov.pasteSubmitting") : t("prov.pasteSubmit")}

gui/src/components/ComboWorkspace.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ function EffortSelect({
140140
aria-label={t("cws.field.defaultEffort")}
141141
onChange={(e) => onChange(e.target.value === "" ? null : e.target.value as ComboEffort)}
142142
>
143-
<option value="">None (target default)</option>
143+
<option value="">{t("cws.field.defaultEffortNone")}</option>
144144
{COMBO_EFFORTS.map((effort) => (
145145
<option key={effort} value={effort}>{effort}</option>
146146
))}

gui/src/i18n/de.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,7 @@ export const de = {
923923
"cws.field.stickyLimit": "Sticky-Erfolge vor Rotation",
924924
"cws.field.stickyLimitHint": "Das gewählte Ziel für so viele erfolgreiche Anfragen behalten, bevor die gewichtete Auswahl weiterschaltet.",
925925
"cws.field.defaultEffort": "Standard-Reasoning",
926+
"cws.field.defaultEffortNone": "Keine (Ziel-Standard)",
926927
"cws.field.defaultEffortHint": "Nur verwendet, wenn der Client keinen Reasoning-Aufwand sendet. Der Client-Wert hat Vorrang; jedes Ziel wendet seine eigene Fähigkeitsbehandlung an.",
927928
"cws.targets": "Ziele",
928929
"cws.targets.failoverHint": "Reihenfolge zählt — das erste ist primär.",

gui/src/i18n/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@ export const en = {
944944
"cws.field.stickyLimit": "Sticky successes before rotate",
945945
"cws.field.stickyLimitHint": "Retain the selected target for this many successful requests before the weighted selector advances.",
946946
"cws.field.defaultEffort": "Default reasoning",
947+
"cws.field.defaultEffortNone": "None (target default)",
947948
"cws.field.defaultEffortHint": "Used only when the client omits reasoning effort. Client effort wins, and each target applies its own capability handling.",
948949
"cws.targets": "Targets",
949950
"cws.targets.failoverHint": "Order matters — first is primary.",

gui/src/i18n/ko.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ export const ko: Record<TKey, string> = {
943943
"cws.field.stickyLimit": "회전 전 sticky 성공 횟수",
944944
"cws.field.stickyLimitHint": "가중 선택기가 다음 대상으로 진행하기 전에 선택된 대상을 이 성공 요청 횟수만큼 유지합니다.",
945945
"cws.field.defaultEffort": "기본 추론 수준",
946+
"cws.field.defaultEffortNone": "없음 (대상 기본값)",
946947
"cws.field.defaultEffortHint": "클라이언트가 추론 수준을 생략한 경우에만 사용합니다. 클라이언트 값이 우선하며 각 대상이 자체 기능에 맞게 처리합니다.",
947948
"cws.targets": "대상",
948949
"cws.targets.failoverHint": "순서가 중요합니다 — 첫 번째가 기본입니다.",

gui/src/i18n/ru.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ export const ru: Record<TKey, string> = {
946946
"cws.field.stickyLimit": "Успешных запросов до ротации",
947947
"cws.field.stickyLimitHint": "Выбранная цель удерживается на указанное число успешных запросов, прежде чем взвешенный селектор перейдёт к следующей.",
948948
"cws.field.defaultEffort": "Рассуждения по умолчанию",
949+
"cws.field.defaultEffortNone": "Нет (по умолчанию для цели)",
949950
"cws.field.defaultEffortHint": "Используется, только если клиент не указал уровень рассуждений. Значение клиента имеет приоритет, а каждая цель применяет собственную обработку возможностей.",
950951
"cws.targets": "Цели",
951952
"cws.targets.failoverHint": "Порядок важен — первая цель основная.",

gui/src/i18n/zh.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ export const zh: Record<TKey, string> = {
943943
"cws.field.stickyLimit": "轮换前的粘性成功次数",
944944
"cws.field.stickyLimitHint": "加权选择器推进前,将所选目标保留这么多次成功请求。",
945945
"cws.field.defaultEffort": "默认推理级别",
946+
"cws.field.defaultEffortNone": "无(使用目标默认)",
946947
"cws.field.defaultEffortHint": "仅在客户端未指定推理级别时使用。客户端值优先,每个目标会按自身能力进行处理。",
947948
"cws.targets": "目标",
948949
"cws.targets.failoverHint": "顺序很重要 — 第一个为主。",

0 commit comments

Comments
 (0)