Merge branch 'main' into autostart-portal

This commit is contained in:
V 2024-01-16 02:22:50 +01:00 committed by GitHub
commit e70790dffc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 534 additions and 241 deletions

View file

@ -22,7 +22,13 @@
"eqeqeq": ["error", "always", { "null": "ignore" }], "eqeqeq": ["error", "always", { "null": "ignore" }],
"spaced-comment": ["error", "always", { "markers": ["!"] }], "spaced-comment": ["error", "always", { "markers": ["!"] }],
"yoda": "error", "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"], "operator-assignment": ["error", "always"],
"no-useless-computed-key": "error", "no-useless-computed-key": "error",
"no-unneeded-ternary": ["error", { "defaultAssignment": false }], "no-unneeded-ternary": ["error", { "defaultAssignment": false }],

32
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS/Distro: [e.g. Windows / Fedora Linux / MacOs]
- Desktop Environment (linux only): [e.g. gnome, kde, sway]
- Version: [e.g. 22]
**Additional context**
Add any other context about the problem here.

10
.github/ISSUE_TEMPLATE/custom.md vendored Normal file
View file

@ -0,0 +1,10 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -37,7 +37,16 @@ jobs:
run: pnpm build run: pnpm build
- name: Run Electron Builder - name: Run Electron Builder
if: ${{ matrix.platform != 'mac' }}
run: | run: |
pnpm electron-builder --${{ matrix.platform }} --publish always pnpm electron-builder --${{ matrix.platform }} --publish always
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- 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 }}

View file

