libvesktop: native dbus module for autostart & app badge (#1180)
Both setAppBadge and autoStart at system boot now use dbus calls. This means that autoStart will work in Flatpak
This commit is contained in:
13
README.md
13
README.md
@@ -17,7 +17,7 @@ Vesktop is a custom Discord desktop app
|
||||
|
||||
## Installing
|
||||
|
||||
Visit https://vesktop.vencord.dev/install
|
||||
Visit https://vesktop.dev/install
|
||||
|
||||
## Building from Source
|
||||
|
||||
@@ -47,3 +47,14 @@ pnpm package --linux pacman
|
||||
# Or package to a directory only
|
||||
pnpm package:dir
|
||||
```
|
||||
|
||||
## Building LibVesktop from Source
|
||||
|
||||
This is a small C++ helper library Vesktop uses on Linux to emit D-Bus events. By default, prebuilt binaries for x64 and arm64 are used.
|
||||
|
||||
If you want to build it from source:
|
||||
1. Install build dependencies:
|
||||
- Debian/Ubuntu: `apt install build-essential python3 curl pkg-config libglib2.0-dev`
|
||||
- Fedora: `dnf install @c-development @development-tools python3 curl pkgconf-pkg-config glib2-devel`
|
||||
2. Run `pnpm buildLibVesktop`
|
||||
3. From now on, building Vesktop will use your own build
|
||||
@@ -11,6 +11,7 @@
|
||||
"scripts": {
|
||||
"build": "tsx scripts/build/build.mts",
|
||||
"build:dev": "pnpm build --dev",
|
||||
"buildLibVesktop": "pnpm -C packages/libvesktop install && pnpm -C packages/libvesktop run build",
|
||||
"package": "pnpm build && electron-builder",
|
||||
"package:dir": "pnpm build && electron-builder --dir",
|
||||
"lint": "eslint",
|
||||
@@ -49,6 +50,7 @@
|
||||
"eslint-plugin-simple-header": "^1.2.2",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"eslint-plugin-unused-imports": "^4.2.0",
|
||||
"libvesktop": "link:packages/libvesktop",
|
||||
"prettier": "^3.6.2",
|
||||
"source-map-support": "^0.5.21",
|
||||
"tsx": "^4.20.6",
|
||||
|
||||
1
packages/libvesktop/.gitignore
vendored
Normal file
1
packages/libvesktop/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
build
|
||||
19
packages/libvesktop/Dockerfile
Normal file
19
packages/libvesktop/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Dockerfile for building both x64 and arm64 on an old distro for maximum compatibility.
|
||||
|
||||
# ubuntu20 is dead but debian11 is still supported for now
|
||||
FROM debian:11
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN dpkg --add-architecture arm64
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential python3 curl pkg-config \
|
||||
g++-aarch64-linux-gnu libglib2.0-dev:amd64 libglib2.0-dev:arm64 \
|
||||
ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||
&& apt-get update && apt-get install -y nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /src
|
||||
19
packages/libvesktop/binding.gyp
Normal file
19
packages/libvesktop/binding.gyp
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "libvesktop",
|
||||
"sources": [ "src/libvesktop.cc" ],
|
||||
"include_dirs": [
|
||||
"<!@(node -p \"require('node-addon-api').include\")"
|
||||
],
|
||||
"cflags_cc": [
|
||||
"<!(pkg-config --cflags glib-2.0 gio-2.0)",
|
||||
"-O3"
|
||||
],
|
||||
"libraries": [
|
||||
"<!@(pkg-config --libs-only-l --libs-only-other glib-2.0 gio-2.0)"
|
||||
],
|
||||
"cflags_cc!": ["-fno-exceptions"],
|
||||
}
|
||||
]
|
||||
}
|
||||
17
packages/libvesktop/build.sh
Executable file
17
packages/libvesktop/build.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
docker build -t libvesktop-builder -f Dockerfile .
|
||||
|
||||
docker run --rm -v "$PWD":/src -w /src libvesktop-builder bash -c "
|
||||
set -e
|
||||
|
||||
echo '=== Building x64 ==='
|
||||
npx node-gyp rebuild --arch=x64
|
||||
mv build/Release/vesktop.node prebuilds/vesktop-x64.node
|
||||
|
||||
echo '=== Building arm64 ==='
|
||||
export CXX=aarch64-linux-gnu-g++
|
||||
npx node-gyp rebuild --arch=arm64
|
||||
mv build/Release/vesktop.node prebuilds/vesktop-arm64.node
|
||||
"
|
||||
3
packages/libvesktop/index.d.ts
vendored
Normal file
3
packages/libvesktop/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export function getAccentColor(): number | null;
|
||||
export function requestBackground(autoStart: boolean, commandLine: string[]): boolean;
|
||||
export function updateUnityLauncherCount(count: number): boolean;
|
||||
14
packages/libvesktop/package.json
Normal file
14
packages/libvesktop/package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "libvesktop",
|
||||
"main": "build/Release/vesktop.node",
|
||||
"types": "index.d.ts",
|
||||
"devDependencies": {
|
||||
"node-addon-api": "^8.5.0",
|
||||
"node-gyp": "^11.4.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node-gyp configure build",
|
||||
"clean": "node-gyp clean",
|
||||
"test": "npm run build && node test.js"
|
||||
}
|
||||
}
|
||||
730
packages/libvesktop/pnpm-lock.yaml
generated
Normal file
730
packages/libvesktop/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,730 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
node-addon-api:
|
||||
specifier: ^8.5.0
|
||||
version: 8.5.0
|
||||
node-gyp:
|
||||
specifier: ^11.4.2
|
||||
version: 11.4.2
|
||||
|
||||
packages:
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@isaacs/fs-minipass@4.0.1':
|
||||
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@npmcli/agent@3.0.0':
|
||||
resolution: {integrity: sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
'@npmcli/fs@4.0.0':
|
||||
resolution: {integrity: sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
abbrev@3.0.1:
|
||||
resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
agent-base@7.1.4:
|
||||
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-regex@6.2.2:
|
||||
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@6.2.3:
|
||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
brace-expansion@2.0.2:
|
||||
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
|
||||
|
||||
cacache@19.0.1:
|
||||
resolution: {integrity: sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
chownr@3.0.0:
|
||||
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
|
||||
color-name@1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
debug@4.4.3:
|
||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
emoji-regex@9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
||||
encoding@0.1.13:
|
||||
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
|
||||
|
||||
env-paths@2.2.1:
|
||||
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
err-code@2.0.3:
|
||||
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
|
||||
|
||||
exponential-backoff@3.1.2:
|
||||
resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==}
|
||||
|
||||
fdir@6.5.0:
|
||||
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
picomatch: ^3 || ^4
|
||||
peerDependenciesMeta:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
foreground-child@3.3.1:
|
||||
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
fs-minipass@3.0.3:
|
||||
resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
|
||||
glob@10.4.5:
|
||||
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
|
||||
hasBin: true
|
||||
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
http-cache-semantics@4.2.0:
|
||||
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
||||
|
||||
http-proxy-agent@7.0.2:
|
||||
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
https-proxy-agent@7.0.6:
|
||||
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
imurmurhash@0.1.4:
|
||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||
engines: {node: '>=0.8.19'}
|
||||
|
||||
ip-address@10.0.1:
|
||||
resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
is-fullwidth-code-point@3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
isexe@3.1.1:
|
||||
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
jackspeak@3.4.3:
|
||||
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
||||
|
||||
lru-cache@10.4.3:
|
||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||
|
||||
make-fetch-happen@14.0.3:
|
||||
resolution: {integrity: sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
minimatch@9.0.5:
|
||||
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minipass-collect@2.0.1:
|
||||
resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minipass-fetch@4.0.1:
|
||||
resolution: {integrity: sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
minipass-flush@1.0.5:
|
||||
resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
minipass-pipeline@1.2.4:
|
||||
resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass-sized@1.0.3:
|
||||
resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass@3.3.6:
|
||||
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass@7.1.2:
|
||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minizlib@3.1.0:
|
||||
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
negotiator@1.0.0:
|
||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
node-addon-api@8.5.0:
|
||||
resolution: {integrity: sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==}
|
||||
engines: {node: ^18 || ^20 || >= 21}
|
||||
|
||||
node-gyp@11.4.2:
|
||||
resolution: {integrity: sha512-3gD+6zsrLQH7DyYOUIutaauuXrcyxeTPyQuZQCQoNPZMHMMS5m4y0xclNpvYzoK3VNzuyxT6eF4mkIL4WSZ1eQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
hasBin: true
|
||||
|
||||
nopt@8.1.0:
|
||||
resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
hasBin: true
|
||||
|
||||
p-map@7.0.3:
|
||||
resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
package-json-from-dist@1.0.1:
|
||||
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
|
||||
|
||||
path-key@3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-scurry@1.11.1:
|
||||
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
|
||||
engines: {node: '>=16 || 14 >=14.18'}
|
||||
|
||||
picomatch@4.0.3:
|
||||
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
proc-log@5.0.0:
|
||||
resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
promise-retry@2.0.1:
|
||||
resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
retry@0.12.0:
|
||||
resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
|
||||
semver@7.7.2:
|
||||
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
shebang-regex@3.0.0:
|
||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
smart-buffer@4.2.0:
|
||||
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
|
||||
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
|
||||
|
||||
socks-proxy-agent@8.0.5:
|
||||
resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
socks@2.8.7:
|
||||
resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==}
|
||||
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
|
||||
|
||||
ssri@12.0.0:
|
||||
resolution: {integrity: sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
string-width@5.1.2:
|
||||
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
tar@7.5.1:
|
||||
resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
unique-filename@4.0.0:
|
||||
resolution: {integrity: sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
unique-slug@5.0.0:
|
||||
resolution: {integrity: sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
which@5.0.0:
|
||||
resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
hasBin: true
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
wrap-ansi@8.1.0:
|
||||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
|
||||
yallist@5.0.0:
|
||||
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
snapshots:
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
dependencies:
|
||||
string-width: 5.1.2
|
||||
string-width-cjs: string-width@4.2.3
|
||||
strip-ansi: 7.1.2
|
||||
strip-ansi-cjs: strip-ansi@6.0.1
|
||||
wrap-ansi: 8.1.0
|
||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||
|
||||
'@isaacs/fs-minipass@4.0.1':
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
'@npmcli/agent@3.0.0':
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6
|
||||
lru-cache: 10.4.3
|
||||
socks-proxy-agent: 8.0.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@npmcli/fs@4.0.0':
|
||||
dependencies:
|
||||
semver: 7.7.2
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
abbrev@3.0.1: {}
|
||||
|
||||
agent-base@7.1.4: {}
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.2.2: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@6.2.3: {}
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
||||
brace-expansion@2.0.2:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
|
||||
cacache@19.0.1:
|
||||
dependencies:
|
||||
'@npmcli/fs': 4.0.0
|
||||
fs-minipass: 3.0.3
|
||||
glob: 10.4.5
|
||||
lru-cache: 10.4.3
|
||||
minipass: 7.1.2
|
||||
minipass-collect: 2.0.1
|
||||
minipass-flush: 1.0.5
|
||||
minipass-pipeline: 1.2.4
|
||||
p-map: 7.0.3
|
||||
ssri: 12.0.0
|
||||
tar: 7.5.1
|
||||
unique-filename: 4.0.0
|
||||
|
||||
chownr@3.0.0: {}
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
||||
color-name@1.1.4: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
debug@4.4.3:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
emoji-regex@9.2.2: {}
|
||||
|
||||
encoding@0.1.13:
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
optional: true
|
||||
|
||||
env-paths@2.2.1: {}
|
||||
|
||||
err-code@2.0.3: {}
|
||||
|
||||
exponential-backoff@3.1.2: {}
|
||||
|
||||
fdir@6.5.0(picomatch@4.0.3):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.3
|
||||
|
||||
foreground-child@3.3.1:
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
signal-exit: 4.1.0
|
||||
|
||||
fs-minipass@3.0.3:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
glob@10.4.5:
|
||||
dependencies:
|
||||
foreground-child: 3.3.1
|
||||
jackspeak: 3.4.3
|
||||
minimatch: 9.0.5
|
||||
minipass: 7.1.2
|
||||
package-json-from-dist: 1.0.1
|
||||
path-scurry: 1.11.1
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
http-cache-semantics@4.2.0: {}
|
||||
|
||||
http-proxy-agent@7.0.2:
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
https-proxy-agent@7.0.6:
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
optional: true
|
||||
|
||||
imurmurhash@0.1.4: {}
|
||||
|
||||
ip-address@10.0.1: {}
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
isexe@3.1.1: {}
|
||||
|
||||
jackspeak@3.4.3:
|
||||
dependencies:
|
||||
'@isaacs/cliui': 8.0.2
|
||||
optionalDependencies:
|
||||
'@pkgjs/parseargs': 0.11.0
|
||||
|
||||
lru-cache@10.4.3: {}
|
||||
|
||||
make-fetch-happen@14.0.3:
|
||||
dependencies:
|
||||
'@npmcli/agent': 3.0.0
|
||||
cacache: 19.0.1
|
||||
http-cache-semantics: 4.2.0
|
||||
minipass: 7.1.2
|
||||
minipass-fetch: 4.0.1
|
||||
minipass-flush: 1.0.5
|
||||
minipass-pipeline: 1.2.4
|
||||
negotiator: 1.0.0
|
||||
proc-log: 5.0.0
|
||||
promise-retry: 2.0.1
|
||||
ssri: 12.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
minimatch@9.0.5:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minipass-collect@2.0.1:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
minipass-fetch@4.0.1:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
minipass-sized: 1.0.3
|
||||
minizlib: 3.1.0
|
||||
optionalDependencies:
|
||||
encoding: 0.1.13
|
||||
|
||||
minipass-flush@1.0.5:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
|
||||
minipass-pipeline@1.2.4:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
|
||||
minipass-sized@1.0.3:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
|
||||
minipass@3.3.6:
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
minipass@7.1.2: {}
|
||||
|
||||
minizlib@3.1.0:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
negotiator@1.0.0: {}
|
||||
|
||||
node-addon-api@8.5.0: {}
|
||||
|
||||
node-gyp@11.4.2:
|
||||
dependencies:
|
||||
env-paths: 2.2.1
|
||||
exponential-backoff: 3.1.2
|
||||
graceful-fs: 4.2.11
|
||||
make-fetch-happen: 14.0.3
|
||||
nopt: 8.1.0
|
||||
proc-log: 5.0.0
|
||||
semver: 7.7.2
|
||||
tar: 7.5.1
|
||||
tinyglobby: 0.2.15
|
||||
which: 5.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
nopt@8.1.0:
|
||||
dependencies:
|
||||
abbrev: 3.0.1
|
||||
|
||||
p-map@7.0.3: {}
|
||||
|
||||
package-json-from-dist@1.0.1: {}
|
||||
|
||||
path-key@3.1.1: {}
|
||||
|
||||
path-scurry@1.11.1:
|
||||
dependencies:
|
||||
lru-cache: 10.4.3
|
||||
minipass: 7.1.2
|
||||
|
||||
picomatch@4.0.3: {}
|
||||
|
||||
proc-log@5.0.0: {}
|
||||
|
||||
promise-retry@2.0.1:
|
||||
dependencies:
|
||||
err-code: 2.0.3
|
||||
retry: 0.12.0
|
||||
|
||||
retry@0.12.0: {}
|
||||
|
||||
safer-buffer@2.1.2:
|
||||
optional: true
|
||||
|
||||
semver@7.7.2: {}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
shebang-regex: 3.0.0
|
||||
|
||||
shebang-regex@3.0.0: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
smart-buffer@4.2.0: {}
|
||||
|
||||
socks-proxy-agent@8.0.5:
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.3
|
||||
socks: 2.8.7
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
socks@2.8.7:
|
||||
dependencies:
|
||||
ip-address: 10.0.1
|
||||
smart-buffer: 4.2.0
|
||||
|
||||
ssri@12.0.0:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
string-width@5.1.2:
|
||||
dependencies:
|
||||
eastasianwidth: 0.2.0
|
||||
emoji-regex: 9.2.2
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
dependencies:
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
tar@7.5.1:
|
||||
dependencies:
|
||||
'@isaacs/fs-minipass': 4.0.1
|
||||
chownr: 3.0.0
|
||||
minipass: 7.1.2
|
||||
minizlib: 3.1.0
|
||||
yallist: 5.0.0
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
|
||||
unique-filename@4.0.0:
|
||||
dependencies:
|
||||
unique-slug: 5.0.0
|
||||
|
||||
unique-slug@5.0.0:
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
|
||||
which@2.0.2:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
which@5.0.0:
|
||||
dependencies:
|
||||
isexe: 3.1.1
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrap-ansi@8.1.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
yallist@4.0.0: {}
|
||||
|
||||
yallist@5.0.0: {}
|
||||
BIN
packages/libvesktop/prebuilds/vesktop-arm64.node
Executable file
BIN
packages/libvesktop/prebuilds/vesktop-arm64.node
Executable file
Binary file not shown.
BIN
packages/libvesktop/prebuilds/vesktop-x64.node
Executable file
BIN
packages/libvesktop/prebuilds/vesktop-x64.node
Executable file
Binary file not shown.
269
packages/libvesktop/src/libvesktop.cc
Normal file
269
packages/libvesktop/src/libvesktop.cc
Normal file
@@ -0,0 +1,269 @@
|
||||
#include <gio/gio.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <napi.h>
|
||||
#include <optional>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
template <typename T>
|
||||
struct GObjectDeleter
|
||||
{
|
||||
void operator()(T *obj) const
|
||||
{
|
||||
if (obj)
|
||||
g_object_unref(obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using GObjectPtr = std::unique_ptr<T, GObjectDeleter<T>>;
|
||||
|
||||
struct GVariantDeleter
|
||||
{
|
||||
void operator()(GVariant *variant) const
|
||||
{
|
||||
if (variant)
|
||||
g_variant_unref(variant);
|
||||
}
|
||||
};
|
||||
|
||||
using GVariantPtr = std::unique_ptr<GVariant, GVariantDeleter>;
|
||||
|
||||
struct GErrorDeleter
|
||||
{
|
||||
void operator()(GError *error) const
|
||||
{
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
}
|
||||
};
|
||||
|
||||
using GErrorPtr = std::unique_ptr<GError, GErrorDeleter>;
|
||||
|
||||
bool update_launcher_count(int count)
|
||||
{
|
||||
GError *error = nullptr;
|
||||
|
||||
const char *chromeDesktop = std::getenv("CHROME_DESKTOP");
|
||||
std::string desktop_id = std::string("application://") + (chromeDesktop ? chromeDesktop : "vesktop.desktop");
|
||||
|
||||
GObjectPtr<GDBusConnection> bus(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error));
|
||||
if (!bus)
|
||||
{
|
||||
GErrorPtr error_ptr(error);
|
||||
std::cerr << "[libvesktop::update_launcher_count] Failed to connect to session bus: "
|
||||
<< (error_ptr ? error_ptr->message : "unknown error") << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
|
||||
g_variant_builder_add(&builder, "{sv}", "count", g_variant_new_int64(count));
|
||||
g_variant_builder_add(&builder, "{sv}", "count-visible", g_variant_new_boolean(count != 0));
|
||||
|
||||
gboolean result = g_dbus_connection_emit_signal(
|
||||
bus.get(),
|
||||
nullptr,
|
||||
"/",
|
||||
"com.canonical.Unity.LauncherEntry",
|
||||
"Update",
|
||||
g_variant_new("(sa{sv})", desktop_id.c_str(), &builder),
|
||||
&error);
|
||||
|
||||
if (!result || error)
|
||||
{
|
||||
GErrorPtr error_ptr(error);
|
||||
std::cerr << "[libvesktop::update_launcher_count] Failed to emit Update signal: "
|
||||
<< (error_ptr ? error_ptr->message : "unknown error") << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<int32_t> get_accent_color()
|
||||
{
|
||||
GError *error = nullptr;
|
||||
|
||||
GObjectPtr<GDBusConnection> bus(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error));
|
||||
if (!bus)
|
||||
{
|
||||
GErrorPtr error_ptr(error);
|
||||
std::cerr << "[libvesktop::get_accent_color] Failed to connect to session bus: "
|
||||
<< (error_ptr ? error_ptr->message : "unknown error") << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
GVariantPtr reply(g_dbus_connection_call_sync(
|
||||
bus.get(),
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.portal.Settings",
|
||||
"Read",
|
||||
g_variant_new("(ss)", "org.freedesktop.appearance", "accent-color"),
|
||||
nullptr,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
5000,
|
||||
nullptr,
|
||||
&error));
|
||||
|
||||
if (!reply)
|
||||
{
|
||||
GErrorPtr error_ptr(error);
|
||||
std::cerr << "[libvesktop::get_accent_color] Failed to call Read: "
|
||||
<< (error_ptr ? error_ptr->message : "unknown error") << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
GVariant *inner_raw = nullptr;
|
||||
g_variant_get(reply.get(), "(v)", &inner_raw);
|
||||
if (!inner_raw)
|
||||
{
|
||||
std::cerr << "[libvesktop::get_accent_color] Inner variant is null" << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
GVariantPtr inner(inner_raw);
|
||||
|
||||
// Unwrap nested variants
|
||||
while (g_variant_is_of_type(inner.get(), G_VARIANT_TYPE_VARIANT))
|
||||
{
|
||||
GVariant *next = g_variant_get_variant(inner.get());
|
||||
inner.reset(next);
|
||||
}
|
||||
|
||||
if (!g_variant_is_of_type(inner.get(), G_VARIANT_TYPE_TUPLE) ||
|
||||
g_variant_n_children(inner.get()) < 3)
|
||||
{
|
||||
std::cerr << "[libvesktop::get_accent_color] Inner variant is not a tuple of 3 doubles" << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
double r = 0.0, g = 0.0, b = 0.0;
|
||||
g_variant_get(inner.get(), "(ddd)", &r, &g, &b);
|
||||
|
||||
bool discard = false;
|
||||
auto toInt = [&discard](double v) -> int
|
||||
{
|
||||
if (!std::isfinite(v) || v < 0.0 || v > 1.0)
|
||||
{
|
||||
discard = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return static_cast<int>(std::round(v * 255.0));
|
||||
};
|
||||
|
||||
int32_t rgb = (toInt(r) << 16) | (toInt(g) << 8) | toInt(b);
|
||||
if (discard)
|
||||
return std::nullopt;
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
bool request_background(bool autostart, const std::vector<std::string> &commandline)
|
||||
{
|
||||
GError *error = nullptr;
|
||||
|
||||
GObjectPtr<GDBusConnection> bus(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error));
|
||||
if (!bus)
|
||||
{
|
||||
GErrorPtr error_ptr(error);
|
||||
std::cerr << "[libvesktop::request_background] Failed to connect to session bus: "
|
||||
<< (error_ptr ? error_ptr->message : "unknown error") << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
|
||||
g_variant_builder_add(&builder, "{sv}", "autostart", g_variant_new_boolean(autostart));
|
||||
|
||||
if (!commandline.empty())
|
||||
{
|
||||
GVariantBuilder cmd_builder;
|
||||
g_variant_builder_init(&cmd_builder, G_VARIANT_TYPE("as"));
|
||||
for (const auto &s : commandline)
|
||||
g_variant_builder_add(&cmd_builder, "s", s.c_str());
|
||||
g_variant_builder_add(&builder, "{sv}", "commandline", g_variant_builder_end(&cmd_builder));
|
||||
}
|
||||
|
||||
GVariantPtr reply(g_dbus_connection_call_sync(
|
||||
bus.get(),
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.portal.Background",
|
||||
"RequestBackground",
|
||||
g_variant_new("(sa{sv})", "", &builder),
|
||||
nullptr,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
5000,
|
||||
nullptr,
|
||||
&error));
|
||||
|
||||
if (!reply)
|
||||
{
|
||||
GErrorPtr error_ptr(error);
|
||||
std::cerr << "[libvesktop::request_background] Failed to call RequestBackground: "
|
||||
<< (error_ptr ? error_ptr->message : "unknown error") << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Napi::Value updateUnityLauncherCount(Napi::CallbackInfo const &info)
|
||||
{
|
||||
if (info.Length() < 1 || !info[0].IsNumber())
|
||||
{
|
||||
Napi::TypeError::New(info.Env(), "Expected (number)").ThrowAsJavaScriptException();
|
||||
return info.Env().Undefined();
|
||||
}
|
||||
|
||||
int count = info[0].As<Napi::Number>().Int32Value();
|
||||
bool success = update_launcher_count(count);
|
||||
return Napi::Boolean::New(info.Env(), success);
|
||||
}
|
||||
|
||||
Napi::Value getAccentColor(const Napi::CallbackInfo &info)
|
||||
{
|
||||
auto color = get_accent_color();
|
||||
if (color)
|
||||
return Napi::Number::New(info.Env(), *color);
|
||||
return info.Env().Null();
|
||||
}
|
||||
|
||||
Napi::Value RequestBackground(const Napi::CallbackInfo &info)
|
||||
{
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() < 2 || !info[0].IsBoolean() || !info[1].IsArray())
|
||||
{
|
||||
Napi::TypeError::New(env, "Expected (boolean, string[])").ThrowAsJavaScriptException();
|
||||
return env.Null();
|
||||
}
|
||||
|
||||
bool autostart = info[0].As<Napi::Boolean>();
|
||||
Napi::Array arr = info[1].As<Napi::Array>();
|
||||
std::vector<std::string> commandline;
|
||||
for (uint32_t i = 0; i < arr.Length(); i++)
|
||||
{
|
||||
Napi::Value v = arr.Get(i);
|
||||
if (v.IsString())
|
||||
commandline.push_back(v.As<Napi::String>().Utf8Value());
|
||||
}
|
||||
|
||||
bool ok = request_background(autostart, commandline);
|
||||
return Napi::Boolean::New(env, ok);
|
||||
}
|
||||
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports)
|
||||
{
|
||||
exports.Set("updateUnityLauncherCount", Napi::Function::New(env, updateUnityLauncherCount));
|
||||
exports.Set("getAccentColor", Napi::Function::New(env, getAccentColor));
|
||||
exports.Set("requestBackground", Napi::Function::New(env, RequestBackground));
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(libvesktop, Init)
|
||||
22
packages/libvesktop/test.js
Normal file
22
packages/libvesktop/test.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @type {typeof import(".")}
|
||||
*/
|
||||
const libVesktop = require(".");
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
|
||||
test("getAccentColor should return a number", () => {
|
||||
const color = libVesktop.getAccentColor();
|
||||
assert.strictEqual(typeof color, "number");
|
||||
});
|
||||
|
||||
test("updateUnityLauncherCount should return true (success)", () => {
|
||||
assert.strictEqual(libVesktop.updateUnityLauncherCount(5), true);
|
||||
assert.strictEqual(libVesktop.updateUnityLauncherCount(0), true);
|
||||
assert.strictEqual(libVesktop.updateUnityLauncherCount(10), true);
|
||||
});
|
||||
|
||||
test("requestBackground should return true (success)", () => {
|
||||
assert.strictEqual(libVesktop.requestBackground(true, ["bash"]), true);
|
||||
assert.strictEqual(libVesktop.requestBackground(false, []), true);
|
||||
});
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -71,6 +71,9 @@ importers:
|
||||
eslint-plugin-unused-imports:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)
|
||||
libvesktop:
|
||||
specifier: link:packages/libvesktop
|
||||
version: link:packages/libvesktop
|
||||
prettier:
|
||||
specifier: ^3.6.2
|
||||
version: 3.6.2
|
||||
|
||||
@@ -25,6 +25,9 @@ const NodeCommonOpts: BuildOptions = {
|
||||
platform: "node",
|
||||
external: ["electron"],
|
||||
target: ["esnext"],
|
||||
loader: {
|
||||
".node": "file"
|
||||
},
|
||||
define: {
|
||||
IS_DEV: JSON.stringify(isDev)
|
||||
}
|
||||
@@ -50,8 +53,29 @@ async function copyVenmic() {
|
||||
]).catch(() => console.warn("Failed to copy venmic. Building without venmic support"));
|
||||
}
|
||||
|
||||
async function copyLibVesktop() {
|
||||
if (process.platform !== "linux") return;
|
||||
|
||||
try {
|
||||
await copyFile(
|
||||
"./packages/libvesktop/build/Release/vesktop.node",
|
||||
`./static/dist/libvesktop-${process.arch}.node`
|
||||
);
|
||||
console.log("Using local libvesktop build");
|
||||
} catch {
|
||||
console.log(
|
||||
"Using prebuilt libvesktop binaries. Run `pnpm buildLibVesktop` and build again to build from source - see README.md for more details"
|
||||
);
|
||||
return Promise.all([
|
||||
copyFile("./packages/libvesktop/prebuilds/vesktop-x64.node", "./static/dist/libvesktop-x64.node"),
|
||||
copyFile("./packages/libvesktop/prebuilds/vesktop-arm64.node", "./static/dist/libvesktop-arm64.node")
|
||||
]).catch(() => console.warn("Failed to copy libvesktop. Building without libvesktop support"));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
copyVenmic(),
|
||||
copyLibVesktop(),
|
||||
createContext({
|
||||
...NodeCommonOpts,
|
||||
entryPoints: ["src/main/index.ts"],
|
||||
|
||||
@@ -8,7 +8,9 @@ import { app, NativeImage, nativeImage } from "electron";
|
||||
import { join } from "path";
|
||||
import { BADGE_DIR } from "shared/paths";
|
||||
|
||||
import { updateUnityLauncherCount } from "./dbus";
|
||||
import { AppEvents } from "./events";
|
||||
import { mainWin } from "./mainWindow";
|
||||
|
||||
const imgCache = new Map<number, NativeImage>();
|
||||
function loadBadge(index: number) {
|
||||
@@ -33,7 +35,7 @@ export function setBadgeCount(count: number) {
|
||||
switch (process.platform) {
|
||||
case "linux":
|
||||
if (count === -1) count = 0;
|
||||
app.setBadgeCount(count);
|
||||
updateUnityLauncherCount(count);
|
||||
break;
|
||||
case "darwin":
|
||||
if (count === 0) {
|
||||
@@ -48,8 +50,6 @@ export function setBadgeCount(count: number) {
|
||||
|
||||
lastIndex = index;
|
||||
|
||||
// circular import shenanigans
|
||||
const { mainWin } = require("./mainWindow") as typeof import("./mainWindow");
|
||||
mainWin.setOverlayIcon(index === null ? null : loadBadge(index), description);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5,30 +5,32 @@
|
||||
*/
|
||||
|
||||
import { app } from "electron";
|
||||
import { existsSync, mkdirSync, renameSync, rmSync, writeFileSync } from "fs";
|
||||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { stripIndent } from "shared/utils/text";
|
||||
|
||||
import { IS_FLATPAK } from "./constants";
|
||||
import { requestBackground } from "./dbus";
|
||||
import { Settings, State } from "./settings";
|
||||
import { escapeDesktopFileArgument } from "./utils/desktopFileEscape";
|
||||
|
||||
interface AutoStart {
|
||||
isEnabled(): boolean;
|
||||
enable(): void;
|
||||
disable(): void;
|
||||
}
|
||||
|
||||
function makeAutoStartLinux(): AutoStart {
|
||||
function getEscapedCommandLine() {
|
||||
const args = process.argv.map(escapeDesktopFileArgument);
|
||||
if (Settings.store.autoStartMinimized) args.push("--start-minimized");
|
||||
return args;
|
||||
}
|
||||
|
||||
function makeAutoStartLinuxDesktop(): AutoStart {
|
||||
const configDir = process.env.XDG_CONFIG_HOME || join(process.env.HOME!, ".config");
|
||||
const dir = join(configDir, "autostart");
|
||||
const file = join(dir, "vesktop.desktop");
|
||||
|
||||
// IM STUPID
|
||||
const legacyName = join(dir, "vencord.desktop");
|
||||
if (existsSync(legacyName)) renameSync(legacyName, file);
|
||||
|
||||
// "Quoting must be done by enclosing the argument between double quotes and escaping the double quote character,
|
||||
// backtick character ("`"), dollar sign ("$") and backslash character ("\") by preceding it with an additional backslash character"
|
||||
// https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables
|
||||
const commandLine = process.argv.map(arg => '"' + arg.replace(/["$`\\]/g, "\\$&") + '"').join(" ");
|
||||
|
||||
return {
|
||||
isEnabled: () => existsSync(file),
|
||||
enable() {
|
||||
@@ -37,7 +39,7 @@ function makeAutoStartLinux(): AutoStart {
|
||||
Type=Application
|
||||
Name=Vesktop
|
||||
Comment=Vesktop autostart script
|
||||
Exec=${commandLine}
|
||||
Exec=${getEscapedCommandLine().join(" ")}
|
||||
StartupNotify=false
|
||||
Terminal=false
|
||||
Icon=vesktop
|
||||
@@ -50,10 +52,49 @@ function makeAutoStartLinux(): AutoStart {
|
||||
};
|
||||
}
|
||||
|
||||
function makeAutoStartLinuxPortal() {
|
||||
return {
|
||||
isEnabled: () => State.store.linuxAutoStartEnabled === true,
|
||||
enable() {
|
||||
const success = requestBackground(true, getEscapedCommandLine());
|
||||
if (success) {
|
||||
State.store.linuxAutoStartEnabled = true;
|
||||
}
|
||||
return success;
|
||||
},
|
||||
disable() {
|
||||
const success = requestBackground(false, []);
|
||||
if (success) {
|
||||
State.store.linuxAutoStartEnabled = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const autoStartWindowsMac: AutoStart = {
|
||||
isEnabled: () => app.getLoginItemSettings().openAtLogin,
|
||||
enable: () => app.setLoginItemSettings({ openAtLogin: true }),
|
||||
enable: () =>
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin: true,
|
||||
args: Settings.store.autoStartMinimized ? ["--start-minimized"] : []
|
||||
}),
|
||||
disable: () => app.setLoginItemSettings({ openAtLogin: false })
|
||||
};
|
||||
|
||||
export const autoStart = process.platform === "linux" ? makeAutoStartLinux() : autoStartWindowsMac;
|
||||
// The portal call uses the app id by default, which is org.chromium.Chromium, even in packaged Vesktop.
|
||||
// This leads to an autostart entry named "Chromium" instead of "Vesktop".
|
||||
// Thus, only use the portal inside Flatpak, where the app is actually correct.
|
||||
// Maybe there is a way to fix it outside of flatpak, but I couldn't figure it out.
|
||||
export const autoStart =
|
||||
process.platform !== "linux"
|
||||
? autoStartWindowsMac
|
||||
: IS_FLATPAK
|
||||
? makeAutoStartLinuxPortal()
|
||||
: makeAutoStartLinuxDesktop();
|
||||
|
||||
Settings.addChangeListener("autoStartMinimized", () => {
|
||||
if (!autoStart.isEnabled()) return;
|
||||
|
||||
autoStart.enable();
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ export const DATA_DIR =
|
||||
|
||||
mkdirSync(DATA_DIR, { recursive: true });
|
||||
|
||||
const SESSION_DATA_DIR = join(DATA_DIR, "sessionData");
|
||||
export const SESSION_DATA_DIR = join(DATA_DIR, "sessionData");
|
||||
app.setPath("sessionData", SESSION_DATA_DIR);
|
||||
|
||||
export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings");
|
||||
@@ -28,12 +28,6 @@ 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_THEMES_DIR = join(DATA_DIR, "themes");
|
||||
|
||||
// needs to be inline require because of circular dependency
|
||||
// as otherwise "DATA_DIR" (which is used by ./settings) will be uninitialised
|
||||
export const VENCORD_FILES_DIR =
|
||||
(require("./settings") as typeof import("./settings")).State.store.vencordDir ||
|
||||
join(SESSION_DATA_DIR, "vencordFiles");
|
||||
|
||||
export const USER_AGENT = `Vesktop/${app.getVersion()} (https://github.com/Vencord/Vesktop)`;
|
||||
|
||||
// dimensions shamelessly stolen from Discord Desktop :3
|
||||
@@ -57,3 +51,5 @@ export const enum MessageBoxChoice {
|
||||
Default,
|
||||
Cancel
|
||||
}
|
||||
|
||||
export const IS_FLATPAK = process.env.FLATPAK_ID !== undefined;
|
||||
|
||||
40
src/main/dbus.ts
Normal file
40
src/main/dbus.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
|
||||
* Copyright (c) 2025 Vendicated and Vesktop contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { app } from "electron";
|
||||
import { join } from "path";
|
||||
import { STATIC_DIR } from "shared/paths";
|
||||
|
||||
let libVesktop: typeof import("libvesktop") | null = null;
|
||||
|
||||
function loadLibVesktop() {
|
||||
try {
|
||||
if (!libVesktop) {
|
||||
libVesktop = require(join(STATIC_DIR, `dist/libvesktop-${process.arch}.node`));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to load libvesktop:", e);
|
||||
}
|
||||
|
||||
return libVesktop;
|
||||
}
|
||||
|
||||
export function getAccentColor() {
|
||||
return loadLibVesktop()?.getAccentColor() ?? null;
|
||||
}
|
||||
|
||||
export function updateUnityLauncherCount(count: number) {
|
||||
const libVesktop = loadLibVesktop();
|
||||
if (!libVesktop) {
|
||||
return app.setBadgeCount(count);
|
||||
}
|
||||
|
||||
return libVesktop.updateUnityLauncherCount(count);
|
||||
}
|
||||
|
||||
export function requestBackground(autoStart: boolean, commandLine: string[]) {
|
||||
return loadLibVesktop()?.requestBackground(autoStart, commandLine) ?? false;
|
||||
}
|
||||
@@ -28,13 +28,14 @@ import { debounce } from "shared/utils/debounce";
|
||||
import { IpcEvents } from "../shared/IpcEvents";
|
||||
import { setBadgeCount } from "./appBadge";
|
||||
import { autoStart } from "./autoStart";
|
||||
import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants";
|
||||
import { VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants";
|
||||
import { mainWin } from "./mainWindow";
|
||||
import { Settings, State } from "./settings";
|
||||
import { handle, handleSync } from "./utils/ipcWrappers";
|
||||
import { PopoutWindows } from "./utils/popout";
|
||||
import { isDeckGameMode, showGamePage } from "./utils/steamOS";
|
||||
import { isValidVencordInstall } from "./utils/vencordLoader";
|
||||
import { VENCORD_FILES_DIR } from "./vencordFilesDir";
|
||||
|
||||
handleSync(IpcEvents.GET_VENCORD_PRELOAD_FILE, () => join(VENCORD_FILES_DIR, "vencordDesktopPreload.js"));
|
||||
handleSync(IpcEvents.GET_VENCORD_RENDERER_SCRIPT, () =>
|
||||
|
||||
@@ -22,7 +22,7 @@ import type { SettingsStore } from "shared/utils/SettingsStore";
|
||||
|
||||
import { createAboutWindow } from "./about";
|
||||
import { initArRPC } from "./arrpc";
|
||||
import { BrowserUserAgent, DEFAULT_HEIGHT, DEFAULT_WIDTH, MIN_HEIGHT, MIN_WIDTH, VENCORD_FILES_DIR } from "./constants";
|
||||
import { BrowserUserAgent, DEFAULT_HEIGHT, DEFAULT_WIDTH, MIN_HEIGHT, MIN_WIDTH } from "./constants";
|
||||
import { AppEvents } from "./events";
|
||||
import { darwinURL } from "./index";
|
||||
import { sendRendererCommand } from "./ipcCommands";
|
||||
@@ -33,6 +33,7 @@ import { clearData } from "./utils/clearData";
|
||||
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
|
||||
import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS";
|
||||
import { downloadVencordFiles, ensureVencordFiles } from "./utils/vencordLoader";
|
||||
import { VENCORD_FILES_DIR } from "./vencordFilesDir";
|
||||
|
||||
let isQuitting = false;
|
||||
|
||||
|
||||
56
src/main/utils/desktopFileEscape.ts
Normal file
56
src/main/utils/desktopFileEscape.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
|
||||
* Copyright (c) 2025 Vendicated and Vesktop contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
// https://specifications.freedesktop.org/desktop-entry-spec/latest/exec-variables.html
|
||||
|
||||
// "If an argument contains a reserved character the argument must be quoted."
|
||||
const desktopFileReservedChars = new Set([
|
||||
" ",
|
||||
"\t",
|
||||
"\n",
|
||||
'"',
|
||||
"'",
|
||||
"\\",
|
||||
">",
|
||||
"<",
|
||||
"~",
|
||||
"|",
|
||||
"&",
|
||||
";",
|
||||
"$",
|
||||
"*",
|
||||
"?",
|
||||
"#",
|
||||
"(",
|
||||
")",
|
||||
"`"
|
||||
]);
|
||||
|
||||
export function escapeDesktopFileArgument(arg: string) {
|
||||
let needsQuoting = false;
|
||||
let out = "";
|
||||
|
||||
for (const c of arg) {
|
||||
if (desktopFileReservedChars.has(c)) {
|
||||
// "Quoting must be done by enclosing the argument between double quotes"
|
||||
needsQuoting = true;
|
||||
// "and escaping the double quote character, backtick character ("`"), dollar sign ("$")
|
||||
// and backslash character ("\") by preceding it with an additional backslash character"
|
||||
if (c === '"' || c === "`" || c === "$" || c === "\\") {
|
||||
out += "\\";
|
||||
}
|
||||
}
|
||||
|
||||
// "Literal percentage characters must be escaped as %%"
|
||||
if (c === "%") {
|
||||
out += "%%";
|
||||
} else {
|
||||
out += c;
|
||||
}
|
||||
}
|
||||
|
||||
return needsQuoting ? `"${out}"` : out;
|
||||
}
|
||||
@@ -6,9 +6,10 @@
|
||||
|
||||
import { mkdirSync } from "fs";
|
||||
import { access, constants as FsConstants, writeFile } from "fs/promises";
|
||||
import { VENCORD_FILES_DIR } from "main/vencordFilesDir";
|
||||
import { join } from "path";
|
||||
|
||||
import { USER_AGENT, VENCORD_FILES_DIR } from "../constants";
|
||||
import { USER_AGENT } from "../constants";
|
||||
import { downloadFile, fetchie } from "./http";
|
||||
|
||||
const API_BASE = "https://api.github.com";
|
||||
|
||||
13
src/main/vencordFilesDir.ts
Normal file
13
src/main/vencordFilesDir.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
|
||||
* Copyright (c) 2025 Vendicated and Vesktop contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { join } from "path";
|
||||
|
||||
import { SESSION_DATA_DIR } from "./constants";
|
||||
import { State } from "./settings";
|
||||
|
||||
// this is in a separate file to avoid circular dependencies
|
||||
export const VENCORD_FILES_DIR = State.store.vencordDir || join(SESSION_DATA_DIR, "vencordFiles");
|
||||
@@ -9,18 +9,28 @@ import { useState } from "@vencord/types/webpack/common";
|
||||
import { SettingsComponent } from "./Settings";
|
||||
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
|
||||
|
||||
export const AutoStartToggle: SettingsComponent = () => {
|
||||
export const AutoStartToggle: SettingsComponent = ({ settings }) => {
|
||||
const [autoStartEnabled, setAutoStartEnabled] = useState(VesktopNative.autostart.isEnabled());
|
||||
|
||||
return (
|
||||
<VesktopSettingsSwitch
|
||||
title="Start With System"
|
||||
description="Automatically start Vesktop on computer start-up"
|
||||
value={autoStartEnabled}
|
||||
onChange={async v => {
|
||||
await VesktopNative.autostart[v ? "enable" : "disable"]();
|
||||
setAutoStartEnabled(v);
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
<VesktopSettingsSwitch
|
||||
title="Start With System"
|
||||
description="Automatically start Vesktop on computer start-up"
|
||||
value={autoStartEnabled}
|
||||
onChange={async v => {
|
||||
await VesktopNative.autostart[v ? "enable" : "disable"]();
|
||||
setAutoStartEnabled(v);
|
||||
}}
|
||||
/>
|
||||
|
||||
<VesktopSettingsSwitch
|
||||
title="Auto Start Minimized"
|
||||
description={"Start Vesktop minimized when starting with system"}
|
||||
value={settings.autoStartMinimized ?? false}
|
||||
onChange={v => (settings.autoStartMinimized = v)}
|
||||
disabled={!autoStartEnabled}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
2
src/shared/settings.d.ts
vendored
2
src/shared/settings.d.ts
vendored
@@ -11,6 +11,7 @@ export interface Settings {
|
||||
transparencyOption?: "none" | "mica" | "tabbed" | "acrylic";
|
||||
tray?: boolean;
|
||||
minimizeToTray?: boolean;
|
||||
autoStartMinimized?: boolean;
|
||||
openLinksWithElectron?: boolean;
|
||||
staticTitle?: boolean;
|
||||
enableMenu?: boolean;
|
||||
@@ -54,6 +55,7 @@ export interface State {
|
||||
firstLaunch?: boolean;
|
||||
|
||||
steamOSLayoutVersion?: number;
|
||||
linuxAutoStartEnabled?: boolean;
|
||||
|
||||
vencordDir?: string;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
<h2>Links</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vesktop.vencord.dev/wiki" target="_blank">Vesktop Wiki</a>
|
||||
<a href="https://vesktop.dev" target="_blank">Vesktop Website</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vencord.dev" target="_blank">Vencord Website</a>
|
||||
<a href="https://vesktop.dev/wiki" target="_blank">Vesktop Wiki</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/Vencord/Vesktop" target="_blank">Source Code</a>
|
||||
@@ -76,9 +76,8 @@
|
||||
</li>
|
||||
<li>
|
||||
And many
|
||||
<a href="https://github.com/Vencord/Vesktop/blob/main/pnpm-lock.yaml" target="_blank"
|
||||
>more open source libraries</a
|
||||
>
|
||||
<a href="https://github.com/Vencord/Vesktop/blob/main/pnpm-lock.yaml" target="_blank">more open source
|
||||
libraries</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -104,4 +103,4 @@
|
||||
}
|
||||
|
||||
walk(document.body);
|
||||
</script>
|
||||
</script>
|
||||
@@ -1,123 +0,0 @@
|
||||
<head>
|
||||
<link rel="stylesheet" href="./style.css" type="text/css" />
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
min-height: 100%;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.5em;
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
padding: 0.5em;
|
||||
color: var(--fg);
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
font-weight: bold;
|
||||
transition: filter 0.2 ease-in-out;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
button:active {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
.green {
|
||||
background-color: #248046;
|
||||
}
|
||||
|
||||
.red {
|
||||
background-color: #ed4245;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<section>
|
||||
<h1>Update Available</h1>
|
||||
<p>There's a new update for Vesktop! Update now to get new fixes and features!</p>
|
||||
<p>
|
||||
Current: <span id="current"></span>
|
||||
<br />
|
||||
Latest: <span id="latest"></span>
|
||||
</p>
|
||||
|
||||
<h2>Changelog</h2>
|
||||
<p id="changelog">Loading...</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<label id="disable-remind">
|
||||
<input type="checkbox" />
|
||||
<span>Do not remind again for </span>
|
||||
</label>
|
||||
|
||||
<div class="buttons">
|
||||
<button name="download" class="green">Download Update</button>
|
||||
<button name="close" class="red">Close</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="module">
|
||||
const data = await Updater.getData();
|
||||
document.getElementById("current").textContent = data.currentVersion;
|
||||
document.getElementById("latest").textContent = data.latestVersion;
|
||||
|
||||
document.querySelector("#disable-remind > span").textContent += data.latestVersion;
|
||||
|
||||
function checkDisableRemind() {
|
||||
const checkbox = document.querySelector("#disable-remind > input");
|
||||
if (checkbox.checked) {
|
||||
Updater.ignore();
|
||||
}
|
||||
}
|
||||
|
||||
const onClicks = {
|
||||
download() {
|
||||
checkDisableRemind();
|
||||
Updater.download();
|
||||
},
|
||||
close() {
|
||||
checkDisableRemind();
|
||||
Updater.close();
|
||||
}
|
||||
};
|
||||
|
||||
for (const name in onClicks) {
|
||||
document.querySelectorAll(`button[name="${name}"]`).forEach(button => {
|
||||
button.addEventListener("click", onClicks[name]);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="module">
|
||||
import { micromark } from "https://esm.sh/micromark@3?bundle";
|
||||
import { gfm, gfmHtml } from "https://esm.sh/micromark-extension-gfm@2?bundle";
|
||||
|
||||
const changelog = (await Updater.getData()).release.body;
|
||||
if (changelog)
|
||||
document.getElementById("changelog").innerHTML = micromark(changelog, {
|
||||
extensions: [gfm()],
|
||||
htmlExtensions: [gfmHtml()]
|
||||
})
|
||||
.replace(/h1>/g, "h3>")
|
||||
.replace(/<a /g, '<a target="_blank" ');
|
||||
</script>
|
||||
Reference in New Issue
Block a user