Merge pull request #4 from sz6084/main

Fixing merge conflict
This commit is contained in:
ading2210 2025-02-10 18:45:34 -08:00 committed by GitHub
commit 33f452038d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 1082 additions and 889 deletions

View file

@ -24,6 +24,7 @@ body:
- Issues with Input Methods[^4] - Issues with Input Methods[^4]
- Issues with File Drag and Drop[^5] - Issues with File Drag and Drop[^5]
- Network Errors[^6] - Network Errors[^6]
- Anything about Screenshare Performance[^7]
Linux users: Please only report issues with supported packages (flatpak and any builds from the README / releases). Linux users: Please only report issues with supported packages (flatpak and any builds from the README / releases).
We do not support other packages, like the AUR or Nix packages, so please first make sure your issue is reproducible with official releases, We do not support other packages, like the AUR or Nix packages, so please first make sure your issue is reproducible with official releases,
@ -36,6 +37,8 @@ body:
[^4]: These things are handled by Chromium / Electron, not us. If they don't work, it's either an issue with your system or a bug with Chromium. [^4]: These things are handled by Chromium / Electron, not us. If they don't work, it's either an issue with your system or a bug with Chromium.
[^5]: You are likely using the Vesktop flatpak and trying to drop a file the flatpak can't access. You can fix this by installing Flatseal and using it to grant Vesktop full access to your files [^5]: You are likely using the Vesktop flatpak and trying to drop a file the flatpak can't access. You can fix this by installing Flatseal and using it to grant Vesktop full access to your files
[^6]: Issue on your end, you have to fix it. Try changing your DNS to [1.1.1.1 (Cloudflare DNS)](https://developers.cloudflare.com/1.1.1.1/setup/) [^6]: Issue on your end, you have to fix it. Try changing your DNS to [1.1.1.1 (Cloudflare DNS)](https://developers.cloudflare.com/1.1.1.1/setup/)
[^7]: Screensharing is managed entirely by Chromium and your System. For optimal performance, make sure you [enable Hardware Acceleration](https://wiki.archlinux.org/title/Chromium#Hardware_video_acceleration).
Depending on GPU driver, it might not be supported. We are actively working on making this work out of the box everywhere.
- type: input - type: input
id: discord id: discord

View file

@ -53,6 +53,7 @@ Below you can find unofficial packages created by the community. They are not of
- Arch Linux: [Vesktop on the Arch user repository](https://aur.archlinux.org/packages?K=vesktop) - Arch Linux: [Vesktop on the Arch user repository](https://aur.archlinux.org/packages?K=vesktop)
- NixOS: https://wiki.nixos.org/wiki/Discord#Vesktop - NixOS: https://wiki.nixos.org/wiki/Discord#Vesktop
- Slackware: [Vesktop on the SlackBuilds](https://slackbuilds.org/result/?search=vesktop)
- Windows - Scoop: https://scoop.sh/#/apps?q=Vesktop - Windows - Scoop: https://scoop.sh/#/apps?q=Vesktop
## Building from Source ## Building from Source

View file

@ -21,10 +21,12 @@
"test": "pnpm lint && pnpm testTypes", "test": "pnpm lint && pnpm testTypes",
"testTypes": "tsc --noEmit", "testTypes": "tsc --noEmit",
"watch": "pnpm build --watch", "watch": "pnpm build --watch",
"updateMeta": "tsx scripts/utils/updateMeta.mts" "updateMeta": "tsx scripts/utils/updateMeta.mts",
"updateArrpcDB": "node ./node_modules/arrpc/update_db.js",
"postinstall": "pnpm updateArrpcDB"
}, },
"dependencies": { "dependencies": {
"arrpc": "github:OpenAsar/arrpc#5aadc307cb9bf4479f0a12364a253b07a77ace22", "arrpc": "github:OpenAsar/arrpc#2234e9c9111f4c42ebcc3aa6a2215bfd979eef77",
"electron-updater": "^6.3.9" "electron-updater": "^6.3.9"
}, },
"optionalDependencies": { "optionalDependencies": {
@ -32,28 +34,28 @@
}, },
"devDependencies": { "devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2", "@fal-works/esbuild-plugin-global-externals": "^2.1.2",
"@stylistic/eslint-plugin": "^2.11.0", "@stylistic/eslint-plugin": "^2.13.0",
"@types/node": "^22.10.1", "@types/node": "^22.13.0",
"@types/react": "^18.3.12", "@types/react": "^18.3.18",
"@vencord/types": "^1.8.4", "@vencord/types": "^1.8.4",
"dotenv": "^16.4.6", "dotenv": "^16.4.7",
"electron": "^33.2.1", "electron": "^34.0.2",
"electron-builder": "^25.1.8", "electron-builder": "^25.1.8",
"esbuild": "^0.24.0", "esbuild": "^0.24.2",
"eslint": "^9.16.0", "eslint": "^9.19.0",
"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.2.1", "eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-simple-header": "^1.2.1", "eslint-plugin-simple-header": "^1.2.1",
"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.4.1", "prettier": "^3.4.2",
"source-map-support": "^0.5.21", "source-map-support": "^0.5.21",
"tsx": "^4.19.2", "tsx": "^4.19.2",
"type-fest": "^4.30.0", "type-fest": "^4.33.0",
"typescript": "^5.7.2", "typescript": "^5.7.3",
"typescript-eslint": "^8.17.0", "typescript-eslint": "^8.22.0",
"xml-formatter": "^3.6.3" "xml-formatter": "^3.6.4"
}, },
"packageManager": "pnpm@9.1.0", "packageManager": "pnpm@9.1.0",
"engines": { "engines": {

1715
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -6,9 +6,9 @@
import "./ipc"; import "./ipc";
import { join } from "path";
import { app, BrowserWindow, nativeTheme, net, protocol, session } from "electron"; import { app, BrowserWindow, nativeTheme, net, protocol, session } from "electron";
import { autoUpdater } from "electron-updater"; import { autoUpdater } from "electron-updater";
import { join } from "path";
import { DATA_DIR, VESKTOP_SPLASH_DIR } from "./constants"; import { DATA_DIR, VESKTOP_SPLASH_DIR } from "./constants";
import { createFirstLaunchTour } from "./firstLaunch"; import { createFirstLaunchTour } from "./firstLaunch";
@ -84,36 +84,35 @@ function init() {
registerScreenShareHandler(); registerScreenShareHandler();
registerMediaPermissionsHandler(); registerMediaPermissionsHandler();
//register file handler so we can load the custom splash animation from the user's filesystem // register file handler so we can load the custom splash animation from the user's filesystem
protocol.handle("splash-animation", () => { protocol.handle("splash-animation", () => {
const { splashAnimationPath } = Settings.store; const { splashAnimationPath } = Settings.store;
const fullPath = join(VESKTOP_SPLASH_DIR, splashAnimationPath as string); const fullPath = join(VESKTOP_SPLASH_DIR, splashAnimationPath as string);
return net.fetch("file:///"+fullPath); return net.fetch("file:///" + fullPath);
}); });
//this patches the discord csp to allow the splash-animation:// protocol // this patches the discord csp to allow the splash-animation:// protocol
//the vencord:// protocol is already whitelisted, but the code for doing that is in the // the vencord:// protocol is already whitelisted, but the code for doing that is in the
//vencord repo, not the vesktop one. hopefully in the future, the splash image functionality // vencord repo, not the vesktop one. hopefully in the future, the splash image functionality
//can be added to the vencord:// protocol handler, or the vencord:// protocol handler can be moved here // can be added to the vencord:// protocol handler, or the vencord:// protocol handler can be moved here
let otherHandler: any = null; let otherHandler: any = null;
session.defaultSession.webRequest.onHeadersReceived(({responseHeaders, resourceType}, callback) => { session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, callback) => {
if (responseHeaders && resourceType === "mainFrame" && responseHeaders["content-security-policy"]) { if (responseHeaders && resourceType === "mainFrame" && responseHeaders["content-security-policy"]) {
let csp = responseHeaders["content-security-policy"][0]; let csp = responseHeaders["content-security-policy"][0];
csp = csp.replace("img-src", "img-src splash-animation:"); csp = csp.replace("img-src", "img-src splash-animation:");
responseHeaders["content-security-policy"] = [csp]; responseHeaders["content-security-policy"] = [csp];
} }
if (otherHandler) { if (otherHandler) {
otherHandler({responseHeaders, resourceType}, callback); otherHandler({ responseHeaders, resourceType }, callback);
} } else {
else {
callback({ cancel: false, responseHeaders }); callback({ cancel: false, responseHeaders });
} }
}); });
//we need to overwrite onHeadersReceived because normally electron only allows one handler to be active at a time // we need to overwrite onHeadersReceived because normally electron only allows one handler to be active at a time
session.defaultSession.webRequest.onHeadersReceived = (handler) => { session.defaultSession.webRequest.onHeadersReceived = handler => {
otherHandler = handler; otherHandler = handler;
} };
bootstrap(); bootstrap();

View file

@ -7,12 +7,12 @@
if (process.platform === "linux") import("./venmic"); if (process.platform === "linux") import("./venmic");
import { execFile } from "child_process"; import { execFile } from "child_process";
import { app, BrowserWindow, clipboard, dialog, nativeImage, RelaunchOptions, session, shell } from "electron";
import { mkdirSync, readFileSync, watch, existsSync } from "fs";
import { open, readFile, copyFile, mkdir, rmdir } from "fs/promises";
import { release } from "os";
import { randomBytes } from "crypto"; import { randomBytes } from "crypto";
import { join, extname } from "path"; import { app, BrowserWindow, clipboard, dialog, nativeImage, RelaunchOptions, session, shell } from "electron";
import { existsSync, mkdirSync, readFileSync, watch } from "fs";
import { copyFile, mkdir, open, readFile, rmdir } from "fs/promises";
import { release } from "os";
import { extname, join } from "path";
import { debounce } from "shared/utils/debounce"; import { debounce } from "shared/utils/debounce";
import { IpcEvents } from "../shared/IpcEvents"; import { IpcEvents } from "../shared/IpcEvents";
@ -130,9 +130,7 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async (_e, value?: null) => {
handle(IpcEvents.SELECT_IMAGE_PATH, async () => { handle(IpcEvents.SELECT_IMAGE_PATH, async () => {
const res = await dialog.showOpenDialog(mainWin!, { const res = await dialog.showOpenDialog(mainWin!, {
properties: ["openFile"], properties: ["openFile"],
filters: [ filters: [{ name: "Images", extensions: ["apng", "avif", "gif", "jpeg", "png", "svg", "webp"] }]
{name: "Images", extensions: ["apng", "avif", "gif", "jpeg", "png", "svg", "webp"]}
]
}); });
if (!res.filePaths.length) return "cancelled"; if (!res.filePaths.length) return "cancelled";
@ -142,9 +140,9 @@ handle(IpcEvents.SELECT_IMAGE_PATH, async () => {
const destPath = join(VESKTOP_SPLASH_DIR, imageName); const destPath = join(VESKTOP_SPLASH_DIR, imageName);
if (existsSync(VESKTOP_SPLASH_DIR)) { if (existsSync(VESKTOP_SPLASH_DIR)) {
await rmdir(VESKTOP_SPLASH_DIR, {recursive: true}); await rmdir(VESKTOP_SPLASH_DIR, { recursive: true });
} }
await mkdir(VESKTOP_SPLASH_DIR, {recursive: true}); await mkdir(VESKTOP_SPLASH_DIR, { recursive: true });
await copyFile(originalPath, destPath); await copyFile(originalPath, destPath);
return imageName; return imageName;
@ -159,6 +157,17 @@ handle(IpcEvents.CLIPBOARD_COPY_IMAGE, async (_, buf: ArrayBuffer, src: string)
}); });
}); });
function openDebugPage(page: string) {
const win = new BrowserWindow({
autoHideMenuBar: true
});
win.loadURL(page);
}
handle(IpcEvents.DEBUG_LAUNCH_GPU, () => openDebugPage("chrome://gpu"));
handle(IpcEvents.DEBUG_LAUNCH_WEBRTC_INTERNALS, () => openDebugPage("chrome://webrtc-internals"));
function readCss() { function readCss() {
return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => ""); return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => "");
} }

