feat(reminders): view and cancel a message's existing reminders

There was no way to see or cancel a reminder once set (removeReminder was only
called by the fire-and-forget monitor), and addReminder didn't dedupe, so a
message could silently accumulate duplicate reminders. The Remind Me dialog now
lists the reminders already set on that message (soonest first) each with a
cancel button.

- New shared, tested formatFriendlyDateTime(ts, now?) in utils/datetimeInput.ts
  (Today/Tomorrow/date + time).
- Per-row cancel busy-guard; inline "Could not cancel" on failure.

Also applies two nits from the custom-time review: focus the date input when the
custom picker is revealed, and clear the error when editing date/time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 15:51:11 -04:00
co-authored by Claude Opus 4.8
parent b6725a6ee3
commit 7d67cdeef0
4 changed files with 123 additions and 5 deletions
+1
View File
@@ -750,6 +750,7 @@ Redacted events display "This message has been deleted" along with the redaction
- Message context menu → **Remind Me** sets a personal reminder to revisit a message; reminders are stored in `io.lotus.reminders` account data (sync across devices) via `useReminders`, and fire from `ClientNonUIFeatures`.
- `RemindMeDialog.tsx` offers quick presets (in 20 min / 1 hour / 3 hours / tomorrow 9am) **plus a "Custom time…" option** that reveals date + time pickers for an arbitrary reminder time (validated to be ≥ 1 minute in the future).
- **Manage existing reminders**: opening the dialog on a message that already has reminders lists them (soonest first, friendly time via `formatFriendlyDateTime`) each with a cancel (×) button, so you can see and remove pending reminders instead of silently stacking duplicates.
- The date/time input helpers (`toLocalDate`, `toLocalTime`, `parseLocalDateTime`, `pickerInputStyle`) are shared, pure, and unit-tested in `src/app/utils/datetimeInput.ts` (`datetimeInput.test.ts`) — also used by `ScheduleMessageModal` (deduped from a prior inline copy).
### File Upload Compression (opt-in)