diff --git a/.eslintrc.json b/.eslintrc.json index 4287749..fb0e152 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -22,7 +22,13 @@ "eqeqeq": ["error", "always", { "null": "ignore" }], "spaced-comment": ["error", "always", { "markers": ["!"] }], "yoda": "error", - "prefer-destructuring": ["error", { "object": true, "array": false }], + "prefer-destructuring": [ + "error", + { + "VariableDeclarator": { "array": false, "object": true }, + "AssignmentExpression": { "array": false, "object": false } + } + ], "operator-assignment": ["error", "always"], "no-useless-computed-key": "error", "no-unneeded-ternary": ["error", { "defaultAssignment": false }], diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 778ec25..80de47d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,8 +37,16 @@ jobs: run: pnpm build - name: Run Electron Builder + if: ${{ matrix.platform != 'mac' }} run: | pnpm electron-builder --${{ matrix.platform }} --publish always env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CSC_LINK: ${{ matrix.platform == "mac" && secrets.APPLE_SIGNING_CERT }} + + - name: Run Electron Builder + if: ${{ matrix.platform == 'mac' }} + run: | + pnpm electron-builder --${{ matrix.platform }} --publish always + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CSC_LINK: ${{ secrets.APPLE_SIGNING_CERT }} diff --git a/README.md b/README.md index 0e55685..9bf1275 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,63 @@ # Vesktop -Vesktop is a cross platform desktop app aiming to give you a snappier Discord experience with [Vencord](https://github.com/Vendicated/Vencord) pre-installed +Vesktop is a custom Discord desktop app + +**Main features**: +- Vencord preinstalled +- Much more lightweight and faster than the official Discord app +- Linux Screenshare with sound & wayland +- Much better privacy, since Discord has no access to your system **Not yet supported**: - -- Global Keybinds - -Bug reports, feature requests & contributions are highly appreciated!! +- Global Keybinds +- see the [Roadmap](https://github.com/Vencord/Vesktop/issues/324) ![](https://github.com/Vencord/Vesktop/assets/45497981/8608a899-96a9-4027-9725-2cb02ba189fd) -![grafik](https://github.com/Vencord/Vesktop/assets/45497981/8701e5de-52c4-4346-a990-719cb971642e) +![](https://github.com/Vencord/Vesktop/assets/45497981/8701e5de-52c4-4346-a990-719cb971642e) ## Installing ### Windows -Download and run Vesktop-Setup-VERSION.exe from [releases](https://github.com/Vencord/Vesktop/releases/latest) +If you don't know the difference, pick the Installer. + +- [Installer](https://vencord.dev/download/vesktop/amd64/windows) +- [Portable](https://vencord.dev/download/vesktop/amd64/windows-portable) ### Mac -Download and run Vesktop-VERSION.dmg from [releases](https://github.com/Vencord/Vesktop/releases/latest) +If you don't know the difference, pick amd64 + +- [amd64 / x86_64](https://vencord.dev/download/vesktop/amd64/dmg) +- [arm64 / aarch64](https://vencord.dev/download/vesktop/arm64/dmg) ### Linux -[![](https://dl.flathub.org/assets/badges/flathub-badge-en.svg)](https://flathub.org/apps/dev.vencord.Vesktop) +[![Download on Flathub](https://dl.flathub.org/assets/badges/flathub-badge-en.svg)](https://flathub.org/apps/dev.vencord.Vesktop) -#### Arch based +If you don't know the difference, pick amd64. -Install [vencord-desktop-git](https://aur.archlinux.org/packages/vencord-desktop-git) from the AUR using your favourite AUR helper, for example [yay](https://github.com/Jguer/yay) +- amd64 / x86_64 + - [AppImage](https://vencord.dev/download/vesktop/amd64/appimage) + - [Ubuntu/Debian (.deb)](https://vencord.dev/download/vesktop/amd64/deb) + - [Fedora/RHEL (.rpm)](https://vencord.dev/download/vesktop/amd64/rpm) + - [tarball](https://vencord.dev/download/vesktop/amd64/tar) +- arm64 / aarch64 + - [AppImage](https://vencord.dev/download/vesktop/arm64/appimage) + - [Ubuntu/Debian (.deb)](https://vencord.dev/download/vesktop/arm64/deb) + - [Fedora/RHEL (.rpm)](https://vencord.dev/download/vesktop/arm64/rpm) + - [tarball](https://vencord.dev/download/vesktop/arm64/tar) -#### Ubuntu/Debian based +#### Community packages -Download Vesktop-VERSION.deb from [releases](https://github.com/Vencord/Vesktop/releases/latest) +Below you can find unofficial packages created by the community. They are not officially supported by us, so before reporting issues, please first confirm the issue also happens on official builds. When in doubt, consult with their packager first. The flatpak and AppImage should work on any distro that [supports them](https://flatpak.org/setup/), so I recommend you just use those instead! -#### Fedora/RHEL based +- Arch Linux: [Vesktop on the Arch user repository](https://aur.archlinux.org/packages?K=vesktop) +- NixOS: https://nixos.wiki/wiki/Discord#Vesktop -Download Vesktop-VERSION.rpm from [releases](https://github.com/Vencord/Vesktop/releases/latest) +## Building from Source -#### Other - -Either download Vesktop-VERSION.AppImage and just run it directly or grab Vesktop-VERSION.tar.gz, extract it somewhere and run `vesktop`. - -If other packages are created, feel free to open an issue and we'll link them here. - -## Building - -Packaging will create builds in the dist/ folder. You can then install them like mentioned above or distribute them +Packaging will create builds in the dist/ folder ```sh git clone https://github.com/Vencord/Vesktop @@ -64,7 +76,3 @@ pnpm package --linux pacman # Or package to a directory only pnpm package:dir ``` - -## Motivation - -The official Discord Desktop app is very resource heavy compared to Discord in your Browser. There are multiple alternative Electron apps (ArmCord, WebCord, probably more) that prove how much of a performance gain you can gain by using a custom app. ArmCord already supports Vencord but makes it pretty limited for us. Making our own standalone app gives us much more control. diff --git a/meta/dev.vencord.Vesktop.metainfo.xml b/meta/dev.vencord.Vesktop.metainfo.xml index d897226..be55d24 100644 --- a/meta/dev.vencord.Vesktop.metainfo.xml +++ b/meta/dev.vencord.Vesktop.metainfo.xml @@ -28,6 +28,22 @@ + + https://github.com/Vencord/Vesktop/releases/tag/v1.5.0 + +