View file

@ -39,13 +39,12 @@ export function createSplashWindow(startMinimized = false) {
splash.webContents.executeJavaScript(` splash.webContents.executeJavaScript(`
document.getElementById("animation").src = "splash-animation://img"; document.getElementById("animation").src = "splash-animation://img";
`); `);
} } else {
else { splash.webContents.insertCSS(`img {image-rendering: pixelated}`);
splash.webContents.insertCSS(`img {image-rendering: pixelated}`)
splash.webContents.executeJavaScript(` splash.webContents.executeJavaScript(`
document.getElementById("animation").src = "../shiggy.gif"; document.getElementById("animation").src = "../shiggy.gif";
`); `);
} }
return splash; return splash;
} }

View file

@ -79,5 +79,9 @@ export const VesktopNative = {
clipboard: { clipboard: {
copyImage: (imageBuffer: Uint8Array, imageSrc: string) => copyImage: (imageBuffer: Uint8Array, imageSrc: string) =>
invoke<void>(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc) invoke<void>(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc)
},
debug: {
launchGpu: () => invoke<void>(IpcEvents.DEBUG_LAUNCH_GPU),
launchWebrtcInternals: () => invoke<void>(IpcEvents.DEBUG_LAUNCH_WEBRTC_INTERNALS)
} }
}; };

