# 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`
