feat(plugin): BiggerStreamPreview (#1222)
Co-authored-by: V <vendicated@riseup.net>
This commit is contained in:
parent
55af40ee74
commit
e8d90d2b45
|
@ -147,6 +147,26 @@ export function OwnerCrownIcon(props: IconProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discord's screenshare icon, as seen in the connection panel
|
||||||
|
*/
|
||||||
|
export function ScreenshareIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
{...props}
|
||||||
|
className={classes(props.className, "vc-screenshare-icon")}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M2 4.5C2 3.397 2.897 2.5 4 2.5H20C21.103 2.5 22 3.397 22 4.5V15.5C22 16.604 21.103 17.5 20 17.5H13V19.5H17V21.5H7V19.5H11V17.5H4C2.897 17.5 2 16.604 2 15.5V4.5ZM13.2 14.3375V11.6C9.864 11.6 7.668 12.6625 6 15C6.672 11.6625 8.532 8.3375 13.2 7.6625V5L18 9.6625L13.2 14.3375Z"
|
||||||
|
/>
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function ImageVisible(props: IconProps) {
|
export function ImageVisible(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
|
|
101
src/plugins/biggerStreamPreview/index.tsx
Normal file
101
src/plugins/biggerStreamPreview/index.tsx
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2023 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu";
|
||||||
|
import { ScreenshareIcon } from "@components/Icons";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import { openImageModal } from "@utils/discord";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
import { Menu } from "@webpack/common";
|
||||||
|
import { Channel, User } from "discord-types/general";
|
||||||
|
|
||||||
|
import { ApplicationStreamingStore, ApplicationStreamPreviewStore } from "./webpack/stores";
|
||||||
|
import { ApplicationStream, Stream } from "./webpack/types/stores";
|
||||||
|
|
||||||
|
export interface UserContextProps {
|
||||||
|
channel: Channel,
|
||||||
|
channelSelected: boolean,
|
||||||
|
className: string,
|
||||||
|
config: { context: string; };
|
||||||
|
context: string,
|
||||||
|
onHeightUpdate: Function,
|
||||||
|
position: string,
|
||||||
|
target: HTMLElement,
|
||||||
|
theme: string,
|
||||||
|
user: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StreamContextProps {
|
||||||
|
appContext: string,
|
||||||
|
className: string,
|
||||||
|
config: { context: string; };
|
||||||
|
context: string,
|
||||||
|
exitFullscreen: Function,
|
||||||
|
onHeightUpdate: Function,
|
||||||
|
position: string,
|
||||||
|
target: HTMLElement,
|
||||||
|
stream: Stream,
|
||||||
|
theme: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handleViewPreview = async ({ guildId, channelId, ownerId }: ApplicationStream | Stream) => {
|
||||||
|
const previewUrl = await ApplicationStreamPreviewStore.getPreviewURL(guildId, channelId, ownerId);
|
||||||
|
if (!previewUrl) return;
|
||||||
|
|
||||||
|
openImageModal(previewUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addViewStreamContext: NavContextMenuPatchCallback = (children, { userId }: { userId: string | bigint; }) => () => {
|
||||||
|
const streamPreviewItemIdentifier = "view-stream-preview";
|
||||||
|
|
||||||
|
const stream = ApplicationStreamingStore.getAnyStreamForUser(userId);
|
||||||
|
|
||||||
|
const streamPreviewItem = (
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="View Stream Preview"
|
||||||
|
id={streamPreviewItemIdentifier}
|
||||||
|
icon={ScreenshareIcon}
|
||||||
|
action={() => stream && handleViewPreview(stream)}
|
||||||
|
disabled={!stream}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
children.push(<Menu.MenuSeparator />, streamPreviewItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const streamContextPatch: NavContextMenuPatchCallback = (children, { stream }: StreamContextProps) => {
|
||||||
|
return addViewStreamContext(children, { userId: stream.ownerId });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const userContextPatch: NavContextMenuPatchCallback = (children, { user }: UserContextProps) => {
|
||||||
|
return addViewStreamContext(children, { userId: user.id });
|
||||||
|
};
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "BiggerStreamPreview",
|
||||||
|
description: "This plugin allows you to enlarge stream previews",
|
||||||
|
authors: [Devs.phil],
|
||||||
|
start: () => {
|
||||||
|
addContextMenuPatch("user-context", userContextPatch);
|
||||||
|
addContextMenuPatch("stream-context", streamContextPatch);
|
||||||
|
},
|
||||||
|
stop: () => {
|
||||||
|
removeContextMenuPatch("user-context", userContextPatch);
|
||||||
|
removeContextMenuPatch("stream-context", streamContextPatch);
|
||||||
|
}
|
||||||
|
});
|
25
src/plugins/biggerStreamPreview/webpack/stores.ts
Normal file
25
src/plugins/biggerStreamPreview/webpack/stores.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2023 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import { findStoreLazy } from "@webpack";
|
||||||
|
|
||||||
|
import * as t from "./types/stores";
|
||||||
|
|
||||||
|
export const ApplicationStreamPreviewStore: t.ApplicationStreamPreviewStore = findStoreLazy("ApplicationStreamPreviewStore");
|
||||||
|
export const ApplicationStreamingStore: t.ApplicationStreamingStore = findStoreLazy("ApplicationStreamingStore");
|
77
src/plugins/biggerStreamPreview/webpack/types/stores.ts
Normal file
77
src/plugins/biggerStreamPreview/webpack/types/stores.ts
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2023 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FluxStore } from "@webpack/types";
|
||||||
|
|
||||||
|
export interface ApplicationStreamPreviewStore extends FluxStore {
|
||||||
|
getIsPreviewLoading: (guildId: string | bigint | null, channelId: string | bigint, ownerId: string | bigint) => boolean;
|
||||||
|
getPreviewURL: (guildId: string | bigint | null, channelId: string | bigint, ownerId: string | bigint) => Promise<string | null>;
|
||||||
|
getPreviewURLForStreamKey: (streamKey: string) => ReturnType<ApplicationStreamPreviewStore["getPreviewURL"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApplicationStream {
|
||||||
|
streamType: string;
|
||||||
|
guildId: string | null;
|
||||||
|
channelId: string;
|
||||||
|
ownerId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Stream extends ApplicationStream {
|
||||||
|
state: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RTCStream {
|
||||||
|
region: string,
|
||||||
|
streamKey: string,
|
||||||
|
viewerIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StreamMetadata {
|
||||||
|
id: string | null,
|
||||||
|
pid: number | null,
|
||||||
|
sourceName: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StreamingStoreState {
|
||||||
|
activeStreams: [string, Stream][];
|
||||||
|
rtcStreams: { [key: string]: RTCStream; };
|
||||||
|
streamerActiveStreamMetadatas: { [key: string]: StreamMetadata | null; };
|
||||||
|
streamsByUserAndGuild: { [key: string]: { [key: string]: ApplicationStream; }; };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* example how a stream key could look like: `call(type of connection):1116549917987192913(channelId):305238513941667851(ownerId)`
|
||||||
|
*/
|
||||||
|
export interface ApplicationStreamingStore extends FluxStore {
|
||||||
|
getActiveStreamForApplicationStream: (stream: ApplicationStream) => Stream | null;
|
||||||
|
getActiveStreamForStreamKey: (streamKey: string) => Stream | null;
|
||||||
|
getActiveStreamForUser: (userId: string | bigint, guildId?: string | bigint | null) => Stream | null;
|
||||||
|
getAllActiveStreams: () => Stream[];
|
||||||
|
getAllApplicationStreams: () => ApplicationStream[];
|
||||||
|
getAllApplicationStreamsForChannel: (channelId: string | bigint) => ApplicationStream[];
|
||||||
|
getAllActiveStreamsForChannel: (channelId: string | bigint) => Stream[];
|
||||||
|
getAnyStreamForUser: (userId: string | bigint) => Stream | ApplicationStream | null;
|
||||||
|
getStreamForUser: (userId: string | bigint, guildId?: string | bigint | null) => Stream | null;
|
||||||
|
getCurrentUserActiveStream: () => Stream | null;
|
||||||
|
getLastActiveStream: () => Stream | null;
|
||||||
|
getState: () => StreamingStoreState;
|
||||||
|
getRTCStream: (streamKey: string) => RTCStream | null;
|
||||||
|
getStreamerActiveStreamMetadata: () => StreamMetadata;
|
||||||
|
getViewerIds: (stream: ApplicationStream) => string[];
|
||||||
|
isSelfStreamHidden: (channelId: string | bigint | null) => boolean;
|
||||||
|
}
|
|
@ -20,15 +20,12 @@ import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatc
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { ImageIcon } from "@components/Icons";
|
import { ImageIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { openImageModal } from "@utils/discord";
|
||||||
import { LazyComponent } from "@utils/react";
|
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { find, findByCode, findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { GuildMemberStore, Menu } from "@webpack/common";
|
import { GuildMemberStore, Menu } from "@webpack/common";
|
||||||
import type { Channel, Guild, User } from "discord-types/general";
|
import type { Channel, Guild, User } from "discord-types/general";
|
||||||
|
|
||||||
const ImageModal = LazyComponent(() => findByCode(".MEDIA_MODAL_CLOSE,"));
|
|
||||||
const MaskedLink = LazyComponent(() => find(m => m.type?.toString().includes("MASKED_LINK)")));
|
|
||||||
const BannerStore = findByPropsLazy("getGuildBannerURL");
|
const BannerStore = findByPropsLazy("getGuildBannerURL");
|
||||||
|
|
||||||
interface UserContextProps {
|
interface UserContextProps {
|
||||||
|
@ -60,26 +57,29 @@ const settings = definePluginSettings({
|
||||||
value: "jpg",
|
value: "jpg",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
imgSize: {
|
||||||
|
type: OptionType.SELECT,
|
||||||
|
description: "The image size to use",
|
||||||
|
options: ["128", "256", "512", "1024", "2048", "4096"].map(n => ({ label: n, value: n, default: n === "1024" }))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function openImage(url: string) {
|
function openImage(url: string) {
|
||||||
const format = url.startsWith("/") ? "png" : settings.store.format;
|
const format = url.startsWith("/") ? "png" : settings.store.format;
|
||||||
|
|
||||||
const u = new URL(url, window.location.href);
|
const u = new URL(url, window.location.href);
|
||||||
u.searchParams.set("size", "512");
|
u.searchParams.set("size", settings.store.imgSize);
|
||||||
u.pathname = u.pathname.replace(/\.(png|jpe?g|webp)$/, `.${format}`);
|
u.pathname = u.pathname.replace(/\.(png|jpe?g|webp)$/, `.${format}`);
|
||||||
url = u.toString();
|
url = u.toString();
|
||||||
|
|
||||||
openModal(modalProps => (
|
u.searchParams.set("size", "4096");
|
||||||
<ModalRoot size={ModalSize.DYNAMIC} {...modalProps}>
|
const originalUrl = u.toString();
|
||||||
<ImageModal
|
|
||||||
shouldAnimate={true}
|
openImageModal(url, {
|
||||||
original={url}
|
original: originalUrl,
|
||||||
src={url}
|
height: 256
|
||||||
renderLinkComponent={MaskedLink}
|
});
|
||||||
/>
|
|
||||||
</ModalRoot>
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => () => {
|
const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => () => {
|
||||||
|
@ -90,7 +90,7 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
id="view-avatar"
|
id="view-avatar"
|
||||||
label="View Avatar"
|
label="View Avatar"
|
||||||
action={() => openImage(BannerStore.getUserAvatarURL(user, true, 512))}
|
action={() => openImage(BannerStore.getUserAvatarURL(user, true))}
|
||||||
icon={ImageIcon}
|
icon={ImageIcon}
|
||||||
/>
|
/>
|
||||||
{memberAvatar && (
|
{memberAvatar && (
|
||||||
|
@ -122,7 +122,6 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild: { id, icon
|
||||||
openImage(BannerStore.getGuildIconURL({
|
openImage(BannerStore.getGuildIconURL({
|
||||||
id,
|
id,
|
||||||
icon,
|
icon,
|
||||||
size: 512,
|
|
||||||
canAnimate: true
|
canAnimate: true
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,6 +319,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
name: "amia",
|
name: "amia",
|
||||||
id: 142007603549962240n
|
id: 142007603549962240n
|
||||||
},
|
},
|
||||||
|
phil: {
|
||||||
|
name: "phil",
|
||||||
|
id: 305288513941667851n
|
||||||
|
},
|
||||||
ImLvna: {
|
ImLvna: {
|
||||||
name: "Luna <3",
|
name: "Luna <3",
|
||||||
id: 174200708818665472n
|
id: 174200708818665472n
|
||||||
|
|
|
@ -18,9 +18,11 @@
|
||||||
|
|
||||||
import { MessageObject } from "@api/MessageEvents";
|
import { MessageObject } from "@api/MessageEvents";
|
||||||
import { findByPropsLazy, findLazy } from "@webpack";
|
import { findByPropsLazy, findLazy } from "@webpack";
|
||||||
import { ChannelStore, ComponentDispatch, GuildStore, PrivateChannelsStore, SelectedChannelStore } from "@webpack/common";
|
import { ChannelStore, ComponentDispatch, GuildStore, MaskedLink, ModalImageClasses, PrivateChannelsStore, SelectedChannelStore } from "@webpack/common";
|
||||||
import { Guild, Message } from "discord-types/general";
|
import { Guild, Message } from "discord-types/general";
|
||||||
|
|
||||||
|
import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal";
|
||||||
|
|
||||||
const PreloadedUserSettings = findLazy(m => m.ProtoClass?.typeName.endsWith("PreloadedUserSettings"));
|
const PreloadedUserSettings = findLazy(m => m.ProtoClass?.typeName.endsWith("PreloadedUserSettings"));
|
||||||
const MessageActions = findByPropsLazy("editMessage", "sendMessage");
|
const MessageActions = findByPropsLazy("editMessage", "sendMessage");
|
||||||
|
|
||||||
|
@ -77,3 +79,23 @@ export function sendMessage(
|
||||||
|
|
||||||
return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra);
|
return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function openImageModal(url: string, props?: Partial<React.ComponentProps<ImageModal>>): string {
|
||||||
|
return openModal(modalProps => (
|
||||||
|
<ModalRoot
|
||||||
|
{...modalProps}
|
||||||
|
className={ModalImageClasses.modal}
|
||||||
|
size={ModalSize.DYNAMIC}>
|
||||||
|
<ImageModal
|
||||||
|
className={ModalImageClasses.image}
|
||||||
|
original={url}
|
||||||
|
placeholder={url}
|
||||||
|
src={url}
|
||||||
|
renderLinkComponent={props => <MaskedLink {...props} />}
|
||||||
|
shouldHideMediaOptions={false}
|
||||||
|
shouldAnimate
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</ModalRoot>
|
||||||
|
));
|
||||||
|
}
|
|
@ -16,7 +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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { filters, mapMangledModuleLazy } from "@webpack";
|
import { filters, findByCode, mapMangledModuleLazy } from "@webpack";
|
||||||
import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react";
|
import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react";
|
||||||
|
|
||||||
import { LazyComponent } from "./react";
|
import { LazyComponent } from "./react";
|
||||||
|
@ -107,6 +107,25 @@ export const Modals = mapMangledModuleLazy(".closeWithCircleBackground", {
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ImageModal = ComponentType<{
|
||||||
|
className?: string;
|
||||||
|
src: string;
|
||||||
|
placeholder: string;
|
||||||
|
original: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
animated?: boolean;
|
||||||
|
responsive?: boolean;
|
||||||
|
renderLinkComponent(props: any): ReactNode;
|
||||||
|
maxWidth?: number;
|
||||||
|
maxHeight?: number;
|
||||||
|
shouldAnimate?: boolean;
|
||||||
|
onClose?(): void;
|
||||||
|
shouldHideMediaOptions?: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export const ImageModal = LazyComponent(() => findByCode(".renderLinkComponent", ".responsive") as ImageModal);
|
||||||
|
|
||||||
export const ModalRoot = LazyComponent(() => Modals.ModalRoot);
|
export const ModalRoot = LazyComponent(() => Modals.ModalRoot);
|
||||||
export const ModalHeader = LazyComponent(() => Modals.ModalHeader);
|
export const ModalHeader = LazyComponent(() => Modals.ModalHeader);
|
||||||
export const ModalContent = LazyComponent(() => Modals.ModalContent);
|
export const ModalContent = LazyComponent(() => Modals.ModalContent);
|
||||||
|
|
24
src/webpack/common/classes.ts
Normal file
24
src/webpack/common/classes.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2023 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { findByPropsLazy } from "@webpack";
|
||||||
|
|
||||||
|
import * as t from "./types/classes";
|
||||||
|
|
||||||
|
export const ModalImageClasses: t.ImageModalClasses = findByPropsLazy("image", "modal");
|
||||||
|
export const ButtonWrapperClasses: t.ButtonWrapperClasses = findByPropsLazy("buttonWrapper", "buttonContent");
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// eslint-disable-next-line path-alias/no-relative
|
// eslint-disable-next-line path-alias/no-relative
|
||||||
import { filters, findByPropsLazy, waitFor } from "@webpack";
|
import { filters, waitFor } from "@webpack";
|
||||||
|
|
||||||
import { waitForComponent } from "./internal";
|
import { waitForComponent } from "./internal";
|
||||||
import * as t from "./types/components";
|
import * as t from "./types/components";
|
||||||
|
@ -51,11 +51,10 @@ export let Avatar: t.Avatar;
|
||||||
/** css colour resolver stuff, no clue what exactly this does, just copied usage from Discord */
|
/** css colour resolver stuff, no clue what exactly this does, just copied usage from Discord */
|
||||||
export let useToken: t.useToken;
|
export let useToken: t.useToken;
|
||||||
|
|
||||||
|
export const MaskedLink = waitForComponent<t.MaskedLink>("MaskedLink", m => m?.type?.toString().includes("MASKED_LINK)"));
|
||||||
export const Timestamp = waitForComponent<t.Timestamp>("Timestamp", filters.byCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format"));
|
export const Timestamp = waitForComponent<t.Timestamp>("Timestamp", filters.byCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format"));
|
||||||
export const Flex = waitForComponent<t.Flex>("Flex", ["Justify", "Align", "Wrap"]);
|
export const Flex = waitForComponent<t.Flex>("Flex", ["Justify", "Align", "Wrap"]);
|
||||||
|
|
||||||
export const ButtonWrapperClasses = findByPropsLazy("buttonWrapper", "buttonContent") as Record<string, string>;
|
|
||||||
|
|
||||||
waitFor("FormItem", m => {
|
waitFor("FormItem", m => {
|
||||||
({ useToken, Card, Button, FormSwitch: Switch, Tooltip, TextInput, TextArea, Text, Select, SearchableSelect, Slider, ButtonLooks, TabBar, Popout, Dialog, Paginator, ScrollerThin, Clickable, Avatar } = m);
|
({ useToken, Card, Button, FormSwitch: Switch, Tooltip, TextInput, TextArea, Text, Select, SearchableSelect, Slider, ButtonLooks, TabBar, Popout, Dialog, Paginator, ScrollerThin, Clickable, Avatar } = m);
|
||||||
Forms = m;
|
Forms = m;
|
||||||
|
|
|
@ -16,6 +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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export * from "./classes";
|
||||||
export * from "./components";
|
export * from "./components";
|
||||||
export * from "./menu";
|
export * from "./menu";
|
||||||
export * from "./react";
|
export * from "./react";
|
||||||
|
@ -24,4 +25,3 @@ export * as ComponentTypes from "./types/components.d";
|
||||||
export * as MenuTypes from "./types/menu.d";
|
export * as MenuTypes from "./types/menu.d";
|
||||||
export * as UtilTypes from "./types/utils.d";
|
export * as UtilTypes from "./types/utils.d";
|
||||||
export * from "./utils";
|
export * from "./utils";
|
||||||
|
|
||||||
|
|
40
src/webpack/common/types/classes.d.ts
vendored
Normal file
40
src/webpack/common/types/classes.d.ts
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2023 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ImageModalClasses {
|
||||||
|
image: string,
|
||||||
|
modal: string,
|
||||||
|
responsiveWidthMobile: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ButtonWrapperClasses {
|
||||||
|
hoverScale: string;
|
||||||
|
buttonWrapper: string;
|
||||||
|
button: string;
|
||||||
|
iconMask: string;
|
||||||
|
buttonContent: string;
|
||||||
|
icon: string;
|
||||||
|
pulseIcon: string;
|
||||||
|
pulseButton: string;
|
||||||
|
notificationDot: string;
|
||||||
|
sparkleContainer: string;
|
||||||
|
sparkleStar: string;
|
||||||
|
sparklePlus: string;
|
||||||
|
sparkle: string;
|
||||||
|
active: string;
|
||||||
|
}
|
7
src/webpack/common/types/components.d.ts
vendored
7
src/webpack/common/types/components.d.ts
vendored
|
@ -398,6 +398,13 @@ export type Paginator = ComponentType<{
|
||||||
hideMaxPage?: boolean;
|
hideMaxPage?: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
export type MaskedLink = ComponentType<{
|
||||||
|
onClick(): void;
|
||||||
|
trusted: boolean;
|
||||||
|
title: string,
|
||||||
|
href: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
export type ScrollerThin = ComponentType<PropsWithChildren<{
|
export type ScrollerThin = ComponentType<PropsWithChildren<{
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
|
|
1
src/webpack/common/types/menu.d.ts
vendored
1
src/webpack/common/types/menu.d.ts
vendored
|
@ -44,6 +44,7 @@ export interface Menu {
|
||||||
onChildrenScroll?: Function;
|
onChildrenScroll?: Function;
|
||||||
childRowHeight?: number;
|
childRowHeight?: number;
|
||||||
listClassName?: string;
|
listClassName?: string;
|
||||||
|
disabled?: boolean;
|
||||||
}>;
|
}>;
|
||||||
MenuCheckboxItem: RC<{
|
MenuCheckboxItem: RC<{
|
||||||
id: string;
|
id: string;
|
||||||
|
|
Loading…
Reference in a new issue