mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 16: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() {
|
renderSessionTabs() {
|
||||||
|
// Don't re-render while user is typing in the inline rename input
|
||||||
|
if (this._inlineRenameActive) return;
|
||||||
this._debouncedCall('sessionTabs', this._renderSessionTabsImmediate);
|
this._debouncedCall('sessionTabs', this._renderSessionTabsImmediate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1988,6 +1990,7 @@ class CodemanApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_fullRenderSessionTabs() {
|
_fullRenderSessionTabs() {
|
||||||
|
if (this._inlineRenameActive) return;
|
||||||
const container = this.$('sessionTabs');
|
const container = this.$('sessionTabs');
|
||||||
|
|
||||||
// Clean up any orphaned dropdowns before re-rendering
|
// 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}"]`);
|
const tabName = document.querySelector(`.tab-name[data-session-id="${sessionId}"]`);
|
||||||
if (!tabName) return;
|
if (!tabName) return;
|
||||||
|
|
||||||
|
// Prevent tab re-renders from destroying the input while renaming
|
||||||
|
this._inlineRenameActive = true;
|
||||||
|
|
||||||
const currentName = this.getSessionName(session);
|
const currentName = this.getSessionName(session);
|
||||||
const parsed = parseSessionPrefix(session.name);
|
const parsed = parseSessionPrefix(session.name);
|
||||||
const originalContent = tabName.textContent;
|
const originalContent = tabName.textContent;
|
||||||
|
// Clear existing content to make room for the input element
|
||||||
tabName.textContent = '';
|
tabName.textContent = '';
|
||||||
tabName.innerHTML = '';
|
while (tabName.firstChild) tabName.removeChild(tabName.firstChild);
|
||||||
|
|
||||||
// If prefix detected, show it as non-editable label
|
// If prefix detected, show it as non-editable label
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
@@ -938,6 +942,8 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
input.select();
|
input.select();
|
||||||
|
|
||||||
const finishRename = async () => {
|
const finishRename = async () => {
|
||||||
|
if (!this._inlineRenameActive) return; // prevent double-fire
|
||||||
|
this._inlineRenameActive = false;
|
||||||
const suffix = input.value.trim();
|
const suffix = input.value.trim();
|
||||||
let fullName;
|
let fullName;
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
@@ -959,6 +965,8 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
this.showToast('Failed to rename', 'error');
|
this.showToast('Failed to rename', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Re-render tabs to restore full tab structure
|
||||||
|
this.renderSessionTabs();
|
||||||
};
|
};
|
||||||
|
|
||||||
input.addEventListener('blur', finishRename);
|
input.addEventListener('blur', finishRename);
|
||||||
|
|||||||
Reference in New Issue
Block a user