Skip to content

Comments

Autocompletions for reply and create#529

Merged
MrgSub merged 6 commits intostagingfrom
feat/autocomplete-sentences
Mar 30, 2025
Merged

Autocompletions for reply and create#529
MrgSub merged 6 commits intostagingfrom
feat/autocomplete-sentences

Conversation

@ahmetskilinc
Copy link
Contributor

@ahmetskilinc ahmetskilinc commented Mar 28, 2025

Summary by CodeRabbit

  • New Features

    • Added an autocomplete feature that provides context-aware text suggestions while editing emails.
    • Enhanced the editor to use personalized sender and user information for improved suggestion accuracy.
    • Upgraded the reply composer to leverage session data, offering a more tailored drafting experience.
    • Introduced a collection of predefined email phrases for openers, closers, and custom phrases to streamline email composition.
  • Style

    • Introduced animated ghost text suggestions with a shimmering effect, now optimized for dark mode.
    • Added styles for a suggestion panel and individual suggestion items to improve user experience.

@vercel
Copy link

vercel bot commented Mar 28, 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 Mar 29, 2025 10:11pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 28, 2025

Walkthrough

A new autocomplete feature has been added to the Mail app in the create module. The new editor-autocomplete.ts file introduces an AutoComplete extension using the Tiptap framework. It listens for the "Tab" key to trigger suggestions, which are filtered and inserted into the text with a shimmering effect defined in the new CSS file ghost-text.css. The Editor component now integrates this extension via updated props, and the reply-composer.tsx component uses session data through useSession to pass user information to the editor.

Changes

File(s) Change Summary
apps/mail/components/create/editor-autocomplete.ts New file: Implements an AutoComplete extension for Tiptap. Defines interfaces (SenderInfo, EmailSuggestions, AutoCompleteOptions) and adds logic in addProseMirrorPlugins to trigger text suggestions on "Tab" key press with decoration effects.
apps/mail/components/create/ghost-text.css New file: Adds CSS classes for .ghost-text-suggestion, .suggestion-panel, and .suggestion-item, including styles for dark mode and a slideIn animation for the suggestion panel.
apps/mail/components/create/editor.tsx, apps/mail/components/mail/reply-composer.tsx Updated: The Editor component now imports and integrates the AutoComplete extension and updates its props (myInfo, senderInfo). The reply-composer.tsx file retrieves session data using useSession to supply user information to the editor.
apps/mail/components/create/email-phrases.ts New file: Defines an interface EmailPhrases and a constant emailPhrases for managing predefined email phrases (openers, closers, custom).

Possibly related PRs

  • Improved ai with custom prompt #534: The changes in the main PR are related to the modifications in the retrieved PR as both involve enhancements to the Editor component, specifically integrating new properties and functionalities that improve user interaction and suggestion handling.
  • reply ai #526: The changes in the main PR introduce a new AutoComplete extension in editor-autocomplete.ts, while the retrieved PR modifies the Editor component in editor.tsx by integrating the AutoComplete extension, indicating a direct relationship between the two.

Suggested reviewers

  • MrgSub
  • nizzyabi

Poem

I hop through lines of code so bright,
Bringing suggestions to life in flight.
With each Tab press, a hint appears,
Shimmering softly, allaying fears.
A rabbit's cheer in digital delight!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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

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

🧹 Nitpick comments (1)
apps/mail/components/create/editor-autocomplete.ts (1)

27-70: Clean implementation of suggestion matching logic

The suggestion matching function correctly handles empty inputs, incorporates personalized suggestions based on sender/user info, and properly filters and sorts the suggestions.

However, there's an unnecessary console.log statement that should be removed.

-          console.log(name);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 76cf73a and f9d480a.

📒 Files selected for processing (4)
  • apps/mail/components/create/editor-autocomplete.ts (1 hunks)
  • apps/mail/components/create/editor.tsx (4 hunks)
  • apps/mail/components/create/ghost-text.css (1 hunks)
  • apps/mail/components/mail/reply-composer.tsx (4 hunks)
🔇 Additional comments (9)
apps/mail/components/create/ghost-text.css (1)

1-39: Well-implemented shimmer effect with proper dark mode support

