Skip to content

Dev#16

Merged
BuckyMcYolo merged 2 commits intomainfrom
dev
Mar 9, 2026
Merged

Dev#16
BuckyMcYolo merged 2 commits intomainfrom
dev

Conversation

@BuckyMcYolo
Copy link
Copy Markdown
Owner

@BuckyMcYolo BuckyMcYolo commented Mar 9, 2026

Message Editing and Deletion Feature Implementation

Overview

This PR implements comprehensive message editing and deletion functionality across the full stack of the townhall application. The implementation includes realtime socket event handlers, backend service logic with access control, frontend UI components with optimistic updates, custom React hooks for state management, and utility modules for text processing.

Key Implementation Details

Socket Event Architecture:

  • New message:delete and message:edit socket event handlers on the realtime server
  • Server validates payloads with Zod schemas, checks user permissions, and emits corresponding results
  • message:deleted and message:updated server-to-client events for real-time synchronization
  • Proper error handling with acknowledgments returning { ok: true/false, error? }

Backend Service Layer:

  • deleteMessage() and editMessage() async functions with full access control verification
  • Database queries validate message ownership and channel access
  • Return types include channel context and updated message data
  • Max content length enforced at 2000 characters

Frontend State Management:

  • useMessageDeletion hook: Optimistic deletion with cache filtering and socket listener for remote deletions
  • useMessageEditing hook: Optimistic edits with cache updates and socket listener for remote edits
  • Both hooks properly clean up listeners and handle socket disconnection
  • Automatic cache invalidation and re-fetch on server-side failures

UI Components:

  • MessageEditInput: TipTap editor component with markdown, links, and mentions support
  • MessageItem: Extended with edit/delete state management and confirmation dialogs
  • MessageActionBar: Reorganized to show Edit above Delete with proper permission checks
  • MessageMarkdown: Shows "(edited)" indicator when message has been edited
  • New AlertDialog component suite for delete confirmation
  • message-action-bar.tsx properly conditions callbacks on canManageMessage && onCallback

Route Integration:

  • Channel route creates handleDelete and handleEdit handlers via the new hooks
  • DM route follows identical pattern
  • Both route files properly pass handlers and mentionCandidates to MessageList
  • MessageList propagates props through to individual MessageItem components

Type System & Exports:

  • All new functions and types properly exported from their modules
  • MentionCandidate type properly defined and available throughout component tree
  • Zod schemas ensure runtime validation of socket payloads
  • RealtimeMessage extended with optional editedAt field

Utility Module:

  • editor-utils.ts extracts mention processing logic from message-input.tsx
  • toStoredMarkdown() normalizes markdown and converts TipTap mentions to stored format
  • extractMentionIds() pulls unique mention IDs from stored content
  • message-input.tsx exports SUGGESTION_MENU_SELECTOR and createMentionSuggestion for reuse

Code Quality Assessment

Strengths:

  • Consistent patterns across socket events (mirrors existing message:send and message:reaction:toggle flows)
  • Proper separation of concerns: types, services, hooks, components, utilities
  • Comprehensive access control with channel and ownership checks
  • Optimistic UI updates with automatic failure recovery
  • Type-safe implementation with Zod runtime validation
  • Socket listeners properly cleaned up on unmount
  • Handles edge cases like unchanged content (edit cancels if content matches)
  • Proper keyboard handling in edit input (Escape to cancel, Enter to save unless suggestion menu open)

Areas of Concern:

  • No visible test coverage: No test files found for new hooks, services, or components
  • Regex-based mention handling: TIPTAP_MARKDOWN_MENTION_REGEX and STORED_MENTION_REGEX patterns may be fragile without comprehensive test coverage
  • Broad change scope: 16 modified/created files with interdependencies increase integration risk
  • Content comparison logic: Relies on string trimming matching between frontend toStoredMarkdown and backend trimming - any mismatch in logic could cause edit rejections
  • IME composition handling: KeyDown event listener for Enter may not properly detect IME composition state (event.isComposing check not visible in shown code)
  • EditedAt timestamp: Frontend generates new Date().toISOString() for optimistic UI; server may generate different timestamp on actual update, potential mismatch

