Fix initializing custom themes with ThemeStore too early

This commit is contained in:
Nuckyz 2025-05-14 17:08:56 -03:00
parent 707d688887
commit c1f19d5288
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
11 changed files with 42 additions and 32 deletions

View file

@ -261,7 +261,7 @@ page.on("console", async e => {
const [, tag, message, otherMessage] = args as Array<string>; const [, tag, message, otherMessage] = args as Array<string>;
switch (tag) { switch (tag) {
case "WebpackInterceptor:": case "WebpackPatcher:":
const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/); const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/);
const patchSlowMatch = message.match(/Patch by (.+?) (took [\d.]+?ms) \(Module id is (.+?)\): (.+)/); const patchSlowMatch = message.match(/Patch by (.+?) (took [\d.]+?ms) \(Module id is (.+?)\): (.+)/);
const match = patchFailMatch ?? patchSlowMatch; const match = patchFailMatch ?? patchSlowMatch;

View file

@ -16,10 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { LazyComponent, LazyComponentWrapper } from "@utils/lazyReact";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins"; import { Margins } from "@utils/margins";
import { LazyComponent, LazyComponentWrapper } from "@utils/react"; import type { React } from "@webpack/common";
import { React } from "@webpack/common";
import { ErrorCard } from "./ErrorCard"; import { ErrorCard } from "./ErrorCard";
@ -46,7 +46,9 @@ const NO_ERROR = {};
// We might want to import this in a place where React isn't ready yet. // We might want to import this in a place where React isn't ready yet.
// Thus, wrap in a LazyComponent // Thus, wrap in a LazyComponent
const ErrorBoundary = LazyComponent(() => { const ErrorBoundary = LazyComponent(() => {
return class ErrorBoundary extends React.PureComponent<React.PropsWithChildren<Props>> { // This component is used in a lot of files which end up importing other Webpack commons and causing circular imports.
// For this reason, use a non import access here.
return class ErrorBoundary extends Vencord.Webpack.Common.React.PureComponent<React.PropsWithChildren<Props>> {
state = { state = {
error: NO_ERROR as any, error: NO_ERROR as any,
stack: "", stack: "",

View file

@ -46,13 +46,13 @@ async function runReporter() {
for (const patch of patches) { for (const patch of patches) {
if (!patch.all) { if (!patch.all) {
new Logger("WebpackInterceptor").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`); new Logger("WebpackPatcher").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`);
} }
} }
for (const [plugin, moduleId, match, totalTime] of patchTimings) { for (const [plugin, moduleId, match, totalTime] of patchTimings) {
if (totalTime > 5) { if (totalTime > 5) {
new Logger("WebpackInterceptor").warn(`Patch by ${plugin} took ${Math.round(totalTime * 100) / 100}ms (Module id is ${String(moduleId)}): ${match}`); new Logger("WebpackPatcher").warn(`Patch by ${plugin} took ${Math.round(totalTime * 100) / 100}ms (Module id is ${String(moduleId)}): ${match}`);
} }
} }

View file

@ -7,7 +7,7 @@
import { proxyLazy } from "@utils/lazy"; import { proxyLazy } from "@utils/lazy";
import { sleep } from "@utils/misc"; import { sleep } from "@utils/misc";
import { Queue } from "@utils/Queue"; import { Queue } from "@utils/Queue";
import { Flux, FluxDispatcher, GuildChannelStore, PrivateChannelsStore } from "@webpack/common"; import { ChannelActionCreators, Flux, FluxDispatcher, GuildChannelStore } from "@webpack/common";
export const OnlineMemberCountStore = proxyLazy(() => { export const OnlineMemberCountStore = proxyLazy(() => {
const preloadQueue = new Queue(); const preloadQueue = new Queue();
@ -22,7 +22,7 @@ export const OnlineMemberCountStore = proxyLazy(() => {
async _ensureCount(guildId: string) { async _ensureCount(guildId: string) {
if (onlineMemberMap.has(guildId)) return; if (onlineMemberMap.has(guildId)) return;
await PrivateChannelsStore.preload(guildId, GuildChannelStore.getDefaultChannel(guildId).id); await ChannelActionCreators.preload(guildId, GuildChannelStore.getDefaultChannel(guildId).id);
} }
ensureCount(guildId?: string) { ensureCount(guildId?: string) {

View file

@ -17,7 +17,7 @@
*/ */
import { MessageObject } from "@api/MessageEvents"; import { MessageObject } from "@api/MessageEvents";
import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
import { Channel, Guild, Message, User } from "discord-types/general"; import { Channel, Guild, Message, User } from "discord-types/general";
import { Except } from "type-fest"; import { Except } from "type-fest";
@ -91,7 +91,7 @@ export function getCurrentGuild(): Guild | undefined {
} }
export function openPrivateChannel(userId: string) { export function openPrivateChannel(userId: string) {
PrivateChannelsStore.openPrivateChannel(userId); ChannelActionCreators.openPrivateChannel(userId);
} }
export const enum Theme { export const enum Theme {

View file

@ -19,7 +19,6 @@
import { Settings, SettingsStore } from "@api/Settings"; import { Settings, SettingsStore } from "@api/Settings";
import { ThemeStore } from "@webpack/common"; import { ThemeStore } from "@webpack/common";
let style: HTMLStyleElement; let style: HTMLStyleElement;
let themesStyle: HTMLStyleElement; let themesStyle: HTMLStyleElement;
@ -61,7 +60,10 @@ async function initThemes() {
const { themeLinks, enabledThemes } = Settings; const { themeLinks, enabledThemes } = Settings;
// "darker" and "midnight" both count as dark // "darker" and "midnight" both count as dark
const activeTheme = ThemeStore.theme === "light" ? "light" : "dark"; // This function is first called on DOMContentLoaded, so ThemeStore may not have been loaded yet
const activeTheme = ThemeStore == null
? undefined
: ThemeStore.theme === "light" ? "light" : "dark";
const links = themeLinks const links = themeLinks
.map(rawLink => { .map(rawLink => {
@ -90,7 +92,6 @@ async function initThemes() {
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
initSystemValues(); initSystemValues();
initThemes();
toggle(Settings.useQuickCss); toggle(Settings.useQuickCss);
SettingsStore.addChangeListener("useQuickCss", toggle); SettingsStore.addChangeListener("useQuickCss", toggle);
@ -98,6 +99,16 @@ document.addEventListener("DOMContentLoaded", () => {
SettingsStore.addChangeListener("themeLinks", initThemes); SettingsStore.addChangeListener("themeLinks", initThemes);
SettingsStore.addChangeListener("enabledThemes", initThemes); SettingsStore.addChangeListener("enabledThemes", initThemes);
if (!IS_WEB) {
VencordNative.quickCss.addThemeChangeListener(initThemes);
}
initThemes();
});
export function initQuickCssThemeStore() {
initThemes();
let currentTheme = ThemeStore.theme; let currentTheme = ThemeStore.theme;
ThemeStore.addChangeListener(() => { ThemeStore.addChangeListener(() => {
if (currentTheme === ThemeStore.theme) return; if (currentTheme === ThemeStore.theme) return;
@ -105,7 +116,4 @@ document.addEventListener("DOMContentLoaded", () => {
currentTheme = ThemeStore.theme; currentTheme = ThemeStore.theme;
initThemes(); initThemes();
}); });
}
if (!IS_WEB)
VencordNative.quickCss.addThemeChangeListener(initThemes);
});

View file

@ -17,9 +17,7 @@
*/ */
import { LazyComponent, LazyComponentWrapper } from "@utils/react"; import { LazyComponent, LazyComponentWrapper } from "@utils/react";
import { FilterFn, filters, lazyWebpackSearchHistory, waitFor } from "@webpack";
// eslint-disable-next-line path-alias/no-relative
import { FilterFn, filters, lazyWebpackSearchHistory, waitFor } from "../webpack";
export function waitForComponent<T extends React.ComponentType<any> = React.ComponentType<any> & Record<string, any>>(name: string, filter: FilterFn | string | string[]) { export function waitForComponent<T extends React.ComponentType<any> = React.ComponentType<any> & Record<string, any>>(name: string, filter: FilterFn | string | string[]) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["waitForComponent", Array.isArray(filter) ? filter : [filter]]); if (IS_REPORTER) lazyWebpackSearchHistory.push(["waitForComponent", Array.isArray(filter) ? filter : [filter]]);

View file

@ -16,8 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
// eslint-disable-next-line path-alias/no-relative import { filters, mapMangledModuleLazy, waitFor, wreq } from "@webpack";
import { filters, mapMangledModuleLazy, waitFor, wreq } from "../webpack";
import type * as t from "./types/menu"; import type * as t from "./types/menu";
export const Menu = {} as t.Menu; export const Menu = {} as t.Menu;

View file

@ -16,8 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
// eslint-disable-next-line path-alias/no-relative import { findByCodeLazy, findByPropsLazy, waitFor } from "@webpack";
import { findByCodeLazy, findByPropsLazy, waitFor } from "../webpack";
export let React: typeof import("react"); export let React: typeof import("react");
export let useState: typeof React.useState; export let useState: typeof React.useState;

View file

@ -16,10 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { findByCodeLazy, findByPropsLazy } from "@webpack";
import type * as Stores from "discord-types/stores"; import type * as Stores from "discord-types/stores";
// eslint-disable-next-line path-alias/no-relative
import { findByCodeLazy, findByPropsLazy } from "../webpack";
import { waitForStore } from "./internal"; import { waitForStore } from "./internal";
import * as t from "./types/stores"; import * as t from "./types/stores";
@ -33,7 +32,7 @@ export let MessageStore: Omit<Stores.MessageStore, "getMessages"> & GenericStore
getMessages(chanId: string): any; getMessages(chanId: string): any;
}; };
// this is not actually a FluxStore // TODO: The correct name for this is ChannelActionCreators and it has already been exported again from utils. Remove this export once enough time has passed
export const PrivateChannelsStore = findByPropsLazy("openPrivateChannel"); export const PrivateChannelsStore = findByPropsLazy("openPrivateChannel");
export let PermissionStore: GenericStore; export let PermissionStore: GenericStore;
export let GuildChannelStore: GenericStore; export let GuildChannelStore: GenericStore;
@ -86,4 +85,8 @@ waitForStore("GuildChannelStore", m => GuildChannelStore = m);
waitForStore("MessageStore", m => MessageStore = m); waitForStore("MessageStore", m => MessageStore = m);
waitForStore("WindowStore", m => WindowStore = m); waitForStore("WindowStore", m => WindowStore = m);
waitForStore("EmojiStore", m => EmojiStore = m); waitForStore("EmojiStore", m => EmojiStore = m);
waitForStore("ThemeStore", m => ThemeStore = m); waitForStore("ThemeStore", m => {
ThemeStore = m;
// Importing this directly can easily cause circular imports. For this reason, use a non import access here.
Vencord.QuickCss.initQuickCssThemeStore();
});

View file

@ -16,16 +16,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { _resolveReady, filters, findByCodeLazy, findByPropsLazy, findLazy, mapMangledModuleLazy, waitFor } from "@webpack";
import type { Channel } from "discord-types/general"; import type { Channel } from "discord-types/general";
// eslint-disable-next-line path-alias/no-relative
import { _resolveReady, filters, findByCodeLazy, findByPropsLazy, findLazy, mapMangledModuleLazy, waitFor } from "../webpack";
import type * as t from "./types/utils"; import type * as t from "./types/utils";
export let FluxDispatcher: t.FluxDispatcher; export let FluxDispatcher: t.FluxDispatcher;
waitFor(["dispatch", "subscribe"], m => { waitFor(["dispatch", "subscribe"], m => {
FluxDispatcher = m; FluxDispatcher = m;
// Non import call to avoid circular dependency // Non import access to avoid circular dependency
Vencord.Plugins.subscribeAllPluginsFluxEvents(m); Vencord.Plugins.subscribeAllPluginsFluxEvents(m);
const cb = () => { const cb = () => {
@ -35,7 +34,7 @@ waitFor(["dispatch", "subscribe"], m => {
m.subscribe("CONNECTION_OPEN", cb); m.subscribe("CONNECTION_OPEN", cb);
}); });
export let ComponentDispatch; export let ComponentDispatch: any;
waitFor(["dispatchToLastSubscribed"], m => ComponentDispatch = m); waitFor(["dispatchToLastSubscribed"], m => ComponentDispatch = m);
export const Constants: t.Constants = mapMangledModuleLazy('ME:"/users/@me"', { export const Constants: t.Constants = mapMangledModuleLazy('ME:"/users/@me"', {
@ -177,6 +176,7 @@ export const MessageActions = findByPropsLazy("editMessage", "sendMessage");
export const MessageCache = findByPropsLazy("clearCache", "_channelMessages"); export const MessageCache = findByPropsLazy("clearCache", "_channelMessages");
export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal"); export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");
export const InviteActions = findByPropsLazy("resolveInvite"); export const InviteActions = findByPropsLazy("resolveInvite");
export const ChannelActionCreators = findByPropsLazy("openPrivateChannel");
export const IconUtils: t.IconUtils = findByPropsLazy("getGuildBannerURL", "getUserAvatarURL"); export const IconUtils: t.IconUtils = findByPropsLazy("getGuildBannerURL", "getUserAvatarURL");