From 1d995e58f515dbeb908ba34bf70f829bfd3ccfac Mon Sep 17 00:00:00 2001 From: Ven Date: Fri, 10 Feb 2023 22:33:34 +0100 Subject: Notification API (#467) Co-authored-by: Ven Co-authored-by: afn Co-authored-by: afn --- src/webpack/common/components.ts | 3 ++ src/webpack/common/internal.tsx | 6 ++- src/webpack/common/react.ts | 2 +- src/webpack/common/stores.ts | 77 +++++++++++++++++++++++--------- src/webpack/common/types/components.d.ts | 6 +-- src/webpack/common/types/index.d.ts | 1 + src/webpack/common/types/stores.d.ts | 40 +++++++++++++++++ src/webpack/common/types/utils.d.ts | 14 ------ src/webpack/common/utils.ts | 1 - 9 files changed, 109 insertions(+), 41 deletions(-) create mode 100644 src/webpack/common/types/stores.d.ts (limited to 'src/webpack/common') diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index be585c3..27d103f 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -49,5 +49,8 @@ export const Slider = waitForComponent("Slider", filters.byCode("close export const Flex = waitForComponent("Flex", ["Justify", "Align", "Wrap"]); export const ButtonWrapperClasses = findByPropsLazy("buttonWrapper", "buttonContent") as Record; +/** + * @deprecated Use @utils/margins instead + */ export const Margins: t.Margins = findByPropsLazy("marginTop20"); export const ButtonLooks: t.ButtonLooks = findByPropsLazy("BLANK", "FILLED", "INVERTED"); diff --git a/src/webpack/common/internal.tsx b/src/webpack/common/internal.tsx index df768f7..e2f42d8 100644 --- a/src/webpack/common/internal.tsx +++ b/src/webpack/common/internal.tsx @@ -19,7 +19,7 @@ import { LazyComponent } from "@utils/misc"; // eslint-disable-next-line path-alias/no-relative -import { FilterFn, waitFor } from "../webpack"; +import { FilterFn, filters, waitFor } from "../webpack"; export function waitForComponent = React.ComponentType & Record>(name: string, filter: FilterFn | string | string[]): T { let myValue: T = function () { @@ -34,3 +34,7 @@ export function waitForComponent = React.Comp return lazyComponent; } + +export function waitForStore(name: string, cb: (v: any) => void) { + waitFor(filters.byStoreName(name), cb); +} diff --git a/src/webpack/common/react.ts b/src/webpack/common/react.ts index 455f39b..d73a3df 100644 --- a/src/webpack/common/react.ts +++ b/src/webpack/common/react.ts @@ -25,7 +25,7 @@ export let useEffect: typeof React.useEffect; export let useMemo: typeof React.useMemo; export let useRef: typeof React.useRef; -export const ReactDOM: typeof import("react-dom") = findByPropsLazy("createPortal", "render"); +export const ReactDOM: typeof import("react-dom") & typeof import("react-dom/client") = findByPropsLazy("createPortal", "render"); waitFor("useState", m => { React = m; diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index bcd26b1..0bd9e87 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -19,36 +19,71 @@ import type * as Stores from "discord-types/stores"; // eslint-disable-next-line path-alias/no-relative -import { filters, findByPropsLazy, mapMangledModuleLazy, waitFor } from "../webpack"; +import { filters, findByCodeLazy, findByPropsLazy, mapMangledModuleLazy } from "../webpack"; +import { waitForStore } from "./internal"; +import * as t from "./types/stores"; -export const MessageStore = findByPropsLazy("getRawMessages") as Omit & { +export const Flux: t.Flux = findByPropsLazy("connectStores"); + +type GenericStore = t.FluxStore & Record; + +export let MessageStore: Omit & { getMessages(chanId: string): any; }; -export const PermissionStore = findByPropsLazy("can", "getGuildPermissions"); + +// this is not actually a FluxStore export const PrivateChannelsStore = findByPropsLazy("openPrivateChannel"); -export const GuildChannelStore = findByPropsLazy("getChannels"); -export const ReadStateStore = findByPropsLazy("lastMessageId"); -export const PresenceStore = findByPropsLazy("setCurrentUserOnConnectionOpen"); - -export let GuildStore: Stores.GuildStore; -export let UserStore: Stores.UserStore; -export let SelectedChannelStore: Stores.SelectedChannelStore; -export let SelectedGuildStore: any; -export let ChannelStore: Stores.ChannelStore; -export let GuildMemberStore: Stores.GuildMemberStore; -export let RelationshipStore: Stores.RelationshipStore & { +export let PermissionStore: GenericStore; +export let GuildChannelStore: GenericStore; +export let ReadStateStore: GenericStore; +export let PresenceStore: GenericStore; + +export let GuildStore: Stores.GuildStore & t.FluxStore; +export let UserStore: Stores.UserStore & t.FluxStore; +export let SelectedChannelStore: Stores.SelectedChannelStore & t.FluxStore; +export let SelectedGuildStore: t.FluxStore & Record; +export let ChannelStore: Stores.ChannelStore & t.FluxStore; +export let GuildMemberStore: Stores.GuildMemberStore & t.FluxStore; +export let RelationshipStore: Stores.RelationshipStore & t.FluxStore & { /** Get the date (as a string) that the relationship was created */ getSince(userId: string): string; }; +export let WindowStore: t.WindowStore; + export const MaskedLinkStore = mapMangledModuleLazy('"MaskedLinkStore"', { openUntrustedLink: filters.byCode(".apply(this,arguments)") }); -waitFor(["getCurrentUser", "initialize"], m => UserStore = m); -waitFor("getSortedPrivateChannels", m => ChannelStore = m); -waitFor("getCurrentlySelectedChannelId", m => SelectedChannelStore = m); -waitFor("getLastSelectedGuildId", m => SelectedGuildStore = m); -waitFor("getGuildCount", m => GuildStore = m); -waitFor(["getMember", "initialize"], m => GuildMemberStore = m); -waitFor("getRelationshipType", m => RelationshipStore = m); +/** + * React hook that returns stateful data for one or more stores + * You might need a custom comparator (4th argument) if your store data is an object + * + * @param stores The stores to listen to + * @param mapper A function that returns the data you need + * @param idk some thing, idk just pass null + * @param isEqual A custom comparator for the data returned by mapper + * + * @example const user = useStateFromStores([UserStore], () => UserStore.getCurrentUser(), null, (old, current) => old.id === current.id); + */ +export const useStateFromStores: ( + stores: t.FluxStore[], + mapper: () => T, + idk?: any, + isEqual?: (old: T, newer: T) => boolean +) => T + = findByCodeLazy("useStateFromStores"); + +waitForStore("UserStore", s => UserStore = s); +waitForStore("ChannelStore", m => ChannelStore = m); +waitForStore("SelectedChannelStore", m => SelectedChannelStore = m); +waitForStore("SelectedGuildStore", m => SelectedGuildStore = m); +waitForStore("GuildStore", m => GuildStore = m); +waitForStore("GuildMemberStore", m => GuildMemberStore = m); +waitForStore("RelationshipStore", m => RelationshipStore = m); +waitForStore("PermissionStore", m => PermissionStore = m); +waitForStore("PresenceStore", m => PresenceStore = m); +waitForStore("ReadStateStore", m => ReadStateStore = m); +waitForStore("GuildChannelStore", m => GuildChannelStore = m); +waitForStore("MessageStore", m => MessageStore = m); +waitForStore("WindowStore", m => WindowStore = m); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index 3f76c22..9cd01de 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -215,9 +215,9 @@ export type Select = ComponentType. +*/ + +import { FluxDispatcher, FluxEvents } from "./utils"; + +export class FluxStore { + constructor(dispatcher: FluxDispatcher, eventHandlers?: Partial void>>); + + emitChange(): void; + getDispatchToken(): string; + getName(): string; + initialize(): void; + initializeIfNeeded(): void; + __getLocalVars(): Record; +} + +export interface Flux { + Store: typeof FluxStore; +} + +export class WindowStore extends FluxStore { + isElementFullScreen(): boolean; + isFocused(): boolean; + windowSize(): Record<"width" | "height", number>; +} diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts index 7222be4..0e2a6ca 100644 --- a/src/webpack/common/types/utils.d.ts +++ b/src/webpack/common/types/utils.d.ts @@ -31,20 +31,6 @@ export interface FluxDispatcher { unsubscribe(event: FluxEvents, callback: (data: any) => void): void; } -declare class FluxStore { - constructor(dispatcher: FluxDispatcher, eventHandlers?: Partial void>>); - - emitChange(): void; - getDispatchToken(): string; - getName(): string; - initialize(): void; - initializeIfNeeded(): void; -} - -export interface Flux { - Store: typeof FluxStore; -} - export type Parser = Record< | "parse" | "parseTopic" diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index daac207..b53c340 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -23,7 +23,6 @@ import { _resolveReady,filters, findByCodeLazy, findByPropsLazy, mapMangledModul import type * as t from "./types/utils"; export let FluxDispatcher: t.FluxDispatcher; -export const Flux: t.Flux = findByPropsLazy("connectStores"); export const RestAPI: t.RestAPI = findByPropsLazy("getAPIBaseURL", "get"); export const moment: typeof import("moment") = findByPropsLazy("parseTwoDigitYear"); -- cgit