Potential Edge Cases Not Addressed:

  • What happens if a user rapidly edits the same message multiple times
  • Concurrent edits by multiple users (last-write-wins behavior)
  • Network race conditions between emit and ack
  • Socket reconnection while edit is in progress

Confidence Score: 4/5

Rationale: The implementation is well-structured, follows established patterns throughout the codebase, and demonstrates solid architectural decisions. The wiring between components, hooks, routes, and socket handlers is complete and correct. Type safety is properly maintained, error handling is comprehensive, and optimistic UI updates include fallback mechanisms.

The main deductions are: (1) complete absence of visible test coverage for new functionality, (2) reliance on regex patterns that could be brittle, and (3) potential timing issues with optimistic timestamps. However, the core implementation quality is strong, with proper cleanup, error handling, and permission checks throughout. The PR is production-ready with the understanding that test coverage should be added separately.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

This pull request adds message deletion and editing functionality across the realtime server and web client. New socket event handlers process delete/edit operations, new React hooks manage optimistic UI updates with cache synchronization, and new components enable message editing interfaces and confirmation dialogs.

Changes

Cohort / File(s) Summary
Realtime Server Message Operations
apps/realtime/src/index.ts, apps/realtime/src/services/messages.ts
Added two new socket event handlers (message:delete, message:edit) that parse payloads, call service functions, emit acknowledgment events, and handle errors. Introduced deleteMessage and editMessage service functions with access/ownership validation and result types (DeleteMessageResult, EditMessageResult).
Message Editing UI
apps/web/src/components/chat/message-edit-input.tsx, apps/web/src/components/chat/message-markdown.tsx
Created new MessageEditInput component with TipTap editor for inline message editing with keyboard shortcuts (Escape to cancel, Enter to save) and content validation (max 2000 chars). Extended MessageMarkdown with optional editedAt prop to display "(edited)" label when messages are modified.
Message Actions & Integration
apps/web/src/components/chat/message-action-bar.tsx, apps/web/src/components/chat/message-item.tsx
Reorganized action menu layout with Copy always visible and Delete/Edit consolidated under canManageMessage guard with a separator. Integrated delete confirmation dialog and edit mode toggling into MessageItem with new onDelete, onEdit, and mentionCandidates props.
Message List Prop Threading
apps/web/src/components/chat/message-list.tsx
Added optional onDelete, onEdit, and mentionCandidates props to MessageList and threaded them down to child MessageItem components.
Optimistic Update Hooks
apps/web/src/hooks/use-message-deletion.ts, apps/web/src/hooks/use-message-editing.ts
Created two new React hooks providing optimistic cache updates and socket event subscription. useMessageDeletion removes messages from cache before server confirmation; useMessageEditing updates message content/editedAt in cache with server sync.
Editor Utilities & Adapters
apps/web/src/lib/editor-utils.ts, apps/web/src/lib/realtime-adapter.ts, apps/web/src/components/chat/composer/message-input.tsx
Extracted mention and markdown utilities into new editor-utils module with regex constants and conversion functions. Updated realtime-adapter to map editedAt from realtime messages. Exported SUGGESTION_MENU_SELECTOR and createMentionSuggestion from message-input and imported utilities from external module.
Route Integration
apps/web/src/routes/_authenticated/$guildSlug/$channelId.tsx, apps/web/src/routes/_authenticated/dms/$dmId.tsx
Integrated new deletion and editing hooks into both guild channel and DM routes, wiring handleDelete and handleEdit handlers to MessageList component.
Realtime Type Definitions
packages/realtime-types/src/events.ts
Added new event schemas (deleteMessagePayloadSchema, editMessagePayloadSchema), payload types, acknowledgment types, and client-to-server (message:delete, message:edit) and server-to-client (message:deleted, message:updated) events. Extended RealtimeMessage with optional editedAt field.
UI Component Library
packages/ui/src/components/alert-dialog.tsx
Introduced comprehensive AlertDialog component wrapper around radix-ui with subcomponents (Trigger, Content, Header, Footer, Title, Description, Action, Cancel, Media) supporting composition and consistent styling.
Documentation
ROADMAP.md
Marked Phase 1 "Message deletion" task as complete.