@ -3,14 +3,14 @@
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 cross platform desktop app aiming to give you a snappier Discord experience with [Vencord](https://github.com/Vendicated/Vencord) pre-installed
**Not yet supported**: **Not yet supported**:
- Global Keybinds
- Global Keybinds
Bug reports, feature requests & contributions are highly appreciated!! Bug reports, feature requests & contributions are highly appreciated!!
![](https://github.com/Vencord/Vesktop/assets/45497981/8608a899-96a9-4027-9725-2cb02ba189fd) ![](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) ![grafik](https://github.com/Vencord/Vesktop/assets/45497981/8701e5de-52c4-4346-a990-719cb971642e)
## Installing ## Installing
### Windows ### Windows
@ -39,7 +39,7 @@ Download Vesktop-VERSION.rpm from [releases](https://github.com/Vencord/Vesktop/
#### Other #### Other
Either download Vesktop-VERSION.AppImage and just run it directly or grab Vesktop-VERSION.tar.gz, extract it somewhere and run `vencorddesktop`. 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. If other packages are created, feel free to open an issue and we'll link them here.

View file

@ -1,8 +1,8 @@
!macro preInit !macro preInit
SetRegView 64 SetRegView 64
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
SetRegView 32 SetRegView 32
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
!macroend !macroend

View file

@ -28,6 +28,22 @@
</screenshot> </screenshot>
</screenshots> </screenshots>
<releases> <releases>
<release version="1.5.0" date="2024-01-16" type="stable">
<url>https://github.com/Vencord/Vesktop/releases/tag/v1.5.0</url>
<description>
<p>What's Changed</p>
<ul>
<li>fully renamed to Vesktop. You will likely have to login to Discord again. You might have to re-create your vesktop shortcut</li>
<li>added option to disable smooth scrolling by @ZirixCZ</li>
<li>added setting to disable hardware acceleration by @zt64</li>
<li>fixed adding connections</li>
<li>fixed / improved discord popouts</li>
<li>you can now use the custom discord titlebar on linux/mac</li>
<li>the splash window is now draggable</li>
<li>now signed on mac</li>
</ul>
</description>
</release>
<release version="0.4.4" date="2023-12-02" type="stable"> <release version="0.4.4" date="2023-12-02" type="stable">
<url>https://github.com/Vencord/Vesktop/releases/tag/v0.4.4</url> <url>https://github.com/Vencord/Vesktop/releases/tag/v0.4.4</url>
<description> <description>

View file

@ -1,6 +1,6 @@
{ {
"name": "VencordDesktop", "name": "vesktop",
"version": "0.4.4", "version": "1.5.0",
"private": true, "private": true,
"description": "", "description": "",
"keywords": [], "keywords": [],
@ -27,17 +27,17 @@
"arrpc": "github:OpenAsar/arrpc#98879cae0565e6fce34e4cb6f544bf42c6a7e7c8" "arrpc": "github:OpenAsar/arrpc#98879cae0565e6fce34e4cb6f544bf42c6a7e7c8"
}, },
"optionalDependencies": { "optionalDependencies": {
"@vencord/venmic": "^3.2.0" "@vencord/venmic": "^3.2.3"
}, },
"devDependencies": { "devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2", "@fal-works/esbuild-plugin-global-externals": "^2.1.2",
"@types/node": "^20.10.6", "@types/node": "^20.11.2",
"@types/react": "^18.2.46", "@types/react": "^18.2.48",
"@typescript-eslint/eslint-plugin": "^6.17.0", "@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.17.0", "@typescript-eslint/parser": "^6.19.0",
"@vencord/types": "^0.1.2", "@vencord/types": "^0.1.2",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"electron": "^28.1.1", "electron": "^28.1.3",
"electron-builder": "^24.9.1", "electron-builder": "^24.9.1",
"esbuild": "^0.19.11", "esbuild": "^0.19.11",
"eslint": "^8.56.0", "eslint": "^8.56.0",
@ -45,10 +45,10 @@
"eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-license-header": "^0.6.0", "eslint-plugin-license-header": "^0.6.0",
"eslint-plugin-path-alias": "^1.0.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-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^3.0.0", "eslint-plugin-unused-imports": "^3.0.0",
"prettier": "^3.1.1", "prettier": "^3.2.2",
"source-map-support": "^0.5.21", "source-map-support": "^0.5.21",
"tsx": "^4.7.0", "tsx": "^4.7.0",
"type-fest": "^4.9.0", "type-fest": "^4.9.0",
@ -61,7 +61,7 @@
"pnpm": ">=8" "pnpm": ">=8"
}, },
"build": { "build": {
"appId": "dev.vencord.desktop", "appId": "dev.vencord.vesktop",
"productName": "Vesktop", "productName": "Vesktop",
"files": [ "files": [
"!*", "!*",
@ -110,8 +110,7 @@
"GenericName": "Internet Messenger", "GenericName": "Internet Messenger",
"Type": "Application", "Type": "Application",
"Categories": "Network;InstantMessaging;Chat;", "Categories": "Network;InstantMessaging;Chat;",
"Keywords": "discord;vencord;electron;chat;", "Keywords": "discord;vencord;electron;chat;"
"StartupWMClass": "VencordDesktop"
} }
}, },
"mac": { "mac": {

210
pnpm-lock.yaml generated
View file

@ -11,25 +11,25 @@ dependencies:
optionalDependencies: optionalDependencies:
'@vencord/venmic': '@vencord/venmic':
specifier: ^3.2.0 specifier: ^3.2.3
version: 3.2.0 version: 3.2.3
devDependencies: devDependencies:
'@fal-works/esbuild-plugin-global-externals': '@fal-works/esbuild-plugin-global-externals':
specifier: ^2.1.2 specifier: ^2.1.2
version: 2.1.2 version: 2.1.2
'@types/node': '@types/node':
specifier: ^20.10.6 specifier: ^20.11.2
version: 20.10.6 version: 20.11.2
'@types/react': '@types/react':
specifier: ^18.2.46 specifier: ^18.2.48
version: 18.2.46 version: 18.2.48
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^6.17.0 specifier: ^6.19.0
version: 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.56.0)(typescript@5.3.3) version: 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^6.17.0 specifier: ^6.19.0
version: 6.17.0(eslint@8.56.0)(typescript@5.3.3) version: 6.19.0(eslint@8.56.0)(typescript@5.3.3)
'@vencord/types': '@vencord/types':
specifier: ^0.1.2 specifier: ^0.1.2
version: 0.1.2 version: 0.1.2
@ -37,8 +37,8 @@ devDependencies:
specifier: ^16.3.1 specifier: ^16.3.1
version: 16.3.1 version: 16.3.1
electron: electron:
specifier: ^28.1.1 specifier: ^28.1.3
version: 28.1.1 version: 28.1.3
electron-builder: electron-builder:
specifier: ^24.9.1 specifier: ^24.9.1
version: 24.9.1 version: 24.9.1
@ -61,17 +61,17 @@ devDependencies:
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.0.0(eslint@8.56.0) version: 1.0.0(eslint@8.56.0)
eslint-plugin-prettier: eslint-plugin-prettier:
specifier: ^5.1.2 specifier: ^5.1.3
version: 5.1.2(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1) version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.2)
eslint-plugin-simple-import-sort: eslint-plugin-simple-import-sort:
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.0(eslint@8.56.0) version: 10.0.0(eslint@8.56.0)
eslint-plugin-unused-imports: eslint-plugin-unused-imports:
specifier: ^3.0.0 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: prettier:
specifier: ^3.1.1 specifier: ^3.2.2
version: 3.1.1 version: 3.2.2
source-map-support: source-map-support:
specifier: ^0.5.21 specifier: ^0.5.21
version: 0.5.21 version: 0.5.21
@ -423,11 +423,11 @@ packages:
resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==}
dev: true dev: true
/@humanwhocodes/config-array@0.11.13: /@humanwhocodes/config-array@0.11.14:
resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
engines: {node: '>=10.10.0'} engines: {node: '>=10.10.0'}
dependencies: dependencies:
'@humanwhocodes/object-schema': 2.0.1 '@humanwhocodes/object-schema': 2.0.2
debug: 4.3.4 debug: 4.3.4
minimatch: 3.1.2 minimatch: 3.1.2
transitivePeerDependencies: transitivePeerDependencies:
@ -439,8 +439,8 @@ packages:
engines: {node: '>=12.22'} engines: {node: '>=12.22'}
dev: true dev: true
/@humanwhocodes/object-schema@2.0.1: /@humanwhocodes/object-schema@2.0.2:
resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==}
dev: true dev: true
/@isaacs/cliui@8.0.2: /@isaacs/cliui@8.0.2:
@ -529,7 +529,7 @@ packages:
dependencies: dependencies:
'@types/http-cache-semantics': 4.0.4 '@types/http-cache-semantics': 4.0.4
'@types/keyv': 3.1.4 '@types/keyv': 3.1.4
'@types/node': 20.10.6 '@types/node': 20.11.2
'@types/responselike': 1.0.3 '@types/responselike': 1.0.3
dev: true dev: true
@ -542,7 +542,7 @@ packages:
/@types/fs-extra@9.0.13: /@types/fs-extra@9.0.13:
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
dependencies: dependencies:
'@types/node': 20.10.6 '@types/node': 20.11.2
dev: true dev: true
/@types/http-cache-semantics@4.0.4: /@types/http-cache-semantics@4.0.4:
@ -560,7 +560,7 @@ packages:
/@types/keyv@3.1.4: /@types/keyv@3.1.4:
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
dependencies: dependencies:
'@types/node': 20.10.6 '@types/node': 20.11.2
dev: true dev: true
/@types/lodash@4.14.202: /@types/lodash@4.14.202:
@ -571,14 +571,14 @@ packages:
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
dev: true dev: true
/@types/node@18.19.4: /@types/node@18.19.7:
resolution: {integrity: sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==} resolution: {integrity: sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==}
dependencies: dependencies:
undici-types: 5.26.5 undici-types: 5.26.5
dev: true dev: true
/@types/node@20.10.6: /@types/node@20.11.2:
resolution: {integrity: sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==} resolution: {integrity: sha512-cZShBaVa+UO1LjWWBPmWRR4+/eY/JR/UIEcDlVsw3okjWEu+rB7/mH6X3B/L+qJVHDLjk9QW/y2upp9wp1yDXA==}
dependencies: dependencies:
undici-types: 5.26.5 undici-types: 5.26.5
dev: true dev: true
@ -587,7 +587,7 @@ packages:
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
requiresBuild: true requiresBuild: true
dependencies: dependencies:
'@types/node': 20.10.6 '@types/node': 20.11.2
xmlbuilder: 15.1.1 xmlbuilder: 15.1.1
dev: true dev: true
optional: true optional: true
@ -599,7 +599,7 @@ packages:
/@types/react-dom@18.2.18: /@types/react-dom@18.2.18:
resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==} resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==}
dependencies: dependencies:
'@types/react': 18.2.46 '@types/react': 18.2.48
dev: true dev: true
/@types/react@17.0.2: /@types/react@17.0.2:
@ -609,8 +609,8 @@ packages:
csstype: 3.1.3 csstype: 3.1.3
dev: true dev: true
/@types/react@18.2.46: /@types/react@18.2.48:
resolution: {integrity: sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==} resolution: {integrity: sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==}
dependencies: dependencies:
'@types/prop-types': 15.7.11 '@types/prop-types': 15.7.11
'@types/scheduler': 0.16.8 '@types/scheduler': 0.16.8
@ -620,7 +620,7 @@ packages:
/@types/responselike@1.0.3: /@types/responselike@1.0.3:
resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
dependencies: dependencies:
'@types/node': 20.10.6 '@types/node': 20.11.2
dev: true dev: true
/@types/scheduler@0.16.8: /@types/scheduler@0.16.8:
@ -641,12 +641,12 @@ packages:
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
requiresBuild: true requiresBuild: true
dependencies: dependencies:
'@types/node': 20.10.6 '@types/node': 20.11.2
dev: true dev: true
optional: true optional: true
/@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):
resolution: {integrity: sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==} resolution: {integrity: sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
@ -657,11 +657,11 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@eslint-community/regexpp': 4.10.0 '@eslint-community/regexpp': 4.10.0
'@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)
'@typescript-eslint/scope-manager': 6.17.0 '@typescript-eslint/scope-manager': 6.19.0
'@typescript-eslint/type-utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/type-utils': 6.19.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/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 6.17.0 '@typescript-eslint/visitor-keys': 6.19.0
debug: 4.3.4 debug: 4.3.4
eslint: 8.56.0 eslint: 8.56.0
graphemer: 1.4.0 graphemer: 1.4.0
@ -674,8 +674,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@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):
resolution: {integrity: sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==} resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
@ -684,10 +684,10 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/scope-manager': 6.17.0 '@typescript-eslint/scope-manager': 6.19.0
'@typescript-eslint/types': 6.17.0 '@typescript-eslint/types': 6.19.0
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 6.17.0 '@typescript-eslint/visitor-keys': 6.19.0
debug: 4.3.4 debug: 4.3.4
eslint: 8.56.0 eslint: 8.56.0
typescript: 5.3.3 typescript: 5.3.3
@ -695,16 +695,16 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/scope-manager@6.17.0: /@typescript-eslint/scope-manager@6.19.0:
resolution: {integrity: sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==} resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
dependencies: dependencies:
'@typescript-eslint/types': 6.17.0 '@typescript-eslint/types': 6.19.0
'@typescript-eslint/visitor-keys': 6.17.0 '@typescript-eslint/visitor-keys': 6.19.0
dev: true dev: true
/@typescript-eslint/type-utils@6.17.0(eslint@8.56.0)(typescript@5.3.3): /@typescript-eslint/type-utils@6.19.0(eslint@8.56.0)(typescript@5.3.3):
resolution: {integrity: sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==} resolution: {integrity: sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
@ -713,8 +713,8 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3)
'@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3)
debug: 4.3.4 debug: 4.3.4
eslint: 8.56.0 eslint: 8.56.0
ts-api-utils: 1.0.3(typescript@5.3.3) ts-api-utils: 1.0.3(typescript@5.3.3)
@ -723,13 +723,13 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/types@6.17.0: /@typescript-eslint/types@6.19.0:
resolution: {integrity: sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==} resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
dev: true dev: true
/@typescript-eslint/typescript-estree@6.17.0(typescript@5.3.3): /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3):
resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==} resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
typescript: '*' typescript: '*'
@ -737,8 +737,8 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/types': 6.17.0 '@typescript-eslint/types': 6.19.0
'@typescript-eslint/visitor-keys': 6.17.0 '@typescript-eslint/visitor-keys': 6.19.0
debug: 4.3.4 debug: 4.3.4
globby: 11.1.0 globby: 11.1.0
is-glob: 4.0.3 is-glob: 4.0.3
@ -750,8 +750,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/utils@6.17.0(eslint@8.56.0)(typescript@5.3.3): /@typescript-eslint/utils@6.19.0(eslint@8.56.0)(typescript@5.3.3):
resolution: {integrity: sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==} resolution: {integrity: sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
@ -759,9 +759,9 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
'@types/json-schema': 7.0.15 '@types/json-schema': 7.0.15
'@types/semver': 7.5.6 '@types/semver': 7.5.6
'@typescript-eslint/scope-manager': 6.17.0 '@typescript-eslint/scope-manager': 6.19.0
'@typescript-eslint/types': 6.17.0 '@typescript-eslint/types': 6.19.0
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3)
eslint: 8.56.0 eslint: 8.56.0
semver: 7.5.4 semver: 7.5.4
transitivePeerDependencies: transitivePeerDependencies:
@ -769,11 +769,11 @@ packages:
- typescript - typescript
dev: true dev: true
/@typescript-eslint/visitor-keys@6.17.0: /@typescript-eslint/visitor-keys@6.19.0:
resolution: {integrity: sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==} resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
dependencies: dependencies:
'@typescript-eslint/types': 6.17.0 '@typescript-eslint/types': 6.19.0
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
dev: true dev: true
@ -785,16 +785,16 @@ packages:
resolution: {integrity: sha512-C/dqZHn3aod/4izZT9sgZEef4478M7QNKTY8Gx2yB1CRYawJcs6hupXT/1SMmepKqrULbltL04Cnh5ieBm3Ucw==} resolution: {integrity: sha512-C/dqZHn3aod/4izZT9sgZEef4478M7QNKTY8Gx2yB1CRYawJcs6hupXT/1SMmepKqrULbltL04Cnh5ieBm3Ucw==}
dependencies: dependencies:
'@types/lodash': 4.14.202 '@types/lodash': 4.14.202
'@types/node': 18.19.4 '@types/node': 18.19.7
'@types/react': 18.2.46 '@types/react': 18.2.48
'@types/react-dom': 18.2.18 '@types/react-dom': 18.2.18
discord-types: 1.3.26 discord-types: 1.3.26
standalone-electron-types: 1.0.0 standalone-electron-types: 1.0.0
type-fest: 3.13.1 type-fest: 3.13.1
dev: true dev: true
/@vencord/venmic@3.2.0: /@vencord/venmic@3.2.3:
resolution: {integrity: sha512-z+Lgmr6IgjkPEIfFZ3ZwVV4aP/OFjnB6k6Ll5YpBPuDZOyqCbKTNLADApbZa/WxMfm7YpZ22g46X4FfizuprEQ==} resolution: {integrity: sha512-mnpAa5aFRkMQhoeYjkygPY+U+/b7Nh55HekchWzl2y5RNHpCxooGANTcw4L80JoCiL+AYRUg8BQU31L7fFQcPw==}
engines: {node: '>=14.15'} engines: {node: '>=14.15'}
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
@ -1066,7 +1066,7 @@ packages:
resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==}
requiresBuild: true requiresBuild: true
dependencies: dependencies:
follow-redirects: 1.15.4(debug@4.3.4) follow-redirects: 1.15.5(debug@4.3.4)
form-data: 4.0.0 form-data: 4.0.0
proxy-from-env: 1.1.0 proxy-from-env: 1.1.0
transitivePeerDependencies: transitivePeerDependencies:
@ -1225,7 +1225,7 @@ packages:
dependencies: dependencies:
function-bind: 1.1.2 function-bind: 1.1.2
get-intrinsic: 1.2.2 get-intrinsic: 1.2.2
set-function-length: 1.1.1 set-function-length: 1.2.0
dev: true dev: true
/callsites@3.1.0: /callsites@3.1.0:
@ -1651,14 +1651,14 @@ packages:
- supports-color - supports-color
dev: true dev: true
/electron@28.1.1: /electron@28.1.3:
resolution: {integrity: sha512-HJSbGHpRl46jWCp5G4OH57KSm2F5u15tB10ixD8iFiz9dhwojqlSQTRAcjSwvga+Vqs1jv7iqwQRrolXP4DgOA==} resolution: {integrity: sha512-NSFyTo6SndTPXzU18XRePv4LnjmuM9rF5GMKta1/kPmi02ISoSRonnD7wUlWXD2x53XyJ6d/TbSVesMW6sXkEQ==}
engines: {node: '>= 12.20.55'} engines: {node: '>= 12.20.55'}
hasBin: true hasBin: true
requiresBuild: true requiresBuild: true
dependencies: dependencies:
'@electron/get': 2.0.3 '@electron/get': 2.0.3
'@types/node': 18.19.4 '@types/node': 18.19.7
extract-zip: 2.0.1 extract-zip: 2.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -1718,8 +1718,8 @@ packages:
object-keys: 1.1.1 object-keys: 1.1.1
object.assign: 4.1.5 object.assign: 4.1.5
regexp.prototype.flags: 1.5.1 regexp.prototype.flags: 1.5.1
safe-array-concat: 1.0.1 safe-array-concat: 1.1.0
safe-regex-test: 1.0.0 safe-regex-test: 1.0.2
string.prototype.trim: 1.2.8 string.prototype.trim: 1.2.8
string.prototype.trimend: 1.0.7 string.prototype.trimend: 1.0.7
string.prototype.trimstart: 1.0.7 string.prototype.trimstart: 1.0.7
@ -1816,7 +1816,7 @@ packages:
peerDependencies: peerDependencies:
eslint-plugin-import: '>=1.4.0' eslint-plugin-import: '>=1.4.0'
dependencies: 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 dev: true
/eslint-import-resolver-node@0.3.9: /eslint-import-resolver-node@0.3.9:
@ -1829,7 +1829,7 @@ packages:
- supports-color - supports-color
dev: true 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==} resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
@ -1850,7 +1850,7 @@ packages:
eslint-import-resolver-webpack: eslint-import-resolver-webpack:
optional: true optional: true
dependencies: 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 debug: 3.2.7
eslint: 8.56.0 eslint: 8.56.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
@ -1858,7 +1858,7 @@ packages:
- supports-color - supports-color
dev: true 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==} resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
@ -1868,7 +1868,7 @@ packages:
'@typescript-eslint/parser': '@typescript-eslint/parser':
optional: true optional: true
dependencies: 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-includes: 3.1.7
array.prototype.findlastindex: 1.2.3 array.prototype.findlastindex: 1.2.3
array.prototype.flat: 1.3.2 array.prototype.flat: 1.3.2
@ -1877,7 +1877,7 @@ packages:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.56.0 eslint: 8.56.0
eslint-import-resolver-node: 0.3.9 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 hasown: 2.0.0
is-core-module: 2.13.1 is-core-module: 2.13.1
is-glob: 4.0.3 is-glob: 4.0.3
@ -1910,8 +1910,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/eslint-plugin-prettier@5.1.2(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1): /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.2):
resolution: {integrity: sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==} resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies: peerDependencies:
'@types/eslint': '>=8.0.0' '@types/eslint': '>=8.0.0'
@ -1926,7 +1926,7 @@ packages:
dependencies: dependencies:
eslint: 8.56.0 eslint: 8.56.0
eslint-config-prettier: 9.1.0(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 prettier-linter-helpers: 1.0.0
synckit: 0.8.8 synckit: 0.8.8
dev: true dev: true
@ -1939,7 +1939,7 @@ packages:
eslint: 8.56.0 eslint: 8.56.0
dev: true 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==} resolution: {integrity: sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -1949,7 +1949,7 @@ packages:
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
optional: true optional: true
dependencies: 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: 8.56.0
eslint-rule-composer: 0.3.0 eslint-rule-composer: 0.3.0
dev: true dev: true
@ -1981,7 +1981,7 @@ packages:
'@eslint-community/regexpp': 4.10.0 '@eslint-community/regexpp': 4.10.0
'@eslint/eslintrc': 2.1.4 '@eslint/eslintrc': 2.1.4
'@eslint/js': 8.56.0 '@eslint/js': 8.56.0
'@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/config-array': 0.11.14
'@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8 '@nodelib/fs.walk': 1.2.8
'@ungap/structured-clone': 1.2.0 '@ungap/structured-clone': 1.2.0
@ -2168,8 +2168,8 @@ packages:
resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
dev: true dev: true
/follow-redirects@1.15.4(debug@4.3.4): /follow-redirects@1.15.5(debug@4.3.4):
resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==} resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
@ -3388,8 +3388,8 @@ packages:
fast-diff: 1.3.0 fast-diff: 1.3.0
dev: true dev: true
/prettier@3.1.1: /prettier@3.2.2:
resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} resolution: {integrity: sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dev: true dev: true
@ -3570,8 +3570,8 @@ packages:
queue-microtask: 1.2.3 queue-microtask: 1.2.3
dev: true dev: true
/safe-array-concat@1.0.1: /safe-array-concat@1.1.0:
resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==}
engines: {node: '>=0.4'} engines: {node: '>=0.4'}
dependencies: dependencies:
call-bind: 1.0.5 call-bind: 1.0.5
@ -3586,8 +3586,9 @@ packages:
dev: false dev: false
optional: true optional: true
/safe-regex-test@1.0.0: /safe-regex-test@1.0.2:
resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==}
engines: {node: '>= 0.4'}
dependencies: dependencies:
call-bind: 1.0.5 call-bind: 1.0.5
get-intrinsic: 1.2.2 get-intrinsic: 1.2.2
@ -3647,11 +3648,12 @@ packages:
dev: false dev: false
optional: true optional: true
/set-function-length@1.1.1: /set-function-length@1.2.0:
resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
dependencies: dependencies:
define-data-property: 1.1.1 define-data-property: 1.1.1
function-bind: 1.1.2
get-intrinsic: 1.2.2 get-intrinsic: 1.2.2
gopd: 1.0.1 gopd: 1.0.1
has-property-descriptors: 1.0.1 has-property-descriptors: 1.0.1
@ -3802,7 +3804,7 @@ packages:
/standalone-electron-types@1.0.0: /standalone-electron-types@1.0.0:
resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==}
dependencies: dependencies:
'@types/node': 18.19.4 '@types/node': 18.19.7
dev: true dev: true
/stat-mode@1.0.0: /stat-mode@1.0.0:

