From 7e0532444d5a980d2d24371664614653446d054e Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 9 Apr 2023 00:49:47 +0200 Subject: [PATCH] Initial Settings UI work --- README.md | 2 ++ package.json | 2 +- scripts/{ => build}/build.mts | 5 +++ scripts/build/injectReact.mjs | 3 ++ scripts/build/tsconfig.esbuild.json | 7 ++++ scripts/startWatch.mts | 2 +- src/main/index.ts | 14 +++----- src/main/settings.ts | 34 +++++-------------- src/renderer/index.ts | 1 + src/renderer/settings.ts | 28 ++++++++++++++++ src/renderer/ui/Settings.tsx | 36 +++++++++++++++++++++ src/renderer/ui/patchSettings.ts | 15 +++++++++ src/renderer/vencord.ts | 12 +++++++ src/shared/settings.d.ts | 12 +++++++ src/shared/utils/makeChangeListenerProxy.ts | 20 ++++++++++++ src/shared/utils/monkeyPatch.ts | 13 ++++++++ 16 files changed, 169 insertions(+), 37 deletions(-) rename scripts/{ => build}/build.mts (81%) create mode 100644 scripts/build/injectReact.mjs create mode 100644 scripts/build/tsconfig.esbuild.json create mode 100644 src/renderer/settings.ts create mode 100644 src/renderer/ui/Settings.tsx create mode 100644 src/renderer/ui/patchSettings.ts create mode 100644 src/renderer/vencord.ts create mode 100644 src/shared/settings.d.ts create mode 100644 src/shared/utils/makeChangeListenerProxy.ts create mode 100644 src/shared/utils/monkeyPatch.ts diff --git a/README.md b/README.md index fc820a9..592598d 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ pnpm start # Or package pnpm package +# Or only build the pacman target +pnpm package --linux pacman # Or package to a directory only pnpm package:dir ``` diff --git a/package.json b/package.json index ed67c48..ee6376e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "author": "Vendicated ", "main": "dist/js/main.js", "scripts": { - "build": "tsx scripts/build.mts", + "build": "tsx scripts/build/build.mts", "package": "pnpm build && electron-builder", "package:dir": "pnpm build && electron-builder --dir", "start": "pnpm build && electron .", diff --git a/scripts/build.mts b/scripts/build/build.mts similarity index 81% rename from scripts/build.mts rename to scripts/build/build.mts index ce24951..cc52a90 100644 --- a/scripts/build.mts +++ b/scripts/build/build.mts @@ -36,6 +36,11 @@ await Promise.all([ entryPoints: ["src/renderer/index.ts"], outfile: "dist/js/renderer.js", format: "iife", + inject: ["./scripts/build/injectReact.mjs"], + jsxFactory: "VencordCreateElement", + jsxFragment: "VencordFragment", + // Work around https://github.com/evanw/esbuild/issues/2460 + tsconfig: "./scripts/build/tsconfig.esbuild.json" }) ]); diff --git a/scripts/build/injectReact.mjs b/scripts/build/injectReact.mjs new file mode 100644 index 0000000..0890ac0 --- /dev/null +++ b/scripts/build/injectReact.mjs @@ -0,0 +1,3 @@ +export const VencordFragment = /* #__PURE__*/ Symbol.for("react.fragment"); +export let VencordCreateElement = + (...args) => (VencordCreateElement = Vencord.Webpack.Common.React.createElement)(...args); diff --git a/scripts/build/tsconfig.esbuild.json b/scripts/build/tsconfig.esbuild.json new file mode 100644 index 0000000..e3e28a1 --- /dev/null +++ b/scripts/build/tsconfig.esbuild.json @@ -0,0 +1,7 @@ +// Work around https://github.com/evanw/esbuild/issues/2460 +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "react" + } +} diff --git a/scripts/startWatch.mts b/scripts/startWatch.mts index c84f149..8dad898 100644 --- a/scripts/startWatch.mts +++ b/scripts/startWatch.mts @@ -11,5 +11,5 @@ function spawn(bin: string, args: string[]) { cpSpawn(join("node_modules", ".bin", bin + EXT), args, OPTS); } -spawn("tsx", ["scripts/build.mts", "--", "--watch"]); +spawn("tsx", ["scripts/build/build.mts", "--", "--watch"]); spawn("electron", ["."]); diff --git a/src/main/index.ts b/src/main/index.ts index 7454f4e..97e22ce 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,17 +1,13 @@ import { app, BrowserWindow } from 'electron'; -import { createMainWindow } from "./mainWindow"; -import { createSplashWindow } from "./splash"; - import { join } from "path"; - -import { DATA_DIR, VENCORD_FILES_DIR } from "./constants"; - -import { once } from "../shared/utils/once"; -import { ensureVencordFiles } from "./utils/vencordLoader"; - import { ICON_PATH } from "../shared/paths"; +import { once } from "../shared/utils/once"; +import { DATA_DIR, VENCORD_FILES_DIR } from "./constants"; import "./ipc"; +import { createMainWindow } from "./mainWindow"; import { Settings } from "./settings"; +import { createSplashWindow } from "./splash"; +import { ensureVencordFiles } from "./utils/vencordLoader"; // Make the Vencord files use our DATA_DIR process.env.VENCORD_USER_DATA_DIR = DATA_DIR; diff --git a/src/main/settings.ts b/src/main/settings.ts index e00e452..76a79d4 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -1,23 +1,12 @@ import { readFileSync, writeFileSync } from "fs"; import { join } from "path"; +import type { Settings as TSettings } from "shared/settings"; +import { makeChangeListenerProxy } from "shared/utils/makeChangeListenerProxy"; import { DATA_DIR } from "./constants"; const SETTINGS_FILE = join(DATA_DIR, "settings.json"); -interface Settings { - maximized?: boolean; - minimized?: boolean; - windowBounds?: { - x: number; - y: number; - width: number; - height: number; - }; - discordBranch?: "stable" | "canary" | "ptb"; - openLinksWithElectron?: boolean; -} - -export let PlainSettings = {} as Settings; +export let PlainSettings = {} as TSettings; try { const content = readFileSync(SETTINGS_FILE, "utf8"); try { @@ -27,21 +16,14 @@ try { } } catch { } -function makeSettingsProxy(settings: Settings) { - return new Proxy(settings, { - set(target, prop, value) { - Reflect.set(target, prop, value); - - writeFileSync(SETTINGS_FILE, JSON.stringify(target, null, 4)); - - return true; - } - }); -} +const makeSettingsProxy = (settings: TSettings) => makeChangeListenerProxy( + settings, + target => writeFileSync(SETTINGS_FILE, JSON.stringify(target, null, 4)) +); export let Settings = makeSettingsProxy(PlainSettings); -export function setSettings(settings: Settings) { +export function setSettings(settings: TSettings) { writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 4)); PlainSettings = settings; Settings = makeSettingsProxy(settings); diff --git a/src/renderer/index.ts b/src/renderer/index.ts index 7c17265..432f846 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -1,3 +1,4 @@ import "./fixes"; +import "./ui/patchSettings"; console.log("read if cute :3"); diff --git a/src/renderer/settings.ts b/src/renderer/settings.ts new file mode 100644 index 0000000..80070b8 --- /dev/null +++ b/src/renderer/settings.ts @@ -0,0 +1,28 @@ +import type { Settings as TSettings } from "shared/settings"; +import { makeChangeListenerProxy } from "shared/utils/makeChangeListenerProxy"; +import { Common } from "./vencord"; + +const signals = new Set<() => void>(); + +export const PlainSettings = VencordDesktop.settings.get() as TSettings; +export const Settings = makeChangeListenerProxy(PlainSettings, s => { + VencordDesktop.settings.set(s); + signals.forEach(fn => fn()); +}); + +export function useSettings() { + const [, update] = Common.React.useReducer(x => x + 1, 0); + Common.React.useEffect(() => { + signals.add(update); + return () => signals.delete(update); + }, []); + + return Settings; +} + +export function getValueAndOnChange(key: keyof TSettings) { + return { + value: Settings[key] as any, + onChange: (value: any) => Settings[key] = value + }; +} diff --git a/src/renderer/ui/Settings.tsx b/src/renderer/ui/Settings.tsx new file mode 100644 index 0000000..29fb259 --- /dev/null +++ b/src/renderer/ui/Settings.tsx @@ -0,0 +1,36 @@ +import { getValueAndOnChange, useSettings } from "renderer/settings"; +import { Common } from "../vencord"; + +export default function SettingsUi() { + const Settings = useSettings(); + const { Forms: { FormSection, FormText, FormDivider, FormSwitch, FormTitle }, Text, Select } = Common; + + return ( + + + Vencord Desktop Settings + + + Discord Branch +