Repository navigation
Keep timer shortcuts away from buttons and open menus - #172
Merged
Merged
Conversation
Space, Escape, and the arrow keys were listened for on the whole window, so they started or reset a speech while a button, select, or menu already had them. Escape after closing a menu also reset a paused speech. Those keys are now ignored when a control is using them. Co-authored-by: Gáborjáni-Szabó Ádám <Programcode@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reachedEnable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. Next included review available in 49 minutes. View limit details
Note 🎁 Summarized by CodeRabbit Free
Comment |
Programcode
marked this pull request as ready for review
October 22, 2026 12:26
Programcode
added a commit
that referenced
this pull request
Oct 22, 2026
Programcode
added a commit
that referenced
this pull request
Oct 23, 2026
…-01, 18, 17, 02, 19, 06, 07, 13) (#202) * Fix sign-in links, the OAuth callback and per-account state (T2 auth batch) Google and the emailed sign-in link now return to /auth/callback, which holds a loading screen until the code exchange settles and then opens the deep link or /login. PKCE flow ids are appended to redirects and passed to the exchange, so a failed resend or another tab's sign-in no longer deletes the verifier a pending link needs. Auth errors in the callback URL and failed exchanges show a localized message on /login instead of a console warning. Links already in inboxes (/?code=, /app?code=) are moved onto the callback route before the first render. Sign-out uses local scope. After a sign-out, /login returns only the same account to the page it left. The onboarding tour is tracked per account, and on phones it no longer blocks the header menu. The local confirmation email template is code-only with the code out of the subject. Fixes AUTH-01, AUTH-18, AUTH-17, AUTH-02, AUTH-19, AUTH-06, AUTH-07, AUTH-13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address Codex review: hold loading for another account's callback, keep link errors - AuthProvider keeps loading while a callback exchange runs even when the browser's stored session (another account) is announced meanwhile, so the callback page never opens `next` as the wrong account. - A callback error is no longer cleared by any SIGNED_IN (a session restore fires one). When the link fails but another session survives, the callback page opens that account and shows the failure as a toast. - The onboarding store validates its stored copy on every rehydrate (merge), not only on migration. - A tour left running never opens for an account that already finished it. - RequireAuth records the last account in an effect, not during render (docs/standards/async-and-state.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the callback code in the URL until the exchange settles Codex review r2: clearing `code` and `sb_flow_id` before the exchange meant a reload during the spinner found no code and sent the user to /login with an unused code and verifier. The URL is now cleaned once the exchange succeeds, fails or times out; auth errors and empty callbacks are cleaned at once, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the callback code after an exchange timeout A timeout is not a final answer: the code may still be good, so the URL keeps it and a reload can retry, as main did before. Only a success or a definitive failure cleans it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Offer a retry when the callback exchange times out; bound the user lookup Codex review r3: - After a timeout the provider kept the code, but the callback page still navigated to /login and lost it. A timeout now has its own error kind: the page stays on the callback URL and offers Try again (a reload that reuses the code) and Back to sign-in. A late success still opens the app. The provider stays the only owner of stripping callback parameters. - confirmRestoredSession's user lookup had no deadline, and during a callback nothing else ends loading. It now times out after 4 s and, like any unanswered lookup, keeps the local session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a stored account out of a callback; settle late exchange answers Fresh review (Claude, replacing Codex r4, which hit a 429): - While a callback signs an account in, the listener no longer checks or loads a session the browser already had. A dead stored account's lookup could sign out, or block, the account just signed in. init loads the outcome: the new account, or the stored one only if the callback fails. The blocked-session branch also respects callbackPending. - After a timeout the exchange's late answer is final: a success clears the timeout notice and opens the app; a failure shows its real reason instead of a retry that would report a missing verifier. Either way the used code leaves the URL, and only while the callback page is still showing. - The timeout page shows before an existing session would open the app, and its Back to sign-in keeps the deep link. - A dead stored session's sign-out is bounded, so it cannot hold startup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let only the exchange's answer sign an account in during a callback Follow-up review: after a timeout, init restored and checked the stored account while the late exchange could still sign someone else in. A late success during that check got overwritten by the stored account (and the new account's rows loaded under the old owner), and a dead stored account could block the late success. While the code exchange has no answer, even past the timeout, the listener now ignores auth-js's events. init applies the answer itself: the new account on success, or the stored account through the usual server check once the exchange definitively failed. After a timeout nothing is restored until the late answer arrives. A late failure sets its error only while the callback page is still showing. applySession now also does what the listener did for these sign-ins: keep Google's provider token for Drive export and drop the previous account's Crossfire draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * After a callback timeout, let the user act; guard the stored-session restore Follow-up review of 7f1fc05: - The listener ignored auth events until the slow exchange answered, so after the timeout a sign-in on /login was never seen (and never, if the request stalled for good). It now ignores them only until the exchange answers or times out. A late success arrives like any sign-in; it is applied directly only if a blocked restore dropped it. A late failure restores the stored session only if nobody signed in meanwhile. - restoreStoredSession drops its result when a different account was applied while the stored one was being checked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a newer sign-in when the restored stored account turns out dead Follow-up review of 074c9fe (Low): the guard that keeps an account signed in during the stored session's check ran only for a live stored account. It now runs before the dead branch's drop as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add callback fields to the SharedPage auth mock after merging main * Blur the paused timer button before the reset shortcut in the timer recipe (#172) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Space, Escape, and the arrow keys were listened for on the whole window. Pressing them while a button, select, or menu had focus also started, reset, or changed the speech. Escape that only closed a menu reset a paused speech.
Those keys are now ignored when the event was already handled, when a control is focused, or when Ctrl, Alt, or Cmd is held. Escape still does not reset a speech that is running.
No layout change. Keyboard behavior on the timer page changed: shortcuts no longer fire while a control has them.
Verified locally (GitHub Actions is out of minutes, so this is not a CI pass):
npx vitest run src/test/timer/timer-shortcuts.test.ts(2 passed)npx eslinton the helper, TimerPage, and the testnpm run typecheckNot run:
npm run verifyand a browser pass on the timer page.