View file

@ -25,7 +25,7 @@ import { addPatch } from "renderer/patches/shared";
import { useSettings } from "renderer/settings"; import { useSettings } from "renderer/settings";
import { isLinux, isWindows } from "renderer/utils"; import { isLinux, isWindows } from "renderer/utils";
const StreamResolutions = ["480", "720", "1080", "1440"] as const; const StreamResolutions = ["480", "720", "1080", "1440", "2160"] as const;
const StreamFps = ["15", "30", "60"] as const; const StreamFps = ["15", "30", "60"] as const;
const MediaEngineStore = findStoreLazy("MediaEngineStore"); const MediaEngineStore = findStoreLazy("MediaEngineStore");
@ -801,4 +801,4 @@ function ModalComponent({
</Modals.ModalFooter> </Modals.ModalFooter>
</Modals.ModalRoot> </Modals.ModalRoot>
); );
} }

View file

@ -11,45 +11,45 @@ import { SettingsComponent } from "./Settings";
export const CustomSplashAnimation: SettingsComponent = ({ settings }) => { export const CustomSplashAnimation: SettingsComponent = ({ settings }) => {
return ( return (
<> <>
<Forms.FormText>
<Forms.FormText> {settings.splashAnimationPath ? (
{settings.splashAnimationPath ? ( <div
<div style={{ style={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
gap: "16px" gap: "16px"
}}> }}
{/* adding the Math.random() here ensures that a new image is fetched when the user changes the path */} >
<img src={"splash-animation:///" + Math.random()} width="64px" height="64px"></img> {/* adding the Math.random() here ensures that a new image is fetched when the user changes the path */}
<p>The custom splash animation is enabled.</p> <img src={"splash-animation:///" + Math.random()} width="64px" height="64px"></img>
</div> <p>The custom splash animation is enabled.</p>
) : ( </div>
"A custom splash animation is not set." ) : (
)} "A custom splash animation is not set."
</Forms.FormText> )}
<div className="vcd-location-btns" style={{marginBottom: 20}}> </Forms.FormText>
<Button <div className="vcd-settings-button-grid" style={{ marginBottom: 20 }}>
size={Button.Sizes.SMALL} <Button
onClick={async () => { size={Button.Sizes.SMALL}
const choice = await VesktopNative.fileManager.selectImagePath(); onClick={async () => {
if (choice === "cancelled") return; const choice = await VesktopNative.fileManager.selectImagePath();
settings.splashAnimationPath = choice; if (choice === "cancelled") return;
}} settings.splashAnimationPath = choice;
> }}
Change >
</Button> Change
<Button </Button>
size={Button.Sizes.SMALL} <Button
color={Button.Colors.RED} size={Button.Sizes.SMALL}
onClick={() => { color={Button.Colors.RED}
//todo: delete the image after resetting the path? onClick={() => {
settings.splashAnimationPath = undefined // todo: delete the image after resetting the path?
}} settings.splashAnimationPath = undefined;
> }}
Reset >
</Button> Reset
</div> </Button>
</div>
</> </>
); );
}; };

