···
import { Config, ExtensionLoadSource } from "@moonlight-mod/types";
2
+
import { ExtensionState, MoonbaseExtension, MoonbaseNatives } from "../types";
import Flux from "@moonlight-mod/wp/common_flux";
import Dispatcher from "@moonlight-mod/wp/common_fluxDispatcher";
···
class MoonbaseSettingsStore extends Flux.Store<any> {
private origConfig: Config;
12
+
private extensionIndex: number;
22
-
extensions: { [id: string]: MoonbaseExtension };
23
-
updates: { [id: string]: { version: string; download: string } };
18
+
extensions: { [id: number]: MoonbaseExtension };
19
+
updates: { [id: number]: { version: string; download: string } };
this.origConfig = moonlightNode.config;
this.config = this.clone(this.origConfig);
26
+
this.extensionIndex = 0;
···
for (const ext of moonlightNode.extensions) {
38
-
const existingExtension = this.extensions[ext.id];
39
-
if (existingExtension != null) continue;
41
-
this.extensions[ext.id] = {
35
+
const uniqueId = this.extensionIndex++;
36
+
this.extensions[uniqueId] = {
state: moonlight.enabledExtensions.has(ext.id)
: ExtensionState.Disabled
···
for (const [repo, exts] of Object.entries(ret)) {
for (const ext of exts) {
54
-
const existingExtension = this.extensions[ext.id];
55
-
if (existingExtension !== undefined) {
56
-
if (this.hasUpdate(repo, ext, existingExtension)) {
57
-
this.updates[ext.id] = {
58
-
version: ext.version!,
59
-
download: ext.download
49
+
const uniqueId = this.extensionIndex++;
50
+
const extensionData = {
54
+
source: { type: ExtensionLoadSource.Normal, url: repo },
55
+
state: ExtensionState.NotDownloaded
63
-
this.extensions[ext.id].manifest = ext;
64
-
this.extensions[ext.id].source = {
65
-
type: ExtensionLoadSource.Normal,
58
+
if (this.alreadyExists(extensionData)) {
59
+
if (this.hasUpdate(extensionData)) {
60
+
this.updates[uniqueId] = {
61
+
version: ext.version!,
62
+
download: ext.download
72
-
this.extensions[ext.id] = {
75
-
source: { type: ExtensionLoadSource.Normal, url: repo },
76
-
state: ExtensionState.NotDownloaded
79
-
logger.error(`Error processing extension ${ext.id}`, e);
69
+
this.extensions[uniqueId] = extensionData;
logger.error(`Error processing repository ${repo}`, e);
···
91
-
// this logic sucks so bad lol
94
-
repoExt: RepositoryManifest,
95
-
existing: MoonbaseExtension
80
+
private alreadyExists(ext: MoonbaseExtension) {
81
+
return Object.values(this.extensions).some(
82
+
(e) => e.id === ext.id && e.source.url === ext.source.url
86
+
private hasUpdate(ext: MoonbaseExtension) {
87
+
const existing = Object.values(this.extensions).find(
88
+
(e) => e.id === ext.id && e.source.url === ext.source.url
90
+
if (existing == null) return false;
98
-
existing.source.type === ExtensionLoadSource.Normal &&
99
-
existing.source.url != null &&
100
-
existing.source.url === repo &&
101
-
repoExt.version != null &&
102
-
existing.manifest.version !== repoExt.version
93
+
existing.manifest.version !== ext.manifest.version &&
94
+
existing.state !== ExtensionState.NotDownloaded
···
121
-
getExtension(id: string) {
122
-
return this.extensions[id];
113
+
getExtension(uniqueId: number) {
114
+
return this.extensions[uniqueId];
125
-
getExtensionName(id: string) {
126
-
return Object.prototype.hasOwnProperty.call(this.extensions, id)
127
-
? this.extensions[id].manifest.meta?.name ?? id
117
+
getExtensionUniqueId(id: string) {
118
+
return Object.values(this.extensions).find((ext) => ext.id === id)
122
+
getExtensionConflicting(uniqueId: number) {
123
+
const ext = this.getExtension(uniqueId);
124
+
if (ext.state !== ExtensionState.NotDownloaded) return false;
125
+
return Object.values(this.extensions).some(
128
+
e.uniqueId !== uniqueId &&
129
+
e.state !== ExtensionState.NotDownloaded
133
+
getExtensionName(uniqueId: number) {
134
+
const ext = this.getExtension(uniqueId);
135
+
return ext.manifest.meta?.name ?? ext.id;
131
-
getExtensionUpdate(id: string) {
132
-
return Object.prototype.hasOwnProperty.call(this.updates, id)
138
+
getExtensionUpdate(uniqueId: number) {
139
+
return this.updates[uniqueId]?.version;
137
-
getExtensionEnabled(id: string) {
138
-
const val = this.config.extensions[id];
142
+
getExtensionEnabled(uniqueId: number) {
143
+
const ext = this.getExtension(uniqueId);
144
+
if (ext.state === ExtensionState.NotDownloaded) return false;
145
+
const val = this.config.extensions[ext.id];
if (val == null) return false;
return typeof val === "boolean" ? val : val.enabled;
143
-
getExtensionConfig<T>(id: string, key: string): T | undefined {
144
-
const defaultValue = this.extensions[id].manifest.settings?.[key]?.default;
150
+
getExtensionConfig<T>(uniqueId: number, key: string): T | undefined {
151
+
const ext = this.getExtension(uniqueId);
152
+
const defaultValue = ext.manifest.settings?.[key]?.default;
const clonedDefaultValue = this.clone(defaultValue);
146
-
const cfg = this.config.extensions[id];
154
+
const cfg = this.config.extensions[ext.id];
if (cfg == null || typeof cfg === "boolean") return clonedDefaultValue;
return cfg.config?.[key] ?? clonedDefaultValue;
152
-
getExtensionConfigName(id: string, key: string) {
153
-
return this.extensions[id].manifest.settings?.[key]?.displayName ?? key;
160
+
getExtensionConfigName(uniqueId: number, key: string) {
161
+
const ext = this.getExtension(uniqueId);
162
+
return ext.manifest.settings?.[key]?.displayName ?? key;
156
-
getExtensionConfigDescription(id: string, key: string) {
157
-
return this.extensions[id].manifest.settings?.[key]?.description;
165
+
getExtensionConfigDescription(uniqueId: number, key: string) {
166
+
const ext = this.getExtension(uniqueId);
167
+
return ext.manifest.settings?.[key]?.description;
160
-
setExtensionConfig(id: string, key: string, value: any) {
161
-
const oldConfig = this.config.extensions[id];
170
+
setExtensionConfig(uniqueId: number, key: string, value: any) {
171
+
const ext = this.getExtension(uniqueId);
172
+
const oldConfig = this.config.extensions[ext.id];
typeof oldConfig === "boolean"
···
config: { ...(oldConfig?.config ?? {}), [key]: value }
173
-
this.config.extensions[id] = newConfig;
184
+
this.config.extensions[ext.id] = newConfig;
this.modified = this.isModified();
178
-
setExtensionEnabled(id: string, enabled: boolean) {
179
-
let val = this.config.extensions[id];
189
+
setExtensionEnabled(uniqueId: number, enabled: boolean) {
190
+
const ext = this.getExtension(uniqueId);
191
+
let val = this.config.extensions[ext.id];
182
-
this.config.extensions[id] = { enabled };
194
+
this.config.extensions[ext.id] = { enabled };
this.modified = this.isModified();
···
194
-
this.config.extensions[id] = val;
206
+
this.config.extensions[ext.id] = val;
this.modified = this.isModified();
199
-
async installExtension(id: string) {
200
-
const ext = this.getExtension(id);
211
+
async installExtension(uniqueId: number) {
212
+
const ext = this.getExtension(uniqueId);
if (!("download" in ext.manifest)) {
throw new Error("Extension has no download URL");
207
-
const url = this.updates[id]?.download ?? ext.manifest.download;
219
+
const url = this.updates[uniqueId]?.download ?? ext.manifest.download;
await natives.installExtension(ext.manifest, url, ext.source.url!);
if (ext.state === ExtensionState.NotDownloaded) {
210
-
this.extensions[id].state = ExtensionState.Disabled;
222
+
this.extensions[uniqueId].state = ExtensionState.Disabled;
213
-
delete this.updates[id];
225
+
delete this.updates[uniqueId];
logger.error("Error installing extension:", e);
···
222
-
async deleteExtension(id: string) {
223
-
const ext = this.getExtension(id);
234
+
async deleteExtension(uniqueId: number) {
235
+
const ext = this.getExtension(uniqueId);
await natives.deleteExtension(ext.id);
229
-
this.extensions[id].state = ExtensionState.NotDownloaded;
241
+
this.extensions[uniqueId].state = ExtensionState.NotDownloaded;
logger.error("Error deleting extension:", e);