From 4b1e96b76ee4eea16fcb3b5cae74e173541b3c74 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 21 Oct 2022 23:58:41 +0200 Subject: [PATCH] Vencord Web: QuickCss Monaco Editor --- browser/VencordNativeStub.ts | 21 +++++++--- src/components/Monaco.ts | 80 ++++++++++++++++++++++++++++++++++++ src/components/Settings.tsx | 9 ++++ src/utils/IpcEvents.ts | 1 + 4 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 src/components/Monaco.ts diff --git a/browser/VencordNativeStub.ts b/browser/VencordNativeStub.ts index b6d1121..ee093fa 100644 --- a/browser/VencordNativeStub.ts +++ b/browser/VencordNativeStub.ts @@ -1,20 +1,28 @@ import IpcEvents from "../src/utils/IpcEvents"; +import * as DataStore from "../src/api/DataStore"; // Discord deletes this so need to store in variable -var { localStorage } = window; +const { localStorage } = window; + +// listeners for ipc.on +const listeners = {} as Record>; const handlers = { - [IpcEvents.GET_REPO]: () => "", // TODO + [IpcEvents.GET_REPO]: () => "https://github.com/Vendicated/Vencord", // shrug [IpcEvents.GET_SETTINGS_DIR]: () => "LocalStorage", - [IpcEvents.GET_QUICK_CSS]: () => localStorage.getItem("VencordQuickCss"), + [IpcEvents.GET_QUICK_CSS]: () => DataStore.get("VencordQuickCss").then(s => s ?? ""), + [IpcEvents.SET_QUICK_CSS]: (css: string) => { + DataStore.set("VencordQuickCss", css); + listeners[IpcEvents.QUICK_CSS_UPDATE]?.forEach(l => l(null, css)); + }, + [IpcEvents.GET_SETTINGS]: () => localStorage.getItem("VencordSettings") || "{}", [IpcEvents.SET_SETTINGS]: (s: string) => localStorage.setItem("VencordSettings", s), [IpcEvents.GET_UPDATES]: () => ({ ok: true, value: [] }), [IpcEvents.OPEN_EXTERNAL]: (url: string) => open(url, "_blank"), - [IpcEvents.OPEN_QUICKCSS]: () => { } // TODO }; function onEvent(event: string, ...args: any[]) { @@ -23,16 +31,17 @@ function onEvent(event: string, ...args: any[]) { return handler(...args); } +// probably should make this less cursed at some point window.VencordNative = { getVersions: () => ({}), ipc: { send: (event: string, ...args: any[]) => void onEvent(event, ...args), sendSync: onEvent, on(event: string, listener: () => {}) { - // TODO quickCss + (listeners[event] ??= new Set()).add(listener); }, off(event: string, listener: () => {}) { - // not used for now + return listeners[event]?.delete(listener); }, invoke: (event: string, ...args: any[]) => Promise.resolve(onEvent(event, ...args)) }, diff --git a/src/components/Monaco.ts b/src/components/Monaco.ts new file mode 100644 index 0000000..b23d27b --- /dev/null +++ b/src/components/Monaco.ts @@ -0,0 +1,80 @@ +// this is not actually a Component but I'll put it here anyway trolley + +import { IpcEvents } from "../utils"; +import { debounce } from "../utils/debounce"; +import { find } from "../webpack/webpack"; + +const setCss = debounce((css: string) => { + VencordNative.ipc.invoke(IpcEvents.SET_QUICK_CSS, css); +}); + +// FIXME: Discord Desktop support. +// open() fails to create the popup and returns null. Probably have to +// do some logic in main + +// adapted from https://stackoverflow.com/a/63179814 +export async function launchMonacoEditor() { + // TODO: Making the popup larger does not enlarge the editor and instead + // just adds white space + const win = open("about:blank", void 0, "popup,width=1000,height=1000")!; + + win.getCurrentCss = () => VencordNative.ipc.invoke(IpcEvents.GET_QUICK_CSS); + win.callback = (editor: any) => { + editor.onDidChangeModelContent(() => + setCss(editor.getValue()) + ); + }; + + let { theme } = find(m => m.ProtoClass?.typeName.endsWith("PreloadedUserSettings")) + .getCurrentValue().appearance; + theme = theme === 1 ? "vs-dark" : "vs-light"; + + // problem? + win.document.write(` + + + + + + QuickCss Editor + + + + +
+ + + + + + +`); +} diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index ba7d71d..e3d40f1 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -5,6 +5,7 @@ import { useAwaiter } from "../utils/misc"; import { Alerts, Button, Forms, Margins, Parser, React, Switch } from "../webpack/common"; import ErrorBoundary from "./ErrorBoundary"; import { Flex } from "./Flex"; +import { launchMonacoEditor } from "./Monaco"; export default ErrorBoundary.wrap(function Settings() { const [settingsDir, , settingsDirPending] = useAwaiter(() => VencordNative.ipc.invoke(IpcEvents.GET_SETTINGS_DIR), "Loading..."); @@ -66,6 +67,14 @@ export default ErrorBoundary.wrap(function Settings() { } + {IS_WEB && } + >(obj: T): T { export default strEnum({ QUICK_CSS_UPDATE: "VencordQuickCssUpdate", GET_QUICK_CSS: "VencordGetQuickCss", + SET_QUICK_CSS: "VencordSetQuickCss", GET_SETTINGS_DIR: "VencordGetSettingsDir", GET_SETTINGS: "VencordGetSettings", SET_SETTINGS: "VencordSetSettings",