From 0f48df114ae63fe6a05f016a4a1e944dc7a47360 Mon Sep 17 00:00:00 2001 From: sepehr Date: Sun, 3 May 2026 01:28:54 +0200 Subject: [PATCH] fix(chat): buttons always visible on last msg + preview panel outside scroll zone --- .../components/contextual-ai-chat.tsx | 60 +++++++++++++++++-- memento-note/scripts/fix-chat-buttons.js | 54 +++++++++++++++++ 2 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 memento-note/scripts/fix-chat-buttons.js diff --git a/memento-note/components/contextual-ai-chat.tsx b/memento-note/components/contextual-ai-chat.tsx index bc6d5b0..bf3a704 100644 --- a/memento-note/components/contextual-ai-chat.tsx +++ b/memento-note/components/contextual-ai-chat.tsx @@ -462,11 +462,14 @@ export function ContextualAIChat({ ? :

{content}

} - {/* Hover-actions — visible only on assistant messages */} - {isAssistant && onApplyToNote && ( + {/* Inject buttons — always visible on last assistant msg */} + {isAssistant && onApplyToNote && (() => { + const lastAssistantId = messages.filter(m => m.role === 'assistant').at(-1)?.id + const alwaysShow = msg.id === lastAssistantId + return (
- )} + ) + })()} ) @@ -560,6 +564,54 @@ export function ContextualAIChat({
+ {/* ══ Inject Preview Panel — fixed, always visible, NO scroll needed ══ */} + {resourceEnriching && ( +
+ + Traitement IA en cours... +
+ )} + {resourcePreview && !resourceEnriching && ( +
+
+ + {resourcePreview.source === 'complete' ? 'Complété par IA' + : resourcePreview.source === 'merge' ? 'Fusionné par IA' + : 'Aperçu'} + + +
+
+ +
+
+ + +
+
+ )} + {/* Scope & Tone Control Area */}
{/* Scope bar */} diff --git a/memento-note/scripts/fix-chat-buttons.js b/memento-note/scripts/fix-chat-buttons.js new file mode 100644 index 0000000..dacd77d --- /dev/null +++ b/memento-note/scripts/fix-chat-buttons.js @@ -0,0 +1,54 @@ +const fs = require('fs'); +const path = require('path'); +const filePath = path.join(__dirname, '..', 'components', 'contextual-ai-chat.tsx'); +let src = fs.readFileSync(filePath, 'utf8'); + +// ─── FIX 1: make inject buttons always visible on last assistant msg ────────── +// Replace the hover-gated condition with always-visible for last msg +const OLD_BUTTONS_CONDITION = ` {/* Hover-actions \u2014 visible only on assistant messages */}\r\n {isAssistant && onApplyToNote && (\r\n
`; + +const NEW_BUTTONS_CONDITION = ` {/* Inject buttons \u2014 always visible on last assistant msg */}\r\n {isAssistant && onApplyToNote && (() => {\r\n const lastAssistantId = messages.filter(m => m.role === 'assistant').at(-1)?.id\r\n const alwaysShow = msg.id === lastAssistantId\r\n return (\r\n
`; + +// Also need to close the IIFE +const OLD_BUTTONS_CLOSE = `
\r\n )}\r\n
`; +const NEW_BUTTONS_CLOSE = `
\r\n )\r\n })()}\r\n `; + +if (src.includes(OLD_BUTTONS_CONDITION)) { + src = src.replace(OLD_BUTTONS_CONDITION, NEW_BUTTONS_CONDITION); + console.log('Fix 1a: buttons condition updated'); +} else { + console.error('Fix 1a: OLD_BUTTONS_CONDITION not found!'); + process.exit(1); +} + +if (src.includes(OLD_BUTTONS_CLOSE)) { + src = src.replace(OLD_BUTTONS_CLOSE, NEW_BUTTONS_CLOSE); + console.log('Fix 1b: buttons IIFE close updated'); +} else { + console.error('Fix 1b: OLD_BUTTONS_CLOSE not found!'); + process.exit(1); +} + +// ─── FIX 2: Move preview panel OUTSIDE the scrollable div ──────────────────── +// The scrollable div ends with: messagesEndRef then +// We need to: +// A) Remove the preview block from inside the scrollable area (already was removed in previous sessions since it was added after messagesEndRef) +// B) Add preview as shrink-0 panel between the scroll div and controls + +// Find the closing of the scrollable area + start of controls +const OLD_SCROLL_END = `
\r\n
\r\n\r\n {/* Scope & Tone Control Area */}`; +const NEW_SCROLL_END = `
\r\n
\r\n\r\n {/* \u2550\u2550 Inject Preview Panel \u2014 fixed, always visible, NO scroll needed \u2550\u2550 */}\r\n {resourceEnriching && (\r\n
\r\n \r\n Traitement IA en cours...\r\n
\r\n )}\r\n {resourcePreview && !resourceEnriching && (\r\n
\r\n
\r\n \r\n {resourcePreview.source === 'complete' ? 'Compl\u00e9t\u00e9 par IA'\r\n : resourcePreview.source === 'merge' ? 'Fusionn\u00e9 par IA'\r\n : 'Aper\u00e7u'}\r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n setResourcePreview(null)}\r\n className="flex-1 text-[11px] py-1.5 rounded-lg border border-border/60 text-muted-foreground hover:bg-muted transition-colors"\r\n >\r\n Annuler\r\n \r\n {\r\n if (onApplyToNote && resourcePreview) {\r\n onApplyToNote(resourcePreview.text)\r\n setResourcePreview(null)\r\n setResourceText('')\r\n toast.success('Appliqu\u00e9 \u00e0 la note')\r\n }\r\n }}\r\n disabled={!onApplyToNote}\r\n className="flex-1 text-[11px] py-1.5 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 flex items-center justify-center gap-1"\r\n >\r\n \r\n Appliquer \u00e0 la note\r\n \r\n
\r\n
\r\n )}\r\n\r\n {/* Scope & Tone Control Area */}`; + +if (src.includes(OLD_SCROLL_END)) { + src = src.replace(OLD_SCROLL_END, NEW_SCROLL_END); + console.log('Fix 2: preview panel moved outside scroll'); +} else { + console.error('Fix 2: OLD_SCROLL_END not found!'); + // Show what we're looking for context + const idx = src.indexOf('messagesEndRef'); + console.error('Context around messagesEndRef:', JSON.stringify(src.slice(idx-20, idx+200))); + process.exit(1); +} + +fs.writeFileSync(filePath, src); +console.log('Done!');