Skip to content

fix(clients): reschedule a snoozed thread from its menu - #35139

Open
ekrako wants to merge 1 commit into
pingdotgg:mainfrom
ekrako:fix/reschedule-snoozed-thread
Open

ekrako wants to merge 1 commit into
pingdotgg:mainfrom
ekrako:fix/reschedule-snoozed-thread

Conversation

@ekrako

@ekrako ekrako commented Nov 12, 2026

Copy link
Copy Markdown

Fresh replacement for #18170, opened from current main following Theo's request. The changes and linked screenshots/videos below are carried over from that PR; its verification section records the original testing.

What Changed

Supersedes #16081 (closed for missing mobile evidence; same change, rebased on current main, mobile verification added below).

A snoozed thread's menu now offers Reschedule next to Wake thread, with the same presets as Snooze (In 1 hour, In 3 hours, This evening, Tomorrow, Custom…). Wake thread gets a bell icon so the two stand apart.

Rescheduling keeps the row on the Snoozed shelf and only updates its wake label.

  • Web: the confirmation is the shared sidebar undo notice, "Rescheduled 1 thread, ⌘Z to undo". Undo restores the previous wake time instead of waking the thread. The claim goes through the shared ThreadUndo stack, so a newer wake time expires the older notice; an older Undo can never replace a newer choice.
  • Mobile: Reschedule is a submenu on snoozed rows. Mobile has no undo notice, so the row just shows its new wake time. Snoozed rows now carry the minute stamp, so the preset times in the submenu stay current while it is open.

Why

Once a thread was snoozed, the only exit was Wake thread. Picking a later time meant waking it and snoozing again, which also moved the row off and back onto the shelf.

UI Changes

Web

Dark theme, right-click on a snoozed row.

Before (main) After
Snoozed row menu on main: only Wake thread Snoozed row menu with Wake thread and Reschedule
Reschedule presets Rescheduled to 3h, row stays, notice shown
Reschedule submenu Row stays on Snoozed shelf at 3h with Rescheduled notice

Older Undo does not replace a newer choice: reschedule to Tomorrow (17h), click Undo, the row returns to 3h (the previous wake), not the original 60m. A further ⌘Z is a no-op.

Second reschedule (17h) After Undo (back to 3h) Extra ⌘Z, unchanged
Second reschedule to 17h Undo restores previous wake time 3h Older undo is gone

Recording (snooze, reschedule, second reschedule, Undo, ⌘Z):

https://github.com/ekrako/t3code/raw/eac47816dd99a431398eff565ae4ccd707167b75/pr-12088/after-reschedule-undo.mp4

Mobile (iOS Simulator, iPhone 17)

Long-press on a snoozed row.

Before (main): row Before (main): menu, no Reschedule After: menu with Reschedule

The row keeps its place on the Snoozed shelf while its wake time changes: 58m → In 3 hours → Tomorrow.

Reschedule presets After "In 3 hours" After "Tomorrow, 9:00"

Recording (two reschedules; idle waits trimmed). The preset times tick from 12:53 to 12:54 while the submenu is open:

https://github.com/ekrako/t3code/raw/87ae7fb5a0aea43662e5f6b6efdd0fb1f4d74159/pr-12088/mobile/after-reschedule-mobile.mp4

The soft keyboard under every simulator context menu is a simulator artifact (no hardware keyboard attached); it shows on main too.

Verification

  • Web: vp test run on Sidebar.snooze.test.ts, threadActionMenu.logic.test.ts, useThreadActions.undo.test.ts: 40 pass. Covers restoring the previous wake on undo, waking instead when that wake time has already passed, an older Undo being ignored after a newer choice, and Reschedule staying disabled without operate permission.
  • Mobile: vp test run src/features/threads/: 331 pass, including snoozed rows carrying the preset minute stamp.
  • apps/web and apps/mobile tsc --noEmit clean. Lint and fmt clean on changed files.
  • Web pass in headless Chrome against a dev server seeded with real data, with a parallel main build for the before shots.
  • Mobile pass on the iOS Simulator (dev client built from this branch, main worktree for the before shots) against a disposable seeded backend.
  • Not checked: Android (no Android SDK on this host). The screenshots were taken before the final rebase onto current main; the rebase had no conflicts in these files.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Model: Claude Opus 5.5 | Harness: Claude Code in T3 Code

