fix Toasts

This commit is contained in:
Vendicated 2026-10-03 00:50:35 +02:00
parent d9bc6f71fd
commit 0c3c9625a7
No known key found for this signature in database
GPG key ID: D66986BAF75ECF18
24 changed files with 117 additions and 156 deletions

View file

@ -53,3 +53,8 @@ export const enum PremiumType {
TIER_2 = 2,
TIER_0 = 3,
}
export const enum ToastPosition {
TOP = 0,
BOTTOM = 1,
}

View file

@ -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";

35
packages/discord-types/src/toasts.d.ts vendored Normal file
View file

@ -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;
}

View file

@ -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");

View file

@ -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;
}

View file

@ -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
});
}
})}

View file

@ -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");
}
},

View file

@ -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");
}
}}
>

View file

@ -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) {

View file

@ -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() {

View file

@ -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);
}

View file

@ -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");
}
}

View file

@ -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");
}
}}
>

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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<T = unknown>(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<T = unknown>(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<UserReviewsData> {
export async function getReviews(id: string, { limit, offset = 0, fetchVotes = false }: { limit?: number; offset?: number; fetchVotes?: boolean; } = {}): Promise<UserReviewsData> {
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<ReviewVote[]> {
return res?.votes ?? [];
}
export async function addReview(review: { userid: string; comment: string }): Promise<UserReviewsData | null> {
export async function addReview(review: { userid: string; comment: string; }): Promise<UserReviewsData | null> {
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"

View file

@ -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
});
}

View file

@ -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<TranslationValue> {
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();

View file

@ -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;
}

View file

@ -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);
});

View file

@ -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
}]}

View file

@ -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 {

View file

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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 = {