this repo has no description
1import WebpackRequire from "@moonlight-mod/types/discord/require";
2import { DownloadIconSVG, ExtensionState, TrashIconSVG } from "../types";
3import { ExtensionLoadSource } from "types/src";
4import info from "./info";
5import settings from "./settings";
6
7export enum ExtensionPage {
8 Info,
9 Description,
10 Settings
11}
12
13export default (require: typeof WebpackRequire) => {
14 const React = require("common_react");
15 const spacepack = require("spacepack_spacepack").spacepack;
16 const CommonComponents = require("common_components");
17 const Flux = require("common_flux");
18
19 const { ExtensionInfo } = info(require);
20 const { Settings } = settings(require);
21 const { MoonbaseSettingsStore } =
22 require("moonbase_stores") as typeof import("../webpackModules/stores");
23
24 const UserProfileClasses = spacepack.findByCode(
25 "tabBarContainer",
26 "topSection"
27 )[0].exports;
28
29 const DownloadIcon = spacepack.findByCode(DownloadIconSVG)[0].exports.default;
30 const TrashIcon = spacepack.findByCode(TrashIconSVG)[0].exports.default;
31
32 function ExtensionCard({ id }: { id: string }) {
33 const [tab, setTab] = React.useState(ExtensionPage.Info);
34 const { ext, enabled, busy, update } = Flux.useStateFromStores(
35 [MoonbaseSettingsStore],
36 () => {
37 return {
38 ext: MoonbaseSettingsStore.getExtension(id),
39 enabled: MoonbaseSettingsStore.getExtensionEnabled(id),
40 busy: MoonbaseSettingsStore.busy,
41 update: MoonbaseSettingsStore.getExtensionUpdate(id)
42 };
43 }
44 );
45
46 // Why it work like that :sob:
47 if (ext == null) return <></>;
48
49 const {
50 Card,
51 CardClasses,
52 Flex,
53 Text,
54 MarkdownParser,
55 Switch,
56 TabBar,
57 Button
58 } = CommonComponents;
59
60 const tagline = ext.manifest?.meta?.tagline;
61 const settings = ext.manifest?.settings;
62 const description = ext.manifest?.meta?.description;
63
64 return (
65 <Card editable={true} className={CardClasses.card}>
66 <div className={CardClasses.cardHeader}>
67 <Flex direction={Flex.Direction.VERTICAL}>
68 <Flex direction={Flex.Direction.HORIZONTAL}>
69 <Text variant="text-md/semibold">
70 {ext.manifest?.meta?.name ?? ext.id}
71 </Text>
72 </Flex>
73
74 {tagline != null && (
75 <Text variant="text-sm/normal">
76 {MarkdownParser.parse(tagline)}
77 </Text>
78 )}
79 </Flex>
80
81 <Flex
82 direction={Flex.Direction.HORIZONTAL}
83 align={Flex.Align.END}
84 justify={Flex.Justify.END}
85 >
86 {ext.state === ExtensionState.NotDownloaded ? (
87 <Button
88 color={Button.Colors.BRAND}
89 submitting={busy}
90 onClick={() => {
91 MoonbaseSettingsStore.installExtension(id);
92 }}
93 >
94 Install
95 </Button>
96 ) : (
97 <div
98 // too lazy to learn how <Flex /> works lmao
99 style={{
100 display: "flex",
101 alignItems: "center",
102 gap: "1rem"
103 }}
104 >
105 {ext.source.type === ExtensionLoadSource.Normal && (
106 // TODO: this needs centering
107 <Button
108 color={Button.Colors.RED}
109 size={Button.Sizes.ICON}
110 submitting={busy}
111 onClick={() => {
112 MoonbaseSettingsStore.deleteExtension(id);
113 }}
114 >
115 <TrashIcon width={27} />
116 </Button>
117 )}
118
119 {update !== null && (
120 <Button
121 color={Button.Colors.BRAND}
122 size={Button.Sizes.ICON}
123 submitting={busy}
124 onClick={() => {
125 MoonbaseSettingsStore.installExtension(id);
126 }}
127 >
128 <DownloadIcon width={27} />
129 </Button>
130 )}
131
132 <Switch
133 checked={enabled}
134 onChange={() => {
135 MoonbaseSettingsStore.setExtensionEnabled(id, !enabled);
136 }}
137 />
138 </div>
139 )}
140 </Flex>
141 </div>
142
143 <div className={UserProfileClasses.body}>
144 {(description != null || settings != null) && (
145 <div
146 className={UserProfileClasses.tabBarContainer}
147 style={{
148 padding: "0 10px"
149 }}
150 >
151 <TabBar
152 selectedItem={tab}
153 type="top"
154 onItemSelect={setTab}
155 className={UserProfileClasses.tabBar}
156 >
157 <TabBar.Item
158 className={UserProfileClasses.tabBarItem}
159 id={ExtensionPage.Info}
160 >
161 Info
162 </TabBar.Item>
163
164 {description != null && (
165 <TabBar.Item
166 className={UserProfileClasses.tabBarItem}
167 id={ExtensionPage.Description}
168 >
169 Description
170 </TabBar.Item>
171 )}
172
173 {settings != null && (
174 <TabBar.Item
175 className={UserProfileClasses.tabBarItem}
176 id={ExtensionPage.Settings}
177 >
178 Settings
179 </TabBar.Item>
180 )}
181 </TabBar>
182 </div>
183 )}
184
185 <Flex
186 justify={Flex.Justify.START}
187 wrap={Flex.Wrap.WRAP}
188 style={{
189 padding: "16px 16px"
190 }}
191 >
192 {tab === ExtensionPage.Info && <ExtensionInfo ext={ext} />}
193 {tab === ExtensionPage.Description && (
194 <Text variant="text-md/normal">
195 {MarkdownParser.parse(description ?? "*No description*")}
196 </Text>
197 )}
198 {tab === ExtensionPage.Settings && <Settings ext={ext} />}
199 </Flex>
200 </div>
201 </Card>
202 );
203 }
204
205 return function Moonbase() {
206 const { extensions } = Flux.useStateFromStoresObject(
207 [MoonbaseSettingsStore],
208 () => {
209 return { extensions: MoonbaseSettingsStore.extensions };
210 }
211 );
212
213 const sorted = Object.values(extensions).sort((a, b) => {
214 const aName = a.manifest.meta?.name ?? a.id;
215 const bName = b.manifest.meta?.name ?? b.id;
216 return aName.localeCompare(bName);
217 });
218
219 return (
220 <>
221 {sorted.map((ext) => (
222 <ExtensionCard id={ext.id} key={ext.id} />
223 ))}
224 </>
225 );
226 };
227};