diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts new file mode 100644 index 0000000..cd722c0 --- /dev/null +++ b/src/preload/VesktopNative.ts @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Aerocord, a vesktop fork for older microsoft NT releases such as NT 6.0, 6.1, 6.2 and 6.3. + * Credits to vendicated and the rest of the vesktop contribuitors for making Vesktop! + */ + +import { ipcRenderer } from "electron"; +import type { Settings } from "shared/settings"; +import type { LiteralUnion } from "type-fest"; + +import { IpcEvents } from "../shared/IpcEvents"; +import { invoke, sendSync } from "./typedIpc"; + +type SpellCheckerResultCallback = (word: string, suggestions: string[]) => void; + +const spellCheckCallbacks = new Set(); + +ipcRenderer.on(IpcEvents.SPELLCHECK_RESULT, (_, w: string, s: string[]) => { + spellCheckCallbacks.forEach(cb => cb(w, s)); +}); + +export const VesktopNative = { + app: { + relaunch: () => invoke(IpcEvents.RELAUNCH), + getVersion: () => sendSync(IpcEvents.GET_VERSION), + setBadgeCount: (count: number) => invoke(IpcEvents.SET_BADGE_COUNT, count), + supportsWindowsTransparency: () => sendSync(IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY) + }, + autostart: { + isEnabled: () => sendSync(IpcEvents.AUTOSTART_ENABLED), + enable: () => invoke(IpcEvents.ENABLE_AUTOSTART), + disable: () => invoke(IpcEvents.DISABLE_AUTOSTART) + }, + fileManager: { + showItemInFolder: (path: string) => invoke(IpcEvents.SHOW_ITEM_IN_FOLDER, path), + selectVencordDir: () => invoke>(IpcEvents.SELECT_VENCORD_DIR) + }, + settings: { + get: () => sendSync(IpcEvents.GET_SETTINGS), + set: (settings: Settings, path?: string) => invoke(IpcEvents.SET_SETTINGS, settings, path) + }, + spellcheck: { + setLanguages: (languages: readonly string[]) => invoke(IpcEvents.SPELLCHECK_SET_LANGUAGES, languages), + onSpellcheckResult(cb: SpellCheckerResultCallback) { + spellCheckCallbacks.add(cb); + }, + offSpellcheckResult(cb: SpellCheckerResultCallback) { + spellCheckCallbacks.delete(cb); + }, + replaceMisspelling: (word: string) => invoke(IpcEvents.SPELLCHECK_REPLACE_MISSPELLING, word), + addToDictionary: (word: string) => invoke(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, word) + }, + win: { + focus: () => invoke(IpcEvents.FOCUS), + close: (key?: string) => invoke(IpcEvents.CLOSE, key), + minimize: () => invoke(IpcEvents.MINIMIZE), + maximize: () => invoke(IpcEvents.MAXIMIZE) + }, + capturer: { + getLargeThumbnail: (id: string) => invoke(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id) + }, + /** only available on Linux. */ + virtmic: { + list: () => + invoke< + { ok: false; isGlibCxxOutdated: boolean } | { ok: true; targets: string[]; hasPipewirePulse: boolean } + >(IpcEvents.VIRT_MIC_LIST), + start: (targets: string[], workaround?: boolean) => invoke(IpcEvents.VIRT_MIC_START, targets, workaround), + startSystem: (workaround?: boolean, onlyDefaultSpeakers?: boolean) => + invoke(IpcEvents.VIRT_MIC_START_SYSTEM, workaround, onlyDefaultSpeakers), + stop: () => invoke(IpcEvents.VIRT_MIC_STOP) + }, + arrpc: { + onActivity(cb: (data: string) => void) { + ipcRenderer.on(IpcEvents.ARRPC_ACTIVITY, (_, data: string) => cb(data)); + } + }, + clipboard: { + copyImage: (imageBuffer: Uint8Array, imageSrc: string) => + invoke(IpcEvents.CLIPBOARD_COPY_IMAGE, imageBuffer, imageSrc) + } +}; diff --git a/src/preload/index.ts b/src/preload/index.ts new file mode 100644 index 0000000..d56b30a --- /dev/null +++ b/src/preload/index.ts @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Aerocord, a vesktop fork for older microsoft NT releases such as NT 6.0, 6.1, 6.2 and 6.3. + * Credits to vendicated and the rest of the vesktop contribuitors for making Vesktop! + */ + +import { contextBridge, ipcRenderer, webFrame } from "electron"; +import { readFileSync, watch } from "fs"; + +import { IpcEvents } from "../shared/IpcEvents"; +import { VesktopNative } from "./VesktopNative"; + +contextBridge.exposeInMainWorld("VesktopNative", VesktopNative); + +require(ipcRenderer.sendSync(IpcEvents.GET_VENCORD_PRELOAD_FILE)); + +webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_VENCORD_RENDERER_SCRIPT)); +webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_RENDERER_SCRIPT)); + +// #region css +const rendererCss = ipcRenderer.sendSync(IpcEvents.GET_RENDERER_CSS_FILE); + +const style = document.createElement("style"); +style.id = "vcd-css-core"; +style.textContent = readFileSync(rendererCss, "utf-8"); + +if (document.readyState === "complete") { + document.documentElement.appendChild(style); +} else { + document.addEventListener("DOMContentLoaded", () => document.documentElement.appendChild(style), { + once: true + }); +} + +if (IS_DEV) { + // persistent means keep process running if watcher is the only thing still running + // which we obviously don't want + watch(rendererCss, { persistent: false }, () => { + document.getElementById("vcd-css-core")!.textContent = readFileSync(rendererCss, "utf-8"); + }); +} +// #endregion + +VesktopNative.spellcheck.setLanguages(window.navigator.languages); diff --git a/src/preload/typedIpc.ts b/src/preload/typedIpc.ts new file mode 100644 index 0000000..c1aa9d0 --- /dev/null +++ b/src/preload/typedIpc.ts @@ -0,0 +1,16 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Aerocord, a vesktop fork for older microsoft NT releases such as NT 6.0, 6.1, 6.2 and 6.3. + * Credits to vendicated and the rest of the vesktop contribuitors for making Vesktop! + */ + +import { ipcRenderer } from "electron"; +import { IpcEvents } from "shared/IpcEvents"; + +export function invoke(event: IpcEvents, ...args: any[]) { + return ipcRenderer.invoke(event, ...args) as Promise; +} + +export function sendSync(event: IpcEvents, ...args: any[]) { + return ipcRenderer.sendSync(event, ...args) as T; +}