# Editor & composer — handoff ## Summary The message composer is a **Slate**-based rich text editor with autocomplete for users, rooms, and emoticons. Converts between editor state and Matrix HTML/plaintext. Supports toolbar formatting, intents, and file paste/drop integration. ## User-facing behavior - Type messages with bold/italic/code etc. (toolbar) - `@user` and `#room` mentions with autocomplete popup - `:emoji` emoticon autocomplete - Paste images/files into composer - Draft persistence per room ## Architecture ``` Editor.tsx (Slate) → Elements.tsx, Toolbar.tsx → autocomplete/ (User, Room, Emoticon) → input.ts / output.ts — Matrix format conversion RoomInput.tsx wires Editor to send pipeline + uploads text-area plugin (legacy/plain areas in some UI) ``` ## Key files | Path | Role | |------|------| | `cinny/src/app/components/editor/Editor.tsx` | Main Slate editor | | `cinny/src/app/components/editor/Toolbar.tsx` | Formatting toolbar | | `cinny/src/app/components/editor/input.ts` | Parse into editor | | `cinny/src/app/components/editor/output.ts` | Serialize to Matrix | | `cinny/src/app/components/editor/autocomplete/` | Mention/emoji menus | | `cinny/src/app/features/room/RoomInput.tsx` | Room composer wrapper | | `cinny/src/app/plugins/text-area/` | Plain text area utilities | | `cinny/src/app/hooks/useFilePasteHandler.ts` | Paste files | | `cinny/src/app/hooks/useFileDrop.ts` | Drag-drop files | | `cinny/src/app/state/room/roomInputDrafts.ts` | Draft persistence | ## Data model | Key | Storage | |-----|---------| | `roomIdToMsgDraftAtomFamily` | localStorage per room | | `roomIdToUploadItemsAtomFamily` | pending uploads | ## Dependencies - `slate`, `slate-react` - `folds` UI primitives ## Integration points - **room-timeline**: send on submit - **emoji-stickers**: emoticon autocomplete + custom packs - **plugins**: `text-composer-toolbar`, `composer-actions` slots - **media-and-url-preview**: upload before send ## Testing ### Manual 1. Mention user and room; verify pill rendering in sent message. 2. Format bold/italic; verify HTML in `formatted_body`. 3. Reload mid-compose; draft restores. 4. Paste image; upload card appears. ### Automated - `Editor.preview.tsx` exists for dev preview ## Known issues & gotchas - `useCompositionEndTracking` in App.tsx for IME composition - Slate types in `slate.d.ts` — keep custom elements typed - Plain text vs HTML fallback for clients without HTML support ## Future work - WYSIWYG markdown mode - Draft sync across devices via account data ## Related docs - [room-timeline HANDOFF](../room-timeline/HANDOFF.md) - [emoji-stickers HANDOFF](../emoji-stickers/HANDOFF.md) ## Add your extra things here - `plainToEditorInput`, `toPlainText` helpers exported from editor index - Forum has separate composers: `ForumReplyComposer`, `ForumChatComposer`