Enter asks, Ctrl+Enter breaks the line — in both chat modes
Almost every message here is one line, so the common action takes the bare key. Shift+Enter also breaks a line, because that is the reflex people arrive with.
This commit is contained in:
@@ -2028,7 +2028,19 @@ vv_ai_profiles_script();
|
|||||||
wrapEl.addEventListener('keydown', e => {
|
wrapEl.addEventListener('keydown', e => {
|
||||||
const inp = $('input');
|
const inp = $('input');
|
||||||
|
|
||||||
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { e.preventDefault(); send(); return; }
|
// Enter asks; Ctrl/Cmd+Enter breaks the line. The reverse of the usual editor convention,
|
||||||
|
// and right for this box: almost every message here is one line, so the common action
|
||||||
|
// gets the bare key and the rare one gets the modifier. Shift+Enter also breaks a line,
|
||||||
|
// because that is the reflex people arrive with from every other chat box.
|
||||||
|
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
||||||
|
e.preventDefault();
|
||||||
|
const t = e.target;
|
||||||
|
const s = t.selectionStart ?? t.value.length, n = t.selectionEnd ?? s;
|
||||||
|
t.value = t.value.slice(0, s) + '\n' + t.value.slice(n);
|
||||||
|
t.selectionStart = t.selectionEnd = s + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); return; }
|
||||||
|
|
||||||
// Terminal habit: an empty box and Up gets back what you just asked, to edit rather than
|
// Terminal habit: an empty box and Up gets back what you just asked, to edit rather than
|
||||||
// retype. Only when empty, or it would eat cursor movement in a question being written.
|
// retype. Only when empty, or it would eat cursor movement in a question being written.
|
||||||
@@ -2360,7 +2372,8 @@ vv_ai_profiles_script();
|
|||||||
// broke the tab it lives on.
|
// broke the tab it lives on.
|
||||||
function vv_ai_chat_keys(): array {
|
function vv_ai_chat_keys(): array {
|
||||||
return [
|
return [
|
||||||
['keys' => ['Ctrl', 'Enter'], 'what' => 'Ask', 'id' => 'send'],
|
['keys' => ['Enter'], 'what' => 'Ask', 'id' => 'send'],
|
||||||
|
['keys' => ['Ctrl', 'Enter'], 'what' => 'New line', 'id' => 'nl'],
|
||||||
['keys' => ['↑'], 'what' => 'Your last question, to edit', 'id' => 'recall'],
|
['keys' => ['↑'], 'what' => 'Your last question, to edit', 'id' => 'recall'],
|
||||||
['keys' => ['/'], 'what' => 'Command — /help lists them', 'id' => 'slash'],
|
['keys' => ['/'], 'what' => 'Command — /help lists them', 'id' => 'slash'],
|
||||||
['keys' => ['Esc'], 'what' => 'Close a menu, or clear the box', 'id' => 'esc'],
|
['keys' => ['Esc'], 'what' => 'Close a menu, or clear the box', 'id' => 'esc'],
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ function vv_nc_pane_markup(string $prefix, bool $meshDefault = false,
|
|||||||
|
|
||||||
<div style="display:flex;gap:6px;align-items:flex-start;margin-top:8px;flex-wrap:wrap;">
|
<div style="display:flex;gap:6px;align-items:flex-start;margin-top:8px;flex-wrap:wrap;">
|
||||||
<textarea id="vv-nc-text" rows="2" placeholder="Message the mesh…"
|
<textarea id="vv-nc-text" rows="2" placeholder="Message the mesh…"
|
||||||
onkeydown="if((event.ctrlKey||event.metaKey)&&event.key==='Enter')vvNcSend()"
|
onkeydown="vvNcKey(event)"
|
||||||
style="flex:1 1 260px;min-width:0;background:#0d0d0d;border:1px solid #2a2a2a;
|
style="flex:1 1 260px;min-width:0;background:#0d0d0d;border:1px solid #2a2a2a;
|
||||||
color:#ddd;border-radius:4px;padding:6px 8px;font-family:inherit;
|
color:#ddd;border-radius:4px;padding:6px 8px;font-family:inherit;
|
||||||
font-size:12px;resize:vertical;"></textarea>
|
font-size:12px;resize:vertical;"></textarea>
|
||||||
@@ -555,6 +555,21 @@ function vvNcGrow(fromAi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same bargain as the assistant's box, because they are two halves of one card and a key that
|
||||||
|
// sends in one and breaks a line in the other is the kind of difference that costs a message.
|
||||||
|
function vvNcKey(e) {
|
||||||
|
if (e.key !== 'Enter') return;
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
const t = e.target;
|
||||||
|
const s = t.selectionStart ?? t.value.length, n = t.selectionEnd ?? s;
|
||||||
|
t.value = t.value.slice(0, s) + '\n' + t.value.slice(n);
|
||||||
|
t.selectionStart = t.selectionEnd = s + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!e.shiftKey) { e.preventDefault(); vvNcSend(); }
|
||||||
|
}
|
||||||
|
|
||||||
function vvNcEmoji(sel) {
|
function vvNcEmoji(sel) {
|
||||||
const t = document.getElementById('vv-nc-text');
|
const t = document.getElementById('vv-nc-text');
|
||||||
if (t && sel.value) { t.value += sel.value; t.focus(); }
|
if (t && sel.value) { t.value += sel.value; t.focus(); }
|
||||||
|
|||||||
Reference in New Issue
Block a user