diff --git a/src/main/ipc.ts b/src/main/ipc.ts index e0bf131..3404d34 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -93,12 +93,8 @@ handle(IpcEvents.MAXIMIZE, e => { } }); -handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => { - const ses = session.defaultSession; - - const available = ses.availableSpellCheckerLanguages; - const applicable = languages.filter(l => available.includes(l)).slice(0, 3); - if (applicable.length) ses.setSpellCheckerLanguages(applicable); +handleSync(IpcEvents.SPELLCHECK_GET_AVAILABLE_LANGUAGES, e => { + e.returnValue = session.defaultSession.availableSpellCheckerLanguages; }); handle(IpcEvents.SPELLCHECK_REPLACE_MISSPELLING, (e, word: string) => { diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 3ee1fd0..a3675d8 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -13,6 +13,7 @@ import { MenuItemConstructorOptions, nativeTheme, screen, + session, Tray } from "electron"; import { rm } from "fs/promises"; @@ -360,12 +361,27 @@ function initSettingsListeners(win: BrowserWindow) { addSettingsListener("enableMenu", enabled => { win.setAutoHideMenuBar(enabled ?? false); }); + + addSettingsListener("spellCheckLanguages", languages => initSpellCheckLanguages(win, languages)); +} + +async function initSpellCheckLanguages(win: BrowserWindow, languages?: string[]) { + languages ??= await win.webContents.executeJavaScript("[...new Set(navigator.languages)]").catch(() => []); + if (!languages) return; + + const ses = session.defaultSession; + + const available = ses.availableSpellCheckerLanguages; + const applicable = languages.filter(l => available.includes(l)).slice(0, 5); + if (applicable.length) ses.setSpellCheckerLanguages(applicable); } function initSpellCheck(win: BrowserWindow) { win.webContents.on("context-menu", (_, data) => { win.webContents.send(IpcEvents.SPELLCHECK_RESULT, data.misspelledWord, data.dictionarySuggestions); }); + + initSpellCheckLanguages(win, Settings.store.spellCheckLanguages); } function createMainWindow() { diff --git a/src/main/settings.ts b/src/main/settings.ts index 03c705e..f2c1b80 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -35,11 +35,6 @@ function loadSettings(file: string, name: string) { } export const Settings = loadSettings(SETTINGS_FILE, "Vesktop settings"); -if (Object.hasOwn(Settings.plain, "discordWindowsTitleBar")) { - Settings.plain.customTitleBar = Settings.plain.discordWindowsTitleBar; - delete Settings.plain.discordWindowsTitleBar; - Settings.markAsChanged(); -} export const VencordSettings = loadSettings(VENCORD_SETTINGS_FILE, "Vencord settings"); diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 184b095..bea57d4 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -40,7 +40,7 @@ export const VesktopNative = { set: (settings: Settings, path?: string) => invoke(IpcEvents.SET_SETTINGS, settings, path) }, spellcheck: { - setLanguages: (languages: readonly string[]) => invoke(IpcEvents.SPELLCHECK_SET_LANGUAGES, languages), + getAvailableLanguages: () => sendSync(IpcEvents.SPELLCHECK_GET_AVAILABLE_LANGUAGES), onSpellcheckResult(cb: SpellCheckerResultCallback) { spellCheckCallbacks.add(cb); }, diff --git a/src/preload/index.ts b/src/preload/index.ts index 2cc0d11..75bf9cd 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -40,5 +40,3 @@ if (IS_DEV) { }); } // #endregion - -VesktopNative.spellcheck.setLanguages(window.navigator.languages); diff --git a/src/renderer/index.ts b/src/renderer/index.ts index 1ccc2e4..99dca25 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -12,7 +12,7 @@ import "./themedSplash"; console.log("read if cute :3"); export * as Components from "./components"; -import { findByPropsLazy } from "@vencord/types/webpack"; +import { findByPropsLazy, onceReady } from "@vencord/types/webpack"; import { FluxDispatcher } from "@vencord/types/webpack/common"; import SettingsUi from "./components/settings/Settings"; @@ -52,8 +52,10 @@ const arRPC = Vencord.Plugins.plugins["WebRichPresence (arRPC)"] as any as { handleEvent(e: MessageEvent): void; }; -VesktopNative.arrpc.onActivity(data => { +VesktopNative.arrpc.onActivity(async data => { if (!Settings.store.arRPC) return; + await onceReady; + arRPC.handleEvent(new MessageEvent("message", { data })); }); diff --git a/src/renderer/patches/spellCheck.tsx b/src/renderer/patches/spellCheck.tsx index 9f0dbbd..040d41b 100644 --- a/src/renderer/patches/spellCheck.tsx +++ b/src/renderer/patches/spellCheck.tsx @@ -6,7 +6,8 @@ import { addContextMenuPatch } from "@vencord/types/api/ContextMenu"; import { findStoreLazy } from "@vencord/types/webpack"; -import { FluxDispatcher, Menu, useStateFromStores } from "@vencord/types/webpack/common"; +import { FluxDispatcher, Menu, useMemo, useStateFromStores } from "@vencord/types/webpack/common"; +import { useSettings } from "renderer/settings"; import { addPatch } from "./shared"; @@ -50,7 +51,16 @@ addContextMenuPatch("textarea-context", children => { const spellCheckEnabled = useStateFromStores([SpellCheckStore], () => SpellCheckStore.isEnabled()); const hasCorrections = Boolean(word && corrections?.length); - children.push( + const availableLanguages = useMemo(VesktopNative.spellcheck.getAvailableLanguages, []); + + const settings = useSettings(); + const spellCheckLanguages = (settings.spellCheckLanguages ??= [...new Set(navigator.languages)]); + + const pasteSectionIndex = children.findIndex(c => c?.props?.children?.some(c => c?.props?.id === "paste")); + + children.splice( + pasteSectionIndex === -1 ? children.length : pasteSectionIndex, + 0, {hasCorrections && ( <> @@ -69,14 +79,39 @@ addContextMenuPatch("textarea-context", children => { /> )} - { - FluxDispatcher.dispatch({ type: "SPELLCHECK_TOGGLE" }); - }} - /> + + + { + FluxDispatcher.dispatch({ type: "SPELLCHECK_TOGGLE" }); + }} + /> + + + {availableLanguages.map(lang => { + const isEnabled = spellCheckLanguages.includes(lang); + return ( + = 5} + action={() => { + const newSpellCheckLanguages = spellCheckLanguages.filter(l => l !== lang); + if (newSpellCheckLanguages.length === spellCheckLanguages.length) { + newSpellCheckLanguages.push(lang); + } + + settings.spellCheckLanguages = newSpellCheckLanguages; + }} + /> + ); + })} + + ); }); diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index df64403..ea632fb 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -29,7 +29,7 @@ export const enum IpcEvents { UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD", UPDATE_IGNORE = "VCD_UPDATE_IGNORE", - SPELLCHECK_SET_LANGUAGES = "VCD_SPELLCHECK_SET_LANGUAGES", + SPELLCHECK_GET_AVAILABLE_LANGUAGES = "VCD_SPELLCHECK_GET_AVAILABLE_LANGUAGES", SPELLCHECK_RESULT = "VCD_SPELLCHECK_RESULT", SPELLCHECK_REPLACE_MISSPELLING = "VCD_SPELLCHECK_REPLACE_MISSPELLING", SPELLCHECK_ADD_TO_DICTIONARY = "VCD_SPELLCHECK_ADD_TO_DICTIONARY", diff --git a/src/shared/settings.d.ts b/src/shared/settings.d.ts index 4678751..a30d5cd 100644 --- a/src/shared/settings.d.ts +++ b/src/shared/settings.d.ts @@ -21,8 +21,6 @@ export interface Settings { appBadge?: boolean; disableMinSize?: boolean; clickTrayToShowHide?: boolean; - /** @deprecated use customTitleBar */ - discordWindowsTitleBar?: boolean; customTitleBar?: boolean; checkUpdates?: boolean; @@ -30,6 +28,8 @@ export interface Settings { splashTheming?: boolean; splashColor?: string; splashBackground?: string; + + spellCheckLanguages?: string[]; } export interface State {