Closes discussions

Fresh branch verification

Replacement prepared with gpt-6.1-sol in the Codex harness through T3 Code. Original implementation attribution is retained above.

@github-actions github-actions Bot added the vouch:unvouched Author is not yet trusted in the VOUCHED list. label Nov 12, 2026
@ekrako
ekrako force-pushed the fix/reschedule-snoozed-thread branch from b9a82a1 to c149e88 Compare November 12, 2026 10:26
@github-actions github-actions Bot added the size:L 100-499 changed lines (additions + deletions). label Nov 12, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at b9a82a1

Macroscope's review found this PR approvable — Snoozed threads gain an explicit Reschedule action that preserves their shelf placement and restores the previous wake time on Undo. The change reuses existing snooze operations without changing product defaults.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • Resume reviews
  • Trigger review

No actionable comments were generated in the recent review.

Walkthrough

Web and mobile thread menus now offer rescheduling for snoozed threads. Undo can restore the previous wake time when it remains in the future, or unsnooze the thread when that time has passed. Fresh snoozes retain their existing undo behavior.

Changes: Snooze Rescheduling

Layer / File(s) Summary
Web and mobile reschedule controls
apps/web/src/components/threadActionMenu.logic.ts, apps/web/src/components/threadActionMenu.logic.test.ts, apps/web/src/contextMenuFallback.ts, apps/mobile/src/features/threads/thread-list-v2-items.tsx, apps/mobile/src/features/threads/threadListV2.ts, apps/mobile/src/features/threads/threadListV2.test.ts, docs/user/thread-sidebar.md
Web and mobile menus provide reschedule options for snoozed threads. Mobile snoozed rows retain preset timing. Wake actions use updated icons, and the sidebar instructions describe rescheduling.
Reschedule action handling
apps/web/src/components/Sidebar.snooze.ts, apps/web/src/components/Sidebar.snooze.test.ts, apps/web/src/components/Sidebar.tsx, apps/web/src/hooks/useThreadActions.ts, apps/mobile/src/features/home/useThreadListActions.ts
Web and mobile actions distinguish rescheduling from a fresh snooze. Web actions capture the prior wake time and skip forward navigation when rescheduling. Mobile reschedules bypass the dismissal animation.
Undo planning and restoration
packages/client-runtime/src/state/threadUndo.ts, apps/web/src/hooks/showThreadUndoNotice.ts, apps/web/src/hooks/useThreadActions.undo.test.ts, apps/mobile/src/features/home/thread-undo-notice.ts, apps/mobile/src/features/home/useThreadListActions.test.ts
Undo restores a prior wake time when it remains in the future and unsnoozes when it has expired. Notices identify reschedules, and tests cover restoration and stale undo behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant ThreadMenu
  participant SnoozeAction
  participant UndoRuntime
  User->>ThreadMenu: Select a reschedule option
  ThreadMenu->>SnoozeAction: Start snooze action
  SnoozeAction->>UndoRuntime: Plan undo using the prior wake time
  User->>UndoRuntime: Undo the reschedule
  UndoRuntime->>UndoRuntime: Restore prior wake time or unsnooze if expired
Loading

Possibly related PRs

Suggested reviewers: t3dotgg, maria-rcks

Merge Risk: Minimal · previous review e450f

This change adds a Reschedule action for snoozed threads on web and mobile, with undo restoring the previous wake time. No concrete merge-blocking risk was found in the supplied evidence.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title "fix(clients): reschedule a snoozed thread from its menu" names the main change. The changeset adds a Reschedule action to snoozed-thread menus on web and mobile, with undo support on web. T…
Description check Passed The description follows the repository template. It includes a conventional-style title reference, a What Changed section explaining the behavior, a Why section for the problem, UI before/after screen…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "fix(clients): reschedule a snoozed thread from its menu" names the main change. The changeset adds a Reschedule action to snoozed-thread menus on web and mobile, with undo support on web. The title follows the conventional commit format and is specific. It does not cover the undo behavior or the mobile submenu, which is acceptable for a title.

Full details: Description check

Explanation

