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:
@@ -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}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user