From 61c94f40d31eaf3c340943e3d22aa22084673eb2 Mon Sep 17 00:00:00 2001 From: Oj Date: Wed, 7 Apr 2021 16:56:51 +0100 Subject: [PATCH] [PCCompat] Rewrite to use seperate global dir and object, other structural changes --- moduleWrappers/powercord/entities.js | 129 +------------------- moduleWrappers/powercord/global/commands.js | 33 +++++ moduleWrappers/powercord/global/index.js | 11 ++ moduleWrappers/powercord/global/notices.js | 5 + moduleWrappers/powercord/global/settings.js | 39 ++++++ moduleWrappers/powercord/util/settings.js | 33 +++++ package.json | 4 +- src/preprocessors/pcPlugin.js | 2 +- 8 files changed, 130 insertions(+), 126 deletions(-) create mode 100644 moduleWrappers/powercord/global/commands.js create mode 100644 moduleWrappers/powercord/global/index.js create mode 100644 moduleWrappers/powercord/global/notices.js create mode 100644 moduleWrappers/powercord/global/settings.js create mode 100644 moduleWrappers/powercord/util/settings.js diff --git a/moduleWrappers/powercord/entities.js b/moduleWrappers/powercord/entities.js index f1d70fa..0e0e0d0 100644 --- a/moduleWrappers/powercord/entities.js +++ b/moduleWrappers/powercord/entities.js @@ -1,140 +1,21 @@ -// Also set Powercord global var stuff here since entities import is needed to use Plugin (which every PC plugin uses) - -const sendMessage = goosemodScope.webpackModules.findByProps('sendMessage', 'receiveMessage').sendMessage; -const getChannelId = goosemod.webpackModules.findByProps('getChannelId').getChannelId; - -export const powercord = { - api: { - commands: { - registerCommand: ({ command, alias, description, usage, executor }) => { - // TODO: implement alias - - goosemodScope.patcher.commands.add(command, description, - async ( { args: [ { text } ] } ) => { - const out = await executor(text.split(' ')); // Run original executor func (await incase it's an async function) - - if (!out.send) { - goosemodScope.patcher.internalMessage(out.result); // PC impl. sends internal message when out.send === false, so we also do the same via our previous Patcher API function - - return; - } - - // When send is true, we send it as a message via sendMessage - - sendMessage(getChannelId(), { - content: out.result, - - tts: false, - invalidEmojis: [], - validNonShortcutEmojis: [] - }); - }, [ - { type: 3, required: false, name: 'args', description: 'Arguments for PC command' } // Argument for any string for compat. with PC's classical commands - ]); - }, - - unregisterCommand: (command) => { - goosemodScope.patcher.commands.remove(command); - } - }, - - notices: { - sendToast: (_id, { header, content, type, buttons }) => { - // TODO: implement full toast in future instead of just small current GM toast - - goosemodScope.showToast(content); - } - }, - - settings: { - registerSettings: (id, { label, render, category }) => { - const { React } = goosemodScope.webpackModules.common; - - const SettingsView = goosemodScope.webpackModules.findByDisplayName('SettingsView'); - - const FormTitle = goosemodScope.webpackModules.findByDisplayName('FormTitle'); - const FormSection = goosemodScope.webpackModules.findByDisplayName('FormSection'); - - goosemodScope.patcher.inject(id, SettingsView.prototype, 'getPredicateSections', (_, sections) => { - if (!sections.find(c => c.section === 'changelog')) return sections; - - const dividers = sections.filter(c => c.section === 'DIVIDER'); - - const finalLabel = typeof label === 'function' ? label() : label; - - sections.splice(sections.indexOf(dividers[dividers.length - 2]) - 2, 0, - { - section: finalLabel, - label: finalLabel, - predicate: () => { }, - element: () => React.createElement(FormSection, { }, - React.createElement(FormTitle, { tag: 'h2' }, finalLabel), - - render({ - getSetting: settingStores[category].getSetting, - updateSetting: settingStores[category].updateSetting - }) - ) - } - ); - - return sections; - }); - }, - - unregisterSettings: (id) => { - goosemodScope.patcher.uninject(id); - } - } - } -}; - -const settingStores = {}; - -class SimpleStore { - constructor() { - this.store = {}; - } - - getSetting = (key, defaultValue) => { - return this.store[key] ?? defaultValue; - } - - updateSetting = (key, value) => { - if (value === undefined) { - return this.toggleSetting(key); - } - - this.store[key] = value; - } - - toggleSetting = (key) => { - this.store[key] = !this.store[key]; - } - - deleteSetting = (key) => { - delete this.store[key]; - } - - getKeys = () => Object.keys(this.store) -} +import * as Settings from './util/settings'; export class Plugin { constructor() { } - loadStylesheet(path) { + loadStylesheet(path) { // TODO: actually implement this func const url = `https://raw.githubusercontent.com/${this.github.repo}/main/${path}`; return url; } - delayedConstructor() { + delayedConstructor() { // Run funcs which rely on after eval (GooseMod sets keys on this class with more info, mostly metadata) if (this.delayedConstructed) return; this.delayedConstructed = true; - settingStores[this.entityID] = new SimpleStore(); + Settings.makeStore(this.entityID); } get entityID() { @@ -142,7 +23,7 @@ export class Plugin { } get settings() { - const store = settingStores[this.entityID]; + const store = Settings.settingStores[this.entityID]; return { // Basic wrapper with renamed functions get: store.getSetting, diff --git a/moduleWrappers/powercord/global/commands.js b/moduleWrappers/powercord/global/commands.js new file mode 100644 index 0000000..f8cbb87 --- /dev/null +++ b/moduleWrappers/powercord/global/commands.js @@ -0,0 +1,33 @@ +const sendMessage = goosemodScope.webpackModules.findByProps('sendMessage', 'receiveMessage').sendMessage; +const getChannelId = goosemod.webpackModules.findByProps('getChannelId').getChannelId; + +export const registerCommand = ({ command, alias, description, usage, executor }) => { + // TODO: implement alias + + goosemodScope.patcher.commands.add(command, description, + async ( { args: [ { text } ] } ) => { + const out = await executor(text.split(' ')); // Run original executor func (await incase it's an async function) + + if (!out.send) { + goosemodScope.patcher.internalMessage(out.result); // PC impl. sends internal message when out.send === false, so we also do the same via our previous Patcher API function + + return; + } + + // When send is true, we send it as a message via sendMessage + + sendMessage(getChannelId(), { + content: out.result, + + tts: false, + invalidEmojis: [], + validNonShortcutEmojis: [] + }); + }, [ + { type: 3, required: false, name: 'args', description: 'Arguments for PC command' } // Argument for any string for compat. with PC's classical commands + ]); +}; + +export const unregisterCommand = (command) => { + goosemodScope.patcher.commands.remove(command); +}; \ No newline at end of file diff --git a/moduleWrappers/powercord/global/index.js b/moduleWrappers/powercord/global/index.js new file mode 100644 index 0000000..32e747b --- /dev/null +++ b/moduleWrappers/powercord/global/index.js @@ -0,0 +1,11 @@ +import * as commands from './commands.js'; +import * as notices from './notices.js'; +import * as settings from './settings.js'; + +export default { + api: { + commands, + notices, + settings + } +}; \ No newline at end of file diff --git a/moduleWrappers/powercord/global/notices.js b/moduleWrappers/powercord/global/notices.js new file mode 100644 index 0000000..d6e012b --- /dev/null +++ b/moduleWrappers/powercord/global/notices.js @@ -0,0 +1,5 @@ +export const sendToast = (_id, { header, content, type, buttons }) => { + // TODO: implement full toast in future instead of just small current GM toast + + goosemodScope.showToast(content); +}; \ No newline at end of file diff --git a/moduleWrappers/powercord/global/settings.js b/moduleWrappers/powercord/global/settings.js new file mode 100644 index 0000000..eb19955 --- /dev/null +++ b/moduleWrappers/powercord/global/settings.js @@ -0,0 +1,39 @@ +import * as Settings from '../util/settings'; + +export const registerSettings = (id, { label, render, category }) => { + const { React } = goosemodScope.webpackModules.common; + + const SettingsView = goosemodScope.webpackModules.findByDisplayName('SettingsView'); + + const FormTitle = goosemodScope.webpackModules.findByDisplayName('FormTitle'); + const FormSection = goosemodScope.webpackModules.findByDisplayName('FormSection'); + + goosemodScope.patcher.inject(id, SettingsView.prototype, 'getPredicateSections', (_, sections) => { + if (!sections.find(c => c.section === 'changelog')) return sections; + + const dividers = sections.filter(c => c.section === 'DIVIDER'); + + const finalLabel = typeof label === 'function' ? label() : label; + + sections.splice(sections.indexOf(dividers[dividers.length - 2]) - 2, 0, + { + section: finalLabel, + label: finalLabel, + predicate: () => { }, + element: () => React.createElement(FormSection, { }, + React.createElement(FormTitle, { tag: 'h2' }, finalLabel), + + render({ + ...Settings.settingStores[category] + }) + ) + } + ); + + return sections; + }); +}; + +export const unregisterSettings = (id) => { + goosemodScope.patcher.uninject(id); +}; \ No newline at end of file diff --git a/moduleWrappers/powercord/util/settings.js b/moduleWrappers/powercord/util/settings.js new file mode 100644 index 0000000..bde6780 --- /dev/null +++ b/moduleWrappers/powercord/util/settings.js @@ -0,0 +1,33 @@ +export const settingStores = {}; + +export const makeStore = (key) => { + settingStores[key] = new SimpleStore(); +}; + +class SimpleStore { + constructor() { + this.store = {}; + } + + getSetting = (key, defaultValue) => { + return this.store[key] ?? defaultValue; + } + + updateSetting = (key, value) => { + if (value === undefined) { + return this.toggleSetting(key); + } + + this.store[key] = value; + } + + toggleSetting = (key) => { + this.store[key] = !this.store[key]; + } + + deleteSetting = (key) => { + delete this.store[key]; + } + + getKeys = () => Object.keys(this.store) +} \ No newline at end of file diff --git a/package.json b/package.json index cf9acf6..a4b78e1 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,9 @@ "powercord/injector": "./moduleWrappers/powercord/injector.js", "powercord/webpack": "./moduleWrappers/powercord/webpack.js", "powercord/util": "./moduleWrappers/powercord/util.js", - "powercord/components/settings": "./moduleWrappers/powercord/components/settings.js" + "powercord/components/settings": "./moduleWrappers/powercord/components/settings.js", + + "_powercord/global": "./moduleWrappers/powercord/global/index.js" }, "type": "module" } diff --git a/src/preprocessors/pcPlugin.js b/src/preprocessors/pcPlugin.js index 5c2e11f..2036f78 100644 --- a/src/preprocessors/pcPlugin.js +++ b/src/preprocessors/pcPlugin.js @@ -19,7 +19,7 @@ export default (manifestPath, repo) => { const content = readFileSync(pcManifest.main || 'index.js', 'utf8');//.replace(/\\/g, '\\\\').replace(/`/g, '\\`'); - const jsCode = content.replace(`module.exports = class`, `export default new class`).replace(/{ *Plugin *}/, `{ Plugin, powercord }`); + const jsCode = `import powercord from '_powercord/global';\n` + content.replace(`module.exports = class`, `export default new class`); writeFileSync(`${manifestPath}/goosemodModule.json`, JSON.stringify(manifest)); writeFileSync(`${manifestPath}/../index.js`, jsCode);