mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-09 17:29:12 +00:00
feat(web): persist collapsed workspace groups to localStorage (#1045)
This commit is contained in:
parent
c240bfab7d
commit
ac1882fe28
4 changed files with 50 additions and 1 deletions
5
.changeset/web-persist-workspace-collapse.md
Normal file
5
.changeset/web-persist-workspace-collapse.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@moonshot-ai/kimi-code": patch
|
||||
---
|
||||
|
||||
Persist the collapsed state of workspace groups in the web sidebar across page reloads.
|
||||
|
|
@ -7,6 +7,7 @@ import { computed, nextTick, onBeforeUnmount, ref } from 'vue';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import { serverEndpointLabel } from '../api/config';
|
||||
import { copyTextToClipboard } from '../lib/clipboard';
|
||||
import { loadCollapsedWorkspaces, saveCollapsedWorkspaces } from '../lib/storage';
|
||||
import type { Session, WorkspaceGroup as WorkspaceGroupType, WorkspaceView } from '../types';
|
||||
import SessionRow from './SessionRow.vue';
|
||||
import WorkspaceGroup from './WorkspaceGroup.vue';
|
||||
|
|
@ -89,7 +90,7 @@ function onSelectResult(sessionId: string): void {
|
|||
// ---------------------------------------------------------------------------
|
||||
// Collapse groups
|
||||
// ---------------------------------------------------------------------------
|
||||
const collapsedIds = ref<Set<string>>(new Set());
|
||||
const collapsedIds = ref<Set<string>>(new Set(loadCollapsedWorkspaces()));
|
||||
|
||||
function isCollapsed(id: string): boolean {
|
||||
return collapsedIds.value.has(id);
|
||||
|
|
@ -107,6 +108,7 @@ function toggleCollapse(id: string): void {
|
|||
next.add(id);
|
||||
}
|
||||
collapsedIds.value = next;
|
||||
saveCollapsedWorkspaces(next);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const STORAGE_KEYS = {
|
|||
accent: 'kimi-web.accent',
|
||||
colorScheme: 'kimi-web.color-scheme',
|
||||
hiddenWorkspaces: 'kimi-web.hidden-workspaces',
|
||||
collapsedWorkspaces: 'kimi-web.collapsed-workspaces',
|
||||
betaToc: 'kimi-web.beta-toc',
|
||||
notifyOnComplete: 'kimi-web.notify-on-complete',
|
||||
inputHistory: 'kimi-web.input-history',
|
||||
|
|
@ -122,3 +123,18 @@ export function saveUnread(changes: Record<string, boolean>): void {
|
|||
}
|
||||
safeSetString(STORAGE_KEYS.unread, JSON.stringify(merged));
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapsed workspace ids in the sidebar. Persisted as a JSON array of ids so
|
||||
* the fold state of each workspace group survives a page refresh. There is no
|
||||
* server-side source of truth for this UI-only state.
|
||||
*/
|
||||
export function loadCollapsedWorkspaces(): string[] {
|
||||
const parsed = safeGetJson<unknown>(STORAGE_KEYS.collapsedWorkspaces);
|
||||
if (!Array.isArray(parsed)) return [];
|
||||
return parsed.filter((id): id is string => typeof id === 'string');
|
||||
}
|
||||
|
||||
export function saveCollapsedWorkspaces(ids: Iterable<string>): void {
|
||||
safeSetJson(STORAGE_KEYS.collapsedWorkspaces, Array.from(ids));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
loadCollapsedWorkspaces,
|
||||
loadUnread,
|
||||
saveCollapsedWorkspaces,
|
||||
saveUnread,
|
||||
STORAGE_KEYS,
|
||||
draftStorageKey,
|
||||
|
|
@ -169,3 +171,27 @@ describe('loadUnread / saveUnread', () => {
|
|||
expect(loadUnread()).toEqual({ C: true, D: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadCollapsedWorkspaces / saveCollapsedWorkspaces', () => {
|
||||
it('returns an empty array when the key is missing', () => {
|
||||
expect(loadCollapsedWorkspaces()).toEqual([]);
|
||||
});
|
||||
|
||||
it('round-trips the collapsed ids', () => {
|
||||
saveCollapsedWorkspaces(['ws-1', 'ws-2']);
|
||||
expect(loadCollapsedWorkspaces()).toEqual(['ws-1', 'ws-2']);
|
||||
});
|
||||
|
||||
it('accepts any iterable of ids', () => {
|
||||
saveCollapsedWorkspaces(new Set(['ws-1', 'ws-3']));
|
||||
expect(loadCollapsedWorkspaces()).toEqual(['ws-1', 'ws-3']);
|
||||
});
|
||||
|
||||
it('drops non-string entries and returns [] for malformed values', () => {
|
||||
safeSetString(STORAGE_KEYS.collapsedWorkspaces, JSON.stringify(['ws-1', 2, null, 'ws-2']));
|
||||
expect(loadCollapsedWorkspaces()).toEqual(['ws-1', 'ws-2']);
|
||||
|
||||
safeSetString(STORAGE_KEYS.collapsedWorkspaces, JSON.stringify({ ws: true }));
|
||||
expect(loadCollapsedWorkspaces()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue