AI reply menu: click Fast/Full → context input → OK

Restructured flow:
1. Click Fast or Full → reveals an optional context textarea
   ("Add context (optional)") below
2. Type optional steering note or leave blank
3. Click OK → triggers the draft with the chosen mode + note

Dropped the standalone … note-toggle button — the textarea is now
gated on picking a mode, which makes it easier to discover.
This commit is contained in:
pewdiepie-archdaemon
2026-06-13 06:59:10 +09:00
parent cedc38fee8
commit 3819a23344
+27 -27
View File
@@ -5923,8 +5923,8 @@ function _showAiReplyChoice(btn, em, data) {
// Full = layered concentric circles to suggest "more, deeper" — not a fully
// filled circle so it reads as a complement to the lightning, not as a "stop".
menu.innerHTML = `
<div class="email-ai-reply-row" style="display:flex;flex-direction:column;gap:6px;min-width:180px;">
<div style="display:flex;align-items:center;gap:4px;">
<div class="email-ai-reply-row" data-step="choose" style="display:flex;flex-direction:column;gap:6px;min-width:180px;">
<div data-mode-row style="display:flex;align-items:center;gap:4px;">
<button class="memory-toolbar-btn" data-mode="ai-reply-fast" title="Shorter, faster draft" style="display:inline-flex;align-items:center;gap:5px;">
<svg width="11" height="11" viewBox="0 0 24 24" fill="var(--accent, var(--red))" aria-hidden="true"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
Fast
@@ -5933,39 +5933,39 @@ function _showAiReplyChoice(btn, em, data) {
<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" style="color:var(--accent, var(--red));"><circle cx="12" cy="12" r="6"/></svg>
Full
</button>
<button class="memory-toolbar-btn" data-act="note-toggle" title="Add a note about how to reply" style="display:inline-flex;align-items:center;justify-content:center;padding:4px 6px;line-height:1;margin-left:auto;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/></svg>
</button>
</div>
<div data-note-panel hidden>
<textarea data-note-input rows="2" placeholder="e.g. reply nicely but say no" style="width:100%;box-sizing:border-box;resize:vertical;min-height:38px;font-family:inherit;font-size:11px;padding:5px 6px;border-radius:5px;border:1px solid var(--border,#333);background:var(--bg-elev,#1a1a1a);color:var(--fg);"></textarea>
<div data-note-panel hidden style="display:flex;flex-direction:column;gap:6px;">
<textarea data-note-input rows="2" placeholder="Add context (optional)" style="width:100%;box-sizing:border-box;resize:vertical;min-height:42px;font-family:inherit;font-size:11px;padding:5px 6px;border-radius:5px;border:1px solid var(--border,#333);background:var(--bg-elev,#1a1a1a);color:var(--fg);"></textarea>
<button data-act="note-ok" class="memory-toolbar-btn" style="display:inline-flex;align-items:center;justify-content:center;gap:5px;">OK</button>
</div>
</div>
`;
const modeRow = menu.querySelector('[data-mode-row]');
const notePanel = menu.querySelector('[data-note-panel]');
const noteInput = menu.querySelector('[data-note-input]');
menu.querySelector('[data-act="note-toggle"]').addEventListener('click', (ev) => {
ev.preventDefault();
ev.stopPropagation();
const opening = notePanel.hasAttribute('hidden');
if (opening) {
notePanel.removeAttribute('hidden');
setTimeout(() => noteInput.focus(), 0);
} else {
notePanel.setAttribute('hidden', '');
}
});
let pendingMode = null;
menu.addEventListener('click', async (ev) => {
const choice = ev.target.closest('[data-mode]');
if (!choice) return;
ev.preventDefault();
ev.stopPropagation();
const mode = choice.getAttribute('data-mode') || 'ai-reply';
// Always pick up whatever's in the textarea — empty = no note,
// typed = passed through as steering context.
const noteHint = (noteInput.value || '').trim();
_closeAiReplyChoice();
await _runAiReplyFromButton(btn, em, data, mode, noteHint);
if (choice) {
ev.preventDefault();
ev.stopPropagation();
// First click reveals the optional-context textarea; the actual
// draft runs on OK. Empty context just runs the chosen mode.
pendingMode = choice.getAttribute('data-mode') || 'ai-reply';
modeRow.setAttribute('hidden', '');
notePanel.removeAttribute('hidden');
setTimeout(() => noteInput.focus(), 0);
return;
}
const ok = ev.target.closest('[data-act="note-ok"]');
if (ok) {
ev.preventDefault();
ev.stopPropagation();
const noteHint = (noteInput.value || '').trim();
const mode = pendingMode || 'ai-reply';
_closeAiReplyChoice();
await _runAiReplyFromButton(btn, em, data, mode, noteHint);
}
});
// Esc closes the popover; ignore plain clicks inside the menu so the
// textarea stays focused.