perf: optimize app startup and background lifecycles

This commit is contained in:
inman
2026-08-19 00:56:15 +08:00
parent 31332f6d76
commit 927e13349b
121 changed files with 4359 additions and 1400 deletions

View File

@@ -39,7 +39,7 @@ type WatchDirectory = (
onChange: (filename: string | null) => void,
) => ProjectProgressWatcher;
type ProjectProgressProjectStore = Pick<OpencodeProjectStore, 'listProjects' | 'subscribe'>;
type ProjectProgressProjectStore = Pick<OpencodeProjectStore, 'getActiveProject' | 'subscribe'> & Partial<Pick<OpencodeProjectStore, 'listProjects'>>;
export type ProjectProgressSyncOptions = {
apiBaseUrl?: string;
@@ -159,6 +159,7 @@ export function createProjectProgressSync(
let unsubscribeProjectStore: (() => void) | null = null;
let unsubscribeSession: (() => void) | null = null;
let started = false;
let activeProjectId: string | null = null;
function clearTimer(state: ProjectProgressState): void {
if (state.timer) {
@@ -373,20 +374,21 @@ export function createProjectProgressSync(
async function start(): Promise<void> {
if (started) return;
started = true;
activeProjectId = null;
unsubscribeProjectStore = projectStore.subscribe((change) => {
if (change.type === 'remove') {
disposeProject(change.projectId);
if (activeProjectId === change.projectId) activeProjectId = null;
return;
}
attachProject(change.project);
if (activeProjectId === change.project.id) attachProject(change.project);
});
unsubscribeSession = subscribeWorksSquareSession((session) => {
if (!session) return;
for (const projectId of states.keys()) scheduleProject(projectId, true);
});
const projects = await projectStore.listProjects();
for (const project of projects) attachProject(project);
await activate();
}
function stop(): void {
@@ -398,11 +400,39 @@ export function createProjectProgressSync(
unsubscribeSession = null;
for (const state of states.values()) closeWatcher(state);
states.clear();
activeProjectId = null;
}
async function activate(projectId?: string | null): Promise<void> {
if (!started) return;
let project = await projectStore.getActiveProject();
// A project id is supplied when the renderer just switched projects. Use
// the store's direct lookup list only for that explicit activation (or for
// a single-project legacy store with no persisted active id); never scan
// and watch the full project collection during normal startup.
if (projectId && project?.id !== projectId && projectStore.listProjects) {
project = (await projectStore.listProjects()).find((item) => item.id === projectId) ?? null;
} else if (!project && projectStore.listProjects) {
const projects = await projectStore.listProjects();
project = projects.length === 1 ? projects[0] : null;
}
if (!project || (projectId && project.id !== projectId)) {
for (const state of states.values()) closeWatcher(state);
states.clear();
activeProjectId = null;
return;
}
activeProjectId = project.id;
for (const id of states.keys()) {
if (id !== project.id) disposeProject(id);
}
attachProject(project);
}
return {
start,
stop,
activate,
flushProject: async (projectId: string): Promise<void> => {
const state = states.get(projectId);
if (!state) return;