this repo has no description
at v1.0.1 7.1 kB view raw
1import WebpackRequire from "@moonlight-mod/types/discord/require"; 2import { 3 Config, 4 DetectedExtension, 5 ExtensionLoadSource 6} from "@moonlight-mod/types"; 7import { 8 ExtensionState, 9 MoonbaseExtension, 10 MoonbaseNatives, 11 RepositoryManifest 12} from "./types"; 13 14export const stores = (require: typeof WebpackRequire) => { 15 const Flux = require("common_flux"); 16 const Dispatcher = require("common_fluxDispatcher"); 17 const natives: MoonbaseNatives = moonlight.getNatives("moonbase"); 18 19 class MoonbaseSettingsStore extends Flux.Store<any> { 20 private origConfig: Config; 21 private config: Config; 22 23 modified: boolean; 24 submitting: boolean; 25 installing: boolean; 26 27 extensions: { [id: string]: MoonbaseExtension }; 28 updates: { [id: string]: { version: string; download: string } }; 29 30 constructor() { 31 super(Dispatcher); 32 33 // Fucking Electron making it immutable 34 this.origConfig = moonlightNode.config; 35 this.config = JSON.parse(JSON.stringify(this.origConfig)); 36 37 this.modified = false; 38 this.submitting = false; 39 this.installing = false; 40 41 this.extensions = {}; 42 this.updates = {}; 43 for (const ext of moonlightNode.extensions) { 44 const existingExtension = this.extensions[ext.id]; 45 if (existingExtension != null) continue; 46 47 this.extensions[ext.id] = { 48 ...ext, 49 state: moonlight.enabledExtensions.has(ext.id) 50 ? ExtensionState.Enabled 51 : ExtensionState.Disabled 52 }; 53 } 54 55 natives.fetchRepositories(this.config.repositories).then((ret) => { 56 for (const [repo, exts] of Object.entries(ret)) { 57 try { 58 for (const ext of exts) { 59 try { 60 const existingExtension = this.extensions[ext.id]; 61 if (existingExtension != null) { 62 if (this.hasUpdate(repo, ext, existingExtension)) { 63 this.updates[ext.id] = { 64 version: ext.version!, 65 download: ext.download 66 }; 67 } 68 continue; 69 } 70 71 this.extensions[ext.id] = { 72 id: ext.id, 73 manifest: ext, 74 source: { type: ExtensionLoadSource.Normal, url: repo }, 75 state: ExtensionState.NotDownloaded 76 }; 77 } catch (e) { 78 console.error(`Error processing extension ${ext.id}`, e); 79 } 80 } 81 } catch (e) { 82 console.error(`Error processing repository ${repo}`, e); 83 } 84 } 85 86 this.emitChange(); 87 }); 88 } 89 90 // this logic sucks so bad lol 91 private hasUpdate( 92 repo: string, 93 repoExt: RepositoryManifest, 94 existing: MoonbaseExtension 95 ) { 96 return ( 97 existing.source.type === ExtensionLoadSource.Normal && 98 existing.source.url != null && 99 existing.source.url === repo && 100 repoExt.version != null && 101 existing.manifest.version != repoExt.version 102 ); 103 } 104 105 // Jank 106 private isModified() { 107 const orig = JSON.stringify(this.origConfig); 108 const curr = JSON.stringify(this.config); 109 return orig !== curr; 110 } 111 112 get busy() { 113 return this.submitting || this.installing; 114 } 115 116 showNotice() { 117 return this.modified; 118 } 119 120 getExtension(id: string) { 121 return this.extensions[id]; 122 } 123 124 getExtensionName(id: string) { 125 return this.extensions.hasOwnProperty(id) 126 ? this.extensions[id].manifest.meta?.name ?? id 127 : id; 128 } 129 130 getExtensionUpdate(id: string) { 131 return this.updates.hasOwnProperty(id) ? this.updates[id] : null; 132 } 133 134 getExtensionEnabled(id: string) { 135 const val = this.config.extensions[id]; 136 if (val == null) return false; 137 return typeof val === "boolean" ? val : val.enabled; 138 } 139 140 getExtensionConfig<T>(id: string, key: string): T | undefined { 141 const defaultValue = 142 this.extensions[id].manifest.settings?.[key]?.default; 143 const cfg = this.config.extensions[id]; 144 145 if (cfg == null || typeof cfg === "boolean") return defaultValue; 146 return cfg.config?.[key] ?? defaultValue; 147 } 148 149 getExtensionConfigName(id: string, key: string) { 150 return this.extensions[id].manifest.settings?.[key]?.displayName ?? key; 151 } 152 153 setExtensionConfig(id: string, key: string, value: any) { 154 const oldConfig = this.config.extensions[id]; 155 const newConfig = 156 typeof oldConfig === "boolean" 157 ? { 158 enabled: oldConfig, 159 config: { [key]: value } 160 } 161 : { 162 ...oldConfig, 163 config: { ...(oldConfig?.config ?? {}), [key]: value } 164 }; 165 166 this.config.extensions[id] = newConfig; 167 this.modified = this.isModified(); 168 this.emitChange(); 169 } 170 171 setExtensionEnabled(id: string, enabled: boolean) { 172 let val = this.config.extensions[id]; 173 174 if (val == null) { 175 this.config.extensions[id] = { enabled }; 176 this.emitChange(); 177 return; 178 } 179 180 if (typeof val === "boolean") { 181 val = enabled; 182 } else { 183 val.enabled = enabled; 184 } 185 186 this.config.extensions[id] = val; 187 this.modified = this.isModified(); 188 this.emitChange(); 189 } 190 191 async installExtension(id: string) { 192 const ext = this.getExtension(id); 193 if (!("download" in ext.manifest)) { 194 throw new Error("Extension has no download URL"); 195 } 196 197 this.installing = true; 198 try { 199 const url = this.updates[id]?.download ?? ext.manifest.download; 200 await natives.installExtension(ext.manifest, url, ext.source.url!); 201 if (ext.state === ExtensionState.NotDownloaded) { 202 this.extensions[id].state = ExtensionState.Disabled; 203 } 204 205 delete this.updates[id]; 206 } catch (e) { 207 console.error("Error installing extension:", e); 208 } 209 210 this.installing = false; 211 this.emitChange(); 212 } 213 214 async deleteExtension(id: string) { 215 const ext = this.getExtension(id); 216 if (ext == null) return; 217 218 this.installing = true; 219 try { 220 await natives.deleteExtension(ext.id); 221 this.extensions[id].state = ExtensionState.NotDownloaded; 222 } catch (e) { 223 console.error("Error deleting extension:", e); 224 } 225 226 this.installing = false; 227 this.emitChange(); 228 } 229 230 writeConfig() { 231 this.submitting = true; 232 233 try { 234 moonlightNode.writeConfig(this.config); 235 // I love jank cloning 236 this.origConfig = JSON.parse(JSON.stringify(this.config)); 237 } catch (e) { 238 console.error("Error writing config", e); 239 } 240 241 this.submitting = false; 242 this.modified = false; 243 this.emitChange(); 244 } 245 246 reset() { 247 this.submitting = false; 248 this.modified = false; 249 this.config = JSON.parse(JSON.stringify(this.origConfig)); 250 this.emitChange(); 251 } 252 } 253 254 return { 255 MoonbaseSettingsStore: new MoonbaseSettingsStore() 256 }; 257};