diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 7cae318..492cfd0 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -1,8 +1,22 @@ import React, { useEffect } from 'react'; import { ActivityBar, Sidebar, Editor, StatusBar, Panel, TabBar, ToastContainer, showToast } from './components'; -import { useAppStore, PostData, MediaData, TaskProgress } from './store'; +import { useAppStore, PostData, MediaData, TaskProgress, TabState } from './store'; import './App.css'; +// Helper to load tabs for a project from localStorage +const TAB_STATE_PREFIX = 'bds-tabs-'; +const loadTabsForProject = (projectId: string): TabState | null => { + try { + const stored = localStorage.getItem(`${TAB_STATE_PREFIX}${projectId}`); + if (stored) { + return JSON.parse(stored) as TabState; + } + } catch (error) { + console.error('Failed to load tab state:', error); + } + return null; +}; + const App: React.FC = () => { const { setPosts, @@ -24,6 +38,7 @@ const App: React.FC = () => { setActiveView, setSelectedPost, openTab, + restoreTabState, } = useAppStore(); // Load initial data @@ -32,7 +47,7 @@ const App: React.FC = () => { setLoading(true); try { // First, get active project to set the correct context in backend engines - await window.electronAPI?.projects.getActive(); + const activeProject = await window.electronAPI?.projects.getActive(); // Load posts (now with correct project context, limited to 500) const postsResult = await window.electronAPI?.posts.getAll({ limit: 500, offset: 0 }); @@ -46,6 +61,14 @@ const App: React.FC = () => { if (media) { setMedia(media as MediaData[]); } + + // Restore tabs for the active project + if (activeProject && (activeProject as { id: string }).id) { + const savedTabState = loadTabsForProject((activeProject as { id: string }).id); + if (savedTabState) { + restoreTabState(savedTabState); + } + } // Re-configure Dropbox sync from saved credentials const savedCreds = localStorage.getItem('bds-credentials'); @@ -89,6 +112,25 @@ const App: React.FC = () => { loadData(); }, []); + // Save tabs when window closes + useEffect(() => { + const saveTabsOnUnload = () => { + const state = useAppStore.getState(); + const projectId = state.activeProject?.id; + if (projectId) { + const tabState = state.getTabState(); + try { + localStorage.setItem(`${TAB_STATE_PREFIX}${projectId}`, JSON.stringify(tabState)); + } catch (error) { + console.error('Failed to save tab state on unload:', error); + } + } + }; + + window.addEventListener('beforeunload', saveTabsOnUnload); + return () => window.removeEventListener('beforeunload', saveTabsOnUnload); + }, []); + // Set up event listeners for real-time updates useEffect(() => { const unsubscribers: Array<() => void> = []; diff --git a/src/renderer/components/ProjectSelector/ProjectSelector.tsx b/src/renderer/components/ProjectSelector/ProjectSelector.tsx index 303ada3..0c3faa0 100644 --- a/src/renderer/components/ProjectSelector/ProjectSelector.tsx +++ b/src/renderer/components/ProjectSelector/ProjectSelector.tsx @@ -1,10 +1,33 @@ import React, { useState, useRef, useEffect } from 'react'; -import { useAppStore, ProjectData, PostData, MediaData } from '../../store'; +import { useAppStore, ProjectData, PostData, MediaData, TabState } from '../../store'; import { showToast } from '../Toast'; import './ProjectSelector.css'; +// Helper functions for project-specific tab persistence +const TAB_STATE_PREFIX = 'bds-tabs-'; + +const saveTabsForProject = (projectId: string, tabState: TabState): void => { + try { + localStorage.setItem(`${TAB_STATE_PREFIX}${projectId}`, JSON.stringify(tabState)); + } catch (error) { + console.error('Failed to save tab state:', error); + } +}; + +const loadTabsForProject = (projectId: string): TabState | null => { + try { + const stored = localStorage.getItem(`${TAB_STATE_PREFIX}${projectId}`); + if (stored) { + return JSON.parse(stored) as TabState; + } + } catch (error) { + console.error('Failed to load tab state:', error); + } + return null; +}; + export const ProjectSelector: React.FC = () => { - const { projects, activeProject, setProjects, setActiveProject, setPosts, setMedia, setSelectedPost, setSelectedMedia, removeProject } = useAppStore(); + const { projects, activeProject, setProjects, setActiveProject, setPosts, setMedia, setSelectedPost, setSelectedMedia, removeProject, getTabState, restoreTabState, clearTabs } = useAppStore(); const [isOpen, setIsOpen] = useState(false); const [showCreateModal, setShowCreateModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -51,6 +74,15 @@ export const ProjectSelector: React.FC = () => { } try { + // Save current project's tab state before switching + if (activeProject) { + const currentTabState = getTabState(); + saveTabsForProject(activeProject.id, currentTabState); + } + + // Clear tabs for the transition + clearTabs(); + const updatedProject = await window.electronAPI?.projects.setActive(project.id); if (updatedProject) { setActiveProject(updatedProject as ProjectData); @@ -70,6 +102,12 @@ export const ProjectSelector: React.FC = () => { } if (mediaResult) setMedia(mediaResult as MediaData[]); + // Restore tabs for the new project + const savedTabState = loadTabsForProject(project.id); + if (savedTabState) { + restoreTabState(savedTabState); + } + showToast.success(`Switched to ${project.name}`); } } catch (error) {