Add SpellCheck suggestions

This commit is contained in:
V 2023-06-25 03:44:19 +02:00
parent 31799ccfb0
commit a7ded71404
No known key found for this signature in database
GPG key ID: A1DC0CFB5615D905
9 changed files with 139 additions and 3 deletions

1
src/globals.d.ts vendored
View file

@ -8,6 +8,7 @@ declare global {
export var VencordDesktopNative: typeof import("preload/VencordDesktopNative").VencordDesktopNative; export var VencordDesktopNative: typeof import("preload/VencordDesktopNative").VencordDesktopNative;
export var VencordDesktop: typeof import("renderer/index"); export var VencordDesktop: typeof import("renderer/index");
export var vcdLS: typeof localStorage; export var vcdLS: typeof localStorage;
export var VCDP: any;
export var IS_DEV: boolean; export var IS_DEV: boolean;
} }

View file

@ -76,6 +76,14 @@ ipcMain.handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => {
if (applicable.length) ses.setSpellCheckerLanguages(applicable); if (applicable.length) ses.setSpellCheckerLanguages(applicable);
}); });
ipcMain.handle(IpcEvents.SPELLCHECK_REPLACE_MISSPELLING, (e, word: string) => {
e.sender.replaceMisspelling(word);
});
ipcMain.handle(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, (e, word: string) => {
e.sender.session.addWordToSpellCheckerDictionary(word);
});
ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => { ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
const res = await dialog.showOpenDialog(mainWin!, { const res = await dialog.showOpenDialog(mainWin!, {
properties: ["openDirectory"] properties: ["openDirectory"]

View file

@ -6,6 +6,7 @@
import { app, BrowserWindow, BrowserWindowConstructorOptions, Menu, Tray } from "electron"; import { app, BrowserWindow, BrowserWindowConstructorOptions, Menu, Tray } from "electron";
import { join } from "path"; import { join } from "path";
import { IpcEvents } from "shared/IpcEvents";
import { once } from "shared/utils/once"; import { once } from "shared/utils/once";
import { ICON_PATH } from "../shared/paths"; import { ICON_PATH } from "../shared/paths";
@ -216,6 +217,12 @@ function initSettingsListeners(win: BrowserWindow) {
}); });
} }
function initSpellCheck(win: BrowserWindow) {
win.webContents.on("context-menu", (_, data) => {
win.webContents.send(IpcEvents.SPELLCHECK_RESULT, data.misspelledWord, data.dictionarySuggestions);
});
}
function createMainWindow() { function createMainWindow() {
const win = (mainWin = new BrowserWindow({ const win = (mainWin = new BrowserWindow({
show: false, show: false,
@ -225,7 +232,8 @@ function createMainWindow() {
sandbox: false, sandbox: false,
contextIsolation: true, contextIsolation: true,
devTools: true, devTools: true,
preload: join(__dirname, "preload.js") preload: join(__dirname, "preload.js"),
spellcheck: true
}, },
icon: ICON_PATH, icon: ICON_PATH,
frame: VencordSettings.store.frameless !== true, frame: VencordSettings.store.frameless !== true,
@ -255,6 +263,7 @@ function createMainWindow() {
initMenuBar(win); initMenuBar(win);
makeLinksOpenExternally(win); makeLinksOpenExternally(win);
initSettingsListeners(win); initSettingsListeners(win);
initSpellCheck(win);
win.webContents.setUserAgent( win.webContents.setUserAgent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"

View file

@ -4,12 +4,21 @@
* Copyright (c) 2023 Vendicated and Vencord contributors * Copyright (c) 2023 Vendicated and Vencord contributors
*/ */
import { ipcRenderer } from "electron";
import type { Settings } from "shared/settings"; import type { Settings } from "shared/settings";
import type { LiteralUnion } from "type-fest"; import type { LiteralUnion } from "type-fest";
import { IpcEvents } from "../shared/IpcEvents"; import { IpcEvents } from "../shared/IpcEvents";
import { invoke, sendSync } from "./typedIpcs"; import { invoke, sendSync } from "./typedIpcs";
type SpellCheckerResultCallback = (word: string, suggestions: string[]) => void;
const spellCheckCallbacks = new Set<SpellCheckerResultCallback>();
ipcRenderer.on(IpcEvents.SPELLCHECK_RESULT, (_, w: string, s: string[]) => {
spellCheckCallbacks.forEach(cb => cb(w, s));
});
export const VencordDesktopNative = { export const VencordDesktopNative = {
app: { app: {
relaunch: () => invoke<void>(IpcEvents.RELAUNCH), relaunch: () => invoke<void>(IpcEvents.RELAUNCH),
@ -30,8 +39,15 @@ export const VencordDesktopNative = {
set: (settings: Settings, path?: string) => invoke<void>(IpcEvents.SET_SETTINGS, settings, path) set: (settings: Settings, path?: string) => invoke<void>(IpcEvents.SET_SETTINGS, settings, path)
}, },
spellcheck: { spellcheck: {
setLanguages: (languages: readonly string[]) => invoke<void>(IpcEvents.SPELLCHECK_SET_LANGUAGES, languages) setLanguages: (languages: readonly string[]) => invoke<void>(IpcEvents.SPELLCHECK_SET_LANGUAGES, languages),
// todo: perhaps add ways to learn words onSpellcheckResult(cb: SpellCheckerResultCallback) {
spellCheckCallbacks.add(cb);
},
offSpellcheckResult(cb: SpellCheckerResultCallback) {
spellCheckCallbacks.delete(cb);
},
replaceMisspelling: (word: string) => invoke<void>(IpcEvents.SPELLCHECK_REPLACE_MISSPELLING, word),
addToDictionary: (word: string) => invoke<void>(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, word)
}, },
win: { win: {
focus: () => invoke<void>(IpcEvents.FOCUS) focus: () => invoke<void>(IpcEvents.FOCUS)

View file

@ -6,6 +6,7 @@
import "./fixes"; import "./fixes";
import "./appBadge"; import "./appBadge";
import "./patches";
console.log("read if cute :3"); console.log("read if cute :3");

View file

@ -0,0 +1,8 @@
/*
* SPDX-License-Identifier: GPL-3.0
* Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
// TODO: Possibly auto generate glob if we have more patches in the future
import "./spellCheck";

View file

@ -0,0 +1,30 @@
/*
* SPDX-License-Identifier: GPL-3.0
* Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { Patch } from "@vencord/types/utils/types";
window.VCDP = {};
interface PatchData {
patches: Omit<Patch, "plugin">[];
[key: string]: any;
}
export function addPatch<P extends PatchData>(p: P) {
const { patches, ...globals } = p;
for (const patch of patches as Patch[]) {
if (!Array.isArray(patch.replacement)) patch.replacement = [patch.replacement];
for (const r of patch.replacement) {
if (typeof r.replace === "string") r.replace = r.replace.replaceAll("$self", "VCDP");
}
patch.plugin = "VencordDesktop";
Vencord.Plugins.patches.push(patch as Patch);
}
Object.assign(VCDP, globals);
}

View file

@ -0,0 +1,60 @@
/*
* SPDX-License-Identifier: GPL-3.0
* Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2023 Vendicated and Vencord contributors
*/
import { addContextMenuPatch } from "@vencord/types/api/ContextMenu";
import { Menu } from "@vencord/types/webpack/common";
import { addPatch } from "./shared";
let word: string;
let corrections: string[];
// Make spellcheck suggestions work
addPatch({
patches: [
{
find: ".enableSpellCheck)",
replacement: {
// if (isDesktop) { DiscordNative.onSpellcheck(openMenu(props)) } else { e.preventDefault(); openMenu(props) }
match: /else\{.{1,3}\.preventDefault\(\);(.{1,3}\(.{1,3}\))\}/,
// ... else { $self.onSlateContext(() => openMenu(props)) }
replace: "else {$self.onSlateContext(() => $1)}"
}
}
],
onSlateContext(openMenu: () => void) {
const cb = (w: string, c: string[]) => {
VencordDesktopNative.spellcheck.offSpellcheckResult(cb);
word = w;
corrections = c;
openMenu();
};
VencordDesktopNative.spellcheck.onSpellcheckResult(cb);
}
});
addContextMenuPatch("textarea-context", children => () => {
if (!word || !corrections?.length) return;
children.push(
<Menu.MenuGroup>
{corrections.map(c => (
<Menu.MenuItem
id={"vcd-spellcheck-suggestion-" + c}
label={c}
action={() => VencordDesktopNative.spellcheck.replaceMisspelling(c)}
/>
))}
<Menu.MenuSeparator />
<Menu.MenuItem
id="vcd-spellcheck-learn"
label={`Add ${word} to dictionary`}
action={() => VencordDesktopNative.spellcheck.addToDictionary(word)}
/>
</Menu.MenuGroup>
);
});

View file

@ -27,6 +27,9 @@ export const enum IpcEvents {
UPDATE_IGNORE = "VCD_UPDATE_IGNORE", UPDATE_IGNORE = "VCD_UPDATE_IGNORE",
SPELLCHECK_SET_LANGUAGES = "VCD_SPELLCHECK_SET_LANGUAGES", SPELLCHECK_SET_LANGUAGES = "VCD_SPELLCHECK_SET_LANGUAGES",
SPELLCHECK_RESULT = "VCD_SPELLCHECK_RESULT",
SPELLCHECK_REPLACE_MISSPELLING = "VCD_SPELLCHECK_REPLACE_MISSPELLING",
SPELLCHECK_ADD_TO_DICTIONARY = "VCD_SPELLCHECK_ADD_TO_DICTIONARY",
SET_BADGE_COUNT = "VCD_SET_BADGE_COUNT", SET_BADGE_COUNT = "VCD_SET_BADGE_COUNT",