this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Convert mostly everything to new webpack modules structure

+447 -471
-13
packages/core-extensions/src/common/flux.ts
··· 1 - import { ExtensionWebpackModule } from "@moonlight-mod/types"; 2 - import { CommonFlux } from "@moonlight-mod/types/coreExtensions"; 3 - 4 - const findFlux = ["useStateFromStores:function"]; 5 - 6 - export const flux: ExtensionWebpackModule = { 7 - dependencies: [{ ext: "spacepack", id: "spacepack" }, ...findFlux], 8 - run: (module, exports, require) => { 9 - const spacepack = require("spacepack_spacepack").spacepack; 10 - const Flux = spacepack.findByCode(...findFlux)[0].exports; 11 - module.exports = Flux as CommonFlux; 12 - } 13 - };
-16
packages/core-extensions/src/common/fluxDispatcher.ts
··· 1 - import { ExtensionWebpackModule } from "@moonlight-mod/types"; 2 - 3 - export const fluxDispatcher: ExtensionWebpackModule = { 4 - dependencies: [ 5 - { ext: "spacepack", id: "spacepack" }, 6 - "isDispatching", 7 - "dispatch" 8 - ], 9 - run: (module, exports, require) => { 10 - const spacepack = require("spacepack_spacepack").spacepack; 11 - module.exports = spacepack.findByExports( 12 - "isDispatching", 13 - "dispatch" 14 - )[0].exports.default; 15 - } 16 - };
-12
packages/core-extensions/src/common/http.ts
··· 1 - import { ExtensionWebpackModule } from "@moonlight-mod/types"; 2 - 3 - const findHTTP = ["get", "put", "V8APIError"]; 4 - 5 - export const http: ExtensionWebpackModule = { 6 - dependencies: [{ ext: "spacepack", id: "spacepack" }], 7 - run: (module, exports, require) => { 8 - const spacepack = require("spacepack_spacepack").spacepack; 9 - const HTTP = spacepack.findByExports(...findHTTP)[0].exports; 10 - module.exports = HTTP.ZP ?? HTTP.Z; 11 - } 12 - };
+27 -11
packages/core-extensions/src/common/index.ts
··· 1 1 import { ExtensionWebExports } from "@moonlight-mod/types"; 2 2 3 - import { react } from "./react"; 4 - import { flux } from "./flux"; 5 - import { stores } from "./stores"; 6 - import { http } from "./http"; 7 - import { fluxDispatcher } from "./fluxDispatcher"; 8 - 9 3 export const webpackModules: ExtensionWebExports["webpackModules"] = { 10 4 components: { 11 5 dependencies: [ ··· 15 9 ] 16 10 }, 17 11 18 - react, 19 - flux, 20 - stores, 21 - http, 22 - fluxDispatcher 12 + flux: { 13 + dependencies: [ 14 + { ext: "spacepack", id: "spacepack" }, 15 + "useStateFromStores:function" 16 + ] 17 + }, 18 + 19 + fluxDispatcher: { 20 + dependencies: [ 21 + { ext: "spacepack", id: "spacepack" }, 22 + "isDispatching", 23 + "dispatch" 24 + ] 25 + }, 26 + 27 + react: { 28 + dependencies: [ 29 + { ext: "spacepack", id: "spacepack" }, 30 + "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED", 31 + /\.?version(?:=|:)/, 32 + /\.?createElement(?:=|:)/ 33 + ] 34 + }, 35 + 36 + stores: { 37 + dependencies: [{ ext: "common", id: "flux" }] 38 + } 23 39 };
-15
packages/core-extensions/src/common/react.ts
··· 1 - import { ExtensionWebpackModule } from "@moonlight-mod/types"; 2 - 3 - const findReact = [ 4 - "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED", 5 - /\.?version(?:=|:)/, 6 - /\.?createElement(?:=|:)/ 7 - ]; 8 - 9 - export const react: ExtensionWebpackModule = { 10 - dependencies: [...findReact, { ext: "spacepack", id: "spacepack" }], 11 - run: (module, exports, require) => { 12 - const spacepack = require("spacepack_spacepack").spacepack; 13 - module.exports = spacepack.findByCode(...findReact)[0].exports; 14 - } 15 - };
-30
packages/core-extensions/src/common/stores.ts
··· 1 - import { ExtensionWebpackModule } from "@moonlight-mod/types"; 2 - 3 - export const stores: ExtensionWebpackModule = { 4 - dependencies: [{ ext: "common", id: "flux" }], 5 - run: (module, exports, require) => { 6 - const Flux = require("common_flux"); 7 - 8 - module.exports = new Proxy( 9 - {}, 10 - { 11 - get: function (target, key, receiver) { 12 - const allStores = Flux.Store.getAll(); 13 - 14 - let targetStore; 15 - for (const store of allStores) { 16 - const name = store.getName(); 17 - if (name.length === 1) continue; // filter out unnamed stores 18 - 19 - if (name === key) { 20 - targetStore = store; 21 - break; 22 - } 23 - } 24 - 25 - return targetStore; 26 - } 27 - } 28 - ); 29 - } 30 - };
+5
packages/core-extensions/src/common/webpackModules/flux.ts
··· 1 + import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 2 + 3 + module.exports = spacepack.findByCode( 4 + ["useStateFromStores", ":function"].join("") 5 + )[0].exports;
+6
packages/core-extensions/src/common/webpackModules/fluxDispatcher.ts
··· 1 + import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 2 + 3 + module.exports = spacepack.findByExports( 4 + "isDispatching", 5 + "dispatch" 6 + )[0].exports.default;
+7
packages/core-extensions/src/common/webpackModules/react.ts
··· 1 + import spacepack from "@moonlight-mod/wp/spacepack_spacepack"; 2 + 3 + module.exports = spacepack.findByCode( 4 + "__SECRET_INTERNALS_DO_NOT_USE" + "_OR_YOU_WILL_BE_FIRED", 5 + /\.?version(?:=|:)/, 6 + /\.?createElement(?:=|:)/ 7 + )[0].exports;
+23
packages/core-extensions/src/common/webpackModules/stores.ts
··· 1 + import Flux from "@moonlight-mod/wp/common_flux"; 2 + 3 + module.exports = new Proxy( 4 + {}, 5 + { 6 + get: function (target, key, receiver) { 7 + const allStores = Flux.Store.getAll(); 8 + 9 + let targetStore; 10 + for (const store of allStores) { 11 + const name = store.getName(); 12 + if (name.length === 1) continue; // filter out unnamed stores 13 + 14 + if (name === key) { 15 + targetStore = store; 16 + break; 17 + } 18 + } 19 + 20 + return targetStore; 21 + } 22 + } 23 + );
+3 -38
packages/core-extensions/src/disableSentry/index.ts
··· 7 7 replace: { 8 8 type: PatchReplaceType.Normal, 9 9 match: /default:function\(\){return .}/, 10 - replacement: 'default:function(){return require("disableSentry_stub")()}' 10 + replacement: 11 + 'default:function(){return require("disableSentry_stub").proxy()}' 11 12 } 12 13 }, 13 14 { ··· 38 39 ]; 39 40 40 41 export const webpackModules: ExtensionWebExports["webpackModules"] = { 41 - stub: { 42 - run: function (module, exports, require) { 43 - const logger = moonlight.getLogger("disableSentry"); 44 - 45 - const keys = [ 46 - "setUser", 47 - "clearUser", 48 - "setTags", 49 - "setExtra", 50 - "captureException", 51 - "captureCrash", 52 - "captureMessage", 53 - "addBreadcrumb" 54 - ]; 55 - 56 - module.exports = () => 57 - new Proxy( 58 - {}, 59 - { 60 - get(target, prop, receiver) { 61 - if (prop === "profiledRootComponent") { 62 - return (arg: any) => arg; 63 - } else if (prop === "crash") { 64 - return () => { 65 - throw Error("crash"); 66 - }; 67 - } else if (keys.includes(prop.toString())) { 68 - return (...args: any[]) => 69 - logger.debug(`Sentry calling "${prop.toString()}":`, ...args); 70 - } else { 71 - return undefined; 72 - } 73 - } 74 - } 75 - ); 76 - } 77 - } 42 + stub: {} 78 43 };
+33
packages/core-extensions/src/disableSentry/webpackModules/stub.ts
··· 1 + const logger = moonlight.getLogger("disableSentry"); 2 + 3 + const keys = [ 4 + "setUser", 5 + "clearUser", 6 + "setTags", 7 + "setExtra", 8 + "captureException", 9 + "captureCrash", 10 + "captureMessage", 11 + "addBreadcrumb" 12 + ]; 13 + 14 + export const proxy = () => 15 + new Proxy( 16 + {}, 17 + { 18 + get(target, prop, receiver) { 19 + if (prop === "profiledRootComponent") { 20 + return (arg: any) => arg; 21 + } else if (prop === "crash") { 22 + return () => { 23 + throw Error("crash"); 24 + }; 25 + } else if (keys.includes(prop.toString())) { 26 + return (...args: any[]) => 27 + logger.debug(`Sentry calling "${prop.toString()}":`, ...args); 28 + } else { 29 + return undefined; 30 + } 31 + } 32 + } 33 + );
+3 -9
packages/core-extensions/src/moonbase/index.tsx
··· 1 1 import { ExtensionWebExports } from "@moonlight-mod/types"; 2 2 import ui from "./ui"; 3 - import { stores } from "./stores"; 4 3 import { DownloadIconSVG, TrashIconSVG } from "./types"; 5 4 6 5 export const webpackModules: ExtensionWebExports["webpackModules"] = { ··· 8 7 dependencies: [ 9 8 { ext: "common", id: "flux" }, 10 9 { ext: "common", id: "fluxDispatcher" } 11 - ], 12 - run: (module, exports, require) => { 13 - module.exports = stores(require); 14 - } 10 + ] 15 11 }, 16 12 17 13 moonbase: { ··· 26 22 ], 27 23 entrypoint: true, 28 24 run: (module, exports, require) => { 29 - const settings = require("settings_settings"); 25 + const settings = require("settings_settings").Settings; 30 26 const React = require("common_react"); 31 27 const spacepack = require("spacepack_spacepack").spacepack; 32 28 const { MoonbaseSettingsStore } = 33 - require("moonbase_stores") as ReturnType< 34 - (typeof import("./stores"))["stores"] 35 - >; 29 + require("moonbase_stores") as typeof import("./webpackModules/stores"); 36 30 37 31 settings.addSection("Moonbase", "Moonbase", ui(require), null, -2, { 38 32 stores: [MoonbaseSettingsStore],
-257
packages/core-extensions/src/moonbase/stores.ts
··· 1 - import WebpackRequire from "@moonlight-mod/types/discord/require"; 2 - import { Config, ExtensionLoadSource } from "@moonlight-mod/types"; 3 - import { 4 - ExtensionState, 5 - MoonbaseExtension, 6 - MoonbaseNatives, 7 - RepositoryManifest 8 - } from "./types"; 9 - 10 - export const stores = (require: typeof WebpackRequire) => { 11 - const Flux = require("common_flux"); 12 - const Dispatcher = require("common_fluxDispatcher"); 13 - const natives: MoonbaseNatives = moonlight.getNatives("moonbase"); 14 - 15 - const logger = moonlight.getLogger("moonbase"); 16 - 17 - class MoonbaseSettingsStore extends Flux.Store<any> { 18 - private origConfig: Config; 19 - private config: Config; 20 - 21 - modified: boolean; 22 - submitting: boolean; 23 - installing: boolean; 24 - 25 - extensions: { [id: string]: MoonbaseExtension }; 26 - updates: { [id: string]: { version: string; download: string } }; 27 - 28 - constructor() { 29 - super(Dispatcher); 30 - 31 - // Fucking Electron making it immutable 32 - this.origConfig = moonlightNode.config; 33 - this.config = JSON.parse(JSON.stringify(this.origConfig)); 34 - 35 - this.modified = false; 36 - this.submitting = false; 37 - this.installing = false; 38 - 39 - this.extensions = {}; 40 - this.updates = {}; 41 - for (const ext of moonlightNode.extensions) { 42 - const existingExtension = this.extensions[ext.id]; 43 - if (existingExtension != null) continue; 44 - 45 - this.extensions[ext.id] = { 46 - ...ext, 47 - state: moonlight.enabledExtensions.has(ext.id) 48 - ? ExtensionState.Enabled 49 - : ExtensionState.Disabled 50 - }; 51 - } 52 - 53 - natives.fetchRepositories(this.config.repositories).then((ret) => { 54 - for (const [repo, exts] of Object.entries(ret)) { 55 - try { 56 - for (const ext of exts) { 57 - try { 58 - const existingExtension = this.extensions[ext.id]; 59 - if (existingExtension !== null) { 60 - if (this.hasUpdate(repo, ext, existingExtension)) { 61 - this.updates[ext.id] = { 62 - version: ext.version!, 63 - download: ext.download 64 - }; 65 - } 66 - continue; 67 - } 68 - 69 - this.extensions[ext.id] = { 70 - id: ext.id, 71 - manifest: ext, 72 - source: { type: ExtensionLoadSource.Normal, url: repo }, 73 - state: ExtensionState.NotDownloaded 74 - }; 75 - } catch (e) { 76 - logger.error(`Error processing extension ${ext.id}`, e); 77 - } 78 - } 79 - } catch (e) { 80 - logger.error(`Error processing repository ${repo}`, e); 81 - } 82 - } 83 - 84 - this.emitChange(); 85 - }); 86 - } 87 - 88 - // this logic sucks so bad lol 89 - private hasUpdate( 90 - repo: string, 91 - repoExt: RepositoryManifest, 92 - existing: MoonbaseExtension 93 - ) { 94 - return ( 95 - existing.source.type === ExtensionLoadSource.Normal && 96 - existing.source.url != null && 97 - existing.source.url === repo && 98 - repoExt.version != null && 99 - existing.manifest.version !== repoExt.version 100 - ); 101 - } 102 - 103 - // Jank 104 - private isModified() { 105 - const orig = JSON.stringify(this.origConfig); 106 - const curr = JSON.stringify(this.config); 107 - return orig !== curr; 108 - } 109 - 110 - get busy() { 111 - return this.submitting || this.installing; 112 - } 113 - 114 - showNotice() { 115 - return this.modified; 116 - } 117 - 118 - getExtension(id: string) { 119 - return this.extensions[id]; 120 - } 121 - 122 - getExtensionName(id: string) { 123 - return Object.prototype.hasOwnProperty.call(this.extensions, id) 124 - ? this.extensions[id].manifest.meta?.name ?? id 125 - : id; 126 - } 127 - 128 - getExtensionUpdate(id: string) { 129 - return Object.prototype.hasOwnProperty.call(this.updates, id) 130 - ? this.updates[id] 131 - : 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 - logger.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 - logger.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 - logger.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 - };
+2 -3
packages/core-extensions/src/moonbase/ui/index.tsx
··· 18 18 19 19 const { ExtensionInfo } = info(require); 20 20 const { Settings } = settings(require); 21 - const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType< 22 - (typeof import("../stores"))["stores"] 23 - >; 21 + const { MoonbaseSettingsStore } = 22 + require("moonbase_stores") as typeof import("../webpackModules/stores"); 24 23 25 24 const UserProfileClasses = spacepack.findByCode( 26 25 "tabBarContainer",
+2 -3
packages/core-extensions/src/moonbase/ui/info.tsx
··· 24 24 "userInfoSectionHeader" 25 25 )[0].exports; 26 26 27 - const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType< 28 - (typeof import("../stores"))["stores"] 29 - >; 27 + const { MoonbaseSettingsStore } = 28 + require("moonbase_stores") as typeof import("../webpackModules/stores"); 30 29 31 30 function InfoSection({ 32 31 title,
+2 -3
packages/core-extensions/src/moonbase/ui/settings.tsx
··· 20 20 const CommonComponents = require("common_components"); 21 21 const Flux = require("common_flux"); 22 22 23 - const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType< 24 - (typeof import("../stores"))["stores"] 25 - >; 23 + const { MoonbaseSettingsStore } = 24 + require("moonbase_stores") as typeof import("../webpackModules/stores"); 26 25 27 26 function Boolean({ ext, name, setting }: SettingsProps) { 28 27 const { FormSwitch } = CommonComponents;
+251
packages/core-extensions/src/moonbase/webpackModules/stores.ts
··· 1 + import { Config, ExtensionLoadSource } from "@moonlight-mod/types"; 2 + import { 3 + ExtensionState, 4 + MoonbaseExtension, 5 + MoonbaseNatives, 6 + RepositoryManifest 7 + } from "../types"; 8 + import Flux from "@moonlight-mod/wp/common_flux"; 9 + import Dispatcher from "@moonlight-mod/wp/common_fluxDispatcher"; 10 + 11 + const natives: MoonbaseNatives = moonlight.getNatives("moonbase"); 12 + const logger = moonlight.getLogger("moonbase"); 13 + 14 + class 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 + 250 + const settingsStore = new MoonbaseSettingsStore(); 251 + export { settingsStore as MoonbaseSettingsStore };
+4 -58
packages/core-extensions/src/settings/index.ts
··· 1 1 import { Patch } from "@moonlight-mod/types"; 2 - import { 3 - SettingsSection, 4 - Settings as SettingsType 5 - } from "@moonlight-mod/types/coreExtensions"; 6 2 import { ExtensionWebExports } from "@moonlight-mod/types"; 7 3 8 4 export const patches: Patch[] = [ ··· 11 7 replace: { 12 8 match: /\.CUSTOM,element:(.+?)}\];return (.{1,2})/, 13 9 replacement: (_, lastElement, sections) => 14 - `.CUSTOM,element:${lastElement}}];return require("settings_settings")._mutateSections(${sections})` 10 + `.CUSTOM,element:${lastElement}}];return require("settings_settings").Settings._mutateSections(${sections})` 15 11 } 16 12 }, 17 13 { ··· 21 17 replacement: (orig, sections, section) => 22 18 `${orig.replace( 23 19 /Object\.values\(.\.UserSettingsSections\)/, 24 - (orig) => `[...require("settings_settings").sectionNames,...${orig}]` 20 + (orig) => 21 + `[...require("settings_settings").Settings.sectionNames,...${orig}]` 25 22 )}??${sections}.find(x=>x.section==${section})?._moonlight_submenu?.()` 26 23 } 27 24 } 28 25 ]; 29 26 30 27 export const webpackModules: ExtensionWebExports["webpackModules"] = { 31 - settings: { 32 - run: (module, exports, require) => { 33 - const Settings: SettingsType = { 34 - ourSections: [], 35 - sectionNames: [], 36 - 37 - addSection: (section, label, element, color = null, pos, notice) => { 38 - const data: SettingsSection = { 39 - section, 40 - label, 41 - color, 42 - element, 43 - pos: pos ?? -4, 44 - notice: notice 45 - }; 46 - 47 - Settings.ourSections.push(data); 48 - Settings.sectionNames.push(label); 49 - return data; 50 - }, 51 - 52 - addDivider: (pos = null) => { 53 - Settings.ourSections.push({ 54 - section: "DIVIDER", 55 - pos: pos === null ? -4 : pos 56 - }); 57 - }, 58 - 59 - addHeader: function (label, pos = null) { 60 - Settings.ourSections.push({ 61 - section: "HEADER", 62 - label: label, 63 - pos: pos === null ? -4 : pos 64 - }); 65 - }, 66 - 67 - _mutateSections: (sections) => { 68 - for (const section of Settings.ourSections) { 69 - sections.splice( 70 - section.pos < 0 ? sections.length + section.pos : section.pos, 71 - 0, 72 - section 73 - ); 74 - } 75 - 76 - return sections; 77 - } 78 - }; 79 - 80 - module.exports = Settings; 81 - } 82 - } 28 + settings: {} 83 29 };
+53
packages/core-extensions/src/settings/webpackModules/settings.ts
··· 1 + import { 2 + SettingsSection, 3 + Settings as SettingsType 4 + } from "@moonlight-mod/types/coreExtensions"; 5 + 6 + export const Settings: SettingsType = { 7 + ourSections: [], 8 + sectionNames: [], 9 + 10 + addSection: (section, label, element, color = null, pos, notice) => { 11 + const data: SettingsSection = { 12 + section, 13 + label, 14 + color, 15 + element, 16 + pos: pos ?? -4, 17 + notice: notice 18 + }; 19 + 20 + Settings.ourSections.push(data); 21 + Settings.sectionNames.push(label); 22 + return data; 23 + }, 24 + 25 + addDivider: (pos = null) => { 26 + Settings.ourSections.push({ 27 + section: "DIVIDER", 28 + pos: pos === null ? -4 : pos 29 + }); 30 + }, 31 + 32 + addHeader: function (label, pos = null) { 33 + Settings.ourSections.push({ 34 + section: "HEADER", 35 + label: label, 36 + pos: pos === null ? -4 : pos 37 + }); 38 + }, 39 + 40 + _mutateSections: (sections) => { 41 + for (const section of Settings.ourSections) { 42 + sections.splice( 43 + section.pos < 0 ? sections.length + section.pos : section.pos, 44 + 0, 45 + section 46 + ); 47 + } 48 + 49 + return sections; 50 + } 51 + }; 52 + 53 + export default Settings;
+8 -3
packages/types/src/discord/require.ts
··· 12 12 default: Spacepack; 13 13 spacepack: Spacepack; 14 14 }; 15 - declare function WebpackRequire(id: "common_react"): CommonReact; 15 + 16 + declare function WebpackRequire(id: "common_components"): CommonComponents; 16 17 declare function WebpackRequire(id: "common_flux"): CommonFlux; 17 18 declare function WebpackRequire( 18 19 id: "common_fluxDispatcher" 19 20 ): CommonFluxDispatcher; 20 - declare function WebpackRequire(id: "settings_settings"): Settings; 21 - declare function WebpackRequire(id: "common_components"): CommonComponents; 21 + declare function WebpackRequire(id: "common_react"): CommonReact; 22 + 23 + declare function WebpackRequire(id: "settings_settings"): { 24 + Settings: Settings; 25 + default: Settings; 26 + }; 22 27 23 28 export default WebpackRequire;
+18
packages/types/src/import.d.ts
··· 3 3 export const spacepack: Spacepack; 4 4 export default spacepack; 5 5 } 6 + 7 + declare module "@moonlight-mod/wp/common_components" { 8 + import { CommonComponents } from "@moonlight-mod/types/coreExtensions"; 9 + const components: CommonComponents; 10 + export default components; 11 + } 12 + 13 + declare module "@moonlight-mod/wp/common_flux" { 14 + import { CommonFlux } from "@moonlight-mod/types/coreExtensions"; 15 + const Flux: CommonFlux; 16 + export default Flux; 17 + } 18 + 19 + declare module "@moonlight-mod/wp/common_fluxDispatcher" { 20 + import { CommonFluxDispatcher } from "@moonlight-mod/types/coreExtensions"; 21 + const Dispatcher: CommonFluxDispatcher; 22 + export default Dispatcher; 23 + }