diff --git a/README.md b/README.md index a9aec6aa..4efc0143 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - Equicord preinstalled - Custom Splash animations from [this PR](https://github.com/Vencord/Vesktop/pull/355) - Tray Customization & Voice detection and Badge from [this PR](https://github.com/Vencord/Vesktop/pull/517) +- Global Keybind to Toggle voice status from [this PR](https://github.com/Vencord/Vesktop/pull/609) - Remove (#) title prefix when Notification Badge option is toggled from [this PR](https://github.com/Vencord/Vesktop/pull/686) **Not yet supported**: diff --git a/src/main/constants.ts b/src/main/constants.ts index dca18266..144180fd 100644 --- a/src/main/constants.ts +++ b/src/main/constants.ts @@ -75,3 +75,6 @@ export const enum MessageBoxChoice { Default, Cancel } + +export const isWayland = + process.platform === "linux" && (process.env.XDG_SESSION_TYPE === "wayland" || !!process.env.WAYLAND_DISPLAY); diff --git a/src/main/keybinds.ts b/src/main/keybinds.ts new file mode 100644 index 00000000..f7737626 --- /dev/null +++ b/src/main/keybinds.ts @@ -0,0 +1,80 @@ +/* + * 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 { spawnSync } from "node:child_process"; +import { constants, existsSync, open, unlinkSync } from "node:fs"; +import { join } from "node:path"; + +import { Socket } from "net"; +import { IpcEvents } from "shared/IpcEvents"; + +import { mainWin } from "./mainWindow"; + +const xdgRuntimeDir = process.env.XDG_RUNTIME_DIR || process.env.TMP || "/tmp"; +const socketFile = join(xdgRuntimeDir, "vesktop-ipc"); + +const Actions = new Set([IpcEvents.TOGGLE_SELF_DEAF, IpcEvents.TOGGLE_SELF_MUTE]); + +function createFIFO() { + if (existsSync(socketFile)) { + try { + unlinkSync(socketFile); + } catch (err) { + console.error("Failed to remove existing mkfifo file:", err); + return false; + } + } + + try { + spawnSync("mkfifo", [socketFile]); + } catch (err) { + console.error("Failed to create mkfifo while initializing keybinds:", err); + return false; + } + return true; +} + +function openFIFO() { + try { + open(socketFile, constants.O_RDONLY | constants.O_NONBLOCK, (err, fd) => { + if (err) { + console.error("Error opening pipe while initializing keybinds:", err); + return; + } + + const pipe = new Socket({ fd }); + pipe.on("data", data => { + const action = data.toString().trim(); + if (Actions.has(action as IpcEvents)) { + mainWin.webContents.send(action); + } + }); + + pipe.on("end", () => { + pipe.destroy(); + openFIFO(); + }); + }); + } catch (err) { + console.error("Can't open socket file.", err); + } +} + +function cleanup() { + try { + unlinkSync(socketFile); + } catch (err) { + console.error("Failed to remove mkfifo file:", err); + } +} + +process.on("exit", cleanup); + +export function initKeybinds() { + if (createFIFO()) { + openFIFO(); + } +} diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 02c46ec6..8be8aa6b 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -31,11 +31,13 @@ import { DATA_DIR, DEFAULT_HEIGHT, DEFAULT_WIDTH, + isWayland, MessageBoxChoice, MIN_HEIGHT, MIN_WIDTH, VENCORD_DIR } from "./constants"; +import { initKeybinds } from "./keybinds"; import { Settings, State, VencordSettings } from "./settings"; import { addSplashLog, splash } from "./splash"; import { setTrayIcon } from "./tray"; @@ -527,4 +529,5 @@ export async function createWindows() { }); initArRPC(); + if (isWayland) initKeybinds(); } diff --git a/src/main/screenShare.ts b/src/main/screenShare.ts index e30afb17..5ff22258 100644 --- a/src/main/screenShare.ts +++ b/src/main/screenShare.ts @@ -8,11 +8,9 @@ import { desktopCapturer, session, Streams } from "electron"; import type { StreamPick } from "renderer/components/ScreenSharePicker"; import { IpcEvents } from "shared/IpcEvents"; +import { isWayland } from "./constants"; import { handle } from "./utils/ipcWrappers"; -const isWayland = - process.platform === "linux" && (process.env.XDG_SESSION_TYPE === "wayland" || !!process.env.WAYLAND_DISPLAY); - export function registerScreenShareHandler() { handle(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, async (_, id: string) => { const sources = await desktopCapturer.getSources({ diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index a241d64e..829a4738 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -82,6 +82,14 @@ export const VesktopNative = { copyImage: (imageBuffer: Uint8Array, imageSrc: string) => invoke(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc) }, + voice: { + onToggleSelfMute: (listener: (...args: any[]) => void) => { + ipcRenderer.on(IpcEvents.TOGGLE_SELF_MUTE, listener); + }, + onToggleSelfDeaf: (listener: (...args: any[]) => void) => { + ipcRenderer.on(IpcEvents.TOGGLE_SELF_DEAF, listener); + } + }, tray: { setIcon: (iconURI: string) => invoke(IpcEvents.SET_TRAY_ICON, iconURI), getIcon: (iconName: string) => invoke(IpcEvents.GET_TRAY_ICON, iconName), diff --git a/src/renderer/index.ts b/src/renderer/index.ts index 0877d224..d9976808 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -60,6 +60,10 @@ VesktopNative.arrpc.onActivity(async data => { arRPC.handleEvent(new MessageEvent("message", { data })); }); +const VoiceActions = findByPropsLazy("toggleSelfMute"); +VesktopNative.voice.onToggleSelfMute(() => VoiceActions.toggleSelfMute()); +VesktopNative.voice.onToggleSelfDeaf(() => VoiceActions.toggleSelfDeaf()); + // TODO: remove soon const vencordDir = "vencordDir" as keyof typeof Settings.store; if (Settings.store[vencordDir]) { diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index a52a9bf1..d4753208 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -52,6 +52,8 @@ export const enum IpcEvents { ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY", CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE", + TOGGLE_SELF_MUTE = "VCD_TOGGLE_SELF_MUTE", + TOGGLE_SELF_DEAF = "VCD_TOGGLE_SELF_DEAF", SET_TRAY_ICON = "VCD_SET_TRAY_ICON", GET_TRAY_ICON = "VCD_GET_TRAY_ICON",