Skip to content

Conversation

nizzyabi
Copy link
Collaborator

@nizzyabi nizzyabi commented Apr 11, 2025

READ CAREFULLY THEN REMOVE

Remove bullet points that are not relevant.

PLEASE REFRAIN FROM USING AI TO WRITE YOUR CODE AND PR DESCRIPTION. IF YOU DO USE AI TO WRITE YOUR CODE PLEASE PROVIDE A DESCRIPTION AND REVIEW IT CAREFULLY. MAKE SURE YOU UNDERSTAND THE CODE YOU ARE SUBMITTING USING AI.

  • Pull requests that do not follow these guidelines will be closed without review or comment.
  • If you use AI to write your PR description your pr will be close without review or comment.
  • If you are unsure about anything, feel free to ask for clarification.

Description

Please provide a clear description of your changes.


Type of Change

Please delete options that are not relevant.

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature with breaking changes)
  • 📝 Documentation update
  • 🎨 UI/UX improvement
  • 🔒 Security enhancement
  • ⚡ Performance improvement

Areas Affected

Please check all that apply:

  • Email Integration (Gmail, IMAP, etc.)
  • User Interface/Experience
  • Authentication/Authorization
  • Data Storage/Management
  • API Endpoints
  • Documentation
  • Testing Infrastructure
  • Development Workflow
  • Deployment/Infrastructure

Testing Done

Describe the tests you've done:

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • Cross-browser testing (if UI changes)
  • Mobile responsiveness verified (if UI changes)

Security Considerations

For changes involving data or authentication:

  • No sensitive data is exposed
  • Authentication checks are in place
  • Input validation is implemented
  • Rate limiting is considered (if applicable)

Checklist

  • I have read the CONTRIBUTING document
  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in complex areas
  • I have updated the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix/feature works
  • All tests pass locally
  • Any dependent changes are merged and published

Additional Notes

Add any other context about the pull request here.

Screenshots/Recordings

Add screenshots or recordings here if applicable.


By submitting this pull request, I confirm that my contribution is made under the terms of the project's license.

Summary by CodeRabbit

  • New Features

    • Introduced a “Reply All” option in email threads for reaching all intended recipients.
    • Enhanced the reply composer to support multiple recipient fields (To, CC, BCC) for greater flexibility.
  • Bug Fixes

    • Improved recipient validation to prevent duplicates and invalid addresses.
    • Refined error messaging and overall state management for a smoother email composition and sending experience.

MrgSub and others added 2 commits April 11, 2025 10:46
Update navbar component layout for mobile view
Copy link

vercel bot commented Apr 11, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
0 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 11, 2025 5:53pm

Copy link
Contributor

coderabbitai bot commented Apr 11, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request updates several modules in the mail application. In the API driver, a new replyTo field is extracted and returned, with enhanced logging and recipient validations. The reply composer and thread display components are restructured to support multiple recipient types (to, cc, bcc) along with a new "replyAll" mode, accompanied by improved state management and error handling. Additionally, the mail configuration now tracks a new state flag for the reply-all composer, and type definitions in the parsed message have been updated to include the replyTo field.

Changes

Files Change Summary
apps/mail/app/…/google.ts
apps/mail/types/index.ts
Added replyTo extraction and property; enhanced debug logging, recipient validation, duplicate filtering, and header processing improvements.
apps/mail/components/mail/…/reply-composer.tsx
apps/mail/components/mail/…/thread-display.tsx
apps/mail/components/mail/…/use-mail.ts
Updated reply composer to support multiple recipients (to, cc, bcc) and introduced a new "replyAll" mode with adjusted state management and UI behavior; added utility functions and improved error handling.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ThreadDisplay
  participant ReplyCompose
  participant MailAPI

  User->>ThreadDisplay: Click "ReplyAll" button
  ThreadDisplay->>ThreadDisplay: Set replyAllComposerOpen true<br>Reset other composer states
  ThreadDisplay->>ReplyCompose: Render composer in "replyAll" mode
  User->>ReplyCompose: Compose reply with multiple recipients
  ReplyCompose->>MailAPI: Send email request
  MailAPI->>MailAPI: Parse request, extract replyTo and handle recipients
  MailAPI-->>ReplyCompose: Return send confirmation
Loading

Poem

I hopped through the lines with a twitch of my ear,
Finding new routes in the code, fresh and clear.
With "replyAll" leaping high in a joyful parade,
And headers and logs in a fun, coded charade,
My little rabbit heart beams with digital delight,
Celebrating each change as I hop through the night!
🐇💻


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@MrgSub MrgSub changed the base branch from main to staging April 11, 2025 17:51
@MrgSub MrgSub merged commit 68fdc33 into staging Apr 11, 2025
2 of 3 checks passed
@MrgSub MrgSub deleted the bcc-cc-reply-all branch April 11, 2025 17:51
Copy link
Contributor

@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: 0

🔭 Outside diff range comments (1)
apps/mail/components/mail/reply-composer.tsx (1)