The CSS implementation for the ghost text suggestion provides an elegant shimmer effect with proper dark mode support. The animation timing and gradient values create a subtle but noticeable effect that should enhance the user experience.

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

16-16: Good addition of session management

Adding the useSession hook is appropriate for retrieving user information needed by the autocomplete feature.


32-32: Correctly extracts session data

The session data extraction follows best practices using object destructuring.


292-316: Well-structured integration of user data to the Editor component

The component now correctly passes both the user's information (from session) and sender's information (from email data) to the Editor component, enabling personalized autocomplete suggestions.

apps/mail/components/create/editor.tsx (3)

47-47: Appropriate import of the new AutoComplete extension

The AutoComplete import is correctly added to integrate with the existing editor functionality.


75-82: Well-defined interface extensions

The EditorProps interface has been properly extended with optional properties that maintain backward compatibility.


501-532: Comprehensive autocomplete configuration

The AutoComplete extension is configured with a rich set of text suggestions, categorized into openers, closers, and custom phrases. The integration with user and sender information enables personalized suggestions.

apps/mail/components/create/editor-autocomplete.ts (2)

1-19: Well-structured interfaces and proper imports

The interfaces and imports are organized clearly, with appropriate typing for the extension options.


72-144: Robust ProseMirror plugin implementation

The plugin implementation correctly:

  1. Handles Tab key events to trigger suggestions
  2. Extracts current line text for context
  3. Prevents default Tab behavior when suggestions are available
  4. Creates decorations with the shimmer effect for visual feedback

The error handling is thorough, with appropriate checks before attempting to process suggestions.

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: 3

🧹 Nitpick comments (5)
apps/mail/components/create/ghost-text.css (2)

7-18: Consider using CSS variables for colors and sizing.

The suggestion panel styling looks good, but consider using CSS variables for colors, borders, and sizing values for improved maintainability and easier theming.

+:root {
+  --suggestion-bg: white;
+  --suggestion-border: #e0e0e0;
+  --suggestion-shadow: rgba(0, 0, 0, 0.1);
+  --suggestion-max-height: 200px;
+  --suggestion-min-width: 200px;
+}

.suggestion-panel {
  position: absolute;
-  background: white;
-  border: 1px solid #e0e0e0;
+  background: var(--suggestion-bg);
+  border: 1px solid var(--suggestion-border);
  border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
-  max-height: 200px;
+  box-shadow: 0 2px 8px var(--suggestion-shadow);
+  max-height: var(--suggestion-max-height);
  overflow-y: auto;
  z-index: 1000;
  margin-top: 4px;
-  min-width: 200px;
+  min-width: var(--suggestion-min-width);
}

58-75: Add cross-browser scrollbar compatibility.

The scrollbar styling looks great for WebKit browsers (Chrome, Safari), but consider adding Firefox and standard scrollbar properties for cross-browser compatibility.

/* Add scrollbar styling */
.suggestion-panel::-webkit-scrollbar {
  width: 8px;
}

.suggestion-panel::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.suggestion-panel::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 4px;
}

.suggestion-panel::-webkit-scrollbar-thumb:hover {
  background: #555;
}

+/* Firefox scrollbar */
+.suggestion-panel {
+  scrollbar-width: thin;
+  scrollbar-color: #888 #f1f1f1;
+}
apps/mail/components/create/editor-autocomplete.ts (3)

175-184: Add event listeners and cleanup for suggestion items.

The suggestion panel creates DOM elements but doesn't attach click event listeners. Also, there's no cleanup mechanism which could lead to memory leaks.

// Create suggestion panel
const panel = document.createElement('div');
panel.className = 'suggestion-panel';

suggestions.forEach((suggestion, index) => {
  const item = document.createElement('div');
  item.className = `suggestion-item ${index === selectedIndex ? 'selected' : ''}`;
  item.textContent = suggestion.text;
+  // Add click handler for mouse selection
+  item.addEventListener('click', () => {
+    const tr = state.tr.insertText(suggestion.text.slice(currentLine.length), pos);
+    view.dispatch(tr);
+  });
  panel.appendChild(item);
});

190-195: Add ARIA attributes for better accessibility.

The ghost text suggestion should include ARIA attributes to ensure screen readers can properly interpret it.

const span = document.createElement('span');
span.textContent = remainingText;
span.className = 'ghost-text-suggestion';
+ span.setAttribute('aria-hidden', 'true');
+ span.setAttribute('role', 'presentation');
return span;

144-156: Add support for Escape key to dismiss suggestions.

The code handles Tab and Enter for selection, but doesn't provide a way to dismiss suggestions without selecting any.

// Handle selection
- if (event.key === 'Tab' || event.key === 'Enter') {
+ if (event.key === 'Escape') {
+   event.preventDefault();
+   // Clear suggestions by forcing a re-render
+   view.dispatch(view.state.tr);
+   return true;
+ } else if (event.key === 'Tab' || event.key === 'Enter') {
  event.preventDefault();
  const suggestion = suggestions[selectedIndex];
  if (!suggestion) return false;

  const remainingText = suggestion.text.slice(currentLine.length);
  if (!remainingText) return false;

  view.dispatch(view.state.tr.insertText(remainingText, pos));
  selectedIndex = 0;
  return true;
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f9d480a and 9c799ab.

📒 Files selected for processing (4)
  • apps/mail/components/create/editor-autocomplete.ts (1 hunks)
  • apps/mail/components/create/editor.tsx (4 hunks)
  • apps/mail/components/create/ghost-text.css (1 hunks)
  • apps/mail/components/mail/reply-composer.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/mail/components/mail/reply-composer.tsx
  • apps/mail/components/create/editor.tsx
🔇 Additional comments (3)
apps/mail/components/create/ghost-text.css (2)

1-5: Well-designed ghost text styling.

The ghost text styling has good opacity, non-intrusive coloring, and correctly uses pointer-events: none to ensure it doesn't interfere with user interaction.


77-91: Excellent dark mode implementation.

The dark mode styling with gradient effect is well-implemented and properly uses -webkit-background-clip with the standard background-clip property for compatibility.

apps/mail/components/create/editor-autocomplete.ts (1)

29-48: Well-implemented fuzzy matching algorithm.

The fuzzy matching function is efficiently implemented with appropriate scoring for exact matches, prefix matches, and character-by-character matching. The normalization of the score by pattern length is a good approach.

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

🧹 Nitpick comments (2)
apps/mail/components/create/editor-autocomplete.ts (2)

149-152: Clarify complex boolean logic with parentheses.

The mix of && and || operators without clear grouping makes the code hard to understand and potentially error-prone.

Apply this fix:

return matchesCurrentText && 
       !isAlreadyUsed && 
-      (!isInMiddleOfEmail || !suggestion.includes('Hello') && !suggestion.includes('Hi') && !suggestion.includes('Dear')) &&
+      (!isInMiddleOfEmail || !(suggestion.includes('Hello') || suggestion.includes('Hi') || suggestion.includes('Dear'))) &&
       !isSimilarGreetingUsed;

38-40: Consider resetting usedSuggestions when appropriate.

The usedSuggestions Set persists for the lifetime of the extension, which could lead to unexpected behavior if the editor is used for multiple emails.

Consider adding a method to reset this Set when a new email is started or when the editor content is cleared. This would prevent suggestions from being inappropriately filtered out across different emails.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9c799ab and fb4d84e.

📒 Files selected for processing (1)
  • apps/mail/components/create/editor-autocomplete.ts (1 hunks)
🔇 Additional comments (6)
apps/mail/components/create/editor-autocomplete.ts (6)

52-57: Don't directly modify input parameters.

The function is directly modifying properties of the input parameter opts, which can cause unexpected side effects if the same options object is reused elsewhere. Instead, create local copies of the arrays.

Apply this fix:

- opts.suggestions.timeBased = [
-   `Good ${timeOfDay} ${name},`,
-   `I hope you're having a good ${timeOfDay} ${name},`,
-   `Wishing you a wonderful ${timeOfDay} ${name},`,
- ];
+ const timeBased = [
+   `Good ${timeOfDay} ${name},`,
+   `I hope you're having a good ${timeOfDay} ${name},`,
+   `Wishing you a wonderful ${timeOfDay} ${name},`,
+ ];

62-67: Don't directly modify input parameters.

Similar to the previous issue, this code is directly modifying properties of the input parameter.

Apply this fix:

- opts.suggestions.contextBased = [
-   `Thank you for your email regarding ${lastEmail}.`,
-   `I received your message about ${lastEmail}.`,
-   `I understand your point about ${lastEmail}.`,
- ];
+ const contextBased = [
+   `Thank you for your email regarding ${lastEmail}.`,
+   `I received your message about ${lastEmail}.`,
+   `I understand your point about ${lastEmail}.`,
+ ];

70-81: Don't directly modify input parameters.

The function is directly modifying the commonPhrases property of the input parameter.

Apply this fix:

- opts.suggestions.commonPhrases = [
+ const commonPhrases = [
  `I hope this email finds you well.`,
  `I wanted to follow up on our previous conversation.`,
  `I'm writing to discuss...`,
  `I would like to schedule a meeting to discuss...`,
  `Please let me know if you have any questions.`,
  `I look forward to your response.`,
  `I appreciate your time and consideration.`,
  `I'm happy to help with anything else you need.`,
  `Please don't hesitate to reach out if you need any clarification.`,
  `I'll be in touch soon.`,
];

83-99: Don't directly modify input parameters.

The function is still directly modifying the input parameter by pushing to opts.suggestions.openers. This doesn't address the previous review comments that suggested creating copies of arrays.

Apply this fix:

- if (opts.sender) {
-   const { name } = opts.sender;
-   if (name) {
-     opts.suggestions.openers?.push(
-       `Hello ${name},`,
-       `Hi ${name},`,
-       `Dear ${name},`,
-       `Good morning ${name},`,
-       `Good afternoon ${name},`,
-       `Good evening ${name},`,
-       `I hope you're doing well ${name},`,
-       `I trust this email finds you well ${name},`,
-       `I hope you're having a great day ${name},`,
-     );
-   }
- }
+ // Create a copy of openers array
+ let openers = [...(opts.suggestions.openers || [])];
+ if (opts.sender?.name) {
+   const { name } = opts.sender;
+   openers = [
+     ...openers,
+     `Hello ${name},`,
+     `Hi ${name},`,
+     `Dear ${name},`,
+     `Good morning ${name},`,
+     `Good afternoon ${name},`,
+     `Good evening ${name},`,
+     `I hope you're doing well ${name},`,
+     `I trust this email finds you well ${name},`,
+     `I hope you're having a great day ${name},`,
+   ];
+ }

101-118: Don't directly modify input parameters.

The function is still directly modifying the input parameter by pushing to opts.suggestions.closers. This doesn't address the previous review comments that suggested creating copies of arrays.

Apply this fix:

- if (opts.myInfo) {
-   const { name } = opts.myInfo;
-   if (name) {
-     opts.suggestions.closers?.push(
-       `Best regards,\n${name}`,
-       `Kind regards,\n${name}`,
-       `Sincerely,\n${name}`,
-       `Thanks,\n${name}`,
-       `Best wishes,\n${name}`,
-       `Warm regards,\n${name}`,
-       `Cheers,\n${name}`,
-       `Take care,\n${name}`,
-       `Looking forward to your response,\n${name}`,
-       `I look forward to hearing from you,\n${name}`,
-     );
-   }
- }
+ // Create a copy of closers array
+ let closers = [...(opts.suggestions.closers || [])];
+ if (opts.myInfo?.name) {
+   const { name } = opts.myInfo;
+   closers = [
+     ...closers,
+     `Best regards,\n${name}`,
+     `Kind regards,\n${name}`,
+     `Sincerely,\n${name}`,
+     `Thanks,\n${name}`,
+     `Best wishes,\n${name}`,
+     `Warm regards,\n${name}`,
+     `Cheers,\n${name}`,
+     `Take care,\n${name}`,
+     `Looking forward to your response,\n${name}`,
+     `I look forward to hearing from you,\n${name}`,
+   ];
+ }

120-127: Update the allSuggestions array to use the copied arrays.

After implementing the previous fixes to create copies of arrays, you need to update this section to use those copied arrays.

Apply this fix:

const allSuggestions = [
-   ...(opts.suggestions.openers || []),
-   ...(opts.suggestions.closers || []),
-   ...(opts.suggestions.custom || []),
-   ...(opts.suggestions.commonPhrases || []),
-   ...(opts.suggestions.timeBased || []),
-   ...(opts.suggestions.contextBased || []),
+   ...openers,
+   ...closers,
+   ...(opts.suggestions.custom || []),
+   ...commonPhrases,
+   ...(timeBased || []),
+   ...(contextBased || []),
];

- added delay of 2 matching characters
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: 1

🧹 Nitpick comments (1)
apps/mail/components/create/editor-autocomplete.ts (1)

213-214: Consider addressing the TypeScript type incompatibility.

The @ts-expect-error comment suggests there's a type compatibility issue between Tiptap and ProseMirror. While the current approach works, it would be better to find a more type-safe solution if possible.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fb4d84e and fea94e9.

📒 Files selected for processing (2)
  • apps/mail/components/create/editor-autocomplete.ts (1 hunks)
  • apps/mail/components/create/email-phrases.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/mail/components/create/email-phrases.ts
🧰 Additional context used
🧬 Code Definitions (1)
apps/mail/components/create/editor-autocomplete.ts (1)
apps/mail/components/create/email-phrases.ts (1)
  • emailPhrases (7-74)
🪛 Biome (1.9.4)
apps/mail/components/create/editor-autocomplete.ts

[error] 211-211: This code is unreachable

... because either this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (10)
apps/mail/components/create/editor-autocomplete.ts (10)

8-11: Nice use of clear interface definitions.

The SenderInfo interface is well structured and provides good optional fields for name and email, making it flexible for different use cases.


13-20: Good organization of email suggestion categories.

The EmailSuggestions interface provides a comprehensive categorization of different types of email phrases, which enables rich contextual suggestions.


22-32: Well-designed options interface with contextual information.

The AutoCompleteOptions interface elegantly combines suggestions, sender information, and contextual data to create personalized autocomplete suggestions.


85-98: Avoid modifying input parameters and consider graceful handling of missing arrays.

The code correctly customizes openers with the sender's name but creates a new array for the opts.suggestions.openers property instead of modifying it.


100-116: Avoid directly modifying input parameters.

The function modifies the input parameter opts.suggestions.closers by pushing new items to it, which could cause unexpected side effects if the same options object is reused. Consider creating a copy of the array instead.

- if (opts.myInfo) {
-   const { name } = opts.myInfo;
-   if (name) {
-     opts.suggestions.closers?.push(
-       `Best regards,\n${name}`,
-       `Kind regards,\n${name}`,
-       `Sincerely,\n${name}`,
-       `Thanks,\n${name}`,
-       `Best wishes,\n${name}`,
-       `Warm regards,\n${name}`,
-       `Cheers,\n${name}`,
-       `Take care,\n${name}`,
-       `Looking forward to your response,\n${name}`,
-       `I look forward to hearing from you,\n${name}`,
-     );
-   }
- }

+ let closers = [...(opts.suggestions.closers || [])];
+ if (opts.myInfo?.name) {
+   closers = [
+     ...closers,
+     `Best regards,\n${opts.myInfo.name}`,
+     `Kind regards,\n${opts.myInfo.name}`,
+     `Sincerely,\n${opts.myInfo.name}`,
+     `Thanks,\n${opts.myInfo.name}`,
+     `Best wishes,\n${opts.myInfo.name}`,
+     `Warm regards,\n${opts.myInfo.name}`,
+     `Cheers,\n${opts.myInfo.name}`,
+     `Take care,\n${opts.myInfo.name}`,
+     `Looking forward to your response,\n${opts.myInfo.name}`,
+     `I look forward to hearing from you,\n${opts.myInfo.name}`,
+   ];
+ }

118-126: Update the allSuggestions array to use the copied arrays.

After implementing the previous suggestion, you'll need to update this section to use the copied closers array.


127-160: The suggestion filtering algorithm is well-implemented.

The logic checks for:

  1. Text matching with the current input
  2. Not already used suggestions
  3. Context-appropriate suggestions (avoiding greetings in the middle of an email)
  4. Avoiding similar greetings

The sorting prioritizes exact matches and shorter suggestions first, which is a good UX choice.


169-184: Good validation of selection state before attempting to process suggestions.

The code properly checks for valid cursor positions and text selection before proceeding, which prevents potential runtime errors.


196-209: Well-implemented error handling for suggestion application.

The try-catch block ensures that any errors during suggestion application are caught and logged, preventing the entire editor from crashing.


241-250: Nice implementation of the ghost text suggestion UI.

The decoration widget implementation creates a subtle and effective visual cue for the available suggestion, and the CSS class allows for styling the shimmering effect defined in the imported CSS file.

return false;
}

return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unreachable code.

This return statement is unreachable as all code paths above it either return true or false.

-            return true;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return true;
// ... (previous code remains unchanged)
// Unreachable return statement removed
// ... (subsequent code remains unchanged)
🧰 Tools
🪛 Biome (1.9.4)

[error] 211-211: This code is unreachable

... because either this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... this statement, ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

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

🧹 Nitpick comments (2)
apps/mail/components/create/editor.tsx (1)

506-537: Well-organized autocomplete configuration.

The AutoComplete extension is properly configured with categorized suggestions for email openers, closers, and custom phrases. The implementation correctly passes user and sender context to enable personalized suggestions.

The predefined suggestions provide a good starting point, but consider expanding these over time based on user feedback.

Consider extracting these predefined phrase arrays into a separate configuration file to make them easier to maintain and update in the future. This would also allow for localization if needed.

-extensions={[
-  ...defaultExtensions,
-  Markdown,
-  AutoComplete.configure({
-    suggestions: {
-      openers: [
-        'Hi there,',
-        'Hello,',
-        'Dear',
-        'Greetings,',
-        'Good morning,',
-        'Good afternoon,',
-        'Good evening,',
-      ],
-      closers: [
-        'Best regards,',
-        'Kind regards,',
-        'Sincerely,',
-        'Thanks,',
-        'Thank you,',
-        'Cheers,',
-      ],
-      custom: [
-        'I hope this email finds you well.',
-        'I look forward to hearing from you.',
-        'Please let me know if you have any questions.',
-      ],
-    },
-    sender: senderInfo,
-    myInfo: myInfo,
-  }),
-]}
+import { emailSuggestions } from './email-suggestions';
+
+extensions={[
+  ...defaultExtensions,
+  Markdown,
+  AutoComplete.configure({
+    suggestions: emailSuggestions,
+    sender: senderInfo,
+    myInfo: myInfo,
+  }),
+]}
apps/mail/components/mail/reply-composer.tsx (1)

507-514: Properly passing user and sender context to Editor.

The implementation correctly passes the user's information and the email sender's information to the Editor component, enabling personalized autocomplete suggestions.

The optional chaining (?.) is used appropriately to handle potential undefined values.

Consider adding a comment to explain the purpose of passing these props to enhance code readability:

+// Pass user and sender information to enable personalized autocomplete suggestions
myInfo={{
  name: session?.user.name,
  email: session?.user.email,
}}
senderInfo={{
  name: emailData[0]?.sender?.name,
  email: emailData[0]?.sender?.email,
}}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f35a215 and 0acebde.

📒 Files selected for processing (2)
  • apps/mail/components/create/editor.tsx (5 hunks)
  • apps/mail/components/mail/reply-composer.tsx (3 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
apps/mail/components/create/editor.tsx (1)
apps/mail/components/create/editor-autocomplete.ts (1)
  • AutoComplete (34-255)
apps/mail/components/mail/reply-composer.tsx (1)
packages/db/src/schema.ts (1)
  • session (18-29)
🔇 Additional comments (5)
apps/mail/components/create/editor.tsx (3)

47-47: New autocomplete feature added.

This import adds the autocomplete functionality required for the enhanced editor experience.


75-82: Clear and well-structured interface extension.

The EditorProps interface has been properly extended to include optional user and sender information fields. This provides the necessary context for the autocomplete functionality to generate personalized suggestions.


390-391: Props correctly added to function parameters.

The new props are correctly added to the Editor function parameters, matching the interface changes defined above.

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

3-10: Good import organization.

The import section is well-structured. The addition of useSession from the auth-client library is appropriate for accessing user session data.

Also applies to: 18-18


107-107: Added session data retrieval.

Correctly implementing user session data retrieval using the useSession hook from the auth-client library.

@MrgSub MrgSub merged commit 04c2793 into staging Mar 30, 2025
5 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Apr 10, 2025
@ahmetskilinc ahmetskilinc deleted the feat/autocomplete-sentences branch April 26, 2025 14:38
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.

3 participants