From b82837aa5f29d35d3a084a9c44e396776c89d561 Mon Sep 17 00:00:00 2001 From: uroma Date: Thu, 22 Jan 2026 12:40:31 +0000 Subject: [PATCH] Fix tab persistence in Claude IDE - persist closed tabs to localStorage Implement localStorage persistence for closed session and project tabs. When users close tabs, they now remain closed after page refresh. Changes: - session-tabs.js: Add closedSessions tracking with localStorage - project-manager.js: Add closedProjects tracking with localStorage - Filter out closed tabs on load - Persist state whenever tabs are closed Fixes issue where closed tabs would reappear on page refresh. Co-Authored-By: Claude Opus 4.5 --- public/claude-ide/project-manager.js | 49 ++++++++++++++++++++++++++-- public/claude-ide/session-tabs.js | 42 ++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/public/claude-ide/project-manager.js b/public/claude-ide/project-manager.js index 7c09cabf..2947919c 100644 --- a/public/claude-ide/project-manager.js +++ b/public/claude-ide/project-manager.js @@ -22,6 +22,8 @@ class ProjectManager { this.activeProjectId = null; this.activeSessionId = null; this.initialized = false; + this.closedProjects = new Set(); // Track closed project IDs + this.STORAGE_KEY = 'claude_ide_closed_projects'; } /** @@ -31,6 +33,7 @@ class ProjectManager { if (this.initialized) return; console.log('[ProjectManager] Initializing...'); + this.loadClosedProjects(); await this.loadProjects(); this.renderProjectTabs(); this.initialized = true; @@ -44,6 +47,36 @@ class ProjectManager { console.log('[ProjectManager] Initialized with', this.projects.size, 'projects'); } + /** + * Load closed projects from localStorage + */ + loadClosedProjects() { + try { + const stored = localStorage.getItem(this.STORAGE_KEY); + if (stored) { + const closedIds = JSON.parse(stored); + this.closedProjects = new Set(closedIds); + console.log('[ProjectManager] Loaded', this.closedProjects.size, 'closed projects from storage'); + } + } catch (error) { + console.error('[ProjectManager] Error loading closed projects:', error); + this.closedProjects = new Set(); + } + } + + /** + * Save closed projects to localStorage + */ + saveClosedProjects() { + try { + const closedIds = Array.from(this.closedProjects); + localStorage.setItem(this.STORAGE_KEY, JSON.stringify(closedIds)); + console.log('[ProjectManager] Saved', closedIds.length, 'closed projects to storage'); + } catch (error) { + console.error('[ProjectManager] Error saving closed projects:', error); + } + } + /** * Load all sessions and organize them by project */ @@ -97,8 +130,16 @@ class ProjectManager { } }); - this.projects = grouped; - console.log('[ProjectManager] Loaded', this.projects.size, 'projects'); + // Filter out closed projects + const filtered = new Map(); + grouped.forEach((project, key) => { + if (!this.closedProjects.has(project.id)) { + filtered.set(key, project); + } + }); + + this.projects = filtered; + console.log('[ProjectManager] Loaded', this.projects.size, 'projects (filtered out', grouped.size - this.projects.size, 'closed)'); } catch (error) { console.error('[ProjectManager] Error loading projects:', error); @@ -434,6 +475,10 @@ class ProjectManager { console.log('[ProjectManager] Closing project:', projectId); + // Add to closed projects set and persist + this.closedProjects.add(projectId); + this.saveClosedProjects(); + // Remove project from map this.projects.delete(projectKey); diff --git a/public/claude-ide/session-tabs.js b/public/claude-ide/session-tabs.js index 37fd0f29..cad828c2 100644 --- a/public/claude-ide/session-tabs.js +++ b/public/claude-ide/session-tabs.js @@ -21,6 +21,8 @@ class SessionTabs { this.sessions = []; this.activeSessionId = null; this.initialized = false; + this.closedSessions = new Set(); // Track closed session IDs + this.STORAGE_KEY = 'claude_ide_closed_sessions'; } /** @@ -30,16 +32,48 @@ class SessionTabs { if (this.initialized) return; console.log('[SessionTabs] Initializing...'); + this.loadClosedSessions(); this.render(); this.initialized = true; } + /** + * Load closed sessions from localStorage + */ + loadClosedSessions() { + try { + const stored = localStorage.getItem(this.STORAGE_KEY); + if (stored) { + const closedIds = JSON.parse(stored); + this.closedSessions = new Set(closedIds); + console.log('[SessionTabs] Loaded', this.closedSessions.size, 'closed sessions from storage'); + } + } catch (error) { + console.error('[SessionTabs] Error loading closed sessions:', error); + this.closedSessions = new Set(); + } + } + + /** + * Save closed sessions to localStorage + */ + saveClosedSessions() { + try { + const closedIds = Array.from(this.closedSessions); + localStorage.setItem(this.STORAGE_KEY, JSON.stringify(closedIds)); + console.log('[SessionTabs] Saved', closedIds.length, 'closed sessions to storage'); + } catch (error) { + console.error('[SessionTabs] Error saving closed sessions:', error); + } + } + /** * Set sessions for current project */ setSessions(sessions) { - this.sessions = sessions || []; - console.log('[SessionTabs] Set', this.sessions.length, 'sessions'); + // Filter out closed sessions + this.sessions = (sessions || []).filter(s => !this.closedSessions.has(s.id)); + console.log('[SessionTabs] Set', this.sessions.length, 'sessions (filtered out', (sessions || []).length - this.sessions.length, 'closed)'); } /** @@ -191,6 +225,10 @@ class SessionTabs { console.log('[SessionTabs] Closing session:', sessionId); + // Add to closed sessions set and persist + this.closedSessions.add(sessionId); + this.saveClosedSessions(); + // Note: This just removes the tab from view // The session still exists on the server this.sessions = this.sessions.filter(s => s.id !== sessionId);