Merge branch 'translation' into l10n_translation
This commit is contained in:
commit
f79c5fd566
303 changed files with 4613 additions and 1784 deletions
1330
i18n/en-US/equicord.json
Normal file
1330
i18n/en-US/equicord.json
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -21,8 +21,8 @@ import "./AddonCard.css";
|
|||
import { Badge } from "@components/Badge";
|
||||
import { BaseText } from "@components/BaseText";
|
||||
import { Switch } from "@components/Switch";
|
||||
import { t } from "@utils/translation";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import { Tooltip, useRef } from "@webpack/common";
|
||||
import type { MouseEventHandler, ReactNode } from "react";
|
||||
|
||||
|
|
|
|||
|
|
@ -35,19 +35,20 @@ export function resolveError(isValidResult: boolean | string) {
|
|||
|
||||
interface SettingsSectionProps extends PropsWithChildren {
|
||||
name: string;
|
||||
description: string;
|
||||
description: string | (() => string);
|
||||
error?: string | null;
|
||||
inlineSetting?: boolean;
|
||||
tag?: "label" | "div";
|
||||
}
|
||||
|
||||
export function SettingsSection({ tag: Tag = "div", name, description, error, inlineSetting, children }: SettingsSectionProps) {
|
||||
const resolvedDescription = typeof description === "function" ? description() : description;
|
||||
return (
|
||||
<Tag className={cl("section")}>
|
||||
<div className={classes(cl("content"), inlineSetting && cl("inline"))}>
|
||||
<div className={cl("label")}>
|
||||
{name && <BaseText className={cl("title")} size="md" weight="medium">{wordsToTitle(wordsFromCamel(name))}</BaseText>}
|
||||
{description && <BaseText className={cl("description")} size="sm">{description}</BaseText>}
|
||||
{resolvedDescription && <BaseText className={cl("description")} size="sm">{resolvedDescription}</BaseText>}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { HeadingSecondary } from "@components/Heading";
|
|||
import { Paragraph } from "@components/Paragraph";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { ApplicationAssetUtils, FluxDispatcher, showToast } from "@webpack/common";
|
||||
|
||||
|
|
@ -51,15 +52,15 @@ interface MediaData {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
serverUrl: {
|
||||
description: "AudioBookShelf server URL (e.g., https://abs.example.com)",
|
||||
description: t("absRPC.settings.serverUrl"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
username: {
|
||||
description: "AudioBookShelf username",
|
||||
description: t("absRPC.settings.username"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
password: {
|
||||
description: "AudioBookShelf password",
|
||||
description: t("absRPC.settings.password"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
});
|
||||
|
|
@ -85,16 +86,16 @@ function setActivity(activity: Activity | null) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "AudioBookShelfRichPresence",
|
||||
description: "Rich presence for AudioBookShelf media server",
|
||||
description: t("absRPC.description"),
|
||||
authors: [EquicordDevs.vmohammad],
|
||||
|
||||
settingsAboutComponent: () => (
|
||||
<>
|
||||
<HeadingSecondary>How to connect to AudioBookShelf</HeadingSecondary>
|
||||
<HeadingSecondary>{t("absRPC.about.title")}</HeadingSecondary>
|
||||
<Paragraph>
|
||||
Enter your AudioBookShelf server URL, username, and password to display your currently playing audiobooks as Discord Rich Presence.
|
||||
{t("absRPC.about.description")}
|
||||
<br /><br />
|
||||
The plugin will automatically authenticate and fetch your listening progress.
|
||||
{t("absRPC.about.automaticAuth")}
|
||||
</Paragraph>
|
||||
</>
|
||||
),
|
||||
|
|
@ -114,7 +115,7 @@ export default definePlugin({
|
|||
async authenticate(): Promise<boolean> {
|
||||
if (!settings.store.serverUrl || !settings.store.username || !settings.store.password) {
|
||||
logger.warn("AudioBookShelf server URL, username, or password is not set in settings.");
|
||||
showToast("AudioBookShelf RPC is not configured.", "failure", {
|
||||
showToast(t("absRPC.toasts.notConfigured"), "failure", {
|
||||
duration: 15000,
|
||||
});
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "AltKrispSwitch",
|
||||
description: "Makes the Noise Suppression Popout switch between None and Krisp instead of Krisp and Standard",
|
||||
description: t("altKrispSwitch.description"),
|
||||
authors: [Devs.newwares],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,11 +6,12 @@
|
|||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { openUserProfile } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "AlwaysExpandProfiles",
|
||||
description: "Always expands profile popouts to the full modal",
|
||||
description: t("alwaysExpandProfiles.description"),
|
||||
authors: [Devs.thororen],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,50 +6,51 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
dms: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Remove shops above DMs list",
|
||||
description: t("anammox.settings.dms"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
quests: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
description: "Remove quests above DMs list",
|
||||
description: t("anammox.settings.quests"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
serverBoost: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Remove server boost info above channel list",
|
||||
description: t("anammox.settings.serverBoost"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
billing: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Remove billing settings",
|
||||
description: t("anammox.settings.billing"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
gift: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Remove gift button",
|
||||
description: t("anammox.settings.gift"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
emojiList: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Remove unavailable categories from the emoji picker",
|
||||
description: t("anammox.settings.emojiList"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "Anammox",
|
||||
description: "Hides various features related to nitro and the store",
|
||||
description: t("anammox.description"),
|
||||
authors: [Devs.Kyuuhachi],
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -6,57 +6,58 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { SelectedChannelStore, UserStore } from "@webpack/common";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
volume: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Volume of the animalese sound",
|
||||
description: t("animalese.settings.volume"),
|
||||
default: 0.5,
|
||||
markers: [0, 0.1, 0.25, 0.5, 0.6, 0.75, 1],
|
||||
},
|
||||
speed: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Speed of the animalese sound",
|
||||
description: t("animalese.settings.speed"),
|
||||
default: 1,
|
||||
markers: [0.5, 0.75, 1, 1.25, 1.5],
|
||||
},
|
||||
pitch: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Pitch multiplier",
|
||||
description: t("animalese.settings.pitch"),
|
||||
default: 1,
|
||||
markers: [0.75, 0.8, 0.85, 1, 1.15, 1.25, 1.35, 1.5],
|
||||
},
|
||||
messageLengthLimit: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "Maximum length of message to process",
|
||||
description: t("animalese.settings.messageLengthLimit"),
|
||||
default: 50,
|
||||
},
|
||||
processOwnMessages: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable to yap your own messages too",
|
||||
description: t("animalese.settings.processOwnMessages"),
|
||||
default: true,
|
||||
},
|
||||
soundQuality: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Quality of sound to use",
|
||||
description: t("animalese.settings.soundQuality"),
|
||||
options: [
|
||||
{
|
||||
label: "High",
|
||||
label: t("animalese.quality.high"),
|
||||
value: "high",
|
||||
default: true
|
||||
},
|
||||
{
|
||||
label: "Medium",
|
||||
label: t("animalese.quality.medium"),
|
||||
value: "med"
|
||||
},
|
||||
{
|
||||
label: "Low",
|
||||
label: t("animalese.quality.low"),
|
||||
value: "low"
|
||||
},
|
||||
{
|
||||
label: "Lowest",
|
||||
label: t("animalese.quality.lowest"),
|
||||
value: "low"
|
||||
}
|
||||
]
|
||||
|
|
@ -192,7 +193,7 @@ async function playSound(buffer: AudioBuffer, volume: number) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "Animalese",
|
||||
description: "Plays animal crossing animalese for every message sent (they yap a lot)",
|
||||
description: t("animalese.description"),
|
||||
authors: [EquicordDevs.ryanamay, EquicordDevs.Mocha],
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -6,20 +6,21 @@
|
|||
|
||||
import { addMessagePreSendListener, removeMessagePreSendListener } from "@api/MessageEvents";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { ChannelStore, GuildMemberStore, SelectedChannelStore, SelectedGuildStore } from "@webpack/common";
|
||||
|
||||
export default definePlugin({
|
||||
name: "AtSomeone",
|
||||
authors: [Devs.Joona],
|
||||
description: "Mention someone randomly",
|
||||
description: t("atSomeone.description"),
|
||||
patches: [
|
||||
{
|
||||
find: ".LAUNCHABLE_APPLICATIONS;",
|
||||
replacement: [
|
||||
{
|
||||
match: /&(\i)\(\)\((\i),\i\(\)\.test\)&&(\i)\.push\(\i\(\)\)/g,
|
||||
replace: "$&,$1()($2,/someone/.test)&&$3.push({text:'@someone',description:'Mention someone randomly'})"
|
||||
replace: "$&,$1()($2,/someone/.test)&&$3.push({text:'@someone',description:$self.getSomeoneDescription()})"
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -31,6 +32,9 @@ export default definePlugin({
|
|||
}
|
||||
}
|
||||
],
|
||||
getSomeoneDescription() {
|
||||
return t("atSomeone.contextMenu.someone");
|
||||
},
|
||||
start() {
|
||||
this.preSend = addMessagePreSendListener((_, msg) => {
|
||||
msg.content = msg.content.replace(/@someone/g, () => `<@${randomUser()}>`);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { ChannelStore, DraftType, SelectedChannelStore, UploadHandler } from "@webpack/common";
|
||||
import { zipSync } from "fflate";
|
||||
|
|
@ -16,7 +17,7 @@ const logger = new Logger("AutoZipper");
|
|||
const settings = definePluginSettings({
|
||||
extensions: {
|
||||
type: OptionType.STRING,
|
||||
description: "Comma-separated list of file extensions to auto-zip (e.g., .psd,.blend,.exe,.dmg)",
|
||||
description: t("autoZipper.settings.extensions"),
|
||||
default: ".psd,.blend,.exe,.dmg,.app,.apk,.iso",
|
||||
onChange: () => {
|
||||
extensionsToZip.clear();
|
||||
|
|
@ -208,7 +209,7 @@ function handlePaste(event: ClipboardEvent) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "AutoZipper",
|
||||
description: "Automatically zips specified file types and folders before uploading to Discord",
|
||||
description: t("autoZipper.description"),
|
||||
authors: [EquicordDevs.SSnowly],
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import usrbg from "@plugins/usrbg";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { UserProfileStore } from "@webpack/common";
|
||||
|
|
@ -28,12 +29,12 @@ interface Nameplate {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
animate: {
|
||||
description: "Animate banners",
|
||||
description: t("bannersEverywhere.settings.animate"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
preferNameplate: {
|
||||
description: "prefer nameplate over banner",
|
||||
description: t("bannersEverywhere.settings.preferNameplate"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
|
|
@ -43,7 +44,7 @@ const DATASTORE_KEY = "bannersEverywhere";
|
|||
|
||||
export default definePlugin({
|
||||
name: "BannersEverywhere",
|
||||
description: "Displays banners in the member list ",
|
||||
description: t("bannersEverywhere.description"),
|
||||
authors: [Devs.ImLvna, Devs.AutumnVN],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { Heading } from "@components/Heading";
|
|||
import { EquicordDevs } from "@utils/constants";
|
||||
import { copyWithToast } from "@utils/discord";
|
||||
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Button, ChannelStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -68,12 +69,12 @@ function openDecodedBase64Modal(decodedContent) {
|
|||
<ErrorBoundary>
|
||||
<ModalRoot {...props} size={ModalSize.LARGE}>
|
||||
<ModalHeader>
|
||||
<BaseText size="lg" weight="semibold" style={{ flexGrow: 1 }}>Decoded Base64 Content</BaseText>
|
||||
<BaseText size="lg" weight="semibold" style={{ flexGrow: 1 }}>{t("baseDecoder.ui.modalTitle")}</BaseText>
|
||||
<ModalCloseButton onClick={() => closeModal(key)} />
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<div style={{ padding: "16px 0" }}>
|
||||
<Heading>Decoded Content</Heading>
|
||||
<Heading>{t("baseDecoder.ui.decodedContent")}</Heading>
|
||||
{decodedContent.map((content, index) => (
|
||||
<CodeBlock key={index} content={content} lang="" />
|
||||
))}
|
||||
|
|
@ -82,8 +83,8 @@ function openDecodedBase64Modal(decodedContent) {
|
|||
<ModalFooter>
|
||||
<Flex gap={10}>
|
||||
{decodedContent.map((content, index) => (
|
||||
<Button key={index} onClick={() => copyWithToast(content, "Decoded content copied to clipboard!")}>
|
||||
Copy Decoded Content {index + 1}
|
||||
<Button key={index} onClick={() => copyWithToast(content, t("baseDecoder.ui.copiedToast"))}>
|
||||
{t("baseDecoder.ui.copyDecoded")} {index + 1}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
|
|
@ -95,18 +96,18 @@ function openDecodedBase64Modal(decodedContent) {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
clickMethod: {
|
||||
description: "Change the button to decode base64 content of any message.",
|
||||
description: t("baseDecoder.settings.clickMethod"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "Left Click to decode the base64 content.", value: "Left", default: true },
|
||||
{ label: "Right click to decode the base64 content.", value: "Right" }
|
||||
{ label: t("baseDecoder.settings.clickMethodOptions.left"), value: "Left", default: true },
|
||||
{ label: t("baseDecoder.settings.clickMethodOptions.right"), value: "Right" }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "DecodeBase64",
|
||||
description: "Decode base64 content of any message and copy the decoded content.",
|
||||
description: t("baseDecoder.description"),
|
||||
authors: [EquicordDevs.ThePirateStoner],
|
||||
settings,
|
||||
messagePopoverButton: {
|
||||
|
|
@ -137,8 +138,8 @@ export default definePlugin({
|
|||
};
|
||||
|
||||
const label = settings.store.clickMethod === "Right"
|
||||
? "Copy Decoded (Left Click) / Decode Base64 (Right Click)"
|
||||
: "Decode Base64 (Left Click) / Copy Decoded (Right Click)";
|
||||
? t("baseDecoder.ui.tooltipLeft")
|
||||
: t("baseDecoder.ui.tooltipRight");
|
||||
|
||||
return {
|
||||
label,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import "./styles.css";
|
|||
|
||||
import { migratePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { patchActivityList } from "./patch-helpers/activityList";
|
||||
|
|
@ -18,7 +19,7 @@ migratePluginSettings("BetterActivities", "MemberListActivities");
|
|||
|
||||
export default definePlugin({
|
||||
name: "BetterActivities",
|
||||
description: "Shows activity icons in the member list and allows showing all activities",
|
||||
description: t("betterActivities.description"),
|
||||
authors: [Devs.D3SOX, Devs.Arjix, Devs.AutumnVN, Devs.thororen],
|
||||
tags: ["activity"],
|
||||
settings,
|
||||
|
|
|
|||
|
|
@ -5,38 +5,39 @@
|
|||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { t } from "@utils/translation";
|
||||
import { OptionType } from "@utils/types";
|
||||
import { React } from "@webpack/common";
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
memberList: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show activity icons in the member list",
|
||||
description: t("betterActivities.settings.memberList"),
|
||||
default: true,
|
||||
restartNeeded: true,
|
||||
},
|
||||
iconSize: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Size of the activity icons",
|
||||
description: t("betterActivities.settings.iconSize"),
|
||||
markers: [10, 15, 20],
|
||||
default: 15,
|
||||
stickToMarkers: false,
|
||||
},
|
||||
specialFirst: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show special activities first (Currently Spotify and Twitch)",
|
||||
description: t("betterActivities.settings.specialFirst"),
|
||||
default: true,
|
||||
restartNeeded: false,
|
||||
},
|
||||
renderGifs: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Allow rendering GIFs",
|
||||
description: t("betterActivities.settings.renderGifs"),
|
||||
default: true,
|
||||
restartNeeded: false,
|
||||
},
|
||||
removeGameActivityStatus: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove game activity icon and status",
|
||||
description: t("betterActivities.settings.removeGameActivityStatus"),
|
||||
default: false,
|
||||
restartNeeded: true,
|
||||
},
|
||||
|
|
@ -55,26 +56,26 @@ export const settings = definePluginSettings({
|
|||
},
|
||||
userPopout: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show all activities in the profile popout/sidebar",
|
||||
description: t("betterActivities.settings.userPopout"),
|
||||
default: true,
|
||||
restartNeeded: true,
|
||||
},
|
||||
hideTooltip: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hides activities in various places",
|
||||
description: t("betterActivities.settings.hideTooltip"),
|
||||
default: true,
|
||||
},
|
||||
allActivitiesStyle: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Style for showing all activities",
|
||||
description: t("betterActivities.settings.allActivitiesStyle"),
|
||||
options: [
|
||||
{
|
||||
default: true,
|
||||
label: "Carousel",
|
||||
label: t("betterActivities.options.carousel"),
|
||||
value: "carousel",
|
||||
},
|
||||
{
|
||||
label: "List",
|
||||
label: t("betterActivities.options.list"),
|
||||
value: "list",
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import "./style.css";
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { showToast, Toasts } from "@webpack/common";
|
||||
|
||||
|
|
@ -245,7 +246,7 @@ function handleColorChange(value, settingKey, defaultValue) {
|
|||
if (rgb.match(rgbPattern)) {
|
||||
settings.store[settingKey] = rgb;
|
||||
} else {
|
||||
showToast(`Invalid color format for ${settingKey}, make sure it's in the format 'R, G, B' or '#RRGGBB'`, Toasts.Type.FAILURE);
|
||||
showToast(t("betterAudioPlayer.toasts.invalidColor", { settingKey }), Toasts.Type.FAILURE);
|
||||
settings.store[settingKey] = defaultValue;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -256,39 +257,39 @@ function handleColorChange(value, settingKey, defaultValue) {
|
|||
const settings = definePluginSettings({
|
||||
oscilloscope: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable oscilloscope visualizer",
|
||||
description: t("betterAudioPlayer.settings.oscilloscope"),
|
||||
default: true,
|
||||
},
|
||||
spectrograph: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable spectrograph visualizer",
|
||||
description: t("betterAudioPlayer.settings.spectrograph"),
|
||||
default: true,
|
||||
},
|
||||
oscilloscopeSolidColor: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Use solid color for oscilloscope",
|
||||
description: t("betterAudioPlayer.settings.oscilloscopeSolidColor"),
|
||||
default: false,
|
||||
},
|
||||
oscilloscopeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Color for oscilloscope",
|
||||
description: t("betterAudioPlayer.settings.oscilloscopeColor"),
|
||||
default: "255, 255, 255",
|
||||
onChange: value => handleColorChange(value, "oscilloscopeColor", "255, 255, 255"),
|
||||
},
|
||||
spectrographSolidColor: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Use solid color for spectrograph",
|
||||
description: t("betterAudioPlayer.settings.spectrographSolidColor"),
|
||||
default: false,
|
||||
},
|
||||
spectrographColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Color for spectrograph",
|
||||
description: t("betterAudioPlayer.settings.spectrographColor"),
|
||||
default: "33, 150, 243",
|
||||
onChange: value => handleColorChange(value, "spectrographColor", "33, 150, 243"),
|
||||
},
|
||||
forceMoveBelow: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Force the visualizer below the audio player",
|
||||
description: t("betterAudioPlayer.settings.forceMoveBelow"),
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
|
@ -297,7 +298,7 @@ let observer: MutationObserver | null = null;
|
|||
|
||||
export default definePlugin({
|
||||
name: "BetterAudioPlayer",
|
||||
description: "Adds a spectrograph and oscilloscope visualizer to audio attachment players",
|
||||
description: t("betterAudioPlayer.description"),
|
||||
authors: [EquicordDevs.creations],
|
||||
settings,
|
||||
start() {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { Heading } from "@components/Heading";
|
|||
import { DeleteIcon, PlusIcon } from "@components/Icons";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Button, TextInput } from "@webpack/common";
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ function ReasonsComponent() {
|
|||
|
||||
return (
|
||||
<section>
|
||||
<Heading>Reasons</Heading>
|
||||
<Heading>{t("betterBanReasons.ui.reasons")}</Heading>
|
||||
{reasons.map((r, i) => (
|
||||
<div
|
||||
key={i}
|
||||
|
|
@ -33,7 +34,7 @@ function ReasonsComponent() {
|
|||
reasons[i] = v;
|
||||
settings.store.reasons = reasons;
|
||||
}}
|
||||
placeholder="Reason"
|
||||
placeholder={t("betterBanReasons.ui.reasonPlaceholder")}
|
||||
/>
|
||||
<Button
|
||||
className={cl("remove-button")}
|
||||
|
|
@ -51,7 +52,7 @@ function ReasonsComponent() {
|
|||
))}
|
||||
<div className={cl("reason-wrapper")}>
|
||||
<Button onClick={() => settings.store.reasons.push("")} className={cl("add-button")} size={Button.Sizes.LARGE} color={Button.Colors.TRANSPARENT}>
|
||||
<PlusIcon /> Add another reason
|
||||
<PlusIcon /> {t("betterBanReasons.ui.addAnotherReason")}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -60,20 +61,20 @@ function ReasonsComponent() {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
reasons: {
|
||||
description: "Your custom reasons",
|
||||
description: t("betterBanReasons.settings.reasons"),
|
||||
type: OptionType.COMPONENT,
|
||||
default: [] as string[],
|
||||
component: ReasonsComponent,
|
||||
},
|
||||
isTextInputDefault: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: 'Shows a text input instead of a select menu by default. (Equivalent to clicking the "Other" option)'
|
||||
description: t("betterBanReasons.settings.isTextInputDefault")
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterBanReasons",
|
||||
description: "Create custom reasons to use in the Discord ban modal, and/or show a text input by default instead of the options.",
|
||||
description: t("betterBanReasons.description"),
|
||||
authors: [Devs.Inbestigator],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import "./styles.css";
|
|||
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { getIntlMessage, openUserProfile } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Button, React, RelationshipStore, TextInput, UserStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ let updateFunc = (v: any) => { };
|
|||
|
||||
export default definePlugin({
|
||||
name: "BetterBlockedUsers",
|
||||
description: "Allows you to search in blocked users list and makes names selectable in settings.",
|
||||
description: t("betterBlockedUsers.description"),
|
||||
authors: [EquicordDevs.TheArmagan],
|
||||
patches: [
|
||||
{
|
||||
|
|
@ -50,7 +51,7 @@ export default definePlugin({
|
|||
}, []);
|
||||
|
||||
return <TextInput
|
||||
placeholder="Search users..."
|
||||
placeholder={t("betterBlockedUsers.ui.searchPlaceholder")}
|
||||
style={{ width: "200px" }}
|
||||
onInput={e => {
|
||||
const search = (e.target as HTMLInputElement).value.toLowerCase().trim();
|
||||
|
|
|
|||
|
|
@ -7,17 +7,18 @@
|
|||
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { FluxDispatcher, UserStore } from "@webpack/common";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
autoFillArguments: {
|
||||
description: "Automatically fill command with all arguements instead of just required ones",
|
||||
description: t("betterCommands.settings.autoFillArguments"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
},
|
||||
allowNewlinesInCommands: {
|
||||
description: "Allow newlines in command inputs (CTRL + Shift + Enter)",
|
||||
description: t("betterCommands.settings.allowNewlinesInCommands"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
}
|
||||
|
|
@ -32,7 +33,7 @@ function fetchIndex(target: object) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "BetterCommands",
|
||||
description: "Enhances the command system with miscellaneous improvements.",
|
||||
description: t("betterCommands.description"),
|
||||
authors: [Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
@ -70,11 +71,11 @@ export default definePlugin({
|
|||
commands: [
|
||||
{
|
||||
name: "refresh",
|
||||
description: "Refreshes Discord application commands locally",
|
||||
description: t("betterCommands.commands.refresh.description"),
|
||||
options: [
|
||||
{
|
||||
name: "user",
|
||||
description: "specific user to try and refresh",
|
||||
description: t("betterCommands.commands.refresh.userOption"),
|
||||
type: ApplicationCommandOptionType.USER,
|
||||
}
|
||||
],
|
||||
|
|
@ -86,7 +87,7 @@ export default definePlugin({
|
|||
const user = findOption(opts, "user") as string;
|
||||
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content: "Refreshing application commands...",
|
||||
content: t("betterCommands.commands.refresh.refreshing"),
|
||||
});
|
||||
|
||||
fetchIndex({ type: "channel", channelId });
|
||||
|
|
@ -103,12 +104,12 @@ export default definePlugin({
|
|||
}
|
||||
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content: "Commands refreshed successfully!",
|
||||
content: t("betterCommands.commands.refresh.success"),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("[Refresh Command] Error refreshing commands:", err);
|
||||
sendBotMessage(ctx.channel.id, {
|
||||
content: "Failed to refresh commands. Check the console for details.",
|
||||
content: t("betterCommands.commands.refresh.failed"),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { InfoIcon } from "@components/Icons";
|
|||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { openUserProfile } from "@utils/discord";
|
||||
import { classes } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { StartAt } from "@utils/types";
|
||||
import { Guild } from "@vencord/discord-types";
|
||||
import { findByPropsLazy, findCssClassesLazy } from "@webpack";
|
||||
|
|
@ -33,7 +34,7 @@ function lurk(id: string) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "BetterInvites",
|
||||
description: "See invites expiration date, view inviter profile and preview servers before joining by clicking the name",
|
||||
description: t("betterInvites.description"),
|
||||
authors: [EquicordDevs.iamme, Devs.thororen],
|
||||
patches: [
|
||||
{
|
||||
|
|
@ -66,7 +67,9 @@ export default definePlugin({
|
|||
const timestamp = <>{Parser.parse(`<t:${Math.round(new Date(expires_at).getTime() / 1000)}:R>`)}</>;
|
||||
const tooltipText = (
|
||||
<>
|
||||
This invite will {expires_at ? <>expire {timestamp}</> : <>not expire</>}
|
||||
{t("betterInvites.ui.expireTooltip", {
|
||||
expiry: expires_at ? <>{t("betterInvites.ui.expireWill")} {timestamp}</> : <>{t("betterInvites.ui.notExpire")}</>
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
||||
|
|
@ -98,7 +101,7 @@ export default definePlugin({
|
|||
: "/assets/1f0bfc0865d324c2587920a7d80c609b.png?size=128"}
|
||||
/>
|
||||
<div className="vc-bi-header-text">
|
||||
{inviter.global_name || inviter.username} invited you to {guildName}
|
||||
{t("betterInvites.ui.invitedYouTo", { inviter: inviter.global_name || inviter.username, guild: guildName })}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { MessageStore } from "@webpack/common";
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterPlusReacts",
|
||||
authors: [Devs.Joona],
|
||||
description: "The amount of plus before :emoji: is the message to add it to",
|
||||
description: t("betterPlusReacts.description"),
|
||||
patches: [
|
||||
{
|
||||
find: ".SLASH_COMMAND_USED,",
|
||||
|
|
|
|||
|
|
@ -6,42 +6,43 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
removeNameplate: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove nameplate styling.",
|
||||
description: t("betterUserArea.settings.removeNameplate"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeAudioMenus: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove menus next to mute and deafen buttons.",
|
||||
description: t("betterUserArea.settings.removeAudioMenus"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
alwaysShowUsername: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Always show username instead of status.",
|
||||
description: t("betterUserArea.settings.alwaysShowUsername"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeButtonTooltips: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove button tooltips.",
|
||||
description: t("betterUserArea.settings.removeButtonTooltips"),
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeAvatarDecoration: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove avatar decoration.",
|
||||
description: t("betterUserArea.settings.removeAvatarDecoration"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeUsernameStyles: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove username colors and effects.",
|
||||
description: t("betterUserArea.settings.removeUsernameStyles"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
|
|
@ -49,7 +50,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "BetterUserArea",
|
||||
description: "Customize and make the user area more clean.",
|
||||
description: t("betterUserArea.description"),
|
||||
authors: [Devs.prism],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
|
||||
|
|
@ -14,24 +15,24 @@ let blockedKeywords: Array<RegExp>;
|
|||
const settings = definePluginSettings({
|
||||
blockedWords: {
|
||||
type: OptionType.STRING,
|
||||
description: "Comma-seperated list of words to block",
|
||||
description: t("blockKeywords.settings.blockedWords"),
|
||||
default: "",
|
||||
restartNeeded: true
|
||||
},
|
||||
useRegex: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Use each value as a regular expression when checking message content (advanced)",
|
||||
description: t("blockKeywords.settings.useRegex"),
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
caseSensitive: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Whether to use a case sensitive search or not",
|
||||
description: t("blockKeywords.settings.caseSensitive"),
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
ignoreBlockedMessages: {
|
||||
description: "Completely ignores (recent) new messages bar",
|
||||
description: t("blockKeywords.settings.ignoreBlockedMessages"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
restartNeeded: true,
|
||||
|
|
@ -69,7 +70,7 @@ export function containsBlockedKeywords(message: Message) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "BlockKeywords",
|
||||
description: "Blocks messages containing specific user-defined keywords, as if the user sending them was blocked.",
|
||||
description: t("blockKeywords.description"),
|
||||
authors: [EquicordDevs.catcraft],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "BlockKrisp",
|
||||
description: "Prevent Krisp from loading",
|
||||
description: t("blockKrisp.description"),
|
||||
authors: [Devs.D3SOX],
|
||||
patches: [
|
||||
// Block loading modules on Desktop
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "BypassPinPrompt",
|
||||
description: "Bypass the pin prompt when using the pin functions",
|
||||
description: t("bypassPinPrompt.description"),
|
||||
authors: [Devs.thororen],
|
||||
patches: [
|
||||
...[
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { Devs } from "@utils/constants";
|
||||
import { getCurrentChannel } from "@utils/discord";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import type { Message } from "@vencord/discord-types";
|
||||
import { ChannelActionCreators, ChannelStore, Menu, MessageStore, NavigationRouter, PresenceStore, UserStore, WindowStore } from "@webpack/common";
|
||||
|
|
@ -79,7 +80,7 @@ function ContextCallback(name: "guild" | "user" | "channel"): NavContextMenuPatc
|
|||
<Menu.MenuGroup>
|
||||
<Menu.MenuItem
|
||||
id={`status-${name}-bypass`}
|
||||
label={`${enabled ? "Remove" : "Add"} Status Bypass`}
|
||||
label={enabled ? t("bypassStatus.contextMenu.removeStatusBypass") : t("bypassStatus.contextMenu.addStatusBypass")}
|
||||
icon={() => Icon(enabled)}
|
||||
action={() => {
|
||||
let bypasses: string[] = settings.store[`${name}s`].split(", ");
|
||||
|
|
@ -96,58 +97,58 @@ function ContextCallback(name: "guild" | "user" | "channel"): NavContextMenuPatc
|
|||
const settings = definePluginSettings({
|
||||
guilds: {
|
||||
type: OptionType.STRING,
|
||||
description: "Guilds to let bypass (notified when pinged anywhere in guild)",
|
||||
description: t("bypassStatus.settings.guilds"),
|
||||
default: "",
|
||||
placeholder: "Separate with commas",
|
||||
placeholder: t("bypassStatus.placeholder.separateWithCommas"),
|
||||
onChange: value => settings.store.guilds = processIds(value)
|
||||
},
|
||||
channels: {
|
||||
type: OptionType.STRING,
|
||||
description: "Channels to let bypass (notified when pinged in that channel)",
|
||||
description: t("bypassStatus.settings.channels"),
|
||||
default: "",
|
||||
placeholder: "Separate with commas",
|
||||
placeholder: t("bypassStatus.placeholder.separateWithCommas"),
|
||||
onChange: value => settings.store.channels = processIds(value)
|
||||
},
|
||||
users: {
|
||||
type: OptionType.STRING,
|
||||
description: "Users to let bypass (notified for all messages sent in DMs)",
|
||||
description: t("bypassStatus.settings.users"),
|
||||
default: "",
|
||||
placeholder: "Separate with commas",
|
||||
placeholder: t("bypassStatus.placeholder.separateWithCommas"),
|
||||
onChange: value => settings.store.users = processIds(value)
|
||||
},
|
||||
allowOutsideOfDms: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Allow selected users to bypass status outside of DMs too (acts like a channel/guild bypass, but it's for all messages sent by the selected users)"
|
||||
description: t("bypassStatus.settings.allowOutsideOfDms")
|
||||
},
|
||||
notificationSound: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Whether the notification sound should be played",
|
||||
description: t("bypassStatus.settings.notificationSound"),
|
||||
default: true,
|
||||
},
|
||||
respectSilentPings: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Respect silent pings (@silent / suppress notifications)",
|
||||
description: t("bypassStatus.settings.respectSilentPings"),
|
||||
default: true
|
||||
},
|
||||
statusToUse: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Status to use for whitelist",
|
||||
description: t("bypassStatus.settings.statusToUse"),
|
||||
options: [
|
||||
{
|
||||
label: "Online",
|
||||
label: t("bypassStatus.statusOptions.online"),
|
||||
value: "online",
|
||||
},
|
||||
{
|
||||
label: "Idle",
|
||||
label: t("bypassStatus.statusOptions.idle"),
|
||||
value: "idle",
|
||||
},
|
||||
{
|
||||
label: "Do Not Disturb",
|
||||
label: t("bypassStatus.statusOptions.dnd"),
|
||||
value: "dnd",
|
||||
default: true
|
||||
},
|
||||
{
|
||||
label: "Invisible",
|
||||
label: t("bypassStatus.statusOptions.invisible"),
|
||||
value: "invisible",
|
||||
}
|
||||
]
|
||||
|
|
@ -156,7 +157,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "BypassStatus",
|
||||
description: "Still get notifications from specific sources when in do not disturb mode. Right-click on users/channels/guilds to set them to bypass do not disturb mode.",
|
||||
description: t("bypassStatus.description"),
|
||||
authors: [Devs.Inbestigator],
|
||||
dependencies: ["AudioPlayerAPI"],
|
||||
flux: {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import "./style.css";
|
||||
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Channel } from "@vencord/discord-types";
|
||||
import { GuildStore, React, SelectedGuildStore } from "@webpack/common";
|
||||
|
|
@ -31,7 +32,7 @@ function renderBadge(id: number, title: string) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "ChannelBadges",
|
||||
description: "Adds badges to channels based on their type",
|
||||
description: t("channelBadges.description"),
|
||||
authors: [EquicordDevs.creations, Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
@ -64,9 +65,9 @@ export default definePlugin({
|
|||
const guild = selectedGuildId ? GuildStore.getGuild(selectedGuildId) : null;
|
||||
|
||||
const badgeConditions = [
|
||||
{ id: 6101, condition: isPrivate, title: "This channel is locked." },
|
||||
{ id: 6100, condition: isNSFW, title: "This channel is marked as NSFW." },
|
||||
{ id: 6102, condition: guild?.rulesChannelId === channel.id, title: "This channel is the server rules channel." },
|
||||
{ id: 6101, condition: isPrivate, title: t("channelBadges.tooltips.lockedChannel") },
|
||||
{ id: 6100, condition: isNSFW, title: t("channelBadges.tooltips.nsfwChannel") },
|
||||
{ id: 6102, condition: guild?.rulesChannelId === channel.id, title: t("channelBadges.tooltips.rulesChannel") },
|
||||
];
|
||||
|
||||
let badges: JSX.Element[] = [];
|
||||
|
|
|
|||
|
|
@ -5,270 +5,271 @@
|
|||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { t } from "@utils/translation";
|
||||
import { OptionType } from "@utils/types";
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
oneBadgePerChannel: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
description: "Show only one badge per channel",
|
||||
description: t("channelBadges.settings.oneBadgePerChannel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showTextBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Text badge",
|
||||
description: t("channelBadges.settings.showTextBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showVoiceBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Voice badge",
|
||||
description: t("channelBadges.settings.showVoiceBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showCategoryBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Category badge",
|
||||
description: t("channelBadges.settings.showCategoryBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showDirectoryBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Directory badge",
|
||||
description: t("channelBadges.settings.showDirectoryBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showAnnouncementThreadBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Announcement Thread badge",
|
||||
description: t("channelBadges.settings.showAnnouncementThreadBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showPublicThreadBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Public Thread badge",
|
||||
description: t("channelBadges.settings.showPublicThreadBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showPrivateThreadBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Private Thread badge",
|
||||
description: t("channelBadges.settings.showPrivateThreadBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showStageBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Stage badge",
|
||||
description: t("channelBadges.settings.showStageBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showAnnouncementBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Announcement badge",
|
||||
description: t("channelBadges.settings.showAnnouncementBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showForumBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Forum badge",
|
||||
description: t("channelBadges.settings.showForumBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showMediaBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Media badge",
|
||||
description: t("channelBadges.settings.showMediaBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showNSFWBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show NSFW badge",
|
||||
description: t("channelBadges.settings.showNSFWBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showLockedBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Locked badge",
|
||||
description: t("channelBadges.settings.showLockedBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showRulesBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Rules badge",
|
||||
description: t("channelBadges.settings.showRulesBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
showUnknownBadge: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show Unknown badge",
|
||||
description: t("channelBadges.settings.showUnknownBadge"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
|
||||
textBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Text",
|
||||
description: "Text badge label",
|
||||
description: t("channelBadges.settings.textBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
voiceBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Voice",
|
||||
description: "Voice badge label",
|
||||
description: t("channelBadges.settings.voiceBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
categoryBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Category",
|
||||
description: "Category badge label",
|
||||
description: t("channelBadges.settings.categoryBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
announcementBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "News",
|
||||
description: "Announcement badge label",
|
||||
description: t("channelBadges.settings.announcementBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
announcementThreadBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "News Thread",
|
||||
description: "Announcement Thread badge label",
|
||||
description: t("channelBadges.settings.announcementThreadBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
publicThreadBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Thread",
|
||||
description: "Public Thread badge label",
|
||||
description: t("channelBadges.settings.publicThreadBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
privateThreadBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Private Thread",
|
||||
description: "Private Thread badge label",
|
||||
description: t("channelBadges.settings.privateThreadBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
stageBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Stage",
|
||||
description: "Stage badge label",
|
||||
description: t("channelBadges.settings.stageBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
directoryBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Directory",
|
||||
description: "Directory badge label",
|
||||
description: t("channelBadges.settings.directoryBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
forumBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Forum",
|
||||
description: "Forum badge label",
|
||||
description: t("channelBadges.settings.forumBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
mediaBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Media",
|
||||
description: "Media badge label",
|
||||
description: t("channelBadges.settings.mediaBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
nsfwBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "NSFW",
|
||||
description: "NSFW badge label",
|
||||
description: t("channelBadges.settings.nsfwBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
lockedBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Locked",
|
||||
description: "Locked badge label",
|
||||
description: t("channelBadges.settings.lockedBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
rulesBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Rules",
|
||||
description: "Rules badge label",
|
||||
description: t("channelBadges.settings.rulesBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
unknownBadgeLabel: {
|
||||
type: OptionType.STRING,
|
||||
default: "Unknown",
|
||||
description: "Unknown badge label",
|
||||
description: t("channelBadges.settings.unknownBadgeLabel"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
|
||||
textBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Text badge color",
|
||||
description: t("channelBadges.settings.textBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
voiceBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Voice badge color",
|
||||
description: t("channelBadges.settings.voiceBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
categoryBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Category badge color",
|
||||
description: t("channelBadges.settings.categoryBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
announcementBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Announcement badge color",
|
||||
description: t("channelBadges.settings.announcementBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
announcementThreadBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Announcement Thread badge color",
|
||||
description: t("channelBadges.settings.announcementThreadBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
publicThreadBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Public Thread badge color",
|
||||
description: t("channelBadges.settings.publicThreadBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
privateThreadBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Private Thread badge color",
|
||||
description: t("channelBadges.settings.privateThreadBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
stageBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Stage badge color",
|
||||
description: t("channelBadges.settings.stageBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
directoryBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Directory badge color",
|
||||
description: t("channelBadges.settings.directoryBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
forumBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Forum badge color",
|
||||
description: t("channelBadges.settings.forumBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
mediaBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Media badge color",
|
||||
description: t("channelBadges.settings.mediaBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
nsfwBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "NSFW badge color",
|
||||
description: t("channelBadges.settings.nsfwBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
lockedBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Locked badge color",
|
||||
description: t("channelBadges.settings.lockedBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
rulesBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Rules badge color",
|
||||
description: t("channelBadges.settings.rulesBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
unknownBadgeColor: {
|
||||
type: OptionType.STRING,
|
||||
description: "Unknown badge color",
|
||||
description: t("channelBadges.settings.unknownBadgeColor"),
|
||||
restartNeeded: true,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import "./style.css";
|
|||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Channel, Message } from "@vencord/discord-types";
|
||||
import { ChannelStore, Menu } from "@webpack/common";
|
||||
|
|
@ -23,7 +24,7 @@ const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channe
|
|||
|
||||
const menuItem = (
|
||||
<Menu.MenuItem
|
||||
label="Open in New Tab"
|
||||
label={t("channelTabs.contextMenu.openInNewTab")}
|
||||
id="open-link-in-tab"
|
||||
action={() => createTab({
|
||||
guildId: channel.guild_id || "@me", // Normalize for DMs/Group Chats
|
||||
|
|
@ -46,7 +47,7 @@ const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channe
|
|||
|
||||
export default definePlugin({
|
||||
name: "ChannelTabs",
|
||||
description: "Group your commonly visited channels in tabs, like a browser",
|
||||
description: t("channelTabs.description"),
|
||||
authors: [Devs.TheSun, Devs.TheKodeToad, EquicordDevs.keifufu, Devs.Nickyux, EquicordDevs.DiabeloDEV, EquicordDevs.justjxke],
|
||||
dependencies: ["ContextMenuAPI"],
|
||||
contextMenus: {
|
||||
|
|
|
|||
|
|
@ -8,20 +8,21 @@ import "./style.css";
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { UserStore } from "@webpack/common";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
colorEffects: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Turn on or off color effects for getting close to the character limit",
|
||||
description: t("characterCounter.settings.colorEffects"),
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "CharacterCounter",
|
||||
description: "Adds a character counter to the chat input",
|
||||
description: t("characterCounter.description"),
|
||||
authors: [EquicordDevs.creations, EquicordDevs.Panniku, Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Channel } from "@vencord/discord-types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "CleanChannelName",
|
||||
authors: [Devs.AutumnVN],
|
||||
description: "remove all emoji and decor shit from channel names",
|
||||
description: t("cleanChannelName.description"),
|
||||
patches: [
|
||||
{
|
||||
find: "loadAllGuildAndPrivateChannelsFromDisk(){",
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
*/
|
||||
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "CleanerChannelGroups",
|
||||
description: "Hides all channels in collapsed categories, even if they have unread messages.",
|
||||
description: t("cleanerChannelGroups.description"),
|
||||
authors: [EquicordDevs.justjxke],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { GuildMember } from "@vencord/discord-types";
|
||||
import { ChannelStore, GuildMemberStore, GuildRoleStore, React, RelationshipStore, UserStore } from "@webpack/common";
|
||||
|
|
@ -14,52 +15,52 @@ import { ChannelStore, GuildMemberStore, GuildRoleStore, React, RelationshipStor
|
|||
const settings = definePluginSettings({
|
||||
hideVc: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hide voice channels containing blocked users.",
|
||||
description: t("clientSideBlock.settings.hideVc"),
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
usersToBlock: {
|
||||
type: OptionType.STRING,
|
||||
description: "User IDs seperated by a comma and a space",
|
||||
description: t("clientSideBlock.settings.usersToBlock"),
|
||||
restartNeeded: true,
|
||||
default: ""
|
||||
},
|
||||
hideBlockedUsers: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Should blocked users should also be hidden everywhere",
|
||||
description: t("clientSideBlock.settings.hideBlockedUsers"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
hideBlockedMessages: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Should messages from blocked users should be hidden fully (same as the old noblockedmessages plugin)",
|
||||
description: t("clientSideBlock.settings.hideBlockedMessages"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
hideEmptyRoles: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Should role headers be hidden if all of their members are blocked",
|
||||
description: t("clientSideBlock.settings.hideEmptyRoles"),
|
||||
restartNeeded: true,
|
||||
default: true
|
||||
},
|
||||
blockedReplyDisplay: {
|
||||
type: OptionType.SELECT,
|
||||
description: "What should display instead of the message when someone replies to someone you have hidden",
|
||||
description: t("clientSideBlock.settings.blockedReplyDisplay"),
|
||||
restartNeeded: true,
|
||||
options: [
|
||||
{ value: "displayText", label: "Display text saying a hidden message was replied to", default: true },
|
||||
{ value: "hideReply", label: "Literally nothing" }
|
||||
{ value: "displayText", label: t("clientSideBlock.settings.blockedReplyDisplayOptions.displayText"), default: true },
|
||||
{ value: "hideReply", label: t("clientSideBlock.settings.blockedReplyDisplayOptions.hideReply") }
|
||||
]
|
||||
},
|
||||
guildBlackList: {
|
||||
type: OptionType.STRING,
|
||||
description: "Guild ids to disable functionality in",
|
||||
description: t("clientSideBlock.settings.guildBlackList"),
|
||||
restartNeeded: true,
|
||||
default: ""
|
||||
},
|
||||
guildWhiteList: {
|
||||
type: OptionType.STRING,
|
||||
description: "Guild ids to enable functionality in",
|
||||
description: t("clientSideBlock.settings.guildWhiteList"),
|
||||
restartNeeded: true,
|
||||
default: ""
|
||||
}
|
||||
|
|
@ -100,7 +101,7 @@ function hiddenReplyComponent() {
|
|||
case "displayText":
|
||||
return <Paragraph style={{ marginTop: "0px", marginBottom: "0px" }}>
|
||||
<i>
|
||||
↓ Replying to blocked message
|
||||
↓ {t("clientSideBlock.reply.replyingToBlocked")}
|
||||
</i>
|
||||
</Paragraph>;
|
||||
case "hideReply":
|
||||
|
|
@ -141,7 +142,7 @@ function activeNowView(cards) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "ClientSideBlock",
|
||||
description: "Allows you to locally hide almost all content from any user",
|
||||
description: t("clientSideBlock.description"),
|
||||
tags: ["blocked", "block", "hide", "hidden", "noblockedmessages"],
|
||||
authors: [Devs.Samwich, EquicordDevs.KamiRu],
|
||||
settings,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
|||
import { Button } from "@components/Button";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { getIntlMessage } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Activity } from "@vencord/discord-types";
|
||||
import { PresenceStore, SettingsRouter, UserStore } from "@webpack/common";
|
||||
|
|
@ -18,34 +19,34 @@ const extraFramerates = [45, 90, 120, 144, 165, 240];
|
|||
const settings = definePluginSettings({
|
||||
richPresenceTagging: {
|
||||
type: OptionType.SELECT,
|
||||
description: "When should clips be tagged with the current Rich Presence?",
|
||||
description: t("clipsEnhancements.settings.richPresenceTagging"),
|
||||
options: [
|
||||
{ label: "Always", value: "always" },
|
||||
{ label: "Only when beginning or end of activity name matches", value: "whenMatched", default: true },
|
||||
{ label: "Never", value: "never" },
|
||||
{ label: t("clipsEnhancements.settings.richPresenceTaggingOptions.always"), value: "always" },
|
||||
{ label: t("clipsEnhancements.settings.richPresenceTaggingOptions.whenMatched"), value: "whenMatched", default: true },
|
||||
{ label: t("clipsEnhancements.settings.richPresenceTaggingOptions.never"), value: "never" },
|
||||
]
|
||||
},
|
||||
enableScreenshotKeybind: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable the screenshot keybind feature",
|
||||
description: t("clipsEnhancements.settings.enableScreenshotKeybind"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
enableVoiceOnlyClips: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable voice-only clips (audio without video)",
|
||||
description: t("clipsEnhancements.settings.enableVoiceOnlyClips"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
enableAdvancedSignals: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable advanced clip signals (auto-clip triggers)",
|
||||
description: t("clipsEnhancements.settings.enableAdvancedSignals"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
ignorePlatformRestriction: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Allow Platform Restricted Clipping (may cause save errors)",
|
||||
description: t("clipsEnhancements.settings.ignorePlatformRestriction"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
|
|
@ -60,7 +61,7 @@ const settings = definePluginSettings({
|
|||
SettingsRouter.openUserSettings("clips_panel");
|
||||
}}
|
||||
>
|
||||
Change FPS and duration options in Clips settings!
|
||||
{t("clipsEnhancements.settings.clipsLink")}
|
||||
</Button >
|
||||
</>
|
||||
);
|
||||
|
|
@ -71,7 +72,7 @@ const settings = definePluginSettings({
|
|||
migratePluginSettings("ClipsEnhancements", "TimelessClips");
|
||||
export default definePlugin({
|
||||
name: "ClipsEnhancements",
|
||||
description: "Add more Clip FPS and duration options, custom clip length, RPC tagging and more",
|
||||
description: t("clipsEnhancements.description"),
|
||||
authors: [Devs.niko, Devs.Joona, EquicordDevs.keircn],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { BaseText } from "@components/BaseText";
|
||||
import { Button } from "@components/Button";
|
||||
import { EquicordDevs, IS_MAC } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { useEffect, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -92,9 +93,9 @@ function KeybindRecorder() {
|
|||
return (
|
||||
<div className="vc-command-palette-keybind-input">
|
||||
<div className="vc-command-palette-keybind-info">
|
||||
<BaseText size="md" weight="semibold">Command Palette Hotkey</BaseText>
|
||||
<BaseText size="md" weight="semibold">{t("commandPalette.ui.hotkeyTitle")}</BaseText>
|
||||
<BaseText size="sm" weight="normal" style={{ color: "var(--text-muted)" }}>
|
||||
Hotkey used to open the command palette
|
||||
{t("commandPalette.ui.hotkeyDescription")}
|
||||
</BaseText>
|
||||
{error && (
|
||||
<BaseText size="xs" weight="normal" className="vc-command-palette-keybind-conflict">
|
||||
|
|
@ -111,14 +112,14 @@ function KeybindRecorder() {
|
|||
>
|
||||
{isListening ? (
|
||||
<BaseText size="sm" weight="normal" style={{ color: "var(--white)", opacity: 0.8 }}>
|
||||
Press any key...
|
||||
{t("commandPalette.ui.pressAnyKey")}
|
||||
</BaseText>
|
||||
) : (
|
||||
formatKeybind(currentKeybind)
|
||||
)}
|
||||
</Button>
|
||||
<Button size="small" variant="secondary" onClick={handleReset}>
|
||||
Reset
|
||||
{t("commandPalette.ui.reset")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -127,31 +128,31 @@ function KeybindRecorder() {
|
|||
|
||||
export const settings = definePluginSettings({
|
||||
hotkey: {
|
||||
description: "Hotkey used to open the command palette",
|
||||
description: t("commandPalette.settings.hotkey"),
|
||||
type: OptionType.COMPONENT,
|
||||
default: DEFAULT_KEYS,
|
||||
component: KeybindRecorder
|
||||
},
|
||||
visualStyle: {
|
||||
description: "Palette appearance",
|
||||
description: t("commandPalette.settings.visualStyle"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "Classic", value: "classic", default: true },
|
||||
{ label: "Polished", value: "polished" }
|
||||
{ label: t("commandPalette.settings.visualStyleOptions.classic"), value: "classic", default: true },
|
||||
{ label: t("commandPalette.settings.visualStyleOptions.polished"), value: "polished" }
|
||||
]
|
||||
},
|
||||
showTags: {
|
||||
description: "Display tag chips for commands",
|
||||
description: t("commandPalette.settings.showTags"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
},
|
||||
enableTagFilter: {
|
||||
description: "Show the tag filter bar",
|
||||
description: t("commandPalette.settings.enableTagFilter"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
},
|
||||
customCommands: {
|
||||
description: "Manage custom command palette entries",
|
||||
description: t("commandPalette.settings.customCommands"),
|
||||
type: OptionType.COMPONENT,
|
||||
component: CommandPaletteSettingsPanel
|
||||
}
|
||||
|
|
@ -223,7 +224,7 @@ function hotkeyUsesModifiers() {
|
|||
|
||||
export default definePlugin({
|
||||
name: "CommandPalette",
|
||||
description: "Quickly run actions through a searchable command palette",
|
||||
description: t("commandPalette.description"),
|
||||
authors: [EquicordDevs.justjxke, EquicordDevs.Ethan],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import "./styles.css";
|
|||
import SettingsPlugin from "@plugins/_core/settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { removeFromArray } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { StartAt } from "@utils/types";
|
||||
import { SettingsRouter } from "@webpack/common";
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ function ComponentsIcon(props: React.SVGProps<SVGSVGElement>) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "Components",
|
||||
description: "Adds a new tab to settings to browse Discord components.",
|
||||
description: t("components.description"),
|
||||
authors: [Devs.prism],
|
||||
dependencies: ["Settings"],
|
||||
startAt: StartAt.WebpackReady,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { DeleteIcon } from "@components/Icons";
|
|||
import { EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { useForceUpdater } from "@utils/react";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Button, TextInput, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ function FlaggedInput({ index, forceUpdate }) {
|
|||
return (<Flex flexDirection="row">
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<TextInput
|
||||
placeholder="Word"
|
||||
placeholder={t("contentWarning.ui.placeholder")}
|
||||
spellCheck={false}
|
||||
value={value}
|
||||
onChange={updateValue}
|
||||
|
|
@ -130,7 +131,7 @@ function FlaggedWords() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<HeadingTertiary>Flagged Words</HeadingTertiary>
|
||||
<HeadingTertiary>{t("contentWarning.ui.flaggedWords")}</HeadingTertiary>
|
||||
{inputs}
|
||||
</>
|
||||
);
|
||||
|
|
@ -143,7 +144,7 @@ const settings = definePluginSettings({
|
|||
},
|
||||
onClick: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Only show trigger content on click instead of hover",
|
||||
description: t("contentWarning.settings.onClick"),
|
||||
default: false,
|
||||
}
|
||||
});
|
||||
|
|
@ -151,7 +152,7 @@ const settings = definePluginSettings({
|
|||
export default definePlugin({
|
||||
name: "ContentWarning",
|
||||
authors: [EquicordDevs.camila314],
|
||||
description: "Allows you to specify certain trigger words that will be blurred by default. Hovering/Clicking on the blurred content will reveal it.",
|
||||
description: t("contentWarning.description"),
|
||||
settings,
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Menu, Toasts, UserProfileStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ function copyProfileColors(userId) {
|
|||
if (!colors) {
|
||||
Toasts.show({
|
||||
type: Toasts.Type.FAILURE,
|
||||
message: "No profile colors found!",
|
||||
message: t("copyProfileColors.toast.noColorsFound"),
|
||||
id: Toasts.genId()
|
||||
});
|
||||
return;
|
||||
|
|
@ -49,14 +50,14 @@ function copyProfileColors(userId) {
|
|||
copyToClipboard(formattedColors);
|
||||
Toasts.show({
|
||||
type: Toasts.Type.SUCCESS,
|
||||
message: "Profile colors copied to clipboard!",
|
||||
message: t("copyProfileColors.toast.copied"),
|
||||
id: Toasts.genId()
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to copy to clipboard:", e);
|
||||
Toasts.show({
|
||||
type: Toasts.Type.FAILURE,
|
||||
message: "Error copying profile colors!",
|
||||
message: t("copyProfileColors.toast.error"),
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}
|
||||
|
|
@ -81,7 +82,7 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }) =
|
|||
<Menu.MenuItem
|
||||
id="CopyProfileColors"
|
||||
icon={ColorIcon}
|
||||
label="Copy Profile Colors"
|
||||
label={t("copyProfileColors.contextMenu.copyProfileColors")}
|
||||
action={() => copyProfileColors(user.id)}
|
||||
/>
|
||||
);
|
||||
|
|
@ -89,7 +90,7 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }) =
|
|||
|
||||
export default definePlugin({
|
||||
name: "CopyProfileColors",
|
||||
description: "A plugin to copy people's profile gradient colors to clipboard.",
|
||||
description: t("copyProfileColors.description"),
|
||||
authors: [EquicordDevs.Crxa, EquicordDevs.Cortex],
|
||||
contextMenus: {
|
||||
"user-context": userContextMenuPatch,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { findByCodeLazy } from "@webpack";
|
||||
|
|
@ -22,7 +23,7 @@ const getMetadataFromApi: (activity: any, userId: string) => Promise<any> = find
|
|||
|
||||
export default definePlugin({
|
||||
name: "CopyStatusUrls",
|
||||
description: "Copy the users status url when you right-click it",
|
||||
description: t("copyStatusUrls.description"),
|
||||
authors: [Devs.sadan],
|
||||
|
||||
patches: [
|
||||
|
|
@ -45,7 +46,7 @@ export default definePlugin({
|
|||
copyToClipboard(button_urls[index]);
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Copied URL",
|
||||
message: t("copyStatusUrls.toast.copied"),
|
||||
type: Toasts.Type.SUCCESS,
|
||||
options: {
|
||||
position: Toasts.Position.TOP
|
||||
|
|
@ -55,7 +56,7 @@ export default definePlugin({
|
|||
console.error(e);
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Error copying URL, check console for more info",
|
||||
message: t("copyStatusUrls.toast.error"),
|
||||
type: Toasts.Type.FAILURE,
|
||||
options: {
|
||||
position: Toasts.Position.TOP
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import type { Channel, User } from "@vencord/discord-types";
|
||||
import { Menu } from "@webpack/common";
|
||||
|
|
@ -37,7 +38,7 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: U
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-copy-user-mention"
|
||||
label="Copy User Mention"
|
||||
label={t("copyUserMention.contextMenu.copyUserMention")}
|
||||
action={() => copyToClipboard(`<@${user.id}>`)}
|
||||
icon={MentionIcon}
|
||||
/>
|
||||
|
|
@ -47,7 +48,7 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: U
|
|||
export default definePlugin({
|
||||
name: "CopyUserMention",
|
||||
authors: [EquicordDevs.Cortex, Devs.castdrian],
|
||||
description: "Adds a button to copy user's mention on the user context menu, works best with ValidUser.",
|
||||
description: t("copyUserMention.description"),
|
||||
contextMenus: {
|
||||
"user-context": UserContextMenuPatch
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { Divider } from "@components/Divider";
|
|||
import { Heading } from "@components/Heading";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { ColorPicker } from "@webpack/common";
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ function OnekoColorSettings() {
|
|||
<div>
|
||||
<div className={cl("color-modal")}>
|
||||
<div>
|
||||
<Heading className="form-subtitle">Fur Color</Heading>
|
||||
<Heading className="form-subtitle">{t("cursorBuddy.ui.furColor")}</Heading>
|
||||
<div className={cl("color")}>
|
||||
<ColorPicker
|
||||
color={parseHexToNumber(furColor) ?? 16777215}
|
||||
|
|
@ -65,7 +66,7 @@ function OnekoColorSettings() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<Heading className="form-subtitle">Outline Color</Heading>
|
||||
<Heading className="form-subtitle">{t("cursorBuddy.ui.outlineColor")}</Heading>
|
||||
<div className={cl("color")}>
|
||||
<ColorPicker
|
||||
color={parseHexToNumber(outlineColor) ?? 0}
|
||||
|
|
@ -81,30 +82,30 @@ function OnekoColorSettings() {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
buddy: {
|
||||
description: "Pick a cursor buddy",
|
||||
description: t("cursorBuddy.settings.buddy"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{
|
||||
label: "Oneko",
|
||||
label: t("cursorBuddy.settings.buddyOptions.oneko"),
|
||||
value: "oneko",
|
||||
default: true
|
||||
},
|
||||
{
|
||||
label: "Fatass Horse",
|
||||
label: t("cursorBuddy.settings.buddyOptions.fathorse"),
|
||||
value: "fathorse"
|
||||
}
|
||||
],
|
||||
onChange: load,
|
||||
},
|
||||
speed: {
|
||||
description: "Speed of your buddy",
|
||||
description: t("cursorBuddy.settings.speed"),
|
||||
type: OptionType.NUMBER,
|
||||
default: 10,
|
||||
isValid: (value: number) => value >= 0 || "Speed must be bigger than 0",
|
||||
onChange: load,
|
||||
},
|
||||
fps: {
|
||||
description: "Framerate of your buddy",
|
||||
description: t("cursorBuddy.settings.fps"),
|
||||
type: OptionType.NUMBER,
|
||||
default: 24,
|
||||
isValid: (value: number) => value > 0 || "Framerate must be bigger than 0",
|
||||
|
|
@ -125,14 +126,14 @@ const settings = definePluginSettings({
|
|||
component: OnekoColorSettings,
|
||||
},
|
||||
furColor: {
|
||||
description: "Fur hex color for Oneko",
|
||||
description: t("cursorBuddy.settings.furColor"),
|
||||
type: OptionType.STRING,
|
||||
default: "#FFFFFF",
|
||||
onChange: load,
|
||||
hidden: true,
|
||||
},
|
||||
outlineColor: {
|
||||
description: "Outline hex color for Oneko",
|
||||
description: t("cursorBuddy.settings.outlineColor"),
|
||||
type: OptionType.STRING,
|
||||
default: "#000000",
|
||||
onChange: load,
|
||||
|
|
@ -149,26 +150,26 @@ const settings = definePluginSettings({
|
|||
),
|
||||
},
|
||||
size: {
|
||||
description: "Size of the fatass horse",
|
||||
description: t("cursorBuddy.settings.size"),
|
||||
type: OptionType.NUMBER,
|
||||
default: 120,
|
||||
isValid: (value: number) => value > 0 || "Size must be bigger than 0",
|
||||
onChange: load
|
||||
},
|
||||
fade: {
|
||||
description: "If the horse should fade when the cursor is near",
|
||||
description: t("cursorBuddy.settings.fade"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
onChange: load
|
||||
},
|
||||
freeroam: {
|
||||
description: "If the horse should roam freely when idle",
|
||||
description: t("cursorBuddy.settings.freeroam"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
onChange: load
|
||||
},
|
||||
shake: {
|
||||
description: "If the horse should shake the window when it's walking",
|
||||
description: t("cursorBuddy.settings.shake"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
onChange: load,
|
||||
|
|
@ -192,7 +193,7 @@ const settings = definePluginSettings({
|
|||
disabled() { return this.store.buddy !== "fathorse"; },
|
||||
},
|
||||
shake: {
|
||||
disabled() { return this.store.buddy !== "fathorse"; },
|
||||
disabled() { return this.store.buddy !== "fathorse"; }
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -234,7 +235,7 @@ function load() {
|
|||
migratePluginSettings("CursorBuddy", "Oneko", "oneko");
|
||||
export default definePlugin({
|
||||
name: "CursorBuddy",
|
||||
description: "Adds a sprite that follows your cursor.",
|
||||
description: t("cursorBuddy.description"),
|
||||
authors: [Devs.Ven, Devs.adryd, EquicordDevs.nexpid, EquicordDevs.ZcraftElite],
|
||||
tags: ["Oneko", "FatassHorse", "Pet"],
|
||||
settings,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { makeContextItem } from "./components";
|
||||
|
|
@ -13,7 +14,7 @@ import { folderProp, int2rgba } from "./util";
|
|||
|
||||
export default definePlugin({
|
||||
name: "CustomFolderIcons",
|
||||
description: "Customize folder icons with any png",
|
||||
description: t("customFolderIcons.description"),
|
||||
authors: [EquicordDevs.sadan],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { Heading } from "@components/Heading";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
||||
import { Button, React, showToast, TextInput } from "@webpack/common";
|
||||
|
||||
|
|
@ -245,7 +246,7 @@ const settings = definePluginSettings({
|
|||
});
|
||||
dataUriCache.clear();
|
||||
setResetTrigger(prev => prev + 1);
|
||||
showToast("All overrides reset successfully!");
|
||||
showToast(t("customSounds.toast.resetSuccess"));
|
||||
};
|
||||
|
||||
const triggerFileUpload = () => {
|
||||
|
|
@ -277,10 +278,10 @@ const settings = definePluginSettings({
|
|||
}
|
||||
|
||||
setResetTrigger(prev => prev + 1);
|
||||
showToast("Settings imported successfully!");
|
||||
showToast(t("customSounds.toast.importSuccess"));
|
||||
} catch (error) {
|
||||
console.error("Error importing settings:", error);
|
||||
showToast("Error importing settings. Check console for details.");
|
||||
showToast(t("customSounds.toast.importError"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -314,7 +315,7 @@ const settings = definePluginSettings({
|
|||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
showToast(`Exported ${overrides.length} settings (audio files not included)`);
|
||||
showToast(t("customSounds.toast.exportSuccess", { count: overrides.length }));
|
||||
};
|
||||
|
||||
const filteredSoundTypes = allSoundTypes.filter(type =>
|
||||
|
|
@ -325,10 +326,10 @@ const settings = definePluginSettings({
|
|||
return (
|
||||
<div>
|
||||
<div className="vc-custom-sounds-buttons">
|
||||
<Button color={Button.Colors.BRAND} onClick={triggerFileUpload}>Import</Button>
|
||||
<Button color={Button.Colors.PRIMARY} onClick={downloadSettings}>Export</Button>
|
||||
<Button color={Button.Colors.RED} onClick={resetOverrides}>Reset All</Button>
|
||||
<Button color={Button.Colors.WHITE} onClick={debugCustomSounds}>Debug</Button>
|
||||
<Button color={Button.Colors.BRAND} onClick={triggerFileUpload}>{t("customSounds.settings.import")}</Button>
|
||||
<Button color={Button.Colors.PRIMARY} onClick={downloadSettings}>{t("customSounds.settings.export")}</Button>
|
||||
<Button color={Button.Colors.RED} onClick={resetOverrides}>{t("customSounds.settings.resetAll")}</Button>
|
||||
<Button color={Button.Colors.WHITE} onClick={debugCustomSounds}>{t("customSounds.settings.debug")}</Button>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
|
|
@ -339,11 +340,11 @@ const settings = definePluginSettings({
|
|||
</div>
|
||||
|
||||
<div className={cl("search")}>
|
||||
<Heading>Search Sounds</Heading>
|
||||
<Heading>{t("customSounds.settings.searchSounds")}</Heading>
|
||||
<TextInput
|
||||
value={searchQuery}
|
||||
onChange={e => setSearchQuery(e)}
|
||||
placeholder="Search by name or ID"
|
||||
placeholder={t("customSounds.settings.searchPlaceholder")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -365,7 +366,7 @@ const settings = definePluginSettings({
|
|||
await ensureDataURICached(currentOverride.selectedFileId);
|
||||
} catch (error) {
|
||||
console.error(`[CustomSounds] Failed to cache data URI for ${type.id}:`, error);
|
||||
showToast("Error loading custom sound file");
|
||||
showToast(t("customSounds.toast.loadError"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +393,7 @@ export function findOverride(id: string): SoundOverride | null {
|
|||
|
||||
export default definePlugin({
|
||||
name: "CustomSounds",
|
||||
description: "Customize Discord's sounds.",
|
||||
description: t("customSounds.description"),
|
||||
authors: [Devs.ScattrdBlade, Devs.TheKodeToad],
|
||||
settings,
|
||||
startAt: StartAt.Init,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { Paragraph } from "@components/Paragraph";
|
|||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { useForceUpdater } from "@utils/react";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { moment, TextInput, useEffect, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ const TimeRow = (props: TimeRowProps) => {
|
|||
const settings = definePluginSettings({
|
||||
formats: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Customize the timestamp formats",
|
||||
description: t("customTimestamps.settings.formats"),
|
||||
component: componentProps => {
|
||||
const [settingsState, setSettingsState] = useState(useSettings().plugins?.CustomTimestamps?.formats ?? {});
|
||||
|
||||
|
|
@ -92,9 +93,9 @@ const settings = definePluginSettings({
|
|||
{key === "sameDayFormat" && (
|
||||
<div className={Margins.bottom20}>
|
||||
<Divider style={{ marginBottom: "10px" }} />
|
||||
<Heading tag="h1">Calendar formats</Heading>
|
||||
<Heading tag="h1">{t("customTimestamps.settings.calendarFormats")}</Heading>
|
||||
<Paragraph>
|
||||
How to format the [calendar] value if used in the above timestamps.
|
||||
{t("customTimestamps.settings.calendarFormatsDescription")}
|
||||
</Paragraph>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -124,19 +125,18 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "CustomTimestamps",
|
||||
description: "Custom timestamps on messages and tooltips",
|
||||
description: t("customTimestamps.description"),
|
||||
authors: [Devs.Rini, EquicordDevs.nvhhr, EquicordDevs.Suffocate, Devs.Obsidian],
|
||||
settings,
|
||||
settingsAboutComponent: () => (
|
||||
<div className={"vc-cmt-info-card"}>
|
||||
<HeadingPrimary>How to use:</HeadingPrimary>
|
||||
<HeadingPrimary>{t("customTimestamps.about.title")}</HeadingPrimary>
|
||||
<Paragraph>
|
||||
<Link href="https://momentjs.com/docs/#/displaying/format/">Moment.js formatting documentation</Link>
|
||||
<div className={Margins.top8}>
|
||||
Additionally you can use these in your inputs:<br />
|
||||
<b>[calendar]</b> enables dynamic date formatting such
|
||||
as "Today" or "Yesterday".<br />
|
||||
<b>[relative]</b> gives you times such as "4 hours ago".<br />
|
||||
{t("customTimestamps.about.additional")}<br />
|
||||
<b>[calendar]</b> {t("customTimestamps.about.calendar")}<br />
|
||||
<b>[relative]</b> {t("customTimestamps.about.relative")}<br />
|
||||
</div>
|
||||
</Paragraph>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { get } from "@api/DataStore";
|
|||
import { definePluginSettings, Settings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { openModal } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Channel, User } from "@vencord/discord-types";
|
||||
import { extractAndLoadChunksLazy } from "@webpack";
|
||||
|
|
@ -46,7 +47,7 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: {
|
|||
|
||||
const setCustomColorItem = (
|
||||
<Menu.MenuItem
|
||||
label="Set Color"
|
||||
label={t("customUserColors.contextMenu.setColor")}
|
||||
id="set-color"
|
||||
icon={ColorIcon}
|
||||
action={async () => {
|
||||
|
|
@ -64,7 +65,7 @@ const channelContextMenuPatch: NavContextMenuPatchCallback = (children, { channe
|
|||
|
||||
const setCustomColorItem = (
|
||||
<Menu.MenuItem
|
||||
label="Set Color"
|
||||
label={t("customUserColors.contextMenu.setColor")}
|
||||
id="set-color"
|
||||
icon={ColorIcon}
|
||||
action={async () => {
|
||||
|
|
@ -87,19 +88,19 @@ export function getCustomColorString(id: string | undefined, withHash?: boolean)
|
|||
const settings = definePluginSettings({
|
||||
dmList: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Users with custom colors defined will have their name in the dm list colored",
|
||||
description: t("customUserColors.settings.dmList"),
|
||||
default: true,
|
||||
},
|
||||
colorInServers: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "If name colors should be changed within servers",
|
||||
description: t("customUserColors.settings.colorInServers"),
|
||||
default: true,
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "CustomUserColors",
|
||||
description: "Lets you add a custom color to any user, anywhere! Highly recommend to use with typingTweaks and roleColorEverywhere",
|
||||
description: t("customUserColors.description"),
|
||||
authors: [EquicordDevs.mochienya],
|
||||
contextMenus: {
|
||||
"user-context": userContextMenuPatch,
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "DisableCameras",
|
||||
description: "Disables cameras in a call by default",
|
||||
description: t("disableCameras.description"),
|
||||
authors: [Devs.Joona],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@
|
|||
import "./styles.css";
|
||||
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { makeDevBanner, settings } from "./components";
|
||||
|
||||
export default definePlugin({
|
||||
name: "DiscordDevBanner",
|
||||
description: "Enables the Discord developer banner, in which displays the build-ID",
|
||||
description: t("discordDevBanner.description"),
|
||||
authors: [EquicordDevs.KrystalSkull, Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -1,26 +1,15 @@
|
|||
/*
|
||||
* Vencord, a modification for Discord's desktop app
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2026 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { classes } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findByPropsLazy, findCssClassesLazy } from "@webpack";
|
||||
import { useDrag, useDrop, useLayoutEffect, useRef, UserSettingsActionCreators } from "@webpack/common";
|
||||
|
|
@ -44,7 +33,7 @@ type EmojiDescriptor = {
|
|||
export default definePlugin({
|
||||
name: "DragFavoriteEmotes",
|
||||
authors: [EquicordDevs.PWall],
|
||||
description: "Adds the ability to change the order of your favourite emotes",
|
||||
description: t("dragFavoriteEmotes.description"),
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::EMOJI_FAVORITE_TOOLTIP}",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { EquicordDevs } from "@utils/constants";
|
||||
import { getGuildAcronym, insertTextIntoChatInputBox } from "@utils/discord";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import type { Channel } from "@vencord/discord-types";
|
||||
import { ChannelType } from "@vencord/discord-types/enums";
|
||||
|
|
@ -74,61 +75,61 @@ function shouldIgnoreDrop(key: string): boolean {
|
|||
const settings = definePluginSettings({
|
||||
userOutput: {
|
||||
type: OptionType.SELECT,
|
||||
description: "User drop output.",
|
||||
description: t("dragify.settings.userOutput"),
|
||||
options: [
|
||||
{ label: "Mention user", value: "mention", default: true },
|
||||
{ label: "User ID", value: "id" },
|
||||
{ label: t("dragify.settings.userOutputOptions.mention"), value: "mention", default: true },
|
||||
{ label: t("dragify.settings.userOutputOptions.id"), value: "id" },
|
||||
],
|
||||
},
|
||||
channelOutput: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Channel drop output.",
|
||||
description: t("dragify.settings.channelOutput"),
|
||||
options: [
|
||||
{ label: "#channel mention", value: "mention", default: true },
|
||||
{ label: "Channel link", value: "link" },
|
||||
{ label: t("dragify.settings.channelOutputOptions.mention"), value: "mention", default: true },
|
||||
{ label: t("dragify.settings.channelOutputOptions.link"), value: "link" },
|
||||
],
|
||||
},
|
||||
inviteExpireAfter: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Invite expiration.",
|
||||
description: t("dragify.settings.inviteExpireAfter"),
|
||||
options: [
|
||||
{ label: "30 minutes", value: 1800 },
|
||||
{ label: "1 hour", value: 3600 },
|
||||
{ label: "6 hours", value: 21600 },
|
||||
{ label: "12 hours", value: 43200 },
|
||||
{ label: "1 day", value: 86400 },
|
||||
{ label: "7 days", value: 604800 },
|
||||
{ label: "Never", value: 0, default: true },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.30min"), value: 1800 },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.1hour"), value: 3600 },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.6hours"), value: 21600 },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.12hours"), value: 43200 },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.1day"), value: 86400 },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.7days"), value: 604800 },
|
||||
{ label: t("dragify.settings.inviteExpireAfterOptions.never"), value: 0, default: true },
|
||||
],
|
||||
},
|
||||
inviteMaxUses: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Invite max uses.",
|
||||
description: t("dragify.settings.inviteMaxUses"),
|
||||
options: [
|
||||
{ label: "No limit", value: 0, default: true },
|
||||
{ label: "1 use", value: 1 },
|
||||
{ label: "5 uses", value: 5 },
|
||||
{ label: "10 uses", value: 10 },
|
||||
{ label: "25 uses", value: 25 },
|
||||
{ label: "50 uses", value: 50 },
|
||||
{ label: "100 uses", value: 100 },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.noLimit"), value: 0, default: true },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.1use"), value: 1 },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.5uses"), value: 5 },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.10uses"), value: 10 },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.25uses"), value: 25 },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.50uses"), value: 50 },
|
||||
{ label: t("dragify.settings.inviteMaxUsesOptions.100uses"), value: 100 },
|
||||
],
|
||||
},
|
||||
inviteTemporaryMembership: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
description: "Grant temporary membership.",
|
||||
description: t("dragify.settings.inviteTemporaryMembership"),
|
||||
},
|
||||
reuseExistingInvites: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
description: "Reuse existing invite instead of creating a new one.",
|
||||
description: t("dragify.settings.reuseExistingInvites"),
|
||||
},
|
||||
allowChatBodyDrop: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
restartNeeded: true,
|
||||
description: "Allow dropping into the main chat body to insert text.",
|
||||
description: t("dragify.settings.allowChatBodyDrop"),
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -159,7 +160,7 @@ const inviteCache = new Map<string, { code: string; expiresAt: number | null; ma
|
|||
|
||||
export default definePlugin({
|
||||
name: "Dragify",
|
||||
description: "Drop users, channels, or servers into chat to insert mentions or invites.",
|
||||
description: t("dragify.description"),
|
||||
authors: [EquicordDevs.justjxke],
|
||||
settings,
|
||||
|
||||
|
|
@ -340,7 +341,7 @@ export default definePlugin({
|
|||
clearDragState();
|
||||
} catch (error) {
|
||||
logger.error("Failed handling drop", error);
|
||||
showToast("Dragify failed to handle drop.", Toasts.Type.FAILURE);
|
||||
showToast(t("dragify.toast.dropFailed"), Toasts.Type.FAILURE);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -385,11 +386,11 @@ export default definePlugin({
|
|||
|
||||
const inviteChannelId = inviteChannel?.id ?? fallbackChannelId;
|
||||
if (!inviteChannelId) {
|
||||
showToast("No channel available for invites.", Toasts.Type.FAILURE);
|
||||
showToast(t("dragify.toast.noChannelForInvites"), Toasts.Type.FAILURE);
|
||||
return null;
|
||||
}
|
||||
if (inviteChannel && inviteChannel.guild_id !== guildId) {
|
||||
showToast("No channel available for invites.", Toasts.Type.FAILURE);
|
||||
showToast(t("dragify.toast.noChannelForInvites"), Toasts.Type.FAILURE);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -413,11 +414,11 @@ export default definePlugin({
|
|||
maxUses: maxUses === 0 ? null : maxUses,
|
||||
uses: 0,
|
||||
});
|
||||
showToast("Invite created.", Toasts.Type.SUCCESS);
|
||||
showToast(t("dragify.toast.inviteCreated"), Toasts.Type.SUCCESS);
|
||||
return `https://discord.gg/${code}`;
|
||||
} catch (error) {
|
||||
logger.error("Failed to create invite", error);
|
||||
showToast("Unable to create invite.", Toasts.Type.FAILURE); // uh oh!
|
||||
showToast(t("dragify.toast.inviteFailed"), Toasts.Type.FAILURE); // uh oh!
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { Button } from "@components/Button";
|
|||
import { Devs, IS_MAC } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { copyWithToast } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
import { useEffect, useState } from "@webpack/common";
|
||||
|
|
@ -79,14 +80,14 @@ function KeybindRecorder() {
|
|||
className={cl("keybind-button", isListening ? "listening" : "")}
|
||||
onClick={() => setIsListening(true)}
|
||||
>
|
||||
{isListening ? "Recording..." : <KeybindShortcut shortcut={currentKeybind.join("+")} />}
|
||||
{isListening ? t("elementHighlighter.ui.recording") : <KeybindShortcut shortcut={currentKeybind.join("+")} />}
|
||||
</button>
|
||||
<Button
|
||||
size="small"
|
||||
variant="secondary"
|
||||
onClick={() => { settings.store.keybind = DEFAULT_KEYBIND; }}
|
||||
>
|
||||
Reset
|
||||
{t("elementHighlighter.ui.reset")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -94,48 +95,48 @@ function KeybindRecorder() {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
keybind: {
|
||||
description: "Toggle Highlighter",
|
||||
description: t("elementHighlighter.settings.keybind"),
|
||||
type: OptionType.COMPONENT,
|
||||
default: DEFAULT_KEYBIND,
|
||||
component: KeybindRecorder
|
||||
},
|
||||
showClasses: {
|
||||
description: "Display the element's CSS class names in the tooltip",
|
||||
description: t("elementHighlighter.settings.showClasses"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showId: {
|
||||
description: "Display the element's ID attribute in the tooltip",
|
||||
description: t("elementHighlighter.settings.showId"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showFont: {
|
||||
description: "Display the computed font family and font size",
|
||||
description: t("elementHighlighter.settings.showFont"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showPadding: {
|
||||
description: "Display the element's padding values",
|
||||
description: t("elementHighlighter.settings.showPadding"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showMargin: {
|
||||
description: "Display the element's margin values",
|
||||
description: t("elementHighlighter.settings.showMargin"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showBorderRadius: {
|
||||
description: "Display the element's border-radius values",
|
||||
description: t("elementHighlighter.settings.showBorderRadius"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showPosition: {
|
||||
description: "Display the element's CSS position type and z-index",
|
||||
description: t("elementHighlighter.settings.showPosition"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
},
|
||||
showDisplay: {
|
||||
description: "Display the element's display type along with flex or grid properties",
|
||||
description: t("elementHighlighter.settings.showDisplay"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false
|
||||
}
|
||||
|
|
@ -354,7 +355,7 @@ function onClick(e: MouseEvent) {
|
|||
if (!el || el === overlay || el === tooltip) return;
|
||||
|
||||
const colorVar = getColorVar(el);
|
||||
if (colorVar) copyWithToast(colorVar, "Copied color to clipboard!");
|
||||
if (colorVar) copyWithToast(colorVar, t("elementHighlighter.ui.copiedColor"));
|
||||
}
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
|
|
@ -448,7 +449,7 @@ function onToggle(e: KeyboardEvent) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "ElementHighlighter",
|
||||
description: "Highlight and inspect elements easily.",
|
||||
description: t("elementHighlighter.description"),
|
||||
authors: [Devs.prism],
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import customRPC from "@plugins/customRPC";
|
||||
import { Devs, EquicordDevs, GUILD_ID, SUPPORT_CHANNEL_ID, SUPPORT_CHANNEL_IDS, VC_SUPPORT_CHANNEL_IDS } from "@utils/constants";
|
||||
import { isAnyPluginDev } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { StandingState } from "@vencord/discord-types/enums";
|
||||
import { findByCodeLazy, findExportedComponentLazy, findStoreLazy } from "@webpack";
|
||||
|
|
@ -28,11 +29,11 @@ const WarningIcon = findExportedComponentLazy("WarningIcon");
|
|||
const ShieldIcon = findExportedComponentLazy("ShieldIcon");
|
||||
|
||||
const StandingConfig: Record<number, { label: string; hoverColor: string; Icon: ComponentType<any>; }> = {
|
||||
[StandingState.ALL_GOOD]: { label: "All good!", hoverColor: "var(--status-positive)", Icon: ShieldIcon },
|
||||
[StandingState.LIMITED]: { label: "Limited", hoverColor: "var(--status-warning)", Icon: WarningIcon },
|
||||
[StandingState.VERY_LIMITED]: { label: "Very limited", hoverColor: "var(--orange-345)", Icon: WarningIcon },
|
||||
[StandingState.AT_RISK]: { label: "At risk", hoverColor: "var(--status-danger)", Icon: WarningIcon },
|
||||
[StandingState.SUSPENDED]: { label: "Suspended", hoverColor: "var(--interactive-muted)", Icon: WarningIcon },
|
||||
[StandingState.ALL_GOOD]: { label: t("equicordHelper.standing.allGood"), hoverColor: "var(--status-positive)", Icon: ShieldIcon },
|
||||
[StandingState.LIMITED]: { label: t("equicordHelper.standing.limited"), hoverColor: "var(--status-warning)", Icon: WarningIcon },
|
||||
[StandingState.VERY_LIMITED]: { label: t("equicordHelper.standing.veryLimited"), hoverColor: "var(--orange-345)", Icon: WarningIcon },
|
||||
[StandingState.AT_RISK]: { label: t("equicordHelper.standing.atRisk"), hoverColor: "var(--status-danger)", Icon: WarningIcon },
|
||||
[StandingState.SUSPENDED]: { label: t("equicordHelper.standing.suspended"), hoverColor: "var(--interactive-muted)", Icon: WarningIcon },
|
||||
};
|
||||
|
||||
function StandingButton() {
|
||||
|
|
@ -61,42 +62,42 @@ function StandingButton() {
|
|||
const settings = definePluginSettings({
|
||||
noMirroredCamera: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Prevents the camera from being mirrored on your screen",
|
||||
description: t("equicordHelper.settings.noMirroredCamera"),
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
removeActivitySection: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Removes the activity section above member list",
|
||||
description: t("equicordHelper.settings.removeActivitySection"),
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
showYourOwnActivityButtons: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Discord hides your own activity buttons for some reason",
|
||||
description: t("equicordHelper.settings.showYourOwnActivityButtons"),
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
noDefaultHangStatus: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Disable the default hang status when joining voice channels",
|
||||
description: t("equicordHelper.settings.noDefaultHangStatus"),
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
refreshSlashCommands: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Refreshes Slash Commands to show newly added commands without restarting your client.",
|
||||
description: t("equicordHelper.settings.refreshSlashCommands"),
|
||||
default: false,
|
||||
},
|
||||
forceRoleIcon: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Forces role icons to display next to messages in compact mode",
|
||||
description: t("equicordHelper.settings.forceRoleIcon"),
|
||||
restartNeeded: true,
|
||||
default: false
|
||||
},
|
||||
accountStandingButton: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show an account standing button in the header bar",
|
||||
description: t("equicordHelper.settings.accountStandingButton"),
|
||||
default: false,
|
||||
restartNeeded: true,
|
||||
}
|
||||
|
|
@ -104,7 +105,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "EquicordHelper",
|
||||
description: "Used to provide support, fix discord caused crashes, and other misc features.",
|
||||
description: t("equicordHelper.description"),
|
||||
authors: [Devs.thororen, EquicordDevs.nyx, EquicordDevs.Naibuu, EquicordDevs.keircn, EquicordDevs.SerStars, EquicordDevs.mart],
|
||||
required: true,
|
||||
settings,
|
||||
|
|
@ -218,13 +219,13 @@ export default definePlugin({
|
|||
if (!selfId || isAnyPluginDev(selfId)) return;
|
||||
if (VC_SUPPORT_CHANNEL_IDS.includes(channelId) && !clicked) {
|
||||
return Alerts.show({
|
||||
title: "Vencord Support Channel Warning",
|
||||
body: "Before asking for help. Check updates and if this issue is actually caused by Equicord!",
|
||||
confirmText: "Equicord Support",
|
||||
title: t("equicordHelper.alerts.supportWarningTitle"),
|
||||
body: t("equicordHelper.alerts.supportWarningBody"),
|
||||
confirmText: t("equicordHelper.alerts.equicordSupport"),
|
||||
onConfirm() {
|
||||
NavigationRouter.transitionTo(`/channels/${GUILD_ID}/${SUPPORT_CHANNEL_ID}`);
|
||||
},
|
||||
cancelText: "Okay continue",
|
||||
cancelText: t("equicordHelper.alerts.okayContinue"),
|
||||
onCancel() {
|
||||
clicked = true;
|
||||
},
|
||||
|
|
@ -235,17 +236,17 @@ export default definePlugin({
|
|||
commands: [
|
||||
{
|
||||
name: "refresh-commands",
|
||||
description: "Refresh Slash Commands",
|
||||
description: t("equicordHelper.commands.refreshCommands"),
|
||||
inputType: ApplicationCommandInputType.BUILT_IN,
|
||||
predicate: () => settings.store.refreshSlashCommands,
|
||||
execute: async (opts, ctx) => {
|
||||
try {
|
||||
ApplicationCommandIndexStore.indices = {};
|
||||
sendBotMessage(ctx.channel.id, { content: "Slash Commands refreshed successfully." });
|
||||
sendBotMessage(ctx.channel.id, { content: t("equicordHelper.commands.refreshSuccess") });
|
||||
}
|
||||
catch (e) {
|
||||
console.error("[refreshSlashCommands] Failed to refresh commands:", e);
|
||||
sendBotMessage(ctx.channel.id, { content: "Failed to refresh commands. Check console for details." });
|
||||
sendBotMessage(ctx.channel.id, { content: t("equicordHelper.commands.refreshFailed") });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import "./styles.css";
|
|||
import { HeaderBarButton } from "@api/HeaderBar";
|
||||
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Popout, useRef, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ export const settings = definePluginSettings({
|
|||
showPluginMenu: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show the plugins menu in the toolbox",
|
||||
description: t("equicordToolbox.settings.showPluginMenu"),
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ function VencordPopoutButton() {
|
|||
ref={buttonRef}
|
||||
className="vc-toolbox-btn"
|
||||
onClick={() => setShow(v => !v)}
|
||||
tooltip={isShown ? null : "Equicord Toolbox"}
|
||||
tooltip={isShown ? null : t("equicordToolbox.ui.tooltip")}
|
||||
icon={Icon}
|
||||
selected={isShown}
|
||||
/>
|
||||
|
|
@ -76,7 +77,7 @@ function VencordPopoutButton() {
|
|||
migratePluginSettings("EquicordToolbox", "VencordToolbox");
|
||||
export default definePlugin({
|
||||
name: "EquicordToolbox",
|
||||
description: "Adds a button next to the inbox button in the channel header that houses Equicord quick actions",
|
||||
description: t("equicordToolbox.description"),
|
||||
authors: [Devs.Ven, Devs.AutumnVN],
|
||||
dependencies: ["HeaderBarAPI"],
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { Settings, useSettings } from "@api/Settings";
|
|||
import { openPluginModal, openSettingsTabModal, PluginsTab, ThemesTab } from "@components/settings";
|
||||
import { useAwaiter } from "@utils/react";
|
||||
import { wordsFromCamel, wordsToTitle } from "@utils/text";
|
||||
import { t } from "@utils/translation";
|
||||
import { OptionType, Plugin } from "@utils/types";
|
||||
import { Menu, showToast, useMemo, useState } from "@webpack/common";
|
||||
import type { ReactNode } from "react";
|
||||
|
|
@ -27,7 +28,7 @@ function buildPluginMenu() {
|
|||
return (
|
||||
<Menu.MenuItem
|
||||
id="plugins"
|
||||
label="Plugins"
|
||||
label={t("equicordToolbox.ui.plugins")}
|
||||
action={() => openSettingsTabModal(PluginsTab)}
|
||||
>
|
||||
{pluginEntries}
|
||||
|
|
@ -103,7 +104,7 @@ export function buildPluginMenuEntries(includeEmpty = false) {
|
|||
checked={s[key]}
|
||||
action={() => {
|
||||
s[key] = !s[key];
|
||||
if (option.restartNeeded) showToast("Restart to apply the change");
|
||||
if (option.restartNeeded) showToast(t("equicordToolbox.ui.restartToApply"));
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
@ -120,7 +121,7 @@ export function buildPluginMenuEntries(includeEmpty = false) {
|
|||
checked={s[key] === opt.value}
|
||||
action={() => {
|
||||
s[key] = opt.value;
|
||||
if (option.restartNeeded) showToast("Restart to apply the change");
|
||||
if (option.restartNeeded) showToast(t("equicordToolbox.ui.restartToApply"));
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
|
@ -188,7 +189,7 @@ export function buildThemeMenu() {
|
|||
return (
|
||||
<Menu.MenuItem
|
||||
id="themes"
|
||||
label="Themes"
|
||||
label={t("equicordToolbox.ui.themes")}
|
||||
action={() => openSettingsTabModal(ThemesTab)}
|
||||
>
|
||||
{buildThemeMenuEntries()}
|
||||
|
|
@ -205,19 +206,19 @@ export function buildThemeMenuEntries() {
|
|||
<Menu.MenuCheckboxItem
|
||||
id="toggle-quickcss"
|
||||
checked={useQuickCss}
|
||||
label={"Enable QuickCSS"}
|
||||
label={t("equicordToolbox.ui.enableQuickCss")}
|
||||
action={() => {
|
||||
Settings.useQuickCss = !useQuickCss;
|
||||
}}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
id="edit-quickcss"
|
||||
label="Edit QuickCSS"
|
||||
label={t("equicordToolbox.ui.editQuickCss")}
|
||||
action={() => VencordNative.quickCss.openEditor()}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
id="manage-themes"
|
||||
label="Manage Themes"
|
||||
label={t("equicordToolbox.ui.manageThemes")}
|
||||
action={() => openSettingsTabModal(ThemesTab)}
|
||||
/>
|
||||
{!!themes?.length && (
|
||||
|
|
@ -304,7 +305,7 @@ export function renderPopout(onClose: () => void) {
|
|||
>
|
||||
<Menu.MenuItem
|
||||
id="notifications"
|
||||
label="Open Notification Log"
|
||||
label={t("equicordToolbox.ui.openNotificationLog")}
|
||||
action={openNotificationLogModal}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { AudioPlayerInterface, createAudioPlayer } from "@api/AudioPlayer";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
let clickCount = 0;
|
||||
|
|
@ -25,14 +26,14 @@ function play() {
|
|||
const settings = definePluginSettings({
|
||||
amount: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "amount of clicks to trigger crossant",
|
||||
description: t("equissant.settings.amount"),
|
||||
default: 10,
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "Equissant",
|
||||
description: "Crossant every specified amount of clicks :trolley:",
|
||||
description: t("equissant.description"),
|
||||
authors: [EquicordDevs.SomeAspy, Devs.thororen],
|
||||
dependencies: ["AudioPlayerAPI"],
|
||||
settings,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { Button } from "@components/Button";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
import { ChannelActions, Constants, GuildStore, IconUtils, MediaEngineStore, Menu, RestAPI, SearchableSelect, SelectedChannelStore, TextInput, Toasts } from "@webpack/common";
|
||||
|
|
@ -31,7 +32,7 @@ function GuildSelector() {
|
|||
<SearchableSelect
|
||||
options={options}
|
||||
value={options.find(o => o.value === soundGuildId)}
|
||||
placeholder="Select a server..."
|
||||
placeholder={t("exitSounds.ui.selectServer")}
|
||||
maxVisibleItems={6}
|
||||
closeOnSelect={true}
|
||||
onChange={v => settings.store.soundGuildId = v}
|
||||
|
|
@ -58,7 +59,7 @@ function SoundIdInput() {
|
|||
<TextInput
|
||||
value={soundId}
|
||||
onChange={v => settings.store.soundId = v}
|
||||
placeholder="Enter sound ID..."
|
||||
placeholder={t("exitSounds.ui.enterSoundId")}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
|
|
@ -74,12 +75,12 @@ function SoundIdInput() {
|
|||
const settings = definePluginSettings({
|
||||
soundGuildId: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Select the server containing the sound.",
|
||||
description: t("exitSounds.settings.soundGuildId"),
|
||||
component: GuildSelector
|
||||
},
|
||||
soundId: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Enter the ID of the sound you want to play.",
|
||||
description: t("exitSounds.settings.soundId"),
|
||||
component: SoundIdInput
|
||||
}
|
||||
});
|
||||
|
|
@ -89,7 +90,7 @@ const SoundButtonContext: NavContextMenuPatchCallback = (children, { sound }: {
|
|||
<Menu.MenuGroup>
|
||||
<Menu.MenuItem
|
||||
id="set-global-exit-sound"
|
||||
label="Set as global exit sound"
|
||||
label={t("exitSounds.ui.setGlobalExitSound")}
|
||||
action={() => {
|
||||
settings.store.soundGuildId = sound.guildId;
|
||||
settings.store.soundId = sound.soundId;
|
||||
|
|
@ -103,7 +104,7 @@ let original: typeof ChannelActions.selectVoiceChannel;
|
|||
|
||||
export default definePlugin({
|
||||
name: "ExitSounds",
|
||||
description: "Play soundboard sounds when you disconnect from voice.",
|
||||
description: t("exitSounds.description"),
|
||||
authors: [Devs.prism],
|
||||
dependencies: ["AudioPlayerAPI"],
|
||||
settings,
|
||||
|
|
@ -130,7 +131,7 @@ export default definePlugin({
|
|||
await new Promise(r => setTimeout(r, 500));
|
||||
} catch {
|
||||
Toasts.show({
|
||||
message: "Oops! Something went wrong.",
|
||||
message: t("exitSounds.toasts.somethingWentWrong"),
|
||||
id: Toasts.genId(),
|
||||
type: Toasts.Type.FAILURE
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
|||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { showItemInFolder } from "@utils/native";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { saveFile } from "@utils/web";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
|
|
@ -22,12 +23,12 @@ import { ContactsList } from "./types";
|
|||
const settings = definePluginSettings({
|
||||
openFileAfterExport: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Open the exported file in the default file handler after export",
|
||||
description: t("exportMessages.settings.openFileAfterExport"),
|
||||
default: true
|
||||
},
|
||||
exportContacts: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Export a list of friends to your clipboard. Adds a new button to the menu bar for the friends tab.",
|
||||
description: t("exportMessages.settings.exportContacts"),
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
|
@ -81,14 +82,14 @@ async function exportMessage(message: Message) {
|
|||
}
|
||||
|
||||
showNotification({
|
||||
title: "Export Messages",
|
||||
body: `Message exported successfully as ${filename}`,
|
||||
title: t("exportMessages.notifications.title"),
|
||||
body: t("exportMessages.notifications.exportSuccess", { filename }),
|
||||
icon: "📄"
|
||||
});
|
||||
} catch (error) {
|
||||
showNotification({
|
||||
title: "Export Messages",
|
||||
body: "Failed to export message",
|
||||
title: t("exportMessages.notifications.title"),
|
||||
body: t("exportMessages.notifications.exportFailed"),
|
||||
icon: "❌"
|
||||
});
|
||||
}
|
||||
|
|
@ -102,7 +103,7 @@ const messageContextMenuPatch = (children: Array<React.ReactElement<any> | null>
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="export-message"
|
||||
label="Export Message"
|
||||
label={t("exportMessages.ui.exportMessage")}
|
||||
icon={() => (
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" />
|
||||
|
|
@ -128,7 +129,7 @@ function getUsernames(contacts: ContactsList[], type: number): string[] {
|
|||
|
||||
export default definePlugin({
|
||||
name: "ExportMessages",
|
||||
description: "Allows you to export any message to a file",
|
||||
description: t("exportMessages.description"),
|
||||
authors: [EquicordDevs.veygax, EquicordDevs.dat_insanity],
|
||||
settings,
|
||||
contextMenus: {
|
||||
|
|
@ -165,14 +166,14 @@ export default definePlugin({
|
|||
},
|
||||
addExportButton() {
|
||||
return <ErrorBoundary noop key=".2">
|
||||
<button className="export-contacts-button" onClick={() => { this.copyContactToClipboard(); console.log("clicked"); }}>Export</button>
|
||||
<button className="export-contacts-button" onClick={() => { this.copyContactToClipboard(); console.log("clicked"); }}>{t("exportMessages.ui.export")}</button>
|
||||
</ErrorBoundary>;
|
||||
},
|
||||
copyContactToClipboard() {
|
||||
if (this.contactList) {
|
||||
copyToClipboard(JSON.stringify(this.contactList));
|
||||
Toasts.show({
|
||||
message: "Contacts copied to clipboard successfully.",
|
||||
message: t("exportMessages.ui.contactsCopied"),
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId(),
|
||||
options: {
|
||||
|
|
@ -182,11 +183,8 @@ export default definePlugin({
|
|||
});
|
||||
return;
|
||||
}
|
||||
// reason why you need to click the all tab is because the data is extracted during
|
||||
// the request itself when you fetch all your friends. this is done to avoid sending a
|
||||
// manual request to discord, which may raise suspicion and might even get you terminated.
|
||||
Toasts.show({
|
||||
message: "Contact list is undefined. Click on the \"All\" tab before exporting.",
|
||||
message: t("exportMessages.ui.contactListUndefined"),
|
||||
type: Toasts.Type.FAILURE,
|
||||
id: Toasts.genId(),
|
||||
options: {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Constants, PermissionsBits, PermissionStore, React, RestAPI, useCallback, useEffect, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -49,23 +50,23 @@ function showIcon() {
|
|||
// TY ToggleVideoBind
|
||||
const settings = definePluginSettings({
|
||||
keyBind: {
|
||||
description: "The key to toggle trash when pressed.",
|
||||
description: t("fastDeleteChannels.settings.keyBind"),
|
||||
type: OptionType.STRING,
|
||||
default: "KeyZ",
|
||||
isValid: (value: string) => validKeycodes.includes(value),
|
||||
},
|
||||
reqCtrl: {
|
||||
description: "Require control to be held.",
|
||||
description: t("fastDeleteChannels.settings.reqCtrl"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
},
|
||||
reqShift: {
|
||||
description: "Require shift to be held.",
|
||||
description: t("fastDeleteChannels.settings.reqShift"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
},
|
||||
reqAlt: {
|
||||
description: "Require alt to be held.",
|
||||
description: t("fastDeleteChannels.settings.reqAlt"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
|
|
@ -73,7 +74,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "FastDeleteChannels",
|
||||
description: "Adds a trash icon to delete channels",
|
||||
description: t("fastDeleteChannels.description"),
|
||||
authors: [Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Embed } from "@vencord/discord-types";
|
||||
import { findComponentByCodeLazy, findCssClassesLazy, proxyLazyWebpack } from "@webpack";
|
||||
|
|
@ -44,7 +45,7 @@ const EmbedContext = proxyLazyWebpack(() => React.createContext<null | Embed>(nu
|
|||
|
||||
export default definePlugin({
|
||||
name: "FavouriteAnything",
|
||||
description: "Favourite any image",
|
||||
description: t("favouriteAnything.description"),
|
||||
authors: [Devs.nin0dev, EquicordDevs.davri],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Menu } from "@webpack/common";
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) =
|
|||
|
||||
group.push(
|
||||
<Menu.MenuItem
|
||||
label={`Upload to ${serviceName}`}
|
||||
label={t("fileUpload.ui.uploadTo", { serviceName })}
|
||||
key="file-upload"
|
||||
id="file-upload"
|
||||
action={() => uploadFile(url)}
|
||||
|
|
@ -56,7 +57,7 @@ const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) =>
|
|||
children.push(
|
||||
<Menu.MenuGroup id="file-upload-group">
|
||||
<Menu.MenuItem
|
||||
label={`Upload to ${serviceName}`}
|
||||
label={t("fileUpload.ui.uploadTo", { serviceName })}
|
||||
key="file-upload"
|
||||
id="file-upload"
|
||||
action={() => uploadFile(url)}
|
||||
|
|
@ -67,7 +68,7 @@ const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) =>
|
|||
|
||||
export default definePlugin({
|
||||
name: "FileUpload",
|
||||
description: "Upload images and videos to file hosting services like Zipline and Nest",
|
||||
description: t("fileUpload.description"),
|
||||
authors: [EquicordDevs.creations, EquicordDevs.keircn],
|
||||
settings,
|
||||
contextMenus: {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
|
|
@ -68,19 +69,19 @@ function findReplies(message: Message) {
|
|||
const settings = definePluginSettings({
|
||||
includePings: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Will also search for messages that @ the author directly",
|
||||
description: t("findReply.settings.includePings"),
|
||||
default: false,
|
||||
restartNeeded: false
|
||||
},
|
||||
includeAuthor: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Will also search for messages that reply to the author in general, not just that exact message",
|
||||
description: t("findReply.settings.includeAuthor"),
|
||||
default: false,
|
||||
restartNeeded: false
|
||||
},
|
||||
hideButtonIfNoReply: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hides the button if there are no replies to the message",
|
||||
description: t("findReply.settings.hideButtonIfNoReply"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
|
|
@ -88,7 +89,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "FindReply",
|
||||
description: "Jumps to the earliest reply to a message in a channel (lets you follow past conversations more easily).",
|
||||
description: t("findReply.description"),
|
||||
authors: [Devs.newwares],
|
||||
settings,
|
||||
messagePopoverButton: {
|
||||
|
|
@ -98,7 +99,7 @@ export default definePlugin({
|
|||
const replies = findReplies(message);
|
||||
if (settings.store.hideButtonIfNoReply && !replies.length) return null;
|
||||
return {
|
||||
label: "Jump to Reply",
|
||||
label: t("findReply.ui.jumpToReply"),
|
||||
icon: FindReplyIcon,
|
||||
message,
|
||||
channel: ChannelStore.getChannel(message.channel_id),
|
||||
|
|
@ -115,14 +116,14 @@ export default definePlugin({
|
|||
if (replies.length > 1) {
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Use the bottom panel to navigate between replies.",
|
||||
message: t("findReply.toasts.useBottomPanel"),
|
||||
type: Toasts.Type.MESSAGE
|
||||
});
|
||||
const container = document.querySelector("[class*=channelBottomBarArea_]");
|
||||
if (!container) {
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Couldn't find the container element.",
|
||||
message: t("findReply.toasts.containerNotFound"),
|
||||
type: Toasts.Type.FAILURE
|
||||
});
|
||||
return;
|
||||
|
|
@ -139,7 +140,7 @@ export default definePlugin({
|
|||
} else {
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Couldn't find a reply.",
|
||||
message: t("findReply.toasts.noReplyFound"),
|
||||
type: Toasts.Type.FAILURE
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { isPluginEnabled } from "@api/PluginManager";
|
||||
import anonymiseFileNames, { tarExtMatcher } from "@plugins/anonymiseFileNames";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { ReporterTestable } from "@utils/types";
|
||||
import { CloudUpload } from "@vencord/discord-types";
|
||||
|
||||
|
|
@ -28,7 +29,7 @@ export const reverseExtensionMap = Object.entries(extensionMap).reduce((acc, [ta
|
|||
export default definePlugin({
|
||||
name: "FixFileExtensions",
|
||||
authors: [Devs.thororen],
|
||||
description: "Fixes file extensions by renaming them to a compatible supported format if possible",
|
||||
description: t("fixFileExtensions.description"),
|
||||
reporterTestable: ReporterTestable.None,
|
||||
patches: [
|
||||
// Taken from AnonymiseFileNames
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Notice } from "@components/Notice";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Channel, User, VoiceState } from "@vencord/discord-types";
|
||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
||||
|
|
@ -34,12 +35,12 @@ const settings = definePluginSettings({
|
|||
onlyWhenInVoice: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Only follow the user when you are in a voice channel"
|
||||
description: t("followVoiceUser.settings.onlyWhenInVoice")
|
||||
},
|
||||
leaveWhenUserLeaves: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
description: "Leave the voice channel when the user leaves. (That can cause you to sometimes enter infinite leave/join loop)"
|
||||
description: t("followVoiceUser.settings.leaveWhenUserLeaves")
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { channel,
|
|||
<Menu.MenuSeparator />,
|
||||
<Menu.MenuCheckboxItem
|
||||
id="fvu-follow-user"
|
||||
label="Follow User"
|
||||
label={t("followVoiceUser.ui.followUser")}
|
||||
checked={checked}
|
||||
action={() => {
|
||||
if (followedUserInfo?.userId === user.id) {
|
||||
|
|
@ -73,12 +74,12 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { channel,
|
|||
|
||||
export default definePlugin({
|
||||
name: "FollowVoiceUser",
|
||||
description: "Follow a friend in voice chat.",
|
||||
description: t("followVoiceUser.description"),
|
||||
authors: [EquicordDevs.TheArmagan],
|
||||
settings,
|
||||
settingsAboutComponent: () => (
|
||||
<Notice.Info>
|
||||
This Plugin is used to follow a Friend/Friends into voice chat(s).
|
||||
{t("followVoiceUser.info")}
|
||||
</Notice.Info>
|
||||
),
|
||||
flux: {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { debounce } from "@shared/debounce";
|
|||
import { EquicordDevs } from "@utils/constants";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { React, TextInput } from "@webpack/common";
|
||||
|
||||
|
|
@ -134,13 +135,13 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
|||
|
||||
return (
|
||||
<section>
|
||||
<HeadingSecondary>Search Google Fonts</HeadingSecondary>
|
||||
<Paragraph>Click on any font to apply it.</Paragraph>
|
||||
<HeadingSecondary>{t("fontLoader.ui.searchGoogleFonts")}</HeadingSecondary>
|
||||
<Paragraph>{t("fontLoader.ui.clickToApply")}</Paragraph>
|
||||
|
||||
<TextInput
|
||||
value={query}
|
||||
onChange={e => handleSearch(e)}
|
||||
placeholder="Search fonts..."
|
||||
placeholder={t("fontLoader.ui.searchFonts")}
|
||||
disabled={loading}
|
||||
className={Margins.bottom16}
|
||||
/>
|
||||
|
|
@ -159,7 +160,7 @@ function GoogleFontSearch({ onSelect }: { onSelect: (font: GoogleFontMetadata) =
|
|||
</div>
|
||||
{font.authors?.length && (
|
||||
<Paragraph className={Margins.top8} style={{ opacity: 0.7 }}>
|
||||
by {font.authors.join(", ")}
|
||||
{t("fontLoader.ui.by", { authors: font.authors.join(", ") })}
|
||||
</Paragraph>
|
||||
)}
|
||||
</Card>
|
||||
|
|
@ -192,14 +193,14 @@ const settings = definePluginSettings({
|
|||
},
|
||||
applyOnCodeBlocks: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Apply the font to code blocks",
|
||||
description: t("fontLoader.settings.applyOnCodeBlocks"),
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "FontLoader",
|
||||
description: "Loads any font from Google Fonts",
|
||||
description: t("fontLoader.description"),
|
||||
authors: [EquicordDevs.vmohammad],
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -7,24 +7,25 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { sendMessage } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Channel, Message } from "@vencord/discord-types";
|
||||
|
||||
// Taken From Signature :)
|
||||
const settings = definePluginSettings({
|
||||
forwardPreface: {
|
||||
description: "What should forwarded from be prefaced with",
|
||||
description: t("forwardAnywhere.settings.forwardPreface"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: ">", value: ">", default: true },
|
||||
{ label: "-#", value: "-#" }
|
||||
{ label: t("forwardAnywhere.options.greaterThan"), value: ">", default: true },
|
||||
{ label: t("forwardAnywhere.options.hash"), value: "-#" }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "ForwardAnywhere",
|
||||
description: "If a forward fails send it as a normal message also allows nsfw forwards",
|
||||
description: t("forwardAnywhere.description"),
|
||||
authors: [Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { ChannelStore, UserSettingsActionCreators } from "@webpack/common";
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ function generateSearchResults(query) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "FrequentQuickSwitcher",
|
||||
description: "Rewrites and filters the quick switcher results to be your most frequent channels",
|
||||
description: t("frequentQuickSwitcher.description"),
|
||||
authors: [Devs.Samwich],
|
||||
generateSearchResults: generateSearchResults,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { findStore } from "@webpack";
|
||||
|
|
@ -51,17 +52,17 @@ interface UserPosition {
|
|||
|
||||
export default definePlugin({
|
||||
name: "FriendCloud",
|
||||
description: "Adds a /friendcloud command to visualize the users you most interact with",
|
||||
description: t("friendCloud.description"),
|
||||
authors: [EquicordDevs.Fafa],
|
||||
commands: [
|
||||
{
|
||||
inputType: ApplicationCommandInputType.BUILT_IN,
|
||||
name: "friendcloud",
|
||||
description: "Display user you most interact with in a cloud",
|
||||
description: t("friendCloud.commands.friendcloud"),
|
||||
options: [
|
||||
{
|
||||
name: "count",
|
||||
description: "Number of users to display",
|
||||
description: t("friendCloud.commands.count"),
|
||||
type: ApplicationCommandOptionType.NUMBER,
|
||||
required: false
|
||||
}
|
||||
|
|
@ -69,14 +70,14 @@ export default definePlugin({
|
|||
execute: async (opts, cmdCtx) => {
|
||||
const count = findOption(opts, "count", 25);
|
||||
|
||||
if (!count) return sendBotMessage(cmdCtx.channel.id, { content: "The count must be 1 or higher!" });
|
||||
if (!count) return sendBotMessage(cmdCtx.channel.id, { content: t("friendCloud.errors.countMustBeHigher") });
|
||||
|
||||
try {
|
||||
const affinities: AffinitiesV2[] = findStore("UserAffinitiesV2Store").getUserAffinities();
|
||||
|
||||
if (!affinities?.length) {
|
||||
return sendBotMessage(cmdCtx.channel.id, {
|
||||
content: "No affinities found. Check your [privacy settings](<https://support.discord.com/hc/en-us/articles/21864805694999-Data-Used-to-Improve-Discord>)."
|
||||
content: t("friendCloud.errors.noAffinities")
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +92,7 @@ export default definePlugin({
|
|||
|
||||
if (!users.length) {
|
||||
return sendBotMessage(cmdCtx.channel.id, {
|
||||
content: "No valid users found in affinities. Check your [privacy settings](<https://support.discord.com/hc/en-us/articles/21864805694999-Data-Used-to-Improve-Discord>)."
|
||||
content: t("friendCloud.errors.noValidUsers")
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +154,7 @@ export default definePlugin({
|
|||
if (loadedImages === totalImages) {
|
||||
canvas.toBlob(blob => {
|
||||
if (!blob) {
|
||||
sendBotMessage(cmdCtx.channel.id, { content: "Couldn't generate the image :c" });
|
||||
sendBotMessage(cmdCtx.channel.id, { content: t("friendCloud.errors.couldntGenerate") });
|
||||
return;
|
||||
}
|
||||
const file = new File([blob], "affinities-cloud.png", { type: "image/png" });
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { BaseText } from "@components/BaseText";
|
|||
import { Divider } from "@components/Divider";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { useForceUpdater } from "@utils/react";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Button, ChannelStore, Menu, RelationshipStore, TextInput, useEffect, UserStore, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -99,12 +100,12 @@ function TagConfigCard(props) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<BaseText size="md" tag="h5">Name</BaseText>
|
||||
<BaseText size="md" tag="h5">{t("friendTags.ui.name")}</BaseText>
|
||||
<TextInput value={tagName} onChange={setTagName}></TextInput>
|
||||
<BaseText size="md" tag="h5">Users (Seperated by comma)</BaseText>
|
||||
<BaseText size="md" tag="h5">{t("friendTags.ui.usersSeperated")}</BaseText>
|
||||
<TextInput value={userIds} onChange={setUserIDs}></TextInput>
|
||||
<div className={"vc-friend-tags-user-header-container"}>
|
||||
<BaseText>User List (Click A User To Remove)</BaseText>
|
||||
<BaseText>{t("friendTags.ui.userList")}</BaseText>
|
||||
<div className={"vc-friend-tags-user-header-btns"}>
|
||||
{
|
||||
userIds.split(", ").map(user => {
|
||||
|
|
@ -128,7 +129,7 @@ function TagConfigCard(props) {
|
|||
}}
|
||||
color={Button.Colors.RED}
|
||||
>
|
||||
Remove
|
||||
{t("friendTags.ui.remove")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
|
@ -156,7 +157,7 @@ function TagConfigurationComponent() {
|
|||
});
|
||||
SetData();
|
||||
update();
|
||||
}}>Add</Button>
|
||||
}}>{t("friendTags.ui.add")}</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -187,14 +188,14 @@ const userPatch: NavContextMenuPatchCallback = (children, { user }) => {
|
|||
const buttonElement =
|
||||
<Menu.MenuItem
|
||||
id="vc-tag-group"
|
||||
label="Tag"
|
||||
label={t("friendTags.ui.tag")}
|
||||
>
|
||||
{SavedData.map(tag => {
|
||||
const isTagged = SavedData.filter(e => e.tagName === tag.tagName)[0].userIds.includes(user.id);
|
||||
|
||||
return (
|
||||
<Menu.MenuItem
|
||||
label={`${isTagged ? "Remove from" : "Add to"} ${tag.tagName}`}
|
||||
label={isTagged ? t("friendTags.ui.removeFrom", { tagName: tag.tagName }) : t("friendTags.ui.addTo", { tagName: tag.tagName })}
|
||||
key={`vc-tag-${tag.tagName}`}
|
||||
id={`vc-tag-${tag.tagName}`}
|
||||
action={() => { UserToTagID(user.id, tag.tagName, isTagged); }}
|
||||
|
|
@ -208,7 +209,7 @@ const userPatch: NavContextMenuPatchCallback = (children, { user }) => {
|
|||
|
||||
export default definePlugin({
|
||||
name: "FriendTags",
|
||||
description: "Allows you to filter by custom tags in the quick switcher by starting a search with &",
|
||||
description: t("friendTags.description"),
|
||||
authors: [Devs.Samwich],
|
||||
settings,
|
||||
contextMenus: {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { Paragraph } from "@components/Paragraph";
|
|||
import { Devs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { ModalContent, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Forms, RelationshipStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -40,44 +41,44 @@ function daysSince(dateString: string): number {
|
|||
const ranks: rankInfo[] =
|
||||
[
|
||||
{
|
||||
title: "Sprout",
|
||||
description: "Your friendship is just starting",
|
||||
title: t("friendshipRanks.ranks.sprout.title"),
|
||||
description: t("friendshipRanks.ranks.sprout.description"),
|
||||
requirement: 0,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/sprout.png"
|
||||
},
|
||||
{
|
||||
title: "Blooming",
|
||||
description: "Your friendship is getting there! (1 Month)",
|
||||
title: t("friendshipRanks.ranks.blooming.title"),
|
||||
description: t("friendshipRanks.ranks.blooming.description"),
|
||||
requirement: 30,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/blooming.png"
|
||||
},
|
||||
{
|
||||
title: "Burning",
|
||||
description: "Your friendship has reached terminal velocity (3 Months)",
|
||||
title: t("friendshipRanks.ranks.burning.title"),
|
||||
description: t("friendshipRanks.ranks.burning.description"),
|
||||
requirement: 90,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/burning.png"
|
||||
},
|
||||
{
|
||||
title: "Fighter",
|
||||
description: "Your friendship is strong (6 Months)",
|
||||
title: t("friendshipRanks.ranks.fighter.title"),
|
||||
description: t("friendshipRanks.ranks.fighter.description"),
|
||||
requirement: 182.5,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/fighter.png"
|
||||
},
|
||||
{
|
||||
title: "Star",
|
||||
description: "Your friendship has been going on for a WHILE (1 Year)",
|
||||
title: t("friendshipRanks.ranks.star.title"),
|
||||
description: t("friendshipRanks.ranks.star.description"),
|
||||
requirement: 365,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/star.png"
|
||||
},
|
||||
{
|
||||
title: "Royal",
|
||||
description: "Your friendship has gone through thick and thin- a whole 2 years!",
|
||||
title: t("friendshipRanks.ranks.royal.title"),
|
||||
description: t("friendshipRanks.ranks.royal.description"),
|
||||
requirement: 730,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/royal.png"
|
||||
},
|
||||
{
|
||||
title: "Besties",
|
||||
description: "How do you even manage this??? (5 Years)",
|
||||
title: t("friendshipRanks.ranks.besties.title"),
|
||||
description: t("friendshipRanks.ranks.besties.description"),
|
||||
requirement: 1826.25,
|
||||
iconSrc: "https://equicord.org/assets/plugins/friendshipRanks/besties.png"
|
||||
}
|
||||
|
|
@ -142,7 +143,7 @@ function getBadgesToApply() {
|
|||
|
||||
export default definePlugin({
|
||||
name: "FriendshipRanks",
|
||||
description: "Adds badges showcasing how long you have been friends with a user for",
|
||||
description: t("friendshipRanks.description"),
|
||||
authors: [Devs.Samwich],
|
||||
start() {
|
||||
getBadgesToApply().forEach(b => Badges.addProfileBadge(b));
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { ChannelRTCStore, IconUtils, UserStore, VoiceStateStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -13,7 +14,7 @@ import style from "./style.css?managed";
|
|||
|
||||
export default definePlugin({
|
||||
name: "FullVCPFP",
|
||||
description: "Makes avatars take up the entire vc tile",
|
||||
description: t("fullVcPfp.description"),
|
||||
authors: [EquicordDevs.mochienya],
|
||||
patches: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType, PluginNative, ReporterTestable } from "@utils/types";
|
||||
import { Activity } from "@vencord/discord-types";
|
||||
import { ActivityFlags, ActivityType } from "@vencord/discord-types/enums";
|
||||
|
|
@ -31,7 +32,7 @@ function getImageAsset(data: string) {
|
|||
const settings = definePluginSettings({
|
||||
refreshInterval: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "The interval between activity refreshes (seconds)",
|
||||
description: t("gensokyoRadioRPC.settings.refreshInterval"),
|
||||
markers: [1, 2, 2.5, 3, 5, 10, 15],
|
||||
default: 15,
|
||||
restartNeeded: true,
|
||||
|
|
@ -42,14 +43,14 @@ let updateInterval: NodeJS.Timeout | undefined;
|
|||
|
||||
export default definePlugin({
|
||||
name: "GensokyoRadioRPC",
|
||||
description: "Discord rich presence for Gensokyo Radio!",
|
||||
description: t("gensokyoRadioRPC.description"),
|
||||
authors: [Devs.RyanCaoDev, EquicordDevs.Prince527],
|
||||
reporterTestable: ReporterTestable.None,
|
||||
|
||||
settingsAboutComponent() {
|
||||
return (
|
||||
<Paragraph>
|
||||
Discord rich presence for Gensokyo Radio!
|
||||
{t("gensokyoRadioRPC.info")}
|
||||
</Paragraph>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
|||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { closeModal, openModal } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Channel } from "@vencord/discord-types";
|
||||
import { Menu, Tooltip, useEffect, useState } from "@webpack/common";
|
||||
|
|
@ -26,30 +27,30 @@ export const cl = classNameFactory("vc-boo-");
|
|||
export const settings = definePluginSettings({
|
||||
showIndicator: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show the ghost counter at the top of the server list",
|
||||
description: t("ghosted.settings.showIndicator"),
|
||||
default: true,
|
||||
restartNeeded: false
|
||||
},
|
||||
showDmIcons: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show ghost icons next to individual DMs",
|
||||
description: t("ghosted.settings.showDmIcons"),
|
||||
default: true,
|
||||
restartNeeded: false
|
||||
},
|
||||
ignoreGroupDms: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Exclude all group dms from ghosting",
|
||||
description: t("ghosted.settings.ignoreGroupDms"),
|
||||
default: false
|
||||
},
|
||||
exemptedChannels: {
|
||||
type: OptionType.STRING,
|
||||
description: "Comma-separated list of channel IDs to exempt from ghosting (right-click a DM channel to copy its ID)",
|
||||
description: t("ghosted.settings.exemptedChannels"),
|
||||
default: "",
|
||||
restartNeeded: false
|
||||
},
|
||||
ignoreBots: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Ignore DMs from bots",
|
||||
description: t("ghosted.settings.ignoreBots"),
|
||||
default: true,
|
||||
restartNeeded: false
|
||||
}
|
||||
|
|
@ -88,14 +89,14 @@ function BooIndicator() {
|
|||
const getTooltipText = () => {
|
||||
const ghostedChannels = getGhostedChannels();
|
||||
if (ghostedChannels.length === 0) {
|
||||
return "No Ghosted Users";
|
||||
return t("ghosted.ui.noGhostedUsers");
|
||||
}
|
||||
if (ghostedChannels.length <= 5) {
|
||||
return ghostedChannels
|
||||
.map(id => getChannelDisplayName(id))
|
||||
.join(", ");
|
||||
}
|
||||
return `${ghostedChannels.length} Ghosted Users`;
|
||||
return t("ghosted.ui.ghostedUsers", { count: ghostedChannels.length });
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -125,7 +126,7 @@ function makeContextItem(props) {
|
|||
return <Menu.MenuItem
|
||||
id="ec-ghosted-clear"
|
||||
key="ec-ghosted-clear"
|
||||
label="unghost"
|
||||
label={t("ghosted.ui.unghost")}
|
||||
action={() => {
|
||||
clearChannelFromGhost(props.channel.id);
|
||||
}}
|
||||
|
|
@ -134,7 +135,7 @@ function makeContextItem(props) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "Ghosted",
|
||||
description: "A cute ghost will appear if you don't answer their DMs",
|
||||
description: t("ghosted.description"),
|
||||
authors: [EquicordDevs.vei, Devs.sadan, EquicordDevs.justjxke, EquicordDevs.iamme],
|
||||
settings,
|
||||
dependencies: ["AudioPlayerAPI", "ServerListAPI"],
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { Paragraph } from "@components/Paragraph";
|
|||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Alerts, Button, ContextMenuApi, FluxDispatcher, Menu, React, showToast, TextInput, Toasts, useCallback, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -48,12 +49,12 @@ const addCollectionContextMenuPatch: NavContextMenuPatchCallback = (children, pr
|
|||
if (settings.store.showCopyImageLink) {
|
||||
group.push(
|
||||
<Menu.MenuItem
|
||||
label="Copy Image Link"
|
||||
label={t("gifCollections.ui.copyImageLink")}
|
||||
key="copy-image-link"
|
||||
id="copy-image-link"
|
||||
action={() => {
|
||||
copyToClipboard(gif.url);
|
||||
showToast("Image link copied to clipboard", Toasts.Type.SUCCESS);
|
||||
showToast(t("gifCollections.ui.imageLinkCopied"), Toasts.Type.SUCCESS);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
@ -61,7 +62,7 @@ const addCollectionContextMenuPatch: NavContextMenuPatchCallback = (children, pr
|
|||
|
||||
group.push(
|
||||
<Menu.MenuItem
|
||||
label="Add To Collection"
|
||||
label={t("gifCollections.ui.addToCollection")}
|
||||
key="add-to-collection"
|
||||
id="add-to-collection"
|
||||
>
|
||||
|
|
@ -79,7 +80,7 @@ const addCollectionContextMenuPatch: NavContextMenuPatchCallback = (children, pr
|
|||
<Menu.MenuItem
|
||||
key="create-collection"
|
||||
id="create-collection"
|
||||
label="Create Collection"
|
||||
label={t("gifCollections.ui.createCollection")}
|
||||
action={() => {
|
||||
openModal(modalProps => (
|
||||
<CreateCollectionModal onClose={modalProps.onClose} gif={gif} modalProps={modalProps} />
|
||||
|
|
@ -93,7 +94,7 @@ const addCollectionContextMenuPatch: NavContextMenuPatchCallback = (children, pr
|
|||
|
||||
export const settings = definePluginSettings({
|
||||
itemPrefix: {
|
||||
description: "The prefix for gif items",
|
||||
description: t("gifCollections.settings.itemPrefix"),
|
||||
type: OptionType.STRING,
|
||||
default: "gc-item:",
|
||||
onChange: value => {
|
||||
|
|
@ -106,7 +107,7 @@ export const settings = definePluginSettings({
|
|||
restartNeeded: true
|
||||
},
|
||||
collectionPrefix: {
|
||||
description: "The prefix for collections",
|
||||
description: t("gifCollections.settings.collectionPrefix"),
|
||||
type: OptionType.STRING,
|
||||
default: "gc:",
|
||||
onChange: value => {
|
||||
|
|
@ -119,28 +120,28 @@ export const settings = definePluginSettings({
|
|||
restartNeeded: true
|
||||
},
|
||||
onlyShowCollections: {
|
||||
description: "Only show collections",
|
||||
description: t("gifCollections.settings.onlyShowCollections"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
stopWarnings: {
|
||||
description: "Stop deletion warnings",
|
||||
description: t("gifCollections.settings.stopWarnings"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
showCopyImageLink: {
|
||||
description: "Show 'Copy Image Link' option in context menus",
|
||||
description: t("gifCollections.settings.showCopyImageLink"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
preventDuplicates: {
|
||||
description: "Prevent adding the same GIF to a collection multiple times",
|
||||
description: t("gifCollections.settings.preventDuplicates"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
defaultEmptyCollectionImage: {
|
||||
description: "The image / gif that will be shown when a collection has no images / gifs",
|
||||
description: t("gifCollections.settings.defaultEmptyCollectionImage"),
|
||||
type: OptionType.STRING,
|
||||
default: "https://c.tenor.com/YEG33HsLEaIAAAAC/parksandrec-oops.gif"
|
||||
},
|
||||
|
|
@ -175,14 +176,14 @@ export const settings = definePluginSettings({
|
|||
|
||||
return (
|
||||
<div className="collections-sort-container">
|
||||
<Heading className="collections-sort-title">Sort Collections</Heading>
|
||||
<Heading className="collections-sort-title">{t("gifCollections.ui.sortCollections")}</Heading>
|
||||
<Divider className="collections-sort-divider" />
|
||||
<Paragraph className="collections-sort-description">
|
||||
Choose a sorting criteria for your collections
|
||||
{t("gifCollections.ui.sortCollectionsDescription")}
|
||||
</Paragraph>
|
||||
<Divider className="collections-sort-divider" />
|
||||
<div className="collections-sort-section">
|
||||
<Paragraph className="collections-sort-section-title">Sort By</Paragraph>
|
||||
<Paragraph className="collections-sort-section-title">{t("gifCollections.ui.sortBy")}</Paragraph>
|
||||
<div className="collections-sort-option">
|
||||
<label className="collections-sort-label">
|
||||
<input
|
||||
|
|
@ -193,7 +194,7 @@ export const settings = definePluginSettings({
|
|||
onChange={() => handleSortTypeChange(SortingOptions.NAME)}
|
||||
className="collections-sort-input"
|
||||
/>
|
||||
Name
|
||||
{t("gifCollections.ui.name")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="collections-sort-option">
|
||||
|
|
@ -206,7 +207,7 @@ export const settings = definePluginSettings({
|
|||
onChange={() => handleSortTypeChange(SortingOptions.CREATION_DATE)}
|
||||
className="collections-sort-input"
|
||||
/>
|
||||
Creation Date
|
||||
{t("gifCollections.ui.creationDate")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="collections-sort-option">
|
||||
|
|
@ -219,13 +220,13 @@ export const settings = definePluginSettings({
|
|||
onChange={() => handleSortTypeChange(SortingOptions.MODIFIED_DATE)}
|
||||
className="collections-sort-input"
|
||||
/>
|
||||
Modified Date
|
||||
{t("gifCollections.ui.modifiedDate")}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<Divider className="collections-sort-divider" />
|
||||
<div className="collections-sort-section">
|
||||
<Paragraph className="collections-sort-section-title">Order</Paragraph>
|
||||
<Paragraph className="collections-sort-section-title">{t("gifCollections.ui.order")}</Paragraph>
|
||||
<div className="collections-sort-option">
|
||||
<label className="collections-sort-label">
|
||||
<input
|
||||
|
|
@ -236,7 +237,7 @@ export const settings = definePluginSettings({
|
|||
onChange={() => handleSortOrderChange("asc")}
|
||||
className="collections-sort-input"
|
||||
/>
|
||||
Ascending
|
||||
{t("gifCollections.ui.ascending")}
|
||||
</label>
|
||||
</div>
|
||||
<div className="collections-sort-option">
|
||||
|
|
@ -249,7 +250,7 @@ export const settings = definePluginSettings({
|
|||
onChange={() => handleSortOrderChange("desc")}
|
||||
className="collections-sort-input"
|
||||
/>
|
||||
Descending
|
||||
{t("gifCollections.ui.descending")}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -259,52 +260,52 @@ export const settings = definePluginSettings({
|
|||
},
|
||||
importGifs: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Import Collections",
|
||||
description: t("gifCollections.ui.importCollections"),
|
||||
component: () =>
|
||||
<Button onClick={async () =>
|
||||
(await getCollections()).length ? Alerts.show({
|
||||
title: "Are you sure?",
|
||||
body: "Importing collections will overwrite your current collections.",
|
||||
confirmText: "Import",
|
||||
title: t("gifCollections.ui.areYouSure"),
|
||||
body: t("gifCollections.ui.importOverwrite"),
|
||||
confirmText: t("gifCollections.ui.import"),
|
||||
confirmColor: Button.Colors.RED,
|
||||
cancelText: "Nevermind",
|
||||
cancelText: t("gifCollections.ui.nevermind"),
|
||||
onConfirm: async () => uploadGifCollections()
|
||||
}) : uploadGifCollections()}>
|
||||
Import Collections
|
||||
{t("gifCollections.ui.importCollections")}
|
||||
</Button>,
|
||||
},
|
||||
exportGifs: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Export Collections",
|
||||
description: t("gifCollections.ui.exportCollections"),
|
||||
component: () =>
|
||||
<Button onClick={downloadCollections}>
|
||||
Export Collections
|
||||
{t("gifCollections.ui.exportCollections")}
|
||||
</Button>
|
||||
},
|
||||
resetCollections: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Reset Collections",
|
||||
description: t("gifCollections.ui.resetCollections"),
|
||||
component: () =>
|
||||
<Button onClick={() =>
|
||||
Alerts.show({
|
||||
title: "Are you sure?",
|
||||
body: "Resetting collections will remove all your collections.",
|
||||
confirmText: "Reset",
|
||||
title: t("gifCollections.ui.areYouSure"),
|
||||
body: t("gifCollections.ui.resetRemove"),
|
||||
confirmText: t("gifCollections.ui.reset"),
|
||||
confirmColor: Button.Colors.RED,
|
||||
cancelText: "Nevermind",
|
||||
cancelText: t("gifCollections.ui.nevermind"),
|
||||
onConfirm: async () => {
|
||||
await DataStore.set(DATA_COLLECTION_NAME, []);
|
||||
refreshCacheCollection();
|
||||
}
|
||||
})}>
|
||||
Reset Collections
|
||||
{t("gifCollections.ui.resetCollections")}
|
||||
</Button>
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "GifCollections",
|
||||
description: "Allows you to create collections of gifs",
|
||||
description: t("gifCollections.description"),
|
||||
authors: [Devs.Aria, EquicordDevs.creations],
|
||||
patches: [
|
||||
{
|
||||
|
|
@ -448,7 +449,7 @@ const RemoveItemContextMenu = ({ type, nameOrId, instance }) => (
|
|||
<Menu.MenuItem
|
||||
key="collection-information"
|
||||
id="collection-information"
|
||||
label="Collection Information"
|
||||
label={t("gifCollections.ui.collectionInformation")}
|
||||
action={() => {
|
||||
const collection = cache_collections.find(c => c.name === nameOrId);
|
||||
if (!collection) return;
|
||||
|
|
@ -460,30 +461,30 @@ const RemoveItemContextMenu = ({ type, nameOrId, instance }) => (
|
|||
className="custom-modal"
|
||||
>
|
||||
<ModalHeader separator={false} className="custom-modal-header">
|
||||
<Paragraph className="custom-modal-title">Collection Information</Paragraph>
|
||||
<Paragraph className="custom-modal-title">{t("gifCollections.ui.collectionInformation")}</Paragraph>
|
||||
</ModalHeader>
|
||||
<ModalContent className="custom-modal-content">
|
||||
<section>
|
||||
<Flex className="collection-info">
|
||||
<Heading className="collection-info-title">Name</Heading>
|
||||
<Heading className="collection-info-title">{t("gifCollections.ui.name")}</Heading>
|
||||
<Paragraph className="collection-info-text">{collection.name.replace(/.+?:/, "")}</Paragraph>
|
||||
</Flex>
|
||||
<Flex className="collection-info">
|
||||
<Heading className="collection-info-title">Gifs</Heading>
|
||||
<Heading className="collection-info-title">{t("gifCollections.ui.gifs")}</Heading>
|
||||
<Paragraph className="collection-info-text">{collection.gifs.length}</Paragraph>
|
||||
</Flex>
|
||||
<Flex className="collection-info">
|
||||
<Heading className="collection-info-title">Created At</Heading>
|
||||
<Paragraph className="collection-info-text">{collection.createdAt ? new Date(collection.createdAt).toLocaleString() : "Unknown"}</Paragraph>
|
||||
<Heading className="collection-info-title">{t("gifCollections.ui.createdAt")}</Heading>
|
||||
<Paragraph className="collection-info-text">{collection.createdAt ? new Date(collection.createdAt).toLocaleString() : t("gifCollections.ui.unknown")}</Paragraph>
|
||||
</Flex>
|
||||
<Flex className="collection-info">
|
||||
<Heading className="collection-info-title">Last Updated</Heading>
|
||||
<Paragraph className="collection-info-text">{collection.lastUpdated ? new Date(collection.lastUpdated).toLocaleString() : "Unknown"}</Paragraph>
|
||||
<Heading className="collection-info-title">{t("gifCollections.ui.lastUpdated")}</Heading>
|
||||
<Paragraph className="collection-info-text">{collection.lastUpdated ? new Date(collection.lastUpdated).toLocaleString() : t("gifCollections.ui.unknown")}</Paragraph>
|
||||
</Flex>
|
||||
</section>
|
||||
</ModalContent>
|
||||
<ModalFooter className="custom-modal-footer">
|
||||
<Button onClick={modalProps.onClose} className="custom-modal-button">Close</Button>
|
||||
<Button onClick={modalProps.onClose} className="custom-modal-button">{t("gifCollections.ui.close")}</Button>
|
||||
</ModalFooter>
|
||||
</ModalRoot>
|
||||
));
|
||||
|
|
@ -493,7 +494,7 @@ const RemoveItemContextMenu = ({ type, nameOrId, instance }) => (
|
|||
<Menu.MenuItem
|
||||
key="rename-collection"
|
||||
id="rename-collection"
|
||||
label="Rename"
|
||||
label={t("gifCollections.ui.rename")}
|
||||
action={() => openModal(modalProps => (
|
||||
<RenameCollectionModal
|
||||
onClose={modalProps.onClose}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { UserSettingsActionCreators } from "@webpack/common";
|
||||
|
||||
|
|
@ -30,20 +31,20 @@ function getMessage(opts, other) {
|
|||
const settings = definePluginSettings({
|
||||
pingOwnerChance: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "If there should be a 1 in 10 change to ping the owner of the guild (oh no)",
|
||||
description: t("gifRoulette.settings.pingOwnerChance"),
|
||||
default: true
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "GifRoulette",
|
||||
description: "Adds a command to send a random gif from your favourites, and a one in ten chance to ping the owner of the server",
|
||||
description: t("gifRoulette.description"),
|
||||
authors: [Devs.Samwich],
|
||||
settings,
|
||||
commands: [
|
||||
{
|
||||
name: "gifroulette",
|
||||
description: "Tempt fate and send a gif",
|
||||
description: t("gifRoulette.commands.gifroulette"),
|
||||
execute: (opts, other) => ({
|
||||
content: getMessage(opts, other)
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { BaseText } from "@components/BaseText";
|
|||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { findByCodeLazy } from "@webpack";
|
||||
|
|
@ -23,22 +24,22 @@ export const cl = classNameFactory("vc-github-repos-");
|
|||
export const settings = definePluginSettings({
|
||||
showStars: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show repository stars",
|
||||
description: t("githubRepos.settings.showStars"),
|
||||
default: true
|
||||
},
|
||||
showLanguage: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show repository language",
|
||||
description: t("githubRepos.settings.showLanguage"),
|
||||
default: true
|
||||
},
|
||||
showInMiniProfile: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show full ui in the mini profile instead of just a button",
|
||||
description: t("githubRepos.settings.showInMiniProfile"),
|
||||
default: true
|
||||
},
|
||||
showRepositoryTab: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show repositories tab in profile modal (hides button in connections when enabled)",
|
||||
description: t("githubRepos.settings.showRepositoryTab"),
|
||||
default: true
|
||||
},
|
||||
});
|
||||
|
|
@ -58,7 +59,7 @@ const ProfilePopoutComponent = ErrorBoundary.wrap(
|
|||
{
|
||||
noop: true,
|
||||
fallback: () => <BaseText size="xs" weight="semibold" className="vc-github-repos-error" style={{ color: "var(--text-feedback-critical)" }}>
|
||||
Error, Failed to render GithubRepos
|
||||
{t("githubRepos.ui.error")}
|
||||
</BaseText>
|
||||
}
|
||||
);
|
||||
|
|
@ -79,7 +80,7 @@ const ProfileRepositoriesTab = ErrorBoundary.wrap(
|
|||
|
||||
export default definePlugin({
|
||||
name: "GitHubRepos",
|
||||
description: "Displays a user's public GitHub repositories in their profile",
|
||||
description: t("githubRepos.description"),
|
||||
authors: [EquicordDevs.talhakf, EquicordDevs.Panniku, EquicordDevs.benjii],
|
||||
settings,
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { Button } from "@components/Button";
|
|||
import { BadgeContextMenu } from "@plugins/_api/badges";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { openInviteModal } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { ContextMenuApi, React, Toasts, UserStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ let intervalId: any;
|
|||
migratePluginSetting("GlobalBadges", "showRaincord", "showRa1ncord");
|
||||
export default definePlugin({
|
||||
name: "GlobalBadges",
|
||||
description: "Adds global badges from other client mods",
|
||||
description: t("globalBadges.description"),
|
||||
authors: [Devs.HypedDomi, EquicordDevs.Wolfie, Devs.thororen],
|
||||
settings,
|
||||
settingsAboutComponent: () => (
|
||||
|
|
@ -34,7 +35,7 @@ export default definePlugin({
|
|||
className={cl("settings-button")}
|
||||
onClick={() => openInviteModal(INVITE_LINK)}
|
||||
>
|
||||
Join GlobalBadges Server
|
||||
{t("globalBadges.ui.joinServer")}
|
||||
</Button>
|
||||
</>
|
||||
),
|
||||
|
|
@ -51,7 +52,7 @@ export default definePlugin({
|
|||
await loadBadges();
|
||||
Toasts.show({
|
||||
id: Toasts.genId(),
|
||||
message: "Successfully refetched global badges!",
|
||||
message: t("globalBadges.ui.refetchSuccess"),
|
||||
type: Toasts.Type.SUCCESS
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { ApplicationCommandOptionType, findOption } from "@api/Commands";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
function getMessage(opts) {
|
||||
|
|
@ -48,17 +49,17 @@ const searchEngines = {
|
|||
const settings = definePluginSettings({
|
||||
hyperlink: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "If the sent link should hyperlink with the query as the label",
|
||||
description: t("googleThat.settings.hyperlink"),
|
||||
default: false
|
||||
},
|
||||
embed: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "If the sent link should render an embed",
|
||||
description: t("googleThat.settings.embed"),
|
||||
default: true
|
||||
},
|
||||
defaultEngine: {
|
||||
type: OptionType.SELECT,
|
||||
description: "The search engine to use",
|
||||
description: t("googleThat.settings.defaultEngine"),
|
||||
options: Object.keys(searchEngines).map((key, index) => ({
|
||||
label: key,
|
||||
value: key,
|
||||
|
|
@ -66,7 +67,7 @@ const settings = definePluginSettings({
|
|||
}))
|
||||
},
|
||||
customEngineURL: {
|
||||
description: "The URL of the Engine you wish to use",
|
||||
description: t("googleThat.settings.customEngineURL"),
|
||||
type: OptionType.STRING,
|
||||
placeholder: ""
|
||||
}
|
||||
|
|
@ -74,18 +75,18 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "GoogleThat",
|
||||
description: "Adds a command to send a internet search link",
|
||||
description: t("googleThat.description"),
|
||||
authors: [Devs.Samwich, EquicordDevs.KrystalSkull],
|
||||
tags: ["search", "google", "query", "duckduckgo", "command"],
|
||||
settings,
|
||||
commands: [
|
||||
{
|
||||
name: "googlethat",
|
||||
description: "send a search engine link",
|
||||
description: t("googleThat.commands.googlethat"),
|
||||
options: [
|
||||
{
|
||||
name: "input",
|
||||
description: "The search query",
|
||||
description: t("googleThat.commands.input"),
|
||||
type: ApplicationCommandOptionType.STRING,
|
||||
required: true,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import type { Guild } from "@vencord/discord-types";
|
||||
import { EmojiStore, Menu, StickersStore } from "@webpack/common";
|
||||
|
|
@ -14,14 +15,13 @@ import { zipSync } from "fflate";
|
|||
const StickerExt = [, "png", "apng", "json", "gif"] as const;
|
||||
|
||||
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => {
|
||||
// Assuming "privacy" is the correct ID for the group you want to modify.
|
||||
const group = findGroupChildrenByChildId("privacy", children);
|
||||
|
||||
if (group) {
|
||||
group.push(
|
||||
<>
|
||||
<Menu.MenuItem id="emoji.download" label="Download Emojis" action={() => zipGuildAssets(guild, "emojis")}></Menu.MenuItem>
|
||||
<Menu.MenuItem id="sticker.download" label="Download Stickers" action={() => zipGuildAssets(guild, "stickers")}></Menu.MenuItem>
|
||||
<Menu.MenuItem id="emoji.download" label={t("guildPickerDumper.ui.downloadEmojis")} action={() => zipGuildAssets(guild, "emojis")}></Menu.MenuItem>
|
||||
<Menu.MenuItem id="sticker.download" label={t("guildPickerDumper.ui.downloadStickers")} action={() => zipGuildAssets(guild, "stickers")}></Menu.MenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
|
|||
: StickersStore.getStickersByGuildId(guild.id);
|
||||
|
||||
if (!items) {
|
||||
return console.log("Server not found!");
|
||||
return console.log(t("guildPickerDumper.ui.serverNotFound"));
|
||||
}
|
||||
|
||||
const getProxyEndpoint = () => {
|
||||
|
|
@ -94,7 +94,7 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
|
|||
|
||||
export default definePlugin({
|
||||
name: "GuildPickerDumper",
|
||||
description: "Context menu to dump and download a server's emojis and stickers.",
|
||||
description: t("guildPickerDumper.description"),
|
||||
authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Synth, Devs.thororen],
|
||||
contextMenus: {
|
||||
"guild-context": Patch,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
import clanBadges from "./styles.css?managed";
|
||||
|
|
@ -26,7 +27,7 @@ import clanBadges from "./styles.css?managed";
|
|||
const settings = definePluginSettings({
|
||||
hideTags: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hide tags",
|
||||
description: t("guildTagSettings.settings.hideTags"),
|
||||
default: false,
|
||||
onChange: value => {
|
||||
if (value) enableStyle(clanBadges);
|
||||
|
|
@ -35,7 +36,7 @@ const settings = definePluginSettings({
|
|||
},
|
||||
disableAdoptTagPrompt: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Disable the prompt to adopt tags",
|
||||
description: t("guildTagSettings.settings.disableAdoptTagPrompt"),
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
|
|
@ -43,7 +44,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "GuildTagSettings",
|
||||
description: "Adds some settings for guild tags, such as hiding them or disabling the prompt to adopt them.",
|
||||
description: t("guildTagSettings.description"),
|
||||
authors: [Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { ChatBarButton } from "@api/ChatButtons";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
||||
import { React, useEffect, useState } from "@webpack/common";
|
||||
import type { MouseEventHandler, ReactNode } from "react";
|
||||
|
|
@ -16,12 +17,12 @@ let hidechatbuttonsopen: boolean | undefined;
|
|||
const settings = definePluginSettings({
|
||||
Color: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Color it red on open", // something extra
|
||||
description: t("hideChatButtons.settings.color"),
|
||||
default: false,
|
||||
},
|
||||
Open: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "opened by default",
|
||||
description: t("hideChatButtons.settings.open"),
|
||||
default: false,
|
||||
onChange: (store: { open: boolean; }) => {
|
||||
hidechatbuttonsopen = store.open;
|
||||
|
|
@ -32,7 +33,7 @@ const settings = definePluginSettings({
|
|||
function HideToggleButton(props: { open: boolean | undefined, onClick: MouseEventHandler<HTMLButtonElement>; }) {
|
||||
return (<ChatBarButton
|
||||
onClick={props.onClick}
|
||||
tooltip={props.open ? "Close" : "Open"}
|
||||
tooltip={props.open ? t("hideChatButtons.ui.close") : t("hideChatButtons.ui.open")}
|
||||
>
|
||||
<svg
|
||||
fill={settings.store.Color && props.open ? "#c32a32" : "currentColor"}
|
||||
|
|
@ -74,7 +75,7 @@ function ButtonsInnerComponent({ buttons }: { buttons: ReactNode[]; }) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "HideChatButtons",
|
||||
description: "able to hide the chat buttons",
|
||||
description: t("hideChatButtons.description"),
|
||||
settings: settings,
|
||||
authors: [EquicordDevs.iamme],
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
ServerListRenderPosition,
|
||||
} from "@api/ServerList";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Guild } from "@vencord/discord-types";
|
||||
import { findStoreLazy } from "@webpack";
|
||||
|
|
@ -53,7 +54,7 @@ const Patch: NavContextMenuPatchCallback = (
|
|||
group.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-hide-server"
|
||||
label={isHidden ? "Unhide Server" : "Hide Server"}
|
||||
label={isHidden ? t("hideServers.ui.unhideServer") : t("hideServers.ui.hideServer")}
|
||||
action={() => {
|
||||
if (isHidden) {
|
||||
HiddenServersStore.removeHiddenGuild(guild.id);
|
||||
|
|
@ -75,7 +76,7 @@ export function removeIndicator() {
|
|||
|
||||
export default definePlugin({
|
||||
name: "HideServers",
|
||||
description: "Allows you to hide servers from the guild list and quick switcher by right clicking them",
|
||||
description: t("hideServers.description"),
|
||||
authors: [EquicordDevs.bep],
|
||||
tags: ["guild", "server", "hide", "folder"],
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ export default definePlugin({
|
|||
menuItems.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-hide-folder"
|
||||
label={isHidden ? "Unhide Folder" : "Hide Folder"}
|
||||
label={isHidden ? t("hideServers.ui.unhideFolder") : t("hideServers.ui.hideFolder")}
|
||||
action={() => {
|
||||
if (isHidden) {
|
||||
HiddenServersStore.removeHiddenFolder(folderId, guildIds);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { DataStore } from "@api/index";
|
|||
import { EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { openModal } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { IconComponent } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { findByCodeLazy, findComponentByCodeLazy, findCssClassesLazy, findExportedComponentLazy } from "@webpack";
|
||||
|
|
@ -45,7 +46,7 @@ export const ChannelMessage = findComponentByCodeLazy("Message must not be a thr
|
|||
|
||||
const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => {
|
||||
children.push(
|
||||
<Menu.MenuItem label="Note Message" id="note-message">
|
||||
<Menu.MenuItem label={t("holyNotes.ui.noteMessage")} id="note-message">
|
||||
{Object.keys(noteHandler.getAllNotes()).map(notebook => (
|
||||
<Menu.MenuItem
|
||||
key={notebook}
|
||||
|
|
@ -61,7 +62,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { messag
|
|||
function ToolBarHeader() {
|
||||
return (
|
||||
<HeaderBarButton
|
||||
tooltip="Holy Notes"
|
||||
tooltip={t("holyNotes.ui.holyNotes")}
|
||||
position="bottom"
|
||||
icon={BookmarkIcon}
|
||||
onClick={() => openModal(props => <NoteModal {...props} />)}
|
||||
|
|
@ -71,11 +72,11 @@ function ToolBarHeader() {
|
|||
|
||||
export default definePlugin({
|
||||
name: "HolyNotes",
|
||||
description: "Save messages as notes to revisit later",
|
||||
description: t("holyNotes.description"),
|
||||
authors: [EquicordDevs.Wolfie],
|
||||
|
||||
toolboxActions: {
|
||||
"Open Notes"() {
|
||||
[t("holyNotes.ui.openNotes")]() {
|
||||
openModal(props => <NoteModal {...props} />);
|
||||
}
|
||||
},
|
||||
|
|
@ -93,7 +94,7 @@ export default definePlugin({
|
|||
icon: BookmarkIcon,
|
||||
render(message) {
|
||||
return {
|
||||
label: "Save Note",
|
||||
label: t("holyNotes.ui.saveNote"),
|
||||
icon: BookmarkIcon,
|
||||
message,
|
||||
channel: ChannelStore.getChannel(message.channel_id),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
||||
import { TypingStore, UserStore, useStateFromStores } from "@webpack/common";
|
||||
|
|
@ -15,7 +16,7 @@ const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { ge
|
|||
|
||||
export default definePlugin({
|
||||
name: "HomeTyping",
|
||||
description: "Changes the home button to a typing indicator if someone in your dms is typing",
|
||||
description: t("homeTyping.description"),
|
||||
authors: [Devs.Samwich],
|
||||
TypingIcon() {
|
||||
return <ThreeDots dotRadius={3} themed={true} />;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { RelationshipStore, SelectedChannelStore } from "@webpack/common";
|
||||
|
|
@ -20,18 +21,18 @@ interface IMessageCreate {
|
|||
const settings = definePluginSettings({
|
||||
regex: {
|
||||
type: OptionType.STRING,
|
||||
description: "Regex to trigger on",
|
||||
description: t("hopOn.settings.regex"),
|
||||
default: "hop on (?:fortnite|fn)"
|
||||
},
|
||||
url: {
|
||||
type: OptionType.STRING,
|
||||
description: "URL to open",
|
||||
description: t("hopOn.settings.url"),
|
||||
default: "com.epicgames.launcher://apps/fn%3A4fe75bbc5a674f4f9b356b5c90567da5%3AFortnite?action=launch&silent=true"
|
||||
}
|
||||
});
|
||||
export default definePlugin({
|
||||
name: "HopOn",
|
||||
description: "Hop on Fortnite or Hop on bloons :3",
|
||||
description: t("hopOn.description"),
|
||||
authors: [Devs.ImLvna],
|
||||
settings,
|
||||
flux: {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classes } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { ChannelStore, EmojiStore, RestAPI } from "@webpack/common";
|
||||
import type { SVGProps } from "react";
|
||||
|
|
@ -69,17 +70,17 @@ export function Husk(props: IconProps) {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
findInServer: {
|
||||
description: "Attempt to find emoji of same name in server before using ID in settings (useful if no nitro)",
|
||||
description: t("husk.settings.findInServer"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
},
|
||||
emojiName: {
|
||||
description: "Emoji name (default (from Vencord Server): husk)",
|
||||
description: t("husk.settings.emojiName"),
|
||||
type: OptionType.STRING,
|
||||
default: "husk"
|
||||
},
|
||||
emojiID: {
|
||||
description: "Emoji ID (default (from Vencord Server): 1026532993923293184)",
|
||||
description: t("husk.settings.emojiID"),
|
||||
type: OptionType.BIGINT,
|
||||
default: 1026532993923293184n
|
||||
}
|
||||
|
|
@ -98,14 +99,14 @@ function getEmojiIdThatShouldBeUsed(guildId: string) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "Husk",
|
||||
description: "Adds Husk button (check settings to change used emoji)",
|
||||
description: t("husk.description"),
|
||||
authors: [Devs.nin0dev],
|
||||
settings,
|
||||
messagePopoverButton: {
|
||||
icon: Husk,
|
||||
render(msg) {
|
||||
return {
|
||||
label: "Husk",
|
||||
label: t("husk.ui.husk"),
|
||||
icon: Husk,
|
||||
message: msg,
|
||||
channel: ChannelStore.getChannel(msg.channel_id),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { EyeIcon } from "@components/Icons";
|
|||
import SettingsPlugin from "@plugins/_core/settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { removeFromArray } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { Data } from "./components/data";
|
||||
|
|
@ -18,7 +19,7 @@ import DataUI from "./components/ui";
|
|||
|
||||
export default definePlugin({
|
||||
name: "IRememberYou",
|
||||
description: "Locally saves everyone you've been communicating with (including servers), in case of lose",
|
||||
description: t("iRememberYou.description"),
|
||||
authors: [EquicordDevs.zoodogood, EquicordDevs.keircn],
|
||||
dependencies: ["MessageEventsAPI"],
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ export default definePlugin({
|
|||
async start() {
|
||||
SettingsPlugin.customEntries.push({
|
||||
key: "equicord_i_remember_you",
|
||||
title: "I Remember You",
|
||||
title: t("iRememberYou.ui.iRememberYou"),
|
||||
Component: () => <DataUI usersCollection={data.usersCollection} />,
|
||||
Icon: EyeIcon
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { MagnifyingGlassIcon } from "@components/Icons";
|
|||
import SettingsPlugin from "@plugins/_core/settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { removeFromArray } from "@utils/misc";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { StartAt } from "@utils/types";
|
||||
import { SettingsRouter } from "@webpack/common";
|
||||
|
||||
|
|
@ -18,12 +19,12 @@ import { SettingsAbout } from "./components/Modals";
|
|||
|
||||
export default definePlugin({
|
||||
name: "IconViewer",
|
||||
description: "Adds a new tab to settings to preview all icons.",
|
||||
description: t("iconViewer.description"),
|
||||
authors: [EquicordDevs.iamme],
|
||||
dependencies: ["Settings"],
|
||||
startAt: StartAt.WebpackReady,
|
||||
toolboxActions: {
|
||||
"Open Icons Tab"() {
|
||||
[t("iconViewer.ui.openIconsTab")]() {
|
||||
SettingsRouter.openUserSettings("equicord_icon_viewer_panel");
|
||||
},
|
||||
},
|
||||
|
|
@ -31,7 +32,7 @@ export default definePlugin({
|
|||
start() {
|
||||
SettingsPlugin.customEntries.push({
|
||||
key: "equicord_icon_viewer",
|
||||
title: "Icon Finder",
|
||||
title: t("iconViewer.ui.iconFinder"),
|
||||
Component: IconsTab,
|
||||
Icon: MagnifyingGlassIcon
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Menu, VoiceStateStore } from "@webpack/common";
|
||||
|
||||
|
|
@ -16,12 +17,12 @@ let intervalId: ReturnType<typeof setInterval> | null = null;
|
|||
|
||||
const settings = definePluginSettings({
|
||||
isEnabled: {
|
||||
description: "Enable automatic restart after idle",
|
||||
description: t("idleAutoRestart.settings.isEnabled"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
},
|
||||
idleMinutes: {
|
||||
description: "Minutes of inactivity before restarting (when not in VC)",
|
||||
description: t("idleAutoRestart.settings.idleMinutes"),
|
||||
type: OptionType.SLIDER,
|
||||
markers: [5, 10, 15, 30, 60, 120],
|
||||
default: 30,
|
||||
|
|
@ -35,7 +36,7 @@ function onActivity() {
|
|||
|
||||
export default definePlugin({
|
||||
name: "IdleAutoRestart",
|
||||
description: "Automatically restarts the client after being idle for a configurable amount of time, but avoids restarting while you are in VC.",
|
||||
description: t("idleAutoRestart.description"),
|
||||
authors: [EquicordDevs.SteelTech],
|
||||
settings,
|
||||
|
||||
|
|
@ -43,7 +44,7 @@ export default definePlugin({
|
|||
return (
|
||||
<Menu.MenuItem
|
||||
id="auto-idle-restart-toggle-toolbox"
|
||||
label={settings.store.isEnabled ? "Disable Auto Idle Restart" : "Enable Auto Idle Restart"}
|
||||
label={settings.store.isEnabled ? t("idleAutoRestart.ui.disableAutoIdle") : t("idleAutoRestart.ui.enableAutoIdle")}
|
||||
action={() => {
|
||||
settings.store.isEnabled = !settings.store.isEnabled;
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { Button } from "@components/Button";
|
|||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Channel } from "@vencord/discord-types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
|
|
@ -34,7 +35,7 @@ const ContextMenuPatch: NavContextMenuPatchCallback = (children, { channel }: {
|
|||
<Menu.MenuSeparator />
|
||||
<Menu.MenuCheckboxItem
|
||||
id="vc-ignore-calls-temp"
|
||||
label="Temporarily Ignore Calls"
|
||||
label={t("ignoreCalls.ui.temporarilyIgnore")}
|
||||
checked={tempChecked}
|
||||
action={() => {
|
||||
if (tempChecked)
|
||||
|
|
@ -47,7 +48,7 @@ const ContextMenuPatch: NavContextMenuPatchCallback = (children, { channel }: {
|
|||
/>
|
||||
<Menu.MenuCheckboxItem
|
||||
id="vc-ignore-calls-perm"
|
||||
label="Permanently Ignore Calls"
|
||||
label={t("ignoreCalls.ui.permanentlyIgnore")}
|
||||
checked={permChecked}
|
||||
action={() => {
|
||||
let updated = permanentlyIgnoredUsers.slice();
|
||||
|
|
@ -68,7 +69,7 @@ const ContextMenuPatch: NavContextMenuPatchCallback = (children, { channel }: {
|
|||
const settings = definePluginSettings({
|
||||
permanentlyIgnoredUsers: {
|
||||
type: OptionType.STRING,
|
||||
description: "User IDs (comma + space) who should be permanetly ignored",
|
||||
description: t("ignoreCalls.settings.permanentlyIgnoredUsers"),
|
||||
restartNeeded: true,
|
||||
default: "",
|
||||
},
|
||||
|
|
@ -82,7 +83,7 @@ const args = {
|
|||
|
||||
export default definePlugin({
|
||||
name: "IgnoreCalls",
|
||||
description: "Allows you to ignore calls from specific users or dm groups.",
|
||||
description: t("ignoreCalls.description"),
|
||||
authors: [EquicordDevs.TheArmagan, Devs.thororen],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
@ -121,7 +122,7 @@ export default definePlugin({
|
|||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<Tooltip text="Ignore">
|
||||
<Tooltip text={t("ignoreCalls.ui.ignore")}>
|
||||
{({ onMouseEnter, onMouseLeave }) => (
|
||||
<Button
|
||||
className={cl("button")}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
import { ApplicationCommandInputType, ApplicationCommandOptionType, sendBotMessage } from "@api/Commands";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { CommandArgument, CommandContext } from "@vencord/discord-types";
|
||||
import { DraftType, UploadAttachmentStore, UploadHandler, UploadManager } from "@webpack/common";
|
||||
|
|
@ -50,10 +51,10 @@ async function resolveImage(options: CommandArgument[], ctx: CommandContext): Pr
|
|||
switch (opt.name) {
|
||||
case "image":
|
||||
const upload = UploadAttachmentStore.getUpload(ctx.channel.id, opt.name, DraftType.SlashCommand);
|
||||
if (upload) {
|
||||
if (upload) {
|
||||
if (!upload.isImage) {
|
||||
UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand);
|
||||
throw "Upload is not an image";
|
||||
throw t("imgToGif.errors.notAnImage");
|
||||
}
|
||||
image = upload.item.file;
|
||||
}
|
||||
|
|
@ -73,34 +74,34 @@ async function resolveImage(options: CommandArgument[], ctx: CommandContext): Pr
|
|||
|
||||
export default definePlugin({
|
||||
name: "ImgToGif",
|
||||
description: "Adds a /imgtogif slash command to create a gif from any image",
|
||||
description: t("imgToGif.description"),
|
||||
authors: [EquicordDevs.zyqunix],
|
||||
commands: [
|
||||
{
|
||||
inputType: ApplicationCommandInputType.BUILT_IN,
|
||||
name: "imgtogif",
|
||||
description: "Allows you to turn an image to a gif",
|
||||
description: t("imgToGif.commands.imgtogif"),
|
||||
options: [
|
||||
{
|
||||
name: "image",
|
||||
description: "Image attachment to use",
|
||||
description: t("imgToGif.commands.image"),
|
||||
type: ApplicationCommandOptionType.ATTACHMENT
|
||||
},
|
||||
{
|
||||
name: "width",
|
||||
description: "Width of the gif",
|
||||
description: t("imgToGif.commands.width"),
|
||||
type: ApplicationCommandOptionType.INTEGER
|
||||
},
|
||||
{
|
||||
name: "height",
|
||||
description: "Height of the gif",
|
||||
description: t("imgToGif.commands.height"),
|
||||
type: ApplicationCommandOptionType.INTEGER
|
||||
}
|
||||
],
|
||||
execute: async (opts, cmdCtx) => {
|
||||
try {
|
||||
const { image, width, height } = await resolveImage(opts, cmdCtx);
|
||||
if (!image) throw "No Image specified!";
|
||||
if (!image) throw t("imgToGif.errors.noImage");
|
||||
|
||||
const avatar = await loadImage(image);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { InfoIcon } from "@components/Icons";
|
|||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { getCurrentChannel, getCurrentGuild } from "@utils/discord";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { GuildMember } from "@vencord/discord-types";
|
||||
import { GuildMemberStore, GuildRoleStore, Menu, Parser } from "@webpack/common";
|
||||
|
|
@ -33,21 +34,20 @@ function getMembersInRole(roleId: string, guildId: string) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "InRole",
|
||||
description: "Know who is in a role with the role context menu or /inrole command (read plugin info!)",
|
||||
description: t("inRole.description"),
|
||||
authors: [Devs.nin0dev],
|
||||
dependencies: ["UserSettingsAPI"],
|
||||
start() {
|
||||
// DeveloperMode needs to be enabled for the context menu to be shown
|
||||
DeveloperMode.updateSetting(true);
|
||||
},
|
||||
settingsAboutComponent: () => {
|
||||
return (
|
||||
<>
|
||||
<Paragraph style={{ fontSize: "1.2rem", marginTop: "15px", fontWeight: "bold" }}>{Parser.parse(":warning:")} Limitations</Paragraph>
|
||||
<Paragraph style={{ marginTop: "10px", fontWeight: "500" }} >If you don't have mod permissions on the server, and that server is large (over 100 members), the plugin may be limited in the following ways:</Paragraph>
|
||||
<Paragraph>• Offline members won't be listed</Paragraph>
|
||||
<Paragraph>• Up to 100 members will be listed by default. To get more, scroll down in the member list to load more members.</Paragraph>
|
||||
<Paragraph>• However, friends will always be shown regardless of their status.</Paragraph>
|
||||
<Paragraph style={{ fontSize: "1.2rem", marginTop: "15px", fontWeight: "bold" }}>{Parser.parse(t("inRole.limitations.title"))}</Paragraph>
|
||||
<Paragraph style={{ marginTop: "10px", fontWeight: "500" }} >{t("inRole.limitations.description")}</Paragraph>
|
||||
<Paragraph>• {t("inRole.limitations.offlineNotListed")}</Paragraph>
|
||||
<Paragraph>• {t("inRole.limitations.upTo100")}</Paragraph>
|
||||
<Paragraph>• {t("inRole.limitations.friendsAlwaysShown")}</Paragraph>
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
|
@ -55,20 +55,19 @@ export default definePlugin({
|
|||
commands: [
|
||||
{
|
||||
name: "inrole",
|
||||
description: "Know who is in a role",
|
||||
description: t("inRole.commands.inrole"),
|
||||
inputType: ApplicationCommandInputType.BUILT_IN,
|
||||
options: [
|
||||
{
|
||||
name: "role",
|
||||
description: "The role",
|
||||
description: t("inRole.commands.role"),
|
||||
type: ApplicationCommandOptionType.ROLE,
|
||||
required: true
|
||||
},
|
||||
],
|
||||
execute: (args, ctx) => {
|
||||
// Guild check
|
||||
if (!ctx.guild) {
|
||||
return sendBotMessage(ctx.channel.id, { content: "Make sure that you are in a server." });
|
||||
return sendBotMessage(ctx.channel.id, { content: t("inRole.errors.makeSureServer") });
|
||||
}
|
||||
const role = args[0].value;
|
||||
showInRoleModal(getMembersInRole(role, ctx.guild.id), role, ctx.channel.id);
|
||||
|
|
@ -89,7 +88,7 @@ export default definePlugin({
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-view-inrole"
|
||||
label="View Members in Role"
|
||||
label={t("inRole.ui.viewMembers")}
|
||||
action={() => {
|
||||
showInRoleModal(getMembersInRole(role.id, guild.id), role.id, channel.id);
|
||||
}}
|
||||
|
|
@ -115,7 +114,7 @@ export default definePlugin({
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-view-inrole"
|
||||
label="View Members in Role"
|
||||
label={t("inRole.ui.viewMembers")}
|
||||
action={() => {
|
||||
showInRoleModal(getMembersInRole(role.id, guild.id), role.id, channel.id);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { ChatBarButton, ChatBarButtonFactory } from "@api/ChatButtons";
|
|||
import { addMessagePreSendListener, removeMessagePreSendListener } from "@api/MessageEvents";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { React } from "@webpack/common";
|
||||
|
||||
|
|
@ -20,13 +21,13 @@ const settings = definePluginSettings({
|
|||
showIcon: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Show a button to toggle the Ingtoninator plugin",
|
||||
description: t("ingtoninator.settings.showIcon"),
|
||||
restartNeeded: true
|
||||
},
|
||||
isEnabled: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Enable or disable the Ingtoninator"
|
||||
description: t("ingtoninator.settings.isEnabled")
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ const IngtoninatorButton: ChatBarButtonFactory = ({ isMainChat }) => {
|
|||
|
||||
return (
|
||||
<ChatBarButton
|
||||
tooltip={isEnabled ? "Ingtoninator Enabled" : "Ingtoninator Disabled"}
|
||||
tooltip={isEnabled ? t("ingtoninator.ui.enabled") : t("ingtoninator.ui.disabled")}
|
||||
onClick={toggle}
|
||||
>
|
||||
{isEnabled ? (
|
||||
|
|
@ -145,7 +146,7 @@ function disabledIcon() {
|
|||
|
||||
export default definePlugin({
|
||||
name: "Ingtoninator",
|
||||
description: "Suffixes 'ington' to a random word in your message",
|
||||
description: t("ingtoninator.description"),
|
||||
authors: [EquicordDevs.zyqunix, EquicordDevs.BioTomateDE],
|
||||
settings,
|
||||
chatBarButton: {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { getUserSettingLazy } from "@api/UserSettings";
|
|||
import { HeadingSecondary } from "@components/Heading";
|
||||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { VoiceState } from "@vencord/discord-types";
|
||||
import { findByCodeLazy, findStoreLazy } from "@webpack";
|
||||
|
|
@ -56,7 +57,7 @@ async function autoStartStream(instant = true) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "InstantScreenshare",
|
||||
description: "Instantly screenshare when joining a voice channel with support for desktop sources, windows, and video input devices (cameras, capture cards)",
|
||||
description: t("instantScreenshare.description"),
|
||||
authors: [Devs.HAHALOSAH, Devs.thororen, EquicordDevs.mart],
|
||||
dependencies: ["EquicordToolbox"],
|
||||
tags: ["ScreenshareKeybind"],
|
||||
|
|
@ -65,21 +66,21 @@ export default definePlugin({
|
|||
|
||||
settingsAboutComponent: () => (
|
||||
<>
|
||||
<HeadingSecondary>For Linux</HeadingSecondary>
|
||||
<HeadingSecondary>{t("instantScreenshare.info.linux")}</HeadingSecondary>
|
||||
<Paragraph>
|
||||
For Wayland it only pops up the screenshare select
|
||||
{t("instantScreenshare.info.wayland")}
|
||||
<br />
|
||||
For X11 it may or may not work :shrug:
|
||||
{t("instantScreenshare.info.x11")}
|
||||
</Paragraph>
|
||||
<br />
|
||||
<HeadingSecondary>Video Devices</HeadingSecondary>
|
||||
<HeadingSecondary>{t("instantScreenshare.info.videoDevices")}</HeadingSecondary>
|
||||
<Paragraph>
|
||||
Supports cameras and capture cards (like Elgato HD60X) when enabled in settings
|
||||
{t("instantScreenshare.info.videoDevicesInfo")}
|
||||
</Paragraph>
|
||||
<br />
|
||||
<HeadingSecondary>Regarding Sound & Preview Settings</HeadingSecondary>
|
||||
<HeadingSecondary>{t("instantScreenshare.info.soundPreview")}</HeadingSecondary>
|
||||
<Paragraph>
|
||||
We use the settings set and used by discord to decide if stream preview and sound should be enabled or not
|
||||
{t("instantScreenshare.info.soundPreviewInfo")}
|
||||
</Paragraph>
|
||||
</>
|
||||
),
|
||||
|
|
@ -126,9 +127,9 @@ export default definePlugin({
|
|||
},
|
||||
|
||||
toolboxActions: {
|
||||
"Instant Screenshare"() {
|
||||
[t("instantScreenshare.ui.instantScreenshare")]() {
|
||||
settings.store.toolboxManagement = !settings.store.toolboxManagement;
|
||||
showToast(`Instant Screenshare ${settings.store.toolboxManagement ? "Enabled" : "Disabled"}`, Toasts.Type.SUCCESS);
|
||||
showToast(settings.store.toolboxManagement ? t("instantScreenshare.ui.instantScreenshareEnabled") : t("instantScreenshare.ui.instantScreenshareDisabled"), Toasts.Type.SUCCESS);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { getStegCloak } from "@utils/dependencies";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType, ReporterTestable } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { ChannelStore, Constants, RestAPI, Tooltip } from "@webpack/common";
|
||||
|
|
@ -46,7 +47,7 @@ function PopOverIcon() {
|
|||
|
||||
function Indicator() {
|
||||
return (
|
||||
<Tooltip text="This message has a hidden message! (InvisibleChat)">
|
||||
<Tooltip text={t("invisibleChat.ui.hiddenMessageIndicator")}>
|
||||
{({ onMouseEnter, onMouseLeave }) => (
|
||||
<img
|
||||
aria-label="Hidden Message Indicator (InvisibleChat)"
|
||||
|
|
@ -69,7 +70,7 @@ const ChatBarRender: ChatBarButtonFactory = ({ isMainChat }) => {
|
|||
|
||||
return (
|
||||
<ChatBarButton
|
||||
tooltip="Encrypt Message"
|
||||
tooltip={t("invisibleChat.ui.encryptMessage")}
|
||||
onClick={() => buildEncModal()}
|
||||
buttonProps={{
|
||||
"aria-haspopup": "dialog",
|
||||
|
|
@ -99,7 +100,7 @@ const settings = definePluginSettings({
|
|||
savedPasswords: {
|
||||
type: OptionType.STRING,
|
||||
default: "password, Password",
|
||||
description: "Saved Passwords (Seperated with a , )"
|
||||
description: t("invisibleChat.settings.savedPasswords")
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -148,7 +149,7 @@ export async function buildEmbed(message: any, revealed: string): Promise<void>
|
|||
|
||||
export default definePlugin({
|
||||
name: "InvisibleChat",
|
||||
description: "Encrypt your Messages in a non-suspicious way!",
|
||||
description: t("invisibleChat.description"),
|
||||
authors: [Devs.SammCheese],
|
||||
dependencies: ["MessageUpdaterAPI"],
|
||||
reporterTestable: ReporterTestable.Patches,
|
||||
|
|
@ -180,7 +181,7 @@ export default definePlugin({
|
|||
render(message) {
|
||||
return INV_REGEX.test(message?.content)
|
||||
? {
|
||||
label: "Decrypt Message",
|
||||
label: t("invisibleChat.ui.decryptMessage"),
|
||||
icon: PopOverIcon,
|
||||
message: message,
|
||||
channel: ChannelStore.getChannel(message.channel_id),
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
inviteDuration: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Invite Duration",
|
||||
description: t("inviteDefaults.settings.inviteDuration"),
|
||||
options: [
|
||||
{ label: "30 minutes", value: 1800 },
|
||||
{ label: "1 hour", value: 3600 },
|
||||
|
|
@ -19,14 +20,14 @@ const settings = definePluginSettings({
|
|||
{ label: "12 hours", value: 43200 },
|
||||
{ label: "1 day", value: 86400 },
|
||||
{ label: "7 days", value: 604800 },
|
||||
{ label: "Forever", value: 0, default: true },
|
||||
{ label: t("inviteDefaults.options.forever"), value: 0, default: true },
|
||||
],
|
||||
},
|
||||
maxUses: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Invite Use Count",
|
||||
description: t("inviteDefaults.settings.maxUses"),
|
||||
options: [
|
||||
{ label: "Infinite", value: 0, default: true },
|
||||
{ label: t("inviteDefaults.options.infinite"), value: 0, default: true },
|
||||
{ label: "1", value: 1 },
|
||||
{ label: "5", value: 5 },
|
||||
{ label: "10", value: 10 },
|
||||
|
|
@ -38,13 +39,13 @@ const settings = definePluginSettings({
|
|||
temporaryMembership: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
description: "Temporary Membership",
|
||||
description: t("inviteDefaults.settings.temporaryMembership"),
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "InviteDefaults",
|
||||
description: "Allows you to edit the default values when creating server invites.",
|
||||
description: t("inviteDefaults.description"),
|
||||
authors: [EquicordDevs.VillainsRule],
|
||||
settings,
|
||||
patches: [
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { HeadingSecondary } from "@components/Heading";
|
|||
import { Paragraph } from "@components/Paragraph";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { ApplicationAssetUtils, FluxDispatcher, showToast } from "@webpack/common";
|
||||
|
||||
|
|
@ -60,86 +61,86 @@ interface MediaData {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
serverUrl: {
|
||||
description: "Jellyfin server URL (e.g., https://jellyfin.example.com)",
|
||||
description: t("jellyfinRichPresence.settings.serverUrl"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
apiKey: {
|
||||
description: "Jellyfin API key obtained from your Jellyfin administration dashboard",
|
||||
description: t("jellyfinRichPresence.settings.apiKey"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
userId: {
|
||||
description: "Jellyfin user ID obtained from your user profile URL",
|
||||
description: t("jellyfinRichPresence.settings.userId"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
nameDisplay: {
|
||||
description: "Choose how the application name should appear in Rich Presence",
|
||||
description: t("jellyfinRichPresence.settings.nameDisplay"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "Series/Movie Name", value: "default", default: true },
|
||||
{ label: "Series - Episode/Track/Movie Name", value: "full" },
|
||||
{ label: "Custom", value: "custom" },
|
||||
{ label: t("jellyfinRichPresence.nameFormatOptions.seriesMovieName"), value: "default", default: true },
|
||||
{ label: t("jellyfinRichPresence.nameFormatOptions.seriesEpisodeName"), value: "full" },
|
||||
{ label: t("jellyfinRichPresence.nameFormatOptions.custom"), value: "custom" },
|
||||
],
|
||||
},
|
||||
customName: {
|
||||
description: "Custom Rich Presence name (only used if 'Custom' is selected).\nOptions: {name}, {series}, {season}, {episode}, {artist}, {album}, {year}",
|
||||
description: t("jellyfinRichPresence.settings.customName"),
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
coverType: {
|
||||
description: "Choose which cover to display when watching a TV show",
|
||||
description: t("jellyfinRichPresence.settings.coverType"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "Series Cover", value: "series", default: true },
|
||||
{ label: "Episode Cover", value: "episode" },
|
||||
{ label: t("jellyfinRichPresence.coverTypeOptions.seriesCover"), value: "series", default: true },
|
||||
{ label: t("jellyfinRichPresence.coverTypeOptions.episodeCover"), value: "episode" },
|
||||
],
|
||||
},
|
||||
episodeFormat: {
|
||||
description: "Episode number format",
|
||||
description: t("jellyfinRichPresence.settings.episodeFormat"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "S01E01", value: "long", default: true },
|
||||
{ label: "1x01", value: "short" },
|
||||
{ label: "Season 1 Episode 1", value: "fulltext" },
|
||||
{ label: t("jellyfinRichPresence.episodeFormatOptions.s01e01"), value: "long", default: true },
|
||||
{ label: t("jellyfinRichPresence.episodeFormatOptions.short"), value: "short" },
|
||||
{ label: t("jellyfinRichPresence.episodeFormatOptions.fulltext"), value: "fulltext" },
|
||||
],
|
||||
},
|
||||
showEpisodeName: {
|
||||
description: "Show episode name after season/episode info",
|
||||
description: t("jellyfinRichPresence.settings.showEpisodeName"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
overrideRichPresenceType: {
|
||||
description: "Override the rich presence type",
|
||||
description: t("jellyfinRichPresence.settings.overrideRichPresenceType"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{
|
||||
label: "Off",
|
||||
label: t("jellyfinRichPresence.overrideTypeOptions.off"),
|
||||
value: false,
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
label: "Listening",
|
||||
label: t("jellyfinRichPresence.overrideTypeOptions.listening"),
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: "Playing",
|
||||
label: t("jellyfinRichPresence.overrideTypeOptions.playing"),
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: "Streaming",
|
||||
label: t("jellyfinRichPresence.overrideTypeOptions.streaming"),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: "Watching",
|
||||
label: t("jellyfinRichPresence.overrideTypeOptions.watching"),
|
||||
value: 3
|
||||
},
|
||||
],
|
||||
},
|
||||
showPausedState: {
|
||||
description: "Show Rich Presence when media is paused",
|
||||
description: t("jellyfinRichPresence.settings.showPausedState"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
},
|
||||
privacyMode: {
|
||||
description: "Privacy Mode (Hide media details like Episode/Song Name)",
|
||||
description: t("jellyfinRichPresence.settings.privacyMode"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
|
|
@ -165,14 +166,14 @@ function setActivity(activity: Activity | null) {
|
|||
|
||||
export default definePlugin({
|
||||
name: "JellyfinRichPresence",
|
||||
description: "Rich presence for Jellyfin media server",
|
||||
description: t("jellyfinRichPresence.description"),
|
||||
authors: [EquicordDevs.vmohammad, Devs.SerStars, EquicordDevs.ZcraftElite],
|
||||
|
||||
settingsAboutComponent: () => (
|
||||
<>
|
||||
<HeadingSecondary>How to get an API key</HeadingSecondary>
|
||||
<HeadingSecondary>{t("jellyfinRichPresence.howToGetApiKey.title")}</HeadingSecondary>
|
||||
<Paragraph>
|
||||
Auth token can be found by following these steps:
|
||||
{t("jellyfinRichPresence.howToGetApiKey.description")}
|
||||
<ol style={{ marginTop: 8, marginBottom: 8, paddingLeft: 20 }}>
|
||||
<li>1. Log into your Jellyfin instance</li>
|
||||
<li>2. Open your browser's Developer Tools (usually F12 or right-click then Inspect)</li>
|
||||
|
|
@ -187,7 +188,7 @@ export default definePlugin({
|
|||
</li>
|
||||
</ol>
|
||||
<br />
|
||||
You'll also need your User ID, which can be found in the url of your user profile page.
|
||||
{t("jellyfinRichPresence.howToGetApiKey.userIdInfo")}
|
||||
</Paragraph>
|
||||
</>
|
||||
),
|
||||
|
|
@ -207,7 +208,7 @@ export default definePlugin({
|
|||
async fetchMediaData(): Promise<MediaData | null> {
|
||||
if (!settings.store.serverUrl || !settings.store.apiKey || !settings.store.userId) {
|
||||
logger.warn("Jellyfin server URL, API key, or user ID is not set in settings.");
|
||||
showToast("JellyfinRPC is not configured.", "failure", {
|
||||
showToast(t("jellyfinRichPresence.toasts.notConfigured"), "failure", {
|
||||
duration: 15000,
|
||||
});
|
||||
return null;
|
||||
|
|
@ -302,15 +303,15 @@ export default definePlugin({
|
|||
case "full":
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
appName = settings.store.privacyMode
|
||||
? `${mediaData.seriesName} - [Episode Hidden]`
|
||||
? `${mediaData.seriesName} - ${t("jellyfinRichPresence.privacyMode.episodeHidden")}`
|
||||
: `${mediaData.seriesName} - ${mediaData.name}`;
|
||||
} else if (mediaData.type === "Audio") {
|
||||
appName = settings.store.privacyMode
|
||||
? "[Track Hidden]"
|
||||
? t("jellyfinRichPresence.privacyMode.trackHidden")
|
||||
: `${mediaData.artist || "Unknown Artist"} - ${mediaData.name}`;
|
||||
} else {
|
||||
appName = settings.store.privacyMode
|
||||
? "[Movie Hidden]"
|
||||
? t("jellyfinRichPresence.privacyMode.movieHidden")
|
||||
: mediaData.name || "Jellyfin";
|
||||
}
|
||||
break;
|
||||
|
|
@ -318,10 +319,10 @@ export default definePlugin({
|
|||
appName = templateReplace(settings.store.customName || "{name} on Jellyfin");
|
||||
if (settings.store.privacyMode) {
|
||||
appName = appName
|
||||
.replace(mediaData.name || "", "[Title Hidden]")
|
||||
.replace(mediaData.seriesName || "", "[Series Hidden]")
|
||||
.replace(mediaData.artist || "", "[Artist Hidden]")
|
||||
.replace(mediaData.album || "", "[Album Hidden]");
|
||||
.replace(mediaData.name || "", t("jellyfinRichPresence.privacyMode.titleHidden"))
|
||||
.replace(mediaData.seriesName || "", t("jellyfinRichPresence.privacyMode.seriesHidden"))
|
||||
.replace(mediaData.artist || "", t("jellyfinRichPresence.privacyMode.artistHidden"))
|
||||
.replace(mediaData.album || "", t("jellyfinRichPresence.privacyMode.albumHidden"));
|
||||
}
|
||||
break;
|
||||
case "default":
|
||||
|
|
@ -330,7 +331,7 @@ export default definePlugin({
|
|||
appName = mediaData.seriesName;
|
||||
} else {
|
||||
appName = settings.store.privacyMode
|
||||
? "[Media Hidden]"
|
||||
? t("jellyfinRichPresence.privacyMode.mediaHidden")
|
||||
: mediaData.name || "Jellyfin";
|
||||
}
|
||||
break;
|
||||
|
|
@ -351,14 +352,14 @@ export default definePlugin({
|
|||
|
||||
const getDetails = () => {
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
return settings.store.privacyMode ? "Watching a TV Show" : mediaData.seriesName;
|
||||
return settings.store.privacyMode ? t("jellyfinRichPresence.privacyMode.watchingTvShow") : mediaData.seriesName;
|
||||
}
|
||||
return settings.store.privacyMode ? "Watching Something" : mediaData.name;
|
||||
return settings.store.privacyMode ? t("jellyfinRichPresence.privacyMode.watchingSomething") : mediaData.name;
|
||||
};
|
||||
|
||||
const getState = () => {
|
||||
if (mediaData.isPaused) {
|
||||
return "Paused";
|
||||
return t("jellyfinRichPresence.state.paused");
|
||||
}
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
let episodeFormat = "";
|
||||
|
|
@ -375,13 +376,13 @@ export default definePlugin({
|
|||
episodeFormat = `${season}x${episode.toString().padStart(2, "0")}`;
|
||||
break;
|
||||
case "fulltext":
|
||||
episodeFormat = `Season ${season} Episode ${episode}`;
|
||||
episodeFormat = t("jellyfinRichPresence.state.season", { season }) + " " + t("jellyfinRichPresence.state.episode", { episode });
|
||||
break;
|
||||
}
|
||||
} else if (season != null) {
|
||||
episodeFormat = format === "fulltext" ? `Season ${season}` : `S${season.toString().padStart(2, "0")}`;
|
||||
episodeFormat = format === "fulltext" ? t("jellyfinRichPresence.state.season", { season }) : `S${season.toString().padStart(2, "0")}`;
|
||||
} else if (episode != null) {
|
||||
episodeFormat = format === "fulltext" ? `Episode ${episode}` : `E${episode.toString().padStart(2, "0")}`;
|
||||
episodeFormat = format === "fulltext" ? t("jellyfinRichPresence.state.episode", { episode }) : `E${episode.toString().padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
if (settings.store.showEpisodeName && mediaData.name && !settings.store.privacyMode) {
|
||||
|
|
@ -390,7 +391,7 @@ export default definePlugin({
|
|||
return episodeFormat;
|
||||
}
|
||||
if (settings.store.privacyMode) {
|
||||
return mediaData.type === "Audio" ? "Listening to music" : (mediaData.year ? "(????)" : undefined);
|
||||
return mediaData.type === "Audio" ? t("jellyfinRichPresence.privacyMode.listeningToMusic") : (mediaData.year ? "(????)" : undefined);
|
||||
}
|
||||
return mediaData.artist || (mediaData.year ? `(${mediaData.year})` : undefined);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Channel, Message, User } from "@vencord/discord-types";
|
||||
import { Constants, Menu, NavigationRouter, RestAPI, SelectedChannelStore, SelectedGuildStore, Toasts } from "@webpack/common";
|
||||
|
|
@ -44,7 +45,7 @@ async function jumpToUserMessage(channelId: string, guildId: string, userId: str
|
|||
if (!messageId) {
|
||||
Toasts.show({
|
||||
type: Toasts.Type.FAILURE,
|
||||
message: "No messages found from this user in this channel.",
|
||||
message: t("jumpTo.errors.noMessagesFound"),
|
||||
id: Toasts.genId()
|
||||
});
|
||||
return;
|
||||
|
|
@ -55,7 +56,7 @@ async function jumpToUserMessage(channelId: string, guildId: string, userId: str
|
|||
} catch (e) {
|
||||
Toasts.show({
|
||||
type: Toasts.Type.FAILURE,
|
||||
message: "Failed to search for messages.",
|
||||
message: t("jumpTo.errors.failedSearch"),
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}
|
||||
|
|
@ -67,12 +68,12 @@ const ChannelMenuPatch: NavContextMenuPatchCallback = (children, { channel }: {
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-jump-to-first"
|
||||
label="Jump To First Message"
|
||||
label={t("jumpTo.ui.jumpToFirst")}
|
||||
action={() => jumpToFirstMessage(channel.id, channel.guild_id)}
|
||||
/>,
|
||||
<Menu.MenuItem
|
||||
id="vc-jump-to-last"
|
||||
label="Jump To Last Message"
|
||||
label={t("jumpTo.ui.jumpToLast")}
|
||||
action={() => jumpToLastMessage(channel.id, channel.guild_id)}
|
||||
/>
|
||||
);
|
||||
|
|
@ -86,12 +87,12 @@ const UserMenuPatch: NavContextMenuPatchCallback = (children, { user, channel }:
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-jump-to-first"
|
||||
label="Jump To First Message"
|
||||
label={t("jumpTo.ui.jumpToFirst")}
|
||||
action={() => jumpToFirstMessage(channel.id, null)}
|
||||
/>,
|
||||
<Menu.MenuItem
|
||||
id="vc-jump-to-last"
|
||||
label="Jump To Last Message"
|
||||
label={t("jumpTo.ui.jumpToLast")}
|
||||
action={() => jumpToLastMessage(channel.id, null)}
|
||||
/>
|
||||
);
|
||||
|
|
@ -107,12 +108,12 @@ const MessageMenuPatch: NavContextMenuPatchCallback = (children, { message }: {
|
|||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-jump-to-first-user"
|
||||
label="Jump To First Message"
|
||||
label={t("jumpTo.ui.jumpToFirst")}
|
||||
action={() => jumpToUserMessage(channelId, guildId, message.author.id, true)}
|
||||
/>,
|
||||
<Menu.MenuItem
|
||||
id="vc-jump-to-last-user"
|
||||
label="Jump To Last Message"
|
||||
label={t("jumpTo.ui.jumpToLast")}
|
||||
action={() => jumpToUserMessage(channelId, guildId, message.author.id, false)}
|
||||
/>
|
||||
);
|
||||
|
|
@ -120,7 +121,7 @@ const MessageMenuPatch: NavContextMenuPatchCallback = (children, { message }: {
|
|||
|
||||
export default definePlugin({
|
||||
name: "JumpTo",
|
||||
description: "Adds context menu options to jump to the start or bottom of a channel/DM.",
|
||||
description: t("jumpTo.description"),
|
||||
authors: [Devs.Samwich, Devs.thororen],
|
||||
contextMenus: {
|
||||
"channel-context": ChannelMenuPatch,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import "./styles.css";
|
|||
import { createAudioPlayer } from "@api/AudioPlayer";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { createRoot, FluxDispatcher, useCallback, useEffect, useState } from "@webpack/common";
|
||||
import { Root } from "react-dom/client";
|
||||
|
|
@ -18,17 +19,17 @@ let jumpscareRoot: Root | undefined;
|
|||
const settings = definePluginSettings({
|
||||
imageSource: {
|
||||
type: OptionType.STRING,
|
||||
description: "Sets the image url of the jumpscare",
|
||||
description: t("jumpscare.settings.imageSource"),
|
||||
default: "https://github.com/Equicord/Equibored/blob/main/icons/jumpscare/troll.gif?raw=true"
|
||||
},
|
||||
audioSource: {
|
||||
type: OptionType.STRING,
|
||||
description: "Sets the audio url of the jumpscare",
|
||||
description: t("jumpscare.settings.audioSource"),
|
||||
default: "https://github.com/Equicord/Equibored/raw/main/sounds/jumpscare/trollolol.mp3?raw=true"
|
||||
},
|
||||
chance: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "The chance of a jumpscare happening (1 in X so: 100 = 1/100 or 1%, 50 = 1/50 or 2%, etc.)",
|
||||
description: t("jumpscare.settings.chance"),
|
||||
default: 1000
|
||||
}
|
||||
});
|
||||
|
|
@ -47,7 +48,7 @@ function getJumpscareRoot(): Root {
|
|||
|
||||
export default definePlugin({
|
||||
name: "Jumpscare",
|
||||
description: "Adds a configurable chance of jumpscaring you whenever you open a channel. Inspired by Geometry Dash Mega Hack",
|
||||
description: t("jumpscare.description"),
|
||||
authors: [Devs.surgedevs],
|
||||
dependencies: ["AudioPlayerAPI"],
|
||||
settings,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import { Devs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { closeAllModals } from "@utils/modal";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { SettingsRouter, useState } from "@webpack/common";
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ let isRecordingGlobal: boolean = false;
|
|||
|
||||
export const settings = definePluginSettings({
|
||||
hotkey: {
|
||||
description: "The hotkey to open the command palette.",
|
||||
description: t("keyboardNavigation.settings.hotkey"),
|
||||
type: OptionType.COMPONENT,
|
||||
default: ["Control", "Shift", "P"],
|
||||
component: () => {
|
||||
|
|
@ -69,7 +70,7 @@ export const settings = definePluginSettings({
|
|||
<div className={`${cl("key-recorder")} ${isRecording ? cl("recording") : ""}`}>
|
||||
{settings.store.hotkey.map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" + ")}
|
||||
<button className={`${cl("key-recorder-button")} ${isRecording ? cl("recording-button") : ""}`} disabled={isRecording}>
|
||||
{isRecording ? "Recording..." : "Record keybind"}
|
||||
{isRecording ? t("keyboardNavigation.ui.recording") : t("keyboardNavigation.ui.recordKeybind")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -78,7 +79,7 @@ export const settings = definePluginSettings({
|
|||
}
|
||||
},
|
||||
allowMouseControl: {
|
||||
description: "Allow the mouse to control the command palette.",
|
||||
description: t("keyboardNavigation.settings.allowMouseControl"),
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
}
|
||||
|
|
@ -86,7 +87,7 @@ export const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "KeyboardNavigation",
|
||||
description: "Allows you to navigate the UI with a keyboard.",
|
||||
description: t("keyboardNavigation.description"),
|
||||
authors: [Devs.Ethan],
|
||||
settings,
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ export default definePlugin({
|
|||
if (IS_DEV) {
|
||||
registerAction({
|
||||
id: "openDevSettings",
|
||||
label: "Open Dev tab",
|
||||
label: t("keyboardNavigation.commands.openDevSettings"),
|
||||
callback: () => SettingsRouter.openUserSettings("equicord_patch_helper_panel"),
|
||||
registrar: "Equicord"
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
import { AudioPlayerInterface, createAudioPlayer } from "@api/AudioPlayer";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
import { ignoredKeys, packs } from "./packs";
|
||||
|
|
@ -105,7 +106,7 @@ function assignSounds(volume: number, pack: "operagx" | "osu") {
|
|||
|
||||
const settings = definePluginSettings({
|
||||
volume: {
|
||||
description: "Volume of the keyboard sounds.",
|
||||
description: t("keyboardSounds.settings.volume"),
|
||||
type: OptionType.SLIDER,
|
||||
markers: [0, 25, 50, 75, 100],
|
||||
stickToMarkers: false,
|
||||
|
|
@ -113,11 +114,11 @@ const settings = definePluginSettings({
|
|||
onChange: value => { assignSounds(value, settings.store.soundPack); }
|
||||
},
|
||||
soundPack: {
|
||||
description: "Sound pack to use.",
|
||||
description: t("keyboardSounds.settings.soundPack"),
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "OperaGX", value: "operagx" as "operagx", default: true },
|
||||
{ label: "osu!", value: "osu" as "osu" }
|
||||
{ label: t("keyboardSounds.options.operaGx"), value: "operagx" as "operagx", default: true },
|
||||
{ label: t("keyboardSounds.options.osu"), value: "osu" as "osu" }
|
||||
],
|
||||
onChange: value => { assignSounds(settings.store.volume, value); }
|
||||
}
|
||||
|
|
@ -125,7 +126,7 @@ const settings = definePluginSettings({
|
|||
|
||||
export default definePlugin({
|
||||
name: "KeyboardSounds",
|
||||
description: "Adds OperaGX or osu! sound effects when typing on your keyboard.",
|
||||
description: t("keyboardSounds.description"),
|
||||
authors: [Devs.HypedDomi, EquicordDevs.Etorix],
|
||||
dependencies: ["AudioPlayerAPI"],
|
||||
settings,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { classNameFactory } from "@utils/css";
|
|||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import { useForceUpdater } from "@utils/react";
|
||||
import { t } from "@utils/translation";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { findByCodeLazy, findCssClassesLazy } from "@webpack";
|
||||
|
|
@ -162,8 +163,8 @@ function ListTypeSelector({ listType, setListType }: { listType: ListType, setLi
|
|||
return (
|
||||
<Select
|
||||
options={[
|
||||
{ label: "Whitelist", value: ListType.Whitelist },
|
||||
{ label: "Blacklist", value: ListType.BlackList }
|
||||
{ label: t("keywordNotify.options.whitelist"), value: ListType.Whitelist },
|
||||
{ label: t("keywordNotify.options.blacklist"), value: ListType.BlackList }
|
||||
]}
|
||||
placeholder={"Select a list type"}
|
||||
isSelected={v => v === listType}
|
||||
|
|
@ -205,7 +206,7 @@ function KeywordEntries() {
|
|||
const elements = keywordEntries.map((entry, i) => {
|
||||
return (
|
||||
<>
|
||||
<Collapsible title={`Keyword Entry ${i + 1}`}>
|
||||
<Collapsible title={t("keywordNotify.ui.keywordEntry", { index: i + 1 })}>
|
||||
<Flex flexDirection="row">
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<TextInput
|
||||
|
|
@ -224,14 +225,14 @@ function KeywordEntries() {
|
|||
</Button>
|
||||
</Flex>
|
||||
<FormSwitch
|
||||
title="Ignore Case"
|
||||
title={t("keywordNotify.ui.ignoreCase")}
|
||||
className={cl("ignoreCaseSwitch")}
|
||||
value={values[i].ignoreCase}
|
||||
onChange={() => {
|
||||
setIgnoreCase(i, !values[i].ignoreCase);
|
||||
}}
|
||||
/>
|
||||
<Heading tag="h5">Whitelist/Blacklist</Heading>
|
||||
<Heading tag="h5">{t("keywordNotify.ui.whitelistBlacklist")}</Heading>
|
||||
<Flex flexDirection="row">
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<ListedIds listIds={values[i].listIds} setListIds={e => setListIds(i, e)} />
|
||||
|
|
@ -242,7 +243,7 @@ function KeywordEntries() {
|
|||
<Button onClick={() => {
|
||||
values[i].listIds.push("");
|
||||
update();
|
||||
}}>Add ID</Button>
|
||||
}}>{t("keywordNotify.ui.addId")}</Button>
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<ListTypeSelector listType={values[i].listType} setListType={e => setListType(i, e)} />
|
||||
</div>
|
||||
|
|
@ -255,7 +256,7 @@ function KeywordEntries() {
|
|||
return (
|
||||
<>
|
||||
{elements}
|
||||
<div><Button onClick={() => addKeywordEntry(update)}>Add Keyword Entry</Button></div>
|
||||
<div><Button onClick={() => addKeywordEntry(update)}>{t("keywordNotify.ui.addKeywordEntry")}</Button></div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -299,17 +300,17 @@ function DoubleCheckmarkIcon(props: IconProps) {
|
|||
const settings = definePluginSettings({
|
||||
ignoreBots: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Ignore messages from bots",
|
||||
description: t("keywordNotify.settings.ignoreBots"),
|
||||
default: true
|
||||
},
|
||||
amountToKeep: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "Amount of messages to keep in the log",
|
||||
description: t("keywordNotify.settings.amountToKeep"),
|
||||
default: 50
|
||||
},
|
||||
keywords: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "Manage keywords",
|
||||
description: t("keywordNotify.settings.keywords"),
|
||||
component: () => <KeywordEntries />
|
||||
}
|
||||
});
|
||||
|
|
@ -317,7 +318,7 @@ const settings = definePluginSettings({
|
|||
export default definePlugin({
|
||||
name: "KeywordNotify",
|
||||
authors: [EquicordDevs.camila314, EquicordDevs.x3rt],
|
||||
description: "Sends a notification if a given message matches certain keywords or regexes",
|
||||
description: t("keywordNotify.description"),
|
||||
settings,
|
||||
patches: [
|
||||
{
|
||||
|
|
@ -497,14 +498,14 @@ export default definePlugin({
|
|||
keywordTabBar() {
|
||||
return (
|
||||
<TabBar.Item className={classes(tabClass.tab)} id={8}>
|
||||
Keywords
|
||||
{t("keywordNotify.ui.keywords")}
|
||||
</TabBar.Item>
|
||||
);
|
||||
},
|
||||
|
||||
keywordClearButton() {
|
||||
return (
|
||||
<Tooltip text="Clear All">
|
||||
<Tooltip text={t("keywordNotify.ui.clearAll")}>
|
||||
{({ onMouseLeave, onMouseEnter }) => (
|
||||
<Button
|
||||
variant="secondary"
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue