feat: 'Send to Chat' button in document editor
Some checks are pending
ci / docker publish / build (amd64) (push) Waiting to run
ci / docker publish / build (arm64) (push) Waiting to run
ci / docker publish / merge manifest + tag (push) Blocked by required conditions

Adds a 'Chat' button to the left of the Save button in the document
editor footer. Clicking it injects a reference into the chat textarea:
[Title](#document-<id>) — <120-char snippet>...

The reference is not the full document content — just a title link
with opening snippet. The user can then send it or edit the message
before sending. This is the first step toward making documents feel
like first-class citizens in agent chat.
This commit is contained in:
Lukas Parsons 2026-07-07 11:49:24 -04:00
parent eba94a0de0
commit 5f13f7b3c9

View file

@ -667,6 +667,22 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
} }
} }
function _sendToChat() {
if (!activeDocId) return;
const doc = docs.get(activeDocId);
if (!doc) return;
const content = typeof doc.content === 'string' ? doc.content : '';
const snippet = content.substring(0, 120).replace(/\n/g, ' ');
const ref = `[${doc.title || 'Untitled'}](#document-${activeDocId})${snippet ? ' — ' + snippet + (content.length > 120 ? '...' : '') : ''}`;
const msgEl = document.getElementById('message');
if (!msgEl) return;
const current = msgEl.value.trim();
msgEl.value = current ? `${current}\n\n${ref}` : ref;
msgEl.focus();
// Trigger input event so the textarea auto-resizes and any listeners fire
msgEl.dispatchEvent(new Event('input', { bubbles: true }));
}
async function _openExportPdfModal() { async function _openExportPdfModal() {
if (!activeDocId) return; if (!activeDocId) return;
await _saveActiveDocBeforeExport(); await _saveActiveDocBeforeExport();
@ -4596,6 +4612,7 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
pinned to the bottom no matter which pane (editor / md-preview / pinned to the bottom no matter which pane (editor / md-preview /
csv / html / pdf) is the one growing to fill. --> csv / html / pdf) is the one growing to fill. -->
<div id="doc-actions-footer" class="doc-email-actions"> <div id="doc-actions-footer" class="doc-email-actions">
<button type="button" id="doc-send-to-chat-btn" class="doc-action-icon-btn" title="Send document reference to chat" style="gap:4px;margin-right:8px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg><span style="font-size:11px;">Chat</span></button>
<span class="email-send-split" id="doc-copy-export-split"> <span class="email-send-split" id="doc-copy-export-split">
<button type="button" id="doc-footer-copy-btn" class="email-send-btn email-send-main" title="Save new version" data-mode="save"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>Save</button> <button type="button" id="doc-footer-copy-btn" class="email-send-btn email-send-main" title="Save new version" data-mode="save"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>Save</button>
<button type="button" id="doc-footer-export-btn" class="email-send-btn email-send-caret" title="Export as…" aria-label="Export options"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 15 12 9 18 15"/></svg></button> <button type="button" id="doc-footer-export-btn" class="email-send-btn email-send-caret" title="Export as…" aria-label="Export options"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 15 12 9 18 15"/></svg></button>
@ -4799,6 +4816,7 @@ import { bindMenuDismiss, dismissOrRemove } from './escMenuStack.js';
else saveDocument({ silent: false, forceVersion: true }); else saveDocument({ silent: false, forceVersion: true });
}); });
document.getElementById('doc-footer-export-btn')?.addEventListener('click', (e) => showExportMenu(null, e.currentTarget.getBoundingClientRect())); document.getElementById('doc-footer-export-btn')?.addEventListener('click', (e) => showExportMenu(null, e.currentTarget.getBoundingClientRect()));
document.getElementById('doc-send-to-chat-btn')?.addEventListener('click', () => _sendToChat());
// Mobile footer: Close the current doc + Copy its content (replaces the // Mobile footer: Close the current doc + Copy its content (replaces the
// per-tab × on small screens, mirroring the email reader's Close footer). // per-tab × on small screens, mirroring the email reader's Close footer).
document.getElementById('doc-mobile-close')?.addEventListener('click', () => { if (activeDocId) closeTab(activeDocId); }); document.getElementById('doc-mobile-close')?.addEventListener('click', () => { if (activeDocId) closeTab(activeDocId); });