The description follows the repository template. It includes a conventional-style title reference, a What Changed section explaining the behavior, a Why section for the problem, UI before/after screenshots and a recording for web and mobile, and a Verification section that lists the focused tests, type checks, and the checks not performed (Android). The Scope section is weak: it does not link a bug issue. It cites a discussion (#18181) and a superseded PR, but it frames the work as a feature (adding Reschedule) rather than a bug fix, which the template says is not accepted without an issue. The Problem and Change headings are not used as labeled sections, but their content is present under other headings. The description is mostly complete, so the check passes, but the author should clarify in Scope why this counts as a bug fix and link the request that shows the bug.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 1194443 and e450ff7.

Files selected for processing: 1

  • apps/web/src/components/Sidebar.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

@ekrako
ekrako force-pushed the fix/reschedule-snoozed-thread branch 8 times, most recently from 1194443 to e450ff7 Compare November 12, 2026 12:02
@maria-rcks

maria-rcks commented Nov 15, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

Verified head e450ff7de3926d410b083559afdbd1800c1b2c1c on a disposable Linux VM using the real dev web app, repository Playwright dependencies, and /usr/bin/google-chrome at 1440×900. No code changes were needed.

Reproduced the missing action on github/main (f0495f741757c0103ed6995621111aec231a526b) in a separate worktree first. Created a project pointing at a real git checkout through the UI, selected Codex gpt-6.1-sol, sent a real turn, and snoozed the completed thread. Main offered Wake thread but no Reschedule. Stopped main before starting the exact PR head. Copied only this app-created task state for the matching comparison; no fixtures, mocks, or demo data were used.

On the PR, the same row offered Reschedule and its presets. Exercised the sidebar context menu and thread-header menu through the client and running server:

PASS 1h -> 3h: row stays on Snoozed; current thread route stays selected
PASS 3h -> Tomorrow -> Undo: restores 3h, rather than waking the thread
PASS additional Ctrl+Z: older reschedule does not overwrite the restored time
PASS reload: rescheduled wake persists
PASS Wake thread: leaves Snoozed
PASS fresh Snooze -> Undo: wakes the thread
PASS Custom duration: 2h -> 4h -> Undo restores 2h
PASS real gpt-6.1-sol follow-up after wake/undo: completed successfully

vp run check:changed d412871f27a52709c5978c3f9b0a0433242c50f6 passed through blacksmith-check: format, lint, knip, seven package typechecks, 339 tests in 17 files, 15 cross-file tests, and React Compiler checks. The remote runner needed its Playwright Chromium installed before the successful run. Existing PR CI reports 31 successful checks.

Before on main:

main snoozed thread menu without reschedule

After on the PR head:

pr snoozed thread menu with reschedule

Reschedule twice and undo, with the row remaining on Snoozed:

reschedule presets and undo in the real dev app

Not verified

Native iOS/Android and Electron clients, macOS/Windows, relay/tunnel connections, and other providers were not exercised in this Linux web pass. Automatic wake at the deadline, undo after the previous deadline expires, and restricted-permission sessions were not exercised in the live app; focused automated checks passed, but that is not a substitute for those runtime cases.

@ekrako
ekrako force-pushed the fix/reschedule-snoozed-thread branch from e450ff7 to e52bfcd Compare November 15, 2026 08:24
@ekrako

ekrako commented Nov 15, 2026

Copy link
Copy Markdown
Author

Rebased onto main at 8c80003d68 and pushed e52bfcdb23a93bea93186f3cc1edabf895ad3491. vp run check:changed passed formatting, lint, unused-code checks, typechecking across 7 affected packages, 366 tests across 18 files, and React Compiler checks. All 8 required CI checks passed on this head.

Fresh native testing used dev clients built from this checkout on an iPhone 17 simulator (iOS 27.0) and Pixel 8 emulator (Android 16/API 36), each with an isolated backend and synthetic completed Replay (dev) threads. On both, a thread snoozed for 1 hour showed Reschedule immediately below Wake thread; choosing In 3 hours kept it Snoozed at 3 hours. Android also preserved that deadline after a full app relaunch; rescheduling to 1 hour and selecting Undo restored the exact prior 3-hour deadline, confirmed through CLI state. iOS relaunch/Undo, physical devices, and timed automatic wake were not tested.

Menu Presets After rescheduling
iOS Screenshot Screenshot Screenshot
Android Screenshot Screenshot Screenshot

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched Author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants