-
Notifications
You must be signed in to change notification settings - Fork 12.1k
chore: Preview composer gsoc #36736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
chore: Preview composer gsoc #36736
Conversation
- Replaced the `ComposerMessageInput`'s underlying `<textarea>` with a `<div contenteditable>`. - Currently, this implementation is non-functional beyond accepting plain text input. - Placeholder support is currently not working due to limitations with `contenteditable`. - Further work is needed to restore full functionality, including keyboard event handling, Markdown formatting, and cursor management. - Clipboard paste and file attachments continue to work as expected. - Updated Storybook stories to include `MessageComposerInputNew` for preview and testing. - Refactored existing stories and exports for clarity and compatibility with the new input component.
- Cloned `CreateComposerAPI.ts` as `newCreateComposerAPI.ts` and updated references from `HTMLTextAreaElement` to `HTMLDivElement`. - Implemented `getSelectionRange` and `setSelectionRange` using the Selection API to replace `input.selectionStart` and `input.selectionEnd`. - Fixed Enter key functionality, allowing messages to be sent as expected. - Restored Bold, Italics, and Strikethrough button functionality, confirming successful Selection API migration. Known Issues & Next Steps - Enabled `/` key to trigger the slash command menu, but pressing Enter currently inserts the command and sends the message immediately. - Emoji autocomplete works, but pressing Enter finalizes the emoji and sends the message. - **The Send button remains visually disabled**, requiring an additional fix to update its state. - Next step: Prevent message sending when popups (slash command, emoji autocomplete) are active.
- Updated reducer function to handle FormEvent<HTMLDivElement> instead of FormEvent<HTMLInputElement>. - Changed event target from HTMLInputElement to HTMLDivElement for compatibility with contenteditable. - Used `innerText.trim()` instead of `value.trim()` to correctly determine if the message input is empty. - Replaced `onChange` with `onInput` in `MessageComposerInputNew` to properly detect user input. This ensures the Send button is correctly enabled or disabled based on input presence. Known Issues & Next Steps: - Pressing `/` opens the slash command menu, but pressing Enter inserts the command and sends the message immediately. - Emoji autocomplete works, but Enter finalizes the emoji and sends the message. - Next step: Prevent message sending when popups (slash command or emoji autocomplete) are active.
- Introduced `featurePreviewComposer` flag to toggle between the new <div contenteditable> input and the classic <textarea> input. - Conditionally render `MessageBoxNew` or `MessageBox` based on the flag. - Added `MessageComposerHint` in `MessageBoxNew` to label the feature as experimental.
- Changed class name from `rc-message-box__textarea` to `rc-message-box__divcontenteditable`. - Rectified string values for `minHeight` and `maxHeight` with numeric values. - Corrected `minHeight` from `52px` to `20px` to match new layout requirements.
This refactor removes ambiguity and improves naming consistency across the message composer components. Renamed: - `MessageComposerInputNew.tsx` → `RichTextComposerInput.tsx` - `MessageBoxNew.tsx` → `RichTextMessageBox.tsx` - `newCreateComposerAPI.ts` → `createRichTextComposerAPI.ts` Updated references in: - `ComposerMessage.tsx` - `MessageComposer.stories.tsx` - `MessageComposer/index.ts`
- Moved `getSelectionRange` and `setSelectionRange` from `createRichTextComposerAPI.ts` to a new `selectionRange.ts` file. - Improves separation of concerns and allows reuse across other modules.
- Replaced `input.value` and `input.selectionEnd` with `innerText` and `getSelectionRange` - Used `setSelectionRange` to handle caret movement - Updated event targets and types from HTMLTextAreaElement to HTMLDivElement
This is a major bugfix that resolves an erratic behavior during keydown events - Added check to skip auto-focus when target is a <div contenteditable="true"> - Prevented focus tug-of-war between main and thread composers - Improved stability of typing behavior in multi-composer layouts - Resolved a critical issue where main and thread composers kept stealing focus from each other - Stabilized typing behavior in multi-composer scenarios
- Implemented a `WeakMap` to store the last cursor position per `contenteditable div` instance - Saved cursor position on `blur` event and restored it on `focus` event
This is a major bugfix that resolves an erratic behavior during Editing mode - Editing mode failed to reset due to `.innerText` collapsing multiple spaces - Caused mismatch between original message and `RichTextComposer` content - Fixed by adding `whiteSpace: 'pre-wrap'` `to RichTextComposerInput` - Ensures consistent text comparison and reliable edit cancellation - Added comment in the `RichTextComposerInput` definition to highlight the significance
- Blocked browser insertion of <b> and <i> tags - Delegated formatting to custom shortcut handler
This issue was caused due to the editor losing focus and cursor position state when clicking a Formatter button. - Added `setSelectionRange` and `focus` prior to `execCommand` call - Fixed issue where the button would append instead of replacing the selected text
- Fixed cursor moving to end of contentEditable input and regaining focus after editing reset
Draft messages were not properly stored and restored due to use of innerText, which strips formatting. - Switched to innerHTML to retain full content structure in Accounts.storageLocation.
- Added TypingState reducer to manage `isTyping` and `hidePlaceholder` flags - Adjusted placeholder visibility based on input DOM structure - Normalized content to treat `<div><br></div>` and empty input as `<br>` - Updated RichTextComposerInput to support and render `hidePlaceholder` prop - Ensured cursor is text-style inside `contenteditable` element - Prevented saving of Composer drafts when content is only `<br>`
- Replaced `_MessageComposerNew` story with `RichTextComposer` for clarity - Added `MessageComposerHint` to highlight experimental status - Passed `placeholder` and new `hidePlaceholder` prop to `RichTextComposerInput` - Updated Storybook args for enhanced prop control
- Corrected the forwarded `ref` target to match the `contentEditable div` - Ensures proper typing and `ref` behavior for editable container - Minor style cleanup for whiteSpace and cursor properties
- Applied `overflow-y: scroll` to the `contenteditable div` for consistent scrollbar visibility - Styled `::-webkit-scrollbar-thumb` to fix invisible scrollbar in Chromium browsers
- Updated `getSelectionRange` to walk DOM and compute offsets precisely - Skipped inline elements and handled `<br>` inside empty `<div>` as visual linebreak - Added offset increment for block-level elements to reflect line structure - Updated `setSelectionRange` to match same offset logic for accurate selection - Resolved inconsistency between `selectionStart` and `selectionEnd` and visual cursor placement
- Normalized multiple newlines in `innerText` during selection wrapping - Added selectionchange listener to debug selection range - Implemented listener cleanup on component release
- Updated `cursorMap` to store both `selectionStart` and `selectionEnd` for accurate range restoration - Replaced single-value tracking with object structure in `WeakMap` - Improved `setSelectionRange` on focus to restore full selection, not just caret
- Updated `resolveComposerBox` to handle both event and programmatic calls with `HTMLDivElement` - Added `instanceof` check to differentiate between `HTMLElement` and event inputs - Added `useEffect` on `shouldPopupPreview` for text resolution after a popup option is selected
- Added `beforeText` state before for text state updation - Added skip checks for parsing if text is unchanged after a focus event - Removed unnecessary reparsing on repeated focus events causing potential edit history bloating
This is an edge case fix that uses `closest('[contenteditable="true"]')` to ensure the correct contenteditable element is targeted. It prevents an issues where pasting into an empty composer caused `input.innerText` to be blank due to `<br>` removal. - Added `parseAST` debug logging for parsed message output. - Updated parsing to treat empty text as `'\n'` to avoid AST generation errors. - Renamed unused state setter params with `_` prefix to indicate they are unused.
This is done to prevent the parser grammar from exploding the URLs inside the Composer The other solution to prevent this is to edit the grammar.pegjs itself which can be complicated - Added `protectLinks` to temporarily replace Markdown, Slack-style, and bare domain links with placeholders before parsing - Added `restoreLinks` to revert placeholders back to original links after generating HTML - Updated `resolveComposerBox` to use these functions, ensuring links are not mangled during parsing - Logs final HTML after restoring links for debugging
- Implemented `resolveComposerBox` when navigating threads with Up/Down arrow keys
- Introduced `renderInline` to convert inline AST tokens - Added support for plain text, mentions, formatting (bold, italic, strike, code) - Implemented partial support for emojis, images, timestamps, and inline LaTeX - Removed support for link token due to URL explosion issue - Added `parseAST` to map parsed blocks into HTML including paragraphs, headings, lists, tasks, quotes, code blocks and line breaks - Implemented partial support for KaTeX blocks
- Escaped user text before assigning to `innerHTML` in the RichTextComposer - Prevented DOM text from being reinterpreted as HTML - Resolved CodeQL/code scanning warnings related to XSS
- Emoji shortcodes convert into Unicode emoticons. - Custom uploaded emojis render as <span> with inline <img> and shortcode fallback.
This is still a work in progress - Paragraphs: replaced `<p>` wrappers with raw text + newline - Headings: preserve `#` prefix inside `<hX>` tags - Unordered lists: prefix list items with `-` - Ordered lists: include numeric prefix and `value` attribute - Code blocks: render with Markdown-style fences (```lang ... ```) - Line breaks: output raw `\n` instead of `<br />`
- Switched `resolveComposerBox` to run on `input` instead of `beforeinput` - Removed unused undo/redo and focus event handling logic - Improved `protectLinks`: - Added email detection - Prevented mentions (`@something`) from being parsed as URLs - Adjusted bare domain regex to exclude `@` prefixes - Updated rendering pipeline: - Writes `innerHTML` directly (works but clears undo history) - Left comments for `execCommand('insertHTML')` as alternative that preserves history - Cursor position is restored after re-render
- Removed unused types (`Dispatch`, `SetStateAction`, `CursorHistory`) - Dropped debug helper `printSelection` and selection tracking - Replaced `beforeinput` listener with unified `input` listener - Updated `resolveComposerBox` signature to remove state dependencies - Cleaned up event removal in `release` function
- Dropped unused types (`Dispatch`, `SetStateAction`, `CursorHistory`) - Removed `setCursorHistory` state and related resolver calls - Simplified `handleFormattingShortcut` to only wrap selection - Cleaned up `setLastCursorPosition` and keyboard/newline handlers by removing resolver logic - Updated `createRichTextComposerAPI` usage to new signature without cursor/history state - Removed `useEffect` that resolved composer after popup option selection
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
|
bacc1b3
to
f811ccc
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #36736 +/- ##
===========================================
+ Coverage 64.26% 65.38% +1.12%
===========================================
Files 3142 3263 +121
Lines 106460 109206 +2746
Branches 20175 20838 +663
===========================================
+ Hits 68418 71406 +2988
+ Misses 35582 35137 -445
- Partials 2460 2663 +203
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
This PR is not meant to be merged, just to create a testing env