Skip to content

Commit 705baf5

Browse files
committed
fix(options): surface provider sign-in feedback as a visible toast
Status messages rendered into an off-screen #status element at the bottom of the page and auto-hid after 2.2s, so feedback from provider panels lower on the page was never seen — the Claude OAuth "Finish" button looked like it did nothing. Make #status a fixed, always-visible toast, add a busy state to the Finish button, surface the empty-paste case, and keep errors on screen long enough to read.
1 parent 5903010 commit 705baf5

2 files changed

Lines changed: 32 additions & 8 deletions

File tree

options.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,19 @@
417417
background: var(--accent-deep-hover);
418418
}
419419
#status {
420-
font-size: 12px;
421-
margin-top: 12px;
420+
position: fixed;
421+
left: 50%;
422+
bottom: 24px;
423+
transform: translateX(-50%);
424+
max-width: min(90vw, 520px);
425+
font-size: 13px;
426+
line-height: 1.4;
427+
padding: 12px 18px;
428+
border-radius: 12px;
429+
background: var(--surface, #1b1b22);
430+
border: 1px solid var(--border, #3a3a44);
431+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
432+
z-index: 9999;
422433
display: none;
423434
}
424435

src/options.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -520,13 +520,16 @@ anyCompatConnected().then((on) => {
520520
}
521521
});
522522

523-
function showStatus(msg, color) {
523+
let _statusHideTimer = null;
524+
function showStatus(msg, color, durationMs = 2600) {
524525
statusEl.textContent = msg;
525526
statusEl.style.color = color;
526527
statusEl.style.display = 'block';
527-
setTimeout(() => {
528+
if (_statusHideTimer) clearTimeout(_statusHideTimer);
529+
_statusHideTimer = setTimeout(() => {
528530
statusEl.style.display = 'none';
529-
}, 2200);
531+
_statusHideTimer = null;
532+
}, durationMs);
530533
}
531534

532535
function openTab(url) {
@@ -895,21 +898,31 @@ document.getElementById('anthropic-oauth-start')?.addEventListener('click', asyn
895898
});
896899

897900
document.getElementById('save-anthropic-oauth')?.addEventListener('click', async () => {
901+
const btn = document.getElementById('save-anthropic-oauth');
898902
const input = document.getElementById('anthropicOAuthCode');
899903
const authCode = input.value.trim();
900-
if (!authCode) return;
904+
if (!authCode) {
905+
showStatus('Paste the Claude code first.', '#f87171');
906+
input.focus();
907+
return;
908+
}
901909
try {
910+
setButtonBusy(btn, true, 'Finishing…');
902911
const s = await chrome.storage.local.get(ANTHROPIC_OAUTH_VERIFIER_KEY);
903912
const verifier = s[ANTHROPIC_OAUTH_VERIFIER_KEY];
904-
if (!verifier) throw new Error('Start Claude sign-in first.');
913+
if (!verifier) throw new Error('Start Claude sign-in first, then paste the code.');
905914
const tokens = await exchangeAnthropicCode({ authCode, verifier });
906915
await saveAnthropicOAuthTokens(tokens);
907916
await chrome.storage.local.remove(['anthropicKey', ANTHROPIC_OAUTH_VERIFIER_KEY]);
908917
input.value = '';
909918
setConnected('anthropic', tokens.access, { method: 'oauth' });
910919
showStatus('✓ Connected to Claude', '#4ade80');
911920
} catch (err) {
912-
showStatus('✗ Claude sign-in: ' + (err?.message || err), '#f87171');
921+
// Keep the real reason on screen long enough to read — Claude codes are
922+
// short-lived, so an expired/reused code is the most common failure here.
923+
showStatus('✗ Claude sign-in: ' + (err?.message || err), '#f87171', 7000);
924+
} finally {
925+
setButtonBusy(btn, false);
913926
}
914927
});
915928

0 commit comments

Comments
 (0)