Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
cfec48401b
37 changed files with 239 additions and 264 deletions
|
|
@ -53,3 +53,8 @@ export const enum PremiumType {
|
|||
TIER_2 = 2,
|
||||
TIER_0 = 3,
|
||||
}
|
||||
|
||||
export const enum ToastPosition {
|
||||
TOP = 0,
|
||||
BOTTOM = 1,
|
||||
}
|
||||
|
|
|
|||
1
packages/discord-types/src/index.d.ts
vendored
1
packages/discord-types/src/index.d.ts
vendored
|
|
@ -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
35
packages/discord-types/src/toasts.d.ts
vendored
Normal 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;
|
||||
}
|
||||
12
packages/discord-types/src/utils.d.ts
vendored
12
packages/discord-types/src/utils.d.ts
vendored
|
|
@ -417,13 +417,13 @@ export interface EmojiUtils {
|
|||
applyPlatformToThemedEmojiColorPalette(colors: any): any;
|
||||
}
|
||||
|
||||
export interface OpenUserSettingsOpts {
|
||||
export interface OpenUserSettingsOptions {
|
||||
/**
|
||||
* a *sub*section of settings to navigate to
|
||||
*
|
||||
* to navigate to a top-level section, use the navigationTarget parameter of {@link SettingsRouter.openUserSettings} instead
|
||||
*
|
||||
* discord has an enum with all the possible values (go dig in the openUserSettings source)
|
||||
* discord has an enum with all the possible values (go dig in the {@link SettingsRouter.openUserSettings} source)
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
|
|
@ -434,10 +434,10 @@ export interface OpenUserSettingsOpts {
|
|||
}
|
||||
|
||||
export interface SettingsRouter {
|
||||
openUserSettings(navigationTarget?: string, opts?: OpenUserSettingsOpts, onOpen?: () => void): Promise<void>;
|
||||
openUserSettings(navigationTarget?: string, opts?: OpenUserSettingsOptions, onOpen?: () => void): Promise<void>;
|
||||
}
|
||||
|
||||
export interface OpenUserProfileModalOpts {
|
||||
export interface OpenUserProfileModalOptions {
|
||||
userId: string;
|
||||
guildId?: string | null;
|
||||
originGuildId?: string | null;
|
||||
|
|
@ -458,6 +458,4 @@ export interface OpenUserProfileModalOpts {
|
|||
onModalOpen?: unknown;
|
||||
}
|
||||
|
||||
export interface UserProfileModalActionCreators {
|
||||
openUserProfileModal(opts: OpenUserProfileModalOpts): Promise<void>;
|
||||
}
|
||||
export type OpenUserProfileModal = (opts: OpenUserProfileModalOptions) => Promise<void>;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
import "~plugins";
|
||||
import "./fixWeirdAppRegionBug.css";
|
||||
|
||||
import nativeTitleBarStyles from "./nativeTitleBar.css?managed";
|
||||
|
||||
export * as Api from "./api";
|
||||
export * as Plugins from "./api/PluginManager";
|
||||
export * as Components from "./components";
|
||||
|
|
@ -29,11 +31,9 @@ export * as Webpack from "./webpack";
|
|||
export * as WebpackPatcher from "./webpack/patchWebpack";
|
||||
export { PlainSettings, Settings };
|
||||
|
||||
import { coreStyleRootNode, initStyles } from "@api/Styles";
|
||||
import { enableStyle, initStyles } from "@api/Styles";
|
||||
import { openSettingsTabModal, UpdaterTab } from "@components/settings";
|
||||
import { debounce } from "@shared/debounce";
|
||||
import { IS_WINDOWS } from "@utils/constants";
|
||||
import { createAndAppendStyle } from "@utils/css";
|
||||
import { StartAt } from "@utils/types";
|
||||
import { SettingsRouter } from "@webpack/common";
|
||||
|
||||
|
|
@ -237,8 +237,7 @@ init();
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
startAllPlugins(StartAt.DOMContentLoaded);
|
||||
|
||||
// FIXME
|
||||
if (IS_DISCORD_DESKTOP && Settings.winNativeTitleBar && IS_WINDOWS) {
|
||||
createAndAppendStyle("vencord-native-titlebar-style", coreStyleRootNode).textContent = "[class*=titleBar]{display: none!important}";
|
||||
if (IS_DISCORD_DESKTOP && Settings.nativeTitleBar) {
|
||||
enableStyle(nativeTitleBarStyles);
|
||||
}
|
||||
}, { once: true });
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export interface Settings {
|
|||
| undefined;
|
||||
windowsMaterial: "none" | "mica" | "tabbed" | "acrylic";
|
||||
disableMinSize: boolean;
|
||||
winNativeTitleBar: boolean;
|
||||
nativeTitleBar: boolean;
|
||||
plugins: {
|
||||
[plugin: string]: {
|
||||
enabled: boolean;
|
||||
|
|
@ -124,7 +124,7 @@ const DefaultSettings: Settings = {
|
|||
macosVibrancyStyle: undefined,
|
||||
windowsMaterial: "none",
|
||||
disableMinSize: false,
|
||||
winNativeTitleBar: false,
|
||||
nativeTitleBar: false,
|
||||
plugins: {},
|
||||
|
||||
uiElements: {
|
||||
|
|
|
|||
|
|
@ -7,24 +7,17 @@
|
|||
import { PlainSettings } from "@api/Settings";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { chooseFile, saveFile } from "@utils/web";
|
||||
import { moment, Toasts } from "@webpack/common";
|
||||
import { moment, showToast } from "@webpack/common";
|
||||
|
||||
import { DataStore } from "..";
|
||||
|
||||
type BackupType = "all" | "plugins" | "css" | "datastore";
|
||||
|
||||
const toast = (type: string, message: string) =>
|
||||
Toasts.show({
|
||||
type,
|
||||
message,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
|
||||
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");
|
||||
|
||||
|
|
@ -118,7 +111,7 @@ export async function exportSettings({ syncDataStore = true, type = "all", minif
|
|||
|
||||
if (type === "all") {
|
||||
logger.warn("Skipping DataStore in backup due to size. Export DataStore separately if needed.");
|
||||
toast(Toasts.Type.MESSAGE, "DataStore too large - exported without it. Use 'Export DataStore' separately if needed.");
|
||||
showToast("DataStore too large - exported without it. Use 'Export DataStore' separately if needed.", "message");
|
||||
dataStore = undefined;
|
||||
} else if (type === "datastore") {
|
||||
throw new Error("DataStore is too large to export. Please clear some plugin data and try again.");
|
||||
|
|
@ -156,7 +149,7 @@ export async function downloadSettingsBackup(type: BackupType = "all", { minify
|
|||
}
|
||||
} catch (err) {
|
||||
logger.error("Failed to export settings:", err);
|
||||
toast(Toasts.Type.FAILURE, "Failed to export settings, check console");
|
||||
showToast("Failed to export settings, check console", "failure");
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import { AddonCard } from "@components/settings/AddonCard";
|
|||
import { classNameFactory } from "@utils/css";
|
||||
import { Logger } from "@utils/Logger";
|
||||
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 { PluginMeta } from "~plugins";
|
||||
|
||||
|
|
@ -79,9 +80,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import { Span } from "@components/Span";
|
|||
import { Margins } from "@utils/margins";
|
||||
import { relaunch } from "@utils/native";
|
||||
import { changes, checkForUpdates, update, updateError } from "@utils/updater";
|
||||
import { ConfirmModal, openModal, React, Toasts, useState } from "@webpack/common";
|
||||
import { ToastPosition } from "@vencord/discord-types/enums";
|
||||
import { ConfirmModal, openModal, React, showToast, Toasts, useState } from "@webpack/common";
|
||||
|
||||
import { runWithDispatch } from "./runWithDispatch";
|
||||
|
||||
|
|
@ -135,6 +136,24 @@ export function Updatable(props: CommonProps) {
|
|||
Update Now
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
disabled={isUpdating || isChecking}
|
||||
onClick={runWithDispatch(setIsChecking, async () => {
|
||||
const outdated = await checkForUpdates();
|
||||
|
||||
if (outdated) {
|
||||
setUpdates(changes);
|
||||
} else {
|
||||
setUpdates([]);
|
||||
|
||||
showToast("No updates found!", "message", {
|
||||
position: ToastPosition.BOTTOM
|
||||
});
|
||||
}
|
||||
})}
|
||||
>
|
||||
Check for Updates
|
||||
</Button>
|
||||
</Flex>
|
||||
{!updates && updateError ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ type KeysOfType<Object, Type> = {
|
|||
}[keyof Object];
|
||||
|
||||
function Switches() {
|
||||
const settings = useSettings(["useQuickCss", "enableReactDevtools", "mainWindowFrameless", "frameless", "winNativeTitleBar", "transparent", "winCtrlQ", "disableMinSize"]);
|
||||
const settings = useSettings(["useQuickCss", "enableReactDevtools", "mainWindowFrameless", "frameless", "nativeTitleBar", "transparent", "winCtrlQ", "disableMinSize"]);
|
||||
|
||||
const Switches = [
|
||||
{
|
||||
|
|
@ -71,7 +71,7 @@ function Switches() {
|
|||
restartRequired: true,
|
||||
}
|
||||
: {
|
||||
key: "winNativeTitleBar",
|
||||
key: "nativeTitleBar",
|
||||
title: "Use Windows' native title bar instead of Discord's custom one",
|
||||
description: "Replace Discord's custom title bar with the standard Windows title bar. This may improve compatibility with some window management tools.",
|
||||
restartRequired: true,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ if (!IS_VANILLA) {
|
|||
return;
|
||||
}
|
||||
|
||||
const { frameless, mainWindowFrameless, winNativeTitleBar, disableMinSize, transparent, macosVibrancyStyle, windowsMaterial } = settings;
|
||||
const { frameless, mainWindowFrameless, nativeTitleBar, disableMinSize, transparent, macosVibrancyStyle, windowsMaterial } = settings;
|
||||
|
||||
const original = options.webPreferences.preload;
|
||||
const isMainWindow = options.title === "Discord";
|
||||
|
|
@ -98,7 +98,7 @@ if (!IS_VANILLA) {
|
|||
options.frame = false;
|
||||
} else if (frameless) {
|
||||
options.frame = false;
|
||||
} else if (process.platform === "win32" && winNativeTitleBar) {
|
||||
} else if (process.platform === "win32" && nativeTitleBar) {
|
||||
delete options.frame;
|
||||
}
|
||||
|
||||
|
|
|
|||
7
src/nativeTitleBar.css
Normal file
7
src/nativeTitleBar.css
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[class*="bar_"] {
|
||||
margin-inline-end: 12px !important;
|
||||
}
|
||||
|
||||
[class*="winButtons_"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ import { copyWithToast } from "@utils/discord";
|
|||
import { Logger } from "@utils/Logger";
|
||||
import { shouldShowContributorBadge, shouldShowEquicordContributorBadge } from "@utils/misc";
|
||||
import definePlugin from "@utils/types";
|
||||
import { ContextMenuApi, Menu, Toasts, UserStore } from "@webpack/common";
|
||||
import { ContextMenuApi, Menu, showToast, UserStore } from "@webpack/common";
|
||||
|
||||
import Plugins, { PluginMeta } from "~plugins";
|
||||
|
||||
|
|
@ -181,11 +181,7 @@ export default definePlugin({
|
|||
toolboxActions: {
|
||||
async "Refetch Badges"() {
|
||||
await loadAllBadges(true);
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Successfully refetched badges!",
|
||||
type: Toasts.Type.SUCCESS
|
||||
});
|
||||
showToast("Successfully refetched badges!", "success");
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { sendBotMessage } from "@api/Commands";
|
||||
import { isPluginEnabled } from "@api/PluginManager";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { getUserSettingLazy } from "@api/UserSettings";
|
||||
|
|
@ -34,7 +33,7 @@ import { CONTRIB_ROLE_ID, Devs, DONOR_ROLE_ID, EQUICORD_TEAM, GUILD_ID, SUPPORT_
|
|||
import { sendMessage } from "@utils/discord";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { isAnyPluginDev, isEquicordGuild, isEquicordSupport, isKnownIssuesCategory, isSupportChannel, tryOrElse } from "@utils/misc";
|
||||
import { isAnyPluginDev, isEquicordGuild, isEquicordSupport, isSupportChannel, tryOrElse } from "@utils/misc";
|
||||
import { relaunch } from "@utils/native";
|
||||
import { onlyOnce } from "@utils/onlyOnce";
|
||||
import { makeCodeblock } from "@utils/text";
|
||||
|
|
@ -49,8 +48,6 @@ import plugins, { PluginMeta } from "~plugins";
|
|||
|
||||
import SettingsPlugin from "./settings";
|
||||
|
||||
const CodeBlockRe = /```snippet\n(.+?)```/s;
|
||||
|
||||
const TrustedRolesIds = [
|
||||
VC_CONTRIB_ROLE_ID, // Vencord Contributor
|
||||
VC_REGULAR_ROLE_ID, // Vencord Regular
|
||||
|
|
@ -61,8 +58,6 @@ const TrustedRolesIds = [
|
|||
VENCORD_CONTRIB_ROLE_ID, // Vencord Contributor
|
||||
];
|
||||
|
||||
const AsyncFunction = async function () { }.constructor;
|
||||
|
||||
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
|
||||
const ShowEmbeds = getUserSettingLazy<boolean>("textAndImages", "renderEmbeds")!;
|
||||
|
||||
|
|
@ -451,12 +446,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");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
|
@ -498,34 +493,6 @@ export default definePlugin({
|
|||
);
|
||||
}
|
||||
}
|
||||
if (equicordSupport || isSupportChannel(props?.channel?.id, true) || isKnownIssuesCategory(props?.channel?.parent_id, true)) {
|
||||
const match = CodeBlockRe.exec(props.message.content || props.message.embeds[0]?.rawDescription || "");
|
||||
if (match) {
|
||||
buttons.push(
|
||||
<Button
|
||||
key="vc-run-snippet"
|
||||
onClick={async () => {
|
||||
try {
|
||||
const result = await AsyncFunction(match[1])();
|
||||
const stringed = String(result);
|
||||
if (stringed) {
|
||||
await sendBotMessage(SelectedChannelStore.getChannelId(), {
|
||||
content: stringed
|
||||
});
|
||||
}
|
||||
|
||||
showToast("Success!", Toasts.Type.SUCCESS);
|
||||
} catch (e) {
|
||||
new Logger(this.name).error("Error while running snippet:", e);
|
||||
showToast("Failed to run snippet :(", Toasts.Type.FAILURE);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Run Snippet
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return buttons.length
|
||||
? <Flex>{buttons}</Flex>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
import { ChatBarButton } from "@api/ChatButtons";
|
||||
import { UploadIcon } from "@components/Icons";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { pluralize } from "@utils/misc";
|
||||
import { pluralise } from "@utils/misc";
|
||||
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 ${pluralize(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`,
|
||||
|
|
@ -86,7 +86,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) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { Link } from "@components/Link";
|
|||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { ReporterTestable } from "@utils/types";
|
||||
import { ApplicationAssetUtils, fetchApplicationsRPC, FluxDispatcher, Toasts } from "@webpack/common";
|
||||
import { ApplicationAssetUtils, fetchApplicationsRPC, FluxDispatcher, showToast } from "@webpack/common";
|
||||
|
||||
async function lookupAsset(applicationId: string, key: string): Promise<string> {
|
||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||
|
|
@ -92,16 +92,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() {
|
||||
|
|
|
|||
|
|
@ -218,12 +218,10 @@ export default definePlugin({
|
|||
settings,
|
||||
openRoleContextMenu,
|
||||
patches: [
|
||||
// This patch is completely overwritten by RoleColorEverywhere, but RoleColorEverywhere handles it itself
|
||||
// member list role headers (in threads)
|
||||
{
|
||||
find: 'tutorialId:"whos-online',
|
||||
replacement: {
|
||||
match: /(?<=#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.{0,200}?"aria-hidden":!0,)children:.{0,200}?(?:—|\\u2014) ",\i\]\}\)\]/,
|
||||
match: /(?<=#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.{0,400}?)children:(?=.{0,20}?(?:—|\\u2014) ",\i\])/,
|
||||
replace: "onContextMenu:e=>$self.openRoleContextMenu(e,arguments[0]),$&"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,22 +18,21 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { getUserSettingLazy } from "@api/UserSettings";
|
||||
import { BaseText } from "@components/BaseText";
|
||||
import { Button } from "@components/Button";
|
||||
import { Card } from "@components/Card";
|
||||
import { Divider } from "@components/Divider";
|
||||
import { ErrorCard } from "@components/ErrorCard";
|
||||
import { Flex } from "@components/Flex";
|
||||
import { Heading } from "@components/Heading";
|
||||
import { Link } from "@components/Link";
|
||||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { isTruthy } from "@utils/guards";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import { useAwaiter } from "@utils/react";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Activity } from "@vencord/discord-types";
|
||||
import { ActivityType } from "@vencord/discord-types/enums";
|
||||
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
|
||||
import { ApplicationAssetUtils, Button, FluxDispatcher, React, UserStore } from "@webpack/common";
|
||||
import { ApplicationAssetUtils, FluxDispatcher, Menu, React, UserStore } from "@webpack/common";
|
||||
|
||||
import { RPCSettings } from "./RpcSettings";
|
||||
|
||||
|
|
@ -80,6 +79,12 @@ export interface RpcConfig {
|
|||
}
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
enablePresence: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Whether to show the presence",
|
||||
default: true,
|
||||
onChange: v => setRpc(!v)
|
||||
},
|
||||
config: {
|
||||
type: OptionType.COMPONENT,
|
||||
component: RPCSettings
|
||||
|
|
@ -211,11 +216,12 @@ async function createActivity(): Promise<Activity | undefined> {
|
|||
}
|
||||
|
||||
export async function setRpc(disable?: boolean) {
|
||||
const shouldDisable = disable ?? !settings.store.enablePresence;
|
||||
const activity: Activity | undefined = await createActivity();
|
||||
|
||||
FluxDispatcher.dispatch({
|
||||
type: "LOCAL_ACTIVITY_UPDATE",
|
||||
activity: !disable ? activity : null,
|
||||
activity: !shouldDisable ? activity : null,
|
||||
socketId: "CustomRPC",
|
||||
});
|
||||
}
|
||||
|
|
@ -257,12 +263,28 @@ export default definePlugin({
|
|||
name: "CustomRPC",
|
||||
description: "Add a fully customisable Rich Presence (Game status) to your Discord profile",
|
||||
tags: ["Activity", "Customisation"],
|
||||
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev],
|
||||
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev, Devs.c0nnorgg],
|
||||
dependencies: ["UserSettingsAPI"],
|
||||
// This plugin's patch is not important for functionality, so don't require a restart
|
||||
requiresRestart: false,
|
||||
settings,
|
||||
|
||||
toolboxActions() {
|
||||
const { enablePresence } = settings.use(["enablePresence"]);
|
||||
|
||||
return (
|
||||
<Menu.MenuCheckboxItem
|
||||
id="custom-rpc-toggle-toolbox"
|
||||
label="Show Custom RPC"
|
||||
checked={enablePresence}
|
||||
action={() => {
|
||||
settings.store.enablePresence = !enablePresence;
|
||||
setRpc();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
start() {
|
||||
startTimestampLoop();
|
||||
setRpc();
|
||||
|
|
@ -284,31 +306,38 @@ export default definePlugin({
|
|||
],
|
||||
|
||||
settingsAboutComponent: () => {
|
||||
const { enablePresence } = settings.use(["enablePresence"]);
|
||||
const [activity] = useAwaiter(createActivity, { fallbackValue: undefined, deps: Object.values(settings.store) });
|
||||
const gameActivityEnabled = ShowCurrentGame.useSetting();
|
||||
const { profileThemeStyle } = useProfileThemeStyle({});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex flexDirection="column" gap=".5em">
|
||||
{!enablePresence && (
|
||||
<Card variant="warning">
|
||||
<Flex flexDirection="column" gap=".5em" alignItems="flex-start">
|
||||
<BaseText size="md" weight="bold">Custom RPC disabled</BaseText>
|
||||
<Paragraph>The "Enable Presence" setting is disabled, so your presence won't show. If this was unintentional, enable it below.</Paragraph>
|
||||
</Flex>
|
||||
</Card>
|
||||
)}
|
||||
{!gameActivityEnabled && (
|
||||
<ErrorCard
|
||||
className={classes(Margins.top16, Margins.bottom16)}
|
||||
style={{ padding: "1em" }}
|
||||
>
|
||||
<Heading>Notice</Heading>
|
||||
<Paragraph>Activity Sharing isn't enabled, people won't be able to see your custom rich presence!</Paragraph>
|
||||
<Card variant="danger">
|
||||
<Flex flexDirection="column" gap=".5em" alignItems="flex-start">
|
||||
<BaseText size="md" weight="bold">Activity Sharing disabled</BaseText>
|
||||
<Paragraph>Activity Sharing isn't enabled, so people won't be able to see your custom rich presence!</Paragraph>
|
||||
|
||||
<Button
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
className={Margins.top8}
|
||||
onClick={() => ShowCurrentGame.updateSetting(true)}
|
||||
>
|
||||
Enable
|
||||
</Button>
|
||||
</ErrorCard>
|
||||
<Button
|
||||
variant="overlayPrimary"
|
||||
onClick={() => ShowCurrentGame.updateSetting(true)}
|
||||
>
|
||||
Enable Activity Sharing
|
||||
</Button>
|
||||
</Flex>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<Flex flexDirection="column" gap=".5em" className={Margins.top16}>
|
||||
<Flex flexDirection="column" gap=".5em">
|
||||
<Paragraph>
|
||||
Go to the <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and
|
||||
get the application ID.
|
||||
|
|
@ -327,16 +356,16 @@ export default definePlugin({
|
|||
</Paragraph>
|
||||
</Flex>
|
||||
|
||||
<Divider className={Margins.top8} />
|
||||
<Divider />
|
||||
|
||||
<div style={{ width: "284px", ...profileThemeStyle, marginTop: 8, borderRadius: 8, background: "var(--background-mod-muted)" }}>
|
||||
<div style={{ width: "284px", ...profileThemeStyle, borderRadius: 8, background: "var(--background-mod-muted)" }}>
|
||||
{activity && <ActivityView
|
||||
activity={activity}
|
||||
user={UserStore.getCurrentUser()}
|
||||
currentUser={UserStore.getCurrentUser()}
|
||||
/>}
|
||||
</div>
|
||||
</>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,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, GuildStore, IconUtils, Menu, Modal, openModalLazy, PermissionsBits, PermissionStore, React, RestAPI, StickersStore, Toasts, Tooltip, UserStore } from "@webpack/common";
|
||||
import { Constants, EmojiStore, FluxDispatcher, 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");
|
||||
|
|
@ -198,11 +198,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 {
|
||||
|
|
@ -210,11 +206,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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ const fakeNitroEmojiRegex = /\/emojis\/(\d+?)\.(png|webp|gif)/;
|
|||
const fakeNitroStickerRegex = /\/stickers\/(\d+?)\./;
|
||||
const fakeNitroGifStickerRegex = /\/attachments\/\d+?\/\d+?\/(\d+?)\.gif/;
|
||||
const hyperLinkRegex = /\[.+?\]\((https?:\/\/.+?)\)/;
|
||||
const hyperLinkOnlyRegex = new RegExp(`^${hyperLinkRegex.source}$`);
|
||||
const mediaSizes = [16, 32, 48, 56, 64, 96, 128, 160, 256, 512, 1024];
|
||||
|
||||
const DEFAULT_EMOJI_SIZE = 48;
|
||||
|
|
@ -578,6 +579,7 @@ export default definePlugin({
|
|||
const contentItems = message.content.split(/\s/);
|
||||
if (settings.store.transformCompoundSentence) itemsToMaybePush.push(...contentItems);
|
||||
else if (contentItems.length === 1) itemsToMaybePush.push(contentItems[0]);
|
||||
else if (hyperLinkOnlyRegex.test(message.content)) itemsToMaybePush.push(message.content);
|
||||
|
||||
itemsToMaybePush.push(...message.attachments.filter(attachment => attachment.content_type === "image/gif").map(attachment => attachment.url));
|
||||
|
||||
|
|
@ -622,7 +624,7 @@ export default definePlugin({
|
|||
shouldIgnoreEmbed(embed: Message["embeds"][number], message: Message) {
|
||||
try {
|
||||
const contentItems = message.content.split(/\s/);
|
||||
if (contentItems.length > 1 && !settings.store.transformCompoundSentence) return false;
|
||||
if (contentItems.length > 1 && !settings.store.transformCompoundSentence && !hyperLinkOnlyRegex.test(message.content)) return false;
|
||||
|
||||
switch (embed.type) {
|
||||
case "image": {
|
||||
|
|
@ -631,6 +633,7 @@ export default definePlugin({
|
|||
if (
|
||||
!settings.store.transformCompoundSentence
|
||||
&& !contentItems.some(item => item === url || item.match(hyperLinkRegex)?.[1] === url)
|
||||
&& !hyperLinkOnlyRegex.test(message.content)
|
||||
) return false;
|
||||
|
||||
if (settings.store.transformEmojis) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
|
@ -296,8 +296,8 @@ export default definePlugin({
|
|||
find: '"LocalActivityStore"',
|
||||
replacement: [
|
||||
{
|
||||
match: /\.LISTENING.+?(?=!?\i\(\)\(\i,\i\))(?<=(\i)\.push.+?)/,
|
||||
replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);`
|
||||
match: /\.LISTENING.+?([,:])(?=!?\i\(\)\(\i,\i\))(?<=(\i)\.push.+?)/,
|
||||
replace: (m, commaOrSemiColon, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored)${commaOrSemiColon}`
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export default definePlugin({
|
|||
FluxDispatcher.dispatch({
|
||||
type: "GUILD_MEMBERS_REQUEST",
|
||||
guildIds: allGuildIds,
|
||||
userIds: toRequest.slice(i, i + 100),
|
||||
userIds: toRequest.slice(i, i + 100).map(e => e.otherUserId),
|
||||
presences: true,
|
||||
nonce: sentNonce,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -145,7 +145,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);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,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, Modal, openModalLazy, TextInput, Toasts, useMemo, useState } from "@webpack/common";
|
||||
import { ColorPicker, Modal, openModalLazy, TextInput, useMemo, useState } from "@webpack/common";
|
||||
|
||||
interface ColorPickerWithSwatchesProps {
|
||||
className?: string;
|
||||
|
|
@ -41,7 +41,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,
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,7 +59,7 @@ 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;
|
||||
}
|
||||
|
||||
|
|
@ -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): Promise<UserReviewsData | null> {
|
||||
export async function addReview(review: { userid: string; comment: string; }): Promise<UserReviewsData | null> {
|
||||
|
||||
const token = await getToken();
|
||||
if (!token) {
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,8 @@
|
|||
*/
|
||||
|
||||
import { isPluginEnabled } from "@api/PluginManager";
|
||||
import { definePluginSettings, Settings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { getCustomColorString } from "@equicordplugins/customUserColors";
|
||||
import BetterRoleContext from "@plugins/betterRoleContext";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import customUserColors, { getCustomColorString } from "@equicordplugins/customUserColors";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import definePlugin, { makeRange, OptionType } from "@utils/types";
|
||||
|
|
@ -110,8 +108,8 @@ export default definePlugin({
|
|||
find: 'tutorialId:"whos-online',
|
||||
replacement: [
|
||||
{
|
||||
match: /(#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.{0,200}?}\):null,).{0,200}?(?:—|\\u2014) ",\i\]\}\)\]/,
|
||||
replace: "$1$self.RoleGroupColor(arguments[0])]"
|
||||
match: /(?<=#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.{0,400}?)children:(?=.{0,20}?(?:—|\\u2014) ",\i\])/,
|
||||
replace: "style:{color:$self.getRoleColor(arguments[0])},$&"
|
||||
},
|
||||
],
|
||||
predicate: () => settings.store.memberList
|
||||
|
|
@ -121,8 +119,8 @@ export default definePlugin({
|
|||
find: "?null:new Intl.NumberFormat",
|
||||
replacement: [
|
||||
{
|
||||
match: /\(0,\i\.jsx\)\("span",\{[^}]+\}\),null==\i\?null:\(0,\i\.jsxs\)\("span",\{children:\["\\xa0\\u2014 ",\i\]\}\)\]/,
|
||||
replace: "$self.RoleGroupColor(arguments[0])]"
|
||||
match: /(?<=#{intl::CHANNEL_MEMBERS_A11Y_LABEL},\{title:\i,count:\i\}\)\}\),\(0,\i\.jsxs\)\("div",\{)/,
|
||||
replace: "style:{color:$self.getRoleColor(arguments[0])},"
|
||||
},
|
||||
],
|
||||
predicate: () => settings.store.memberList
|
||||
|
|
@ -169,7 +167,7 @@ export default definePlugin({
|
|||
|
||||
getColorString(userId: string, channelOrGuildId: string) {
|
||||
try {
|
||||
if (Settings.plugins.CustomUserColors.enabled) {
|
||||
if (isPluginEnabled(customUserColors.name)) {
|
||||
const customColor = getCustomColorString(userId, true);
|
||||
if (customColor) return customColor;
|
||||
}
|
||||
|
|
@ -222,22 +220,9 @@ export default definePlugin({
|
|||
return null;
|
||||
},
|
||||
|
||||
RoleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => {
|
||||
const role = GuildRoleStore.getRole(guildId, id);
|
||||
// we overwrite the context menu event added by BetterRoleContext in our patch
|
||||
const wantsRoleContext = isPluginEnabled(BetterRoleContext.name);
|
||||
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
color: role?.colorString,
|
||||
fontWeight: "unset",
|
||||
letterSpacing: ".05em"
|
||||
}}
|
||||
onContextMenu={wantsRoleContext ? e => BetterRoleContext.openRoleContextMenu(e, { guildId, id }) : undefined}
|
||||
>
|
||||
{title ?? label} — {count}
|
||||
</span>
|
||||
);
|
||||
}, { noop: true })
|
||||
getRoleColor(props: any) {
|
||||
try {
|
||||
return GuildRoleStore.getRole(props?.guildId, props?.id)?.colorString;
|
||||
} catch (e) { }
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default definePlugin({
|
|||
{
|
||||
// This function is a util func from another module
|
||||
// but it only has once use here so it's inlined
|
||||
find: ".CREATE_FORUM_POST||function(",
|
||||
find: '.STICKER_PICKER:return""',
|
||||
replacement: {
|
||||
match: /(?<=\){)if\(\i\.\i\.getUploadCount/,
|
||||
replace: "return true;$&",
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,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, Toasts, Tooltip, useMemo, UserStore, UserSummaryItem, useStateFromStores, VoiceStateStore } from "@webpack/common";
|
||||
import { ChannelRouter, ChannelStore, Parser, PermissionsBits, PermissionStore, React, showToast, Tooltip, useMemo, UserStore, UserSummaryItem, useStateFromStores, VoiceStateStore } from "@webpack/common";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
const cl = classNameFactory("vc-uvs-");
|
||||
|
|
@ -155,7 +155,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 { settings, type VoiceRecorder } from "..";
|
||||
|
||||
|
|
@ -46,7 +46,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 {
|
||||
|
|
@ -56,7 +56,7 @@ export const VoiceRecorderDesktop: VoiceRecorder = ({ setAudioBlob, onRecordingC
|
|||
if (buf)
|
||||
setAudioBlob(new Blob([new Uint8Array(buf)], { type: "audio/ogg; codecs=opus" }));
|
||||
else
|
||||
showToast("Failed to finish recording", Toasts.Type.FAILURE);
|
||||
showToast("Failed to finish recording", "failure");
|
||||
}
|
||||
changeRecording(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import definePlugin, { OptionType } from "@utils/types";
|
|||
import { chooseFile } from "@utils/web";
|
||||
import { RenderModalProps } from "@vencord/discord-types";
|
||||
import { CloudUploadPlatform } from "@vencord/discord-types/enums";
|
||||
import { Button, CloudUploader, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, Modal, openModal, PendingReplyStore, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common";
|
||||
import { Button, CloudUploader, 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 "./components/DesktopRecorder";
|
||||
|
|
@ -190,7 +190,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();
|
||||
}
|
||||
|
|
@ -244,7 +244,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
|
||||
}]}
|
||||
|
|
|
|||
|
|
@ -698,6 +698,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||
Kaede: {
|
||||
name: "Kaede",
|
||||
id: 1492642701320126504n
|
||||
},
|
||||
c0nnorgg: {
|
||||
name: "c0nnorgg",
|
||||
id: 1088882977985003620n,
|
||||
}
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import type { MessageObject } from "@api/MessageEvents";
|
||||
import type { BasicGuild, Channel, CloudUpload, Guild, GuildFeatures, GuildProfile, 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, openUserProfileModal, RestAPI, SelectedChannelStore, SelectedGuildStore, showToast, 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");
|
||||
}
|
||||
|
||||
export interface MessageOptions {
|
||||
|
|
@ -182,10 +178,14 @@ export async function openUserProfile(id: string) {
|
|||
if (!user) throw new Error("No such user: " + id);
|
||||
|
||||
const guildId = SelectedGuildStore.getGuildId();
|
||||
UserProfileActions.openUserProfileModal({
|
||||
openUserProfileModal({
|
||||
userId: id,
|
||||
guildId,
|
||||
channelId: SelectedChannelStore.getChannelId(),
|
||||
sourceAnalyticsLocations: [
|
||||
"username",
|
||||
"user profile popout",
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
@ -70,23 +70,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,
|
||||
|
|
@ -106,40 +89,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 = {
|
||||
|
|
@ -185,9 +146,7 @@ export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?",
|
|||
|
||||
export const MessageActions = findByPropsLazy("editMessage", "sendMessage");
|
||||
export const MessageCache = findByPropsLazy("clearCache", "_channelMessages");
|
||||
export const UserProfileActions: t.UserProfileModalActionCreators = mapMangledModuleLazy(".log(`Failed to fetch profile for $", {
|
||||
openUserProfileModal: filters.byCode('type:"USER_PROFILE_MODAL_OPEN"')
|
||||
});
|
||||
export const openUserProfileModal: t.OpenUserProfileModal = findByCodeLazy('type:"USER_PROFILE_MODAL_OPEN"');
|
||||
export const InviteActions = findByPropsLazy("resolveInvite");
|
||||
export const ChannelActionCreators = findByPropsLazy("openPrivateChannel");
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue