From 0d5e2d0696da494aee2126b4cadbca7e07066b89 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 6 May 2023 01:36:00 +0200 Subject: [skip ci] Refactor utils --- src/Vencord.ts | 4 +- src/api/Commands/index.ts | 2 +- src/api/ContextMenu.ts | 2 +- src/api/MessageEvents.ts | 2 +- src/api/MessagePopover.ts | 2 +- src/api/Notifications/NotificationComponent.tsx | 2 +- src/api/Notifications/Notifications.tsx | 2 +- src/api/Notifications/notificationLog.tsx | 4 +- src/api/ServerList.ts | 2 +- src/api/Settings.ts | 283 +++++++++++++++++++++ src/api/SettingsStore.ts | 6 +- src/api/settings.ts | 283 --------------------- src/components/ErrorBoundary.tsx | 4 +- src/components/PatchHelper.tsx | 2 +- src/components/PluginSettings/PluginModal.tsx | 7 +- src/components/PluginSettings/index.tsx | 9 +- src/components/VencordSettings/CloudTab.tsx | 2 +- src/components/VencordSettings/ThemesTab.tsx | 4 +- src/components/VencordSettings/Updater.tsx | 5 +- src/components/VencordSettings/VencordTab.tsx | 5 +- src/debug/Tracer.ts | 2 +- src/main/ipcMain.ts | 2 +- src/plugins/anonymiseFileNames.ts | 2 +- src/plugins/apiBadges.tsx | 2 +- src/plugins/betterFolders/FolderSideBar.tsx | 2 +- src/plugins/betterFolders/index.ts | 2 +- src/plugins/betterNotes.ts | 5 +- src/plugins/betterRoleDot.ts | 2 +- src/plugins/blurNsfw.ts | 2 +- src/plugins/callTimer.tsx | 2 +- src/plugins/crashHandler.ts | 4 +- src/plugins/customRPC.tsx | 4 +- src/plugins/devCompanion.dev.tsx | 4 +- src/plugins/emoteCloner.tsx | 2 +- src/plugins/experiments.tsx | 2 +- src/plugins/fakeNitro.tsx | 4 +- src/plugins/fakeProfileThemes.tsx | 2 +- src/plugins/fart.ts | 2 +- src/plugins/ignoreActivities.tsx | 2 +- src/plugins/imageZoom/index.tsx | 2 +- src/plugins/index.ts | 4 +- src/plugins/invisibleChat/index.tsx | 2 +- src/plugins/lastfm.tsx | 4 +- src/plugins/messageLinkEmbeds.tsx | 5 +- src/plugins/messageLogger/index.tsx | 4 +- src/plugins/messageTags.ts | 2 +- src/plugins/moreUserTags.ts | 4 +- src/plugins/moyai.ts | 2 +- src/plugins/muteNewGuild.tsx | 2 +- src/plugins/noBlockedMessages.ts | 2 +- src/plugins/noReplyMention.tsx | 2 +- src/plugins/petpet.ts | 2 +- src/plugins/pinDms/settings.ts | 2 +- src/plugins/platformIndicators.tsx | 2 +- src/plugins/pronoundb/pronoundbUtils.ts | 4 +- src/plugins/pronoundb/settings.ts | 2 +- src/plugins/quickReply.ts | 2 +- src/plugins/relationshipNotifier/settings.ts | 2 +- src/plugins/reviewDB/Utils/ReviewDBAPI.ts | 2 +- src/plugins/reviewDB/Utils/Utils.tsx | 4 +- src/plugins/reviewDB/components/MessageButton.tsx | 5 +- .../reviewDB/components/ReviewComponent.tsx | 5 +- src/plugins/reviewDB/components/ReviewsView.tsx | 5 +- src/plugins/reviewDB/index.tsx | 2 +- src/plugins/roleColorEverywhere.tsx | 2 +- src/plugins/searchReply.tsx | 2 +- src/plugins/serverListIndicators.tsx | 4 +- src/plugins/settings.tsx | 6 +- .../shikiCodeblocks/components/Highlighter.tsx | 3 +- src/plugins/shikiCodeblocks/settings.ts | 2 +- src/plugins/showConnections/index.tsx | 5 +- .../components/HiddenChannelLockScreen.tsx | 2 +- src/plugins/showHiddenChannels/index.tsx | 2 +- src/plugins/showMeYourName/index.tsx | 4 +- src/plugins/silentMessageToggle.tsx | 2 +- src/plugins/silentTyping.tsx | 2 +- src/plugins/spotifyControls/SpotifyStore.ts | 4 +- src/plugins/spotifyControls/index.tsx | 2 +- src/plugins/spotifyCrack.ts | 2 +- src/plugins/startupTimings/index.tsx | 2 +- src/plugins/supportHelper.tsx | 2 +- src/plugins/textReplace.tsx | 6 +- src/plugins/typingIndicator.tsx | 4 +- src/plugins/typingTweaks.tsx | 2 +- src/plugins/userVoiceShow/index.tsx | 2 +- src/plugins/usrbg/index.tsx | 2 +- src/plugins/vcNarrator.tsx | 4 +- src/plugins/vencordToolbox/index.tsx | 2 +- src/plugins/viewIcons.tsx | 4 +- src/plugins/volumeBooster.discordDesktop.ts | 2 +- src/plugins/webContextMenus.web.ts | 2 +- src/plugins/welcomeStickerPicker.tsx | 2 +- src/plugins/whoReacted.tsx | 3 +- src/utils/Logger.ts | 2 +- src/utils/cloud.tsx | 4 +- src/utils/constants.ts | 5 + src/utils/dependencies.ts | 2 +- src/utils/index.ts | 13 +- src/utils/lazy.ts | 87 +++++++ src/utils/misc.tsx | 110 +------- src/utils/modal.tsx | 2 +- src/utils/proxyLazy.ts | 82 ------ src/utils/quickCss.ts | 2 +- src/utils/react.ts | 62 ----- src/utils/react.tsx | 128 ++++++++++ src/utils/settingsSync.ts | 4 +- src/utils/text.ts | 39 +++ src/utils/updater.ts | 2 +- src/webpack/common/internal.tsx | 2 +- src/webpack/patchWebpack.ts | 2 +- src/webpack/webpack.ts | 4 +- 111 files changed, 704 insertions(+), 686 deletions(-) create mode 100644 src/api/Settings.ts delete mode 100644 src/api/settings.ts create mode 100644 src/utils/lazy.ts delete mode 100644 src/utils/proxyLazy.ts delete mode 100644 src/utils/react.ts create mode 100644 src/utils/react.tsx (limited to 'src') diff --git a/src/Vencord.ts b/src/Vencord.ts index 4c0d2a8..76719e5 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -28,12 +28,12 @@ import "./utils/quickCss"; import "./webpack/patchWebpack"; import { showNotification } from "./api/Notifications"; -import { PlainSettings, Settings } from "./api/settings"; +import { PlainSettings, Settings } from "./api/Settings"; import { patches, PMLogger, startAllPlugins } from "./plugins"; import { localStorage } from "./utils/localStorage"; import { relaunch } from "./utils/native"; import { getCloudSettings, putCloudSettings } from "./utils/settingsSync"; -import { checkForUpdates, update,UpdateLogger } from "./utils/updater"; +import { checkForUpdates, update, UpdateLogger } from "./utils/updater"; import { onceReady } from "./webpack"; import { SettingsRouter } from "./webpack/common"; diff --git a/src/api/Commands/index.ts b/src/api/Commands/index.ts index 3f639a1..ef4db17 100644 --- a/src/api/Commands/index.ts +++ b/src/api/Commands/index.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { makeCodeblock } from "@utils/misc"; +import { makeCodeblock } from "@utils/text"; import { sendBotMessage } from "./commandHelpers"; import { ApplicationCommandInputType, ApplicationCommandOptionType, ApplicationCommandType, Argument, Command, CommandContext, Option } from "./types"; diff --git a/src/api/ContextMenu.ts b/src/api/ContextMenu.ts index 4d1d577..f1ebfdb 100644 --- a/src/api/ContextMenu.ts +++ b/src/api/ContextMenu.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import type { ReactElement } from "react"; type ContextMenuPatchCallbackReturn = (() => void) | void; diff --git a/src/api/MessageEvents.ts b/src/api/MessageEvents.ts index 50d8b26..b597fea 100644 --- a/src/api/MessageEvents.ts +++ b/src/api/MessageEvents.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { MessageStore } from "@webpack/common"; import type { Channel, Message } from "discord-types/general"; import type { Promisable } from "type-fest"; diff --git a/src/api/MessagePopover.ts b/src/api/MessagePopover.ts index 85dff9c..3391cfb 100644 --- a/src/api/MessagePopover.ts +++ b/src/api/MessagePopover.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { Channel, Message } from "discord-types/general"; import type { MouseEventHandler } from "react"; diff --git a/src/api/Notifications/NotificationComponent.tsx b/src/api/Notifications/NotificationComponent.tsx index 542c29b..caa4b64 100644 --- a/src/api/Notifications/NotificationComponent.tsx +++ b/src/api/Notifications/NotificationComponent.tsx @@ -18,7 +18,7 @@ import "./styles.css"; -import { useSettings } from "@api/settings"; +import { useSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; import { React, useEffect, useMemo, useState, useStateFromStores, WindowStore } from "@webpack/common"; diff --git a/src/api/Notifications/Notifications.tsx b/src/api/Notifications/Notifications.tsx index 600ea63..6025646 100644 --- a/src/api/Notifications/Notifications.tsx +++ b/src/api/Notifications/Notifications.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Queue } from "@utils/Queue"; import { ReactDOM } from "@webpack/common"; import type { ReactNode } from "react"; diff --git a/src/api/Notifications/notificationLog.tsx b/src/api/Notifications/notificationLog.tsx index 72f09ac..9535fb6 100644 --- a/src/api/Notifications/notificationLog.tsx +++ b/src/api/Notifications/notificationLog.tsx @@ -17,10 +17,10 @@ */ import * as DataStore from "@api/DataStore"; -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; -import { useAwaiter } from "@utils/misc"; import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; +import { useAwaiter } from "@utils/react"; import { Alerts, Button, Forms, moment, React, Text, Timestamp, useEffect, useReducer, useState } from "@webpack/common"; import { nanoid } from "nanoid"; import type { DispatchWithoutAction } from "react"; diff --git a/src/api/ServerList.ts b/src/api/ServerList.ts index c98b174..4804413 100644 --- a/src/api/ServerList.ts +++ b/src/api/ServerList.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; const logger = new Logger("ServerListAPI"); diff --git a/src/api/Settings.ts b/src/api/Settings.ts new file mode 100644 index 0000000..e481e48 --- /dev/null +++ b/src/api/Settings.ts @@ -0,0 +1,283 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2022 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import { debounce } from "@utils/debounce"; +import { localStorage } from "@utils/localStorage"; +import { Logger } from "@utils/Logger"; +import { mergeDefaults } from "@utils/misc"; +import { putCloudSettings } from "@utils/settingsSync"; +import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types"; +import { React } from "@webpack/common"; + +import plugins from "~plugins"; + +const logger = new Logger("Settings"); +export interface Settings { + notifyAboutUpdates: boolean; + autoUpdate: boolean; + autoUpdateNotification: boolean, + useQuickCss: boolean; + enableReactDevtools: boolean; + themeLinks: string[]; + frameless: boolean; + transparent: boolean; + winCtrlQ: boolean; + macosTranslucency: boolean; + disableMinSize: boolean; + winNativeTitleBar: boolean; + plugins: { + [plugin: string]: { + enabled: boolean; + [setting: string]: any; + }; + }; + + notifications: { + timeout: number; + position: "top-right" | "bottom-right"; + useNative: "always" | "never" | "not-focused"; + logLimit: number; + }; + + cloud: { + authenticated: boolean; + url: string; + settingsSync: boolean; + settingsSyncVersion: number; + }; +} + +const DefaultSettings: Settings = { + notifyAboutUpdates: true, + autoUpdate: false, + autoUpdateNotification: true, + useQuickCss: true, + themeLinks: [], + enableReactDevtools: false, + frameless: false, + transparent: false, + winCtrlQ: false, + macosTranslucency: false, + disableMinSize: false, + winNativeTitleBar: false, + plugins: {}, + + notifications: { + timeout: 5000, + position: "bottom-right", + useNative: "not-focused", + logLimit: 50 + }, + + cloud: { + authenticated: false, + url: "https://api.vencord.dev/", + settingsSync: false, + settingsSyncVersion: 0 + } +}; + +try { + var settings = JSON.parse(VencordNative.settings.get()) as Settings; + mergeDefaults(settings, DefaultSettings); +} catch (err) { + var settings = mergeDefaults({} as Settings, DefaultSettings); + logger.error("An error occurred while loading the settings. Corrupt settings file?\n", err); +} + +const saveSettingsOnFrequentAction = debounce(async () => { + if (Settings.cloud.settingsSync && Settings.cloud.authenticated) { + await putCloudSettings(); + delete localStorage.Vencord_settingsDirty; + } +}, 60_000); + +type SubscriptionCallback = ((newValue: any, path: string) => void) & { _path?: string; }; +const subscriptions = new Set(); + +const proxyCache = {} as Record; + +// Wraps the passed settings object in a Proxy to nicely handle change listeners and default values +function makeProxy(settings: any, root = settings, path = ""): Settings { + return proxyCache[path] ??= new Proxy(settings, { + get(target, p: string) { + const v = target[p]; + + // using "in" is important in the following cases to properly handle falsy or nullish values + if (!(p in target)) { + // Return empty for plugins with no settings + if (path === "plugins" && p in plugins) + return target[p] = makeProxy({ + enabled: plugins[p].required ?? plugins[p].enabledByDefault ?? false + }, root, `plugins.${p}`); + + // Since the property is not set, check if this is a plugin's setting and if so, try to resolve + // the default value. + if (path.startsWith("plugins.")) { + const plugin = path.slice("plugins.".length); + if (plugin in plugins) { + const setting = plugins[plugin].options?.[p]; + if (!setting) return v; + if ("default" in setting) + // normal setting with a default value + return (target[p] = setting.default); + if (setting.type === OptionType.SELECT) { + const def = setting.options.find(o => o.default); + if (def) + target[p] = def.value; + return def?.value; + } + } + } + return v; + } + + // Recursively proxy Objects with the updated property path + if (typeof v === "object" && !Array.isArray(v) && v !== null) + return makeProxy(v, root, `${path}${path && "."}${p}`); + + // primitive or similar, no need to proxy further + return v; + }, + + set(target, p: string, v) { + // avoid unnecessary updates to React Components and other listeners + if (target[p] === v) return true; + + target[p] = v; + // Call any listeners that are listening to a setting of this path + const setPath = `${path}${path && "."}${p}`; + delete proxyCache[setPath]; + for (const subscription of subscriptions) { + if (!subscription._path || subscription._path === setPath) { + subscription(v, setPath); + } + } + // And don't forget to persist the settings! + PlainSettings.cloud.settingsSyncVersion = Date.now(); + localStorage.Vencord_settingsDirty = true; + saveSettingsOnFrequentAction(); + VencordNative.settings.set(JSON.stringify(root, null, 4)); + return true; + } + }); +} + +/** + * Same as {@link Settings} but unproxied. You should treat this as readonly, + * as modifying properties on this will not save to disk or call settings + * listeners. + * WARNING: default values specified in plugin.options will not be ensured here. In other words, + * settings for which you specified a default value may be uninitialised. If you need proper + * handling for default values, use {@link Settings} + */ +export const PlainSettings = settings; +/** + * A smart settings object. Altering props automagically saves + * the updated settings to disk. + * This recursively proxies objects. If you need the object non proxied, use {@link PlainSettings} + */ +export const Settings = makeProxy(settings); + +/** + * Settings hook for React components. Returns a smart settings + * object that automagically triggers a rerender if any properties + * are altered + * @param paths An optional list of paths to whitelist for rerenders + * @returns Settings + */ +// TODO: Representing paths as essentially "string[].join('.')" wont allow dots in paths, change to "paths?: string[][]" later +export function useSettings(paths?: UseSettings[]) { + const [, forceUpdate] = React.useReducer(() => ({}), {}); + + const onUpdate: SubscriptionCallback = paths + ? (value, path) => paths.includes(path as UseSettings) && forceUpdate() + : forceUpdate; + + React.useEffect(() => { + subscriptions.add(onUpdate); + return () => void subscriptions.delete(onUpdate); + }, []); + + return Settings; +} + +// Resolves a possibly nested prop in the form of "some.nested.prop" to type of T.some.nested.prop +type ResolvePropDeep = P extends "" ? T : + P extends `${infer Pre}.${infer Suf}` ? + Pre extends keyof T ? ResolvePropDeep : never : P extends keyof T ? T[P] : never; + +/** + * Add a settings listener that will be invoked whenever the desired setting is updated + * @param path Path to the setting that you want to watch, for example "plugins.Unindent.enabled" will fire your callback + * whenever Unindent is toggled. Pass an empty string to get notified for all changes + * @param onUpdate Callback function whenever a setting matching path is updated. It gets passed the new value and the path + * to the updated setting. This path will be the same as your path argument, unless it was an empty string. + * + * @example addSettingsListener("", (newValue, path) => console.log(`${path} is now ${newValue}`)) + * addSettingsListener("plugins.Unindent.enabled", v => console.log("Unindent is now", v ? "enabled" : "disabled")) + */ +export function addSettingsListener(path: Path, onUpdate: (newValue: Settings[Path], path: Path) => void): void; +export function addSettingsListener(path: Path, onUpdate: (newValue: Path extends "" ? any : ResolvePropDeep, path: Path extends "" ? string : Path) => void): void; +export function addSettingsListener(path: string, onUpdate: (newValue: any, path: string) => void) { + (onUpdate as SubscriptionCallback)._path = path; + subscriptions.add(onUpdate); +} + +export function migratePluginSettings(name: string, ...oldNames: string[]) { + const { plugins } = settings; + if (name in plugins) return; + + for (const oldName of oldNames) { + if (oldName in plugins) { + logger.info(`Migrating settings from old name ${oldName} to ${name}`); + plugins[name] = plugins[oldName]; + delete plugins[oldName]; + VencordNative.settings.set(JSON.stringify(settings, null, 4)); + break; + } + } +} + +export function definePluginSettings>(def: D, checks?: C) { + const definedSettings: DefinedSettings = { + get store() { + if (!definedSettings.pluginName) throw new Error("Cannot access settings before plugin is initialized"); + return Settings.plugins[definedSettings.pluginName] as any; + }, + use: settings => useSettings( + settings?.map(name => `plugins.${definedSettings.pluginName}.${name}`) as UseSettings[] + ).plugins[definedSettings.pluginName] as any, + def, + checks: checks ?? {}, + pluginName: "", + }; + return definedSettings; +} + +type UseSettings = ResolveUseSettings[keyof T]; + +type ResolveUseSettings = { + [Key in keyof T]: + Key extends string + ? T[Key] extends Record + // @ts-ignore "Type instantiation is excessively deep and possibly infinite" + ? UseSettings extends string ? `${Key}.${UseSettings}` : never + : Key + : never; +}; diff --git a/src/api/SettingsStore.ts b/src/api/SettingsStore.ts index a5a0402..d9369a9 100644 --- a/src/api/SettingsStore.ts +++ b/src/api/SettingsStore.ts @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; -import { proxyLazy } from "@utils/proxyLazy"; +import { proxyLazy } from "@utils/lazy"; +import { Logger } from "@utils/Logger"; import { findModuleId, wreq } from "@webpack"; -import { Settings } from "./settings"; +import { Settings } from "./Settings"; interface Setting { /** diff --git a/src/api/settings.ts b/src/api/settings.ts deleted file mode 100644 index 2329f94..0000000 --- a/src/api/settings.ts +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { debounce } from "@utils/debounce"; -import { localStorage } from "@utils/localStorage"; -import Logger from "@utils/Logger"; -import { mergeDefaults } from "@utils/misc"; -import { putCloudSettings } from "@utils/settingsSync"; -import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types"; -import { React } from "@webpack/common"; - -import plugins from "~plugins"; - -const logger = new Logger("Settings"); -export interface Settings { - notifyAboutUpdates: boolean; - autoUpdate: boolean; - autoUpdateNotification: boolean, - useQuickCss: boolean; - enableReactDevtools: boolean; - themeLinks: string[]; - frameless: boolean; - transparent: boolean; - winCtrlQ: boolean; - macosTranslucency: boolean; - disableMinSize: boolean; - winNativeTitleBar: boolean; - plugins: { - [plugin: string]: { - enabled: boolean; - [setting: string]: any; - }; - }; - - notifications: { - timeout: number; - position: "top-right" | "bottom-right"; - useNative: "always" | "never" | "not-focused"; - logLimit: number; - }; - - cloud: { - authenticated: boolean; - url: string; - settingsSync: boolean; - settingsSyncVersion: number; - }; -} - -const DefaultSettings: Settings = { - notifyAboutUpdates: true, - autoUpdate: false, - autoUpdateNotification: true, - useQuickCss: true, - themeLinks: [], - enableReactDevtools: false, - frameless: false, - transparent: false, - winCtrlQ: false, - macosTranslucency: false, - disableMinSize: false, - winNativeTitleBar: false, - plugins: {}, - - notifications: { - timeout: 5000, - position: "bottom-right", - useNative: "not-focused", - logLimit: 50 - }, - - cloud: { - authenticated: false, - url: "https://api.vencord.dev/", - settingsSync: false, - settingsSyncVersion: 0 - } -}; - -try { - var settings = JSON.parse(VencordNative.settings.get()) as Settings; - mergeDefaults(settings, DefaultSettings); -} catch (err) { - var settings = mergeDefaults({} as Settings, DefaultSettings); - logger.error("An error occurred while loading the settings. Corrupt settings file?\n", err); -} - -const saveSettingsOnFrequentAction = debounce(async () => { - if (Settings.cloud.settingsSync && Settings.cloud.authenticated) { - await putCloudSettings(); - delete localStorage.Vencord_settingsDirty; - } -}, 60_000); - -type SubscriptionCallback = ((newValue: any, path: string) => void) & { _path?: string; }; -const subscriptions = new Set(); - -const proxyCache = {} as Record; - -// Wraps the passed settings object in a Proxy to nicely handle change listeners and default values -function makeProxy(settings: any, root = settings, path = ""): Settings { - return proxyCache[path] ??= new Proxy(settings, { - get(target, p: string) { - const v = target[p]; - - // using "in" is important in the following cases to properly handle falsy or nullish values - if (!(p in target)) { - // Return empty for plugins with no settings - if (path === "plugins" && p in plugins) - return target[p] = makeProxy({ - enabled: plugins[p].required ?? plugins[p].enabledByDefault ?? false - }, root, `plugins.${p}`); - - // Since the property is not set, check if this is a plugin's setting and if so, try to resolve - // the default value. - if (path.startsWith("plugins.")) { - const plugin = path.slice("plugins.".length); - if (plugin in plugins) { - const setting = plugins[plugin].options?.[p]; - if (!setting) return v; - if ("default" in setting) - // normal setting with a default value - return (target[p] = setting.default); - if (setting.type === OptionType.SELECT) { - const def = setting.options.find(o => o.default); - if (def) - target[p] = def.value; - return def?.value; - } - } - } - return v; - } - - // Recursively proxy Objects with the updated property path - if (typeof v === "object" && !Array.isArray(v) && v !== null) - return makeProxy(v, root, `${path}${path && "."}${p}`); - - // primitive or similar, no need to proxy further - return v; - }, - - set(target, p: string, v) { - // avoid unnecessary updates to React Components and other listeners - if (target[p] === v) return true; - - target[p] = v; - // Call any listeners that are listening to a setting of this path - const setPath = `${path}${path && "."}${p}`; - delete proxyCache[setPath]; - for (const subscription of subscriptions) { - if (!subscription._path || subscription._path === setPath) { - subscription(v, setPath); - } - } - // And don't forget to persist the settings! - PlainSettings.cloud.settingsSyncVersion = Date.now(); - localStorage.Vencord_settingsDirty = true; - saveSettingsOnFrequentAction(); - VencordNative.settings.set(JSON.stringify(root, null, 4)); - return true; - } - }); -} - -/** - * Same as {@link Settings} but unproxied. You should treat this as readonly, - * as modifying properties on this will not save to disk or call settings - * listeners. - * WARNING: default values specified in plugin.options will not be ensured here. In other words, - * settings for which you specified a default value may be uninitialised. If you need proper - * handling for default values, use {@link Settings} - */ -export const PlainSettings = settings; -/** - * A smart settings object. Altering props automagically saves - * the updated settings to disk. - * This recursively proxies objects. If you need the object non proxied, use {@link PlainSettings} - */ -export const Settings = makeProxy(settings); - -/** - * Settings hook for React components. Returns a smart settings - * object that automagically triggers a rerender if any properties - * are altered - * @param paths An optional list of paths to whitelist for rerenders - * @returns Settings - */ -// TODO: Representing paths as essentially "string[].join('.')" wont allow dots in paths, change to "paths?: string[][]" later -export function useSettings(paths?: UseSettings[]) { - const [, forceUpdate] = React.useReducer(() => ({}), {}); - - const onUpdate: SubscriptionCallback = paths - ? (value, path) => paths.includes(path as UseSettings) && forceUpdate() - : forceUpdate; - - React.useEffect(() => { - subscriptions.add(onUpdate); - return () => void subscriptions.delete(onUpdate); - }, []); - - return Settings; -} - -// Resolves a possibly nested prop in the form of "some.nested.prop" to type of T.some.nested.prop -type ResolvePropDeep = P extends "" ? T : - P extends `${infer Pre}.${infer Suf}` ? - Pre extends keyof T ? ResolvePropDeep : never : P extends keyof T ? T[P] : never; - -/** - * Add a settings listener that will be invoked whenever the desired setting is updated - * @param path Path to the setting that you want to watch, for example "plugins.Unindent.enabled" will fire your callback - * whenever Unindent is toggled. Pass an empty string to get notified for all changes - * @param onUpdate Callback function whenever a setting matching path is updated. It gets passed the new value and the path - * to the updated setting. This path will be the same as your path argument, unless it was an empty string. - * - * @example addSettingsListener("", (newValue, path) => console.log(`${path} is now ${newValue}`)) - * addSettingsListener("plugins.Unindent.enabled", v => console.log("Unindent is now", v ? "enabled" : "disabled")) - */ -export function addSettingsListener(path: Path, onUpdate: (newValue: Settings[Path], path: Path) => void): void; -export function addSettingsListener(path: Path, onUpdate: (newValue: Path extends "" ? any : ResolvePropDeep, path: Path extends "" ? string : Path) => void): void; -export function addSettingsListener(path: string, onUpdate: (newValue: any, path: string) => void) { - (onUpdate as SubscriptionCallback)._path = path; - subscriptions.add(onUpdate); -} - -export function migratePluginSettings(name: string, ...oldNames: string[]) { - const { plugins } = settings; - if (name in plugins) return; - - for (const oldName of oldNames) { - if (oldName in plugins) { - logger.info(`Migrating settings from old name ${oldName} to ${name}`); - plugins[name] = plugins[oldName]; - delete plugins[oldName]; - VencordNative.settings.set(JSON.stringify(settings, null, 4)); - break; - } - } -} - -export function definePluginSettings>(def: D, checks?: C) { - const definedSettings: DefinedSettings = { - get store() { - if (!definedSettings.pluginName) throw new Error("Cannot access settings before plugin is initialized"); - return Settings.plugins[definedSettings.pluginName] as any; - }, - use: settings => useSettings( - settings?.map(name => `plugins.${definedSettings.pluginName}.${name}`) as UseSettings[] - ).plugins[definedSettings.pluginName] as any, - def, - checks: checks ?? {}, - pluginName: "", - }; - return definedSettings; -} - -type UseSettings = ResolveUseSettings[keyof T]; - -type ResolveUseSettings = { - [Key in keyof T]: - Key extends string - ? T[Key] extends Record - // @ts-ignore "Type instantiation is excessively deep and possibly infinite" - ? UseSettings extends string ? `${Key}.${UseSettings}` : never - : Key - : never; -}; diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx index c34b47d..ea2e02b 100644 --- a/src/components/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary.tsx @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; -import { LazyComponent } from "@utils/misc"; +import { LazyComponent } from "@utils/react"; import { React } from "@webpack/common"; import { ErrorCard } from "./ErrorCard"; diff --git a/src/components/PatchHelper.tsx b/src/components/PatchHelper.tsx index 37782ef..6c95a8a 100644 --- a/src/components/PatchHelper.tsx +++ b/src/components/PatchHelper.tsx @@ -18,8 +18,8 @@ import { debounce } from "@utils/debounce"; import { Margins } from "@utils/margins"; -import { makeCodeblock } from "@utils/misc"; import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; +import { makeCodeblock } from "@utils/text"; import { ReplaceFn } from "@utils/types"; import { search } from "@webpack"; import { Button, Clipboard, Forms, Parser, React, Switch, Text, TextInput } from "@webpack/common"; diff --git a/src/components/PluginSettings/PluginModal.tsx b/src/components/PluginSettings/PluginModal.tsx index 3c5fc78..c502873 100644 --- a/src/components/PluginSettings/PluginModal.tsx +++ b/src/components/PluginSettings/PluginModal.tsx @@ -17,13 +17,14 @@ */ import { generateId } from "@api/Commands"; -import { useSettings } from "@api/settings"; +import { useSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; +import { proxyLazy } from "@utils/lazy"; import { Margins } from "@utils/margins"; -import { classes, LazyComponent } from "@utils/misc"; +import { classes } from "@utils/misc"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal"; -import { proxyLazy } from "@utils/proxyLazy"; +import { LazyComponent } from "@utils/react"; import { OptionType, Plugin } from "@utils/types"; import { findByCode, findByPropsLazy } from "@webpack"; import { Button, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common"; diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 5a367c8..7679c01 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -20,7 +20,7 @@ import "./styles.css"; import * as DataStore from "@api/DataStore"; import { showNotice } from "@api/Notices"; -import { useSettings } from "@api/settings"; +import { useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; @@ -29,11 +29,12 @@ import { Badge } from "@components/PluginSettings/components"; import PluginModal from "@components/PluginSettings/PluginModal"; import { Switch } from "@components/Switch"; import { ChangeList } from "@utils/ChangeList"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; -import { classes, LazyComponent, useAwaiter } from "@utils/misc"; +import { classes } from "@utils/misc"; import { openModalLazy } from "@utils/modal"; import { onlyOnce } from "@utils/onlyOnce"; +import { LazyComponent, useAwaiter } from "@utils/react"; import { Plugin } from "@utils/types"; import { findByCode, findByPropsLazy } from "@webpack"; import { Alerts, Button, Card, Forms, Parser, React, Select, Text, TextInput, Toasts, Tooltip } from "@webpack/common"; @@ -126,7 +127,7 @@ function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLe } // if the plugin has patches, dont use stopPlugin/startPlugin. Wait for restart to apply changes. - if (plugin.patches) { + if (plugin.patches?.length) { settings.enabled = !wasEnabled; onRestartNeeded(plugin.name); return; diff --git a/src/components/VencordSettings/CloudTab.tsx b/src/components/VencordSettings/CloudTab.tsx index 3452cef..5e48a72 100644 --- a/src/components/VencordSettings/CloudTab.tsx +++ b/src/components/VencordSettings/CloudTab.tsx @@ -17,7 +17,7 @@ */ import { showNotification } from "@api/Notifications"; -import { Settings, useSettings } from "@api/settings"; +import { Settings, useSettings } from "@api/Settings"; import { CheckedTextInput } from "@components/CheckedTextInput"; import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/VencordSettings/ThemesTab.tsx index bbd4fa9..75fea34 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/VencordSettings/ThemesTab.tsx @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -import { useSettings } from "@api/settings"; +import { useSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; import { Margins } from "@utils/margins"; -import { useAwaiter } from "@utils/misc"; +import { useAwaiter } from "@utils/react"; import { findLazy } from "@webpack"; import { Card, Forms, React, TextArea } from "@webpack/common"; diff --git a/src/components/VencordSettings/Updater.tsx b/src/components/VencordSettings/Updater.tsx index 6fec9e7..9345d27 100644 --- a/src/components/VencordSettings/Updater.tsx +++ b/src/components/VencordSettings/Updater.tsx @@ -16,16 +16,17 @@ * along with this program. If not, see . */ -import { useSettings } from "@api/settings"; +import { useSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { ErrorCard } from "@components/ErrorCard"; import { Flex } from "@components/Flex"; import { handleComponentFailed } from "@components/handleComponentFailed"; import { Link } from "@components/Link"; import { Margins } from "@utils/margins"; -import { classes, useAwaiter } from "@utils/misc"; +import { classes } from "@utils/misc"; import { relaunch } from "@utils/native"; import { onlyOnce } from "@utils/onlyOnce"; +import { useAwaiter } from "@utils/react"; import { changes, checkForUpdates, getRepo, isNewer, update, updateError, UpdateLogger } from "@utils/updater"; import { Alerts, Button, Card, Forms, Parser, React, Switch, Toasts } from "@webpack/common"; diff --git a/src/components/VencordSettings/VencordTab.tsx b/src/components/VencordSettings/VencordTab.tsx index 672e04e..8c71821 100644 --- a/src/components/VencordSettings/VencordTab.tsx +++ b/src/components/VencordSettings/VencordTab.tsx @@ -18,14 +18,15 @@ import { openNotificationLogModal } from "@api/Notifications/notificationLog"; -import { Settings, useSettings } from "@api/settings"; +import { Settings, useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import DonateButton from "@components/DonateButton"; import ErrorBoundary from "@components/ErrorBoundary"; import { ErrorCard } from "@components/ErrorCard"; import { Margins } from "@utils/margins"; -import { identity, useAwaiter } from "@utils/misc"; +import { identity } from "@utils/misc"; import { relaunch, showItemInFolder } from "@utils/native"; +import { useAwaiter } from "@utils/react"; import { Button, Card, Forms, React, Select, Slider, Switch } from "@webpack/common"; const cl = classNameFactory("vc-settings-"); diff --git a/src/debug/Tracer.ts b/src/debug/Tracer.ts index 185915a..4337e00 100644 --- a/src/debug/Tracer.ts +++ b/src/debug/Tracer.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; if (IS_DEV) { var traces = {} as Record; diff --git a/src/main/ipcMain.ts b/src/main/ipcMain.ts index b734f36..5fcf8b7 100644 --- a/src/main/ipcMain.ts +++ b/src/main/ipcMain.ts @@ -44,7 +44,7 @@ export function readSettings() { } } -export function getSettings(): typeof import("@api/settings").Settings { +export function getSettings(): typeof import("@api/Settings").Settings { try { return JSON.parse(readSettings()); } catch { diff --git a/src/plugins/anonymiseFileNames.ts b/src/plugins/anonymiseFileNames.ts index 26c423c..0baf099 100644 --- a/src/plugins/anonymiseFileNames.ts +++ b/src/plugins/anonymiseFileNames.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/apiBadges.tsx b/src/plugins/apiBadges.tsx index aaa1860..d9e97b2 100644 --- a/src/plugins/apiBadges.tsx +++ b/src/plugins/apiBadges.tsx @@ -22,7 +22,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Heart } from "@components/Heart"; import { Devs } from "@utils/constants"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { closeModal, Modals, openModal } from "@utils/modal"; import definePlugin from "@utils/types"; diff --git a/src/plugins/betterFolders/FolderSideBar.tsx b/src/plugins/betterFolders/FolderSideBar.tsx index 3e44a58..7159f7e 100644 --- a/src/plugins/betterFolders/FolderSideBar.tsx +++ b/src/plugins/betterFolders/FolderSideBar.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { findByPropsLazy, findStoreLazy } from "@webpack"; diff --git a/src/plugins/betterFolders/index.ts b/src/plugins/betterFolders/index.ts index d0e61c0..d41ba75 100644 --- a/src/plugins/betterFolders/index.ts +++ b/src/plugins/betterFolders/index.ts @@ -18,7 +18,7 @@ import "./betterFolders.css"; -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findLazy, findStoreLazy } from "@webpack"; diff --git a/src/plugins/betterNotes.ts b/src/plugins/betterNotes.ts index 4184259..d9c5b45 100644 --- a/src/plugins/betterNotes.ts +++ b/src/plugins/betterNotes.ts @@ -16,9 +16,8 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import { makeLazy } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; export default definePlugin({ @@ -30,7 +29,7 @@ export default definePlugin({ { find: "hideNote:", all: true, - predicate: makeLazy(() => Vencord.Settings.plugins.BetterNotesBox.hide), + predicate: () => Vencord.Settings.plugins.BetterNotesBox.hide, replacement: { match: /hideNote:.+?(?=[,}])/g, replace: "hideNote:true", diff --git a/src/plugins/betterRoleDot.ts b/src/plugins/betterRoleDot.ts index 6e026c7..773176d 100644 --- a/src/plugins/betterRoleDot.ts +++ b/src/plugins/betterRoleDot.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { Clipboard, Toasts } from "@webpack/common"; diff --git a/src/plugins/blurNsfw.ts b/src/plugins/blurNsfw.ts index b24ded9..dadc49b 100644 --- a/src/plugins/blurNsfw.ts +++ b/src/plugins/blurNsfw.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/callTimer.tsx b/src/plugins/callTimer.tsx index f745bf6..9490eba 100644 --- a/src/plugins/callTimer.tsx +++ b/src/plugins/callTimer.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/crashHandler.ts b/src/plugins/crashHandler.ts index c70d467..f15fb8e 100644 --- a/src/plugins/crashHandler.ts +++ b/src/plugins/crashHandler.ts @@ -17,9 +17,9 @@ */ import { showNotification } from "@api/Notifications"; -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { closeAllModals } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; import { maybePromptToUpdate } from "@utils/updater"; diff --git a/src/plugins/customRPC.tsx b/src/plugins/customRPC.tsx index ecd77e9..27776ef 100644 --- a/src/plugins/customRPC.tsx +++ b/src/plugins/customRPC.tsx @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Link } from "@components/Link"; import { Devs } from "@utils/constants"; import { isTruthy } from "@utils/guards"; -import { useAwaiter } from "@utils/misc"; +import { useAwaiter } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; import { filters, findByCodeLazy, findByPropsLazy, mapMangledModuleLazy } from "@webpack"; import { diff --git a/src/plugins/devCompanion.dev.tsx b/src/plugins/devCompanion.dev.tsx index 161cdf9..2fa01f2 100644 --- a/src/plugins/devCompanion.dev.tsx +++ b/src/plugins/devCompanion.dev.tsx @@ -17,9 +17,9 @@ */ import { showNotification } from "@api/Notifications"; -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; import { filters, findAll, search } from "@webpack"; diff --git a/src/plugins/emoteCloner.tsx b/src/plugins/emoteCloner.tsx index 61eec88..0d65148 100644 --- a/src/plugins/emoteCloner.tsx +++ b/src/plugins/emoteCloner.tsx @@ -19,7 +19,7 @@ import { addContextMenuPatch, findGroupChildrenByChildId, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; import { CheckedTextInput } from "@components/CheckedTextInput"; import { Devs } from "@utils/constants"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { ModalContent, ModalHeader, ModalRoot, openModal } from "@utils/modal"; import definePlugin from "@utils/types"; diff --git a/src/plugins/experiments.tsx b/src/plugins/experiments.tsx index 686b822..ed29aa7 100644 --- a/src/plugins/experiments.tsx +++ b/src/plugins/experiments.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; diff --git a/src/plugins/fakeNitro.tsx b/src/plugins/fakeNitro.tsx index 1fb9fc3..52a9d25 100644 --- a/src/plugins/fakeNitro.tsx +++ b/src/plugins/fakeNitro.tsx @@ -17,11 +17,11 @@ */ import { addPreEditListener, addPreSendListener, removePreEditListener, removePreSendListener } from "@api/MessageEvents"; -import { definePluginSettings, Settings } from "@api/settings"; +import { definePluginSettings, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { ApngBlendOp, ApngDisposeOp, getGifEncoder, importApngJs } from "@utils/dependencies"; import { getCurrentGuild } from "@utils/discord"; -import { proxyLazy } from "@utils/proxyLazy"; +import { proxyLazy } from "@utils/lazy"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy, findByPropsLazy, findLazy, findStoreLazy } from "@webpack"; import { ChannelStore, FluxDispatcher, Parser, PermissionStore, UserStore } from "@webpack/common"; diff --git a/src/plugins/fakeProfileThemes.tsx b/src/plugins/fakeProfileThemes.tsx index 8a0db1d..70003e5 100644 --- a/src/plugins/fakeProfileThemes.tsx +++ b/src/plugins/fakeProfileThemes.tsx @@ -17,7 +17,7 @@ */ // This plugin is a port from Alyxia's Vendetta plugin -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; diff --git a/src/plugins/fart.ts b/src/plugins/fart.ts index 9404b39..b92a41d 100644 --- a/src/plugins/fart.ts +++ b/src/plugins/fart.ts @@ -17,7 +17,7 @@ */ import { ApplicationCommandOptionType } from "@api/Commands"; -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { makeRange } from "@components/PluginSettings/components"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/ignoreActivities.tsx b/src/plugins/ignoreActivities.tsx index f141dce..534b3f7 100644 --- a/src/plugins/ignoreActivities.tsx +++ b/src/plugins/ignoreActivities.tsx @@ -19,7 +19,7 @@ import * as DataStore from "@api/DataStore"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; -import { useForceUpdater } from "@utils/misc"; +import { useForceUpdater } from "@utils/react"; import definePlugin from "@utils/types"; import { findByPropsLazy, findStoreLazy } from "@webpack"; import { Tooltip } from "webpack/common"; diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index 9007bf4..da6ac69 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -17,7 +17,7 @@ */ import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; import { makeRange } from "@components/PluginSettings/components"; import { Devs } from "@utils/constants"; diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 404f638..f6d5772 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -17,8 +17,8 @@ */ import { registerCommand, unregisterCommand } from "@api/Commands"; -import { Settings } from "@api/settings"; -import Logger from "@utils/Logger"; +import { Settings } from "@api/Settings"; +import { Logger } from "@utils/Logger"; import { Patch, Plugin } from "@utils/types"; import { FluxDispatcher } from "@webpack/common"; import { FluxEvents } from "@webpack/types"; diff --git a/src/plugins/invisibleChat/index.tsx b/src/plugins/invisibleChat/index.tsx index 0501a18..eb92d76 100644 --- a/src/plugins/invisibleChat/index.tsx +++ b/src/plugins/invisibleChat/index.tsx @@ -17,7 +17,7 @@ */ import { addButton, removeButton } from "@api/MessagePopover"; -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getStegCloak } from "@utils/dependencies"; diff --git a/src/plugins/lastfm.tsx b/src/plugins/lastfm.tsx index c001a59..380d1ea 100644 --- a/src/plugins/lastfm.tsx +++ b/src/plugins/lastfm.tsx @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Link } from "@components/Link"; import { Devs } from "@utils/constants"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { filters, findByPropsLazy, mapMangledModuleLazy } from "@webpack"; import { FluxDispatcher, Forms } from "@webpack/common"; diff --git a/src/plugins/messageLinkEmbeds.tsx b/src/plugins/messageLinkEmbeds.tsx index 951835a..d1fcbf3 100644 --- a/src/plugins/messageLinkEmbeds.tsx +++ b/src/plugins/messageLinkEmbeds.tsx @@ -17,11 +17,12 @@ */ import { addAccessory } from "@api/MessageAccessories"; -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants.js"; -import { classes, LazyComponent } from "@utils/misc"; +import { classes } from "@utils/misc"; import { Queue } from "@utils/Queue"; +import { LazyComponent } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; import { find, findByCode, findByPropsLazy } from "@webpack"; import { diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index 484429f..2da7c2e 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -19,11 +19,11 @@ import "./messageLogger.css"; import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; -import Logger from "@utils/Logger"; +import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; import { FluxDispatcher, i18n, Menu, moment, Parser, Timestamp, UserStore } from "@webpack/common"; diff --git a/src/plugins/messageTags.ts b/src/plugins/messageTags.ts index 02d1e52..d65c388 100644 --- a/src/plugins/messageTags.ts +++ b/src/plugins/messageTags.ts @@ -18,7 +18,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, registerCommand, sendBotMessage, unregisterCommand } from "@api/Commands"; import * as DataStore from "@api/DataStore"; -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/moreUserTags.ts b/src/plugins/moreUserTags.ts index 3fa0aa1..90662b0 100644 --- a/src/plugins/moreUserTags.ts +++ b/src/plugins/moreUserTags.ts @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import { proxyLazy } from "@utils/proxyLazy.js"; +import { proxyLazy } from "@utils/lazy.js"; import definePlugin, { OptionType } from "@utils/types"; import { find, findByPropsLazy } from "@webpack"; import { ChannelStore, GuildStore } from "@webpack/common"; diff --git a/src/plugins/moyai.ts b/src/plugins/moyai.ts index b32bd99..1a48bd6 100644 --- a/src/plugins/moyai.ts +++ b/src/plugins/moyai.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { makeRange } from "@components/PluginSettings/components/SettingSliderComponent"; import { Devs } from "@utils/constants"; import { sleep } from "@utils/misc"; diff --git a/src/plugins/muteNewGuild.tsx b/src/plugins/muteNewGuild.tsx index cf15b77..e5e618f 100644 --- a/src/plugins/muteNewGuild.tsx +++ b/src/plugins/muteNewGuild.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { ModalContent, ModalFooter, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/noBlockedMessages.ts b/src/plugins/noBlockedMessages.ts index d91572a..54bb2d0 100644 --- a/src/plugins/noBlockedMessages.ts +++ b/src/plugins/noBlockedMessages.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; diff --git a/src/plugins/noReplyMention.tsx b/src/plugins/noReplyMention.tsx index 1351ec4..3ec8aef 100644 --- a/src/plugins/noReplyMention.tsx +++ b/src/plugins/noReplyMention.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings } from "@api/settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import type { Message } from "discord-types/general"; diff --git a/src/plugins/petpet.ts b/src/plugins/petpet.ts index 472c6c9..9b1c2f1 100644 --- a/src/plugins/petpet.ts +++ b/src/plugins/petpet.ts @@ -19,7 +19,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, Argument, CommandContext, findOption, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import { getGifEncoder } from "@utils/dependencies"; -import { makeLazy } from "@utils/misc"; +import { makeLazy } from "@utils/lazy"; import definePlugin from "@utils/types"; import { findByCodeLazy, findByPropsLazy } from "@webpack"; diff --git a/src/plugins/pinDms/settings.ts b/src/plugins/pinDms/settings.ts index e8bd267..1e0244e 100644 --- a/src/plugins/pinDms/settings.ts +++ b/src/plugins/pinDms/settings.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings, Settings, useSettings } from "@api/settings"; +import { definePluginSettings, Settings, useSettings } from "@api/Settings"; import { OptionType } from "@utils/types"; import { findStoreLazy } from "@webpack"; diff --git a/src/plugins/platformIndicators.tsx b/src/plugins/platformIndicators.tsx index d6b42a6..03165bf 100644 --- a/src/plugins/platformIndicators.tsx +++ b/src/plugins/platformIndicators.tsx @@ -19,7 +19,7 @@ import { addBadge, BadgePosition, ProfileBadge, removeBadge } from "@api/Badges"; import { addDecorator, removeDecorator } from "@api/MemberListDecorators"; import { addDecoration, removeDecoration } from "@api/MessageDecorations"; -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/plugins/pronoundb/pronoundbUtils.ts b/src/plugins/pronoundb/pronoundbUtils.ts index c079e36..6a1fb31 100644 --- a/src/plugins/pronoundb/pronoundbUtils.ts +++ b/src/plugins/pronoundb/pronoundbUtils.ts @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { Settings } from "@api/Settings"; import { VENCORD_USER_AGENT } from "@utils/constants"; import { debounce } from "@utils/debounce"; -import { useAwaiter } from "@utils/misc"; +import { useAwaiter } from "@utils/react"; import { UserStore } from "@webpack/common"; import { settings } from "./settings"; diff --git a/src/pl