From 3db747d5185875517109463e41aafe1791e8ebf4 Mon Sep 17 00:00:00 2001 From: liurenfeng94-ops <279598012+liurenfeng94-ops@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:17:49 +0800 Subject: [PATCH] Persist last save per project --- src/appState.ts | 7 +++++- src/projectSettings.ts | 40 +++++++++++++++++++++++++++++++++++ test/project-settings.test.ts | 33 +++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/projectSettings.ts create mode 100644 test/project-settings.test.ts diff --git a/src/appState.ts b/src/appState.ts index b37c324..43967d8 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -8,6 +8,7 @@ import { getTracePanel, isTraceViewAlive, postMessage } from './webview' import { getProjectName, getWorkspacePath } from './storage' import { setStatusBarState } from './statusBar' import { sendTraceDir } from './commands' +import { readProjectSettings, writeProjectSettings } from './projectSettings' export const afterWatches = nextTick @@ -86,7 +87,10 @@ export async function initAppState(extensionContext: vscode.ExtensionContext) { } getSaves(projectPath.value) - saveName.value = 'default' + const projectSettings = readProjectSettings(projectPath.value) + saveName.value = projectSettings.lastSaveName && saveNames.value.includes(projectSettings.lastSaveName) + ? projectSettings.lastSaveName + : 'default' }, name => postMessage({ message: 'projectOpen', name })) watchT('savePath', (path) => { @@ -116,6 +120,7 @@ export async function initAppState(extensionContext: vscode.ExtensionContext) { setStatusBarState('saveName', saveName.value) tracePath.value = join(projectPath.value, name, 'traces') + writeProjectSettings(projectPath.value, { lastSaveName: name }) void sendTraceDir(tracePath.value) }, (name) => { diff --git a/src/projectSettings.ts b/src/projectSettings.ts new file mode 100644 index 0000000..0904b15 --- /dev/null +++ b/src/projectSettings.ts @@ -0,0 +1,40 @@ +import { existsSync, readFileSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' + +export interface ProjectSettings { + lastSaveName?: string +} + +const projectSettingsFileName = 'tracer-project-settings.json' + +export function getProjectSettingsPath(projectPath: string) { + return join(projectPath, projectSettingsFileName) +} + +function parseProjectSettings(value: unknown): ProjectSettings { + if (!value || typeof value !== 'object') + return {} + + const settings = value as Record + + return { + lastSaveName: typeof settings.lastSaveName === 'string' ? settings.lastSaveName : undefined, + } +} + +export function readProjectSettings(projectPath: string): ProjectSettings { + const settingsPath = getProjectSettingsPath(projectPath) + if (!existsSync(settingsPath)) + return {} + + try { + return parseProjectSettings(JSON.parse(readFileSync(settingsPath, 'utf8'))) + } + catch { + return {} + } +} + +export function writeProjectSettings(projectPath: string, settings: ProjectSettings) { + writeFileSync(getProjectSettingsPath(projectPath), `${JSON.stringify(settings, null, 2)}\n`) +} diff --git a/test/project-settings.test.ts b/test/project-settings.test.ts new file mode 100644 index 0000000..830f3c1 --- /dev/null +++ b/test/project-settings.test.ts @@ -0,0 +1,33 @@ +import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { describe, expect, it } from 'vitest' +import { getProjectSettingsPath, readProjectSettings, writeProjectSettings } from '../src/projectSettings' + +function tempProjectPath() { + const path = mkdtempSync(join(tmpdir(), 'tracer-project-settings-')) + mkdirSync(path, { recursive: true }) + return path +} + +describe('project settings', () => { + it('persists the last selected save name per project', () => { + const projectPath = tempProjectPath() + + writeProjectSettings(projectPath, { lastSaveName: 'feature/fast-path' }) + + expect(readProjectSettings(projectPath)).toEqual({ lastSaveName: 'feature/fast-path' }) + }) + + it('falls back to empty settings when the file is missing or invalid', () => { + const projectPath = tempProjectPath() + + expect(readProjectSettings(projectPath)).toEqual({}) + + writeFileSync(getProjectSettingsPath(projectPath), '{not-json') + expect(readProjectSettings(projectPath)).toEqual({}) + + writeFileSync(getProjectSettingsPath(projectPath), JSON.stringify({ lastSaveName: 123 })) + expect(readProjectSettings(projectPath)).toEqual({ lastSaveName: undefined }) + }) +})