Repository navigation
Expand file tree
/
Copy pathrelayClientInstallDialog.ts
More file actions
126 lines (112 loc) · 3.83 KB
/
Copy pathrelayClientInstallDialog.ts
File metadata and controls
126 lines (112 loc) · 3.83 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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import {
RelayClientInstallProgressStageSchema,
type RelayClientInstallProgressEvent,
type RelayClientInstallProgressStage,
} from "@t3tools/contracts";
import * as Schema from "effect/Schema";
export class RelayClientInstallConfirmationConflictError extends Schema.TaggedError<RelayClientInstallConfirmationConflictError>()(
"RelayClientInstallConfirmationConflictError",
{
requestedVersion: Schema.String,
activeVersion: Schema.String,
activeDialogStatus: Schema.Literals(["confirming", "installing", "closing"]),
activeInstallStage: Schema.optional(RelayClientInstallProgressStageSchema),
},
) {
override get message(): string {
return `Cannot confirm relay client installation ${this.requestedVersion}; installation ${this.activeVersion} has dialog status ${this.activeDialogStatus}.`;
}
}
export type RelayClientInstallDialogState =
| { readonly status: "idle" }
| { readonly status: "confirming"; readonly version: string }
| {
readonly status: "installing";
readonly version: string;
readonly stage: RelayClientInstallProgressStage;
}
| {
readonly status: "closing";
readonly view:
| { readonly status: "confirming"; readonly version: string }
| {
readonly status: "installing";
readonly version: string;
readonly stage: RelayClientInstallProgressStage;
};
};
const idleState: RelayClientInstallDialogState = { status: "idle" };
let state: RelayClientInstallDialogState = idleState;
let resolveConfirmation: ((confirmed: boolean) => void) | null = null;
const listeners = new Set<() => void>();
function publish(next: RelayClientInstallDialogState) {
state = next;
for (const listener of listeners) {
listener();
}
}
export function readRelayClientInstallDialogState(): RelayClientInstallDialogState {
return state;
}
export function subscribeRelayClientInstallDialog(listener: () => void): () => void {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
}
export function requestRelayClientInstallConfirmation(version: string): Promise<boolean> {
if (state.status !== "idle") {
const activeInstall = state.status === "closing" ? state.view : state;
return Promise.reject(
new RelayClientInstallConfirmationConflictError({
requestedVersion: version,
activeVersion: activeInstall.version,
activeDialogStatus: state.status,
...(activeInstall.status === "installing"
? { activeInstallStage: activeInstall.stage }
: {}),
}),
);
}
publish({ status: "confirming", version });
return new Promise<boolean>((resolve) => {
resolveConfirmation = resolve;
});
}
export function respondToRelayClientInstallConfirmation(confirmed: boolean): void {
if (state.status !== "confirming" || !resolveConfirmation) {
return;
}
const resolve = resolveConfirmation;
resolveConfirmation = null;
publish(
confirmed
? { status: "installing", version: state.version, stage: "checking" }
: { status: "closing", view: state },
);
resolve(confirmed);
}
export function reportRelayClientInstallProgress(event: RelayClientInstallProgressEvent): void {
if (state.status !== "installing" || event.type !== "progress") {
return;
}
publish({ ...state, stage: event.stage });
}
export function finishRelayClientInstall(): void {
resolveConfirmation?.(false);
resolveConfirmation = null;
if (state.status === "confirming" || state.status === "installing") {
publish({ status: "closing", view: state });
}
}
export function completeRelayClientInstallDialogClose(): void {
if (state.status === "closing") {
publish(idleState);
}
}
export function resetRelayClientInstallDialogForTests(): void {
resolveConfirmation?.(false);
resolveConfirmation = null;
publish(idleState);
listeners.clear();
}