Plugin

CallTimer

Adds a timer to vcs

Voice Utility
index.tsx
Download

Source

src/plugins/callTimer/index.tsx
1import { definePluginSettings } from "@api/Settings";
2import ErrorBoundary from "@components/ErrorBoundary";
3import { Devs } from "@utils/constants";
4import { useTimer } from "@utils/react";
5import definePlugin, { OptionType } from "@utils/types";
6import { React } from "@webpack/common";
7
8import alignedChatInputFix from "./alignedChatInputFix.css?managed";
9
10const settings = definePluginSettings({
11 format: {
12 type: OptionType.SELECT,
13 description: "The timer format. This can be any valid moment.js format",
14 options: [
15 {
16 label: "30d 23:00:42",
17 value: "stopwatch",
18 default: true
19 },
20 {
21 label: "30d 23h 00m 42s",
22 value: "human"
23 }
24 ]
25 }
26});
27
28function formatDuration(ms: number) {
29 // here be dragons (moment fucking sucks)
30 const human = settings.store.format === "human";
31
32 const format = (n: number) => human ? n : n.toString().padStart(2, "0");
33 const unit = (s: string) => human ? s : "";
34 const delim = human ? " " : ":";
35
36 // thx copilot
37 const d = Math.floor(ms / 86400000);
38 const h = Math.floor((ms % 86400000) / 3600000);
39 const m = Math.floor(((ms % 86400000) % 3600000) / 60000);
40 const s = Math.floor((((ms % 86400000) % 3600000) % 60000) / 1000);
41
42 let res = "";
43 if (d) res += `${d}d `;
44 if (h || res) res += `${format(h)}${unit("h")}${delim}`;
45 if (m || res || !human) res += `${format(m)}${unit("m")}${delim}`;
46 res += `${format(s)}${unit("s")}`;
47
48 return res;
49}
50
51
52
53export default definePlugin({
54 name: "CallTimer",
55 description: "Adds a timer to vcs",
56 tags: ["Voice", "Utility"],
57 authors: [Devs.Ven],
58 managedStyle: alignedChatInputFix,
59 settings,
60
61 startTime: 0,
62 interval: void 0 as NodeJS.Timeout | undefined,
63
64 patches: [
65 {
66 find: '"RTCConnectionMenu"',
67 replacement: {
68 match: /("RTCConnectionMenu".{0,200}?lineClamp:1,children:)(\i)(?=,|}\))/,
69 replace: "$1[$2,$self.renderTimer({ channelId: this?.props?.channel?.id })]"
70 }
71 },
72 ],
73
74 renderTimer: ErrorBoundary.wrap(({ channelId }: { channelId: string; }) => {
75 const time = useTimer({ deps: [channelId] });
76
77 return (
78 <p style={{ margin: 0, fontFamily: "var(--font-code)" }}>
79 {formatDuration(time)}
80 </p>
81 );
82 }, { noop: true }),
83});
84