150 lines
4.3 KiB
TypeScript
150 lines
4.3 KiB
TypeScript
import { create } from "zustand";
|
|
import { Commit, CommitHash } from "../components/commits/types";
|
|
|
|
// Store for app-wide state
|
|
interface ProjectStore {
|
|
// Inputs
|
|
inputMode: "image" | "video";
|
|
setInputMode: (mode: "image" | "video") => void;
|
|
isImportedFromCode: boolean;
|
|
setIsImportedFromCode: (imported: boolean) => void;
|
|
referenceImages: string[];
|
|
setReferenceImages: (images: string[]) => void;
|
|
|
|
// Outputs
|
|
commits: Record<string, Commit>;
|
|
head: CommitHash | null;
|
|
|
|
addCommit: (commit: Commit) => void;
|
|
removeCommit: (hash: CommitHash) => void;
|
|
resetCommits: () => void;
|
|
|
|
appendCommitCode: (
|
|
hash: CommitHash,
|
|
numVariant: number,
|
|
code: string
|
|
) => void;
|
|
setCommitCode: (hash: CommitHash, numVariant: number, code: string) => void;
|
|
updateSelectedVariantIndex: (hash: CommitHash, index: number) => void;
|
|
|
|
setHead: (hash: CommitHash) => void;
|
|
resetHead: () => void;
|
|
|
|
executionConsoles: { [key: number]: string[] };
|
|
appendExecutionConsole: (variantIndex: number, line: string) => void;
|
|
resetExecutionConsoles: () => void;
|
|
}
|
|
|
|
export const useProjectStore = create<ProjectStore>((set) => ({
|
|
// Inputs and their setters
|
|
inputMode: "image",
|
|
setInputMode: (mode) => set({ inputMode: mode }),
|
|
isImportedFromCode: false,
|
|
setIsImportedFromCode: (imported) => set({ isImportedFromCode: imported }),
|
|
referenceImages: [],
|
|
setReferenceImages: (images) => set({ referenceImages: images }),
|
|
|
|
// Outputs
|
|
commits: {},
|
|
head: null,
|
|
|
|
addCommit: (commit: Commit) => {
|
|
// When adding a new commit, make sure all existing commits are marked as committed
|
|
set((state) => ({
|
|
commits: {
|
|
...Object.fromEntries(
|
|
Object.entries(state.commits).map(([hash, existingCommit]) => [
|
|
hash,
|
|
{ ...existingCommit, isCommitted: true },
|
|
])
|
|
),
|
|
[commit.hash]: commit,
|
|
},
|
|
}));
|
|
},
|
|
removeCommit: (hash: CommitHash) => {
|
|
set((state) => {
|
|
const newCommits = { ...state.commits };
|
|
delete newCommits[hash];
|
|
return { commits: newCommits };
|
|
});
|
|
},
|
|
resetCommits: () => set({ commits: {} }),
|
|
|
|
appendCommitCode: (hash: CommitHash, numVariant: number, code: string) =>
|
|
set((state) => {
|
|
const commit = state.commits[hash];
|
|
// Don't update if the commit is already committed
|
|
if (commit.isCommitted) {
|
|
throw new Error("Attempted to append code to a committed commit");
|
|
}
|
|
return {
|
|
commits: {
|
|
...state.commits,
|
|
[hash]: {
|
|
...commit,
|
|
variants: commit.variants.map((variant, index) =>
|
|
index === numVariant
|
|
? { ...variant, code: variant.code + code }
|
|
: variant
|
|
),
|
|
},
|
|
},
|
|
};
|
|
}),
|
|
setCommitCode: (hash: CommitHash, numVariant: number, code: string) =>
|
|
set((state) => {
|
|
const commit = state.commits[hash];
|
|
// Don't update if the commit is already committed
|
|
if (commit.isCommitted) {
|
|
throw new Error("Attempted to set code of a committed commit");
|
|
}
|
|
return {
|
|
commits: {
|
|
...state.commits,
|
|
[hash]: {
|
|
...commit,
|
|
variants: commit.variants.map((variant, index) =>
|
|
index === numVariant ? { ...variant, code } : variant
|
|
),
|
|
},
|
|
},
|
|
};
|
|
}),
|
|
updateSelectedVariantIndex: (hash: CommitHash, index: number) =>
|
|
set((state) => {
|
|
const commit = state.commits[hash];
|
|
// Don't update if the commit is already committed
|
|
if (commit.isCommitted) {
|
|
throw new Error(
|
|
"Attempted to update selected variant index of a committed commit"
|
|
);
|
|
}
|
|
return {
|
|
commits: {
|
|
...state.commits,
|
|
[hash]: {
|
|
...commit,
|
|
selectedVariantIndex: index,
|
|
},
|
|
},
|
|
};
|
|
}),
|
|
|
|
setHead: (hash: CommitHash) => set({ head: hash }),
|
|
resetHead: () => set({ head: null }),
|
|
|
|
executionConsoles: {},
|
|
appendExecutionConsole: (variantIndex: number, line: string) =>
|
|
set((state) => ({
|
|
executionConsoles: {
|
|
...state.executionConsoles,
|
|
[variantIndex]: [
|
|
...(state.executionConsoles[variantIndex] || []),
|
|
line,
|
|
],
|
|
},
|
|
})),
|
|
resetExecutionConsoles: () => set({ executionConsoles: {} }),
|
|
}));
|