diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e53c37..459edac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,19 +26,3 @@ jobs: with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} RELEASE: true - - - name: Update AUR package - if: ${{ matrix.os == 'ubuntu-latest' }} - run: | - mkdir -p -m 700 ~/.ssh - echo $SSH_KEY > ~/.ssh/aur - echo $SSH_PUB_KEY > ~/.ssh/aur.pub - chmod 600 ~/.ssh/* - - export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur" - - sudo ./scripts/ci/install_makepkg.sh - ./scripts/ci/aur_bump.sh - env: - SSH_KEY: ${{ secrets.AUR_SSH_KEY }} - SSH_PUB_KEY: ${{ secrets.AUR_SSH_PUB_KEY }} diff --git a/README.md b/README.md index 2b42b9f..537c313 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,16 @@ # Vencord Desktop -A standalone Electron app that loads Discord & Vencord +Vencord Desktop is a cross platform desktop app aiming to give you a snappier Discord experience with Vencord pre-installed -Vencord Desktop is currently in very early alpha. Bug reports, feature requests & contributions are highly appreciated!! +Vencord Desktop is currently in beta + +**Not yet supported**: +- Screensharing +- Global Keybinds + +Bug reports, feature requests & contributions are highly appreciated!! + +![image](https://user-images.githubusercontent.com/45497981/235024615-94565eaf-f412-4384-a3f5-d8cde7458f6d.png) ## Installing diff --git a/package.json b/package.json index a7700e0..41d2385 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "VencordDesktop", - "version": "0.1.8", + "version": "0.2.1", "private": true, "description": "", "keywords": [], @@ -22,11 +22,16 @@ "testTypes": "tsc --noEmit", "watch": "pnpm build --watch" }, + "dependencies": { + "arrpc": "^3.1.0" + }, "devDependencies": { + "@fal-works/esbuild-plugin-global-externals": "^2.1.2", "@types/node": "^18.15.11", "@types/react": "^18.0.33", "@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/parser": "^5.57.1", + "@vencord/types": "^0.1.2", "dotenv": "^16.0.3", "electron": "^23.2.0", "electron-builder": "^23.6.0", @@ -78,11 +83,30 @@ } }, "mac": { + "target": [ + { + "target": "default", + "arch": [ + "x64", + "arm64" + ] + } + ], "category": "Network" }, "nsis": { "include": "build/installer.nsh", "oneClick": false + }, + "win": { + "target": [ + "nsis", + "portable" + ] + }, + "publish": { + "provider": "github", + "releaseType": "release" } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4816cd5..22b617d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,14 @@ lockfileVersion: '6.0' +dependencies: + arrpc: + specifier: ^3.1.0 + version: 3.1.0 + devDependencies: + '@fal-works/esbuild-plugin-global-externals': + specifier: ^2.1.2 + version: 2.1.2 '@types/node': specifier: ^18.15.11 version: 18.15.11 @@ -13,6 +21,9 @@ devDependencies: '@typescript-eslint/parser': specifier: ^5.57.1 version: 5.57.1(eslint@8.38.0)(typescript@5.0.2) + '@vencord/types': + specifier: ^0.1.2 + version: 0.1.2 dotenv: specifier: ^16.0.3 version: 16.0.3 @@ -367,6 +378,10 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@fal-works/esbuild-plugin-global-externals@2.1.2: + resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} + dev: true + /@humanwhocodes/config-array@0.11.8: resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} engines: {node: '>=10.10.0'} @@ -492,6 +507,10 @@ packages: '@types/node': 18.15.11 dev: true + /@types/lodash@4.14.194: + resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==} + dev: true + /@types/minimatch@5.1.2: resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} dev: true @@ -522,6 +541,19 @@ packages: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} dev: true + /@types/react-dom@18.0.11: + resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==} + dependencies: + '@types/react': 18.0.33 + dev: true + + /@types/react@17.0.2: + resolution: {integrity: sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==} + dependencies: + '@types/prop-types': 15.7.5 + csstype: 3.1.2 + dev: true + /@types/react@18.0.33: resolution: {integrity: sha512-sHxzVxeanvQyQ1lr8NSHaj0kDzcNiGpILEVt69g9S31/7PfMvNCKLKcsHw4lYKjs3cGNJjXSP4mYzX43QlnjNA==} dependencies: @@ -698,6 +730,18 @@ packages: eslint-visitor-keys: 3.4.0 dev: true + /@vencord/types@0.1.2: + resolution: {integrity: sha512-C/dqZHn3aod/4izZT9sgZEef4478M7QNKTY8Gx2yB1CRYawJcs6hupXT/1SMmepKqrULbltL04Cnh5ieBm3Ucw==} + dependencies: + '@types/lodash': 4.14.194 + '@types/node': 18.15.11 + '@types/react': 18.0.33 + '@types/react-dom': 18.0.11 + discord-types: 1.3.26 + standalone-electron-types: 1.0.0 + type-fest: 3.8.0 + dev: true + /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -850,6 +894,15 @@ packages: es-shim-unscopables: 1.0.0 dev: true + /arrpc@3.1.0: + resolution: {integrity: sha512-QKagtB5fUDqDXT31tTUzcG3+rFxsMlrjKb3iE68/b2NbT1c6+0WYkkrJh4GaVPqH0Tlqy13sEgPW3XJ/VNmBDQ==} + dependencies: + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + /asar@3.2.0: resolution: {integrity: sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==} engines: {node: '>=10.12.0'} @@ -1342,6 +1395,13 @@ packages: path-type: 4.0.0 dev: true + /discord-types@1.3.26: + resolution: {integrity: sha512-ToG51AOCH+JTQf7b+8vuYQe5Iqwz7nZ7StpECAZ/VZcI1ZhQk13pvt9KkRTfRv1xNvwJ2qib4e3+RifQlo8VPQ==} + dependencies: + '@types/react': 17.0.2 + moment: 2.29.4 + dev: true + /dmg-builder@23.6.0: resolution: {integrity: sha512-jFZvY1JohyHarIAlTbfQOk+HnceGjjAdFjVn3n8xlDWKsYNqbO4muca6qXEZTfGXeQMG7TYim6CeS5XKSfSsGA==} dependencies: @@ -2875,6 +2935,10 @@ packages: hasBin: true dev: true + /moment@2.29.4: + resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + dev: true + /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: true @@ -3390,6 +3454,12 @@ packages: dev: true optional: true + /standalone-electron-types@1.0.0: + resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} + dependencies: + '@types/node': 18.15.11 + dev: true + /stat-mode@1.0.0: resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} engines: {node: '>= 6'} @@ -3729,6 +3799,19 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xmlbuilder@15.1.1: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} diff --git a/scripts/build/build.mts b/scripts/build/build.mts index 11c4d5f..5d2e0ee 100644 --- a/scripts/build/build.mts +++ b/scripts/build/build.mts @@ -6,6 +6,8 @@ import { BuildContext, BuildOptions, context } from "esbuild"; +import vencordDep from "./vencordDep.mjs"; + const isDev = process.argv.includes("--dev"); const CommonOpts: BuildOptions = { @@ -35,17 +37,20 @@ await Promise.all([ createContext({ ...NodeCommonOpts, entryPoints: ["src/main/index.ts"], - outfile: "dist/js/main.js" + outfile: "dist/js/main.js", + footer: { js: "//# sourceURL=VCDMain" } }), createContext({ ...NodeCommonOpts, entryPoints: ["src/preload/index.ts"], - outfile: "dist/js/preload.js" + outfile: "dist/js/preload.js", + footer: { js: "//# sourceURL=VCDPreload" } }), createContext({ ...NodeCommonOpts, entryPoints: ["src/updater/preload.ts"], - outfile: "dist/js/updaterPreload.js" + outfile: "dist/js/updaterPreload.js", + footer: { js: "//# sourceURL=VCDUpdaterPreload" } }), createContext({ ...CommonOpts, @@ -57,7 +62,10 @@ await Promise.all([ jsxFactory: "VencordCreateElement", jsxFragment: "VencordFragment", // Work around https://github.com/evanw/esbuild/issues/2460 - tsconfig: "./scripts/build/tsconfig.esbuild.json" + tsconfig: "./scripts/build/tsconfig.esbuild.json", + external: ["@vencord/types/*"], + plugins: [vencordDep], + footer: { js: "//# sourceURL=VCDRenderer" } }) ]); diff --git a/scripts/build/vencordDep.mts b/scripts/build/vencordDep.mts new file mode 100644 index 0000000..d0c87ce --- /dev/null +++ b/scripts/build/vencordDep.mts @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { globalExternalsWithRegExp } from "@fal-works/esbuild-plugin-global-externals"; + +const names = { + webpack: "Vencord.Webpack", + "webpack/common": "Vencord.Webpack.Common", + utils: "Vencord.Util", + api: "Vencord.Api", + "api/settings": "Vencord", + components: "Vencord.Components" +}; + +export default globalExternalsWithRegExp({ + getModuleInfo(modulePath) { + const path = modulePath.replace("@vencord/types/", ""); + let varName = names[path]; + if (!varName) { + const altMapping = names[path.split("/")[0]]; + if (!altMapping) throw new Error("Unknown module path: " + modulePath); + + varName = + altMapping + + "." + + // @ts-ignore + path.split("/")[1].replaceAll("/", "."); + } + return { + varName, + type: "cjs" + }; + }, + modulePathFilter: /^@vencord\/types.+$/ +}); diff --git a/scripts/ci/aur_bump.sh b/scripts/ci/aur_bump.sh deleted file mode 100755 index b18c21b..0000000 --- a/scripts/ci/aur_bump.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -set -e - -VERSION=$(git describe --tags --abbrev=0 | tr -d 'v') -SHASUM=$(sha256sum "dist/VencordDesktop-$VERSION.tar.gz" | awk '{ print $1 }') - -git clone ssh://aur@aur.archlinux.org/vencord-desktop-bin.git aurpkg - -cd aurpkg - -sed -i "s/^pkgver=.*$/pkgver=$VERSION/" PKGBUILD -sed -i "s/^sha256sums=('.*'/sha256sums=('$SHASUM'/" PKGBUILD -makepkg --printsrcinfo > .SRCINFO - -git commit -a -m "Bump version to $VERSION" -git push - -cd .. -rm -rf aurpkg diff --git a/scripts/ci/install_makepkg.sh b/scripts/ci/install_makepkg.sh deleted file mode 100755 index f741fc0..0000000 --- a/scripts/ci/install_makepkg.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -set -e - -for i in \ - "makepkg_6.0.2-3_amd64.deb" \ - "libalpm13_13.0.2-3_amd64.deb" \ - "pacman-package-manager_6.0.2-3_amd64.deb"; do - wget -O/tmp/$i https://fr.archive.ubuntu.com/ubuntu/pool/universe/p/pacman-package-manager/$i - dpkg -i /tmp/$i || true -done - -apt-get -f install -oDpkg::Use-Pty=0 -qq diff --git a/src/globals.d.ts b/src/globals.d.ts index 606f4f5..f4dcaa9 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -7,8 +7,6 @@ declare global { export var VencordDesktopNative: typeof import("preload/VencordDesktopNative").VencordDesktopNative; export var VencordDesktop: typeof import("renderer/index"); - // TODO - export var Vencord: any; export var vcdLS: typeof localStorage; export var IS_DEV: boolean; diff --git a/src/main/about.ts b/src/main/about.ts index 4daf965..a335b85 100644 --- a/src/main/about.ts +++ b/src/main/about.ts @@ -4,7 +4,8 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { BrowserWindow } from "electron"; +import { app, BrowserWindow } from "electron"; +import { readFileSync } from "fs"; import { join } from "path"; import { ICON_PATH, STATIC_DIR } from "shared/paths"; @@ -19,7 +20,9 @@ export function createAboutWindow() { makeLinksOpenExternally(about); - about.loadFile(join(STATIC_DIR, "about.html")); + const html = readFileSync(join(STATIC_DIR, "about.html"), "utf-8").replaceAll("%VERSION%", app.getVersion()); + + about.loadURL("data:text/html;charset=utf-8," + html); return about; } diff --git a/src/main/arrpc.ts b/src/main/arrpc.ts new file mode 100644 index 0000000..9ea348d --- /dev/null +++ b/src/main/arrpc.ts @@ -0,0 +1,21 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import Server from "arrpc"; +import { send as sendToBridge } from "arrpc/src/bridge"; + +import { Settings } from "./settings"; + +let server: any; + +export async function initArRPC() { + if (server || !Settings.store.arRPC) return; + + server = await new Server(); + server.on("activity", sendToBridge); +} + +Settings.addChangeListener("arRPC", initArRPC); diff --git a/src/main/autoStart.ts b/src/main/autoStart.ts new file mode 100644 index 0000000..17ee6fd --- /dev/null +++ b/src/main/autoStart.ts @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { app } from "electron"; +import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs"; +import { join } from "path"; + +interface AutoStart { + isEnabled(): boolean; + enable(): void; + disable(): void; +} + +function makeAutoStartLinux(): AutoStart { + const dir = join(process.env.HOME!, ".config", "autostart"); + const file = join(dir, "vencord.desktop"); + + return { + isEnabled: () => existsSync(file), + enable() { + const desktopFile = ` +[Desktop Entry] +Type=Application +Version=1.0 +Name=Vencord +Comment=Vencord autostart script +Exec=${process.execPath} +Terminal=false +StartupNotify=false +`.trim(); + + mkdirSync(dir, { recursive: true }); + writeFileSync(file, desktopFile); + }, + disable: () => rmSync(file, { force: true }) + }; +} + +const autoStartWindowsMac: AutoStart = { + isEnabled: () => app.getLoginItemSettings().openAtLogin, + enable: () => app.setLoginItemSettings({ openAtLogin: true }), + disable: () => app.setLoginItemSettings({ openAtLogin: false }) +}; + +export const autoStart = process.platform === "linux" ? makeAutoStartLinux() : autoStartWindowsMac; diff --git a/src/main/firstLaunch.ts b/src/main/firstLaunch.ts new file mode 100644 index 0000000..458c416 --- /dev/null +++ b/src/main/firstLaunch.ts @@ -0,0 +1,67 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { app } from "electron"; +import { BrowserWindow } from "electron/main"; +import { copyFileSync, mkdirSync, readdirSync } from "fs"; +import { join } from "path"; +import { SplashProps } from "shared/browserWinProperties"; +import { STATIC_DIR } from "shared/paths"; + +import { autoStart } from "./autoStart"; +import { DATA_DIR } from "./constants"; +import { createWindows } from "./mainWindow"; +import { Settings } from "./settings"; + +interface Data { + minimizeToTray: boolean; + discordBranch: "stable" | "canary" | "ptb"; + autoStart: boolean; + importSettings: boolean; +} + +export function createFirstLaunchTour() { + const win = new BrowserWindow({ + ...SplashProps, + frame: true, + autoHideMenuBar: true, + height: 420, + width: 550 + }); + + win.loadFile(join(STATIC_DIR, "first-launch.html")); + win.webContents.addListener("console-message", (_e, _l, msg) => { + if (msg === "cancel") return app.exit(); + + if (!msg.startsWith("form:")) return; + const data = JSON.parse(msg.slice(5)) as Data; + + Settings.store.minimizeToTray = data.minimizeToTray; + Settings.store.discordBranch = data.discordBranch; + Settings.store.firstLaunch = false; + + if (data.autoStart) autoStart.enable(); + + if (data.importSettings) { + const from = join(app.getPath("userData"), "..", "Vencord", "settings"); + const to = join(DATA_DIR, "settings"); + try { + const files = readdirSync(from); + mkdirSync(to, { recursive: true }); + + for (const file of files) { + copyFileSync(join(from, file), join(to, file)); + } + } catch (e) { + console.error("Failed to import settings:", e); + } + } + + win.close(); + + createWindows(); + }); +} diff --git a/src/main/index.ts b/src/main/index.ts index 4671cfb..4730d63 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -7,16 +7,14 @@ import "./ipc"; import { app, BrowserWindow } from "electron"; -import { join } from "path"; import { checkUpdates } from "updater/main"; import { ICON_PATH } from "../shared/paths"; -import { once } from "../shared/utils/once"; -import { DATA_DIR, VENCORD_FILES_DIR } from "./constants"; -import { createMainWindow } from "./mainWindow"; +import { DATA_DIR } from "./constants"; +import { createFirstLaunchTour } from "./firstLaunch"; +import { createWindows, mainWin } from "./mainWindow"; import { Settings } from "./settings"; -import { createSplashWindow } from "./splash"; -import { ensureVencordFiles } from "./utils/vencordLoader"; + if (IS_DEV) { require("source-map-support").install(); } @@ -24,11 +22,21 @@ if (IS_DEV) { // Make the Vencord files use our DATA_DIR process.env.VENCORD_USER_DATA_DIR = DATA_DIR; -const runVencordMain = once(() => require(join(VENCORD_FILES_DIR, "vencordDesktopMain.js"))); - -let mainWin: BrowserWindow | null = null; - function init() { + // <-- BEGIN COPY PASTED FROM DISCORD --> + + // work around chrome 66 disabling autoplay by default + app.commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required"); + + // WinRetrieveSuggestionsOnlyOnDemand: Work around electron 13 bug w/ async spellchecking on Windows. + // HardwareMediaKeyHandling,MediaSessionService: Prevent Discord from registering as a media service. + app.commandLine.appendSwitch( + "disable-features", + "WinRetrieveSuggestionsOnlyOnDemand,HardwareMediaKeyHandling,MediaSessionService" + ); + + // <-- END COPY PASTED FROM DISCORD --> + app.on("second-instance", (_event, _cmdLine, _cwd, data: any) => { if (data.IS_DEV) app.quit(); else if (mainWin) { @@ -43,7 +51,7 @@ function init() { if (process.platform === "win32") app.setAppUserModelId("dev.vencord.desktop"); else if (process.platform === "darwin") app.dock.setIcon(ICON_PATH); - createWindows(); + bootstrap(); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) createWindows(); @@ -63,22 +71,12 @@ if (!app.requestSingleInstanceLock({ IS_DEV })) { init(); } -async function createWindows() { - const splash = createSplashWindow(); - - await ensureVencordFiles(); - runVencordMain(); - - mainWin = createMainWindow(); - - mainWin.once("ready-to-show", () => { - splash.destroy(); - mainWin!.show(); - - if (Settings.store.maximized) { - mainWin!.maximize(); - } - }); +async function bootstrap() { + if (!Object.hasOwn(Settings.store, "firstLaunch")) { + createFirstLaunchTour(); + } else { + createWindows(); + } } app.on("window-all-closed", () => { diff --git a/src/main/ipc.ts b/src/main/ipc.ts index e78e09e..18917c9 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -11,6 +11,7 @@ import { join } from "path"; import { debounce } from "shared/utils/debounce"; import { IpcEvents } from "../shared/IpcEvents"; +import { autoStart } from "./autoStart"; import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE } from "./constants"; import { mainWin } from "./mainWindow"; import { Settings } from "./settings"; @@ -39,6 +40,12 @@ ipcMain.on(IpcEvents.GET_VERSION, e => { e.returnValue = app.getVersion(); }); +ipcMain.on(IpcEvents.AUTOSTART_ENABLED, e => { + e.returnValue = autoStart.isEnabled(); +}); +ipcMain.handle(IpcEvents.ENABLE_AUTOSTART, autoStart.enable); +ipcMain.handle(IpcEvents.DISABLE_AUTOSTART, autoStart.disable); + ipcMain.handle(IpcEvents.SET_SETTINGS, (_, settings: typeof Settings.store, path?: string) => { Settings.setData(settings, path); }); diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 5a9db34..34a72cd 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -6,13 +6,16 @@ import { app, BrowserWindow, BrowserWindowConstructorOptions, Menu, Tray } from "electron"; import { join } from "path"; +import { once } from "shared/utils/once"; import { ICON_PATH } from "../shared/paths"; import { createAboutWindow } from "./about"; -import { DEFAULT_HEIGHT, DEFAULT_WIDTH, MIN_HEIGHT, MIN_WIDTH } from "./constants"; +import { initArRPC } from "./arrpc"; +import { DEFAULT_HEIGHT, DEFAULT_WIDTH, MIN_HEIGHT, MIN_WIDTH, VENCORD_FILES_DIR } from "./constants"; import { Settings, VencordSettings } from "./settings"; +import { createSplashWindow } from "./splash"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; -import { downloadVencordFiles } from "./utils/vencordLoader"; +import { downloadVencordFiles, ensureVencordFiles } from "./utils/vencordLoader"; let isQuitting = false; let tray: Tray; @@ -88,7 +91,6 @@ function initMenuBar(win: BrowserWindow) { submenu: [ { label: "About Vencord Desktop", - role: "about", click: createAboutWindow }, { @@ -125,25 +127,20 @@ function initMenuBar(win: BrowserWindow) { click() { app.quit(); } + }, + // See https://github.com/electron/electron/issues/14742 and https://github.com/electron/electron/issues/5256 + { + label: "Zoom in (hidden, hack for Qwertz and others)", + accelerator: "CmdOrCtrl+=", + role: "zoomIn", + visible: false } ] }, { role: "fileMenu" }, { role: "editMenu" }, { role: "viewMenu" }, - { role: "windowMenu" }, - { - label: "Zoom", - submenu: [ - // See https://github.com/electron/electron/issues/14742 and https://github.com/electron/electron/issues/5256 - { - label: "Zoom in", - accelerator: "CmdOrCtrl+=", - role: "zoomIn" - } - ], - visible: false - } + { role: "windowMenu" } ]); Menu.setApplicationMenu(menu); @@ -219,7 +216,7 @@ function initSettingsListeners(win: BrowserWindow) { }); } -export function createMainWindow() { +function createMainWindow() { const win = (mainWin = new BrowserWindow({ show: false, autoHideMenuBar: true, @@ -232,6 +229,7 @@ export function createMainWindow() { }, icon: ICON_PATH, frame: VencordSettings.store.frameless !== true, + ...(Settings.store.staticTitle ? { title: "Vencord" } : {}), ...(VencordSettings.store.macosTranslucency ? { vibrancy: "sidebar", @@ -250,6 +248,8 @@ export function createMainWindow() { return false; }); + if (Settings.store.staticTitle) win.on("page-title-updated", e => e.preventDefault()); + initWindowBoundsListeners(win); if (Settings.store.tray ?? true) initTray(win); initMenuBar(win); @@ -269,3 +269,25 @@ export function createMainWindow() { return win; } + +const runVencordMain = once(() => require(join(VENCORD_FILES_DIR, "vencordDesktopMain.js"))); + +export async function createWindows() { + const splash = createSplashWindow(); + + await ensureVencordFiles(); + runVencordMain(); + + mainWin = createMainWindow(); + + mainWin.once("ready-to-show", () => { + splash.destroy(); + mainWin!.show(); + + if (Settings.store.maximized) { + mainWin!.maximize(); + } + }); + + initArRPC(); +} diff --git a/src/preload/VencordDesktopNative.ts b/src/preload/VencordDesktopNative.ts index b24be18..61dd2a0 100644 --- a/src/preload/VencordDesktopNative.ts +++ b/src/preload/VencordDesktopNative.ts @@ -16,6 +16,11 @@ export const VencordDesktopNative = { relaunch: () => invoke(IpcEvents.RELAUNCH), getVersion: () => sendSync(IpcEvents.GET_VERSION) }, + autostart: { + isEnabled: () => sendSync(IpcEvents.AUTOSTART_ENABLED), + enable: () => invoke(IpcEvents.ENABLE_AUTOSTART), + disable: () => invoke(IpcEvents.DISABLE_AUTOSTART) + }, fileManager: { showItemInFolder: (path: string) => invoke(IpcEvents.SHOW_ITEM_IN_FOLDER, path), selectVencordDir: () => invoke>(IpcEvents.SELECT_VENCORD_DIR) diff --git a/src/renderer/components/Settings.tsx b/src/renderer/components/Settings.tsx index 6e5760e..1c43b79 100644 --- a/src/renderer/components/Settings.tsx +++ b/src/renderer/components/Settings.tsx @@ -6,20 +6,15 @@ import "./settings.css"; +import { Margins } from "@vencord/types/utils"; +import { Button, Forms, Select, Switch, Text, useState } from "@vencord/types/webpack/common"; import { useSettings } from "renderer/settings"; -import { Common, Util } from "../vencord"; - -const { Margins } = Util; - export default function SettingsUi() { const Settings = useSettings(); - const { - Forms: { FormSection, FormText, FormDivider, FormSwitch, FormTitle }, - Text, - Select, - Button - } = Common; + + const { autostart } = VencordDesktopNative; + const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled()); const switches: [keyof typeof Settings, string, string, boolean?, (() => boolean)?][] = [ ["tray", "Tray Icon", "Add a tray icon for Vencord Desktop", true], @@ -30,6 +25,7 @@ export default function SettingsUi() { true, () => Settings.tray ?? true ], + ["arRPC", "Rich Presence", "Enables Rich Presence via arRPC", false], [ "disableMinSize", "Disable minimum window size", @@ -39,16 +35,17 @@ export default function SettingsUi() { "openLinksWithElectron", "Open Links in app (experimental)", "Opens links in a new Vencord Desktop window instead of your web browser" - ] + ], + ["staticTitle", "Static Title", 'Makes the window title "Vencord" instead of changing to the current page'] ]; return ( - + Vencord Desktop Settings - Discord Branch + Discord Branch + + + + + + + + + + + + +
+ + +
+ + + diff --git a/tsconfig.json b/tsconfig.json index ccad342..4e23ba2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,12 @@ "target": "ESNEXT", "jsx": "preserve", - "baseUrl": "./src/" + // we have duplicate electron types but it's w/e + "skipLibCheck": true, + + "baseUrl": "./src/", + + "typeRoots": ["./node_modules/@types", "./node_modules/@vencord"] }, "include": ["src/**/*"] }