Skip to content

new create email tabs#1737

Closed
ahmetskilinc wants to merge 16 commits intostagingfrom
07-15-new_create_email_tabs
Closed

new create email tabs#1737
ahmetskilinc wants to merge 16 commits intostagingfrom
07-15-new_create_email_tabs

Conversation

@ahmetskilinc
Copy link
Contributor

@ahmetskilinc ahmetskilinc commented Jul 15, 2025

ready to be merged

Summary by CodeRabbit

  • New Features

    • Introduced a multi-tab email compose interface, allowing users to open, switch, minimize, and fullscreen multiple compose windows on both desktop and mobile.
    • Compose tabs persist state, including drafts, recipients, and attachments, across sessions.
  • Improvements

    • Enhanced draft saving with visual feedback and more frequent auto-save.
    • Optimized email composer performance and reduced unnecessary re-renders.
    • Updated compose and reply UI for better responsiveness and usability.
    • Improved toolbar and button styling for a more consistent appearance.
    • Compose actions (sidebar button, hotkeys, command palette, and draft clicks) now open new compose tabs.
  • Bug Fixes

    • Fixed inconsistencies in compose state management when opening drafts or new emails.
  • Refactor

    • Removed the previous modal-based compose email route and related logic.
    • Streamlined state management using a new tab-based approach.
  • Style

    • Updated button and icon sizes, colors, and layout for a cleaner look.
    • Improved visual feedback for draft saving and toolbar actions.
  • Chores

    • Reorganized imports and cleaned up formatting for consistency.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 15, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto incremental reviews are disabled on this repository.

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 change removes the legacy single compose page and its route, replacing it with a new multi-tabbed compose system managed by Jotai atoms. Compose tabs now support advanced state management, draft handling, and responsive UI, with all compose triggers updated to use the new tab-based approach.

Changes

Cohort / File(s) Change Summary
Legacy Compose Page Removal
apps/mail/app/(routes)/mail/compose/page.tsx, apps/mail/app/routes.ts
Removes the old /mail/compose route and its page, including session validation, query param extraction, and modal compose UI.
Compose Tab State Management
apps/mail/store/composeTabsStore.ts
Introduces a state management module using Jotai atoms for compose tabs, including tab creation, removal, updating, minimizing, fullscreen, and mobile switching. Atoms persist tab state and synchronize UI across desktop and mobile.
Multi-Tab Compose UI
apps/mail/components/create/compose-tabs.tsx
Adds a comprehensive ComposeTabs component for managing multiple compose tabs, with responsive design, tab switching, minimize/fullscreen, draft loading, email sending, and animated UI transitions for both desktop and mobile.
Compose Triggers Refactored
apps/mail/components/context/command-palette-context.tsx, apps/mail/components/mail/mail-list.tsx, apps/mail/components/mail/thread-display.tsx, apps/mail/components/ui/app-sidebar.tsx, apps/mail/lib/hotkeys/global-hotkeys.tsx
Refactors all compose triggers (command palette, mail list, thread display, sidebar button, global hotkey) to use the new Jotai atom-based compose tab system instead of query state or modal dialogs.
Compose Integration in Layout
apps/mail/components/mail/mail.tsx
Integrates the new ComposeTabs component into the main mail layout, adjusts panel overflow handling for compatibility with floating compose tabs.
Email Composer Refactor
apps/mail/components/create/email-composer.tsx
Refactors EmailComposer to support external draft state, add memoization, improve draft saving UX, and adapt to tabbed/fullscreen contexts. Adds new props for tab integration and synchronizes draft state with parent.
UI/Styling Adjustments
apps/mail/components/ai-toggle-button.tsx, apps/mail/components/create/schedule-send-picker.tsx, apps/mail/components/create/template-button.tsx, apps/mail/components/create/toolbar.tsx, apps/mail/components/icons/icons.tsx, apps/mail/components/mail/reply-composer.tsx
Applies minor UI and styling tweaks to buttons, toolbars, icons, and reply composer for consistency with the new compose tab system. No functional changes.
Compose Editor Hook
apps/mail/hooks/use-compose-editor.ts
Updates the onUpdate callback to clarify and reorder handler invocations, ensuring length change is handled before content change, with new comments for clarity.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI_Trigger as Compose Trigger (Sidebar, Hotkey, etc.)
    participant ComposeTabs
    participant ComposeTab
    participant Store as ComposeTabsStore (Jotai Atoms)
    participant EmailComposer

    User->>UI_Trigger: Click "Compose" / Press hotkey / Open draft
    UI_Trigger->>Store: addComposeTabAtom({ prefillData? })
    Store->>ComposeTabs: Update composeTabsAtom, set active tab
    ComposeTabs->>ComposeTab: Render new tab UI
    ComposeTab->>EmailComposer: Pass draftId, initial values
    EmailComposer->>Store: onChange, onDraftCreated, updateComposeTabAtom
    User->>EmailComposer: Edit, Save, Send
    EmailComposer->>Store: updateComposeTabAtom / removeComposeTabAtom (on send/close)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Suggested labels