Sequence Diagram

sequenceDiagram
    participant User as User (Client)
    participant UI as Web UI
    participant Hook as Edit/Delete Hook
    participant Cache as Query Cache
    participant Socket as WebSocket
    participant Server as Realtime Server
    participant DB as Database

    User->>UI: Click Delete/Edit message
    UI->>Hook: Call handleDelete/handleEdit

    Hook->>Cache: Optimistically update cache<br/>(remove message or update content)
    Hook->>Socket: Emit message:delete/message:edit<br/>with payload (channelId, messageId, content)
    
    Socket->>Server: Receive event payload
    Server->>Server: Validate ownership & permissions
    Server->>DB: Delete/update message in database
    DB-->>Server: Confirmation
    Server->>Socket: Emit message:deleted/<br/>message:updated event
    Server-->>Socket: Send ack (ok: true)
    
    Socket->>Hook: Receive message:deleted/<br/>message:updated event
    Hook->>Cache: Apply confirmed update<br/>(if matches channelId)
    
    alt On Error
        Server-->>Socket: Send ack (ok: false, error)
        Socket->>Hook: Receive ack with error
        Hook->>Cache: Invalidate messages query<br/>(re-fetch from server)
    end
    
    Cache->>UI: Notify of cache update
    UI->>User: Render updated message list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • feat: added simple SocketIO server in apps/realtime #8: Extends realtime message service APIs with new deleteMessage and editMessage functions that build on existing message handling patterns established in that PR.
  • Dev #12: Enhances chat UI components (message-action-bar, message-item, message-list) by integrating message deletion and editing capabilities that leverage the component scaffolding from that PR.

Poem

🐰 Hops of joy through edit land,
Messages now bend to hand,
Delete with grace, edit with care,
Optimistic updates fill the air!
Socket whispers truth so sweet,
Cache and server now compete.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Dev' is vague and generic, providing no meaningful information about the changeset's purpose or primary changes. Rename the title to clearly describe the main feature being implemented, such as 'Add message editing and deletion capabilities' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/hooks/use-message-editing.ts`:
- Around line 55-79: The optimistic editedAt timestamp created in handleEdit
(editedAt) can diverge from the server's authoritative timestamp; update the
socket.emit ack handling in handleEdit to accept a server-editedAt (e.g.,
result.editedAt) and, when result.ok is true, call
updateMessageInCache(messageId, content, result.editedAt) to reconcile the cache
with the server; keep the optimistic update for immediacy but overwrite it on
successful ack with the server timestamp, and on failure continue invalidating
via queryClient.invalidateQueries({ queryKey: ["messages", channelId] }).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 24cf558f-f28a-421e-a971-dee38daf5de6

📥 Commits

Reviewing files that changed from the base of the PR and between 2bc78b7 and 4b91738.

📒 Files selected for processing (17)
  • ROADMAP.md
  • apps/realtime/src/index.ts
  • apps/realtime/src/services/messages.ts
  • apps/web/src/components/chat/composer/message-input.tsx
  • apps/web/src/components/chat/message-action-bar.tsx
  • apps/web/src/components/chat/message-edit-input.tsx
  • apps/web/src/components/chat/message-item.tsx
  • apps/web/src/components/chat/message-list.tsx
  • apps/web/src/components/chat/message-markdown.tsx
  • apps/web/src/hooks/use-message-deletion.ts
  • apps/web/src/hooks/use-message-editing.ts
  • apps/web/src/lib/editor-utils.ts
  • apps/web/src/lib/realtime-adapter.ts
  • apps/web/src/routes/_authenticated/$guildSlug/$channelId.tsx
  • apps/web/src/routes/_authenticated/dms/$dmId.tsx
  • packages/realtime-types/src/events.ts
  • packages/ui/src/components/alert-dialog.tsx

Comment thread apps/web/src/hooks/use-message-editing.ts
@BuckyMcYolo BuckyMcYolo merged commit 4f0d477 into main Mar 9, 2026
1 check passed
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.

1 participant