34 Commits

Author SHA1 Message Date
Vendicated
45f56c63a0 bump to v0.3.3 2023-09-30 22:45:22 +02:00
Tornike Khintibidze
89af4316d3 Optimize the menu bar for macOS (#120)
Co-authored-by: V <vendicated@riseup.net>
2023-09-30 20:43:27 +00:00
Cynthia Foxwell
a9bfb857ae Bump Electron to 25.8.4 for CVE-2023-5217 (#134) 2023-09-30 19:38:32 +00:00
Vendicated
b9e411ac90 fix deb/rpm icon 2023-09-28 02:31:42 +02:00
Zyrouge
670de01938 fix: appimage not relaunching (#128) 2023-09-27 04:52:00 +02:00
Lewis Crichton
ef064eba3d ci: switch to vedantmgoyal2009/winget-releaser (#103)
Co-authored-by: V <vendicated@riseup.net>
2023-09-26 00:00:17 +02:00
V
d5f63da939 bump to v0.3.2 2023-09-25 22:11:53 +02:00
Pierre
2aadc61af9 Downgrade electron to v25.8.2 (#126) 2023-09-25 22:09:46 +02:00
Zyrouge
061fec44af fix icon missing in some windows (#124)
Co-authored-by: V <vendicated@riseup.net>
2023-09-25 01:19:54 +00:00
V
b876f450c3 bump arrpc 2023-09-25 03:17:50 +02:00
V
5f5febda9d bump electron for important security fixes 2023-09-25 03:12:51 +02:00
Lewis Crichton
94ba59afb5 fix: add correct WMClass to desktop file (#108)
resolves #96
2023-08-31 22:52:12 +02:00
V
566737017c ci: publish as draft 2023-08-27 22:40:37 +02:00
Lewis Crichton
196ee4e42c ci: winget (#101) 2023-08-27 22:27:23 +02:00
V
9bb02f8581 security: make ipc only allow discord origins 2023-08-25 15:32:06 +02:00
V
c76d7195a5 Bump to 0.3.0 2023-08-16 02:05:17 +02:00
V
50a103710d Add Vesktop section to Settings customSections 2023-08-16 02:02:23 +02:00
DaBluLite
e6e66e775c Fix platformClass: change "platform-windows" to "platform-win" (#94) 2023-08-14 13:55:47 +00:00
V
a5ec031a2f Fix windows titlebar on canary 2023-08-12 04:01:10 +02:00
V
4dceadbbd2 Bump to 0.2.9 (for real this time) 2023-08-12 03:15:37 +02:00
V
6ee920ff2c Show error toast when selecting invalid venchord dir 2023-08-12 03:15:21 +02:00
V
28ad4a6f73 Improve valid vencord install checks 2023-08-12 03:13:07 +02:00
V
c5ac3e64a6 Bump to 0.2.9 2023-08-12 03:09:38 +02:00
Justice Almanzar
6dc26aea6a vecord: download proper vesktop specific preload & renderer css (#90)
Co-authored-by: V <vendicated@riseup.net>
2023-08-12 03:09:14 +02:00
Hugo C
9003b94f85 mac: fix dock notification badge (#88) 2023-08-08 13:08:32 +02:00
V
f7b7931847 only pass partial info 2023-08-07 00:48:23 +02:00
V
b87bcaefe9 Wayland: Skip our screenshare screen picker 2023-08-07 00:39:38 +02:00
V
3108de7c79 Port Discord's windows title bar (#86) 2023-08-07 00:23:27 +02:00
Lewis Crichton
57006e7e52 feat: portable zip (#85) 2023-08-06 02:05:48 +02:00
Nickyux
8f1ea1f440 Update Settings Text to Vesktop (#84) 2023-08-05 17:18:12 +00:00
TymanWasTaken
26b6fb13d4 Update pnpm in package.json (#79)
Co-authored-by: V <vendicated@riseup.net>
2023-08-04 20:36:28 +02:00
V
e1971f55a0 bump arrpc; fixes false positives 2023-08-04 20:21:49 +02:00
V
ba2618878e add vencord themes watcher 2023-08-04 19:39:33 +02:00
V
87595deae7 Fix static title 2023-08-02 23:59:02 +02:00
23 changed files with 324 additions and 106 deletions

17
.github/workflows/winget-submission.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Submit to Winget Community Repo
on:
release:
types: [published]
jobs:
winget:
name: Publish winget package
runs-on: ubuntu-latest
steps:
- name: Submit package to Winget Community Repo
uses: vedantmgoyal2009/winget-releaser@52ef3f3028ed79a9606d7678d0a88d295bc0c690 # v2
with:
identifier: Vencord.Vesktop
token: ${{ secrets.WINGET_PAT }}
installers-regex: '\.exe$'

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
dist
node_modules
.env
.DS_Store
.idea/

View File

@@ -1,6 +1,6 @@
{
"name": "VencordDesktop",
"version": "0.2.8",
"version": "0.3.3",
"private": true,
"description": "",
"keywords": [],
@@ -23,7 +23,7 @@
"watch": "pnpm build --watch"
},
"dependencies": {
"arrpc": "github:OpenAsar/arrpc#bfcba7e3d6e6f7301a5699c4a1eb10c968e7b568"
"arrpc": "github:OpenAsar/arrpc#89f4da610ccfac93f461826a446a17cd3b23953d"
},
"devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
@@ -33,7 +33,7 @@
"@typescript-eslint/parser": "^6.2.1",
"@vencord/types": "^0.1.2",
"dotenv": "^16.3.1",
"electron": "^25.4.0",
"electron": "^25.8.4",
"electron-builder": "^24.6.3",
"esbuild": "^0.18.17",
"eslint": "^8.46.0",
@@ -50,7 +50,7 @@
"type-fest": "^4.1.0",
"typescript": "^5.1.6"
},
"packageManager": "pnpm@8.1.1",
"packageManager": "pnpm@8.6.11",
"engines": {
"node": ">=18",
"pnpm": ">=8"
@@ -66,6 +66,7 @@
"LICENSE"
],
"linux": {
"icon": "build/icon.icns",
"category": "Network",
"maintainer": "vendicated+vesktop@riseup.net",
"target": [
@@ -79,7 +80,8 @@
"GenericName": "Internet Messenger",
"Type": "Application",
"Categories": "Network;InstantMessaging;Chat;",
"Keywords": "discord;vencord;electron;chat;"
"Keywords": "discord;vencord;electron;chat;",
"WMClass": "VencordDesktop"
}
},
"mac": {
@@ -101,12 +103,11 @@
"win": {
"target": [
"nsis",
"portable"
"zip"
]
},
"publish": {
"provider": "github",
"releaseType": "release"
"provider": "github"
}
}
}

29
pnpm-lock.yaml generated
View File

@@ -6,8 +6,8 @@ settings:
dependencies:
arrpc:
specifier: github:OpenAsar/arrpc#bfcba7e3d6e6f7301a5699c4a1eb10c968e7b568
version: github.com/OpenAsar/arrpc/bfcba7e3d6e6f7301a5699c4a1eb10c968e7b568
specifier: github:OpenAsar/arrpc#89f4da610ccfac93f461826a446a17cd3b23953d
version: github.com/OpenAsar/arrpc/89f4da610ccfac93f461826a446a17cd3b23953d
devDependencies:
'@fal-works/esbuild-plugin-global-externals':
@@ -32,8 +32,8 @@ devDependencies:
specifier: ^16.3.1
version: 16.3.1
electron:
specifier: ^25.4.0
version: 25.4.0
specifier: ^25.8.4
version: 25.8.4
electron-builder:
specifier: ^24.6.3
version: 24.6.3
@@ -1245,6 +1245,7 @@ packages:
/boolean@3.2.0:
resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
requiresBuild: true
dev: true
optional: true
@@ -1637,6 +1638,7 @@ packages:
/detect-node@2.1.0:
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
requiresBuild: true
dev: true
optional: true
@@ -1764,8 +1766,8 @@ packages:
- supports-color
dev: true
/electron@25.4.0:
resolution: {integrity: sha512-VLTRxDhL4UvQbqM7pTNENnJo62cdAPZT92N+B7BZQ5Xfok1wuVPEewIjBot4K7U3EpLUuHn1veeLzho3ihiP+Q==}
/electron@25.8.4:
resolution: {integrity: sha512-hUYS3RGdaa6E1UWnzeGnsdsBYOggwMMg4WGxNGvAoWtmRrr6J1BsjFW/yRq4WsJHJce2HdzQXtz4OGXV6yUCLg==}
engines: {node: '>= 12.20.55'}
hasBin: true
requiresBuild: true
@@ -1863,6 +1865,7 @@ packages:
/es6-error@4.1.1:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
requiresBuild: true
dev: true
optional: true
@@ -3058,6 +3061,7 @@ packages:
/json-stringify-safe@5.0.1:
resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
requiresBuild: true
dev: true
optional: true
@@ -3172,6 +3176,7 @@ packages:
/matcher@3.0.0:
resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
engines: {node: '>=10'}
requiresBuild: true
dependencies:
escape-string-regexp: 4.0.0
dev: true
@@ -3680,6 +3685,7 @@ packages:
/roarr@2.15.4:
resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
engines: {node: '>=8.0'}
requiresBuild: true
dependencies:
boolean: 3.2.0
detect-node: 2.1.0
@@ -3743,6 +3749,7 @@ packages:
/semver-compare@1.0.0:
resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
requiresBuild: true
dev: true
optional: true
@@ -3762,6 +3769,7 @@ packages:
/serialize-error@7.0.1:
resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
engines: {node: '>=10'}
requiresBuild: true
dependencies:
type-fest: 0.13.1
dev: true
@@ -3889,6 +3897,7 @@ packages:
/sprintf-js@1.1.2:
resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==}
requiresBuild: true
dev: true
optional: true
@@ -4115,6 +4124,7 @@ packages:
/type-fest@0.13.1:
resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
engines: {node: '>=10'}
requiresBuild: true
dev: true
optional: true
@@ -4356,10 +4366,11 @@ packages:
engines: {node: '>=10'}
dev: true
github.com/OpenAsar/arrpc/bfcba7e3d6e6f7301a5699c4a1eb10c968e7b568:
resolution: {tarball: https://codeload.github.com/OpenAsar/arrpc/tar.gz/bfcba7e3d6e6f7301a5699c4a1eb10c968e7b568}
github.com/OpenAsar/arrpc/89f4da610ccfac93f461826a446a17cd3b23953d:
resolution: {tarball: https://codeload.github.com/OpenAsar/arrpc/tar.gz/89f4da610ccfac93f461826a446a17cd3b23953d}
name: arrpc
version: 3.1.0
version: 3.2.0
hasBin: true
dependencies:
ws: 8.13.0
transitivePeerDependencies:

View File

@@ -23,11 +23,17 @@ let lastIndex: null | number = -1;
export function setBadgeCount(count: number) {
switch (process.platform) {
case "darwin":
case "linux":
if (count === -1) count = 0;
app.setBadgeCount(count);
break;
case "darwin":
if (count === 0) {
app.dock.setBadge("");
break;
}
app.dock.setBadge(count === -1 ? "•" : count.toString());
break;
case "win32":
const [index, description] = getBadgeIndexAndDescription(count);
if (lastIndex === index) break;

View File

@@ -11,6 +11,7 @@ export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR || join(app.getPath("u
export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings");
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

View File

@@ -9,7 +9,7 @@ import { BrowserWindow } from "electron/main";
import { copyFileSync, mkdirSync, readdirSync } from "fs";
import { join } from "path";
import { SplashProps } from "shared/browserWinProperties";
import { VIEW_DIR } from "shared/paths";
import { ICON_PATH, VIEW_DIR } from "shared/paths";
import { autoStart } from "./autoStart";
import { DATA_DIR } from "./constants";
@@ -31,7 +31,8 @@ export function createFirstLaunchTour() {
frame: true,
autoHideMenuBar: true,
height: 470,
width: 550
width: 550,
icon: ICON_PATH
});
makeLinksOpenExternally(win);

View File

@@ -4,8 +4,9 @@
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { app, dialog, ipcMain, session, shell } from "electron";
import { existsSync, readFileSync, watch } from "fs";
import { execFile } from "child_process";
import { app, dialog, RelaunchOptions, session, shell } from "electron";
import { mkdirSync, readFileSync, watch } from "fs";
import { open, readFile } from "fs/promises";
import { release } from "os";
import { join } from "path";
@@ -14,69 +15,76 @@ 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 } from "./constants";
import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants";
import { mainWin } from "./mainWindow";
import { Settings } from "./settings";
import { handle, handleSync } from "./utils/ipcWrappers";
import { isValidVencordInstall } from "./utils/vencordLoader";
ipcMain.on(IpcEvents.GET_VENCORD_PRELOAD_FILE, e => {
e.returnValue = join(VENCORD_FILES_DIR, "preload.js");
});
handleSync(IpcEvents.GET_VENCORD_PRELOAD_FILE, () => join(VENCORD_FILES_DIR, "vencordDesktopPreload.js"));
handleSync(IpcEvents.GET_VENCORD_RENDERER_SCRIPT, () =>
readFileSync(join(VENCORD_FILES_DIR, "vencordDesktopRenderer.js"), "utf-8")
);
ipcMain.on(IpcEvents.GET_VENCORD_RENDERER_SCRIPT, e => {
e.returnValue = readFileSync(join(VENCORD_FILES_DIR, "vencordDesktopRenderer.js"), "utf-8");
});
handleSync(IpcEvents.GET_RENDERER_SCRIPT, () => readFileSync(join(__dirname, "renderer.js"), "utf-8"));
handleSync(IpcEvents.GET_RENDERER_CSS_FILE, () => join(__dirname, "renderer.css"));
ipcMain.on(IpcEvents.GET_RENDERER_SCRIPT, e => {
e.returnValue = readFileSync(join(__dirname, "renderer.js"), "utf-8");
});
handleSync(IpcEvents.GET_SETTINGS, () => Settings.plain);
handleSync(IpcEvents.GET_VERSION, () => app.getVersion());
ipcMain.on(IpcEvents.GET_RENDERER_CSS_FILE, e => {
e.returnValue = join(__dirname, "renderer.css");
});
handleSync(
IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY,
() => process.platform === "win32" && Number(release().split(".").pop()) >= 22621
);
ipcMain.on(IpcEvents.GET_SETTINGS, e => {
e.returnValue = Settings.plain;
});
handleSync(IpcEvents.AUTOSTART_ENABLED, () => autoStart.isEnabled());
handle(IpcEvents.ENABLE_AUTOSTART, autoStart.enable);
handle(IpcEvents.DISABLE_AUTOSTART, autoStart.disable);
ipcMain.on(IpcEvents.GET_VERSION, e => {
e.returnValue = app.getVersion();
});
ipcMain.on(IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY, e => {
e.returnValue = process.platform === "win32" && Number(release().split(".").pop()) >= 22621;
});
ipcMain.on(IpcEvents.AUTOSTART_ENABLED, e => {
e.returnValue = autoStart.isEnabled();
});
ipcMain.handle(IpcEvents.ENABLE_AUTOSTART, autoStart.enable);
ipcMain.handle(IpcEvents.DISABLE_AUTOSTART, autoStart.disable);
ipcMain.handle(IpcEvents.SET_SETTINGS, (_, settings: typeof Settings.store, path?: string) => {
handle(IpcEvents.SET_SETTINGS, (_, settings: typeof Settings.store, path?: string) => {
Settings.setData(settings, path);
});
ipcMain.handle(IpcEvents.RELAUNCH, () => {
app.relaunch();
handle(IpcEvents.RELAUNCH, () => {
const options: RelaunchOptions = {
args: process.argv.slice(1).concat(["--relaunch"])
};
if (app.isPackaged && process.env.APPIMAGE) {
execFile(process.env.APPIMAGE, options.args);
} else {
app.relaunch(options);
}
app.exit();
});
ipcMain.handle(IpcEvents.SHOW_ITEM_IN_FOLDER, (_, path) => {
handle(IpcEvents.SHOW_ITEM_IN_FOLDER, (_, path) => {
shell.showItemInFolder(path);
});
ipcMain.handle(IpcEvents.FOCUS, () => {
handle(IpcEvents.FOCUS, () => {
if (process.platform === "win32") mainWin.minimize(); // Windows is weird
mainWin.restore();
mainWin.show();
});
ipcMain.handle(IpcEvents.CLOSE, e => {
e.sender.close();
handle(IpcEvents.CLOSE, e => {
mainWin.close();
});
ipcMain.handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => {
handle(IpcEvents.MINIMIZE, e => {
mainWin.minimize();
});
handle(IpcEvents.MAXIMIZE, e => {
if (mainWin.isMaximized()) {
mainWin.unmaximize();
} else {
mainWin.maximize();
}
});
handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => {
const ses = session.defaultSession;
const available = ses.availableSpellCheckerLanguages;
@@ -84,29 +92,27 @@ ipcMain.handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => {
if (applicable.length) ses.setSpellCheckerLanguages(applicable);
});
ipcMain.handle(IpcEvents.SPELLCHECK_REPLACE_MISSPELLING, (e, word: string) => {
handle(IpcEvents.SPELLCHECK_REPLACE_MISSPELLING, (e, word: string) => {
e.sender.replaceMisspelling(word);
});
ipcMain.handle(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, (e, word: string) => {
handle(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, (e, word: string) => {
e.sender.session.addWordToSpellCheckerDictionary(word);
});
ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
const res = await dialog.showOpenDialog(mainWin!, {
properties: ["openDirectory"]
});
if (!res.filePaths.length) return "cancelled";
const dir = res.filePaths[0];
for (const file of ["vencordDesktopMain.js", "preload.js", "vencordDesktopRenderer.js", "renderer.css"]) {
if (!existsSync(join(dir, file))) return "invalid";
}
if (!isValidVencordInstall(dir)) return "invalid";
return dir;
});
ipcMain.handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count));
handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count));
function readCss() {
return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => "");
@@ -122,3 +128,12 @@ open(VENCORD_QUICKCSS_FILE, "a+").then(fd => {
}, 50)
);
});
mkdirSync(VENCORD_THEMES_DIR, { recursive: true });
watch(
VENCORD_THEMES_DIR,
{ persistent: false },
debounce(() => {
mainWin?.webContents.postMessage("VencordThemeUpdate", void 0);
})
);

View File

@@ -147,6 +147,8 @@ async function clearData(win: BrowserWindow) {
app.quit();
}
type MenuItemList = Array<MenuItemConstructorOptions | false>;
function initMenuBar(win: BrowserWindow) {
const isWindows = process.platform === "win32";
const isDarwin = process.platform === "darwin";
@@ -181,14 +183,38 @@ function initMenuBar(win: BrowserWindow) {
app.quit();
}
},
isDarwin && {
label: "Hide",
role: "hide"
},
isDarwin && {
label: "Hide others",
role: "hideOthers"
},
...(!isDarwin
? []
: ([
{
type: "separator"
},
{
label: "Settings",
accelerator: "CmdOrCtrl+,",
async click() {
mainWin.webContents.executeJavaScript(
"Vencord.Webpack.Common.SettingsRouter.open('My Account')"
);
}
},
{
type: "separator"
},
{
label: "Hide Vesktop", // Should probably remove the label, but it says "Hide VencordDesktop" instead of "Hide Vesktop"
role: "hide"
},
{
role: "hideOthers"
},
{
role: "unhide"
},
{
type: "separator"
}
] satisfies MenuItemList)),
{
label: "Quit",
accelerator: wantCtrlQ ? "CmdOrCtrl+Q" : void 0,
@@ -213,7 +239,7 @@ function initMenuBar(win: BrowserWindow) {
role: "zoomIn",
visible: false
}
] satisfies Array<MenuItemConstructorOptions | false>;
] satisfies MenuItemList;
const menu = Menu.buildFromTemplate([
{
@@ -315,8 +341,11 @@ function createMainWindow() {
removeSettingsListeners();
removeVencordSettingsListeners();
const { staticTitle, transparencyOption, enableMenu } = Settings.store;
const { staticTitle, transparencyOption, enableMenu, discordWindowsTitleBar } = Settings.store;
const { frameless, macosTranslucency } = VencordSettings.store;
const noFrame = frameless === true || (process.platform === "win32" && discordWindowsTitleBar === true);
const win = (mainWin = new BrowserWindow({
show: false,
webPreferences: {
@@ -328,7 +357,7 @@ function createMainWindow() {
spellcheck: true
},
icon: ICON_PATH,
frame: frameless !== true,
frame: !noFrame,
...(transparencyOption && transparencyOption !== "none"
? {
backgroundColor: "#00000000",
@@ -336,7 +365,7 @@ function createMainWindow() {
transparent: true
}
: {}),
...(staticTitle ? { title: "Vencord" } : {}),
...(staticTitle ? { title: "Vesktop" } : {}),
...(macosTranslucency
? {
vibrancy: "sidebar",

View File

@@ -4,12 +4,14 @@
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { desktopCapturer, ipcMain, session, Streams } from "electron";
import { desktopCapturer, session, Streams } from "electron";
import type { StreamPick } from "renderer/components/ScreenSharePicker";
import { IpcEvents } from "shared/IpcEvents";
import { handle } from "./utils/ipcWrappers";
export function registerScreenShareHandler() {
ipcMain.handle(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, async (_, id: string) => {
handle(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, async (_, id: string) => {
const sources = await desktopCapturer.getSources({
types: ["window", "screen"],
thumbnailSize: {
@@ -29,12 +31,22 @@ export function registerScreenShareHandler() {
}
});
const isWayland =
process.platform === "linux" &&
(process.env.XDG_SESSION_TYPE === "wayland" || !!process.env.WAYLAND_DISPLAY);
const data = sources.map(({ id, name, thumbnail }) => ({
id,
name,
url: thumbnail.toDataURL()
}));
if (isWayland) {
const video = data[0];
callback(video ? { video } : {});
return;
}
const choice = await request.frame
.executeJavaScript(`Vesktop.Components.ScreenShare.openScreenSharePicker(${JSON.stringify(data)})`)
.then(e => e as StreamPick)

View File

@@ -7,10 +7,13 @@
import { BrowserWindow } from "electron";
import { join } from "path";
import { SplashProps } from "shared/browserWinProperties";
import { VIEW_DIR } from "shared/paths";
import { ICON_PATH, VIEW_DIR } from "shared/paths";
export function createSplashWindow() {
const splash = new BrowserWindow(SplashProps);
const splash = new BrowserWindow({
...SplashProps,
icon: ICON_PATH
});
splash.loadFile(join(VIEW_DIR, "splash.html"));

View File

@@ -0,0 +1,36 @@
/*
* SPDX-License-Identifier: GPL-3.0
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { ipcMain, IpcMainEvent, IpcMainInvokeEvent, WebFrameMain } from "electron";
import { IpcEvents } from "shared/IpcEvents";
export function validateSender(frame: WebFrameMain) {
const { hostname, protocol } = new URL(frame.url);
if (protocol === "file:") return;
switch (hostname) {
case "discord.com":
case "ptb.discord.com":
case "canary.discord.com":
break;
default:
throw new Error("ipc: Disallowed host " + hostname);
}
}
export function handleSync(event: IpcEvents, cb: (e: IpcMainEvent, ...args: any[]) => any) {
ipcMain.on(event, (e, ...args) => {
validateSender(e.senderFrame);
e.returnValue = cb(e, ...args);
});
}
export function handle(event: IpcEvents, cb: (e: IpcMainInvokeEvent, ...args: any[]) => any) {
ipcMain.handle(event, (e, ...args) => {
validateSender(e.senderFrame);
return cb(e, ...args);
});
}

View File

@@ -13,7 +13,12 @@ import { downloadFile, simpleGet } from "./http";
const API_BASE = "https://api.github.com";
const FILES_TO_DOWNLOAD = ["vencordDesktopMain.js", "preload.js", "vencordDesktopRenderer.js", "renderer.css"];
export const FILES_TO_DOWNLOAD = [
"vencordDesktopMain.js",
"vencordDesktopPreload.js",
"vencordDesktopRenderer.js",
"vencordDesktopRenderer.css"
];
export interface ReleaseData {
name: string;
@@ -50,8 +55,12 @@ export async function downloadVencordFiles() {
);
}
export function isValidVencordInstall(dir: string) {
return FILES_TO_DOWNLOAD.every(f => existsSync(join(dir, f)));
}
export async function ensureVencordFiles() {
if (existsSync(join(VENCORD_FILES_DIR, "vencordDesktopMain.js"))) return;
if (isValidVencordInstall(VENCORD_FILES_DIR)) return;
mkdirSync(VENCORD_FILES_DIR, { recursive: true });
await downloadVencordFiles();

View File

@@ -51,7 +51,10 @@ export const VesktopNative = {
addToDictionary: (word: string) => invoke<void>(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, word)
},
win: {
focus: () => invoke<void>(IpcEvents.FOCUS)
focus: () => invoke<void>(IpcEvents.FOCUS),
close: () => invoke<void>(IpcEvents.CLOSE),
minimize: () => invoke<void>(IpcEvents.MINIMIZE),
maximize: () => invoke<void>(IpcEvents.MAXIMIZE)
},
capturer: {
getLargeThumbnail: (id: string) => invoke<string>(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id)

View File

@@ -7,10 +7,10 @@
import "./settings.css";
import { Margins } from "@vencord/types/utils";
import { Button, Forms, Select, Switch, Text, useState } from "@vencord/types/webpack/common";
import { Button, Forms, Select, Switch, Text, Toasts, useState } from "@vencord/types/webpack/common";
import { setBadge } from "renderer/appBadge";
import { useSettings } from "renderer/settings";
import { isMac } from "renderer/utils";
import { isMac, isWindows } from "renderer/utils";
import { isTruthy } from "shared/utils/guards";
export default function SettingsUi() {
@@ -21,6 +21,11 @@ export default function SettingsUi() {
const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled());
const allSwitches: Array<false | [keyof typeof Settings, string, string, boolean?, (() => boolean)?]> = [
isWindows && [
"discordWindowsTitleBar",
"Discord Titlebar",
"Use Discord's custom title bar instead of the Windows one. Requires a full restart."
],
!isMac && ["tray", "Tray Icon", "Add a tray icon for Vesktop", true],
!isMac && [
"minimizeToTray",
@@ -35,13 +40,13 @@ export default function SettingsUi() {
"Disable minimum window size",
"Allows you to make the window as small as your heart desires"
],
["staticTitle", "Static Title", 'Makes the window title "Vesktop" instead of changing to the current page'],
["enableMenu", "Enable Menu Bar", "Enables the application menu bar. Press ALT to toggle visibility."],
[
"openLinksWithElectron",
"Open Links in app (experimental)",
"Opens links in a new Vesktop window instead of your web browser"
],
["staticTitle", "Static Title", 'Makes the window title "Vencord" instead of changing to the current page'],
["enableMenu", "Enable Menu Bar", "Enables the application menu bar. Press ALT to toggle visibility."]
]
];
const switches = allSwitches.filter(isTruthy);
@@ -164,8 +169,14 @@ export default function SettingsUi() {
const choice = await VesktopNative.fileManager.selectVencordDir();
switch (choice) {
case "cancelled":
return;
case "invalid":
// TODO
Toasts.show({
message:
"You did not choose a valid Vencord install. Make sure you're selecting the dist dir!",
id: Toasts.genId(),
type: Toasts.Type.FAILURE
});
return;
}
Settings.vencordDir = choice;

View File

@@ -3,3 +3,8 @@
[class|=listItem]:has(+ [class|=listItem] [data-list-item-id=guildsnav___app-download-button]) {
display: none;
}
/* FIXME: Remove after 23/08/23 */
.vc-desktop-settings {
display: none;
}

View File

@@ -14,6 +14,7 @@ export * as Components from "./components";
import { findByPropsLazy } from "@vencord/types/webpack";
import { FluxDispatcher } from "@vencord/types/webpack/common";
import SettingsUi from "./components/Settings";
import { Settings } from "./settings";
export { Settings };
@@ -35,6 +36,17 @@ export async function openInviteModal(code: string) {
return true;
}
const customSettingsSections = (
Vencord.Plugins.plugins.Settings as any as { customSections: ((ID: Record<string, unknown>) => any)[] }
).customSections;
customSettingsSections.push(() => ({
section: "Vesktop",
label: "Vesktop Settings",
element: SettingsUi,
className: "vc-vesktop-settings"
}));
const arRPC = Vencord.Plugins.plugins["WebRichPresence (arRPC)"];
arRPC.required = !!Settings.store.arRPC;

View File

@@ -7,3 +7,4 @@
// TODO: Possibly auto generate glob if we have more patches in the future
import "./spellCheck";
import "./platformClass";
import "./windowsTitleBar";

View File

@@ -4,6 +4,9 @@
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { Settings } from "renderer/settings";
import { isMac, isWindows } from "renderer/utils";
import { addPatch } from "./shared";
addPatch({
@@ -18,5 +21,9 @@ addPatch({
}
],
getPlatformClass: () => (navigator.platform.toLowerCase().startsWith("mac") ? "platform-osx" : "platform-web")
getPlatformClass() {
if (isMac) return "platform-osx";
if (isWindows && Settings.store.discordWindowsTitleBar) return "platform-win";
return "platform-web";
}
});

View File

@@ -0,0 +1,30 @@
/*
* SPDX-License-Identifier: GPL-3.0
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { Settings } from "renderer/settings";
import { addPatch } from "./shared";
if (Settings.store.discordWindowsTitleBar)
addPatch({
patches: [
{
find: ".wordmarkWindows",
replacement: [
{
// TODO: Fix eslint rule
// eslint-disable-next-line no-useless-escape
match: /case \i\.\i\.WINDOWS:/,
replace: 'case "WEB":'
},
...["close", "minimize", "maximize"].map(op => ({
match: new RegExp(String.raw`\i\.\i\.${op}\b`),
replace: `VesktopNative.win.${op}`
}))
]
}
]
});

View File

@@ -16,6 +16,8 @@ export const enum IpcEvents {
RELAUNCH = "VCD_RELAUNCH",
CLOSE = "VCD_CLOSE",
FOCUS = "VCD_FOCUS",
MINIMIZE = "VCD_MINIMIZE",
MAXIMIZE = "VCD_MAXIMIZE",
SHOW_ITEM_IN_FOLDER = "VCD_SHOW_ITEM_IN_FOLDER",
GET_SETTINGS = "VCD_GET_SETTINGS",

View File

@@ -7,21 +7,23 @@
import type { Rectangle } from "electron";
export interface Settings {
transparencyOption?: "none" | "mica" | "tabbed" | "acrylic";
maximized?: boolean;
minimized?: boolean;
windowBounds?: Rectangle;
discordBranch?: "stable" | "canary" | "ptb";
openLinksWithElectron?: boolean;
vencordDir?: string;
disableMinSize?: boolean;
transparencyOption?: "none" | "mica" | "tabbed" | "acrylic";
tray?: boolean;
minimizeToTray?: boolean;
skippedUpdate?: string;
openLinksWithElectron?: boolean;
staticTitle?: boolean;
enableMenu?: boolean;
arRPC?: boolean;
appBadge?: boolean;
discordWindowsTitleBar?: boolean;
maximized?: boolean;
minimized?: boolean;
windowBounds?: Rectangle;
disableMinSize?: boolean;
skippedUpdate?: string;
firstLaunch?: boolean;
}

View File

@@ -4,13 +4,14 @@
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { app, BrowserWindow, ipcMain, shell } from "electron";
import { app, BrowserWindow, shell } from "electron";
import { Settings } from "main/settings";
import { handle } from "main/utils/ipcWrappers";
import { makeLinksOpenExternally } from "main/utils/makeLinksOpenExternally";
import { githubGet, ReleaseData } from "main/utils/vencordLoader";
import { join } from "path";
import { IpcEvents } from "shared/IpcEvents";
import { VIEW_DIR } from "shared/paths";
import { ICON_PATH, VIEW_DIR } from "shared/paths";
export interface UpdateData {
currentVersion: string;
@@ -20,8 +21,8 @@ export interface UpdateData {
let updateData: UpdateData;
ipcMain.handle(IpcEvents.UPDATER_GET_DATA, () => updateData);
ipcMain.handle(IpcEvents.UPDATER_DOWNLOAD, () => {
handle(IpcEvents.UPDATER_GET_DATA, () => updateData);
handle(IpcEvents.UPDATER_DOWNLOAD, () => {
const portable = !!process.env.PORTABLE_EXECUTABLE_FILE;
const { assets } = updateData.release;
@@ -50,7 +51,7 @@ ipcMain.handle(IpcEvents.UPDATER_DOWNLOAD, () => {
shell.openExternal(url);
});
ipcMain.handle(IpcEvents.UPDATE_IGNORE, () => {
handle(IpcEvents.UPDATE_IGNORE, () => {
Settings.store.skippedUpdate = updateData.latestVersion;
});
@@ -107,7 +108,8 @@ function openNewUpdateWindow() {
nodeIntegration: false,
contextIsolation: true,
sandbox: true
}
},
icon: ICON_PATH
});
makeLinksOpenExternally(win);