design

Suggested reviewers

  • MrgSub

Poem

Compose takes flight, no longer one,
Tabs for all—now email’s fun!
Atoms manage every state,
Drafts and sends coordinate.
Minimize, maximize, full-screen too,
Multi-tabbed dreams coming true.
🚀 Inbox zero, here we come!

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 07-15-new_create_email_tabs

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch 3 times, most recently from 5753133 to 766001e Compare July 23, 2025 10:58
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 23, 2025

Bug Report

Name Severity Example test case Description
Attachment data loss Critical 1. Create a new email in a tab. 2. Add an attachment to the email. 3. Reload the page. Attachment data is not correctly persisted in local storage, leading to data loss when the page is reloaded.

Comments? Email us. Your free trial ends in 6 days.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from 766001e to b2c2f45 Compare July 23, 2025 13:53
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 23, 2025

Bug Report

Name Severity Example test case Description
Local Storage Quota Exceeded Medium Create many compose tabs, each with a large email body and attachments. Exceeding local storage quota can crash the application.
Race Condition on Tab ID Low Rapidly click the "new tab" button multiple times. Two tabs could be created with the same ID.
Data Loss on Tab Close Low Create a new tab, enter some text, and then force-close the browser. Unsaved changes will be lost if the user bypasses the confirmation dialog.
Inconsistent focus behavior Low Open two new compose tabs. Minimize one, and then fullscreen the other. Then click inside the minimized tab. Focus may not be in the expected tab when switching between minimized and fullscreen tabs.
Attachment Handling Medium Upload a file with a malicious filename. Improper sanitization in serializeFiles could lead to vulnerabilities.

Comments? Email us. Your free trial ends in 6 days.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 23, 2025

Bug Report

Name Severity Example test case Description
Attachments not persisted High Open a new compose tab, add an attachment, close the browser, reopen the browser The ComposeTab interface includes a File[] for attachments, which cannot be serialized to JSON for storage in localStorage. This leads to attachments being lost when the tab is persisted.

Comments? Email us. Your free trial ends in 6 days.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from 10cd6c3 to 41cd954 Compare July 24, 2025 15:28
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 24, 2025

Bug Report

Name Severity Example test case Description
Whitespace Changes Not Auto-Saved Low Add whitespace to the email body and close the tab before auto-save Whitespace changes are not considered as content changes, leading to potential formatting loss if the user relies on auto-save.

Comments? Email us. Your free trial ends in 5 days.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 25, 2025

Bug Report

Name Severity Example test case Description
AutoSave Timer Optimization Low Open a compose tab and leave it untouched for a long time. The saveDraft() function is called repeatedly even if the content hasn't changed, wasting resources.
Draft Saving Inconsistency Medium Compose an email and save it. Then open the same email again through a draft link. Make changes to the subject of the new email and see if it saves correctly. There are two ways a draftId is handled. One through useQueryState and another through propDraftId. When there is a propDraftId being passed to the component, the draftId from the query state should be ignored completely.
Local Storage getItem catch block Low Cause JSON.parse to fail in the getItem of composeTabsAtom getItem function has a catch block with no logging or error handling and could cause an infinite loop or other problems if JSON.parse fails.

Comments? Email us. Your free trial ends in 4 days.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from df6d938 to cf6ba88 Compare July 31, 2025 13:01
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 31, 2025

Bug Report

Name Severity Example test case Description
Race condition in autosaving logic Medium 1. Open a new compose tab. 2. Type some text into the email body. 3. Simulate a network interruption. 4. Type some more text. 5. Wait for autosave. 6. Re-enable network. 7. Observe data loss. The autosaving logic in EmailComposer.tsx is racy. Can lead to data loss or repeated failed save attempts. There should be logic to prevent the auto-save function from running if there is a current save operation that has not yet completed.

Comments? Email us.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from cf6ba88 to b55b2e2 Compare August 4, 2025 01:47
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 4, 2025