View file

@ -5,9 +5,29 @@
*/ */
import { app } from "electron"; import { app } from "electron";
import { existsSync, readdirSync, renameSync, rmdirSync } from "fs";
import { join } from "path"; import { join } from "path";
export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR || join(app.getPath("userData"), "VencordDesktop"); const LEGACY_DATA_DIR = join(app.getPath("appData"), "VencordDesktop", "VencordDesktop");
export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR || join(app.getPath("userData"));
// TODO: remove eventually
if (existsSync(LEGACY_DATA_DIR)) {
try {
console.warn("Detected legacy settings dir", LEGACY_DATA_DIR + ".", "migrating to", DATA_DIR);
for (const file of readdirSync(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);
}
}
app.setPath("sessionData", join(DATA_DIR, "sessionData"));
export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings"); export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings");
export const VENCORD_QUICKCSS_FILE = join(VENCORD_SETTINGS_DIR, "quickCss.css"); export const VENCORD_QUICKCSS_FILE = join(VENCORD_SETTINGS_DIR, "quickCss.css");
export const VENCORD_SETTINGS_FILE = join(VENCORD_SETTINGS_DIR, "settings.json"); export const VENCORD_SETTINGS_FILE = join(VENCORD_SETTINGS_DIR, "settings.json");
@ -26,6 +46,8 @@ export const MIN_HEIGHT = 500;
export const DEFAULT_WIDTH = 1280; export const DEFAULT_WIDTH = 1280;
export const DEFAULT_HEIGHT = 720; export const DEFAULT_HEIGHT = 720;
export const DISCORD_HOSTNAMES = ["discord.com", "canary.discord.com", "ptb.discord.com"];
const UserAgents = { 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", 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", linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",

View file

@ -14,7 +14,7 @@ import { ICON_PATH, VIEW_DIR } from "shared/paths";
import { autoStart } from "./autoStart"; import { autoStart } from "./autoStart";
import { DATA_DIR } from "./constants"; import { DATA_DIR } from "./constants";
import { createWindows } from "./mainWindow"; import { createWindows } from "./mainWindow";
import { Settings } from "./settings"; import { Settings, State } from "./settings";
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
interface Data { interface Data {
@ -44,9 +44,9 @@ export function createFirstLaunchTour() {
if (!msg.startsWith("form:")) return; if (!msg.startsWith("form:")) return;
const data = JSON.parse(msg.slice(5)) as Data; const data = JSON.parse(msg.slice(5)) as Data;
State.store.firstLaunch = false;
Settings.store.minimizeToTray = data.minimizeToTray; Settings.store.minimizeToTray = data.minimizeToTray;
Settings.store.discordBranch = data.discordBranch; Settings.store.discordBranch = data.discordBranch;
Settings.store.firstLaunch = false;
Settings.store.arRPC = data.richPresence; Settings.store.arRPC = data.richPresence;
if (data.autoStart) autoStart.enable(); if (data.autoStart) autoStart.enable();

View file

@ -14,7 +14,7 @@ import { createFirstLaunchTour } from "./firstLaunch";
import { createWindows, mainWin } from "./mainWindow"; import { createWindows, mainWin } from "./mainWindow";
import { registerMediaPermissionsHandler } from "./mediaPermissions"; import { registerMediaPermissionsHandler } from "./mediaPermissions";
import { registerScreenShareHandler } from "./screenShare"; import { registerScreenShareHandler } from "./screenShare";
import { Settings } from "./settings"; import { Settings, State } from "./settings";
import { isDeckGameMode } from "./utils/steamOS"; import { isDeckGameMode } from "./utils/steamOS";
if (IS_DEV) { if (IS_DEV) {
@ -58,7 +58,7 @@ function init() {
app.whenReady().then(async () => { app.whenReady().then(async () => {
checkUpdates(); checkUpdates();
if (process.platform === "win32") app.setAppUserModelId("dev.vencord.desktop"); if (process.platform === "win32") app.setAppUserModelId("dev.vencord.vesktop");
registerScreenShareHandler(); registerScreenShareHandler();
registerMediaPermissionsHandler(); registerMediaPermissionsHandler();
@ -84,7 +84,7 @@ if (!app.requestSingleInstanceLock({ IS_DEV })) {
} }
async function bootstrap() { async function bootstrap() {
if (!Object.hasOwn(Settings.store, "firstLaunch")) { if (!Object.hasOwn(State.store, "firstLaunch")) {
createFirstLaunchTour(); createFirstLaunchTour();
} else { } else {
createWindows(); createWindows();

View file

@ -4,10 +4,10 @@
* Copyright (c) 2023 Vendicated and Vencord contributors * Copyright (c) 2023 Vendicated and Vencord contributors
*/ */
if (process.platform === "linux") import("./virtmic"); if (process.platform === "linux") import("./venmic");
import { execFile } from "child_process"; 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 { mkdirSync, readFileSync, watch } from "fs";
import { open, readFile } from "fs/promises"; import { open, readFile } from "fs/promises";
import { release } from "os"; import { release } from "os";
@ -120,6 +120,13 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count)); handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count));
handle(IpcEvents.CLIPBOARD_COPY_IMAGE, async (_, buf: ArrayBuffer, src: string) => {
clipboard.write({
html: `<img src="${src.replaceAll('"', '\\"')}">`,
image: nativeImage.createFromBuffer(Buffer.from(buf))
});
});
function readCss() { function readCss() {
return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => ""); return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => "");
} }

View file

@ -34,7 +34,7 @@ import {
UserAgent, UserAgent,
VENCORD_FILES_DIR VENCORD_FILES_DIR
} from "./constants"; } from "./constants";
import { Settings, VencordSettings } from "./settings"; import { Settings, State, VencordSettings } from "./settings";
import { createSplashWindow } from "./splash"; import { createSplashWindow } from "./splash";
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS"; import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS";
@ -78,8 +78,7 @@ function initTray(win: BrowserWindow) {
label: "Open", label: "Open",
click() { click() {
win.show(); win.show();
}, }
enabled: false
}, },
{ {
label: "About", label: "About",
@ -122,14 +121,6 @@ function initTray(win: BrowserWindow) {
tray.setToolTip("Vesktop"); tray.setToolTip("Vesktop");
tray.setContextMenu(trayMenu); tray.setContextMenu(trayMenu);
tray.on("click", () => win.show()); 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) { async function clearData(win: BrowserWindow) {
@ -210,7 +201,6 @@ function initMenuBar(win: BrowserWindow) {
type: "separator" type: "separator"
}, },
{ {
label: "Hide Vesktop", // Should probably remove the label, but it says "Hide VencordDesktop" instead of "Hide Vesktop"
role: "hide" role: "hide"
}, },
{ {
@ -268,7 +258,7 @@ function getWindowBoundsOptions(): BrowserWindowConstructorOptions {
// We want the default window behaivour to apply in game mode since it expects everything to be fullscreen and maximized. // We want the default window behaivour to apply in game mode since it expects everything to be fullscreen and maximized.
if (isDeckGameMode) return {}; if (isDeckGameMode) return {};
const { x, y, width, height } = Settings.store.windowBounds ?? {}; const { x, y, width, height } = State.store.windowBounds ?? {};
const options = { const options = {
width: width ?? DEFAULT_WIDTH, width: width ?? DEFAULT_WIDTH,
@ -313,8 +303,8 @@ function getDarwinOptions(): BrowserWindowConstructorOptions {
function initWindowBoundsListeners(win: BrowserWindow) { function initWindowBoundsListeners(win: BrowserWindow) {
const saveState = () => { const saveState = () => {
Settings.store.maximized = win.isMaximized(); State.store.maximized = win.isMaximized();
Settings.store.minimized = win.isMinimized(); State.store.minimized = win.isMinimized();
}; };
win.on("maximize", saveState); win.on("maximize", saveState);
@ -322,7 +312,7 @@ function initWindowBoundsListeners(win: BrowserWindow) {
win.on("unmaximize", saveState); win.on("unmaximize", saveState);
const saveBounds = () => { const saveBounds = () => {
Settings.store.windowBounds = win.getBounds(); State.store.windowBounds = win.getBounds();
}; };
win.on("resize", saveBounds); win.on("resize", saveBounds);
@ -375,11 +365,11 @@ function createMainWindow() {
removeSettingsListeners(); removeSettingsListeners();
removeVencordSettingsListeners(); removeVencordSettingsListeners();
const { staticTitle, transparencyOption, enableMenu, discordWindowsTitleBar } = Settings.store; const { staticTitle, transparencyOption, enableMenu, customTitleBar } = Settings.store;
const { frameless } = VencordSettings.store; const { frameless } = VencordSettings.store;
const noFrame = frameless === true || (process.platform === "win32" && discordWindowsTitleBar === true); const noFrame = frameless === true || customTitleBar === true;
const win = (mainWin = new BrowserWindow({ const win = (mainWin = new BrowserWindow({
show: false, show: false,
@ -396,7 +386,12 @@ function createMainWindow() {
...(transparencyOption && ...(transparencyOption &&
transparencyOption !== "none" && { transparencyOption !== "none" && {
backgroundColor: "#00000000", backgroundColor: "#00000000",
backgroundMaterial: transparencyOption, backgroundMaterial: transparencyOption
}),
// Fix transparencyOption for custom discord titlebar
...(customTitleBar &&
transparencyOption &&
transparencyOption !== "none" && {
transparent: true transparent: true
}), }),
...(staticTitle && { title: "Vesktop" }), ...(staticTitle && { title: "Vesktop" }),
@ -442,7 +437,8 @@ function createMainWindow() {
const runVencordMain = once(() => require(join(VENCORD_FILES_DIR, "vencordDesktopMain.js"))); const runVencordMain = once(() => require(join(VENCORD_FILES_DIR, "vencordDesktopMain.js")));
export async function createWindows() { export async function createWindows() {
const splash = createSplashWindow(); const startMinimized = process.argv.includes("--start-minimized");
const splash = createSplashWindow(startMinimized);
// SteamOS letterboxes and scales it terribly, so just full screen it // SteamOS letterboxes and scales it terribly, so just full screen it
if (isDeckGameMode) splash.setFullScreen(true); if (isDeckGameMode) splash.setFullScreen(true);
await ensureVencordFiles(); await ensureVencordFiles();
@ -452,10 +448,10 @@ export async function createWindows() {
mainWin.webContents.on("did-finish-load", () => { mainWin.webContents.on("did-finish-load", () => {
splash.destroy(); splash.destroy();
mainWin!.show();
if (Settings.store.maximized && !isDeckGameMode) { if (!startMinimized) {
mainWin!.maximize(); mainWin!.show();
if (State.store.maximized && !isDeckGameMode) mainWin!.maximize();
} }
if (isDeckGameMode) { if (isDeckGameMode) {
@ -464,6 +460,12 @@ export async function createWindows() {
askToApplySteamLayout(mainWin); askToApplySteamLayout(mainWin);
} }
mainWin.once("show", () => {
if (State.store.maximized && !mainWin!.isMaximized() && !isDeckGameMode) {
mainWin!.maximize();
}
});
}); });
initArRPC(); initArRPC();

View file

@ -4,14 +4,15 @@
* Copyright (c) 2023 Vendicated and Vencord contributors * Copyright (c) 2023 Vendicated and Vencord contributors
*/ */
import { mkdirSync, readFileSync, writeFileSync } from "fs"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import { dirname, join } from "path"; import { dirname, join } from "path";
import type { Settings as TSettings } from "shared/settings"; import type { Settings as TSettings, State as TState } from "shared/settings";
import { SettingsStore } from "shared/utils/SettingsStore"; import { SettingsStore } from "shared/utils/SettingsStore";
import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants"; import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants";
const SETTINGS_FILE = join(DATA_DIR, "settings.json"); const SETTINGS_FILE = join(DATA_DIR, "settings.json");
const STATE_FILE = join(DATA_DIR, "state.json");
function loadSettings<T extends object = any>(file: string, name: string) { function loadSettings<T extends object = any>(file: string, name: string) {
let settings = {} as T; let settings = {} as T;
@ -20,7 +21,7 @@ function loadSettings<T extends object = any>(file: string, name: string) {
try { try {
settings = JSON.parse(content); settings = JSON.parse(content);
} catch (err) { } catch (err) {
console.error(`Failed to parse ${name} settings.json:`, err); console.error(`Failed to parse ${name}.json:`, err);
} }
} catch {} } catch {}
@ -33,5 +34,31 @@ function loadSettings<T extends object = any>(file: string, name: string) {
return store; return store;
} }
export const Settings = loadSettings<TSettings>(SETTINGS_FILE, "Vesktop"); export const Settings = loadSettings<TSettings>(SETTINGS_FILE, "Vesktop settings");
export const VencordSettings = loadSettings<any>(VENCORD_SETTINGS_FILE, "Vencord"); if (Object.hasOwn(Settings.plain, "discordWindowsTitleBar")) {
Settings.plain.customTitleBar = Settings.plain.discordWindowsTitleBar;
delete Settings.plain.discordWindowsTitleBar;
Settings.markAsChanged();
}
export const VencordSettings = loadSettings<any>(VENCORD_SETTINGS_FILE, "Vencord settings");
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 [
"firstLaunch",
"maximized",
"minimized",
"skippedUpdate",
"steamOSLayoutVersion",
"windowBounds"
] as const) {
state[prop] = Settings.plain[prop];
delete Settings.plain[prop];
}
Settings.markAsChanged();
writeFileSync(STATE_FILE, JSON.stringify(state, null, 4));
}
export const State = loadSettings<TState>(STATE_FILE, "Vesktop state");

View file

@ -11,10 +11,11 @@ import { ICON_PATH, VIEW_DIR } from "shared/paths";
import { Settings } from "./settings"; import { Settings } from "./settings";
export function createSplashWindow() { export function createSplashWindow(startMinimized = false) {
const splash = new BrowserWindow({ const splash = new BrowserWindow({
...SplashProps, ...SplashProps,
icon: ICON_PATH icon: ICON_PATH,
show: !startMinimized
}); });
splash.loadFile(join(VIEW_DIR, "splash.html")); splash.loadFile(join(VIEW_DIR, "splash.html"));

View file

@ -5,20 +5,14 @@
*/ */
import { ipcMain, IpcMainEvent, IpcMainInvokeEvent, WebFrameMain } from "electron"; import { ipcMain, IpcMainEvent, IpcMainInvokeEvent, WebFrameMain } from "electron";
import { DISCORD_HOSTNAMES } from "main/constants";
import { IpcEvents } from "shared/IpcEvents"; import { IpcEvents } from "shared/IpcEvents";
export function validateSender(frame: WebFrameMain) { export function validateSender(frame: WebFrameMain) {
const { hostname, protocol } = new URL(frame.url); const { hostname, protocol } = new URL(frame.url);
if (protocol === "file:") return; if (protocol === "file:") return;
switch (hostname) { if (!DISCORD_HOSTNAMES.includes(hostname)) throw new Error("ipc: Disallowed host " + hostname);
case "discord.com":
case "ptb.discord.com":
case "canary.discord.com":
break;
default:
throw new Error("ipc: Disallowed host " + hostname);
}
} }
export function handleSync(event: IpcEvents, cb: (e: IpcMainEvent, ...args: any[]) => any) { export function handleSync(event: IpcEvents, cb: (e: IpcMainEvent, ...args: any[]) => any) {

View file

@ -5,48 +5,67 @@
*/ */
import { BrowserWindow, shell } from "electron"; import { BrowserWindow, shell } from "electron";
import { DISCORD_HOSTNAMES } from "main/constants";
import { Settings } from "../settings"; import { Settings } from "../settings";
import { createOrFocusPopup, setupPopout } from "./popout";
import { execSteamURL, isDeckGameMode, steamOpenURL } from "./steamOS"; import { execSteamURL, isDeckGameMode, steamOpenURL } from "./steamOS";
export function makeLinksOpenExternally(win: BrowserWindow) { export function handleExternalUrl(url: string, protocol?: string): { action: "deny" | "allow" } {
win.webContents.setWindowOpenHandler(({ url }) => { if (protocol == null) {
switch (url) {
case "about:blank":
case "https://discord.com/popout":
return { action: "allow" };
}
try { 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 { } catch {
return { action: "deny" }; return { action: "deny" };
} }
switch (protocol) { if (frameName.startsWith("DISCORD_") && pathname === "/popout" && DISCORD_HOSTNAMES.includes(hostname)) {
case "http:": return createOrFocusPopup(frameName, features);
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" }; 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);
}); });
} }

112
src/main/utils/popout.ts Normal file
View file

@ -0,0 +1,112 @@
/*
* 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 { 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: process.platform === "linux",
titleBarStyle: process.platform === "darwin" ? "hidden" : undefined,
trafficLightPosition:
process.platform === "darwin"
? {
x: 10,
y: 3
}
: undefined,
webPreferences: {
nodeIntegration: false,
contextIsolation: true
}
};
const PopoutWindows = new Map<string, BrowserWindow>();
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 <const>{ action: "deny" };
}
return <const>{
action: "allow",
overrideBrowserWindowOptions: {
...DEFAULT_POPOUT_OPTIONS,
...parseWindowFeatures(features)
}
};
}
export function setupPopout(win: BrowserWindow, key: string) {
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);
});
}

View file

@ -9,7 +9,7 @@ import { writeFile } from "fs/promises";
import { join } from "path"; import { join } from "path";
import { MessageBoxChoice } from "../constants"; import { MessageBoxChoice } from "../constants";
import { Settings } from "../settings"; import { State } from "../settings";
// Bump this to re-show the prompt // Bump this to re-show the prompt
const layoutVersion = 2; const layoutVersion = 2;
@ -70,8 +70,8 @@ async function showLayout(appId: string) {
export async function askToApplySteamLayout(win: BrowserWindow) { export async function askToApplySteamLayout(win: BrowserWindow) {
const appId = getAppId(); const appId = getAppId();
if (!appId) return; if (!appId) return;
if (Settings.store.steamOSLayoutVersion === layoutVersion) return; if (State.store.steamOSLayoutVersion === layoutVersion) return;
const update = Boolean(Settings.store.steamOSLayoutVersion); const update = Boolean(State.store.steamOSLayoutVersion);
// Touch screen breaks in some menus when native touch mode is enabled on latest SteamOS beta, remove most of the update specific text once that's fixed. // Touch screen breaks in some menus when native touch mode is enabled on latest SteamOS beta, remove most of the update specific text once that's fixed.
const { response } = await dialog.showMessageBox(win, { const { response } = await dialog.showMessageBox(win, {
@ -87,8 +87,8 @@ ${update ? "Click" : "Tap"} no to keep your current layout.`,
type: "question" type: "question"
}); });
if (Settings.store.steamOSLayoutVersion !== layoutVersion) { if (State.store.steamOSLayoutVersion !== layoutVersion) {
Settings.store.steamOSLayoutVersion = layoutVersion; State.store.steamOSLayoutVersion = layoutVersion;
} }
if (response === MessageBoxChoice.Cancel) return; if (response === MessageBoxChoice.Cancel) return;

View file

@ -51,22 +51,17 @@ ipcMain.handle(IpcEvents.VIRT_MIC_LIST, () => {
: { ok: false, isGlibcxxToOld }; : { ok: false, isGlibcxxToOld };
}); });
ipcMain.handle( ipcMain.handle(IpcEvents.VIRT_MIC_START, (_, targets: string[]) =>
IpcEvents.VIRT_MIC_START, obtainVenmic()?.link({
(_, targets: string[]) => include: targets.map(target => ({ key: "application.name", value: target })),
obtainVenmic()?.link({ exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }]
include: targets.map(target => ({ key: "application.name", value: target })), })
exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }]
})
); );
ipcMain.handle( ipcMain.handle(IpcEvents.VIRT_MIC_START_SYSTEM, () =>
IpcEvents.VIRT_MIC_START_SYSTEM, obtainVenmic()?.link({
() => exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }]
// @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_STOP, () => obtainVenmic()?.unlink()); ipcMain.handle(IpcEvents.VIRT_MIC_STOP, () => obtainVenmic()?.unlink());

View file

@ -71,5 +71,9 @@ export const VesktopNative = {
onActivity(cb: (data: string) => void) { onActivity(cb: (data: string) => void) {
ipcRenderer.on(IpcEvents.ARRPC_ACTIVITY, (_, data: string) => cb(data)); ipcRenderer.on(IpcEvents.ARRPC_ACTIVITY, (_, data: string) => cb(data));
} }
},
clipboard: {
copyImage: (imageBuffer: Uint8Array, imageSrc: string) =>
invoke<void>(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc)
} }
}; };

View file

@ -10,7 +10,7 @@ import { Margins } from "@vencord/types/utils";
import { Button, Forms, Select, Switch, Text, Toasts, useState } from "@vencord/types/webpack/common"; import { Button, Forms, Select, Switch, Text, Toasts, useState } from "@vencord/types/webpack/common";
import { setBadge } from "renderer/appBadge"; import { setBadge } from "renderer/appBadge";
import { useSettings } from "renderer/settings"; import { useSettings } from "renderer/settings";
import { isMac, isWindows } from "renderer/utils"; import { isMac } from "renderer/utils";
import { isTruthy } from "shared/utils/guards"; import { isTruthy } from "shared/utils/guards";
export default function SettingsUi() { export default function SettingsUi() {
@ -21,10 +21,10 @@ export default function SettingsUi() {
const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled()); const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled());
const allSwitches: Array<false | [keyof typeof Settings, string, string, boolean?, (() => boolean)?]> = [ const allSwitches: Array<false | [keyof typeof Settings, string, string, boolean?, (() => boolean)?]> = [
isWindows && [ [
"discordWindowsTitleBar", "customTitleBar",
"Discord Titlebar", "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."
], ],
!isMac && ["tray", "Tray Icon", "Add a tray icon for Vesktop", true], !isMac && ["tray", "Tray Icon", "Add a tray icon for Vesktop", true],
!isMac && [ !isMac && [

View file

@ -5,7 +5,7 @@
*/ */
import { Settings } from "renderer/settings"; import { Settings } from "renderer/settings";
import { isMac, isWindows } from "renderer/utils"; import { isMac } from "renderer/utils";
import { addPatch } from "./shared"; import { addPatch } from "./shared";
@ -22,8 +22,8 @@ addPatch({
], ],
getPlatformClass() { getPlatformClass() {
if (Settings.store.customTitleBar) return "platform-win";
if (isMac) return "platform-osx"; if (isMac) return "platform-osx";
if (isWindows && Settings.store.discordWindowsTitleBar) return "platform-win";
return "platform-web"; return "platform-web";
} }
}); });

View file

@ -8,7 +8,7 @@ import { Settings } from "renderer/settings";
import { addPatch } from "./shared"; import { addPatch } from "./shared";
if (Settings.store.discordWindowsTitleBar) if (Settings.store.customTitleBar)
addPatch({ addPatch({
patches: [ patches: [
{ {

View file

@ -47,5 +47,7 @@ export const enum IpcEvents {
VIRT_MIC_START_SYSTEM = "VCD_VIRT_MIC_START_ALL", VIRT_MIC_START_SYSTEM = "VCD_VIRT_MIC_START_ALL",
VIRT_MIC_STOP = "VCD_VIRT_MIC_STOP", VIRT_MIC_STOP = "VCD_VIRT_MIC_STOP",
ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY" ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY",
CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE"
} }

View file

@ -19,20 +19,26 @@ export interface Settings {
hardwareAcceleration?: boolean; hardwareAcceleration?: boolean;
arRPC?: boolean; arRPC?: boolean;
appBadge?: boolean; appBadge?: boolean;
discordWindowsTitleBar?: boolean;
maximized?: boolean;
minimized?: boolean;
windowBounds?: Rectangle;
disableMinSize?: boolean; disableMinSize?: boolean;
/** @deprecated use customTitleBar */
discordWindowsTitleBar?: boolean;
customTitleBar?: boolean;
checkUpdates?: boolean; checkUpdates?: boolean;
skippedUpdate?: string;
firstLaunch?: boolean;
splashTheming?: boolean; splashTheming?: boolean;
splashColor?: string; splashColor?: string;
splashBackground?: string; splashBackground?: string;
}
export interface State {
maximized?: boolean;
minimized?: boolean;
windowBounds?: Rectangle;
skippedUpdate?: string;
firstLaunch?: boolean;
steamOSLayoutVersion?: number; steamOSLayoutVersion?: number;
} }

View file

@ -144,4 +144,11 @@ export class SettingsStore<T extends object> {
listeners.delete(cb); listeners.delete(cb);
if (!listeners.size) this.pathListeners.delete(path as string); if (!listeners.size) this.pathListeners.delete(path as string);
} }
/**
* Call all global change listeners
*/
public markAsChanged() {
this.globalListeners.forEach(cb => cb(this.plain, ""));
}
} }

View file

@ -5,7 +5,7 @@
*/ */
import { app, BrowserWindow, shell } from "electron"; import { app, BrowserWindow, shell } from "electron";
import { Settings } from "main/settings"; import { Settings, State } from "main/settings";
import { handle } from "main/utils/ipcWrappers"; import { handle } from "main/utils/ipcWrappers";
import { makeLinksOpenExternally } from "main/utils/makeLinksOpenExternally"; import { makeLinksOpenExternally } from "main/utils/makeLinksOpenExternally";
import { githubGet, ReleaseData } from "main/utils/vencordLoader"; import { githubGet, ReleaseData } from "main/utils/vencordLoader";
@ -52,7 +52,7 @@ handle(IpcEvents.UPDATER_DOWNLOAD, () => {
}); });
handle(IpcEvents.UPDATE_IGNORE, () => { handle(IpcEvents.UPDATE_IGNORE, () => {
Settings.store.skippedUpdate = updateData.latestVersion; State.store.skippedUpdate = updateData.latestVersion;
}); });
function isOutdated(oldVersion: string, newVersion: string) { function isOutdated(oldVersion: string, newVersion: string) {
@ -91,7 +91,7 @@ export async function checkUpdates() {
release: data release: data
}; };
if (Settings.store.skippedUpdate !== newVersion && isOutdated(oldVersion, newVersion)) { if (State.store.skippedUpdate !== newVersion && isOutdated(oldVersion, newVersion)) {
openNewUpdateWindow(); openNewUpdateWindow();
} }
} catch (e) { } catch (e) {

View file

@ -2,8 +2,9 @@
<link rel="stylesheet" href="./style.css" type="text/css" /> <link rel="stylesheet" href="./style.css" type="text/css" />
<style> <style>
* { body {
user-select: none; user-select: none;
-webkit-app-region: drag;
} }
.wrapper { .wrapper {