add everything
This commit is contained in:
9
.github/ISSUE_TEMPLATE/dev-issue.yml
vendored
9
.github/ISSUE_TEMPLATE/dev-issue.yml
vendored
@@ -5,8 +5,13 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||

|
# This form is reserved for Vesktop Developers. Do not open an issue.
|
||||||
GitHub Issues are for developers, not support. Please use our [support server](https://vencord.dev/discord) if you are not a developer.
|
|
||||||
|
Instead, use the [#vesktop-support channel](https://discord.com/channels/1015060230222131221/1345457031426871417) on our [Discord server](https://vencord.dev/discord) for help and reporting issues.
|
||||||
|
|
||||||
|
Your issue will be closed immediately with no comment and you will be blocked if you ignore this.
|
||||||
|
|
||||||
|
This is because 99% of issues are not actually bugs, but rather user or system issues and it adds a lot of noise to our development process.
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: content
|
id: content
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
BIN
.github/ISSUE_TEMPLATE/developer-banner.png
vendored
BIN
.github/ISSUE_TEMPLATE/developer-banner.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
2
.github/workflows/meta.yml
vendored
2
.github/workflows/meta.yml
vendored
@@ -37,6 +37,6 @@ jobs:
|
|||||||
|
|
||||||
git add meta/dev.vencord.Vesktop.metainfo.xml
|
git add meta/dev.vencord.Vesktop.metainfo.xml
|
||||||
git commit -m "metainfo: add entry for ${{ github.event.release.tag_name }}"
|
git commit -m "metainfo: add entry for ${{ github.event.release.tag_name }}"
|
||||||
git push
|
git push origin HEAD:main
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
|
||||||
|
|||||||
23
package.json
23
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "not-nextop",
|
"name": "not-nextop",
|
||||||
"version": "1.5.6",
|
"version": "1.5.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Not-Nextop is a custom Discord desktop app",
|
"description": "Not-Nextop is a custom Discord desktop app",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
@@ -34,27 +34,27 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
|
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
|
||||||
"@stylistic/eslint-plugin": "^4.2.0",
|
"@stylistic/eslint-plugin": "^5.1.0",
|
||||||
"@types/node": "^22.15.18",
|
"@types/node": "^24.0.10",
|
||||||
"@types/react": "18.3.1",
|
"@types/react": "18.3.1",
|
||||||
"@vencord/types": "^1.11.5",
|
"@vencord/types": "^1.11.5",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^16.5.0",
|
||||||
"electron": "^36.2.1",
|
"electron": "^37.2.0",
|
||||||
"electron-builder": "^26.0.12",
|
"electron-builder": "^26.0.12",
|
||||||
"esbuild": "^0.25.4",
|
"esbuild": "^0.25.5",
|
||||||
"eslint": "^9.27.0",
|
"eslint": "^9.30.1",
|
||||||
"eslint-import-resolver-alias": "^1.1.2",
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
"eslint-plugin-path-alias": "^2.1.0",
|
"eslint-plugin-path-alias": "^2.1.0",
|
||||||
"eslint-plugin-prettier": "^5.4.0",
|
"eslint-plugin-prettier": "^5.5.1",
|
||||||
"eslint-plugin-simple-header": "^1.2.2",
|
"eslint-plugin-simple-header": "^1.2.2",
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
"eslint-plugin-unused-imports": "^4.1.4",
|
"eslint-plugin-unused-imports": "^4.1.4",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.6.2",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"tsx": "^4.19.4",
|
"tsx": "^4.20.3",
|
||||||
"type-fest": "^4.41.0",
|
"type-fest": "^4.41.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"typescript-eslint": "^8.32.1",
|
"typescript-eslint": "^8.35.1",
|
||||||
"xml-formatter": "^3.6.6"
|
"xml-formatter": "^3.6.6"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.7.1",
|
"packageManager": "pnpm@10.7.1",
|
||||||
@@ -199,7 +199,8 @@
|
|||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"patchedDependencies": {
|
"patchedDependencies": {
|
||||||
"arrpc@3.5.0": "patches/arrpc@3.5.0.patch"
|
"arrpc@3.5.0": "patches/arrpc@3.5.0.patch",
|
||||||
|
"electron-updater": "patches/electron-updater.patch"
|
||||||
},
|
},
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@vencord/venmic",
|
"@vencord/venmic",
|
||||||
|
|||||||
16
patches/electron-updater.patch
Normal file
16
patches/electron-updater.patch
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
diff --git a/out/RpmUpdater.js b/out/RpmUpdater.js
|
||||||
|
index 563187bb18cb0bd154dff6620cb62b8c8f534cd6..d91594026c2bac9cc78ef3b1183df3241d7d9624 100644
|
||||||
|
--- a/out/RpmUpdater.js
|
||||||
|
+++ b/out/RpmUpdater.js
|
||||||
|
@@ -32,7 +32,10 @@ class RpmUpdater extends BaseUpdater_1.BaseUpdater {
|
||||||
|
const sudo = this.wrapSudo();
|
||||||
|
// pkexec doesn't want the command to be wrapped in " quotes
|
||||||
|
const wrapper = /pkexec/i.test(sudo) ? "" : `"`;
|
||||||
|
- const packageManager = this.spawnSyncLog("which zypper");
|
||||||
|
+ let packageManager;
|
||||||
|
+ try {
|
||||||
|
+ packageManager = this.spawnSyncLog("which zypper");
|
||||||
|
+ } catch {}
|
||||||
|
const installerPath = this.installerPath;
|
||||||
|
if (installerPath == null) {
|
||||||
|
this.dispatchError(new Error("No valid update available, can't quit and install"));
|
||||||
902
pnpm-lock.yaml
generated
902
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -58,6 +58,12 @@ await Promise.all([
|
|||||||
outfile: "dist/js/main.js",
|
outfile: "dist/js/main.js",
|
||||||
footer: { js: "//# sourceURL=VCDMain" }
|
footer: { js: "//# sourceURL=VCDMain" }
|
||||||
}),
|
}),
|
||||||
|
createContext({
|
||||||
|
...NodeCommonOpts,
|
||||||
|
entryPoints: ["src/main/arrpc/worker.ts"],
|
||||||
|
outfile: "dist/js/arRpcWorker.js",
|
||||||
|
footer: { js: "//# sourceURL=VCDArRpcWorker" }
|
||||||
|
}),
|
||||||
createContext({
|
createContext({
|
||||||
...NodeCommonOpts,
|
...NodeCommonOpts,
|
||||||
entryPoints: ["src/preload/index.ts"],
|
entryPoints: ["src/preload/index.ts"],
|
||||||
|
|||||||
@@ -4,25 +4,33 @@
|
|||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BrowserWindow } from "electron";
|
import { app, BrowserWindow } from "electron";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { ICON_PATH, VIEW_DIR } from "shared/paths";
|
import { ICON_PATH, VIEW_DIR } from "shared/paths";
|
||||||
|
|
||||||
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
|
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
|
||||||
|
|
||||||
export function createAboutWindow() {
|
export async function createAboutWindow() {
|
||||||
|
const height = 750;
|
||||||
|
const width = height * (4 / 3);
|
||||||
|
|
||||||
const about = new BrowserWindow({
|
const about = new BrowserWindow({
|
||||||
center: true,
|
center: true,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
icon: ICON_PATH,
|
icon: ICON_PATH,
|
||||||
webPreferences: {
|
height,
|
||||||
preload: join(__dirname, "updaterPreload.js")
|
width
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
makeLinksOpenExternally(about);
|
makeLinksOpenExternally(about);
|
||||||
|
|
||||||
about.loadFile(join(VIEW_DIR, "about.html"));
|
const data = new URLSearchParams({
|
||||||
|
APP_VERSION: app.getVersion()
|
||||||
|
});
|
||||||
|
|
||||||
|
about.loadFile(join(VIEW_DIR, "about.html"), {
|
||||||
|
search: data.toString()
|
||||||
|
});
|
||||||
|
|
||||||
return about;
|
return about;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
|
|
||||||
* Copyright (c) 2023 Vendicated and Vencord contributors
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Server from "arrpc";
|
|
||||||
import { IpcCommands } from "shared/IpcEvents";
|
|
||||||
|
|
||||||
import { sendRendererCommand } from "./ipcCommands";
|
|
||||||
import { Settings } from "./settings";
|
|
||||||
|
|
||||||
let server: any;
|
|
||||||
|
|
||||||
const inviteCodeRegex = /^(\w|-)+$/;
|
|
||||||
|
|
||||||
export async function initArRPC() {
|
|
||||||
if (server || !Settings.store.arRPC) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
server = await new Server();
|
|
||||||
server.on("activity", (data: any) => sendRendererCommand(IpcCommands.RPC_ACTIVITY, JSON.stringify(data)));
|
|
||||||
server.on("invite", async (invite: string, callback: (valid: boolean) => void) => {
|
|
||||||
invite = String(invite);
|
|
||||||
if (!inviteCodeRegex.test(invite)) return callback(false);
|
|
||||||
|
|
||||||
await sendRendererCommand(IpcCommands.RPC_INVITE, invite).then(callback);
|
|
||||||
});
|
|
||||||
server.on("link", async (data: any, deepCallback: (valid: boolean) => void) => {
|
|
||||||
await sendRendererCommand(IpcCommands.RPC_DEEP_LINK, data).then(deepCallback);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to start arRPC server", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings.addChangeListener("arRPC", initArRPC);
|
|
||||||
77
src/main/arrpc/index.ts
Normal file
77
src/main/arrpc/index.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
|
||||||
|
* Copyright (c) 2023 Vendicated and Vencord contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { resolve } from "path";
|
||||||
|
import { IpcCommands } from "shared/IpcEvents";
|
||||||
|
import { MessageChannel, Worker } from "worker_threads";
|
||||||
|
|
||||||
|
import { sendRendererCommand } from "../ipcCommands";
|
||||||
|
import { Settings } from "../settings";
|
||||||
|
import { ArRpcEvent, ArRpcHostEvent } from "./types";
|
||||||
|
|
||||||
|
let worker: Worker;
|
||||||
|
|
||||||
|
const inviteCodeRegex = /^(\w|-)+$/;
|
||||||
|
|
||||||
|
export async function initArRPC() {
|
||||||
|
if (worker || !Settings.store.arRPC) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { port1: hostPort, port2: workerPort } = new MessageChannel();
|
||||||
|
|
||||||
|
worker = new Worker(resolve(__dirname, "./arRpcWorker.js"), {
|
||||||
|
workerData: {
|
||||||
|
workerPort
|
||||||
|
},
|
||||||
|
transferList: [workerPort]
|
||||||
|
});
|
||||||
|
|
||||||
|
hostPort.on("message", async ({ type, nonce, data }: ArRpcEvent) => {
|
||||||
|
switch (type) {
|
||||||
|
case "activity": {
|
||||||
|
sendRendererCommand(IpcCommands.RPC_ACTIVITY, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "invite": {
|
||||||
|
const invite = String(data);
|
||||||
|
|
||||||
|
const response: ArRpcHostEvent = {
|
||||||
|
type: "ack-invite",
|
||||||
|
nonce,
|
||||||
|
data: false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!inviteCodeRegex.test(invite)) {
|
||||||
|
return hostPort.postMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.data = await sendRendererCommand(IpcCommands.RPC_INVITE, invite).catch(() => false);
|
||||||
|
|
||||||
|
hostPort.postMessage(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "link": {
|
||||||
|
const response: ArRpcHostEvent = {
|
||||||
|
type: "ack-link",
|
||||||
|
nonce: nonce,
|
||||||
|
data: false
|
||||||
|
};
|
||||||
|
|
||||||
|
response.data = await sendRendererCommand(IpcCommands.RPC_DEEP_LINK, data).catch(() => false);
|
||||||
|
|
||||||
|
hostPort.postMessage(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to start arRPC server", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings.addChangeListener("arRPC", initArRPC);
|
||||||
38
src/main/arrpc/types.ts
Normal file
38
src/main/arrpc/types.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ArRpcEvent = ArRpcActivityEvent | ArRpcInviteEvent | ArRpcLinkEvent;
|
||||||
|
export type ArRpcHostEvent = ArRpcHostAckInviteEvent | ArRpcHostAckLinkEvent;
|
||||||
|
|
||||||
|
export interface ArRpcActivityEvent {
|
||||||
|
type: "activity";
|
||||||
|
nonce: string;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArRpcInviteEvent {
|
||||||
|
type: "invite";
|
||||||
|
nonce: string;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArRpcLinkEvent {
|
||||||
|
type: "link";
|
||||||
|
nonce: string;
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArRpcHostAckInviteEvent {
|
||||||
|
type: "ack-invite";
|
||||||
|
nonce: string;
|
||||||
|
data: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArRpcHostAckLinkEvent {
|
||||||
|
type: "ack-link";
|
||||||
|
nonce: string;
|
||||||
|
data: boolean;
|
||||||
|
}
|
||||||
73
src/main/arrpc/worker.ts
Normal file
73
src/main/arrpc/worker.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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 Server from "arrpc";
|
||||||
|
import { randomUUID } from "crypto";
|
||||||
|
import { MessagePort, workerData } from "worker_threads";
|
||||||
|
|
||||||
|
import { ArRpcEvent, ArRpcHostEvent } from "./types";
|
||||||
|
|
||||||
|
let server: any;
|
||||||
|
|
||||||
|
type InviteCallback = (valid: boolean) => void;
|
||||||
|
type LinkCallback = InviteCallback;
|
||||||
|
|
||||||
|
const inviteCallbacks = new Map<string, InviteCallback>();
|
||||||
|
const linkCallbacks = new Map<string, LinkCallback>();
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const { workerPort } = workerData as { workerPort: MessagePort };
|
||||||
|
|
||||||
|
server = await new Server();
|
||||||
|
|
||||||
|
server.on("activity", (data: any) => {
|
||||||
|
const event: ArRpcEvent = {
|
||||||
|
type: "activity",
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
nonce: randomUUID()
|
||||||
|
};
|
||||||
|
workerPort.postMessage(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("invite", (invite: string, callback: InviteCallback) => {
|
||||||
|
const nonce = randomUUID();
|
||||||
|
inviteCallbacks.set(nonce, callback);
|
||||||
|
|
||||||
|
const event: ArRpcEvent = {
|
||||||
|
type: "invite",
|
||||||
|
data: invite,
|
||||||
|
nonce
|
||||||
|
};
|
||||||
|
workerPort.postMessage(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("link", async (data: any, callback: LinkCallback) => {
|
||||||
|
const nonce = randomUUID();
|
||||||
|
linkCallbacks.set(nonce, callback);
|
||||||
|
|
||||||
|
const event: ArRpcEvent = {
|
||||||
|
type: "link",
|
||||||
|
data,
|
||||||
|
nonce
|
||||||
|
};
|
||||||
|
workerPort.postMessage(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
workerPort.on("message", (e: ArRpcHostEvent) => {
|
||||||
|
switch (e.type) {
|
||||||
|
case "ack-invite": {
|
||||||
|
inviteCallbacks.get(e.nonce)?.(e.data);
|
||||||
|
inviteCallbacks.delete(e.nonce);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "ack-link": {
|
||||||
|
linkCallbacks.get(e.nonce)?.(e.data);
|
||||||
|
linkCallbacks.delete(e.nonce);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -28,23 +28,30 @@ process.env.VENCORD_USER_DATA_DIR = DATA_DIR;
|
|||||||
|
|
||||||
const isLinux = process.platform === "linux";
|
const isLinux = process.platform === "linux";
|
||||||
|
|
||||||
|
export let enableHardwareAcceleration = true;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
app.setAsDefaultProtocolClient("discord");
|
app.setAsDefaultProtocolClient("discord");
|
||||||
|
|
||||||
const { disableSmoothScroll, hardwareAcceleration } = Settings.store;
|
const { disableSmoothScroll, hardwareAcceleration, hardwareVideoAcceleration } = Settings.store;
|
||||||
|
|
||||||
const enabledFeatures = new Set(app.commandLine.getSwitchValue("enable-features").split(","));
|
const enabledFeatures = new Set(app.commandLine.getSwitchValue("enable-features").split(","));
|
||||||
const disabledFeatures = new Set(app.commandLine.getSwitchValue("disable-features").split(","));
|
const disabledFeatures = new Set(app.commandLine.getSwitchValue("disable-features").split(","));
|
||||||
|
app.commandLine.removeSwitch("enable-features");
|
||||||
|
app.commandLine.removeSwitch("disable-features");
|
||||||
|
|
||||||
if (hardwareAcceleration === false) {
|
if (hardwareAcceleration === false || process.argv.includes("--disable-gpu")) {
|
||||||
|
enableHardwareAcceleration = false;
|
||||||
app.disableHardwareAcceleration();
|
app.disableHardwareAcceleration();
|
||||||
} else {
|
} else {
|
||||||
enabledFeatures.add("AcceleratedVideoEncoder");
|
if (hardwareVideoAcceleration) {
|
||||||
enabledFeatures.add("AcceleratedVideoDecoder");
|
enabledFeatures.add("AcceleratedVideoEncoder");
|
||||||
|
enabledFeatures.add("AcceleratedVideoDecoder");
|
||||||
|
|
||||||
if (isLinux) {
|
if (isLinux) {
|
||||||
enabledFeatures.add("AcceleratedVideoDecodeLinuxGL");
|
enabledFeatures.add("AcceleratedVideoDecodeLinuxGL");
|
||||||
enabledFeatures.add("AcceleratedVideoDecodeLinuxZeroCopyGL");
|
enabledFeatures.add("AcceleratedVideoDecodeLinuxZeroCopyGL");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,17 +81,22 @@ function init() {
|
|||||||
if (isLinux) {
|
if (isLinux) {
|
||||||
// Support TTS on Linux using https://wiki.archlinux.org/title/Speech_dispatcher
|
// Support TTS on Linux using https://wiki.archlinux.org/title/Speech_dispatcher
|
||||||
app.commandLine.appendSwitch("enable-speech-dispatcher");
|
app.commandLine.appendSwitch("enable-speech-dispatcher");
|
||||||
|
|
||||||
// Work around Gtk-ERROR: GTK 2/3 symbols detected. Using GTK 2/3 and GTK 4 in the same process is not supported
|
|
||||||
// https://github.com/electron/electron/issues/46538
|
|
||||||
// TODO: Remove this when upstream fixes it
|
|
||||||
app.commandLine.appendSwitch("gtk-version", "3");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disabledFeatures.forEach(feat => enabledFeatures.delete(feat));
|
disabledFeatures.forEach(feat => enabledFeatures.delete(feat));
|
||||||
|
|
||||||
app.commandLine.appendSwitch("enable-features", [...enabledFeatures].filter(Boolean).join(","));
|
const enabledFeaturesArray = enabledFeatures.values().filter(Boolean).toArray();
|
||||||
app.commandLine.appendSwitch("disable-features", [...disabledFeatures].filter(Boolean).join(","));
|
const disabledFeaturesArray = disabledFeatures.values().filter(Boolean).toArray();
|
||||||
|
|
||||||
|
if (enabledFeaturesArray.length) {
|
||||||
|
app.commandLine.appendSwitch("enable-features", enabledFeaturesArray.join(","));
|
||||||
|
console.log("Enabled Chromium features:", enabledFeaturesArray.join(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disabledFeaturesArray.length) {
|
||||||
|
app.commandLine.appendSwitch("disable-features", disabledFeaturesArray.join(","));
|
||||||
|
console.log("Disabled Chromium features:", disabledFeaturesArray.join(", "));
|
||||||
|
}
|
||||||
|
|
||||||
// In the Flatpak on SteamOS the theme is detected as light, but SteamOS only has a dark mode, so we just override it
|
// In the Flatpak on SteamOS the theme is detected as light, but SteamOS only has a dark mode, so we just override it
|
||||||
if (isDeckGameMode) nativeTheme.themeSource = "dark";
|
if (isDeckGameMode) nativeTheme.themeSource = "dark";
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
} from "electron";
|
} 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 { enableHardwareAcceleration } from "main";
|
||||||
import { release } from "os";
|
import { release } from "os";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { debounce } from "shared/utils/debounce";
|
import { debounce } from "shared/utils/debounce";
|
||||||
@@ -45,6 +46,7 @@ handleSync(IpcEvents.GET_RENDERER_CSS_FILE, () => join(__dirname, "renderer.css"
|
|||||||
|
|
||||||
handleSync(IpcEvents.GET_SETTINGS, () => Settings.plain);
|
handleSync(IpcEvents.GET_SETTINGS, () => Settings.plain);
|
||||||
handleSync(IpcEvents.GET_VERSION, () => app.getVersion());
|
handleSync(IpcEvents.GET_VERSION, () => app.getVersion());
|
||||||
|
handleSync(IpcEvents.GET_ENABLE_HARDWARE_ACCELERATION, () => enableHardwareAcceleration);
|
||||||
|
|
||||||
handleSync(
|
handleSync(
|
||||||
IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY,
|
IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY,
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ export interface IpcResponse {
|
|||||||
* You must add a handler for the message in the renderer process.
|
* You must add a handler for the message in the renderer process.
|
||||||
*/
|
*/
|
||||||
export function sendRendererCommand<T = any>(message: string, data?: any) {
|
export function sendRendererCommand<T = any>(message: string, data?: any) {
|
||||||
|
if (mainWin.isDestroyed()) {
|
||||||
|
console.warn("Main window is destroyed, cannot send IPC command:", message);
|
||||||
|
return Promise.reject(new Error("Main window is destroyed"));
|
||||||
|
}
|
||||||
|
|
||||||
const nonce = randomUUID();
|
const nonce = randomUUID();
|
||||||
|
|
||||||
const promise = new Promise<T>((resolve, reject) => {
|
const promise = new Promise<T>((resolve, reject) => {
|
||||||
|
|||||||
@@ -388,6 +388,15 @@ function initSpellCheck(win: BrowserWindow) {
|
|||||||
initSpellCheckLanguages(win, Settings.store.spellCheckLanguages);
|
initSpellCheckLanguages(win, Settings.store.spellCheckLanguages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initDevtoolsListeners(win: BrowserWindow) {
|
||||||
|
win.webContents.on("devtools-opened", () => {
|
||||||
|
win.webContents.send(IpcEvents.DEVTOOLS_OPENED);
|
||||||
|
});
|
||||||
|
win.webContents.on("devtools-closed", () => {
|
||||||
|
win.webContents.send(IpcEvents.DEVTOOLS_CLOSED);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initStaticTitle(win: BrowserWindow) {
|
function initStaticTitle(win: BrowserWindow) {
|
||||||
const listener = (e: { preventDefault: Function }) => e.preventDefault();
|
const listener = (e: { preventDefault: Function }) => e.preventDefault();
|
||||||
|
|
||||||
@@ -473,6 +482,7 @@ function createMainWindow() {
|
|||||||
makeLinksOpenExternally(win);
|
makeLinksOpenExternally(win);
|
||||||
initSettingsListeners(win);
|
initSettingsListeners(win);
|
||||||
initSpellCheck(win);
|
initSpellCheck(win);
|
||||||
|
initDevtoolsListeners(win);
|
||||||
initStaticTitle(win);
|
initStaticTitle(win);
|
||||||
|
|
||||||
win.webContents.setUserAgent(BrowserUserAgent);
|
win.webContents.setUserAgent(BrowserUserAgent);
|
||||||
|
|||||||
@@ -20,12 +20,19 @@ ipcRenderer.on(IpcEvents.SPELLCHECK_RESULT, (_, w: string, s: string[]) => {
|
|||||||
spellCheckCallbacks.forEach(cb => cb(w, s));
|
spellCheckCallbacks.forEach(cb => cb(w, s));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let onDevtoolsOpen = () => {};
|
||||||
|
let onDevtoolsClose = () => {};
|
||||||
|
|
||||||
|
ipcRenderer.on(IpcEvents.DEVTOOLS_OPENED, () => onDevtoolsOpen());
|
||||||
|
ipcRenderer.on(IpcEvents.DEVTOOLS_CLOSED, () => onDevtoolsClose());
|
||||||
|
|
||||||
export const VesktopNative = {
|
export const VesktopNative = {
|
||||||
app: {
|
app: {
|
||||||
relaunch: () => invoke<void>(IpcEvents.RELAUNCH),
|
relaunch: () => invoke<void>(IpcEvents.RELAUNCH),
|
||||||
getVersion: () => sendSync<void>(IpcEvents.GET_VERSION),
|
getVersion: () => sendSync<void>(IpcEvents.GET_VERSION),
|
||||||
setBadgeCount: (count: number) => invoke<void>(IpcEvents.SET_BADGE_COUNT, count),
|
setBadgeCount: (count: number) => invoke<void>(IpcEvents.SET_BADGE_COUNT, count),
|
||||||
supportsWindowsTransparency: () => sendSync<boolean>(IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY)
|
supportsWindowsTransparency: () => sendSync<boolean>(IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY),
|
||||||
|
getEnableHardwareAcceleration: () => sendSync<boolean>(IpcEvents.GET_ENABLE_HARDWARE_ACCELERATION)
|
||||||
},
|
},
|
||||||
autostart: {
|
autostart: {
|
||||||
isEnabled: () => sendSync<boolean>(IpcEvents.AUTOSTART_ENABLED),
|
isEnabled: () => sendSync<boolean>(IpcEvents.AUTOSTART_ENABLED),
|
||||||
@@ -56,7 +63,11 @@ export const VesktopNative = {
|
|||||||
focus: () => invoke<void>(IpcEvents.FOCUS),
|
focus: () => invoke<void>(IpcEvents.FOCUS),
|
||||||
close: (key?: string) => invoke<void>(IpcEvents.CLOSE, key),
|
close: (key?: string) => invoke<void>(IpcEvents.CLOSE, key),
|
||||||
minimize: (key?: string) => invoke<void>(IpcEvents.MINIMIZE, key),
|
minimize: (key?: string) => invoke<void>(IpcEvents.MINIMIZE, key),
|
||||||
maximize: (key?: string) => invoke<void>(IpcEvents.MAXIMIZE, key)
|
maximize: (key?: string) => invoke<void>(IpcEvents.MAXIMIZE, key),
|
||||||
|
setDevtoolsCallbacks: (onOpen: () => void, onClose: () => void) => {
|
||||||
|
onDevtoolsOpen = onOpen;
|
||||||
|
onDevtoolsClose = onClose;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
capturer: {
|
capturer: {
|
||||||
getLargeThumbnail: (id: string) => invoke<string>(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id)
|
getLargeThumbnail: (id: string) => invoke<string>(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id)
|
||||||
|
|||||||
@@ -4,15 +4,16 @@
|
|||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Switch, useState } from "@vencord/types/webpack/common";
|
import { useState } from "@vencord/types/webpack/common";
|
||||||
|
|
||||||
import { SettingsComponent } from "./Settings";
|
import { SettingsComponent } from "./Settings";
|
||||||
|
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
|
||||||
|
|
||||||
export const AutoStartToggle: SettingsComponent = () => {
|
export const AutoStartToggle: SettingsComponent = () => {
|
||||||
const [autoStartEnabled, setAutoStartEnabled] = useState(VesktopNative.autostart.isEnabled());
|
const [autoStartEnabled, setAutoStartEnabled] = useState(VesktopNative.autostart.isEnabled());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch
|
<VesktopSettingsSwitch
|
||||||
value={autoStartEnabled}
|
value={autoStartEnabled}
|
||||||
onChange={async v => {
|
onChange={async v => {
|
||||||
await VesktopNative.autostart[v ? "enable" : "disable"]();
|
await VesktopNative.autostart[v ? "enable" : "disable"]();
|
||||||
@@ -21,6 +22,6 @@ export const AutoStartToggle: SettingsComponent = () => {
|
|||||||
note="Automatically start Not-Nextop on computer start-up"
|
note="Automatically start Not-Nextop on computer start-up"
|
||||||
>
|
>
|
||||||
Start With System
|
Start With System
|
||||||
</Switch>
|
</VesktopSettingsSwitch>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Switch } from "@vencord/types/webpack/common";
|
|
||||||
import { setBadge } from "renderer/appBadge";
|
import { setBadge } from "renderer/appBadge";
|
||||||
|
|
||||||
import { SettingsComponent } from "./Settings";
|
import { SettingsComponent } from "./Settings";
|
||||||
|
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
|
||||||
|
|
||||||
export const NotificationBadgeToggle: SettingsComponent = ({ settings }) => {
|
export const NotificationBadgeToggle: SettingsComponent = ({ settings }) => {
|
||||||
return (
|
return (
|
||||||
<Switch
|
<VesktopSettingsSwitch
|
||||||
value={settings.appBadge ?? true}
|
value={settings.appBadge ?? true}
|
||||||
onChange={v => {
|
onChange={v => {
|
||||||
settings.appBadge = v;
|
settings.appBadge = v;
|
||||||
@@ -21,6 +21,6 @@ export const NotificationBadgeToggle: SettingsComponent = ({ settings }) => {
|
|||||||
note="Show mention badge on the app icon"
|
note="Show mention badge on the app icon"
|
||||||
>
|
>
|
||||||
Notification Badge
|
Notification Badge
|
||||||
</Switch>
|
</VesktopSettingsSwitch>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import "./settings.css";
|
import "./settings.css";
|
||||||
|
|
||||||
import { ErrorBoundary } from "@vencord/types/components";
|
import { ErrorBoundary } from "@vencord/types/components";
|
||||||
import { Forms, Switch, Text } from "@vencord/types/webpack/common";
|
import { Forms, Text } from "@vencord/types/webpack/common";
|
||||||
import { ComponentType } from "react";
|
import { ComponentType } from "react";
|
||||||
import { Settings, useSettings } from "renderer/settings";
|
import { Settings, useSettings } from "renderer/settings";
|
||||||
import { isMac, isWindows } from "renderer/utils";
|
import { isMac, isWindows } from "renderer/utils";
|
||||||
@@ -16,6 +16,7 @@ import { AutoStartToggle } from "./AutoStartToggle";
|
|||||||
import { DeveloperOptionsButton } from "./DeveloperOptions";
|
import { DeveloperOptionsButton } from "./DeveloperOptions";
|
||||||
import { DiscordBranchPicker } from "./DiscordBranchPicker";
|
import { DiscordBranchPicker } from "./DiscordBranchPicker";
|
||||||
import { NotificationBadgeToggle } from "./NotificationBadgeToggle";
|
import { NotificationBadgeToggle } from "./NotificationBadgeToggle";
|
||||||
|
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
|
||||||
import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
|
import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
|
||||||
|
|
||||||
interface BooleanSetting {
|
interface BooleanSetting {
|
||||||
@@ -38,6 +39,14 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
|
|||||||
title: "Hardware Acceleration",
|
title: "Hardware Acceleration",
|
||||||
description: "Enable hardware acceleration",
|
description: "Enable hardware acceleration",
|
||||||
defaultValue: true
|
defaultValue: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "hardwareVideoAcceleration",
|
||||||
|
title: "Video Hardware Acceleration",
|
||||||
|
description:
|
||||||
|
"Enable hardware video acceleration. This can improve performance of screenshare and video playback, but may cause graphical glitches and infinitely loading streams.",
|
||||||
|
defaultValue: false,
|
||||||
|
disabled: () => Settings.store.hardwareAcceleration === false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"User Interface": [
|
"User Interface": [
|
||||||
@@ -132,32 +141,35 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
|
|||||||
function SettingsSections() {
|
function SettingsSections() {
|
||||||
const Settings = useSettings();
|
const Settings = useSettings();
|
||||||
|
|
||||||
const sections = Object.entries(SettingsOptions).map(([title, settings]) => (
|
const sections = Object.entries(SettingsOptions).map(([title, settings], i, arr) => (
|
||||||
<Forms.FormSection
|
<div key={title} className="vcd-settings-category">
|
||||||
title={title}
|
<Text variant="heading-lg/semibold" color="header-primary" className="vcd-settings-category-title">
|
||||||
key={title}
|
{title}
|
||||||
className="vcd-settings-section"
|
</Text>
|
||||||
titleClassName="vcd-settings-title"
|
|
||||||
>
|
|
||||||
{settings.map(Setting => {
|
|
||||||
if (typeof Setting === "function") return <Setting settings={Settings} />;
|
|
||||||
|
|
||||||
const { defaultValue, title, description, key, disabled, invisible } = Setting;
|
<div className="vcd-settings-category-content">
|
||||||
if (invisible?.()) return null;
|
{settings.map(Setting => {
|
||||||
|
if (typeof Setting === "function") return <Setting settings={Settings} />;
|
||||||
|
|
||||||
return (
|
const { defaultValue, title, description, key, disabled, invisible } = Setting;
|
||||||
<Switch
|
if (invisible?.()) return null;
|
||||||
value={Settings[key as any] ?? defaultValue}
|
|
||||||
onChange={v => (Settings[key as any] = v)}
|
return (
|
||||||
note={description}
|
<VesktopSettingsSwitch
|
||||||
disabled={disabled?.()}
|
value={Settings[key as any] ?? defaultValue}
|
||||||
key={key}
|
onChange={v => (Settings[key as any] = v)}
|
||||||
>
|
note={description}
|
||||||
{title}
|
disabled={disabled?.()}
|
||||||
</Switch>
|
key={key}
|
||||||
);
|
>
|
||||||
})}
|
{title}
|
||||||
</Forms.FormSection>
|
</VesktopSettingsSwitch>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{i < arr.length - 1 && <Forms.FormDivider className="vcd-settings-category-divider" />}
|
||||||
|
</div>
|
||||||
));
|
));
|
||||||
|
|
||||||
return <>{sections}</>;
|
return <>{sections}</>;
|
||||||
@@ -167,10 +179,16 @@ export default ErrorBoundary.wrap(
|
|||||||
function SettingsUI() {
|
function SettingsUI() {
|
||||||
return (
|
return (
|
||||||
<Forms.FormSection>
|
<Forms.FormSection>
|
||||||
|
<<<<<<< HEAD
|
||||||
<Text variant="heading-lg/semibold" style={{ color: "var(--header-primary)" }} tag="h2">
|
<Text variant="heading-lg/semibold" style={{ color: "var(--header-primary)" }} tag="h2">
|
||||||
Not-Nextop Settings
|
Not-Nextop Settings
|
||||||
|
=======
|
||||||
|
{/* FIXME: Outdated type */}
|
||||||
|
{/* @ts-expect-error Outdated type */}
|
||||||
|
<Text variant="heading-xl/semibold" color="header-primary" className="vcd-settings-title">
|
||||||
|
Vesktop Settings
|
||||||
|
>>>>>>> 27293d4ae9db3a395325f7993cf3cc74a21e0122
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<SettingsSections />
|
<SettingsSections />
|
||||||
</Forms.FormSection>
|
</Forms.FormSection>
|
||||||
);
|
);
|
||||||
|
|||||||
16
src/renderer/components/settings/VesktopSettingsSwitch.tsx
Normal file
16
src/renderer/components/settings/VesktopSettingsSwitch.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* 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 { Switch } from "@vencord/types/webpack/common";
|
||||||
|
import { ComponentProps } from "react";
|
||||||
|
|
||||||
|
export function VesktopSettingsSwitch(props: ComponentProps<typeof Switch>) {
|
||||||
|
return (
|
||||||
|
<Switch {...props} hideBorder className="vcd-settings-switch">
|
||||||
|
{props.children}
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,8 +13,8 @@ export const WindowsTransparencyControls: SettingsComponent = ({ settings }) =>
|
|||||||
if (!VesktopNative.app.supportsWindowsTransparency()) return null;
|
if (!VesktopNative.app.supportsWindowsTransparency()) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<Forms.FormTitle className={Margins.top16 + " " + Margins.bottom8}>Transparency Options</Forms.FormTitle>
|
<Forms.FormTitle className={Margins.bottom8}>Transparency Options</Forms.FormTitle>
|
||||||
<Forms.FormText className={Margins.bottom8}>
|
<Forms.FormText className={Margins.bottom8}>
|
||||||
Requires a full restart. You will need a theme that supports transparency for this to work.
|
Requires a full restart. You will need a theme that supports transparency for this to work.
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
@@ -42,8 +42,6 @@ export const WindowsTransparencyControls: SettingsComponent = ({ settings }) =>
|
|||||||
isSelected={v => v === settings.transparencyOption}
|
isSelected={v => v === settings.transparencyOption}
|
||||||
serialize={s => s}
|
serialize={s => s}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<Forms.FormDivider className={Margins.top16 + " " + Margins.bottom16} />
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,10 +5,30 @@
|
|||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vcd-settings-section {
|
.vcd-settings-title {
|
||||||
margin-top: 1.5rem;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vcd-settings-title {
|
.vcd-settings-category {
|
||||||
margin-bottom: 0.5rem;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vcd-settings-category-title {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vcd-settings-category-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vcd-settings-category-divider {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vcd-settings-switch {
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { addPatch } from "./shared";
|
|
||||||
|
|
||||||
addPatch({
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: '"mod+alt+i"',
|
|
||||||
replacement: {
|
|
||||||
match: /"discord\.com"===location\.host/,
|
|
||||||
replace: "false"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
41
src/renderer/patches/devtoolsFixes.ts
Normal file
41
src/renderer/patches/devtoolsFixes.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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 { addPatch } from "./shared";
|
||||||
|
|
||||||
|
addPatch({
|
||||||
|
patches: [
|
||||||
|
// Discord Web blocks the devtools keybin on mac specifically, disable that
|
||||||
|
{
|
||||||
|
find: '"mod+alt+i"',
|
||||||
|
replacement: {
|
||||||
|
match: /"discord\.com"===location\.host/,
|
||||||
|
replace: "false"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Discord Web uses an incredibly broken devtools detector with false positives.
|
||||||
|
// They "hide" (aka remove from storage) your token if it "detects" open devtools.
|
||||||
|
// Due to the false positives, this leads to random logouts.
|
||||||
|
// Patch their devtools detection to use proper Electron APIs instead to fix the false positives
|
||||||
|
{
|
||||||
|
find: ".setDevtoolsCallbacks(",
|
||||||
|
group: true,
|
||||||
|
replacement: [
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
match: /if\(null!=(\i)\)(?=.{0,50}\1\.window\.setDevtoolsCallbacks)/,
|
||||||
|
replace: "if(true)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
match: /\b\i\.window\.setDevtoolsCallbacks/g,
|
||||||
|
replace: "VesktopNative.win.setDevtoolsCallbacks"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
@@ -56,7 +56,7 @@ addContextMenuPatch("textarea-context", children => {
|
|||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const spellCheckLanguages = (settings.spellCheckLanguages ??= [...new Set(navigator.languages)]);
|
const spellCheckLanguages = (settings.spellCheckLanguages ??= [...new Set(navigator.languages)]);
|
||||||
|
|
||||||
const pasteSectionIndex = children.findIndex(c => c?.props?.children?.some(c => c?.props?.id === "paste"));
|
const pasteSectionIndex = children.findIndex(c => c?.props?.children?.some?.(c => c?.props?.id === "paste"));
|
||||||
|
|
||||||
children.splice(
|
children.splice(
|
||||||
pasteSectionIndex === -1 ? children.length : pasteSectionIndex,
|
pasteSectionIndex === -1 ? children.length : pasteSectionIndex,
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ addPatch({
|
|||||||
// eslint-disable-next-line no-useless-escape
|
// eslint-disable-next-line no-useless-escape
|
||||||
match: /(focus(\(\i\)){).{0,150}?\.focus\(\i,\i\)/,
|
match: /(focus(\(\i\)){).{0,150}?\.focus\(\i,\i\)/,
|
||||||
replace: "$1VesktopNative.win.focus$2"
|
replace: "$1VesktopNative.win.focus$2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /,getEnableHardwareAcceleration/,
|
||||||
|
replace: "$&:VesktopNative.app.getEnableHardwareAcceleration,_oldGetEnableHardwareAcceleration"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ if (Settings.store.customTitleBar)
|
|||||||
},
|
},
|
||||||
// Visual Refresh
|
// Visual Refresh
|
||||||
{
|
{
|
||||||
find: '"data-windows":',
|
find: ".systemBar,",
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
// TODO: Fix eslint rule
|
// TODO: Fix eslint rule
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ function resolveColor(color: string) {
|
|||||||
const updateSplashColors = () => {
|
const updateSplashColors = () => {
|
||||||
const bodyStyles = document.body.computedStyleMap();
|
const bodyStyles = document.body.computedStyleMap();
|
||||||
|
|
||||||
const color = bodyStyles.get("--text-normal");
|
const color = bodyStyles.get("--text-default");
|
||||||
const backgroundColor = bodyStyles.get("--background-primary");
|
const backgroundColor = bodyStyles.get("--background-primary");
|
||||||
|
|
||||||
if (isValidColor(color)) {
|
if (isValidColor(color)) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const enum IpcEvents {
|
|||||||
|
|
||||||
GET_VERSION = "VCD_GET_VERSION",
|
GET_VERSION = "VCD_GET_VERSION",
|
||||||
SUPPORTS_WINDOWS_TRANSPARENCY = "VCD_SUPPORTS_WINDOWS_TRANSPARENCY",
|
SUPPORTS_WINDOWS_TRANSPARENCY = "VCD_SUPPORTS_WINDOWS_TRANSPARENCY",
|
||||||
|
GET_ENABLE_HARDWARE_ACCELERATION = "VCD_GET_ENABLE_HARDWARE_ACCELERATION",
|
||||||
|
|
||||||
RELAUNCH = "VCD_RELAUNCH",
|
RELAUNCH = "VCD_RELAUNCH",
|
||||||
CLOSE = "VCD_CLOSE",
|
CLOSE = "VCD_CLOSE",
|
||||||
@@ -48,14 +49,15 @@ 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",
|
|
||||||
|
|
||||||
CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE",
|
CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE",
|
||||||
|
|
||||||
DEBUG_LAUNCH_GPU = "VCD_DEBUG_LAUNCH_GPU",
|
DEBUG_LAUNCH_GPU = "VCD_DEBUG_LAUNCH_GPU",
|
||||||
DEBUG_LAUNCH_WEBRTC_INTERNALS = "VCD_DEBUG_LAUNCH_WEBRTC",
|
DEBUG_LAUNCH_WEBRTC_INTERNALS = "VCD_DEBUG_LAUNCH_WEBRTC",
|
||||||
|
|
||||||
IPC_COMMAND = "VCD_IPC_COMMAND"
|
IPC_COMMAND = "VCD_IPC_COMMAND",
|
||||||
|
|
||||||
|
DEVTOOLS_OPENED = "VCD_DEVTOOLS_OPENED",
|
||||||
|
DEVTOOLS_CLOSED = "VCD_DEVTOOLS_CLOSED"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum IpcCommands {
|
export const enum IpcCommands {
|
||||||
|
|||||||
1
src/shared/settings.d.ts
vendored
1
src/shared/settings.d.ts
vendored
@@ -16,6 +16,7 @@ export interface Settings {
|
|||||||
enableMenu?: boolean;
|
enableMenu?: boolean;
|
||||||
disableSmoothScroll?: boolean;
|
disableSmoothScroll?: boolean;
|
||||||
hardwareAcceleration?: boolean;
|
hardwareAcceleration?: boolean;
|
||||||
|
hardwareVideoAcceleration?: boolean;
|
||||||
arRPC?: boolean;
|
arRPC?: boolean;
|
||||||
appBadge?: boolean;
|
appBadge?: boolean;
|
||||||
disableMinSize?: boolean;
|
disableMinSize?: boolean;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<head>
|
<head>
|
||||||
|
<title>About Vesktop</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="./style.css" type="text/css" />
|
<link rel="stylesheet" href="./style.css" type="text/css" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -9,19 +11,25 @@
|
|||||||
h1 {
|
h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1 id="title">Vesktop</h1>
|
<h1 id="title">Vesktop v{{APP_VERSION}}</h1>
|
||||||
<p>
|
<p>Vesktop is a cross platform Discord Desktop client, aiming to give you a better Discord experience</p>
|
||||||
Vesktop is a free/libre cross platform desktop app aiming to give you a snappier Discord experience with Vencord
|
|
||||||
pre-installed
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Links</h2>
|
<h2>Links</h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://vesktop.vencord.dev/wiki" target="_blank">Vesktop Wiki</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://vencord.dev" target="_blank">Vencord Website</a>
|
<a href="https://vencord.dev" target="_blank">Vencord Website</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -34,6 +42,17 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>License</h2>
|
||||||
|
<p>
|
||||||
|
Vesktop is licensed under the
|
||||||
|
<a href="https://www.gnu.org/licenses/gpl-3.0.txt" target="_blank">GNU General Public License v3.0</a>.
|
||||||
|
<br />
|
||||||
|
This is free software, and you are welcome to redistribute it under certain conditions; see the license for
|
||||||
|
details.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Acknowledgements</h2>
|
<h2>Acknowledgements</h2>
|
||||||
<p>These awesome libraries empower Vesktop</p>
|
<p>These awesome libraries empower Vesktop</p>
|
||||||
@@ -53,23 +72,36 @@
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/Soundux/rohrkabel" target="_blank">rohrkabel</a>
|
<a href="https://github.com/Soundux/rohrkabel" target="_blank">rohrkabel</a>
|
||||||
- A C++ RAII Pipewire-API Wrapper
|
- A C++ RAII Pipewire-API Wrapper
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
And many
|
And many
|
||||||
<a href="https://github.com/Vencord/Vesktop/blob/main/pnpm-lock.yaml" target="_blank"
|
<a href="https://github.com/Vencord/Vesktop/blob/main/pnpm-lock.yaml" target="_blank"
|
||||||
>more awesome open source libraries</a
|
>more open source libraries</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="module">
|
<script>
|
||||||
const data = await Updater.getData();
|
const data = new URLSearchParams(location.search);
|
||||||
if (data.currentVersion) {
|
|
||||||
const title = document.getElementById("title");
|
|
||||||
|
|
||||||
title.textContent += ` v${data.currentVersion}`;
|
// replace all {{FOO}} placeholders in the document with the values from the URL
|
||||||
|
|
||||||
|
/** @param {Node} [node] */
|
||||||
|
function walk(node) {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
node.textContent = node.textContent.replace(/{{(\w+)}}/g, (match, key) => data.get(key) || match);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.nodeType === Node.ELEMENT_NODE && node.nodeName !== "SCRIPT") {
|
||||||
|
for (const child of node.childNodes) {
|
||||||
|
walk(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walk(document.body);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<head>
|
<head>
|
||||||
|
<title>Vesktop Setup</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="./style.css" type="text/css" />
|
<link rel="stylesheet" href="./style.css" type="text/css" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
--fg-secondary: #313338;
|
--fg-secondary: #313338;
|
||||||
--fg-semi-trans: rgb(0 0 0 / 0.2);
|
--fg-semi-trans: rgb(0 0 0 / 0.2);
|
||||||
--link: #006ce7;
|
--link: #006ce7;
|
||||||
|
--link-hover: #005bb5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
--fg-secondary: #b5bac1;
|
--fg-secondary: #b5bac1;
|
||||||
--fg-semi-trans: rgb(255 255 255 / 0.2);
|
--fg-semi-trans: rgb(255 255 255 / 0.2);
|
||||||
--link: #00a8fc;
|
--link: #00a8fc;
|
||||||
|
--link-hover: #0086c3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,4 +29,9 @@ body {
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
|
transition: color 0.2s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--link-hover);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user