diff --git a/frontend/src/views/WorkspaceView.vue b/frontend/src/views/WorkspaceView.vue index deef333..798b1bb 100644 --- a/frontend/src/views/WorkspaceView.vue +++ b/frontend/src/views/WorkspaceView.vue @@ -37,7 +37,22 @@ function _storageKey(pid: number) { 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 gridColumns = computed(() => { @@ -102,11 +117,11 @@ function scrollToBottom() { watch(() => chatStore.streamingContent, scrollToBottom); function togglePanel(panel: keyof typeof panelOpen.value) { - // Ensure at least one panel stays open const open = panelOpen.value; const openCount = [open.tasks, open.chat, open.notes].filter(Boolean).length; if (open[panel] && openCount <= 1) return; panelOpen.value[panel] = !panelOpen.value[panel]; + localStorage.setItem(_panelKey(projectId.value), JSON.stringify(panelOpen.value)); } async function sendMessage() { @@ -156,6 +171,9 @@ function resetTextareaHeight() { } onMounted(async () => { + // Restore panel state + panelOpen.value = _loadPanelState(projectId.value); + // Load project info try { project.value = await apiGet(`/api/projects/${projectId.value}`);