Plugin

ShowTimeoutDuration

Shows how much longer a user's timeout will last, either in the timeout icon tooltip or next to it

Servers Utility
index.tsx
Download

Source

src/plugins/showTimeoutDuration/index.tsx
1/*
2 * FiveCord — a Discord client mod
3 * Copyright (c) 2025 FiveCord
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7import "./styles.css";
8
9import { definePluginSettings } from "@api/Settings";
10import ErrorBoundary from "@components/ErrorBoundary";
11import { TooltipContainer } from "@components/TooltipContainer";
12import { Devs } from "@utils/constants";
13import { getIntlMessage } from "@utils/discord";
14import { canonicalizeMatch } from "@utils/patches";
15import definePlugin, { OptionType } from "@utils/types";
16import { Message } from "@vencord/discord-types";
17import { findComponentLazy } from "@webpack";
18import { ChannelStore, GuildMemberStore, Text } from "@webpack/common";
19import { ReactNode } from "react";
20
21const countDownFilter = canonicalizeMatch(/#{intl::MAX_AGE_NEVER}/);
22const CountDown = findComponentLazy(m => m.prototype?.render && countDownFilter.test(m.prototype.render.toString()));
23
24const enum DisplayStyle {
25 Tooltip = "tooltip",
26 Inline = "ssalggnikool"
27}
28
29const settings = definePluginSettings({
30 displayStyle: {
31 description: "How to display the timeout duration",
32 type: OptionType.SELECT,
33 options: [
34 { label: "In the Tooltip", value: DisplayStyle.Tooltip },
35 { label: "Next to the timeout icon", value: DisplayStyle.Inline, default: true },
36 ],
37 }
38});
39
40function renderTimeout(message: Message, inline: boolean) {
41 const guildId = ChannelStore.getChannel(message.channel_id)?.guild_id;
42 if (!guildId) return null;
43
44 const member = GuildMemberStore.getMember(guildId, message.author.id);
45 if (!member?.communicationDisabledUntil) return null;
46
47 const countdown = () => (
48 <CountDown
49 deadline={new Date(member.communicationDisabledUntil!)}
50 showUnits
51 stopAtOneSec
52 />
53 );
54
55 getIntlMessage("GUILD_ENABLE_COMMUNICATION_TIME_REMAINING", {
56 username: message.author.username,
57 countdown
58 });
59
60 return inline
61 ? countdown()
62 : getIntlMessage("GUILD_ENABLE_COMMUNICATION_TIME_REMAINING", {
63 username: message.author.username,
64 countdown
65 });
66}
67
68export default definePlugin({
69 name: "ShowTimeoutDuration",
70 description: "Shows how much longer a user&#039;s timeout will last, either in the timeout icon tooltip or next to it",
71 tags: ["Servers", "Utility"],
72 authors: [Devs.Ven, Devs.Sqaaakoi],
73
74 settings,
75
76 patches: [
77 {
78 find: "#{intl::GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY}",
79 replacement: [
80 {
81 match: /\i\.\i,{(text:.{0,30}#{intl::GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY}\))/,
82 replace: "$self.TooltipWrapper,{message:arguments[0].message,$1"
83 }
84 ]
85 }
86 ],
87
88 TooltipWrapper: ErrorBoundary.wrap(({ message, children, text }: { message: Message; children: ReactNode; text: ReactNode; }) => {
89 if (settings.store.displayStyle === DisplayStyle.Tooltip)
90 return <TooltipContainer text={renderTimeout(message, false)}>{children}</TooltipContainer>;
91
92 return (
93 <div className="vc-std-wrapper">
94 <TooltipContainer text={text}>{children}</TooltipContainer>
95 <Text variant="text-md/normal" color="status-danger">
96 {renderTimeout(message, true)} timeout remaining
97 </Text>
98 </div>
99 );
100 }, { noop: true })
101});
102