mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
fix(client): preserve inline rename input across tab re-renders (#81)
When the inline session-rename input is open, any incoming SSE event that triggers renderSessionTabs() (a sibling session updating, a hook firing, a status change) destroys the input element mid-keystroke and the user loses what they were typing. Add a _inlineRenameActive flag that: - guards the two render paths (renderSessionTabs and _fullRenderSessionTabs) so they bail out early while a rename is in progress; - is set true when the inline input mounts (session-ui.js); - is cleared in finishRename, which then explicitly calls renderSessionTabs to restore the normal tab structure. Also add a re-entrance guard at the top of finishRename so the blur event and the Enter keydown do not both fire it (was a latent double-call). Drive-by: replace tabName.innerHTML = "" with explicit child removal. The preceding textContent = "" already clears the element; this avoids an innerHTML write on a node that takes user-supplied content on the next line. Follow-up to the inline-rename feature cherry-picked from #60. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
41a82fcf02
commit
eade261763
@@ -1844,6 +1844,8 @@ class CodemanApp {
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
renderSessionTabs() {
|
||||
// Don't re-render while user is typing in the inline rename input
|
||||
if (this._inlineRenameActive) return;
|
||||
this._debouncedCall('sessionTabs', this._renderSessionTabsImmediate);
|
||||
}
|
||||
|
||||
@@ -1988,6 +1990,7 @@ class CodemanApp {
|
||||
}
|
||||
|
||||
_fullRenderSessionTabs() {
|
||||
if (this._inlineRenameActive) return;
|
||||
const container = this.$('sessionTabs');
|
||||
|
||||
// Clean up any orphaned dropdowns before re-rendering
|
||||
|
||||
@@ -912,11 +912,15 @@ Object.assign(CodemanApp.prototype, {
|
||||
const tabName = document.querySelector(`.tab-name[data-session-id="${sessionId}"]`);
|
||||
if (!tabName) return;
|
||||
|
||||
// Prevent tab re-renders from destroying the input while renaming
|
||||
this._inlineRenameActive = true;
|
||||
|
||||
const currentName = this.getSessionName(session);
|
||||
const parsed = parseSessionPrefix(session.name);
|
||||
const originalContent = tabName.textContent;
|
||||
// Clear existing content to make room for the input element
|
||||
tabName.textContent = '';
|
||||
tabName.innerHTML = '';
|
||||
while (tabName.firstChild) tabName.removeChild(tabName.firstChild);
|
||||
|
||||
// If prefix detected, show it as non-editable label
|
||||
if (parsed) {
|
||||
@@ -938,6 +942,8 @@ Object.assign(CodemanApp.prototype, {
|
||||
input.select();
|
||||
|
||||
const finishRename = async () => {
|
||||
if (!this._inlineRenameActive) return; // prevent double-fire
|
||||
this._inlineRenameActive = false;
|
||||
const suffix = input.value.trim();
|
||||
let fullName;
|
||||
if (parsed) {
|
||||
@@ -959,6 +965,8 @@ Object.assign(CodemanApp.prototype, {
|
||||
this.showToast('Failed to rename', 'error');
|
||||
}
|
||||
}
|
||||
// Re-render tabs to restore full tab structure
|
||||
this.renderSessionTabs();
|
||||
};
|
||||
|
||||
input.addEventListener('blur', finishRename);
|
||||
|
||||
Reference in New Issue
Block a user