Skip to content

Keep timer shortcuts away from buttons and open menus - #172

Merged
Programcode merged 1 commit into
mainfrom
cursor/timer-shortcuts-ignore-controls-791b
Oct 22, 2026
Merged

Programcode merged 1 commit into
mainfrom
cursor/timer-shortcuts-ignore-controls-791b

Conversation

@Programcode

Copy link
Copy Markdown
Owner

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 eslint on the helper, TimerPage, and the test
  • npm run typecheck

Not run: npm run verify and a browser pass on the timer page.

Open in Web Open in Cursor 

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>
@vercel

vercel Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
debate-navigator Ready Ready Preview Oct 22, 2026 11:22am UTC
debatelab-staging Ready Ready Preview Oct 22, 2026 11:22am UTC

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Next included review available in 49 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 4f9e0a0 and 130966f.

📒 Files selected for processing: 3
  • src/lib/timer-shortcuts.ts
  • src/pages/TimerPage.tsx
  • src/test/timer/timer-shortcuts.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Programcode
Programcode merged commit 0f50644 into main Oct 22, 2026
7 of 14 checks passed
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

2 active deployments
Preview – debatelab-staging — 130966f1 Deployed Oct 22, 2026 by vercel[bot]
Preview – debate-navigator — 130966f1 Deployed Oct 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants