From 96f528b9571ce2a0a322f770c40d71305ebd993e Mon Sep 17 00:00:00 2001 From: bal-spec Date: Sun, 19 Apr 2026 12:20:14 -0700 Subject: [PATCH] fix: group chat character pickers always select first character (#14) --- CHANGELOG.md | 7 +++++++ index.js | 55 ++++++++++++++++++++++++++++++++++++++++----------- manifest.json | 2 +- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8fd520..da60777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 2.1.11 + +### Bug Fixes + +- **Fix group chat character pickers always selecting first character**: In group chats, the Consolidate, Reformat, and Memory Manager character pickers silently ignored the user's selection and always operated on the first character. The selected radio button was read after `callGenericPopup` closed and destroyed the popup DOM, so the selector always returned `undefined`, which coerced to index `0`. Fixed by tracking the selection via a delegated `change` listener before the popup closes. Fixes [#14](https://github.com/bal-spec/sillytavern-character-memory/issues/14). +- **Fix Pin always saving to first character in group chats**: The pin handler tried to auto-match the message sender by name, but silently fell back to the first group member whenever the match failed (user messages, name discrepancies, disabled members). Pin now shows an explicit character picker in group chats, pre-selected to the message sender when a match is found. Fixes [#14](https://github.com/bal-spec/sillytavern-character-memory/issues/14). + ## 2.1.10 ### Bug Fixes diff --git a/index.js b/index.js index 24ebcdd..92363d2 100644 --- a/index.js +++ b/index.js @@ -6619,12 +6619,16 @@ async function showMemoryManager() { const count = blocks.reduce((sum, b) => sum + b.bullets.length, 0); return { ...t, count }; })); - const pickerHtml = targetData.map((t, i) => - ``, + const pickerHtml = targetData.map((tgt, i) => + ``, ).join('
'); + let selectedIdx = 0; + $(document).on('change.mmPicker', 'input[name="charMemory_mmTarget"]', function () { + selectedIdx = Number($(this).val()) || 0; + }); const picked = await callGenericPopup(`Select a character to view/edit memories for:

${pickerHtml}`, POPUP_TYPE.CONFIRM); + $(document).off('change.mmPicker'); if (!picked) return; - const selectedIdx = Number($('input[name="charMemory_mmTarget"]:checked').val()) || 0; target = targets[selectedIdx]; } @@ -7096,12 +7100,16 @@ async function consolidateMemories() { if (targets.length === 1) { target = targets[0]; } else { - const pickerHtml = targets.map((t, i) => - ``, + const pickerHtml = targets.map((tgt, i) => + ``, ).join('
'); + let selectedIdx = 0; + $(document).on('change.consolPicker', 'input[name="charMemory_consolTarget"]', function () { + selectedIdx = Number($(this).val()) || 0; + }); const picked = await callGenericPopup(`Select a character to consolidate memories for:

${pickerHtml}`, POPUP_TYPE.CONFIRM); + $(document).off('change.consolPicker'); if (!picked) return; - const selectedIdx = Number($('input[name="charMemory_consolTarget"]:checked').val()) || 0; target = targets[selectedIdx]; } @@ -7533,12 +7541,16 @@ async function reformatMemories() { if (targets.length === 1) { target = targets[0]; } else { - const pickerHtml = targets.map((t, i) => - ``, + const pickerHtml = targets.map((tgt, i) => + ``, ).join('
'); + let selectedIdx = 0; + $(document).on('change.reformatPicker', 'input[name="charMemory_reformatTarget"]', function () { + selectedIdx = Number($(this).val()) || 0; + }); const picked = await callGenericPopup(`Select a character to reformat memories for:

${pickerHtml}`, POPUP_TYPE.CONFIRM); + $(document).off('change.reformatPicker'); if (!picked) return; - const selectedIdx = Number($('input[name="charMemory_reformatTarget"]:checked').val()) || 0; target = targets[selectedIdx]; } @@ -8025,10 +8037,29 @@ async function onPinMemoryClick() { const timestamp = getTimestamp(); const chatId = context.chatId || 'unknown'; - // Find the target matching the message sender (for groups, match by name) const targets = getMemoryTargets(); - const senderName = msg.name; - const target = targets.find(t => t.name === senderName) || targets[0]; + if (targets.length === 0) return; + + // In group chats, show a character picker pre-selected to the message sender + let target; + if (targets.length === 1) { + target = targets[0]; + } else { + const senderName = msg.name; + const senderIdx = targets.findIndex(tgt => tgt.name === senderName); + const defaultIdx = senderIdx >= 0 ? senderIdx : 0; + const pickerHtml = targets.map((tgt, i) => + ``, + ).join('
'); + let selectedIdx = defaultIdx; + $(document).on('change.pinPicker', 'input[name="charMemory_pinTarget"]', function () { + selectedIdx = Number($(this).val()) || 0; + }); + const picked = await callGenericPopup(`Pin memory to which character?

${pickerHtml}`, POPUP_TYPE.CONFIRM); + $(document).off('change.pinPicker'); + if (!picked) return; + target = targets[selectedIdx]; + } if (!target) return; const existingContent = await readMemoriesForCharacter(target.avatar, target.fileName); diff --git a/manifest.json b/manifest.json index 307742a..b18056b 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "js": "index.js", "css": "style.css", "author": "bal-spec", - "version": "2.1.10", + "version": "2.1.11", "homePage": "https://github.com/bal-spec/sillytavern-character-memory", "auto_update": true }