perf: optimize app startup and background lifecycles
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user