22 Commits

Author SHA1 Message Date
Vendicated
4a2d12f273 fix lockfile 2025-07-08 01:08:39 +02:00
Vendicated
3498e39cbb bump to v1.5.8 2025-07-08 01:02:17 +02:00
Vendicated
3278b16923 Remove GTK mixed symbols workaround
This bug is fixed in electron 37, so the workaround is no longer needed
2025-07-06 19:16:07 +02:00
Vendicated
fde447bc1d improve about window 2025-07-06 18:57:57 +02:00
Vendicated
4baf6de472 arrpc: fix link handling 2025-07-06 17:54:58 +02:00
Justin
8aa91b4f01 Move arrpc server into a worker thread to reduce stutters (#1053)
Co-authored-by: V <vendicated@riseup.net>
2025-07-06 17:34:32 +02:00
Vendicated
099845deb7 bump electron again surely this time they fixed every bug 2025-07-06 16:27:04 +02:00
Vendicated
3982e122a7 upgrade to electron 37 2025-06-27 23:08:50 +02:00
Cookie
8d3c9390ae update discord css variable name (#1164) 2025-06-27 03:09:33 +02:00
Vendicated
236fc806de fake markdown wtf 2025-06-26 15:09:35 +02:00
Vendicated
2dcebeca79 revise issue template once again 2025-06-26 15:08:28 +02:00
Vendicated
e6589eacfc fix lockfile 2025-06-21 04:12:21 +02:00
Vendicated
29d1c73d81 okay pnpm 2025-06-21 04:10:45 +02:00
Vendicated
26906b9776 patch electron-updater to fix rpm updater 2025-06-21 04:06:13 +02:00
Vendicated
36c67aa54a bump dependencies 2025-06-21 04:06:00 +02:00
Cookie
3cd4e94762 fix spellcheck (#1163) 2025-06-20 19:29:13 +02:00
Vendicated
6950e0b03a add comment explaining the patch 2025-06-10 17:22:30 +02:00
Vendicated
f98309c7b7 fix random logouts (Discord shitcode moment) 2025-06-10 17:16:26 +02:00
Vendicated
a2dade9140 i am very stupid 2025-06-09 01:36:45 +02:00
Vendicated
83ad4970e5 fix Video HWA wrongly being disabled if HWA setting was never changed 2025-06-09 01:36:15 +02:00
Vending Machine
f123f5fc3c Update dev.vencord.Vesktop.metainfo.xml 2025-06-08 22:07:07 +02:00
Vending Machine
0a856b26da Update meta.yml 2025-06-08 22:04:59 +02:00
25 changed files with 648 additions and 315 deletions

View File

@@ -5,8 +5,13 @@ body:
- type: markdown
attributes:
value: |
![Are you a developer? No? This form is not for you!](https://github.com/Vencord/Vesktop/blob/main/.github/ISSUE_TEMPLATE/developer-banner.png?raw=true)
GitHub Issues are for developers, not support. Please use our [support server](https://vencord.dev/discord) if you are not a developer.
# This form is reserved for Vesktop Developers. Do not open an issue.
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
id: content
attributes:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -37,6 +37,6 @@ jobs:
git add meta/dev.vencord.Vesktop.metainfo.xml
git commit -m "metainfo: add entry for ${{ github.event.release.tag_name }}"
git push
git push origin HEAD:main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -28,6 +28,23 @@
</screenshot>
</screenshots>
<releases>
<release version="1.5.7" date="2025-06-08" type="stable">
<url>https://github.com/Vencord/Vesktop/releases/tag/v1.5.7</url>
<description>
<p>What's Changed</p>
<ul>
<li>Starting a screenshare on Windows will no longer mute system audio</li>
<li>Fixed showing "Invalid URL" errors in some edge cases (spotty network)</li>
<li>Now respects your Autogain preference</li>
<li>Improved the flow for linking third party accounts</li>
<li>Fixed issue that would cause the AppImage to have no icon and be unpinnable</li>
<li>Added the ability to screenshare with stereo audio</li>
<li>Added Video Hardware Acceleration switch - Used to always be enabled. Now it is opt-in (disabled by default) to fix graphical glitches that were affecting many users</li>
<li>Fixed Discord titlebar buttons</li>
<li>Fixed "Object has been destroyed" error in some edge cases</li>
</ul>
</description>
</release>
<release version="1.5.6" date="2025-04-13" type="stable">
<url>https://github.com/Vencord/Vesktop/releases/tag/v1.5.6</url>
<description>
@@ -278,4 +295,4 @@
<keyword>Privacy</keyword>
<keyword>Mod</keyword>
</keywords>
</component>
</component>

View File

@@ -1,6 +1,6 @@
{
"name": "vesktop",
"version": "1.5.7",
"version": "1.5.8",
"private": true,
"description": "Vesktop is a custom Discord desktop app",
"keywords": [],
@@ -34,27 +34,27 @@
},
"devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
"@stylistic/eslint-plugin": "^4.4.1",
"@types/node": "^22.15.30",
"@stylistic/eslint-plugin": "^5.1.0",
"@types/node": "^24.0.10",
"@types/react": "18.3.1",
"@vencord/types": "^1.11.5",
"dotenv": "^16.5.0",
"electron": "^36.4.0",
"electron": "^37.2.0",
"electron-builder": "^26.0.12",
"esbuild": "^0.25.5",
"eslint": "^9.28.0",
"eslint": "^9.30.1",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-path-alias": "^2.1.0",
"eslint-plugin-prettier": "^5.4.1",
"eslint-plugin-prettier": "^5.5.1",
"eslint-plugin-simple-header": "^1.2.2",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^4.1.4",
"prettier": "^3.5.3",
"prettier": "^3.6.2",
"source-map-support": "^0.5.21",
"tsx": "^4.19.4",
"tsx": "^4.20.3",
"type-fest": "^4.41.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.33.1",
"typescript-eslint": "^8.35.1",
"xml-formatter": "^3.6.6"
},
"packageManager": "pnpm@10.7.1",
@@ -199,7 +199,8 @@
},
"pnpm": {
"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": [
"@vencord/venmic",

View 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"));

480
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -58,6 +58,12 @@ await Promise.all([
outfile: "dist/js/main.js",
footer: { js: "//# sourceURL=VCDMain" }
}),
createContext({
...NodeCommonOpts,
entryPoints: ["src/main/arrpc/worker.ts"],
outfile: "dist/js/arRpcWorker.js",
footer: { js: "//# sourceURL=VCDArRpcWorker" }
}),
createContext({
...NodeCommonOpts,
entryPoints: ["src/preload/index.ts"],

View File

@@ -4,25 +4,33 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { BrowserWindow } from "electron";
import { app, BrowserWindow } from "electron";
import { join } from "path";
import { ICON_PATH, VIEW_DIR } from "shared/paths";
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
export function createAboutWindow() {
export async function createAboutWindow() {
const height = 750;
const width = height * (4 / 3);
const about = new BrowserWindow({
center: true,
autoHideMenuBar: true,
icon: ICON_PATH,
webPreferences: {
preload: join(__dirname, "updaterPreload.js")
}
height,
width
});
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;
}

View File

@@ -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
View 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
View 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
View 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;
}
}
});
})();

View File

@@ -81,11 +81,6 @@ function init() {
if (isLinux) {
// Support TTS on Linux using https://wiki.archlinux.org/title/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));

View File

@@ -388,6 +388,15 @@ function initSpellCheck(win: BrowserWindow) {
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) {
const listener = (e: { preventDefault: Function }) => e.preventDefault();
@@ -473,6 +482,7 @@ function createMainWindow() {
makeLinksOpenExternally(win);
initSettingsListeners(win);
initSpellCheck(win);
initDevtoolsListeners(win);
initStaticTitle(win);
win.webContents.setUserAgent(BrowserUserAgent);

View File

@@ -20,6 +20,12 @@ ipcRenderer.on(IpcEvents.SPELLCHECK_RESULT, (_, w: string, s: string[]) => {
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 = {
app: {
relaunch: () => invoke<void>(IpcEvents.RELAUNCH),
@@ -57,7 +63,11 @@ export const VesktopNative = {
focus: () => invoke<void>(IpcEvents.FOCUS),
close: (key?: string) => invoke<void>(IpcEvents.CLOSE, 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: {
getLargeThumbnail: (id: string) => invoke<string>(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id)

View File

@@ -46,7 +46,7 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
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
disabled: () => Settings.store.hardwareAcceleration === false
}
],
"User Interface": [

View File

@@ -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"
}
}
]
});

View 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"
}
]
}
]
});

View File

@@ -56,7 +56,7 @@ addContextMenuPatch("textarea-context", children => {
const settings = useSettings();
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(
pasteSectionIndex === -1 ? children.length : pasteSectionIndex,

View File

@@ -59,7 +59,7 @@ function resolveColor(color: string) {
const updateSplashColors = () => {
const bodyStyles = document.body.computedStyleMap();
const color = bodyStyles.get("--text-normal");
const color = bodyStyles.get("--text-default");
const backgroundColor = bodyStyles.get("--background-primary");
if (isValidColor(color)) {

View File

@@ -49,14 +49,15 @@ export const enum IpcEvents {
VIRT_MIC_START_SYSTEM = "VCD_VIRT_MIC_START_ALL",
VIRT_MIC_STOP = "VCD_VIRT_MIC_STOP",
ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY",
CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE",
DEBUG_LAUNCH_GPU = "VCD_DEBUG_LAUNCH_GPU",
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 {

View File

@@ -1,4 +1,6 @@
<head>
<title>About Vesktop</title>
<link rel="stylesheet" href="./style.css" type="text/css" />
<style>
@@ -9,19 +11,25 @@
h1 {
text-align: center;
}
ul {
display: flex;
flex-direction: column;
gap: 0.5em;
}
</style>
</head>
<body>
<h1 id="title">Vesktop</h1>
<p>
Vesktop is a free/libre cross platform desktop app aiming to give you a snappier Discord experience with Vencord
pre-installed
</p>
<h1 id="title">Vesktop v{{APP_VERSION}}</h1>
<p>Vesktop is a cross platform Discord Desktop client, aiming to give you a better Discord experience</p>
<section>
<h2>Links</h2>
<ul>
<li>
<a href="https://vesktop.vencord.dev/wiki" target="_blank">Vesktop Wiki</a>
</li>
<li>
<a href="https://vencord.dev" target="_blank">Vencord Website</a>
</li>
@@ -34,6 +42,17 @@
</ul>
</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>
<h2>Acknowledgements</h2>
<p>These awesome libraries empower Vesktop</p>
@@ -53,23 +72,36 @@
</li>
<li>
<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>
And many
<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>
</ul>
</section>
</body>
<script type="module">
const data = await Updater.getData();
if (data.currentVersion) {
const title = document.getElementById("title");
<script>
const data = new URLSearchParams(location.search);
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>

View File

@@ -1,4 +1,6 @@
<head>
<title>Vesktop Setup</title>
<link rel="stylesheet" href="./style.css" type="text/css" />
<style>

View File

@@ -4,6 +4,7 @@
--fg-secondary: #313338;
--fg-semi-trans: rgb(0 0 0 / 0.2);
--link: #006ce7;
--link-hover: #005bb5;
}
@media (prefers-color-scheme: dark) {
@@ -13,6 +14,7 @@
--fg-secondary: #b5bac1;
--fg-semi-trans: rgb(255 255 255 / 0.2);
--link: #00a8fc;
--link-hover: #0086c3;
}
}
@@ -27,4 +29,9 @@ body {
a {
color: var(--link);
transition: color 0.2s linear;
}
a:hover {
color: var(--link-hover);
}