diff options
author | Phil <letsphil12@gmail.com> | 2023-06-16 19:35:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-16 19:35:50 +0200 |
commit | e8d90d2b45e8be0595f75454429fc1a5cedb4e33 (patch) | |
tree | 68c24a51d3fe3ba00d7a4314989e5c9ddbdf5403 /src/plugins | |
parent | 55af40ee747fbf872eb5bb07a49ea4cd276e8c34 (diff) | |
download | Vencord-e8d90d2b45e8be0595f75454429fc1a5cedb4e33.tar.gz Vencord-e8d90d2b45e8be0595f75454429fc1a5cedb4e33.tar.bz2 Vencord-e8d90d2b45e8be0595f75454429fc1a5cedb4e33.zip |
feat(plugin): BiggerStreamPreview (#1222)
Co-authored-by: V <vendicated@riseup.net>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/biggerStreamPreview/index.tsx | 101 | ||||
-rw-r--r-- | src/plugins/biggerStreamPreview/webpack/stores.ts | 25 | ||||
-rw-r--r-- | src/plugins/biggerStreamPreview/webpack/types/stores.ts | 77 | ||||
-rw-r--r-- | src/plugins/viewIcons.tsx | 35 |
4 files changed, 220 insertions, 18 deletions
diff --git a/src/plugins/biggerStreamPreview/index.tsx b/src/plugins/biggerStreamPreview/index.tsx new file mode 100644 index 0000000..d3ed713 --- /dev/null +++ b/src/plugins/biggerStreamPreview/index.tsx @@ -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); + } +}); diff --git a/src/plugins/biggerStreamPreview/webpack/stores.ts b/src/plugins/biggerStreamPreview/webpack/stores.ts new file mode 100644 index 0000000..e8a4ee2 --- /dev/null +++ b/src/plugins/biggerStreamPreview/webpack/stores.ts @@ -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"); diff --git a/src/plugins/biggerStreamPreview/webpack/types/stores.ts b/src/plugins/biggerStreamPreview/webpack/types/stores.ts new file mode 100644 index 0000000..0265986 --- /dev/null +++ b/src/plugins/biggerStreamPreview/webpack/types/stores.ts @@ -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; +} diff --git a/src/plugins/viewIcons.tsx b/src/plugins/viewIcons.tsx index a224896..616d178 100644 --- a/src/plugins/viewIcons.tsx +++ b/src/plugins/viewIcons.tsx @@ -20,15 +20,12 @@ import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatc import { definePluginSettings } from "@api/Settings"; import { ImageIcon } from "@components/Icons"; import { Devs } from "@utils/constants"; -import { ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { LazyComponent } from "@utils/react"; +import { openImageModal } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; -import { find, findByCode, findByPropsLazy } from "@webpack"; +import { findByPropsLazy } from "@webpack"; import { GuildMemberStore, Menu } from "@webpack/common"; 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"); interface UserContextProps { @@ -60,26 +57,29 @@ const settings = definePluginSettings({ 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) { const format = url.startsWith("/") ? "png" : settings.store.format; + 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}`); url = u.toString(); - openModal(modalProps => ( - <ModalRoot size={ModalSize.DYNAMIC} {...modalProps}> - <ImageModal - shouldAnimate={true} - original={url} - src={url} - renderLinkComponent={MaskedLink} - /> - </ModalRoot> - )); + u.searchParams.set("size", "4096"); + const originalUrl = u.toString(); + + openImageModal(url, { + original: originalUrl, + height: 256 + }); } const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => () => { @@ -90,7 +90,7 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U <Menu.MenuItem id="view-avatar" label="View Avatar" - action={() => openImage(BannerStore.getUserAvatarURL(user, true, 512))} + action={() => openImage(BannerStore.getUserAvatarURL(user, true))} icon={ImageIcon} /> {memberAvatar && ( @@ -122,7 +122,6 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild: { id, icon openImage(BannerStore.getGuildIconURL({ id, icon, - size: 512, canAnimate: true })) } |