Repository navigation
Expand file tree
/
Copy pathguideRunStore.ts
More file actions
73 lines (63 loc) · 2.65 KB
/
Copy pathguideRunStore.ts
File metadata and controls
73 lines (63 loc) · 2.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import type { EnvironmentId, PullRequestRef } from "@t3tools/contracts";
import { create } from "zustand";
import type { PullRequestDetailTab } from "~/rightPanelStore";
import { pullRequestReviewKey } from "../pullRequestReviewStore";
export interface GuideRunWatch {
readonly environmentId: EnvironmentId;
readonly reference: PullRequestRef;
readonly title: string | null;
readonly previousGuideAt: string | null;
readonly previousFailedAt: string | null;
readonly since: number;
/**
* Registered from a server answer that reports the run as Running. The guide atom still holds
* the previous answer then, and its outcome belongs to an earlier run.
*/
readonly answeredRunning?: boolean;
}
export interface GuideProgress {
readonly position: number;
readonly seen: ReadonlySet<number>;
}
const NO_PROGRESS: GuideProgress = { position: 0, seen: new Set() };
interface GuideRunStoreState {
readonly watches: Readonly<Record<string, GuideRunWatch>>;
/** The tab the pull requests page shows, for the pull request (run key) it was chosen on. */
readonly pageDetailTab: { readonly key: string; readonly tab: PullRequestDetailTab } | null;
readonly progress: Readonly<Record<string, GuideProgress>>;
readonly setProgress: (key: string, change: (current: GuideProgress) => GuideProgress) => void;
readonly watch: (watch: GuideRunWatch) => void;
readonly settle: (key: string) => void;
readonly showPageDetailTab: (key: string, tab: PullRequestDetailTab) => void;
}
export function guideRunKey(environmentId: EnvironmentId, reference: PullRequestRef): string {
return `${environmentId}:${pullRequestReviewKey(reference)}`;
}
export const useGuideRunStore = create<GuideRunStoreState>()((set) => ({
watches: {},
pageDetailTab: null,
progress: {},
setProgress: (key, change) =>
set((state) => ({
progress: { ...state.progress, [key]: change(state.progress[key] ?? NO_PROGRESS) },
})),
watch: (watch) =>
set((state) => {
const key = guideRunKey(watch.environmentId, watch.reference);
if (state.watches[key] !== undefined) return state;
return { watches: { ...state.watches, [key]: watch } };
}),
settle: (key) =>
set((state) => {
if (state.watches[key] === undefined) return state;
const { [key]: _settled, ...watches } = state.watches;
return { watches };
}),
showPageDetailTab: (key, tab) => set({ pageDetailTab: { key, tab } }),
}));
export function guideProgressKey(runKey: string, headSha: string): string {
return `${runKey}:${headSha}`;
}
export function useGuideProgress(key: string): GuideProgress {
return useGuideRunStore((state) => state.progress[key] ?? NO_PROGRESS);
}