Skip to content

fix(notifications): restore exact prior state on undo - #1300

Merged
greatest0fallt1me merged 3 commits into
Creditra:mainfrom
Tekgodfrey:fix/notification-undo
Oct 24, 2026
Merged

greatest0fallt1me merged 3 commits into
Creditra:mainfrom
Tekgodfrey:fix/notification-undo

Conversation

@Tekgodfrey

Copy link
Copy Markdown
Contributor

Title

fix(notifications): restore exact prior state on undo and fix Shift+R shortcut

Description

Closes #1225

This PR ensures that NotificationCenter's undo actions restore the exact prior state the user had, makes undo actions resilient against category mute preferences, and fixes the Shift+R keyboard shortcut so it fires reliably in real browsers while ignoring inputs in editable fields.


Undo Semantics & Architecture

1. Exact Undo for "Mark All as Read"

  • Prior State Capture: handleMarkAllAsRead filters and captures only the IDs of notifications that were unread at execution time (notifications.filter(n => !n.read).map(n => n.id)).
  • Restoration: Triggering "Undo" calls undoRead(unreadIds), marking only those captured items as unread. Notifications that were already read before the action maintain their read state.
  • Idempotency: Clicking Undo multiple times is protected with an execution guard, and calling undoRead with the same IDs is an idempotent state transition.

2. Merge-Safe Undo for "Clear All"

  • Snapshot & Window: When "Clear all" is clicked, a snapshot of the current notifications is captured before clearing the list, and an undo toast is displayed for 6 seconds.
  • Pure Merge: Calling restoreNotifications(snapshot) merges the cleared snapshot with any notifications that arrived or updated during the undo window via the pure helper mergeNotifications(snapshot, current, cap).
  • Deduplication & Sorting: Notifications are deduplicated by id (with newer arrivals taking precedence), sorted descending by timestamp (newest first), and capped at the 100-notification limit.
  • Idempotency: Clicking Undo twice does not duplicate notifications.

3. Category Preferences Bypass (bypassPreferences)

  • New Option: Added optional bypassPreferences?: boolean to AddToastOptions.
  • Behavior: When bypassPreferences: true is set, addToast bypasses category mute checks (such as preferences.system = false).
  • Policy: Reserved exclusively for undo toasts and critical alerts to prevent user actions from silencing the only mechanism to revert destructive changes.

4. Keyboard Shortcut (Shift+R)

  • Key Matching: Changed e.key === 'r' to e.key.toLowerCase() === 'r' alongside e.shiftKey to account for standard browser keyboard event dispatching where holding Shift sets e.key === 'R'.
  • Editable Element Guard: Added isEditableTarget(e.target) to suppress the shortcut if focus or the event target is inside an <input>, <textarea>, <select>, or isContentEditable element.
  • Scope: Preserved the requirement that the shortcut only activates when the panel is open (isPanelOpen === true) and unreadCount > 0.

Regression Proof

  • Row 1 (2 unread & 3 read, Mark all, Undo): Failed on main because undoRead(prior.map(n => n.id)) marked all 5 notifications unread.
  • Row 4 (preferences.system = false, Mark all): Failed on main because the undo toast defaulted to category 'system' and addToast returned '', suppressing the toast.
  • Row 5 (Shift+R with panel open): Failed on main because the existing test "activates mark all read with Shift+R keyboard shortcut" dispatched R with Shift, which failed to match e.key === 'r'.

All 3 scenarios now pass reliably.


Verification Results

Test Suite

npm test -- --run src/components/notifications/NotificationCenter.test.tsx src/context/__tests__/notificationMerge.test.ts

@drips-wave

drips-wave Bot commented Oct 20, 2026

Copy link
Copy Markdown

@Tekgodfrey Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Tekgodfrey

Copy link
Copy Markdown
Contributor Author

@greatest0fallt1me kindly review sir

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	src/lib/draw-credit-pricing.ts
@greatest0fallt1me
greatest0fallt1me merged commit ca91e95 into Creditra:main Oct 24, 2026
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.

NotificationCenter: make undo restore the exact prior state and fix the Shift+R mark-all-read shortcut

2 participants