Les thèmes, notes proches, index et suppression de compte parlent comme un utilisateur, plus comme un outil interne.
Co-authored-by: Cursor <cursoragent@cursor.com>
Les boutons des pages Agents, MCP, Données, Intégrations et Généraux suivent la couleur choisie. Les libellés encore techniques (recherche par le sens, notes proches, connexion unique) sont en langage courant.
Co-authored-by: Cursor <cursoragent@cursor.com>
Les boutons suivent la couleur d’apparence, les libellés trop petits ou trop techniques sont clarifiés, et le catalogue des fournisseurs se met à jour tout seul.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remplace le titre « notepad » et le jargon (Intelligence OS, SM-2) par des mots lisibles, et aligne la langue des pages d’auth sur le reste du site.
Co-authored-by: Cursor <cursoragent@cursor.com>
Ne plus réinjecter une note déjà dans la liste, et n’afficher le menu de formatage que sur une vraie sélection de texte.
Co-authored-by: Cursor <cursoragent@cursor.com>
Rendre le dashboard actionnable (inbox, peek, carte mentale), aligner la facturation sur l’essai 7 jours, et bloquer le login e-mail tant que l’adresse n’est pas confirmée.
Co-authored-by: Cursor <cursoragent@cursor.com>
- requestAiConsent now redirects to /settings/general?highlight=aiConsent
instead of opening the modal when called outside the settings page
- Settings page highlights the consent section and scrolls to it
- Adds consent.ai.settingsBanner i18n key (fr/en)
- Keeps inline modal on /settings/general so the grant button still works
- Centralize AI consent 403 responses in server-consent helpers
- Return human-readable message + code + i18n errorKey from all AI APIs
- Update dashboard and AI clients to detect code/errorKey and translate
- Add consent.ai.requiredToast i18n keys (fr/en)
- Ajout du flag ALLOW_DIAGNOSTICS dans sidepanel.js.
- En prod (builds Chrome Store / Firefox) ALLOW_DIAGNOSTICS = false :
le bouton ? et le panneau diagnostic sont masqués, logDiag reste silencieux.
- Mise à jour des scripts de build pour appliquer ALLOW_DIAGNOSTICS = false.
- Bump version 0.4.6.
- build-chrome-store.mjs / build-firefox.mjs : host_permissions et content_scripts matches
passent à http://*/* + https://*/* au lieu de memento-note.com uniquement.
Un Web Clipper a besoin d'accéder à tous les sites ; le manifest Store
bloquait l'injection du content script sur n'importe quel article.
- extract-article.ts : refonte de cleanClipText en filtrage par ligne avec
patterns élargis (mis à jour, temps de lecture, aujourd'hui à HH:MM,
source - date, publié le, etc.).
- Bump version 0.4.5 dans manifest, locales, README et builds.
- content.js : écrit la sélection dans chrome.storage.session/local en plus du message runtime
- sidepanel.js : lit le storage en fallback, loggue chaque étape, affiche un diagnostic panel
- sidepanel.js : avertissement explicite si le content script n'est pas détecté
- sidepanel.js : sépare le rendu Markdown du résumé et l'affichage texte brut de l'extrait
- sidepanel.css : agrandit la zone de prévisualisation
- i18n : nouvelles clés contentScriptMissing, diagnosticsTitle, copyDiagnostics
- locales : correction FR (Retour, Enregistrement, Note, etc.) + version 0.4.4 partout
- extract-article.ts : nettoie textContent des métadonnées (dates, temps de lecture, sources)
- analyze/route.ts : excerpt propre via makeExcerpt
- builds Chrome Store et Firefox regénérés en 0.4.4
Avant : renderConfirm() échappait le résumé et l'extrait avec escapeHtml(),
donc les **gras**, *italique*, [liens](), listes, titres du Markdown
produit par l'IA s'affichaient en texte brut (littéral « **gras** »).
Maintenant : renderMarkdownSafe() parse le Markdown en HTML limité
et sûr (escapeHtml d'abord, puis regex sur le texte échappé — pas de
HTML brut autorisé).
+ Refonte du panneau de prévisualisation :
- .preview-block avec header sticky (label Résumé / Extrait)
- .excerpt-block : min-height 180px, max-height 360px, scroll si long
- .summary-block : fond bleuté léger, bordure gauche sky
- markdown-h3/h4/h5 stylés (serif pour titres), strong/em/code/ul/a
- Polices 14px, line-height 1.7, word-break pour texte long
+ Nouvelle clé i18n summaryLabel dans les 15 locales.
+ Version 0.4.2 → 0.4.3.
VRAI bug (que tu as raison de souligner, j'aurais pas dû revert) :
la fonction applySelectionFromMessage rejetait TOUT message si pageUrl
n'était pas encore settée, ou si les URLs différaient sur un trailing
slash / fragment / query. Et pageUrl se populate de façon async via
chrome.tabs.query dans refreshPageContext — donc le premier SELECTION_CHANGED
arrivait avant pageUrl, était rejeté, et la sélection n'était jamais
appliquée.
Fixes dans sidepanel.js :
- applySelectionFromMessage : si pageUrl vide, on amorce depuis le
message (pageUrl, pageTitle, pageDomain, pageFavicon). Sans ce
fallback, le bouton « Clipper la sélection » n'apparaît jamais.
- Comparaison d'URL tolérante (origin + pathname, sans trailing slash,
hash, query).
- refreshPageContext : ne pas marquer tab?.url undefined comme restricted.
Version bumpée 0.4.1 → 0.4.2 (à chaque livraison comme demandé).
Le rollback complet de content.js, background.js et sidepanel.js vers
la v0.3.1 (que tu confirmes fonctionner) règle la régression. Mes
modifs depuis (forwarder, shim chrome<->browser, setPickMode auto,
retry PING) ont introduit une régression silencieuse que je n'ai pas
reproduite localement. Je remets le code qui marchait.
Manifest = v0.3.1 + ajout sidebar_action + browser_specific_settings.gecko
pour le build Firefox. Version bumpée 0.3.1 → 0.4.1.
Bug réel : la bannière 'Surlignez le texte à clipper' n'apparaissait
jamais en pratique parce que le side panel envoyait SET_PICK_MODE
avant que le content script ne soit prêt (race condition MV3 entre
chrome.scripting.executeScript et la mise en place du listener
chrome.runtime.onMessage). Le retry PING dans ensureContentScript
ne suffisait pas : le listener sidepanel peut aussi être en retard.
Fix radical : content.js affiche la bannière IMMÉDIATEMENT à
l'initialisation, sans attendre SET_PICK_MODE. L'utilisateur voit
immédiatement que l'extension est active. Un bouton ✕ permet de
la fermer (state local au tab). Pas de dépendance sur le side panel
pour le feedback visuel.
+ manifest : retrait de optional_host_permissions (redondant avec
host_permissions http://*/* et https://*/*, peut perturber Chrome
en dev).
+ bannière rediseignée : max-width 640px responsive, animation
slideIn, bouton ✕ accessible.
+ nouvelles clés i18n bannerDismiss dans les 15 locales.
+ build : exclusion de store-assets/ du zip et du xpi (sinon le
package Store faisait 327 Ko au lieu de 47 Ko).
Bannière pick mode :
- ensureContentScript() : retry le PING 8x (avec backoff 80→290ms) après
chrome.scripting.executeScript, parce que l'injection est async côté page
et le listener n'est pas enregistré immédiatement.
- Avant : SET_PICK_MODE partait dans le vide, la bannière « surlignez le
texte à clipper » n'apparaissait jamais.
Responsive :
- Media queries : <380px (Chrome Side Panel narrow), 380-420px (default),
>420px (Firefox sidebar), <320px (very small).
- Padding/margin/font-size adaptatifs selon la largeur du panneau.
- .selection-body : min-height 80px, plus de max-height fixe, scroll si
trop long. overflow-wrap: anywhere pour le texte long.
- .btn : padding 16px / min-height 48px pour le tactile.
- .page-card : word-break + overflow-wrap pour les URLs et titres longs.
- Firefox : media query dédié >480px pour aérer la sidebar Firefox
(plus large que Chrome Side Panel).
Rebuilt :
- memento-web-clipper-chrome-store.zip
- memento-web-clipper-firefox.xpi
Bug réel : chrome.runtime.sendMessage depuis un content script ne va
QU'au background service worker en MV3. Le side panel qui écoute via
chrome.runtime.onMessage ne reçoit jamais rien directement. Résultat :
la sélection, le titre de la page et le contexte n'atteignaient jamais
le panneau.
Fix :
- background.js : ajouter un onMessage qui forward SELECTION_CHANGED et
PAGE_CONTEXT_CHANGED vers toutes les surfaces (side panel).
- sidepanel.js applySelectionFromMessage : normaliser les URLs
(ignorer query/fragment/trailing slash), amorcer pageUrl depuis le
premier message si tabs.query a échoué, accepter une sélection qui
arrive avant refreshPageContext.
La v0.3.1 souffrait du même bug — la sélection fonctionnait parfois par
chance quand Chrome routait le message avant que le side panel ne soit
complètement initialisé. Maintenant c'est garanti.
Traductions:
- 'Tondeuse Web' (FR), 'Cortadora web' (ES), 'Schneiden Sie aus' (DE),
'ritagliare' (IT) etc. — le terme 'clip' était traduit littéralement
(tondeuse = mower, ausschneiden = cut out, ritagliare = trim).
- Garder 'clip' comme terme technique dans les 15 locales, sauf les
formulations verbe qui prennent une conjugaison locale correcte.
- 87 chaînes corrigées dans le bundle de traductions embarqué.
Diagnostic 401:
- Le message 'Veuillez vous connecter à Memento' s'affichait même
quand l'utilisateur était connecté, simplement sur une URL différente
(localhost vs 127.0.0.1 vs LAN IP — les cookies sont scopés par host).
- Nouveau message multi-ligne incluant l'URL configurée + bouton
'Ouvrir Memento' qui ouvre l'onglet directement à cette URL.
- Nouvelle clé i18n errLoginHintUrl (placeholder $URL$) traduite
dans les 15 locales.
Rebuilt :
- memento-web-clipper-chrome-store.zip (44 Ko)
- memento-web-clipper-firefox.xpi (44 Ko)
- extension/scripts/generate-store-assets.py : générateur Python/PIL avec
la palette x.ai premium (BG #0B0A09, TEXT #F4F1EA, OCHRE #D4A373).
- extension/store-assets/ :
* icon-128.png (128×128)
* promo-tile-small.png (440×280)
* promo-tile-large.png (920×680)
* marquee.png (1400×560)
* screenshot-1.png (1280×800) — sidebar idle avec sélecteur de carnet
* screenshot-2.png (1280×800) — confirmation IA avec résumé + tags
* screenshot-3.png (1280×800) — vue RTL/persan (font DejaVu pour glyphes)
Tous les assets respectent les dimensions Chrome Web Store et sont prêts
pour la soumission.
- Nouvelle page /privacy bilingue (FR/EN) avec sélection par Accept-Language
ou ?lang=, sections complètes (données collectées, IA/BYOK, RGPD, sécurité,
contact). Style sombre aligné sur la landing (x.ai premium).
- Liens footer landing.footer.legal.* mis à jour vers /privacy dans les 15 locales.
- Extension Web Clipper rendue cross-browser :
* background.js détecte chrome.sidePanel vs browser.sidebarAction
* sidepanel.js ajoute un shim chrome<->browser pour Firefox
* manifest.json inclut sidebar_action + browser_specific_settings.gecko
+ optional_host_permissions (Chrome les ignore)
- Script scripts/build-firefox.mjs pour produire un .xpi signé pour AMO,
symétrique de build-chrome-store.mjs. Exclusion mutuelle des artefacts
Chrome/Firefox pour éviter la cross-contamination.
- Branding corrigé : 176 occurrences de 'Momento' -> 'Memento' dans le
bundle de traductions embarqué.
- Version bumpée 0.3.1 -> 0.4.0.
Un pot de crédits global (BASIC 100 / PRO 1 000 / BUSINESS 4 000) remplace
les seaux par fonction côté débit. Packs one-shot S/M/L, admin sans seaux
legacy, usage multi-features, hints de coût, anti-flash thème et hydratation
admin. Inclut aussi le pipeline slides renforcé et la page publique polishée.
- Ne plus auto-scroller vers Memory Echo : pastille bas de page + reset scroll au titre
- Badges notes/carnets générés par l’IA dans la sidebar
- Wizard : langue du contenu = langue de la requête ; refresh carnet après création
- Voix : erreurs not-allowed/no-speech moins bruyantes
Centralise la réserve via ai-quota, corrige admin unavailable (-1), brancher les routes sans quota et le host-pays brainstorm, avec usage-meter élargi, noms de clusters, MCP et ajustements dashboard/insights.
Co-authored-by: Cursor <cursoragent@cursor.com>
Ajoute une poignée drag pour la largeur de la sidebar (persistée) et sépare inbox/arbre carnets avec slider vertical ; supprime le bouton Note du jour devenu inutile.
Co-authored-by: Cursor <cursoragent@cursor.com>
Mobile fixes (CRITIQUE):
- theme.ts: C.surface + emerald/blue/amber/purple ajoutés (crash Révision fix)
- note/[id].tsx: édition préserve le HTML (titre seulement, contenu read-only)
+ message explicatif 'utilisez la version web'
- store.ts: logout appelle POST /api/mobile/auth/logout avant clearToken
Mobile auth (SÉCURITÉ):
- Nouvelle route /api/mobile/auth/logout — blacklist Redis du token (TTL 90j)
- verifyMobileToken devient async + check Redis blacklist
- getMobileUserId devient async
Note: Publication IA mode + templates déjà dans note-editor-toolbar.tsx (pas manquant)
Note: Structured Views Wizard déjà branché via StructuredViewsIntro (pas orphelin)
Vrai problème (hauteur, pas largeur) : le conteneur scrollable externe
était flex-1 + overflow-y-auto mais PAS flex flex-col. Du coup le
flex-1 de la vue carnets ne s'appliquait pas → la liste prenait la
hauteur de son contenu et s'arrêtait au milieu (trait flottant + vide
en dessous) quand il y avait peu de carnets.
Fix : ajoute `flex flex-col min-h-0` au conteneur externe pour que la
chaîne flex fonctionne — la liste des carnets remplit désormais toute
la hauteur jusqu'au pied de page (Pack Pro), quel que soit le nombre
de carnets.
Co-authored-by: Cursor <cursoragent@cursor.com>
L'écart précédent (320->352, +32px) était imperceptible. La sidebar
étant ancrée dès md (768px), on applique une largeur franche à ce
breakpoint pour un résultat indiscutable :
- < 768px (mobile overlay) : w-80 (320px)
- >= 768px : w-[26rem] (416px) [+96px]
- >= 1536px : w-[30rem] (480px)
Co-authored-by: Cursor <cursoragent@cursor.com>
La sidebar restait à 320px en production car l'élargissement ne se
déclenchait qu'à partir du breakpoint xl (1280px). Abaisse le seuil à
md (768px) pour couvrir tous les écrans desktop en production.
- < 768px (mobile, overlay) : w-80 (320px)
- >= 768px : w-[22rem] (352px)
- >= 1536px : w-[26rem] (416px)
Le fallback Suspense du layout est aligné pour éviter tout décalage.
Co-authored-by: Cursor <cursoragent@cursor.com>
h-full dépendait du parent pour la hauteur — ne cascadaît pas en prod.
h-screen (100vh) + self-stretch force la hauteur pleine indépendamment.
Suspense fallback aussi mis à h-screen pour éviter le flash.