Bug Report

Name: Race condition in mobile tab switching

Severity: Medium

Example test case:

  1. Open multiple compose tabs on a mobile device.
  2. Rapidly switch between the tabs using the tab switcher.
  3. Observe the UI for visual glitches and check the state of the compose tabs.

Description:
The switchMobileTabAtom in apps/mail/store/composeTabsStore.ts has a race condition where the un-minimization of the target tab can occur before the minimization of the current tab is fully processed. This can lead to visual glitches and an inconsistent state in the composeTabsAtom.

Comments? Email us.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from b55b2e2 to ffca82e Compare August 6, 2025 16:12
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 6, 2025

Bug Report

Name Severity Example test case Description
Incorrect tab selection after closing a tab on mobile Medium 1. Open two compose tabs on mobile. 2. Expand the first tab. 3. Close the first tab. When a non-minimized compose tab is closed on mobile, the logic for selecting the next active tab incorrectly prioritizes minimized tabs. This can lead to a confusing user experience, as the user might expect the next tab to be open instead of a minimized tab.

Comments? Email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 6, 2025

Bug Report

Name Severity Example test case Description
Draft Saving Race Condition Low Make rapid edits to email content. The auto-save timer may fire before hasUnsavedChanges is set, preventing a draft from being saved.
Inconsistent Draft Saving Medium Edit an email and then revert back to the original initialMessage. Drafts are not saved because changes will not be detected after reverting to initial state.
Auto Save Restriction High Setting only subject without recipients or message body prevents draft from saving. The condition `(!values.to.length
Excessive Re-renders Low Continuously type in the editor or modify form fields. Although the onChange callback is debounced, the component still re-renders synchronously on each change due to setHasUnsavedChanges(true), potentially causing performance issues.

Comments? Email us.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 7, 2025

This PR has merge conflicts and has been open for more than 3 days. It will be automatically closed. Please resolve the conflicts and reopen the PR if you'd like to continue working on it.

@github-actions github-actions bot closed this Aug 7, 2025
@ahmetskilinc ahmetskilinc reopened this Aug 7, 2025
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 7, 2025

Bug Report

Name Severity Example test case Description
Incorrect tab activation after deleting active tab on mobile Medium 1. Enable mobile view. 2. Open two compose tabs. 3. Minimize the non-active tab. 4. Select the un-minimized active tab. 5. Delete it. 6. Observe that a tab is activated but not un-minimized. After the active tab is deleted the mobile tab selection logic fails to un-minimize the final tab.

Comments? Email us.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from f3af371 to 1958e9e Compare August 7, 2025 15:50
@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 7, 2025

Bug Report

Name Severity Example test case Description
Memory Leak in Compose Tabs Medium 1. Open and close multiple compose tabs repeatedly. 2. Monitor memory usage of the application. Timers for autosaving drafts in EmailComposerBase are not cleared when a compose tab is closed using removeComposeTabAtom, leading to potential memory leaks.

Comments? Email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Aug 8, 2025

Bug Report

Name Severity Example test case Description
Mobile tab replacement with data loss High 1. On mobile, start composing an email (filling To, Subject or Body). 2. Open a new compose tab. The existing compose tab is overwritten, leading to data loss. This occurs because the addComposeTabAtom logic on mobile doesn't consider the case where an existing tab has data.
Removing last minimized tab on Mobile leaves empty bottom sheet Medium 1. On mobile, create a compose tab. 2. Minimize the compose tab. 3. Remove the minimized compose tab. Removing the last minimized compose tab on mobile view can leave the bottom sheet visible despite their being no active tab.

Comments? Email us.

@ahmetskilinc ahmetskilinc marked this pull request as ready for review August 10, 2025 12:00
@coderabbitai coderabbitai bot requested a review from MrgSub August 10, 2025 12:01
@coderabbitai coderabbitai bot added the design Improvements & changes to design & UX label Aug 10, 2025
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic analysis

10 issues found across 17 files • Review in cubic

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch 2 times, most recently from 1851f25 to ae52380 Compare August 10, 2025 21:13
@ahmetskilinc ahmetskilinc force-pushed the 07-15-new_create_email_tabs branch from ae52380 to a512018 Compare August 11, 2025 17:18
@ahmetskilinc ahmetskilinc added the Ready This label is used when a PR is ready to be merged. label Aug 13, 2025
@ahmetskilinc
Copy link
Contributor Author

closing. will be ported.

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

Labels

design Improvements & changes to design & UX Ready This label is used when a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants