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