mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-10-06 08:58:11 +03:00
Memoize derive calls
If we call files() 90 odd times, it will create 90 different derived stores. This means that we're going to do an awful lot of extra work as each update to the selected ids will trigger 90 jobs. By memoizing the store, we will only ever create one derived object and as such eliminate the dupilcate work.
This commit is contained in:
parent
95eca10174
commit
d89281fdcc
@ -20,6 +20,7 @@
|
||||
import lscache from 'lscache';
|
||||
import { setContext } from 'svelte';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { writable } from 'svelte/store';
|
||||
import { slide } from 'svelte/transition';
|
||||
|
||||
export let branch: Branch;
|
||||
@ -50,10 +51,12 @@
|
||||
|
||||
const project = getContext(Project);
|
||||
|
||||
const fileIdSelection = new FileIdSelection();
|
||||
const branchFiles = writable(branch.files);
|
||||
$: branchFiles.set(branch.files);
|
||||
const fileIdSelection = new FileIdSelection(project.id, branchFiles);
|
||||
setContext(FileIdSelection, fileIdSelection);
|
||||
|
||||
$: selectedFile = fileIdSelection.selectedFile(branch.files, project.id);
|
||||
$: selectedFile = fileIdSelection.selectedFile;
|
||||
|
||||
const userSettings = getContextStoreBySymbol<Settings>(SETTINGS);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import FileContextMenu from './FileContextMenu.svelte';
|
||||
import FileStatusIcons from './FileStatusIcons.svelte';
|
||||
import { Project } from '$lib/backend/projects';
|
||||
import Checkbox from '$lib/components/Checkbox.svelte';
|
||||
import { draggable } from '$lib/dragging/draggable';
|
||||
import { DraggableFile } from '$lib/dragging/draggables';
|
||||
@ -24,10 +23,9 @@
|
||||
const branch = maybeGetContextStore(Branch);
|
||||
const selectedOwnership: Writable<Ownership> | undefined = maybeGetContextStore(Ownership);
|
||||
const fileIdSelection = getContext(FileIdSelection);
|
||||
const project = getContext(Project);
|
||||
const commit = getCommitStore();
|
||||
|
||||
$: selectedFiles = fileIdSelection.files($branch?.files || [], project.id);
|
||||
const selectedFiles = fileIdSelection.files;
|
||||
|
||||
let checked = false;
|
||||
let indeterminate = false;
|
||||
|
@ -13,6 +13,7 @@
|
||||
import lscache from 'lscache';
|
||||
import { marked } from 'marked';
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import type { PullRequest } from '$lib/github/types';
|
||||
|
||||
export let branch: RemoteBranch;
|
||||
@ -21,10 +22,10 @@
|
||||
const project = getContext(Project);
|
||||
const baseBranch = getContextStore(BaseBranch);
|
||||
|
||||
const fileIdSelection = new FileIdSelection();
|
||||
const fileIdSelection = new FileIdSelection(project.id, writable([]));
|
||||
setContext(FileIdSelection, fileIdSelection);
|
||||
|
||||
$: selectedFile = fileIdSelection.selectedFile([], project.id);
|
||||
$: selectedFile = fileIdSelection.selectedFile;
|
||||
|
||||
const defaultBranchWidthRem = 30;
|
||||
const laneWidthKey = 'branchPreviewLaneWidth';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { isDefined } from '$lib/utils/typeguards';
|
||||
import { listRemoteCommitFiles } from '$lib/vbranches/remoteCommits';
|
||||
import { derived } from 'svelte/store';
|
||||
import { derived, type Readable } from 'svelte/store';
|
||||
import type { AnyFile, LocalFile } from '$lib/vbranches/types';
|
||||
|
||||
export interface FileKey {
|
||||
@ -32,7 +32,11 @@ export class FileIdSelection {
|
||||
private value: string[];
|
||||
private callbacks: CallBack[];
|
||||
|
||||
constructor(value: FileKey[] = []) {
|
||||
constructor(
|
||||
private projectId: string,
|
||||
private localFiles: Readable<LocalFile[]>,
|
||||
value: FileKey[] = []
|
||||
) {
|
||||
this.callbacks = [];
|
||||
this.value = value.map((key) => stringifyFileKey(key.fileId, key.commitId));
|
||||
}
|
||||
@ -87,24 +91,36 @@ export class FileIdSelection {
|
||||
return fileKey;
|
||||
}
|
||||
|
||||
selectedFile(localFiles: LocalFile[], branchId: string) {
|
||||
return derived(this, async (value): Promise<AnyFile | undefined> => {
|
||||
if (value.length !== 1) return;
|
||||
const fileKey = parseFileKey(value[0]);
|
||||
return await findFileByKey(localFiles, branchId, fileKey);
|
||||
});
|
||||
#selectedFile: Readable<Promise<AnyFile | undefined>> | undefined;
|
||||
get selectedFile() {
|
||||
this.#selectedFile ||= derived(
|
||||
[this as Readable<string[]>, this.localFiles],
|
||||
async ([selection, localFiles]): Promise<AnyFile | undefined> => {
|
||||
if (selection.length !== 1) return;
|
||||
const fileKey = parseFileKey(selection[0]);
|
||||
return await findFileByKey(localFiles, this.projectId, fileKey);
|
||||
}
|
||||
);
|
||||
|
||||
return this.#selectedFile;
|
||||
}
|
||||
|
||||
files(localFiles: LocalFile[], branchId: string) {
|
||||
return derived(this, async (value) => {
|
||||
const files = await Promise.all(
|
||||
value.map(async (fileKey) => {
|
||||
return await findFileByKey(localFiles, branchId, parseFileKey(fileKey));
|
||||
})
|
||||
);
|
||||
#files: Readable<Promise<AnyFile[]>> | undefined;
|
||||
get files() {
|
||||
this.#files ||= derived(
|
||||
[this as Readable<string[]>, this.localFiles],
|
||||
async ([selection, localFiles]): Promise<AnyFile[]> => {
|
||||
const files = await Promise.all(
|
||||
selection.map(async (fileKey) => {
|
||||
return await findFileByKey(localFiles, this.projectId, parseFileKey(fileKey));
|
||||
})
|
||||
);
|
||||
|
||||
return files.filter(isDefined);
|
||||
});
|
||||
return files.filter(isDefined);
|
||||
}
|
||||
);
|
||||
|
||||
return this.#files;
|
||||
}
|
||||
|
||||
get length() {
|
||||
@ -112,7 +128,7 @@ export class FileIdSelection {
|
||||
}
|
||||
}
|
||||
|
||||
export async function findFileByKey(localFiles: LocalFile[], projectId: string, key: FileKey) {
|
||||
async function findFileByKey(localFiles: LocalFile[], projectId: string, key: FileKey) {
|
||||
if (key.commitId) {
|
||||
const remoteFiles = await listRemoteCommitFiles(projectId, key.commitId);
|
||||
return remoteFiles.find((file) => file.id === key.fileId);
|
||||
|
@ -11,6 +11,8 @@
|
||||
import { FileIdSelection } from '$lib/vbranches/fileIdSelection';
|
||||
import lscache from 'lscache';
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const defaultBranchWidthRem = 30;
|
||||
const laneWidthKey = 'historyLaneWidth';
|
||||
const userSettings = getContextStoreBySymbol<Settings>(SETTINGS);
|
||||
@ -19,10 +21,10 @@
|
||||
const baseBranch = baseBranchService.base;
|
||||
const project = getContext(Project);
|
||||
|
||||
const fileIdSelection = new FileIdSelection();
|
||||
const fileIdSelection = new FileIdSelection(project.id, writable([]));
|
||||
setContext(FileIdSelection, fileIdSelection);
|
||||
|
||||
$: selectedFile = fileIdSelection.selectedFile([], project.id);
|
||||
$: selectedFile = fileIdSelection.selectedFile;
|
||||
|
||||
let rsViewport: HTMLDivElement;
|
||||
let laneWidth: number;
|
||||
|
Loading…
Reference in New Issue
Block a user