mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2025-01-02 14:31:50 +03:00
chore: use Partial<Record<..>> for better type checking
This commit is contained in:
parent
49dfcace64
commit
9d99a4aad8
@ -18,7 +18,7 @@ export function subscribe(
|
||||
return listen(`project://${params.projectId}/git/activity`, () => callback(params));
|
||||
}
|
||||
|
||||
const stores: Record<string, WritableLoadable<Activity[]>> = {};
|
||||
const stores: Partial<Record<string, WritableLoadable<Activity[]>>> = {};
|
||||
|
||||
export function getActivitiesStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
|
@ -3,13 +3,15 @@ import { asyncWritable, type WritableLoadable } from '@square/svelte-store';
|
||||
import * as activities from './activities';
|
||||
import * as sessions from '../ipc/sessions';
|
||||
|
||||
const list = (params: { projectId: string; contextLines?: number }) =>
|
||||
invoke<Record<string, string>>('git_wd_diff', {
|
||||
type Diffs = Partial<Record<string, string>>;
|
||||
|
||||
const list = (params: { projectId: string; contextLines?: number }): Promise<Diffs> =>
|
||||
invoke('git_wd_diff', {
|
||||
projectId: params.projectId,
|
||||
contextLines: params.contextLines ?? 10000
|
||||
});
|
||||
|
||||
const stores: Record<string, WritableLoadable<Record<string, string>>> = {};
|
||||
const stores: Partial<Record<string, WritableLoadable<Diffs>>> = {};
|
||||
|
||||
export function getDiffsStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
|
@ -14,10 +14,11 @@ export function subscribe(
|
||||
);
|
||||
}
|
||||
|
||||
const stores: Record<string, WritableLoadable<string>> = {};
|
||||
const stores: Partial<Record<string, WritableLoadable<string>>> = {};
|
||||
|
||||
export function getHeadStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
export function getHeadStore(params: { projectId: string }): WritableLoadable<string> {
|
||||
const cached = stores[params.projectId];
|
||||
if (cached) return cached;
|
||||
const store = asyncWritable([], () =>
|
||||
get(params).then((head) => head.replace('refs/heads/', ''))
|
||||
);
|
||||
|
@ -18,14 +18,17 @@ export function isUnstaged(status: Status): status is { unstaged: FileStatus } {
|
||||
return 'unstaged' in status && status.unstaged !== null;
|
||||
}
|
||||
|
||||
export function list(params: { projectId: string }) {
|
||||
return invoke<Record<string, Status>>('git_status', params);
|
||||
export function list(params: { projectId: string }): Promise<Statuses> {
|
||||
return invoke('git_status', params);
|
||||
}
|
||||
|
||||
const stores: Record<string, WritableLoadable<Record<string, Status>>> = {};
|
||||
type Statuses = Partial<Record<string, Status>>;
|
||||
|
||||
export function getStatusStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
const stores: Partial<Record<string, WritableLoadable<Statuses>>> = {};
|
||||
|
||||
export function getStatusStore(params: { projectId: string }): WritableLoadable<Statuses> {
|
||||
const cached = stores[params.projectId];
|
||||
if (cached) return cached;
|
||||
const store = asyncWritable([], () => list(params));
|
||||
sessions.subscribe(params, () => list(params).then(store.set));
|
||||
activities.subscribe(params, () => list(params).then(store.set));
|
||||
|
@ -15,8 +15,14 @@ export function isInsert(operation: Operation): operation is OperationInsert {
|
||||
|
||||
export type Delta = { timestampMs: number; operations: Operation[] };
|
||||
|
||||
export async function list(params: { projectId: string; sessionId: string; paths?: string[] }) {
|
||||
return invoke<Record<string, Delta[]>>('list_deltas', params);
|
||||
type Deltas = Partial<Record<string, Delta[]>>;
|
||||
|
||||
export async function list(params: {
|
||||
projectId: string;
|
||||
sessionId: string;
|
||||
paths?: string[];
|
||||
}): Promise<Deltas> {
|
||||
return invoke('list_deltas', params);
|
||||
}
|
||||
|
||||
export function subscribe(
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { invoke, listen } from '$lib/ipc';
|
||||
|
||||
export async function list(params: { projectId: string; sessionId: string; paths?: string[] }) {
|
||||
return invoke<Record<string, string>>('list_session_files', params);
|
||||
return invoke<Partial<Record<string, string>>>('list_session_files', params);
|
||||
}
|
||||
|
||||
export function subscribe(
|
||||
|
@ -2,7 +2,8 @@
|
||||
import { collapse } from '$lib/paths';
|
||||
import { isStaged, isUnstaged, type Status } from '$lib/api/git/statuses';
|
||||
|
||||
export let statuses: Record<string, Status>;
|
||||
export let statuses: Partial<Record<string, Status>>;
|
||||
$: pairs = Object.entries(statuses) as [string, Status][];
|
||||
</script>
|
||||
|
||||
<div>
|
||||
@ -23,7 +24,7 @@
|
||||
<ul
|
||||
class="rounded border border-yellow-400 bg-yellow-500 p-2 font-mono text-[12px] text-yellow-900"
|
||||
>
|
||||
{#each Object.entries(statuses) as [path, status]}
|
||||
{#each pairs as [path, status]}
|
||||
<li class="flex w-full gap-2">
|
||||
<div class="flex w-[3ch] justify-between font-semibold">
|
||||
<span>
|
||||
|
@ -2,10 +2,13 @@ import { writable, type Loadable, derived, Loaded } from 'svelte-loadable-store'
|
||||
import * as bookmarks from '$lib/api/ipc/bookmarks';
|
||||
import { get as getValue, type Readable } from '@square/svelte-store';
|
||||
|
||||
const stores: Record<string, Readable<Loadable<bookmarks.Bookmark[]>>> = {};
|
||||
const stores: Partial<Record<string, Readable<Loadable<bookmarks.Bookmark[]>>>> = {};
|
||||
|
||||
export function getBookmarksStore(params: { projectId: string }) {
|
||||
if (params.projectId in stores) return stores[params.projectId];
|
||||
export function getBookmarksStore(params: {
|
||||
projectId: string;
|
||||
}): Readable<Loadable<bookmarks.Bookmark[]>> {
|
||||
const cached = stores[params.projectId];
|
||||
if (cached) return cached;
|
||||
|
||||
const store = writable(bookmarks.list(params), (set) => {
|
||||
const unsubscribe = bookmarks.subscribe(params, (bookmark) => {
|
||||
|
@ -3,7 +3,7 @@ import * as deltas from '$lib/api/ipc/deltas';
|
||||
import { get, type Writable } from '@square/svelte-store';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
|
||||
export interface DeltasStore extends Writable<Loadable<Record<string, Delta[]>>> {
|
||||
export interface DeltasStore extends Writable<Loadable<Partial<Record<string, Delta[]>>>> {
|
||||
subscribeStream(sessionId: string): () => void;
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ export function getDeltasStore(params: { projectId: string; sessionId: string })
|
||||
return store;
|
||||
}
|
||||
export function getDeltasStore2(projectId: string): DeltasStore {
|
||||
const store = writable<Record<string, Delta[]>>();
|
||||
const store = writable<Partial<Record<string, Delta[]>>>();
|
||||
const subscribe = (sessionId: string) => {
|
||||
const combinedParams = { sessionId, projectId };
|
||||
deltas.list(combinedParams).then((results) => {
|
||||
@ -30,14 +30,11 @@ export function getDeltasStore2(projectId: string): DeltasStore {
|
||||
if (Loaded.isValue(result)) store.set(result);
|
||||
});
|
||||
} else {
|
||||
oldValue;
|
||||
store.set({
|
||||
isLoading: false,
|
||||
value: {
|
||||
...oldValue.value,
|
||||
[filePath]: oldValue.value[filePath]
|
||||
? [...oldValue.value[filePath], ...newDeltas]
|
||||
: newDeltas
|
||||
[filePath]: [...(oldValue.value[filePath] || []), ...newDeltas]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2,11 +2,17 @@ import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import * as files from '$lib/api/ipc/files';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
const stores: Record<string, Readable<Loadable<Record<string, string>>>> = {};
|
||||
type Files = Partial<Record<string, string>>;
|
||||
|
||||
export function getFilesStore(params: { projectId: string; sessionId: string }) {
|
||||
const stores: Partial<Record<string, Readable<Loadable<Files>>>> = {};
|
||||
|
||||
export function getFilesStore(params: {
|
||||
projectId: string;
|
||||
sessionId: string;
|
||||
}): Readable<Loadable<Files>> {
|
||||
const key = `${params.projectId}/${params.sessionId}`;
|
||||
if (key in stores) return stores[key];
|
||||
const cached = stores[key];
|
||||
if (cached) return cached;
|
||||
|
||||
const store = writable(files.list(params), (set) => {
|
||||
const unsubscribe = files.subscribe(params, ({ filePath, contents }) => {
|
||||
@ -27,5 +33,5 @@ export function getFilesStore(params: { projectId: string; sessionId: string })
|
||||
};
|
||||
});
|
||||
stores[key] = store;
|
||||
return store as Readable<Loadable<Record<string, string>>>;
|
||||
return store as Readable<Loadable<Files>>;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import type { Session } from './api/ipc/sessions';
|
||||
|
||||
export type UISession = {
|
||||
session: Session;
|
||||
deltas: Record<string, Delta[]>;
|
||||
deltas: Partial<Record<string, Delta[]>>;
|
||||
earliestDeltaTimestampMs: number;
|
||||
latestDeltaTimestampMs: number;
|
||||
};
|
||||
|
@ -99,12 +99,12 @@ export async function withFileContent(
|
||||
.map((branch) => branch.files)
|
||||
.flat()
|
||||
.map((file) => file.path);
|
||||
const sessionFiles = await invoke<Record<string, string>>('list_session_files', {
|
||||
const sessionFiles = await invoke<Partial<Record<string, string>>>('list_session_files', {
|
||||
projectId: projectId,
|
||||
sessionId: sessionId,
|
||||
paths: filePaths
|
||||
});
|
||||
const sessionDeltas = await invoke<Record<string, Delta[]>>('list_deltas', {
|
||||
const sessionDeltas = await invoke<Partial<Record<string, Delta[]>>>('list_deltas', {
|
||||
projectId: projectId,
|
||||
sessionId: sessionId,
|
||||
paths: filePaths
|
||||
@ -112,7 +112,7 @@ export async function withFileContent(
|
||||
const branchesWithContnent = branches.map((branch) => {
|
||||
branch.files.map((file) => {
|
||||
const contentAtSessionStart = sessionFiles[file.path] || '';
|
||||
const ds = sessionDeltas[file.path];
|
||||
const ds = sessionDeltas[file.path] || [];
|
||||
file.content = applyDeltas(contentAtSessionStart, ds);
|
||||
});
|
||||
return branch;
|
||||
|
@ -18,22 +18,20 @@
|
||||
);
|
||||
|
||||
$: deltasByDate = derived(sessionDeltas, (sessionDeltas) =>
|
||||
sessionDeltas.reduce(
|
||||
(acc, sessionDelta) => {
|
||||
Object.entries(sessionDelta).forEach(([filepath, deltas]) => {
|
||||
const date = startOfDay(new Date(deltas[0].timestampMs)).toString();
|
||||
if (!acc[date]) acc[date] = {};
|
||||
if (!acc[date][filepath]) acc[date][filepath] = [];
|
||||
acc[date][filepath].push(...deltas);
|
||||
});
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, Record<string, Delta[]>>
|
||||
)
|
||||
sessionDeltas.reduce((acc, sessionDelta) => {
|
||||
Object.entries(sessionDelta).forEach(([filepath, deltas]) => {
|
||||
if (!deltas) return;
|
||||
const date = startOfDay(new Date(deltas[0].timestampMs)).toString();
|
||||
if (!acc[date]) acc[date] = {};
|
||||
if (!acc[date][filepath]) acc[date][filepath] = [];
|
||||
acc[date][filepath].push(...deltas);
|
||||
});
|
||||
return acc;
|
||||
}, {} as Record<string, Record<string, Delta[]>>)
|
||||
);
|
||||
|
||||
$: buckets = derived(sessionDeltas, (sessionDeltas) => {
|
||||
const deltas = sessionDeltas.flatMap((deltas) => Object.values(deltas).flat());
|
||||
const deltas = sessionDeltas.flatMap((deltas) => Object.values(deltas).flat() as Delta[]);
|
||||
const timestamps = deltas.map((delta) => delta.timestampMs);
|
||||
return generateBuckets(timestamps, 18);
|
||||
});
|
||||
|
@ -13,8 +13,8 @@
|
||||
export let isCurrent: boolean;
|
||||
export let session: Session;
|
||||
export let currentFilepath: string;
|
||||
export let deltas: Record<string, Delta[]>;
|
||||
export let files: Record<string, string>;
|
||||
export let deltas: Partial<Record<string, Delta[]>>;
|
||||
export let files: Partial<Record<string, string>>;
|
||||
|
||||
const applyDeltas = (text: string, deltas: Delta[]) => {
|
||||
const operations = deltas.flatMap((delta) => delta.operations);
|
||||
@ -37,8 +37,10 @@
|
||||
$: stats = Object.entries(deltas)
|
||||
.map(([path, deltas]) => {
|
||||
const doc = files[path] ?? '';
|
||||
const left = deltas.length > 0 ? applyDeltas(doc, deltas.slice(0, deltas.length - 1)) : doc;
|
||||
const right = deltas.length > 0 ? applyDeltas(left, deltas.slice(deltas.length - 1)) : left;
|
||||
const left =
|
||||
deltas && deltas.length > 0 ? applyDeltas(doc, deltas.slice(0, deltas.length - 1)) : doc;
|
||||
const right =
|
||||
deltas && deltas.length > 0 ? applyDeltas(left, deltas.slice(deltas.length - 1)) : left;
|
||||
const diff = line(left.split('\n'), right.split('\n'));
|
||||
const linesAdded = diff
|
||||
.filter((d) => d[0] === 1)
|
||||
@ -56,7 +58,7 @@
|
||||
if (bookmarks.isLoading) return [];
|
||||
if (Loaded.isError(bookmarks)) return [];
|
||||
const timestamps = Object.values(deltas ?? {}).flatMap((deltas) =>
|
||||
deltas.map((d) => d.timestampMs)
|
||||
(deltas || []).map((d) => d.timestampMs)
|
||||
);
|
||||
const start = Math.min(...timestamps);
|
||||
const end = Math.max(...timestamps);
|
||||
|
@ -12,7 +12,7 @@
|
||||
import { format } from 'date-fns';
|
||||
|
||||
export let sessions: (Session & {
|
||||
deltas: Readable<Record<string, Delta[]>>;
|
||||
deltas: Readable<Partial<Record<string, Delta[]>>>;
|
||||
})[];
|
||||
export let currentSession: Session;
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
import SessionCard from './SessionCard.svelte';
|
||||
|
||||
export let sessions: (Session & {
|
||||
deltas: Readable<Record<string, Delta[]>>;
|
||||
files: Readable<Record<string, string>>;
|
||||
deltas: Readable<Partial<Record<string, Delta[]>>>;
|
||||
files: Readable<Partial<Record<string, string>>>;
|
||||
})[];
|
||||
export let currentSession: Session | undefined;
|
||||
export let currentFilepath: string;
|
||||
|
@ -42,7 +42,9 @@
|
||||
deltas: derived(getDeltasStore({ projectId: projectId, sessionId: session.id }), (deltas) =>
|
||||
Object.entries(deltas)
|
||||
.filter(([path]) => (filter ? path === filter : true))
|
||||
.flatMap(([path, deltas]) => deltas.map((delta) => [path, delta] as [string, Delta]))
|
||||
.flatMap(([path, deltas]) =>
|
||||
(deltas || []).map((delta) => [path, delta] as [string, Delta])
|
||||
)
|
||||
.sort((a, b) => a[1].timestampMs - b[1].timestampMs)
|
||||
),
|
||||
files: derived(getFilesStore({ projectId, sessionId: session.id }), (files) =>
|
||||
|
@ -10,7 +10,7 @@
|
||||
export let fullContext: boolean;
|
||||
export let sessions: Session[];
|
||||
export let deltas: Readable<Loadable<[string, Delta][][]>>;
|
||||
export let files: Readable<Loadable<Record<string, string>[]>>;
|
||||
export let files: Readable<Loadable<Partial<Record<string, string>>[]>>;
|
||||
export let value: number;
|
||||
export let frame: Frame | null = null;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user