feat: commentaires façon Notion — ancres jaunes, tiroir refondu, réactions emoji sur texte (v7.64.0)
- Réaction sur texte : bouton 🙂+ (« React to selected text ») dans la toolbar de sélection → sélecteur d'émoji EXISTANT en mode réaction (en-tête = texte sélectionné + ✋, onglets masqués, ligne Recent au-dessus de la grille People, Filter… et barre de catégories avec + custom inchangés) - Backend : migration 37 text_reactions (UNIQUE plage × emoji × utilisateur → POST idempotent) + GET/POST /api/pages/{id}/reactions (GET groupé par plage emoji/count/mine, POST toggle, 400 sur plage vide) - Affichage : plage commentée/réagie peinte en jaune (_paintAnchors après render/loadComments/loadReactions), pastille 😀+compte après la plage, clic pastille = rouvrir le sélecteur, clic ancre = ouvrir et centrer le fil - Pastilles = annotations : gtTok/gtMd les ignorent (y compris le chemin rapide innerText) et les offsets _srcOffset/_srcNodeLen les excluent → le texte sauvé est identique (vérifié dans le e2e) - Tiroir refondu : carte de fil (avatar, nom, horodatage, ✓ toggle resolve/reopen, ⋯ → Copy link #cmt-<id>/Delete), saisie « Add a comment... » avec @ et envoi ↑/Entrée ; #cmt-<id> ouvre et centre le fil au chargement ; loadComments + loadReactions à l'ouverture (commentCount enfin renseigné) - Fixes : resolveComment ne pouvait pas rouvrir (toujours resolved:true) ; showCommentBtn ignorait les sélections à ancre élément (bouton 💬 jamais affiché) - Tests : tests/test_v764_comments_reactions.py (8, dont toggle API réel), e2e/v764_comments_reactions.spec.js (8 étapes) — 3/3 specs e2e verts, suite complète 1383 passed / 0 failed, ruff OK, OpenAPI 7.64.0 (526 chemins)
This commit is contained in:
@@ -1,5 +1,68 @@
|
||||
# Changelog - FlowDeck
|
||||
|
||||
## v7.64.0 (2026-10-08) — Commentaires façon Notion : ancres jaunes, tiroir refondu, réactions sur texte
|
||||
|
||||
### Added
|
||||
|
||||
- **Réactions emoji sur un texte sélectionné** :
|
||||
- bouton **🙂+** dans la 3ᵉ ligne de la toolbar de sélection, infobulle
|
||||
« React to selected text » → ouvre le **sélecteur d'émoji existant** en mode
|
||||
réaction : en-tête = texte sélectionné (+ ✋), onglets masqués (emoji only),
|
||||
ligne **Recent** au-dessus de la grille **People**, Filter… et barre de
|
||||
catégories inchangées (dont `+` émoji custom).
|
||||
- **stockage** : migration 37 (`text_reactions`, une ligne par plage × émoji ×
|
||||
utilisateur, `UNIQUE` qui rend le POST idempotent) + endpoints
|
||||
`GET/POST /api/pages/{id}/reactions` (GET groupé par plage : `emoji/count/mine`,
|
||||
POST = toggle avec validation de plage non vide).
|
||||
- **affichage** : la plage est peinte en jaune (`.fd-anchor-react`) avec une
|
||||
**pastille** juste après (`😀` + compte si >1) ; clic sur la pastille →
|
||||
réouvre le sélecteur pour cette plage (ajout/suppression).
|
||||
- les pastilles ne sont **pas** du contenu : `gtTok`/`gtMd` les ignorent et les
|
||||
offsets `_srcOffset/_srcNodeLen` les excluent → `sync()` conserve le texte
|
||||
d'origine (vérifié dans le e2e) et les ancres ne décalent jamais.
|
||||
- **Ancres de commentaires visibles** — `_paintAnchors()` (appelé après chaque
|
||||
`render()`, après `loadComments` et `loadReactions`) entoure la plage commentée
|
||||
d'un **jaune** (`.fd-anchor`, gris si résolu) ; **clic sur l'ancre → le tiroir
|
||||
s'ouvre et centre le fil** (flash de surlignage).
|
||||
- **Tiroir de commentaires refondu** (image 1) : fil en carte arrondie avec
|
||||
**avatar coloré + nom + horodatage + ✓ (resolve/reopen) + ⋯** (menu Copy link /
|
||||
Delete), étiquette « 💬 on selected text », et champ de saisie **« Add a
|
||||
comment... »** avec **@** (insère la mention) et **bouton circulaire ↑** (envoi,
|
||||
`Entrée` aussi) — remplace le bouton « Comment ».
|
||||
- **Liens de commentaire** : `Copy link` copie `…#cmt-<id>` ; au chargement d'une
|
||||
page avec ce hash, le fil correspondant s'ouvre et se centre.
|
||||
- **Chargement initial** : `loadComments()` + `loadReactions()` à l'ouverture de la
|
||||
page → les ancres/pastilles sont peintes dès le premier rendu (et `commentCount`
|
||||
du tiroir est enfin renseigné).
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`resolveComment` ne pouvait pas rouvrir** : il envoyait toujours
|
||||
`resolved:true` → accepte désormais l'objet du fil et bascule
|
||||
(`resolveComment(c)`), le bouton ✓ du fil est donc réellement un toggle.
|
||||
- **`showCommentBtn` ignorait les sélections à ancre « élément »** (double-clic,
|
||||
sélection programmatique) → `closest('[data-bid]')` partait du wrapper et le
|
||||
bouton 💬 n'apparaissait pas → gère les 2 types de nœud (même fix que `showFmt`
|
||||
en v7.62).
|
||||
- **`gtTok` chemin rapide (`innerText`) incluait les pastilles de réaction** →
|
||||
sélecteur enrichi (`.fd-react-chip`) pour basculer sur le marcheur qui les
|
||||
exclut : le texte sauvé reste identique.
|
||||
|
||||
### Tests
|
||||
|
||||
- `tests/test_v764_comments_reactions.py` (8 tests) : table + migration 37,
|
||||
endpoints enregistrés, **toggle API réel** (added → removed → added, grouping,
|
||||
400 sur plage vide), markup toolbar/tiroir, peinture des ancres, mode réaction
|
||||
du sélecteur.
|
||||
- **e2e Playwright** `e2e/v764_comments_reactions.spec.js` : bouton 🙂+ avec la
|
||||
bonne infobulle → sélecteur (en-tête = texte, Filter…, onglets masqués) →
|
||||
pastille + plage jaune **avec contenu inchangé après `sync()`** → 💬 → tiroir
|
||||
(avatar, nom, ✓, ⋯, Copy link) → ancre jaune cliquable → ✓ résout → reload :
|
||||
ancres et pastilles rechargées depuis la base ; **3/3 specs e2e verts**
|
||||
(`--workers=1`).
|
||||
- **Suite complète** : `pytest tests/ -q -n auto` → **1383 passed / 0 failed**,
|
||||
`ruff check app tests` → All checks passed.
|
||||
|
||||
## v7.63.0 (2026-10-08) — Menus mobiles façon Notion (barre au « / » + Insert block plein écran)
|
||||
|
||||
### Added
|
||||
|
||||
Reference in New Issue
Block a user