From e699ea63c749a4c4af185d997a1f7588804d458f Mon Sep 17 00:00:00 2001 From: Syncx <47534062+Syncxv@users.noreply.github.com> Date: Sat, 19 Aug 2023 09:19:10 +1000 Subject: [PATCH] feat(plugin): PreviewMessage (#1607) Co-authored-by: V --- src/plugins/previewMessage.tsx | 83 ++++++++++++++++++++++++++++ src/webpack/common/stores.ts | 9 +++ src/webpack/common/types/stores.d.ts | 24 ++++++++ 3 files changed, 116 insertions(+) create mode 100644 src/plugins/previewMessage.tsx diff --git a/src/plugins/previewMessage.tsx b/src/plugins/previewMessage.tsx new file mode 100644 index 00000000..26533185 --- /dev/null +++ b/src/plugins/previewMessage.tsx @@ -0,0 +1,83 @@ +/* + * 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 . +*/ + +import { sendBotMessage } from "@api/Commands"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { Button, ButtonLooks, ButtonWrapperClasses, DraftStore, DraftType, SelectedChannelStore, Tooltip, UserStore } from "@webpack/common"; + +interface Props { + type: { + analyticsName: string; + }; +} + +const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage); + +export function PreviewButton(chatBoxProps: Props) { + if (chatBoxProps.type.analyticsName !== "normal") return null; + const channelId = SelectedChannelStore.getChannelId(); + const draft = getDraft(channelId); + + if (!draft) return null; + + return ( + + {tooltipProps => ( + + )} + + ); + +} + +export default definePlugin({ + name: "PreviewMessage", + description: "Lets you preview your message before sending it", + authors: [Devs.Aria], + patches: [ + { + find: ".activeCommandOption", + replacement: { + match: /(.)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/, + replace: "$&;try{$2||$1.unshift($self.previewIcon(arguments[0]))}catch{}", + } + }, + ], + + previewIcon: ErrorBoundary.wrap(PreviewButton, { noop: true }), +}); diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 05d52542..456255d3 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -27,6 +27,13 @@ export const Flux: t.Flux = findByPropsLazy("connectStores"); export type GenericStore = t.FluxStore & Record; +export enum DraftType { + ChannelMessage = 0, + ThreadSettings = 1, + FirstThreadMessage = 2, + ApplicationLauncherCommand = 3 +} + export let MessageStore: Omit & { getMessages(chanId: string): any; }; @@ -52,6 +59,7 @@ export let RelationshipStore: Stores.RelationshipStore & t.FluxStore & { export let EmojiStore: t.EmojiStore; export let WindowStore: t.WindowStore; +export let DraftStore: t.DraftStore; export const MaskedLinkStore = mapMangledModuleLazy('"MaskedLinkStore"', { openUntrustedLink: filters.byCode(".apply(this,arguments)") @@ -76,6 +84,7 @@ export const useStateFromStores: ( ) => T = findByCodeLazy("useStateFromStores"); +waitForStore("DraftStore", s => DraftStore = s); waitForStore("UserStore", s => UserStore = s); waitForStore("ChannelStore", m => ChannelStore = m); waitForStore("SelectedChannelStore", m => SelectedChannelStore = m); diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 3771150f..ecc87d74 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { DraftType } from "@webpack/common"; import { Channel } from "discord-types/general"; import { FluxDispatcher, FluxEvents } from "./utils"; @@ -148,3 +149,26 @@ export class EmojiStore extends FluxStore { get favoriteEmojisWithoutFetchingLatest(): Emoji[]; }; } + +export interface DraftObject { + channelId: string; + timestamp: number; + draft: string; +} + +interface DraftState { + [userId: string]: { + [channelId: string]: { + [key in DraftType]?: Omit; + } | undefined; + } | undefined; +} + + +export class DraftStore extends FluxStore { + getDraft(channelId: string, type: DraftType): string; + getRecentlyEditedDrafts(type: DraftType): DraftObject[]; + getState(): DraftState; + getThreadDraftWithParentMessageId?(arg: any): any; + getThreadSettings(channelId: string): any | null; +}