What's Changed

+
    +
  • fully renamed to Vesktop. You will likely have to login to Discord again. You might have to re-create your vesktop shortcut
  • +
  • added option to disable smooth scrolling by @ZirixCZ
  • +
  • added setting to disable hardware acceleration by @zt64
  • +
  • fixed adding connections
  • +
  • fixed / improved discord popouts
  • +
  • you can now use the custom discord titlebar on linux/mac
  • +
  • the splash window is now draggable
  • +
  • now signed on mac
  • +
+
+
https://github.com/Vencord/Vesktop/releases/tag/v0.4.4 diff --git a/package.json b/package.json index 0765d00..2c47d5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vesktop", - "version": "0.4.4", + "version": "1.5.0", "private": true, "description": "", "keywords": [], @@ -27,17 +27,17 @@ "arrpc": "github:OpenAsar/arrpc#98879cae0565e6fce34e4cb6f544bf42c6a7e7c8" }, "optionalDependencies": { - "@vencord/venmic": "^3.2.0" + "@vencord/venmic": "^3.2.3" }, "devDependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@types/node": "^20.10.6", - "@types/react": "^18.2.46", - "@typescript-eslint/eslint-plugin": "^6.17.0", - "@typescript-eslint/parser": "^6.17.0", + "@types/node": "^20.11.2", + "@types/react": "^18.2.48", + "@typescript-eslint/eslint-plugin": "^6.19.0", + "@typescript-eslint/parser": "^6.19.0", "@vencord/types": "^0.1.2", "dotenv": "^16.3.1", - "electron": "^28.1.1", + "electron": "^28.1.3", "electron-builder": "^24.9.1", "esbuild": "^0.19.11", "eslint": "^8.56.0", @@ -45,10 +45,10 @@ "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-license-header": "^0.6.0", "eslint-plugin-path-alias": "^1.0.0", - "eslint-plugin-prettier": "^5.1.2", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^3.0.0", - "prettier": "^3.1.1", + "prettier": "^3.2.2", "sharp": "^0.33.0", "sharp-ico": "^0.1.5", "source-map-support": "^0.5.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8bee0a5..00bc0e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,25 +11,25 @@ dependencies: optionalDependencies: '@vencord/venmic': - specifier: ^3.2.0 - version: 3.2.0 + specifier: ^3.2.3 + version: 3.2.3 devDependencies: '@fal-works/esbuild-plugin-global-externals': specifier: ^2.1.2 version: 2.1.2 '@types/node': - specifier: ^20.10.6 - version: 20.10.6 + specifier: ^20.11.2 + version: 20.11.2 '@types/react': - specifier: ^18.2.46 - version: 18.2.46 + specifier: ^18.2.48 + version: 18.2.48 '@typescript-eslint/eslint-plugin': - specifier: ^6.17.0 - version: 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.19.0 + version: 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.17.0 - version: 6.17.0(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.19.0 + version: 6.19.0(eslint@8.56.0)(typescript@5.3.3) '@vencord/types': specifier: ^0.1.2 version: 0.1.2 @@ -37,8 +37,8 @@ devDependencies: specifier: ^16.3.1 version: 16.3.1 electron: - specifier: ^28.1.1 - version: 28.1.1 + specifier: ^28.1.3 + version: 28.1.3 electron-builder: specifier: ^24.9.1 version: 24.9.1 @@ -61,17 +61,17 @@ devDependencies: specifier: ^1.0.0 version: 1.0.0(eslint@8.56.0) eslint-plugin-prettier: - specifier: ^5.1.2 - version: 5.1.2(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1) + specifier: ^5.1.3 + version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.2) eslint-plugin-simple-import-sort: specifier: ^10.0.0 version: 10.0.0(eslint@8.56.0) eslint-plugin-unused-imports: specifier: ^3.0.0 - version: 3.0.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.56.0) + version: 3.0.0(@typescript-eslint/eslint-plugin@6.19.0)(eslint@8.56.0) prettier: - specifier: ^3.1.1 - version: 3.1.1 + specifier: ^3.2.2 + version: 3.2.2 sharp: specifier: ^0.33.0 version: 0.33.0 @@ -446,11 +446,11 @@ packages: resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} dev: true - /@humanwhocodes/config-array@0.11.13: - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} dependencies: - '@humanwhocodes/object-schema': 2.0.1 + '@humanwhocodes/object-schema': 2.0.2 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: @@ -462,8 +462,8 @@ packages: engines: {node: '>=12.22'} dev: true - /@humanwhocodes/object-schema@2.0.1: - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + /@humanwhocodes/object-schema@2.0.2: + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} dev: true <<<<<<< HEAD @@ -742,7 +742,7 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.10.6 + '@types/node': 20.11.2 '@types/responselike': 1.0.3 dev: true @@ -755,7 +755,7 @@ packages: /@types/fs-extra@9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.2 dev: true /@types/http-cache-semantics@4.0.4: @@ -773,7 +773,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.2 dev: true /@types/lodash@4.14.202: @@ -784,14 +784,14 @@ packages: resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} dev: true - /@types/node@18.19.4: - resolution: {integrity: sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==} + /@types/node@18.19.7: + resolution: {integrity: sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==} dependencies: undici-types: 5.26.5 dev: true - /@types/node@20.10.6: - resolution: {integrity: sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==} + /@types/node@20.11.2: + resolution: {integrity: sha512-cZShBaVa+UO1LjWWBPmWRR4+/eY/JR/UIEcDlVsw3okjWEu+rB7/mH6X3B/L+qJVHDLjk9QW/y2upp9wp1yDXA==} dependencies: undici-types: 5.26.5 dev: true @@ -800,7 +800,7 @@ packages: resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} requiresBuild: true dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.2 xmlbuilder: 15.1.1 dev: true optional: true @@ -812,7 +812,7 @@ packages: /@types/react-dom@18.2.18: resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==} dependencies: - '@types/react': 18.2.46 + '@types/react': 18.2.48 dev: true /@types/react@17.0.2: @@ -822,8 +822,8 @@ packages: csstype: 3.1.3 dev: true - /@types/react@18.2.46: - resolution: {integrity: sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==} + /@types/react@18.2.48: + resolution: {integrity: sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==} dependencies: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.8 @@ -833,7 +833,7 @@ packages: /@types/responselike@1.0.3: resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.2 dev: true /@types/scheduler@0.16.8: @@ -854,12 +854,12 @@ packages: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} requiresBuild: true dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.2 dev: true optional: true - /@typescript-eslint/eslint-plugin@6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==} + /@typescript-eslint/eslint-plugin@6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -870,11 +870,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/type-utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.17.0 + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/type-utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 eslint: 8.56.0 graphemer: 1.4.0 @@ -887,8 +887,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.17.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==} + /@typescript-eslint/parser@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -897,10 +897,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.17.0 + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 eslint: 8.56.0 typescript: 5.3.3 @@ -908,16 +908,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.17.0: - resolution: {integrity: sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==} + /@typescript-eslint/scope-manager@6.19.0: + resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 dev: true - /@typescript-eslint/type-utils@6.17.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==} + /@typescript-eslint/type-utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -926,8 +926,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) - '@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.56.0 ts-api-utils: 1.0.3(typescript@5.3.3) @@ -936,13 +936,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@6.17.0: - resolution: {integrity: sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==} + /@typescript-eslint/types@6.19.0: + resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.17.0(typescript@5.3.3): - resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==} + /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3): + resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -950,8 +950,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -963,8 +963,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.17.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==} + /@typescript-eslint/utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -972,9 +972,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) eslint: 8.56.0 semver: 7.5.4 transitivePeerDependencies: @@ -982,11 +982,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@6.17.0: - resolution: {integrity: sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==} + /@typescript-eslint/visitor-keys@6.19.0: + resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.17.0 + '@typescript-eslint/types': 6.19.0 eslint-visitor-keys: 3.4.3 dev: true @@ -998,16 +998,16 @@ packages: resolution: {integrity: sha512-C/dqZHn3aod/4izZT9sgZEef4478M7QNKTY8Gx2yB1CRYawJcs6hupXT/1SMmepKqrULbltL04Cnh5ieBm3Ucw==} dependencies: '@types/lodash': 4.14.202 - '@types/node': 18.19.4 - '@types/react': 18.2.46 + '@types/node': 18.19.7 + '@types/react': 18.2.48 '@types/react-dom': 18.2.18 discord-types: 1.3.26 standalone-electron-types: 1.0.0 type-fest: 3.13.1 dev: true - /@vencord/venmic@3.2.0: - resolution: {integrity: sha512-z+Lgmr6IgjkPEIfFZ3ZwVV4aP/OFjnB6k6Ll5YpBPuDZOyqCbKTNLADApbZa/WxMfm7YpZ22g46X4FfizuprEQ==} + /@vencord/venmic@3.2.3: + resolution: {integrity: sha512-mnpAa5aFRkMQhoeYjkygPY+U+/b7Nh55HekchWzl2y5RNHpCxooGANTcw4L80JoCiL+AYRUg8BQU31L7fFQcPw==} engines: {node: '>=14.15'} os: [linux] requiresBuild: true @@ -1279,7 +1279,7 @@ packages: resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} requiresBuild: true dependencies: - follow-redirects: 1.15.4(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -1438,7 +1438,7 @@ packages: dependencies: function-bind: 1.1.2 get-intrinsic: 1.2.2 - set-function-length: 1.1.1 + set-function-length: 1.2.0 dev: true /callsites@3.1.0: @@ -1901,14 +1901,14 @@ packages: - supports-color dev: true - /electron@28.1.1: - resolution: {integrity: sha512-HJSbGHpRl46jWCp5G4OH57KSm2F5u15tB10ixD8iFiz9dhwojqlSQTRAcjSwvga+Vqs1jv7iqwQRrolXP4DgOA==} + /electron@28.1.3: + resolution: {integrity: sha512-NSFyTo6SndTPXzU18XRePv4LnjmuM9rF5GMKta1/kPmi02ISoSRonnD7wUlWXD2x53XyJ6d/TbSVesMW6sXkEQ==} engines: {node: '>= 12.20.55'} hasBin: true requiresBuild: true dependencies: '@electron/get': 2.0.3 - '@types/node': 18.19.4 + '@types/node': 18.19.7 extract-zip: 2.0.1 transitivePeerDependencies: - supports-color @@ -1968,8 +1968,8 @@ packages: object-keys: 1.1.1 object.assign: 4.1.5 regexp.prototype.flags: 1.5.1 - safe-array-concat: 1.0.1 - safe-regex-test: 1.0.0 + safe-array-concat: 1.1.0 + safe-regex-test: 1.0.2 string.prototype.trim: 1.2.8 string.prototype.trimend: 1.0.7 string.prototype.trimstart: 1.0.7 @@ -2066,7 +2066,7 @@ packages: peerDependencies: eslint-plugin-import: '>=1.4.0' dependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.17.0)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint@8.56.0) dev: true /eslint-import-resolver-node@0.3.9: @@ -2079,7 +2079,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2100,7 +2100,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 @@ -2108,7 +2108,7 @@ packages: - supports-color dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.17.0)(eslint@8.56.0): + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0)(eslint@8.56.0): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} peerDependencies: @@ -2118,7 +2118,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -2127,7 +2127,7 @@ packages: doctrine: 2.1.0 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -2160,8 +2160,8 @@ packages: - supports-color dev: true - /eslint-plugin-prettier@5.1.2(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1): - resolution: {integrity: sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==} + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.2): + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -2176,7 +2176,7 @@ packages: dependencies: eslint: 8.56.0 eslint-config-prettier: 9.1.0(eslint@8.56.0) - prettier: 3.1.1 + prettier: 3.2.2 prettier-linter-helpers: 1.0.0 synckit: 0.8.8 dev: true @@ -2189,7 +2189,7 @@ packages: eslint: 8.56.0 dev: true - /eslint-plugin-unused-imports@3.0.0(@typescript-eslint/eslint-plugin@6.17.0)(eslint@8.56.0): + /eslint-plugin-unused-imports@3.0.0(@typescript-eslint/eslint-plugin@6.19.0)(eslint@8.56.0): resolution: {integrity: sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -2199,7 +2199,7 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/eslint-plugin': 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) eslint: 8.56.0 eslint-rule-composer: 0.3.0 dev: true @@ -2231,7 +2231,7 @@ packages: '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/config-array': 0.11.14 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 @@ -2418,8 +2418,8 @@ packages: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true - /follow-redirects@1.15.4(debug@4.3.4): - resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==} + /follow-redirects@1.15.5(debug@4.3.4): + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} engines: {node: '>=4.0'} requiresBuild: true peerDependencies: @@ -3659,8 +3659,8 @@ packages: fast-diff: 1.3.0 dev: true - /prettier@3.1.1: - resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} + /prettier@3.2.2: + resolution: {integrity: sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==} engines: {node: '>=14'} hasBin: true dev: true @@ -3841,8 +3841,8 @@ packages: queue-microtask: 1.2.3 dev: true - /safe-array-concat@1.0.1: - resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + /safe-array-concat@1.1.0: + resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} engines: {node: '>=0.4'} dependencies: call-bind: 1.0.5 @@ -3857,8 +3857,9 @@ packages: dev: false optional: true - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + /safe-regex-test@1.0.2: + resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==} + engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 @@ -3918,11 +3919,12 @@ packages: dev: false optional: true - /set-function-length@1.1.1: - resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + /set-function-length@1.2.0: + resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==} engines: {node: '>= 0.4'} dependencies: define-data-property: 1.1.1 + function-bind: 1.1.2 get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.1 @@ -4117,7 +4119,7 @@ packages: /standalone-electron-types@1.0.0: resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} dependencies: - '@types/node': 18.19.4 + '@types/node': 18.19.7 dev: true /stat-mode@1.0.0: diff --git a/src/main/constants.ts b/src/main/constants.ts index fb873ee..5c4ecd7 100644 --- a/src/main/constants.ts +++ b/src/main/constants.ts @@ -18,6 +18,10 @@ if (existsSync(LEGACY_DATA_DIR)) { renameSync(join(LEGACY_DATA_DIR, file), join(DATA_DIR, file)); } rmdirSync(LEGACY_DATA_DIR); + renameSync( + join(app.getPath("appData"), "VencordDesktop", "IndexedDB"), + join(DATA_DIR, "sessionData", "IndexedDB") + ); } catch (e) { console.error("Migration failed", e); } @@ -42,6 +46,8 @@ export const MIN_HEIGHT = 500; export const DEFAULT_WIDTH = 1280; export const DEFAULT_HEIGHT = 720; +export const DISCORD_HOSTNAMES = ["discord.com", "canary.discord.com", "ptb.discord.com"]; + const UserAgents = { darwin: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 318b1e3..815e9c9 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -4,11 +4,11 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -if (process.platform === "linux") import("./virtmic"); +if (process.platform === "linux") import("./venmic"); // eslint-disable-next-line simple-import-sort/imports import { execFile } from "child_process"; -import { app, BrowserWindow, dialog, RelaunchOptions, session, shell } from "electron"; +import { app, BrowserWindow, clipboard, dialog, nativeImage, RelaunchOptions, session, shell } from "electron"; import { mkdirSync, readFileSync, watch } from "fs"; import { open, readFile } from "fs/promises"; import { release } from "os"; @@ -22,6 +22,7 @@ import { mainWin } from "./mainWindow"; import { Settings } from "./settings"; import { setBadgeCount } from "./appBadge"; import { handle, handleSync } from "./utils/ipcWrappers"; +import { PopoutWindows } from "./utils/popout"; import { isDeckGameMode, showGamePage } from "./utils/steamOS"; import { isValidVencordInstall } from "./utils/vencordLoader"; @@ -69,14 +70,16 @@ handle(IpcEvents.SHOW_ITEM_IN_FOLDER, (_, path) => { }); handle(IpcEvents.FOCUS, () => { - if (process.platform === "win32") mainWin.minimize(); // Windows is weird - - mainWin.restore(); mainWin.show(); + mainWin.setSkipTaskbar(false); }); -handle(IpcEvents.CLOSE, e => { - (BrowserWindow.fromWebContents(e.sender) ?? e.sender).close(); +handle(IpcEvents.CLOSE, (e, key?: string) => { + const popout = PopoutWindows.get(key!); + if (popout) return popout.close(); + + const win = BrowserWindow.fromWebContents(e.sender) ?? e.sender; + win.close(); }); handle(IpcEvents.MINIMIZE, e => { @@ -121,6 +124,13 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async () => { handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count)); +handle(IpcEvents.CLIPBOARD_COPY_IMAGE, async (_, buf: ArrayBuffer, src: string) => { + clipboard.write({ + html: ``, + image: nativeImage.createFromBuffer(Buffer.from(buf)) + }); +}); + function readCss() { return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => ""); } diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 0ffcf4b..b204dee 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -78,8 +78,7 @@ function initTray(win: BrowserWindow) { label: "Open", click() { win.show(); - }, - enabled: false + } }, { label: "About", @@ -122,14 +121,6 @@ function initTray(win: BrowserWindow) { tray.setToolTip("Vesktop"); tray.setContextMenu(trayMenu); tray.on("click", () => win.show()); - - win.on("show", () => { - trayMenu.items[0].enabled = false; - }); - - win.on("hide", () => { - trayMenu.items[0].enabled = true; - }); } async function clearData(win: BrowserWindow) { @@ -378,11 +369,11 @@ function createMainWindow() { removeSettingsListeners(); removeVencordSettingsListeners(); - const { staticTitle, transparencyOption, enableMenu, discordWindowsTitleBar } = Settings.store; + const { staticTitle, transparencyOption, enableMenu, customTitleBar } = Settings.store; - const { frameless } = VencordSettings.store; + const { frameless, transparent } = VencordSettings.store; - const noFrame = frameless === true || (process.platform === "win32" && discordWindowsTitleBar === true); + const noFrame = frameless === true || customTitleBar === true; const win = (mainWin = new BrowserWindow({ show: false, @@ -396,13 +387,17 @@ function createMainWindow() { }, icon: ICON_PATH, frame: !noFrame, + ...(transparent && { + transparent: true, + backgroundColor: "#00000000" + }), ...(transparencyOption && transparencyOption !== "none" && { backgroundColor: "#00000000", backgroundMaterial: transparencyOption }), // Fix transparencyOption for custom discord titlebar - ...(discordWindowsTitleBar && + ...(customTitleBar && transparencyOption && transparencyOption !== "none" && { transparent: true diff --git a/src/main/settings.ts b/src/main/settings.ts index c4df364..03c705e 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -35,9 +35,15 @@ function loadSettings(file: string, name: string) { } export const Settings = loadSettings(SETTINGS_FILE, "Vesktop settings"); +if (Object.hasOwn(Settings.plain, "discordWindowsTitleBar")) { + Settings.plain.customTitleBar = Settings.plain.discordWindowsTitleBar; + delete Settings.plain.discordWindowsTitleBar; + Settings.markAsChanged(); +} + export const VencordSettings = loadSettings(VENCORD_SETTINGS_FILE, "Vencord settings"); -if (Object.hasOwn(Settings.store, "firstLaunch") && !existsSync(STATE_FILE)) { +if (Object.hasOwn(Settings.plain, "firstLaunch") && !existsSync(STATE_FILE)) { console.warn("legacy state in settings.json detected. migrating to state.json"); const state = {} as TState; for (const prop of [ @@ -47,7 +53,7 @@ if (Object.hasOwn(Settings.store, "firstLaunch") && !existsSync(STATE_FILE)) { "skippedUpdate", "steamOSLayoutVersion", "windowBounds" - ]) { + ] as const) { state[prop] = Settings.plain[prop]; delete Settings.plain[prop]; } diff --git a/src/main/utils/ipcWrappers.ts b/src/main/utils/ipcWrappers.ts index b99298c..3ceb908 100644 --- a/src/main/utils/ipcWrappers.ts +++ b/src/main/utils/ipcWrappers.ts @@ -5,20 +5,14 @@ */ import { ipcMain, IpcMainEvent, IpcMainInvokeEvent, WebFrameMain } from "electron"; +import { DISCORD_HOSTNAMES } from "main/constants"; import { IpcEvents } from "shared/IpcEvents"; export function validateSender(frame: WebFrameMain) { const { hostname, protocol } = new URL(frame.url); if (protocol === "file:") return; - switch (hostname) { - case "discord.com": - case "ptb.discord.com": - case "canary.discord.com": - break; - default: - throw new Error("ipc: Disallowed host " + hostname); - } + if (!DISCORD_HOSTNAMES.includes(hostname)) throw new Error("ipc: Disallowed host " + hostname); } export function handleSync(event: IpcEvents, cb: (e: IpcMainEvent, ...args: any[]) => any) { diff --git a/src/main/utils/makeLinksOpenExternally.ts b/src/main/utils/makeLinksOpenExternally.ts index 5197261..12f2c3d 100644 --- a/src/main/utils/makeLinksOpenExternally.ts +++ b/src/main/utils/makeLinksOpenExternally.ts @@ -5,48 +5,67 @@ */ import { BrowserWindow, shell } from "electron"; +import { DISCORD_HOSTNAMES } from "main/constants"; import { Settings } from "../settings"; +import { createOrFocusPopup, setupPopout } from "./popout"; import { execSteamURL, isDeckGameMode, steamOpenURL } from "./steamOS"; -export function makeLinksOpenExternally(win: BrowserWindow) { - win.webContents.setWindowOpenHandler(({ url }) => { - switch (url) { - case "about:blank": - case "https://discord.com/popout": - return { action: "allow" }; - } - +export function handleExternalUrl(url: string, protocol?: string): { action: "deny" | "allow" } { + if (protocol == null) { try { - var { protocol } = new URL(url); + protocol = new URL(url).protocol; + } catch { + return { action: "deny" }; + } + } + + switch (protocol) { + case "http:": + case "https:": + if (Settings.store.openLinksWithElectron) { + return { action: "allow" }; + } + // eslint-disable-next-line no-fallthrough + case "mailto:": + case "spotify:": + if (isDeckGameMode) { + steamOpenURL(url); + } else { + shell.openExternal(url); + } + break; + case "steam:": + if (isDeckGameMode) { + execSteamURL(url); + } else { + shell.openExternal(url); + } + break; + } + + return { action: "deny" }; +} + +export function makeLinksOpenExternally(win: BrowserWindow) { + win.webContents.setWindowOpenHandler(({ url, frameName, features }) => { + try { + var { protocol, hostname, pathname } = new URL(url); } catch { return { action: "deny" }; } - switch (protocol) { - case "http:": - case "https:": - if (Settings.store.openLinksWithElectron) { - return { action: "allow" }; - } - // eslint-disable-next-line no-fallthrough - case "mailto:": - case "spotify:": - if (isDeckGameMode) { - steamOpenURL(url); - } else { - shell.openExternal(url); - } - break; - case "steam:": - if (isDeckGameMode) { - execSteamURL(url); - } else { - shell.openExternal(url); - } - break; + if (frameName.startsWith("DISCORD_") && pathname === "/popout" && DISCORD_HOSTNAMES.includes(hostname)) { + return createOrFocusPopup(frameName, features); } - return { action: "deny" }; + if (url === "about:blank" || (frameName === "authorize" && DISCORD_HOSTNAMES.includes(hostname))) + return { action: "allow" }; + + return handleExternalUrl(url, protocol); + }); + + win.webContents.on("did-create-window", (win, { frameName }) => { + if (frameName.startsWith("DISCORD_")) setupPopout(win, frameName); }); } diff --git a/src/main/utils/popout.ts b/src/main/utils/popout.ts new file mode 100644 index 0000000..cdeea61 --- /dev/null +++ b/src/main/utils/popout.ts @@ -0,0 +1,116 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vesktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { BrowserWindow, BrowserWindowConstructorOptions } from "electron"; +import { Settings } from "main/settings"; + +import { handleExternalUrl } from "./makeLinksOpenExternally"; + +const ALLOWED_FEATURES = new Set([ + "width", + "height", + "left", + "top", + "resizable", + "movable", + "alwaysOnTop", + "frame", + "transparent", + "hasShadow", + "closable", + "skipTaskbar", + "backgroundColor", + "menubar", + "toolbar", + "location", + "directories", + "titleBarStyle" +]); + +const MIN_POPOUT_WIDTH = 320; +const MIN_POPOUT_HEIGHT = 180; +const DEFAULT_POPOUT_OPTIONS: BrowserWindowConstructorOptions = { + title: "Discord Popout", + backgroundColor: "#2f3136", + minWidth: MIN_POPOUT_WIDTH, + minHeight: MIN_POPOUT_HEIGHT, + frame: Settings.store.customTitleBar !== true, + titleBarStyle: process.platform === "darwin" ? "hidden" : undefined, + trafficLightPosition: + process.platform === "darwin" + ? { + x: 10, + y: 3 + } + : undefined, + webPreferences: { + nodeIntegration: false, + contextIsolation: true + }, + autoHideMenuBar: Settings.store.enableMenu +}; + +export const PopoutWindows = new Map(); + +function focusWindow(window: BrowserWindow) { + window.setAlwaysOnTop(true); + window.focus(); + window.setAlwaysOnTop(false); +} + +function parseFeatureValue(feature: string) { + if (feature === "yes") return true; + if (feature === "no") return false; + + const n = Number(feature); + if (!isNaN(n)) return n; + + return feature; +} + +function parseWindowFeatures(features: string) { + const keyValuesParsed = features.split(","); + + return keyValuesParsed.reduce((features, feature) => { + const [key, value] = feature.split("="); + if (ALLOWED_FEATURES.has(key)) features[key] = parseFeatureValue(value); + + return features; + }, {}); +} + +export function createOrFocusPopup(key: string, features: string) { + const existingWindow = PopoutWindows.get(key); + if (existingWindow) { + focusWindow(existingWindow); + return { action: "deny" }; + } + + return { + action: "allow", + overrideBrowserWindowOptions: { + ...DEFAULT_POPOUT_OPTIONS, + ...parseWindowFeatures(features) + } + }; +} + +export function setupPopout(win: BrowserWindow, key: string) { + win.setMenuBarVisibility(false); + + PopoutWindows.set(key, win); + + /* win.webContents.on("will-navigate", (evt, url) => { + // maybe prevent if not origin match + })*/ + + win.webContents.setWindowOpenHandler(({ url }) => handleExternalUrl(url)); + + win.once("closed", () => { + win.removeAllListeners(); + PopoutWindows.delete(key); + }); +} diff --git a/src/main/virtmic.ts b/src/main/venmic.ts similarity index 73% rename from src/main/virtmic.ts rename to src/main/venmic.ts index ddbde63..fcc40de 100644 --- a/src/main/virtmic.ts +++ b/src/main/venmic.ts @@ -51,22 +51,17 @@ ipcMain.handle(IpcEvents.VIRT_MIC_LIST, () => { : { ok: false, isGlibcxxToOld }; }); -ipcMain.handle( - IpcEvents.VIRT_MIC_START, - (_, targets: string[]) => - obtainVenmic()?.link({ - include: targets.map(target => ({ key: "application.name", value: target })), - exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }] - }) +ipcMain.handle(IpcEvents.VIRT_MIC_START, (_, targets: string[]) => + obtainVenmic()?.link({ + include: targets.map(target => ({ key: "application.name", value: target })), + exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }] + }) ); -ipcMain.handle( - IpcEvents.VIRT_MIC_START_SYSTEM, - () => - // @ts-expect-error venmic types are wrong. include is actually optional but typed as required in vemic - obtainVenmic()?.link({ - exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }] - }) +ipcMain.handle(IpcEvents.VIRT_MIC_START_SYSTEM, () => + obtainVenmic()?.link({ + exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }] + }) ); ipcMain.handle(IpcEvents.VIRT_MIC_STOP, () => obtainVenmic()?.unlink()); diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index d72329d..a2ca74c 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -52,7 +52,7 @@ export const VesktopNative = { }, win: { focus: () => invoke(IpcEvents.FOCUS), - close: () => invoke(IpcEvents.CLOSE), + close: (key?: string) => invoke(IpcEvents.CLOSE, key), minimize: () => invoke(IpcEvents.MINIMIZE), maximize: () => invoke(IpcEvents.MAXIMIZE) }, @@ -71,5 +71,9 @@ export const VesktopNative = { onActivity(cb: (data: string) => void) { ipcRenderer.on(IpcEvents.ARRPC_ACTIVITY, (_, data: string) => cb(data)); } + }, + clipboard: { + copyImage: (imageBuffer: Uint8Array, imageSrc: string) => + invoke(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc) } }; diff --git a/src/renderer/components/Settings.tsx b/src/renderer/components/Settings.tsx index f835aea..7323e44 100644 --- a/src/renderer/components/Settings.tsx +++ b/src/renderer/components/Settings.tsx @@ -10,7 +10,7 @@ import { Margins } from "@vencord/types/utils"; import { Button, Forms, Select, Switch, Text, Toasts, useState } from "@vencord/types/webpack/common"; import { setBadge } from "renderer/appBadge"; import { useSettings } from "renderer/settings"; -import { isMac, isWindows } from "renderer/utils"; +import { isMac } from "renderer/utils"; import { isTruthy } from "shared/utils/guards"; export default function SettingsUi() { @@ -20,13 +20,11 @@ export default function SettingsUi() { const { autostart } = VesktopNative; const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled()); - const allSwitches: Array< - false | [keyof typeof Settings, string, string, boolean?, (() => boolean)?, ((value: boolean) => void)?] - > = [ - isWindows && [ - "discordWindowsTitleBar", + const allSwitches: Array boolean)?]> = [ + [ + "customTitleBar", "Discord Titlebar", - "Use Discord's custom title bar instead of the Windows one. Requires a full restart." + "Use Discord's custom title bar instead of the native system one. Requires a full restart." ], ["arRPC", "Rich Presence", "Enables Rich Presence via arRPC", false], [ @@ -35,7 +33,11 @@ export default function SettingsUi() { "Allows you to make the window as small as your heart desires" ], ["staticTitle", "Static Title", 'Makes the window title "Vesktop" instead of changing to the current page'], - ["enableMenu", "Enable Menu Bar", "Enables the application menu bar. Press ALT to toggle visibility."], + [ + "enableMenu", + "Enable Menu Bar", + "Enables the application menu bar. Press ALT to toggle visibility. Incompatible with 'Discord Titlebar'" + ], ["disableSmoothScroll", "Disable smooth scrolling", "Disables smooth scrolling in Vesktop", false], ["hardwareAcceleration", "Hardware Acceleration", "Enable hardware acceleration", true], ["splashTheming", "Splash theming", "Adapt the splash window colors to your custom theme", false], diff --git a/src/renderer/patches/platformClass.tsx b/src/renderer/patches/platformClass.tsx index 30fbfd0..58767a8 100644 --- a/src/renderer/patches/platformClass.tsx +++ b/src/renderer/patches/platformClass.tsx @@ -5,7 +5,7 @@ */ import { Settings } from "renderer/settings"; -import { isMac, isWindows } from "renderer/utils"; +import { isMac } from "renderer/utils"; import { addPatch } from "./shared"; @@ -22,8 +22,8 @@ addPatch({ ], getPlatformClass() { + if (Settings.store.customTitleBar) return "platform-win"; if (isMac) return "platform-osx"; - if (isWindows && Settings.store.discordWindowsTitleBar) return "platform-win"; return "platform-web"; } }); diff --git a/src/renderer/patches/windowsTitleBar.tsx b/src/renderer/patches/windowsTitleBar.tsx index 4ae50b2..401e1c5 100644 --- a/src/renderer/patches/windowsTitleBar.tsx +++ b/src/renderer/patches/windowsTitleBar.tsx @@ -8,7 +8,7 @@ import { Settings } from "renderer/settings"; import { addPatch } from "./shared"; -if (Settings.store.discordWindowsTitleBar) +if (Settings.store.customTitleBar) addPatch({ patches: [ { diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index bd857c4..df64403 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -47,5 +47,7 @@ export const enum IpcEvents { VIRT_MIC_START_SYSTEM = "VCD_VIRT_MIC_START_ALL", VIRT_MIC_STOP = "VCD_VIRT_MIC_STOP", - ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY" + ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY", + + CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE" } diff --git a/src/shared/settings.d.ts b/src/shared/settings.d.ts index d1bb4d5..49d7180 100644 --- a/src/shared/settings.d.ts +++ b/src/shared/settings.d.ts @@ -20,9 +20,12 @@ export interface Settings { hardwareAcceleration?: boolean; arRPC?: boolean; appBadge?: boolean; - discordWindowsTitleBar?: boolean; disableMinSize?: boolean; + /** @deprecated use customTitleBar */ + discordWindowsTitleBar?: boolean; + customTitleBar?: boolean; + checkUpdates?: boolean; splashTheming?: boolean;