mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 23:49:41 +02:00
fix(ui): stop dropping the session name typed in the options modal
Two independent ways a tab description could be typed in and silently lost. 1. Session Options modal (deterministic). The Session Name input saves on blur, and every autosave handler in the modal bails on a null editingSessionId. closeSessionOptions() cleared that id BEFORE hiding the modal, and hiding it is what blurs the input, so the save always ran too late and returned early. Escape and backdrop-click lost the name with no PUT at all; only the X button worked, because mousedown blurs the input before the click handler runs. Fix: blur the focused modal field first, then clear the id. That also covers the auto-compact prompt, which saves on change and had the same fate. 2. Right-click inline rename (racy). The _inlineRenameActive guard from #81 sits in renderSessionTabs() (the scheduler) and _fullRenderSessionTabs(), but not in _renderSessionTabsImmediate() (the debounced executor). A render queued in the ~100ms before the rename opened still fires and the incremental branch rewrites .tab-name's innerHTML, destroying the input mid-keystroke: it commits a truncated name, or, if it lands before the first keystroke, closes the rename so everything typed after goes nowhere. Fix: guard the executor too. finishRename() re-renders on both commit and cancel, so a render dropped there is picked back up. Verified end-to-end against a live server on an isolated instance: all three modal close paths now persist the name, and the rename input survives a render mid-typing. Both regression tests were checked to fail with their fix reverted; the render one was vacuous at first because the synthetic tab sat on <body> instead of inside #sessionTabs, so it now builds the tab in the real container. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3290,6 +3290,13 @@ class CodemanApp {
|
||||
}
|
||||
|
||||
_renderSessionTabsImmediate() {
|
||||
// Same guard as renderSessionTabs()/_fullRenderSessionTabs(): the incremental
|
||||
// branch below rewrites .tab-name's innerHTML, which destroys the inline rename
|
||||
// <input> mid-keystroke. Guarding only the scheduler is not enough: a render
|
||||
// debounced just BEFORE the rename opened still fires ~100ms later and lands
|
||||
// here directly. finishRename() re-renders on both commit and cancel, so a
|
||||
// render dropped here is picked back up when the rename settles.
|
||||
if (this._inlineRenameActive) return;
|
||||
const container = this.$('sessionTabs');
|
||||
const existingTabs = container.querySelectorAll('.session-tab[data-id]');
|
||||
const existingIds = new Set([...existingTabs].map(t => t.dataset.id));
|
||||
|
||||
@@ -848,6 +848,18 @@ Object.assign(CodemanApp.prototype, {
|
||||
},
|
||||
|
||||
closeSessionOptions() {
|
||||
// Commit the field the user was still editing BEFORE editingSessionId is
|
||||
// cleared. The Session Name input saves on blur (and the auto-compact prompt
|
||||
// on change), and every autosave handler bails out on `!this.editingSessionId`.
|
||||
// Hiding the modal blurs the focused input on its own, but that happens after
|
||||
// the id is gone, so Escape / backdrop-click silently dropped what was typed.
|
||||
// (Clicking the X worked only because mousedown blurs the input first.)
|
||||
const modal = document.getElementById('sessionOptionsModal');
|
||||
const focused = document.activeElement;
|
||||
if (focused && modal && modal.contains(focused) && typeof focused.blur === 'function') {
|
||||
focused.blur();
|
||||
}
|
||||
|
||||
this.editingSessionId = null;
|
||||
// Stop run summary auto-refresh if it was running
|
||||
this.stopRunSummaryAutoRefresh();
|
||||
|
||||
Reference in New Issue
Block a user