this repo has no description
1import React from "@moonlight-mod/wp/react";
2import * as Components from "@moonlight-mod/wp/discord/components/common/index";
3import { useStateFromStores, useStateFromStoresObject } from "@moonlight-mod/wp/discord/packages/flux";
4import spacepack from "@moonlight-mod/wp/spacepack_spacepack";
5import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores";
6import { RepositoryManifest, UpdateState } from "../types";
7
8const { Button, TabBar } = Components;
9const TabBarClasses = spacepack.findByCode(/\.exports={tabBar:"tabBar_[a-z0-9]+",tabBarItem:"tabBarItem_[a-z0-9]+"}/)[0]
10 .exports;
11
12const logger = moonlight.getLogger("moonbase/crashScreen");
13
14type ErrorState = {
15 error: Error;
16 info: {
17 componentStack: string;
18 };
19 __moonlight_update?: UpdateState;
20};
21
22type WrapperProps = {
23 action: React.ReactNode;
24 state: ErrorState;
25};
26
27type UpdateCardProps = {
28 id: number;
29 ext: {
30 version: string;
31 download: string;
32 updateManifest: RepositoryManifest;
33 };
34};
35
36const updateStrings: Record<UpdateState, string> = {
37 [UpdateState.Ready]: "A new version of moonlight is available.",
38 [UpdateState.Working]: "Updating moonlight...",
39 [UpdateState.Installed]: "Updated moonlight. Click Reload to apply changes.",
40 [UpdateState.Failed]: "Failed to update moonlight. Please use the installer."
41};
42const buttonStrings: Record<UpdateState, string> = {
43 [UpdateState.Ready]: "Update moonlight",
44 [UpdateState.Working]: "Updating moonlight...",
45 [UpdateState.Installed]: "",
46 [UpdateState.Failed]: "Update failed"
47};
48const extensionButtonStrings: Record<UpdateState, string> = {
49 [UpdateState.Ready]: "Update",
50 [UpdateState.Working]: "Updating...",
51 [UpdateState.Installed]: "Updated",
52 [UpdateState.Failed]: "Update failed"
53};
54
55function ExtensionUpdateCard({ id, ext }: UpdateCardProps) {
56 const [state, setState] = React.useState(UpdateState.Ready);
57 const installed = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.getExtension(id), [id]);
58
59 return (
60 <div className="moonbase-crash-extensionCard">
61 <div className="moonbase-crash-extensionCard-meta">
62 <div className="moonbase-crash-extensionCard-title">
63 {ext.updateManifest.meta?.name ?? ext.updateManifest.id}
64 </div>
65 <div className="moonbase-crash-extensionCard-version">{`v${installed?.manifest?.version ?? "???"} -> v${
66 ext.version
67 }`}</div>
68 </div>
69 <div className="moonbase-crash-extensionCard-button">
70 <Button
71 color={Button.Colors.GREEN}
72 disabled={state !== UpdateState.Ready}
73 onClick={() => {
74 setState(UpdateState.Working);
75 MoonbaseSettingsStore.installExtension(id)
76 .then(() => setState(UpdateState.Installed))
77 .catch(() => setState(UpdateState.Failed));
78 }}
79 >
80 {extensionButtonStrings[state]}
81 </Button>
82 </div>
83 </div>
84 );
85}
86
87export function wrapAction({ action, state }: WrapperProps) {
88 const [tab, setTab] = React.useState("crash");
89
90 const { updates, updateCount } = useStateFromStoresObject([MoonbaseSettingsStore], () => {
91 const { updates } = MoonbaseSettingsStore;
92 return {
93 updates: Object.entries(updates),
94 updateCount: Object.keys(updates).length
95 };
96 });
97
98 return (
99 <div className="moonbase-crash-wrapper">
100 {action}
101 <TabBar
102 className={`${TabBarClasses.tabBar} moonbase-crash-tabs`}
103 type="top"
104 selectedItem={tab}
105 onItemSelect={(v) => setTab(v)}
106 >
107 <TabBar.Item className={TabBarClasses.tabBarItem} id="crash">
108 Crash Details
109 </TabBar.Item>
110 <TabBar.Item className={TabBarClasses.tabBarItem} id="extensions" disabled={updateCount === 0}>
111 {`Extension Updates (${updateCount})`}
112 </TabBar.Item>
113 </TabBar>
114 {tab === "crash" ? (
115 <div className="moonbase-crash-details-wrapper">
116 <pre className="moonbase-crash-details">
117 <code>
118 {state.error.stack}
119 {"\n\nComponent stack:"}
120 {state.info.componentStack}
121 </code>
122 </pre>
123 </div>
124 ) : null}
125 {tab === "extensions" ? (
126 <div className="moonbase-crash-extensions">
127 {updates.map(([id, ext]) => (
128 <ExtensionUpdateCard id={Number(id)} ext={ext} />
129 ))}
130 </div>
131 ) : null}
132 </div>
133 );
134}
135
136export function UpdateText({ state, setState }: { state: ErrorState; setState: (state: ErrorState) => void }) {
137 if (!state.__moonlight_update) {
138 setState({
139 ...state,
140 __moonlight_update: UpdateState.Ready
141 });
142 }
143 const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion);
144
145 return newVersion == null ? null : (
146 <p>{state.__moonlight_update !== undefined ? updateStrings[state.__moonlight_update] : ""}</p>
147 );
148}
149
150export function UpdateButton({ state, setState }: { state: ErrorState; setState: (state: ErrorState) => void }) {
151 const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion);
152 return newVersion == null ||
153 state.__moonlight_update === UpdateState.Installed ||
154 state.__moonlight_update === undefined ? null : (
155 <Button
156 size={Button.Sizes.LARGE}
157 disabled={state.__moonlight_update !== UpdateState.Ready}
158 onClick={() => {
159 setState({
160 ...state,
161 __moonlight_update: UpdateState.Working
162 });
163
164 MoonbaseSettingsStore.updateMoonlight()
165 .then(() => {
166 setState({
167 ...state,
168 __moonlight_update: UpdateState.Installed
169 });
170 })
171 .catch((e) => {
172 logger.error(e);
173 setState({
174 ...state,
175 __moonlight_update: UpdateState.Failed
176 });
177 });
178 }}
179 >
180 {state.__moonlight_update !== undefined ? buttonStrings[state.__moonlight_update] : ""}
181 </Button>
182 );
183}