846-876: ⚠️ Potential issue

Potential mismatch when saving drafts.
For non-forward modes, line 854 enforces originalEmail.sender.email instead of the current form array for to. This risks losing additional recipients the user typed if they save the draft.

Proposed fix to store the actual recipient array in non-forward modes:

-        to: mode === 'forward' ? getValues('to').join(', ') : originalEmail.sender.email,
+        to: getValues('to').join(', '),

Ensure that the entire array of manually entered addresses is preserved in the draft.

🧹 Nitpick comments (6)
apps/mail/app/api/driver/google.ts (2)

189-191: Consider using structured logging in production

Added debug logs provide helpful information during development but could be noisy in production.

Consider using a logging level system to conditionally output these debug statements:

-console.log('Debug - From email:', fromEmail);
-console.log('Debug - Original to recipients:', JSON.stringify(to, null, 2));
+if (process.env.DEBUG_EMAIL === 'true') {
+  console.log('Debug - From email:', fromEmail);
+  console.log('Debug - Original to recipients:', JSON.stringify(to, null, 2));
+}

215-229: Consider reducing log verbosity for recipient processing

The recipient processing logs for each email address may generate excessive output in production.

Consider condensing the logs or making them conditional:

-console.log('Debug - Processing recipient:', {
-  originalEmail: recipient.email,
-  normalizedEmail: email,
-  fromEmail,
-  isDuplicate: uniqueRecipients.has(email),
-  isSelf: email === fromEmail
-});
+if (process.env.DEBUG_EMAIL === 'true') {
+  console.log('Debug - Processing recipient:', {
+    originalEmail: recipient.email,
+    normalizedEmail: email,
+    fromEmail,
+    isDuplicate: uniqueRecipients.has(email),
+    isSelf: email === fromEmail
+  });
+}
apps/mail/components/mail/reply-composer.tsx (4)

54-62: Consider expanding or externalizing the noreply check.
isNoReplyAddress currently only checks for a few patterns (e.g. noreply, no-reply, notifications@github.com). If you need more control or future-proofing, consider externalizing these checks or broadening them to align with project needs.


334-345: handleAttachment with drag-n-drop synergy.
Asynchronous file handling with a brief simulated wait is straightforward. Consider adding user feedback if a specific file fails to be attached or processed to improve the UX.


382-386: Email format check.
isValidEmail is a simple pattern-based validator. If advanced validation is ever required, consider more robust solutions or library usage.


752-815: RecipientInput components.
The logic to add emails on comma, Enter, or space is a convenient user experience. As a minor nitpick, consider whether adding an email on space might cause accidental additions. Otherwise, the approach is well-structured.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c2fe33 and 5b1f652.

📒 Files selected for processing (5)
  • apps/mail/app/api/driver/google.ts (4 hunks)
  • apps/mail/components/mail/reply-composer.tsx (18 hunks)
  • apps/mail/components/mail/thread-display.tsx (4 hunks)
  • apps/mail/components/mail/use-mail.ts (1 hunks)
  • apps/mail/types/index.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/mail/components/mail/thread-display.tsx (1)
apps/mail/lib/utils.ts (1)
  • cn (51-51)
apps/mail/components/mail/reply-composer.tsx (2)
apps/mail/types/index.ts (1)
  • Sender (32-35)
apps/mail/lib/utils.ts (1)
  • constructReplyBody (379-404)
🔇 Additional comments (42)
apps/mail/types/index.ts (1)

57-57: LGTM - Added optional replyTo field to ParsedMessage interface

The addition of the optional replyTo field aligns well with the extraction of the reply-to header implemented in the API driver.

apps/mail/components/mail/use-mail.ts (1)

9-9: LGTM - Added replyAllComposerOpen state

The addition of the replyAllComposerOpen boolean state properly extends the mail configuration model to support the new reply-all functionality. It's correctly initialized to false in the configAtom, maintaining consistency with the other composer states.

Also applies to: 17-17

apps/mail/components/mail/thread-display.tsx (5)

8-8: LGTM - Added ReplyAll icon import

The ReplyAll icon from lucide-react is properly imported to support the new reply-all functionality.


368-374: LGTM - Updated Reply button handler

The onClick handler for the Reply button now properly ensures that only the reply composer is open by setting replyComposerOpen to true while explicitly setting replyAllComposerOpen and forwardComposerOpen to false.


376-388: LGTM - Added ReplyAll button

The new ReplyAll button is correctly implemented with appropriate icon, translation label, and state management. The active state styling is properly applied using the cn utility when mail.replyAllComposerOpen is true.


396-401: LGTM - Updated Forward button handler

The Forward button handler now properly manages the state of all three composer types, ensuring only one composer is open at a time.


434-434: LGTM - Updated ReplyCompose mode logic

The mode passed to the ReplyCompose component now correctly handles the new replyAll state with proper precedence logic.

apps/mail/app/api/driver/google.ts (5)

136-137: LGTM - Added replyTo field extraction

