diff --git a/packages/discord-types/enums/misc.ts b/packages/discord-types/enums/misc.ts index 81a6e41ca..aaecd1a70 100644 --- a/packages/discord-types/enums/misc.ts +++ b/packages/discord-types/enums/misc.ts @@ -53,3 +53,8 @@ export const enum PremiumType { TIER_2 = 2, TIER_0 = 3, } + +export const enum ToastPosition { + TOP = 0, + BOTTOM = 1, +} diff --git a/packages/discord-types/src/index.d.ts b/packages/discord-types/src/index.d.ts index 83bbba26e..024f3418c 100644 --- a/packages/discord-types/src/index.d.ts +++ b/packages/discord-types/src/index.d.ts @@ -7,5 +7,6 @@ export * from "./fluxEvents"; export * from "./menu"; export * from "./modules"; export * from "./stores"; +export * from "./toasts"; export * from "./utils"; export * as Webpack from "../webpack"; diff --git a/packages/discord-types/src/toasts.d.ts b/packages/discord-types/src/toasts.d.ts new file mode 100644 index 000000000..c058a920b --- /dev/null +++ b/packages/discord-types/src/toasts.d.ts @@ -0,0 +1,35 @@ +import type { ComponentType } from "react"; +import { ToastPosition } from "../enums"; + +export type ToastType = "message" | "success" | "failure" | "custom" | "clip" | "link" | "forward" | "bookmark" | "clock"; + +export type NewToastVariant = "default" | "success" | "critical"; +export type NewToastPosition = "top" | "bottom"; + +export interface ToastData { + message: string; + type?: ToastType; + options?: { + position?: ToastPosition; + duration?: number; + }; +} + +export interface NewToastData { + text: string; + variant: NewToastVariant; + position?: NewToastPosition; + duration?: number; + + icon?: ComponentType; + iconColor?: any; +} + +export type showToast = (data: NewToastData) => void; +export type popToast = (context?: string) => void; +export type createToast = (data: ToastData) => NewToastData; + +export interface Toasts { + show: showToast; + pop: popToast; +} diff --git a/src/api/SettingsSync/offline.ts b/src/api/SettingsSync/offline.ts index 5ff509caf..cc4be37fc 100644 --- a/src/api/SettingsSync/offline.ts +++ b/src/api/SettingsSync/offline.ts @@ -7,20 +7,13 @@ import { PlainSettings } from "@api/Settings"; import { Logger } from "@utils/Logger"; import { chooseFile, saveFile } from "@utils/web"; -import { moment, Toasts } from "@webpack/common"; - -const toast = (type: string, message: string) => - Toasts.show({ - type, - message, - id: Toasts.genId() - }); +import { moment, showToast } from "@webpack/common"; const toastSuccess = () => - toast(Toasts.Type.SUCCESS, "Settings successfully imported. Restart to apply changes!"); + showToast("Settings successfully imported. Restart to apply changes!", "success"); const toastFailure = (err: any) => - toast(Toasts.Type.FAILURE, `Failed to import settings: ${String(err)}`); + showToast(`Failed to import settings: ${String(err)}`, "failure"); const logger = new Logger("SettingsSync:Offline", "#39b7e0"); diff --git a/src/components/settings/tabs/plugins/PluginCard.tsx b/src/components/settings/tabs/plugins/PluginCard.tsx index ac8b9b839..6c84f39dd 100644 --- a/src/components/settings/tabs/plugins/PluginCard.tsx +++ b/src/components/settings/tabs/plugins/PluginCard.tsx @@ -10,7 +10,8 @@ import { Settings } from "@api/Settings"; import { CogWheel, InfoIcon } from "@components/Icons"; import { AddonCard } from "@components/settings/AddonCard"; import { Plugin } from "@utils/types"; -import { React, showToast, Toasts } from "@webpack/common"; +import { ToastPosition } from "@vencord/discord-types/enums"; +import { React, showToast } from "@webpack/common"; import { cl, logger } from "."; import { openPluginModal } from "./PluginModal"; @@ -67,9 +68,7 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on settings.enabled = false; const msg = `Error while ${wasEnabled ? "stopping" : "starting"} plugin ${plugin.name}`; - showToast(msg, Toasts.Type.FAILURE, { - position: Toasts.Position.BOTTOM, - }); + showToast(msg, "failure", { position: ToastPosition.BOTTOM }); return; } diff --git a/src/components/settings/tabs/updater/Components.tsx b/src/components/settings/tabs/updater/Components.tsx index 67c3b443d..d1b13d4e0 100644 --- a/src/components/settings/tabs/updater/Components.tsx +++ b/src/components/settings/tabs/updater/Components.tsx @@ -12,7 +12,8 @@ import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { relaunch } from "@utils/native"; import { changes, checkForUpdates, update, updateError } from "@utils/updater"; -import { Button, ConfirmModal,Forms, openModal, React, Toasts, useState } from "@webpack/common"; +import { ToastPosition } from "@vencord/discord-types/enums"; +import { Button, ConfirmModal, Forms, openModal, React, showToast, useState } from "@webpack/common"; import { runWithDispatch } from "./runWithDispatch"; @@ -132,13 +133,8 @@ export function Updatable(props: CommonProps) { } else { setUpdates([]); - Toasts.show({ - message: "No updates found!", - id: Toasts.genId(), - type: Toasts.Type.MESSAGE, - options: { - position: Toasts.Position.BOTTOM - } + showToast("No updates found!", "message", { + position: ToastPosition.BOTTOM }); } })} diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index d91b4eae7..88e41d6d2 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -31,7 +31,7 @@ import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { shouldShowContributorBadge } from "@utils/misc"; import definePlugin from "@utils/types"; -import { ContextMenuApi, Forms, Menu, Modal, openModal, Toasts, UserStore } from "@webpack/common"; +import { ContextMenuApi, Forms, Menu, Modal, openModal, showToast, UserStore } from "@webpack/common"; const CONTRIBUTOR_BADGE = "https://cdn.discordapp.com/emojis/1092089799109775453.png?size=64"; @@ -131,11 +131,7 @@ export default definePlugin({ toolboxActions: { async "Refetch Badges"() { await loadBadges(true); - Toasts.show({ - id: Toasts.genId(), - message: "Successfully refetched badges!", - type: Toasts.Type.SUCCESS - }); + showToast("Successfully refetched badges!", "success"); } }, diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index 3312c51e9..159ef3865 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -35,7 +35,7 @@ import { makeCodeblock } from "@utils/text"; import definePlugin from "@utils/types"; import { checkForUpdates, isOutdated, update } from "@utils/updater"; import { Channel, RenderModalProps } from "@vencord/discord-types"; -import { Button, ChannelStore, ConfirmModal, Forms, GuildMemberStore, openModal, Parser, PermissionsBits, PermissionStore, RelationshipStore, showToast, Text, Toasts, UserStore } from "@webpack/common"; +import { Button, ChannelStore, ConfirmModal, Forms, GuildMemberStore, openModal, Parser, PermissionsBits, PermissionStore, RelationshipStore, showToast, Text, UserStore } from "@webpack/common"; import { JSX } from "react"; import gitHash from "~git-hash"; @@ -284,12 +284,12 @@ export default definePlugin({ onClick={async () => { try { if (await forceUpdate()) - showToast("Success! Restarting...", Toasts.Type.SUCCESS); + showToast("Success! Restarting...", "success"); else - showToast("Already up to date!", Toasts.Type.MESSAGE); + showToast("Already up to date!"); } catch (e) { new Logger(this.name).error("Error while updating:", e); - showToast("Failed to update :(", Toasts.Type.FAILURE); + showToast("Failed to update :(", "failure"); } }} > @@ -328,10 +328,10 @@ export default definePlugin({ onClick={async () => { try { await AsyncFunction(match[1])(); - showToast("Success!", Toasts.Type.SUCCESS); + showToast("Success!", "success"); } catch (e) { new Logger(this.name).error("Error while running snippet:", e); - showToast("Failed to run snippet :(", Toasts.Type.FAILURE); + showToast("Failed to run snippet :(", "failure"); } }} > diff --git a/src/plugins/addAttachments/index.tsx b/src/plugins/addAttachments/index.tsx index 8f09666fd..81fce021e 100644 --- a/src/plugins/addAttachments/index.tsx +++ b/src/plugins/addAttachments/index.tsx @@ -12,7 +12,7 @@ import definePlugin from "@utils/types"; import { Message } from "@vencord/discord-types"; import { MessageFlags, MessageType } from "@vencord/discord-types/enums"; import { findByPropsLazy } from "@webpack"; -import { AuthenticationStore, ChannelStore, EditMessageStore, MessageStore, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, Toasts } from "@webpack/common"; +import { AuthenticationStore, ChannelStore, EditMessageStore, MessageStore, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast } from "@webpack/common"; const { uniqueId } = findByPropsLazy("uniqueId"); @@ -39,15 +39,15 @@ async function addAttachments(channelId: string, messageId: string, existingAtta if (files.length + existingAttachmentCount > 10) { const remaining = 10 - existingAttachmentCount; if (remaining <= 0) { - showToast("You cannot add more attachments to this message.", Toasts.Type.FAILURE); + showToast("You cannot add more attachments to this message.", "failure"); return; } - showToast(`You can only add ${pluralise(remaining, "more attachment")} to this message.`, Toasts.Type.FAILURE); + showToast(`You can only add ${pluralise(remaining, "more attachment")} to this message.`, "failure"); return; } - showToast("Uploading, this can take a while...", Toasts.Type.CLOCK); + showToast("Uploading, this can take a while...", "clock"); const { body: { attachments } } = await RestAPI.post({ url: `/channels/${channelId}/attachments`, @@ -87,7 +87,7 @@ async function addAttachments(channelId: string, messageId: string, existingAtta } }); - showToast(`${files.length === 1 ? "Attachment" : "Attachments"} added successfully!`, Toasts.Type.SUCCESS); + showToast(`${files.length === 1 ? "Attachment" : "Attachments"} added successfully!`, "success"); } function canAddAttachments(msg: Message) { diff --git a/src/plugins/arRPC.web/index.tsx b/src/plugins/arRPC.web/index.tsx index 7d54ddc36..c631a471e 100644 --- a/src/plugins/arRPC.web/index.tsx +++ b/src/plugins/arRPC.web/index.tsx @@ -21,7 +21,7 @@ import { Link } from "@components/Link"; import { Devs } from "@utils/constants"; import definePlugin, { ReporterTestable } from "@utils/types"; import { findByCodeLazy } from "@webpack"; -import { ApplicationAssetUtils, FluxDispatcher, Forms, Toasts } from "@webpack/common"; +import { ApplicationAssetUtils, FluxDispatcher, Forms, showToast } from "@webpack/common"; const fetchApplicationsRPC = findByCodeLazy('"Invalid Origin"', ".application"); @@ -89,15 +89,7 @@ export default definePlugin({ return; } - Toasts.show({ // show toast on success - message: "Connected to arRPC", - type: Toasts.Type.SUCCESS, - id: Toasts.genId(), - options: { - duration: 1000, - position: Toasts.Position.BOTTOM - } - }); + showToast("Connected to arRPC", "success"); }, stop() { diff --git a/src/plugins/decor/lib/stores/AuthorizationStore.tsx b/src/plugins/decor/lib/stores/AuthorizationStore.tsx index 06fc47400..7aa223d43 100644 --- a/src/plugins/decor/lib/stores/AuthorizationStore.tsx +++ b/src/plugins/decor/lib/stores/AuthorizationStore.tsx @@ -8,7 +8,7 @@ import * as DataStore from "@api/DataStore"; import { AUTHORIZE_URL, CLIENT_ID } from "@plugins/decor/lib/constants"; import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; -import { OAuth2AuthorizeModal, openModal, showToast, Toasts, UserStore, zustandCreate, zustandPersist } from "@webpack/common"; +import { OAuth2AuthorizeModal, openModal, showToast, UserStore, zustandCreate, zustandPersist } from "@webpack/common"; interface AuthorizationState { token: string | null; @@ -74,7 +74,7 @@ export const useAuthorizationStore = proxyLazy(() => zustandCreate( resolve(void 0); } catch (e) { if (e instanceof Error) { - showToast(`Failed to authorize: ${e.message}`, Toasts.Type.FAILURE); + showToast(`Failed to authorize: ${e.message}`, "failure"); new Logger("Decor").error("Failed to authorize", e); reject(e); } diff --git a/src/plugins/expressionCloner/index.tsx b/src/plugins/expressionCloner/index.tsx index 60f148651..d66ddd572 100644 --- a/src/plugins/expressionCloner/index.tsx +++ b/src/plugins/expressionCloner/index.tsx @@ -29,7 +29,7 @@ import definePlugin from "@utils/types"; import { Guild, GuildSticker, Message } from "@vencord/discord-types"; import { StickerFormatType } from "@vencord/discord-types/enums"; import { findByCodeLazy } from "@webpack"; -import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, IconUtils, Menu, Modal, openModalLazy, PermissionsBits, PermissionStore, React, RestAPI, StickersStore, Toasts, Tooltip, UserStore } from "@webpack/common"; +import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, IconUtils, Menu, Modal, openModalLazy, PermissionsBits, PermissionStore, React, RestAPI, showToast, StickersStore, Tooltip, UserStore } from "@webpack/common"; import { Promisable } from "type-fest"; const uploadEmoji = findByCodeLazy(".GUILD_EMOJIS(", "EMOJI_UPLOAD_START"); @@ -196,11 +196,7 @@ async function doClone(guildId: string, data: Sticker | Emoji) { else await cloneEmoji(guildId, data); - Toasts.show({ - message: `Successfully cloned ${data.name} to ${GuildStore.getGuild(guildId)?.name ?? "your server"}!`, - type: Toasts.Type.SUCCESS, - id: Toasts.genId() - }); + showToast(`Successfully cloned ${data.name} to ${GuildStore.getGuild(guildId)?.name ?? "your server"}!`, "success"); } catch (e: any) { let message = "Something went wrong (check console!)"; try { @@ -208,11 +204,7 @@ async function doClone(guildId: string, data: Sticker | Emoji) { } catch { } new Logger("ExpressionCloner").error("Failed to clone", data.name, "to", guildId, e); - Toasts.show({ - message: "Failed to clone: " + message, - type: Toasts.Type.FAILURE, - id: Toasts.genId() - }); + showToast("Failed to clone: " + message, "failure"); } } diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx index f14ca21f3..d0caf7c3e 100644 --- a/src/plugins/ignoreActivities/index.tsx +++ b/src/plugins/ignoreActivities/index.tsx @@ -16,7 +16,7 @@ import CustomRpcPlugin from "@plugins/customRPC"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; -import { FluxDispatcher, Menu, RunningGameStore, showToast, TextArea, Toasts, Tooltip, useEffect, useState } from "@webpack/common"; +import { FluxDispatcher, Menu, RunningGameStore, showToast, TextArea, Tooltip, useEffect, useState } from "@webpack/common"; const enum ActivitiesTypes { Game, @@ -91,12 +91,12 @@ function ImportCustomRPCComponent() { onClick={() => { const id = CustomRpcPlugin.settings.store.appID; if (!id) { - return showToast("CustomRPC application ID is not set.", Toasts.Type.FAILURE); + return showToast("CustomRPC application ID is not set.", "failure"); } const isAlreadyAdded = idsListPushID?.(id); if (isAlreadyAdded) { - showToast("CustomRPC application ID is already added.", Toasts.Type.FAILURE); + showToast("CustomRPC application ID is already added.", "failure"); } }} > diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 08184eed1..443a61b85 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -19,7 +19,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType, PluginNative, SettingsDefinition } from "@utils/types"; -import { showToast, Toasts } from "@webpack/common"; +import { showToast } from "@webpack/common"; import type { MouseEvent } from "react"; interface URLReplacementRule { @@ -135,7 +135,7 @@ export default definePlugin({ } if (rule.match.test(url)) { - showToast("Opened link in native app", Toasts.Type.SUCCESS); + showToast("Opened link in native app", "success"); const newUrl = url.replace(rule.match, rule.replace); VencordNative.native.openExternal(newUrl); diff --git a/src/plugins/pinDms/components/CreateCategoryModal.tsx b/src/plugins/pinDms/components/CreateCategoryModal.tsx index 6b4f075ce..930c4f4ee 100644 --- a/src/plugins/pinDms/components/CreateCategoryModal.tsx +++ b/src/plugins/pinDms/components/CreateCategoryModal.tsx @@ -9,7 +9,7 @@ import { categoryLen, createCategory, getCategory } from "@plugins/pinDms/data"; import { classNameFactory } from "@utils/css"; import { RenderModalProps } from "@vencord/discord-types"; import { extractAndLoadChunksLazy, findComponentByCodeLazy } from "@webpack"; -import { ColorPicker, Forms, Modal,openModalLazy, TextInput, Toasts, useMemo, useState } from "@webpack/common"; +import { ColorPicker, Forms, Modal, openModalLazy, TextInput, useMemo, useState } from "@webpack/common"; interface ColorPickerWithSwatchesProps { className?: string; @@ -40,7 +40,7 @@ function useCategory(categoryId: string | null, initalChannelId: string | null) return getCategory(categoryId); } else if (initalChannelId) { return { - id: Toasts.genId(), + id: crypto.randomUUID(), name: `Pin Category ${categoryLen() + 1}`, color: DEFAULT_COLOR, collapsed: false, diff --git a/src/plugins/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx index cd8728980..8215bff62 100644 --- a/src/plugins/reviewDB/auth.tsx +++ b/src/plugins/reviewDB/auth.tsx @@ -6,7 +6,7 @@ import * as DataStore from "@api/DataStore"; import { Logger } from "@utils/Logger"; -import { OAuth2AuthorizeModal, openModal, showToast, Toasts, UserStore } from "@webpack/common"; +import { OAuth2AuthorizeModal, openModal, showToast, UserStore } from "@webpack/common"; import { ReviewDBAuth } from "./entities"; @@ -50,7 +50,7 @@ export function authorize(callback?: () => void) { permissions={0n} clientId="915703782174752809" cancelCompletesFlow={false} - callback={async (response: { location: string }) => { + callback={async (response: { location: string; }) => { try { const url = new URL(response.location); url.searchParams.append("clientMod", "vencord"); @@ -60,13 +60,13 @@ export function authorize(callback?: () => void) { if (!res.ok) { const { message } = await res.json(); - showToast(message ?? "An error occured while authorizing", Toasts.Type.FAILURE); + showToast(message ?? "An error occured while authorizing", "failure"); return; } const { token } = await res.json(); updateAuth({ token }); - showToast("Successfully logged in!", Toasts.Type.SUCCESS); + showToast("Successfully logged in!", "success"); callback?.(); } catch (e) { new Logger("ReviewDB").error("Failed to authorize", e); diff --git a/src/plugins/reviewDB/reviewDbApi.ts b/src/plugins/reviewDB/reviewDbApi.ts index 48de46e73..0f57853ae 100644 --- a/src/plugins/reviewDB/reviewDbApi.ts +++ b/src/plugins/reviewDB/reviewDbApi.ts @@ -4,8 +4,6 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Toasts } from "@webpack/common"; - import { Auth, authorize, getToken, updateAuth } from "./auth"; import { Review, ReviewDBCurrentUser, ReviewDBUser, ReviewType } from "./entities"; import { settings } from "./settings"; @@ -51,7 +49,7 @@ async function rdbRequest(path: string, options: RequestInit = {}): ...options, headers, }).catch(err => { - showToast("Network error: Failed to connect to ReviewDB.", Toasts.Type.FAILURE); + showToast("Network error: Failed to connect to ReviewDB.", "failure"); return null; }); @@ -61,14 +59,14 @@ async function rdbRequest(path: string, options: RequestInit = {}): if (!res.ok) { const message = data?.message ?? `ReviewDB: Request failed with status ${res.status}`; - showToast(message, Toasts.Type.FAILURE); + showToast(message, "failure"); return null; } return data as T; } -export async function getReviews(id: string, { limit, offset = 0, fetchVotes = false }: { limit?: number; offset?: number; fetchVotes?: boolean } = {}): Promise { +export async function getReviews(id: string, { limit, offset = 0, fetchVotes = false }: { limit?: number; offset?: number; fetchVotes?: boolean; } = {}): Promise { let flags = 0; if (!settings.store.showWarning) flags |= WarningFlag; @@ -92,7 +90,7 @@ export async function getReviews(id: string, { limit, offset = 0, fetchVotes = f }; if (!req.ok) { - showToast(res.message, Toasts.Type.FAILURE); + showToast(res.message, "failure"); return { ...res, reviews: [ @@ -140,7 +138,7 @@ export async function getReviewVotes(id: string): Promise { return res?.votes ?? []; } -export async function addReview(review: { userid: string; comment: string }): Promise { +export async function addReview(review: { userid: string; comment: string; }): Promise { const token = await getToken(); if (!token) { @@ -186,7 +184,7 @@ export async function voteReview(id: number, isUpvote: boolean) { return false; } - const data = await rdbRequest<{ message?: string }>(`/reviews/${id}/vote`, { + const data = await rdbRequest<{ message?: string; }>(`/reviews/${id}/vote`, { method: "POST", body: JSON.stringify({ isUpvote }) }); @@ -204,7 +202,7 @@ export async function deleteReviewVote(id: number) { return false; } - const data = await rdbRequest<{ message?: string }>(`/reviews/${id}/vote`, { + const data = await rdbRequest<{ message?: string; }>(`/reviews/${id}/vote`, { method: "DELETE", }); @@ -224,7 +222,7 @@ async function patchBlock(action: "block" | "unblock", userId: string) { if (!data) return; - showToast(`Successfully ${action}ed user`, Toasts.Type.SUCCESS); + showToast(`Successfully ${action}ed user`, "success"); if (Auth?.user?.blockedUsers) { const newBlockedUsers = action === "block" diff --git a/src/plugins/reviewDB/utils.tsx b/src/plugins/reviewDB/utils.tsx index ec7609c50..e9ea0a68e 100644 --- a/src/plugins/reviewDB/utils.tsx +++ b/src/plugins/reviewDB/utils.tsx @@ -17,7 +17,9 @@ */ import { classNameFactory } from "@utils/css"; -import { Toasts, UserStore } from "@webpack/common"; +import { ToastType } from "@vencord/discord-types"; +import { ToastPosition } from "@vencord/discord-types/enums"; +import { showToast as originalShowToast, UserStore } from "@webpack/common"; import { Auth } from "./auth"; import { Review, UserType } from "./entities"; @@ -42,13 +44,8 @@ export function canReportReview(review: Review) { return review.sender.discordID !== UserStore.getCurrentUser().id; } -export function showToast(message: string, type = Toasts.Type.MESSAGE) { - Toasts.show({ - id: Toasts.genId(), - message, - type, - options: { - position: Toasts.Position.BOTTOM, // NOBODY LIKES TOASTS AT THE TOP - }, +export function showToast(message: string, type: ToastType = "message") { + originalShowToast(message, type, { + position: ToastPosition.BOTTOM }); } diff --git a/src/plugins/translate/utils.ts b/src/plugins/translate/utils.ts index 2c77db511..934def25d 100644 --- a/src/plugins/translate/utils.ts +++ b/src/plugins/translate/utils.ts @@ -19,7 +19,7 @@ import { classNameFactory } from "@utils/css"; import { onlyOnce } from "@utils/onlyOnce"; import { PluginNative } from "@utils/types"; -import { showToast, Toasts } from "@webpack/common"; +import { showToast } from "@webpack/common"; import { DeeplLanguages, deeplLanguageToGoogleLanguage, GoogleLanguages, KagiLanguages } from "./languages"; import { resetLanguageDefaults, settings } from "./settings"; @@ -89,7 +89,7 @@ export async function translate(kind: "received" | "sent", text: string): Promis ? e : "Something went wrong. If this issue persists, please check the console or ask for help in the support server."; - showToast(userMessage, Toasts.Type.FAILURE); + showToast(userMessage, "failure"); throw e instanceof Error ? e @@ -131,12 +131,12 @@ function fallbackToGoogle(text: string, sourceLang: string, targetLang: string): } const showDeeplApiQuotaToast = onlyOnce( - () => showToast("Deepl API quota exceeded. Falling back to Google Translate", Toasts.Type.FAILURE) + () => showToast("Deepl API quota exceeded. Falling back to Google Translate", "failure") ); async function deeplTranslate(text: string, sourceLang: string, targetLang: string): Promise { if (!settings.store.deeplApiKey) { - showToast("DeepL API key is not set. Resetting to Google", Toasts.Type.FAILURE); + showToast("DeepL API key is not set. Resetting to Google", "failure"); settings.store.service = "google"; resetLanguageDefaults(); diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index 3da84a7af..ccb5faf47 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -11,7 +11,7 @@ import { classNameFactory } from "@utils/css"; import { classes } from "@utils/misc"; import { Channel } from "@vencord/discord-types"; import { findByPropsLazy, findCssClassesLazy } from "@webpack"; -import { ChannelRouter, ChannelStore, Parser, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, UserSummaryItem, useStateFromStores, VoiceStateStore } from "@webpack/common"; +import { ChannelRouter, ChannelStore, Parser, PermissionsBits, PermissionStore, React, showToast, Text, Tooltip, useMemo, UserStore, UserSummaryItem, useStateFromStores, VoiceStateStore } from "@webpack/common"; import { PropsWithChildren } from "react"; const cl = classNameFactory("vc-uvs-"); @@ -153,7 +153,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isProfile, is if (e.detail > 1) { if (!isDM && !PermissionStore.can(PermissionsBits.CONNECT, channel)) { - showToast("You cannot join the user's Voice Channel", Toasts.Type.FAILURE); + showToast("You cannot join the user's Voice Channel", "failure"); return; } diff --git a/src/plugins/voiceMessages/DesktopRecorder.tsx b/src/plugins/voiceMessages/DesktopRecorder.tsx index 8b6bc6d06..72fd8c12f 100644 --- a/src/plugins/voiceMessages/DesktopRecorder.tsx +++ b/src/plugins/voiceMessages/DesktopRecorder.tsx @@ -17,7 +17,7 @@ */ import { PluginNative } from "@utils/types"; -import { Button, MediaEngineStore, showToast, Toasts, useState } from "@webpack/common"; +import { Button, MediaEngineStore, showToast, useState } from "@webpack/common"; import type { VoiceRecorder } from "."; import { settings } from "./settings"; @@ -47,7 +47,7 @@ export const VoiceRecorderDesktop: VoiceRecorder = ({ setAudioBlob, onRecordingC if (success) changeRecording(true); else - showToast("Failed to start recording", Toasts.Type.FAILURE); + showToast("Failed to start recording", "failure"); } ); } else { @@ -57,7 +57,7 @@ export const VoiceRecorderDesktop: VoiceRecorder = ({ setAudioBlob, onRecordingC if (buf) setAudioBlob(new Blob([buf], { type: "audio/ogg; codecs=opus" })); else - showToast("Failed to finish recording", Toasts.Type.FAILURE); + showToast("Failed to finish recording", "failure"); } changeRecording(false); }); diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index d2c6c3f3d..e619e44c9 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -32,7 +32,7 @@ import { chooseFile } from "@utils/web"; import { CloudUpload as TCloudUpload, RenderModalProps } from "@vencord/discord-types"; import { CloudUploadPlatform } from "@vencord/discord-types/enums"; import { findLazy } from "@webpack"; -import { Button, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, Modal,openModal, PendingReplyStore, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; +import { Button, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, Modal, openModal, PendingReplyStore, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, useEffect, useState } from "@webpack/common"; import { ComponentType } from "react"; import { VoiceRecorderDesktop } from "./DesktopRecorder"; @@ -140,7 +140,7 @@ function sendAudio(blob: Blob, meta: AudioMetadata) { } }); }); - upload.on("error", () => showToast("Failed to upload voice message", Toasts.Type.FAILURE)); + upload.on("error", () => showToast("Failed to upload voice message", "failure")); upload.upload(); } @@ -216,7 +216,7 @@ function VoiceMessageModal({ modalProps }: { modalProps: RenderModalProps; }) { onClick: () => { sendAudio(blob!, meta ?? EMPTY_META); modalProps.onClose(); - showToast("Now sending voice message... Please be patient", Toasts.Type.MESSAGE); + showToast("Now sending voice message... Please be patient", "clock"); }, disabled: !blob }]} diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 89759d07b..47aea0cc4 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -18,7 +18,7 @@ import type { MessageObject } from "@api/MessageEvents"; import type { Channel, CloudUpload, Guild, GuildFeatures, MediaModalItem, MediaModalProps, Message, User } from "@vencord/discord-types"; -import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, InviteActions, MessageActions, openMediaModal, RestAPI, SelectedChannelStore, SelectedGuildStore, Toasts, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, InviteActions, MessageActions, openMediaModal, RestAPI, SelectedChannelStore, SelectedGuildStore, showToast, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Except } from "type-fest"; import { copyToClipboard } from "./clipboard"; @@ -116,11 +116,7 @@ export function insertTextIntoChatInputBox(text: string) { export async function copyWithToast(text: string, toastMessage = "Copied to clipboard!") { await copyToClipboard(text); - Toasts.show({ - message: toastMessage, - id: Toasts.genId(), - type: Toasts.Type.SUCCESS - }); + showToast(toastMessage, "success"); } interface MessageOptions { diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 32eb73a71..47d23bf8a 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import type * as t from "@vencord/discord-types"; +import * as t from "@vencord/discord-types"; import { _resolveReady, filters, findByCodeLazy, findByPropsLazy, findLazy, mapMangledModuleLazy, waitFor } from "@webpack"; import type * as TSPattern from "ts-pattern"; @@ -66,23 +66,6 @@ waitFor("parseTopic", m => Parser = m); export let Alerts: t.Alerts; waitFor(["show", "close"], m => Alerts = m); -const ToastType = { - MESSAGE: "message", - SUCCESS: "success", - FAILURE: "failure", - CUSTOM: "custom", - CLIP: "clip", - LINK: "link", - FORWARD: "forward", - BOOKMARK: "bookmark", - CLOCK: "clock" -}; - -const ToastPosition = { - TOP: 0, - BOTTOM: 1 -}; - export interface ToastData { message: string, id: string, @@ -102,40 +85,18 @@ export interface ToastOptions { duration?: number; } -interface ToastsExports { - showToast: (data: ToastData) => void; - popToast(): void; -} - -const ToastsExports = mapMangledModuleLazy(".currentToastMap.has(", { - showToast: filters.byCode(".currentToastMap.has("), - popToast: filters.byCode(".delete(") +export const Toasts: t.Toasts = mapMangledModuleLazy(".currentToastMap.has(", { + show: filters.byCode(".currentToastMap.has("), + pop: filters.byCode(".delete(") }); -export function createToast(message: string, type: string, options?: ToastOptions): ToastData { - return { - message, - id: Toasts.genId(), - type, - options - }; -} - -export const Toasts = { - Type: ToastType, - Position: ToastPosition, - genId: () => (Math.random() || Math.random()).toString(36).slice(2), - - show: ToastsExports.showToast, - pop: ToastsExports.popToast, - create: createToast, -}; +export const createToast: t.createToast = findByCodeLazy('variant:"default",icon:', ".duration"); /** * Show a simple toast. If you need more options, use Toasts.show manually */ -export function showToast(message: string, type = ToastType.MESSAGE, options?: ToastOptions) { - Toasts.show(Toasts.create(message, type, options)); +export function showToast(message: string, type: t.ToastType = "message", options?: ToastOptions) { + Toasts.show(createToast({ message, type, options })); } export const UserUtils = {