Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add global shortcuts #326

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
26 changes: 25 additions & 1 deletion src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@
if (process.platform === "linux") import("./venmic");

import { execFile } from "child_process";
import { app, BrowserWindow, clipboard, dialog, nativeImage, RelaunchOptions, session, shell } from "electron";
import {
app,
BrowserWindow,
clipboard,
dialog,
globalShortcut,
nativeImage,
RelaunchOptions,
session,
shell
} from "electron";
import { mkdirSync, readFileSync, watch } from "fs";
import { open, readFile } from "fs/promises";
import { release } from "os";
Expand Down Expand Up @@ -130,6 +140,20 @@ handle(IpcEvents.CLIPBOARD_COPY_IMAGE, async (_, buf: ArrayBuffer, src: string)
});
});

const registered_keybinds = {};

handle(IpcEvents.KEYBIND_REGISTER, (_, id: string, shortcut: string) => {
globalShortcut.register(shortcut, () => {
// false here implies `keyup`
// electron's global shortcut system doesn't really register keyup or down as far as i can tell
mainWin.webContents.executeJavaScript(`Vesktop.keybindCallbacks["${id}"](false)`);
});
registered_keybinds[id] = shortcut;
});
handle(IpcEvents.KEYBIND_UNREGISTER, (_, id: string) => {
globalShortcut.unregister(registered_keybinds[id]);
});

function readCss() {
return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => "");
}
Expand Down
4 changes: 4 additions & 0 deletions src/preload/VesktopNative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,9 @@ export const VesktopNative = {
clipboard: {
copyImage: (imageBuffer: Uint8Array, imageSrc: string) =>
invoke<void>(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc)
},
keybind: {
register: (id: string, shortcut: string) => invoke<void>(IpcEvents.KEYBIND_REGISTER, id, shortcut),
uregister: (id: string) => invoke<void>(IpcEvents.KEYBIND_UNREGISTER, id)
}
};
2 changes: 2 additions & 0 deletions src/renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export { Settings };

const InviteActions = findByPropsLazy("resolveInvite");

export const keybindCallbacks: { [id: string]: Function } = {};

export async function openInviteModal(code: string) {
const { invite } = await InviteActions.resolveInvite(code, "Desktop Modal");
if (!invite) return false;
Expand Down
1 change: 1 addition & 0 deletions src/renderer/patches/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ import "./platformClass";
import "./screenShareAudio";
import "./spellCheck";
import "./windowsTitleBar";
import "./keybinds";
45 changes: 45 additions & 0 deletions src/renderer/patches/keybinds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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 { keybindCallbacks } from "renderer";

import { addPatch } from "./shared";

addPatch({
patches: [
{
find: ".default.Messages.KEYBINDS,children:",
replacement: {
match: /.\.isPlatformEmbedded/,
replace: "true"
}
},
{
find: "[kb store] KeybindStore",
replacement: {
match: /(inputEventRegister\(parseInt\((.{1,2})\),(.{1,2}),(.{1,2}),(.{1,2})\);else\{)([^;]*;[^;]*;.{1,2}\.keyup&&.{1,2}\.bindGlobal\(\(0,(.{1,2}\.toString)\))/,
tuxinal marked this conversation as resolved.
Show resolved Hide resolved
replace: "$1$self.registerKeybind($2,$3,$4,$7);return;$6"
}
},
{
find: "[kb store] KeybindStore",
replacement: {
tuxinal marked this conversation as resolved.
Show resolved Hide resolved
// WHY IS THE RADIX SPEICIFIED
tuxinal marked this conversation as resolved.
Show resolved Hide resolved
match: /(inputEventUnregister\(parseInt\((.{1,2}),10\)\);else\{)/,
replace: "$1$self.unregisterKeybind($2);return;"
}
}
],

registerKeybind: function (id, shortcut, callback, toString) {
keybindCallbacks[id] = callback;
VesktopNative.keybind.register(id, toString(shortcut));
},
unregisterKeybind: function (id) {
delete keybindCallbacks[id];
VesktopNative.keybind.uregister(id);
}
});
4 changes: 3 additions & 1 deletion src/shared/IpcEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ export const enum IpcEvents {

ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY",

CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE"
CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE",
KEYBIND_REGISTER = "VCD_KEYBIND_REGISTER",
KEYBIND_UNREGISTER = "VCD_KEYBIND_UNREGISTER"
}