make it a class

This commit is contained in:
Kiril Videlov 2023-07-08 23:15:08 +02:00 committed by Kiril Videlov
parent e4c1329f51
commit 933da5588a
4 changed files with 101 additions and 98 deletions

View File

@ -1,4 +1,4 @@
import type { Refreshable } from './branchStores';
import type { Refreshable } from './BranchStoresCache';
import type { Readable } from '@square/svelte-store';
import type { Loadable } from 'svelte-loadable-store';
import type { Branch, BranchData, Target } from './types';

View File

@ -0,0 +1,93 @@
import { writable, type Loadable, Value } from 'svelte-loadable-store';
import type { Readable } from '@square/svelte-store';
import { git } from '$lib/api/ipc';
import { stores } from '$lib';
import type { Branch, BranchData, Target } from './types';
import * as ipc from './ipc';
export interface Refreshable {
refresh(): Promise<void | object>;
}
export class BranchStoresCache {
virtualBranchStores: Map<string, Refreshable & Readable<Loadable<Branch[]>>> = new Map();
remoteBranchStores: Map<string, Refreshable & Readable<Loadable<BranchData[]>>> = new Map();
targetBranchStores: Map<string, Readable<Loadable<Target>>> = new Map();
getVirtualBranchStore(projectId: string) {
const cachedStore = this.virtualBranchStores.get(projectId);
if (cachedStore) {
return cachedStore;
}
const writableStore = writable(ipc.listVirtualBranches({ projectId }), (set) => {
stores.sessions({ projectId }).subscribe((sessions) => {
if (sessions.isLoading) return;
if (Value.isError(sessions.value)) return;
const lastSession = sessions.value.at(-1);
if (!lastSession) return;
return stores.deltas({ projectId, sessionId: lastSession.id }).subscribe(() => {
ipc.listVirtualBranches({ projectId }).then(set);
});
});
});
const refreshableStore = {
subscribe: writableStore.subscribe,
refresh: async () => {
const newBranches = await ipc.listVirtualBranches({ projectId });
return writableStore.set({ isLoading: false, value: newBranches });
}
};
this.virtualBranchStores.set(projectId, refreshableStore);
return refreshableStore;
}
getRemoteBranchStore(projectId: string) {
const cachedStore = this.remoteBranchStores.get(projectId);
if (cachedStore) {
return cachedStore;
}
const writableStore = writable(ipc.getRemoteBranchesData({ projectId }), (set) => {
git.fetches.subscribe({ projectId }, () => {
ipc.getRemoteBranchesData({ projectId }).then((branches) => {
set(sortBranchData(branches));
});
});
});
const refreshableStore = {
subscribe: writableStore.subscribe,
refresh: async () => {
const newRemoteBranches = await ipc.getRemoteBranchesData({ projectId });
return writableStore.set({ isLoading: false, value: newRemoteBranches });
}
};
this.remoteBranchStores.set(projectId, refreshableStore);
return refreshableStore;
}
getTargetBranchStore(projectId: string) {
const cachedStore = this.targetBranchStores.get(projectId);
if (cachedStore) {
return cachedStore;
}
const writableStore = writable(ipc.getTargetData({ projectId }), (set) => {
git.fetches.subscribe({ projectId }, () => {
ipc.getTargetData({ projectId }).then((newTarget) => {
set(newTarget);
});
});
});
const refreshableStore = {
subscribe: writableStore.subscribe,
refresh: async () => {
const newTarget = await ipc.getTargetData({ projectId });
return writableStore.set({ isLoading: false, value: newTarget });
}
};
this.targetBranchStores.set(projectId, refreshableStore);
return refreshableStore;
}
}
function sortBranchData(branchData: BranchData[]): BranchData[] {
return branchData.sort((a, b) => b.lastCommitTs - a.lastCommitTs);
}

View File