The code now properly extracts the reply-to header from email messages and includes it in the parsed message data structure, which matches the updated interface.

Also applies to: 173-173


194-205: LGTM - Improved input validation

The added validation logic correctly ensures that the "to" field is a non-empty array before proceeding, improving error handling.


207-247: LGTM - Enhanced recipient handling

The implementation now properly handles recipients with robust filtering, deduplication using a Set, and appropriate error handling when no valid recipients remain after filtering.


249-289: LGTM - Added CC and BCC recipient handling

The code now properly processes CC and BCC recipients with appropriate filtering and deduplication logic, consistent with the handling of primary recipients.


299-310: LGTM - Improved header handling

The code now uses Object.entries() instead of Object.keys() for header processing, which is more appropriate as it provides access to both keys and values. The special handling for the References header ensures proper email threading.

apps/mail/components/mail/reply-composer.tsx (30)

4-10: Imports look good.
These imports from @/lib/utils consolidate needed utilities such as cleanEmailAddress and convertJSONToHTML without any apparent issues.


24-31: React hooks import.
The addition of useRef, useState, useEffect, useCallback, and useReducer is consistent with modern React patterns.


34-34: Using react-hook-form.
Leveraging useForm and useWatch is a solid approach for form state management.


37-38: Custom hooks usage.
useMail and useSettings are properly imported, no concerns here.


41-41: Thread hook import.
useThread fetches the email thread data. This is consistent with the rest of the codebase usage.


48-48: Toast library addition.
Importing toast from sonner is straightforward and used for user notifications.


49-49: Zod type reference.
Declaring a type import from zod suggests potential schema validations, though it does not appear used here.


82-87: Expanded MailState is clear.
Introducing replyComposerOpen, replyAllComposerOpen, and forwardComposerOpen ensures each composer mode is managed distinctly.


145-146: New mode option for replyAll.
Adding 'replyAll' to ReplyComposeProps is consistent with the rest of the logic in the file.


151-157: Extended form data structure.
Storing recipients in arrays for to, cc, bcc aligns with multi-address handling. toInput, ccInput, and bccInput keys help manage user input neatly.


167-169: State toggles for editing recipients.
isEditingRecipients, showCc, and showBcc provide flexible control over UI toggles without any apparent issues.


172-177: Conditional composer display.
Using mode to pick which composer is open is well-structured for managing different reply scenarios.


182-182: Selective composer open state.
Exclusively assigning replyAllComposerOpen fits the approach to toggling only the relevant composer.


208-217: Form initialization.
Default values for arrays and string inputs are clearly defined, which prevents undefined states in the form fields.


229-233: Watching to, cc, and bcc arrays.
Automatically tracking recipient changes is essential for dynamic UI updates and ensures re-renders happen as needed.


234-241: handleAddEmail function.
The trimming logic and duplication check look sound. Using isValidEmail helps maintain minimal validation.


243-328: handleSendEmail logic.
This function properly constructs to, cc, and bcc recipients, sets email subject lines, and calls sendEmail. The flow for reply, replyAll, and forward is coherent, and the error handling with toast user feedback is appropriate for a typical UI.


346-380: Drag events.
The dragOver, dragLeave, and drop handlers handle state updates to maintain correct UI feedback. Implementation is consistent.


387-403: CloseButton component.
Abstracting this logic is clean and consistent with the rest of the code. It neatly prevents accidental clicks through onMouseDown usage.


404-423: toggleComposer resets relevant states.
All composers are closed, and recipient states are reset, preventing leftover data from reuse.


467-476: Keyboard shortcut for send.
Supporting Cmd/Ctrl + Enter is a nice UX feature. Checking isFormValid is important to avoid empty sends.


478-480: Editor content update.
Storing editor content in form state using setValue ensures everything remains in sync with other inputs.


592-652: initializeRecipients for reply modes.
Conditionally populating to and cc for reply vs. replyAll is sound. Skipping BCC in replies is standard. The checks for not including the current user help avoid self-address duplication.


654-662: Auto-setup recipients on composer open.
Synchronizing form values with the latestEmail data upon opening the composer ensures the user sees correct default addresses.


663-748: renderHeaderContent approach.
Toggling between a compact view and expanded recipient editing is a solid pattern. Implementation for cc/bcc toggles is intuitive.


835-835: Form reset on composer close.
This reset() call keeps the form state clean when the composer is not in use.


880-965: Reply, replyAll, and forward buttons.
The logic for toggling each composer’s open state is well-organized. Checking participant counts before enabling “ReplyAll” is a practical approach.


983-983: onSubmit -> handleSubmit bridging.
Calling handleSubmit directly in a custom callback keeps the code consistent with react-hook-form best practices.


990-1021: Dynamic recipient controls in header.
Allowing the user to add cc/bcc on the fly is user-friendly. The ghost button style is a nice UI touch.


1183-1208: Save draft and send button.
Both actions handle enabling/disabling states properly. saveDraft is triggered via an explicit button, and sendEmail is triggered via the arrow button or shortcuts.

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.

2 participants