Persist workspace panel open/closed state per project

Panel state is saved to localStorage as workspace_panels_{projectId} on
every toggle and restored on mount. Each project remembers its own layout
independently. Fallback guard ensures at least one panel is always open
after restore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 20:47:35 -05:00
parent fe63a732df
commit de7709039a
+20 -2
View File
@@ -37,7 +37,22 @@ function _storageKey(pid: number) {
return `workspace_conv_${pid}`; return `workspace_conv_${pid}`;
} }
// Panel collapse state // Panel collapse state — persisted per project
function _panelKey(pid: number) { return `workspace_panels_${pid}`; }
function _loadPanelState(pid: number) {
try {
const raw = localStorage.getItem(_panelKey(pid));
if (raw) {
const saved = JSON.parse(raw);
// Ensure at least one panel is open after restore
if (!saved.tasks && !saved.chat && !saved.notes) saved.chat = true;
return saved as { tasks: boolean; chat: boolean; notes: boolean };
}
} catch { /* ignore */ }
return { tasks: true, chat: true, notes: true };
}
const panelOpen = ref({ tasks: true, chat: true, notes: true }); const panelOpen = ref({ tasks: true, chat: true, notes: true });
const gridColumns = computed(() => { const gridColumns = computed(() => {
@@ -102,11 +117,11 @@ function scrollToBottom() {
watch(() => chatStore.streamingContent, scrollToBottom); watch(() => chatStore.streamingContent, scrollToBottom);
function togglePanel(panel: keyof typeof panelOpen.value) { function togglePanel(panel: keyof typeof panelOpen.value) {
// Ensure at least one panel stays open
const open = panelOpen.value; const open = panelOpen.value;
const openCount = [open.tasks, open.chat, open.notes].filter(Boolean).length; const openCount = [open.tasks, open.chat, open.notes].filter(Boolean).length;
if (open[panel] && openCount <= 1) return; if (open[panel] && openCount <= 1) return;
panelOpen.value[panel] = !panelOpen.value[panel]; panelOpen.value[panel] = !panelOpen.value[panel];
localStorage.setItem(_panelKey(projectId.value), JSON.stringify(panelOpen.value));
} }
async function sendMessage() { async function sendMessage() {
@@ -156,6 +171,9 @@ function resetTextareaHeight() {
} }
onMounted(async () => { onMounted(async () => {
// Restore panel state
panelOpen.value = _loadPanelState(projectId.value);
// Load project info // Load project info
try { try {
project.value = await apiGet<Project>(`/api/projects/${projectId.value}`); project.value = await apiGet<Project>(`/api/projects/${projectId.value}`);