## Implementation Plan: New-line Support in Chat Messages ### Objective Replace the single-line `` used for message composition with a ``, update all client-side JavaScript references and keyboard event handling, and adjust CSS. Downstream layers already support newlines; no changes needed in persistence, routing, or rendering. ### Files to Modify 1. **`templates/messages.html` (line 61)** Change `` to ``. - Remove the `maxlength` attribute; textarea will use the existing server-side truncation in `persist.py`. - Add `rows="1"` to maintain the current single-line appearance until user types newlines. - Keep `placeholder`, `autocomplete="off"`, `data-mention`, `aria-label`. 2. **`static/js/MessagesLayout.js` (lines 17, 165, and any other references to `input[name="content"]`)** - Update the selector from `querySelector('input[name="content"]')` to `querySelector('textarea[name="content"]')`. - In `bindForm()` / `sendViaSocket()` (around line 165 area, exact location to be confirmed during implementation), add handling for **Enter-to-send** with **Shift+Enter-for-newline**: - Prevent default form submission on Enter press (since `` does not submit by default). - If Enter is pressed without Shift, trigger message send. - If Shift+Enter is pressed, insert a newline. - This logic must be applied to `keydown` event on the textarea. - Ensure `.trim()` is called on the value before sending (already present). - Remove any existing Enter-key handler that may interfere. 3. **`static/css/messages.css` (or appropriate stylesheet)** - Apply styles so the `` visually behaves like the current single-line input: - `resize: none` to prevent user resizing. - `overflow-y: auto` with a `max-height` (e.g., `150px`) to allow expansion for multiple lines. - Inherit existing input dimensions (`height`, `padding`, `font-size`, `border`). - Ensure white-space is normal and `word-wrap: break-word` for long lines. 4. **Tests (add a minimal unit test for newline persistence)** - Add a test in `tests/api/messages/send.py` (or a new file under `tests/unit/services/messaging/`) that verifies a message with `\n` characters is stored and returned without stripping. - This is not strictly required by the investigation, but it prevents regression and demonstrates correctness. ### Verification Commands (required to pass) ```bash pip install -e '.[dev]' --break-system-packages -q # Override PEP 668 restriction make test-unit pip install -q ruff && ruff check . ``` **Important:** The previous failures stemmed from PEP 668 blocking pip. Use `--break-system-packages` to bypass. If still failing, create a virtual environment (`python -m venv venv`, source activate, install there) and run commands inside it. ### Definition of Done - [ ] `` replaced with `` in `templates/messages.html:61`. - [ ] JavaScript selector updated from `input[name="content"]` to `textarea[name="content"]` in `MessagesLayout.js` (all occurrences). - [ ] Enter key without Shift triggers message send; Shift+Enter inserts newline — verified by manual test in browser or E2E. - [ ] CSS applied: no resize, max-height, same dimensions as original input — no visual regression for single-line messages. - [ ] A unit test added that sends a message containing `\n` and asserts content is preserved. - [ ] `pip install -e '.[dev]' --break-system-packages -q && make test-unit` exits 0. - [ ] `pip install -q ruff && ruff check .` exits 0. - [ ] (Optional but recommended) Run a subset of existing E2E tests (`tests/e2e/messages.py`) to confirm no regression in message sending flow.