Merge branch 'main' into main

This commit is contained in:
V 2024-01-07 03:05:33 +01:00 committed by GitHub
commit 8c33b8f42b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 111 additions and 60 deletions

View file

@ -3,14 +3,14 @@
Vesktop is a cross platform desktop app aiming to give you a snappier Discord experience with [Vencord](https://github.com/Vendicated/Vencord) pre-installed Vesktop is a cross platform desktop app aiming to give you a snappier Discord experience with [Vencord](https://github.com/Vendicated/Vencord) pre-installed
**Not yet supported**: **Not yet supported**:
- Global Keybinds
- Global Keybinds
Bug reports, feature requests & contributions are highly appreciated!! Bug reports, feature requests & contributions are highly appreciated!!
![](https://github.com/Vencord/Vesktop/assets/45497981/8608a899-96a9-4027-9725-2cb02ba189fd) ![](https://github.com/Vencord/Vesktop/assets/45497981/8608a899-96a9-4027-9725-2cb02ba189fd)
![grafik](https://github.com/Vencord/Vesktop/assets/45497981/8701e5de-52c4-4346-a990-719cb971642e) ![grafik](https://github.com/Vencord/Vesktop/assets/45497981/8701e5de-52c4-4346-a990-719cb971642e)
## Installing ## Installing
### Windows ### Windows
@ -39,7 +39,7 @@ Download Vesktop-VERSION.rpm from [releases](https://github.com/Vencord/Vesktop/
#### Other #### Other
Either download Vesktop-VERSION.AppImage and just run it directly or grab Vesktop-VERSION.tar.gz, extract it somewhere and run `vencorddesktop`. Either download Vesktop-VERSION.AppImage and just run it directly or grab Vesktop-VERSION.tar.gz, extract it somewhere and run `vesktop`.
If other packages are created, feel free to open an issue and we'll link them here. If other packages are created, feel free to open an issue and we'll link them here.

View file

@ -1,8 +1,8 @@
!macro preInit !macro preInit
SetRegView 64 SetRegView 64
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
SetRegView 32 SetRegView 32
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\VencordDesktop" WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$LocalAppData\vesktop"
!macroend !macroend

View file

@ -1,5 +1,5 @@
{ {
"name": "VencordDesktop", "name": "vesktop",
"version": "0.4.4", "version": "0.4.4",
"private": true, "private": true,
"description": "", "description": "",
@ -27,7 +27,7 @@
"arrpc": "github:OpenAsar/arrpc#98879cae0565e6fce34e4cb6f544bf42c6a7e7c8" "arrpc": "github:OpenAsar/arrpc#98879cae0565e6fce34e4cb6f544bf42c6a7e7c8"
}, },
"optionalDependencies": { "optionalDependencies": {
"@vencord/venmic": "^2.1.3" "@vencord/venmic": "^3.2.0"
}, },
"devDependencies": { "devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2", "@fal-works/esbuild-plugin-global-externals": "^2.1.2",
@ -61,7 +61,7 @@
"pnpm": ">=8" "pnpm": ">=8"
}, },
"build": { "build": {
"appId": "dev.vencord.desktop", "appId": "dev.vencord.vesktop",
"productName": "Vesktop", "productName": "Vesktop",
"files": [ "files": [
"!*", "!*",
@ -110,8 +110,7 @@
"GenericName": "Internet Messenger", "GenericName": "Internet Messenger",
"Type": "Application", "Type": "Application",
"Categories": "Network;InstantMessaging;Chat;", "Categories": "Network;InstantMessaging;Chat;",
"Keywords": "discord;vencord;electron;chat;", "Keywords": "discord;vencord;electron;chat;"
"StartupWMClass": "VencordDesktop"
} }
}, },
"mac": { "mac": {

View file

@ -11,8 +11,8 @@ dependencies:
optionalDependencies: optionalDependencies:
'@vencord/venmic': '@vencord/venmic':
specifier: ^2.1.3 specifier: ^3.2.0
version: 2.1.4 version: 3.2.0
devDependencies: devDependencies:
'@fal-works/esbuild-plugin-global-externals': '@fal-works/esbuild-plugin-global-externals':
@ -793,8 +793,8 @@ packages:
type-fest: 3.13.1 type-fest: 3.13.1
dev: true dev: true
/@vencord/venmic@2.1.4: /@vencord/venmic@3.2.0:
resolution: {integrity: sha512-Or//CHB9QtMcUXoDagkq0IF/7R8r7IABCaLIPtG8HCKSuOOFgBJ54PItnPXCliNKXWpwsUxj5z1WlZ4/VdwZHg==} resolution: {integrity: sha512-z+Lgmr6IgjkPEIfFZ3ZwVV4aP/OFjnB6k6Ll5YpBPuDZOyqCbKTNLADApbZa/WxMfm7YpZ22g46X4FfizuprEQ==}
engines: {node: '>=14.15'} engines: {node: '>=14.15'}
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true

View file

@ -5,9 +5,25 @@
*/ */
import { app } from "electron"; import { app } from "electron";
import { existsSync, readdirSync, renameSync, rmdirSync } from "fs";
import { join } from "path"; import { join } from "path";
export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR || join(app.getPath("userData"), "VencordDesktop"); const LEGACY_DATA_DIR = join(app.getPath("appData"), "VencordDesktop", "VencordDesktop");
export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR || join(app.getPath("userData"));
// TODO: remove eventually
if (existsSync(LEGACY_DATA_DIR)) {
try {
console.warn("Detected legacy settings dir", LEGACY_DATA_DIR + ".", "migrating to", DATA_DIR);
for (const file of readdirSync(LEGACY_DATA_DIR)) {
renameSync(join(LEGACY_DATA_DIR, file), join(DATA_DIR, file));
}
rmdirSync(LEGACY_DATA_DIR);
} catch (e) {
console.error("Migration failed", e);
}
}
app.setPath("sessionData", join(DATA_DIR, "sessionData"));
export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings"); export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings");
export const VENCORD_QUICKCSS_FILE = join(VENCORD_SETTINGS_DIR, "quickCss.css"); 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_SETTINGS_FILE = join(VENCORD_SETTINGS_DIR, "settings.json");

View file

@ -14,7 +14,7 @@ import { ICON_PATH, VIEW_DIR } from "shared/paths";
import { autoStart } from "./autoStart"; import { autoStart } from "./autoStart";
import { DATA_DIR } from "./constants"; import { DATA_DIR } from "./constants";
import { createWindows } from "./mainWindow"; import { createWindows } from "./mainWindow";
import { Settings } from "./settings"; import { Settings, State } from "./settings";
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
interface Data { interface Data {
@ -44,9 +44,9 @@ export function createFirstLaunchTour() {
if (!msg.startsWith("form:")) return; if (!msg.startsWith("form:")) return;
const data = JSON.parse(msg.slice(5)) as Data; const data = JSON.parse(msg.slice(5)) as Data;
State.store.firstLaunch = false;
Settings.store.minimizeToTray = data.minimizeToTray; Settings.store.minimizeToTray = data.minimizeToTray;
Settings.store.discordBranch = data.discordBranch; Settings.store.discordBranch = data.discordBranch;
Settings.store.firstLaunch = false;
Settings.store.arRPC = data.richPresence; Settings.store.arRPC = data.richPresence;
if (data.autoStart) autoStart.enable(); if (data.autoStart) autoStart.enable();

View file

@ -6,7 +6,7 @@
import "./ipc"; import "./ipc";
import { app, BrowserWindow } from "electron"; import { app, BrowserWindow, nativeTheme } from "electron";
import { checkUpdates } from "updater/main"; import { checkUpdates } from "updater/main";
import { DATA_DIR } from "./constants"; import { DATA_DIR } from "./constants";
@ -14,7 +14,8 @@ import { createFirstLaunchTour } from "./firstLaunch";
import { createWindows, mainWin } from "./mainWindow"; import { createWindows, mainWin } from "./mainWindow";
import { registerMediaPermissionsHandler } from "./mediaPermissions"; import { registerMediaPermissionsHandler } from "./mediaPermissions";
import { registerScreenShareHandler } from "./screenShare"; import { registerScreenShareHandler } from "./screenShare";
import { Settings } from "./settings"; import { Settings, State } from "./settings";
import { isDeckGameMode } from "./utils/steamOS";
if (IS_DEV) { if (IS_DEV) {
require("source-map-support").install(); require("source-map-support").install();
@ -43,6 +44,9 @@ function init() {
"WinRetrieveSuggestionsOnlyOnDemand,HardwareMediaKeyHandling,MediaSessionService,WidgetLayering" "WinRetrieveSuggestionsOnlyOnDemand,HardwareMediaKeyHandling,MediaSessionService,WidgetLayering"
); );
// 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";
app.on("second-instance", (_event, _cmdLine, _cwd, data: any) => { app.on("second-instance", (_event, _cmdLine, _cwd, data: any) => {
if (data.IS_DEV) app.quit(); if (data.IS_DEV) app.quit();
else if (mainWin) { else if (mainWin) {
@ -54,7 +58,7 @@ function init() {
app.whenReady().then(async () => { app.whenReady().then(async () => {
checkUpdates(); checkUpdates();
if (process.platform === "win32") app.setAppUserModelId("dev.vencord.desktop"); if (process.platform === "win32") app.setAppUserModelId("dev.vencord.vesktop");
registerScreenShareHandler(); registerScreenShareHandler();
registerMediaPermissionsHandler(); registerMediaPermissionsHandler();
@ -80,7 +84,7 @@ if (!app.requestSingleInstanceLock({ IS_DEV })) {
} }
async function bootstrap() { async function bootstrap() {
if (!Object.hasOwn(Settings.store, "firstLaunch")) { if (!Object.hasOwn(State.store, "firstLaunch")) {
createFirstLaunchTour(); createFirstLaunchTour();
} else { } else {
createWindows(); createWindows();

View file

@ -34,7 +34,7 @@ import {
UserAgent, UserAgent,
VENCORD_FILES_DIR VENCORD_FILES_DIR
} from "./constants"; } from "./constants";
import { Settings, VencordSettings } from "./settings"; import { Settings, State, VencordSettings } from "./settings";
import { createSplashWindow } from "./splash"; import { createSplashWindow } from "./splash";
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS"; import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS";
@ -210,7 +210,6 @@ function initMenuBar(win: BrowserWindow) {
type: "separator" type: "separator"
}, },
{ {
label: "Hide Vesktop", // Should probably remove the label, but it says "Hide VencordDesktop" instead of "Hide Vesktop"
role: "hide" role: "hide"
}, },
{ {
@ -268,7 +267,7 @@ function getWindowBoundsOptions(): BrowserWindowConstructorOptions {
// We want the default window behaivour to apply in game mode since it expects everything to be fullscreen and maximized. // We want the default window behaivour to apply in game mode since it expects everything to be fullscreen and maximized.
if (isDeckGameMode) return {}; if (isDeckGameMode) return {};
const { x, y, width, height } = Settings.store.windowBounds ?? {}; const { x, y, width, height } = State.store.windowBounds ?? {};
const options = { const options = {
width: width ?? DEFAULT_WIDTH, width: width ?? DEFAULT_WIDTH,
@ -313,8 +312,8 @@ function getDarwinOptions(): BrowserWindowConstructorOptions {
function initWindowBoundsListeners(win: BrowserWindow) { function initWindowBoundsListeners(win: BrowserWindow) {
const saveState = () => { const saveState = () => {
Settings.store.maximized = win.isMaximized(); State.store.maximized = win.isMaximized();
Settings.store.minimized = win.isMinimized(); State.store.minimized = win.isMinimized();
}; };
win.on("maximize", saveState); win.on("maximize", saveState);
@ -322,7 +321,7 @@ function initWindowBoundsListeners(win: BrowserWindow) {
win.on("unmaximize", saveState); win.on("unmaximize", saveState);
const saveBounds = () => { const saveBounds = () => {
Settings.store.windowBounds = win.getBounds(); State.store.windowBounds = win.getBounds();
}; };
win.on("resize", saveBounds); win.on("resize", saveBounds);
@ -396,7 +395,12 @@ function createMainWindow() {
...(transparencyOption && ...(transparencyOption &&
transparencyOption !== "none" && { transparencyOption !== "none" && {
backgroundColor: "#00000000", backgroundColor: "#00000000",
backgroundMaterial: transparencyOption, backgroundMaterial: transparencyOption
}),
// Fix transparencyOption for custom discord titlebar
...(discordWindowsTitleBar &&
transparencyOption &&
transparencyOption !== "none" && {
transparent: true transparent: true
}), }),
...(staticTitle && { title: "Vesktop" }), ...(staticTitle && { title: "Vesktop" }),
@ -454,7 +458,9 @@ export async function createWindows() {
mainWin.webContents.on("did-finish-load", () => { mainWin.webContents.on("did-finish-load", () => {
splash.destroy(); splash.destroy();
if (!startMinimized || isDeckGameMode) mainWin!.show(); if (State.store.maximized && !isDeckGameMode) {
mainWin!.maximize();
}
if (isDeckGameMode) { if (isDeckGameMode) {
// always use entire display // always use entire display
@ -464,7 +470,7 @@ export async function createWindows() {
} }
mainWin.once("show", () => { mainWin.once("show", () => {
if (Settings.store.maximized && !mainWin!.isMaximized() && !isDeckGameMode) { if (State.store.maximized && !mainWin!.isMaximized() && !isDeckGameMode) {
mainWin!.maximize(); mainWin!.maximize();
} }
}); });

View file

@ -4,14 +4,15 @@
* Copyright (c) 2023 Vendicated and Vencord contributors * Copyright (c) 2023 Vendicated and Vencord contributors
*/ */
import { mkdirSync, readFileSync, writeFileSync } from "fs"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import { dirname, join } from "path"; import { dirname, join } from "path";
import type { Settings as TSettings } from "shared/settings"; import type { Settings as TSettings, State as TState } from "shared/settings";
import { SettingsStore } from "shared/utils/SettingsStore"; import { SettingsStore } from "shared/utils/SettingsStore";
import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants"; import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants";
const SETTINGS_FILE = join(DATA_DIR, "settings.json"); const SETTINGS_FILE = join(DATA_DIR, "settings.json");
const STATE_FILE = join(DATA_DIR, "state.json");
function loadSettings<T extends object = any>(file: string, name: string) { function loadSettings<T extends object = any>(file: string, name: string) {
let settings = {} as T; let settings = {} as T;
@ -20,7 +21,7 @@ function loadSettings<T extends object = any>(file: string, name: string) {
try { try {
settings = JSON.parse(content); settings = JSON.parse(content);
} catch (err) { } catch (err) {
console.error(`Failed to parse ${name} settings.json:`, err); console.error(`Failed to parse ${name}.json:`, err);
} }
} catch {} } catch {}
@ -33,5 +34,25 @@ function loadSettings<T extends object = any>(file: string, name: string) {
return store; return store;
} }
export const Settings = loadSettings<TSettings>(SETTINGS_FILE, "Vesktop"); export const Settings = loadSettings<TSettings>(SETTINGS_FILE, "Vesktop settings");
export const VencordSettings = loadSettings<any>(VENCORD_SETTINGS_FILE, "Vencord"); export const VencordSettings = loadSettings<any>(VENCORD_SETTINGS_FILE, "Vencord settings");
if (Object.hasOwn(Settings.store, "firstLaunch") && !existsSync(STATE_FILE)) {
console.warn("legacy state in settings.json detected. migrating to state.json");
const state = {} as TState;
for (const prop of [
"firstLaunch",
"maximized",
"minimized",
"skippedUpdate",
"steamOSLayoutVersion",
"windowBounds"
]) {
state[prop] = Settings.plain[prop];
delete Settings.plain[prop];
}
Settings.markAsChanged();
writeFileSync(STATE_FILE, JSON.stringify(state, null, 4));
}
export const State = loadSettings<TState>(STATE_FILE, "Vesktop state");

View file

@ -9,7 +9,7 @@ import { writeFile } from "fs/promises";
import { join } from "path"; import { join } from "path";
import { MessageBoxChoice } from "../constants"; import { MessageBoxChoice } from "../constants";
import { Settings } from "../settings"; import { State } from "../settings";
// Bump this to re-show the prompt // Bump this to re-show the prompt
const layoutVersion = 2; const layoutVersion = 2;
@ -70,8 +70,8 @@ async function showLayout(appId: string) {
export async function askToApplySteamLayout(win: BrowserWindow) { export async function askToApplySteamLayout(win: BrowserWindow) {
const appId = getAppId(); const appId = getAppId();
if (!appId) return; if (!appId) return;
if (Settings.store.steamOSLayoutVersion === layoutVersion) return; if (State.store.steamOSLayoutVersion === layoutVersion) return;
const update = Boolean(Settings.store.steamOSLayoutVersion); const update = Boolean(State.store.steamOSLayoutVersion);
// Touch screen breaks in some menus when native touch mode is enabled on latest SteamOS beta, remove most of the update specific text once that's fixed. // Touch screen breaks in some menus when native touch mode is enabled on latest SteamOS beta, remove most of the update specific text once that's fixed.
const { response } = await dialog.showMessageBox(win, { const { response } = await dialog.showMessageBox(win, {
@ -87,8 +87,8 @@ ${update ? "Click" : "Tap"} no to keep your current layout.`,
type: "question" type: "question"
}); });
if (Settings.store.steamOSLayoutVersion !== layoutVersion) { if (State.store.steamOSLayoutVersion !== layoutVersion) {
Settings.store.steamOSLayoutVersion = layoutVersion; State.store.steamOSLayoutVersion = layoutVersion;
} }
if (response === MessageBoxChoice.Cancel) return; if (response === MessageBoxChoice.Cancel) return;

View file

@ -55,22 +55,17 @@ ipcMain.handle(
IpcEvents.VIRT_MIC_START, IpcEvents.VIRT_MIC_START,
(_, targets: string[]) => (_, targets: string[]) =>
obtainVenmic()?.link({ obtainVenmic()?.link({
props: targets.map(target => ({ key: "application.name", value: target })), include: targets.map(target => ({ key: "application.name", value: target })),
mode: "include" exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }]
}) })
); );
ipcMain.handle( ipcMain.handle(
IpcEvents.VIRT_MIC_START_SYSTEM, IpcEvents.VIRT_MIC_START_SYSTEM,
() => () =>
// @ts-expect-error venmic types are wrong. include is actually optional but typed as required in vemic
obtainVenmic()?.link({ obtainVenmic()?.link({
props: [ exclude: [{ key: "application.process.id", value: getRendererAudioServicePid() }]
{
key: "application.process.id",
value: getRendererAudioServicePid()
}
],
mode: "exclude"
}) })
); );

View file

@ -20,19 +20,22 @@ export interface Settings {
arRPC?: boolean; arRPC?: boolean;
appBadge?: boolean; appBadge?: boolean;
discordWindowsTitleBar?: boolean; discordWindowsTitleBar?: boolean;
maximized?: boolean;
minimized?: boolean;
windowBounds?: Rectangle;
disableMinSize?: boolean; disableMinSize?: boolean;
checkUpdates?: boolean; checkUpdates?: boolean;
skippedUpdate?: string;
firstLaunch?: boolean;
splashTheming?: boolean; splashTheming?: boolean;
splashColor?: string; splashColor?: string;
splashBackground?: string; splashBackground?: string;
}
export interface State {
maximized?: boolean;
minimized?: boolean;
windowBounds?: Rectangle;
skippedUpdate?: string;
firstLaunch?: boolean;
steamOSLayoutVersion?: number; steamOSLayoutVersion?: number;
} }

View file

@ -144,4 +144,11 @@ export class SettingsStore<T extends object> {
listeners.delete(cb); listeners.delete(cb);
if (!listeners.size) this.pathListeners.delete(path as string); if (!listeners.size) this.pathListeners.delete(path as string);
} }
/**
* Call all global change listeners
*/
public markAsChanged() {
this.globalListeners.forEach(cb => cb(this.plain, ""));
}
} }

View file

@ -5,7 +5,7 @@
*/ */
import { app, BrowserWindow, shell } from "electron"; import { app, BrowserWindow, shell } from "electron";
import { Settings } from "main/settings"; import { Settings, State } from "main/settings";
import { handle } from "main/utils/ipcWrappers"; import { handle } from "main/utils/ipcWrappers";
import { makeLinksOpenExternally } from "main/utils/makeLinksOpenExternally"; import { makeLinksOpenExternally } from "main/utils/makeLinksOpenExternally";
import { githubGet, ReleaseData } from "main/utils/vencordLoader"; import { githubGet, ReleaseData } from "main/utils/vencordLoader";
@ -52,7 +52,7 @@ handle(IpcEvents.UPDATER_DOWNLOAD, () => {
}); });
handle(IpcEvents.UPDATE_IGNORE, () => { handle(IpcEvents.UPDATE_IGNORE, () => {
Settings.store.skippedUpdate = updateData.latestVersion; State.store.skippedUpdate = updateData.latestVersion;
}); });
function isOutdated(oldVersion: string, newVersion: string) { function isOutdated(oldVersion: string, newVersion: string) {
@ -91,7 +91,7 @@ export async function checkUpdates() {
release: data release: data
}; };
if (Settings.store.skippedUpdate !== newVersion && isOutdated(oldVersion, newVersion)) { if (State.store.skippedUpdate !== newVersion && isOutdated(oldVersion, newVersion)) {
openNewUpdateWindow(); openNewUpdateWindow();
} }
} catch (e) { } catch (e) {