View file

@ -4,12 +4,56 @@
* Copyright (c) 2023 Vendicated and Vencord contributors * Copyright (c) 2023 Vendicated and Vencord contributors
*/ */
import { useForceUpdater } from "@vencord/types/utils"; import {
import { Button, Forms, Toasts } from "@vencord/types/webpack/common"; Margins,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalRoot,
ModalSize,
openModal,
useForceUpdater
} from "@vencord/types/utils";
import { Button, Forms, Text, Toasts } from "@vencord/types/webpack/common";
import { Settings } from "shared/settings";
import { SettingsComponent } from "./Settings"; import { SettingsComponent } from "./Settings";
export const VencordLocationPicker: SettingsComponent = ({ settings }) => { export const DeveloperOptionsButton: SettingsComponent = ({ settings }) => {
return <Button onClick={() => openDeveloperOptionsModal(settings)}>Open Developer Settings</Button>;
};
function openDeveloperOptionsModal(settings: Settings) {
openModal(props => (
<ModalRoot {...props} size={ModalSize.MEDIUM}>
<ModalHeader>
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>
Vesktop Developer Options
</Text>
<ModalCloseButton onClick={props.onClose} />
</ModalHeader>
<ModalContent>
<div style={{ padding: "1em 0" }}>
<Forms.FormTitle tag="h5">Vencord Location</Forms.FormTitle>
<VencordLocationPicker settings={settings} />
<Forms.FormTitle tag="h5" className={Margins.top16}>
Debugging
</Forms.FormTitle>
<div className="vcd-settings-button-grid">
<Button onClick={() => VesktopNative.debug.launchGpu()}>Open chrome://gpu</Button>
<Button onClick={() => VesktopNative.debug.launchWebrtcInternals()}>
Open chrome://webrtc-internals
</Button>
</div>
</div>
</ModalContent>
</ModalRoot>
));
}
const VencordLocationPicker: SettingsComponent = ({ settings }) => {
const forceUpdate = useForceUpdater(); const forceUpdate = useForceUpdater();
const vencordDir = VesktopNative.fileManager.getVencordDir(); const vencordDir = VesktopNative.fileManager.getVencordDir();
@ -31,7 +75,7 @@ export const VencordLocationPicker: SettingsComponent = ({ settings }) => {
"the default location" "the default location"
)} )}
</Forms.FormText> </Forms.FormText>
<div className="vcd-location-btns"> <div className="vcd-settings-button-grid">
<Button <Button
size={Button.Sizes.SMALL} size={Button.Sizes.SMALL}
onClick={async () => { onClick={async () => {

View file

@ -12,11 +12,11 @@ import { Settings, useSettings } from "renderer/settings";
import { isMac, isWindows } from "renderer/utils"; import { isMac, isWindows } from "renderer/utils";
import { AutoStartToggle } from "./AutoStartToggle"; import { AutoStartToggle } from "./AutoStartToggle";
import { CustomSplashAnimation } from "./CustomSplashAnimation";
import { DeveloperOptionsButton } from "./DeveloperOptions";
import { DiscordBranchPicker } from "./DiscordBranchPicker"; import { DiscordBranchPicker } from "./DiscordBranchPicker";
import { NotificationBadgeToggle } from "./NotificationBadgeToggle"; import { NotificationBadgeToggle } from "./NotificationBadgeToggle";
import { VencordLocationPicker } from "./VencordLocationPicker";
import { WindowsTransparencyControls } from "./WindowsTransparencyControls"; import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
import { CustomSplashAnimation } from "./CustomSplashAnimation";
interface BooleanSetting { interface BooleanSetting {
key: keyof typeof Settings.store; key: keyof typeof Settings.store;
@ -119,8 +119,8 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
defaultValue: false defaultValue: false
} }
], ],
"Custom Splash Animation":[CustomSplashAnimation], "Custom Splash Animation": [CustomSplashAnimation],
"Vencord Location": [VencordLocationPicker] "Developer Options": [DeveloperOptionsButton]
}; };
function SettingsSections() { function SettingsSections() {

View file

@ -1,4 +1,4 @@
.vcd-location-btns { .vcd-settings-button-grid {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
gap: 0.5em; gap: 0.5em;

View file

@ -25,7 +25,7 @@ export const enum IpcEvents {
GET_VENCORD_DIR = "VCD_GET_VENCORD_DIR", GET_VENCORD_DIR = "VCD_GET_VENCORD_DIR",
SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR", SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR",
SELECT_IMAGE_PATH= "VCD_SELECT_IMAGE_PATH", SELECT_IMAGE_PATH = "VCD_SELECT_IMAGE_PATH",
UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA", UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA",
UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD", UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD",
@ -51,5 +51,8 @@ export const enum IpcEvents {
ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY", 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_WEBRTC_INTERNALS = "VCD_DEBUG_LAUNCH_WEBRTC"
} }