@ -1,90 +0,0 @@
import { writable, type Loadable, Value } from 'svelte-loadable-store';
import type { Readable } from '@square/svelte-store';
import { git } from '$lib/api/ipc';
import { stores } from '$lib';
import type { Branch, BranchData, Target } from './types';
import * as ipc from './ipc';
export interface Refreshable {
refresh(): Promise<void | object>;
}
const virtualBranchStores: Map<string, Refreshable & Readable<Loadable<Branch[]>>> = new Map();
const remoteBranchStores: Map<string, Refreshable & Readable<Loadable<BranchData[]>>> = new Map();
const targetBranchStores: Map<string, Readable<Loadable<Target>>> = new Map();
export function getVirtualBranchStore(projectId: string) {
const cachedStore = virtualBranchStores.get(projectId);
if (cachedStore) {
return cachedStore;
}
const writableStore = writable(ipc.listVirtualBranches({ projectId }), (set) => {
stores.sessions({ projectId }).subscribe((sessions) => {
if (sessions.isLoading) return;
if (Value.isError(sessions.value)) return;
const lastSession = sessions.value.at(-1);
if (!lastSession) return;
return stores.deltas({ projectId, sessionId: lastSession.id }).subscribe(() => {
ipc.listVirtualBranches({ projectId }).then(set);
});
});
});
const refreshableStore = {
subscribe: writableStore.subscribe,
refresh: async () => {
const newBranches = await ipc.listVirtualBranches({ projectId });
return writableStore.set({ isLoading: false, value: newBranches });
}
};
virtualBranchStores.set(projectId, refreshableStore);
return refreshableStore;
}
export function getRemoteBranchStore(projectId: string) {
const cachedStore = remoteBranchStores.get(projectId);
if (cachedStore) {
return cachedStore;
}
const writableStore = writable(ipc.getRemoteBranchesData({ projectId }), (set) => {
git.fetches.subscribe({ projectId }, () => {
ipc.getRemoteBranchesData({ projectId }).then((branches) => {
set(sortBranchData(branches));
});
});
});
const refreshableStore = {
subscribe: writableStore.subscribe,
refresh: async () => {
const newRemoteBranches = await ipc.getRemoteBranchesData({ projectId });
return writableStore.set({ isLoading: false, value: newRemoteBranches });
}
};
remoteBranchStores.set(projectId, refreshableStore);
return refreshableStore;
}
export function getTargetBranchStore(projectId: string) {
const cachedStore = targetBranchStores.get(projectId);
if (cachedStore) {
return cachedStore;
}
const writableStore = writable(ipc.getTargetData({ projectId }), (set) => {
git.fetches.subscribe({ projectId }, () => {
ipc.getTargetData({ projectId }).then((newTarget) => {
set(newTarget);
});
});
});
const refreshableStore = {
subscribe: writableStore.subscribe,
refresh: async () => {
const newTarget = await ipc.getTargetData({ projectId });
return writableStore.set({ isLoading: false, value: newTarget });
}
};
targetBranchStores.set(projectId, refreshableStore);
return refreshableStore;
}
function sortBranchData(branchData: BranchData[]): BranchData[] {
return branchData.sort((a, b) => b.lastCommitTs - a.lastCommitTs);
}

View File

@ -1,12 +1,12 @@
/**
* Virtual Branch feature package (experiment)
*
* There are three interesting data types coming from the IPC api:
* There are three interesting data types coming from the rust IPC api:
* - Branch, representing a virtual branch
* - BranchData, representing a remote branch
* - Target, representing a target remote branch
*
* There are thee respective functions for getting reactive stores for those types:
* The three types are obtained as reactive stores from the BranchStoresCache's methods:
* - getVirtualBranchStore - List of Branch (virtual branches)
* - getRemoteBranchStore - List of BranchData (remote branches)
* - getTargetBranchStore - Target (sinle target branch)
@ -14,12 +14,12 @@
* BranchController is a class where all virtual branch operations are performed
* This class gets the three stores injected at construction so that any related updates can be peformed
*
* Usage:
* Note to self:
*
* - Create the three relevant stores at the top level (where projects are listed),
* so that it can take advantage of caching, making project navigation quicker.
* - Create the BranchController at the level of a specific project and inject it to components that need it
* - Create the BranchStoresCacheat the top level (where projects are listed),
* so that it can take advantage of caching, making project navigation quicker.
* - Create the BranchController at the level of a specific project and inject it to components that need it.
*/
export type { Branch, File, Hunk, Commit, BranchData, Target } from './types';
export { getVirtualBranchStore, getRemoteBranchStore, getTargetBranchStore } from './branchStores';
export { BranchStoresCache } from './BranchStoresCache';
export { BranchController } from './BranchController';