diff options
-rw-r--r-- | src/plugins/callTimer.ts | 116 | ||||
-rw-r--r-- | src/plugins/callTimer.tsx | 101 |
2 files changed, 101 insertions, 116 deletions
diff --git a/src/plugins/callTimer.ts b/src/plugins/callTimer.ts deleted file mode 100644 index 264e74b..0000000 --- a/src/plugins/callTimer.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 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/>. -*/ - -import { Settings } from "../api/settings"; -import { Devs } from "../utils/constants"; -import definePlugin, { OptionType } from "../utils/types"; -import { FluxDispatcher } from "../webpack/common"; - -export default definePlugin({ - name: "CallTimer", - description: "Adds a timer to vcs", - authors: [Devs.Ven], - - style: void 0 as HTMLStyleElement | undefined, - startTime: 0, - interval: void 0 as NodeJS.Timeout | undefined, - - options: { - format: { - type: OptionType.SELECT, - description: "The timer format. This can be any valid moment.js format", - options: [ - { - label: "30d 23:00:42", - value: "stopwatch", - default: true - }, - { - label: "30d 23h 00m 42s", - value: "human" - } - ] - } - }, - - - formatDuration(ms: number) { - // here be dragons (moment fucking sucks) - const human = Settings.plugins.CallTimer.format === "human"; - - const format = (n: number) => human ? n : n.toString().padStart(2, "0"); - const unit = (s: string) => human ? s : ""; - const delim = human ? " " : ":"; - - // thx copilot - const d = Math.floor(ms / 86400000); - const h = Math.floor((ms % 86400000) / 3600000); - const m = Math.floor(((ms % 86400000) % 3600000) / 60000); - const s = Math.floor((((ms % 86400000) % 3600000) % 60000) / 1000); - - let res = ""; - if (d) res += `${d}d `; - if (h || res) res += `${format(h)}${unit("h")}${delim}`; - if (m || res || !human) res += `${format(m)}${unit("m")}${delim}`; - res += `${format(s)}${unit("s")}`; - - return res; - }, - - setTimer(ms: number) { - if (!this.style) return; - - this.style.textContent = ` - [class*="connection-"] [class*="channel-"]::after { - content: "Connected for ${this.formatDuration(ms)}"; - display: block; - } - `; - }, - - start() { - const style = this.style = document.createElement("style"); - style.id = "VencordCallTimer"; - document.head.appendChild(style); - - this.setTimer(0); - - this.handleRtcConnectionState = this.handleRtcConnectionState.bind(this); - FluxDispatcher.subscribe("RTC_CONNECTION_STATE", this.handleRtcConnectionState); - }, - - handleRtcConnectionState(e: { state: string; }) { - if (e.state === "RTC_CONNECTED" || e.state === "RTC_DISCONNECTED") { - clearInterval(this.interval); - if (e.state === "RTC_CONNECTED") { - this.startTime = Date.now(); - this.interval = setInterval( - () => this.setTimer(Math.round(Date.now() - this.startTime)), - 1000 - ); - } else this.startTime = 0; - this.setTimer(0); - } - }, - - stop() { - FluxDispatcher.unsubscribe("RTC_CONNECTION_STATE", this.handleRtcConnectionState); - this.style?.remove(); - clearInterval(this.interval); - } -}); diff --git a/src/plugins/callTimer.tsx b/src/plugins/callTimer.tsx new file mode 100644 index 0000000..40aa160 --- /dev/null +++ b/src/plugins/callTimer.tsx @@ -0,0 +1,101 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2022 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/>. +*/ + +import { Settings } from "../api/settings"; +import ErrorBoundary from "../components/ErrorBoundary"; +import { Devs } from "../utils/constants"; +import definePlugin, { OptionType } from "../utils/types"; +import { React } from "../webpack/common"; + +function formatDuration(ms: number) { + // here be dragons (moment fucking sucks) + const human = Settings.plugins.CallTimer.format === "human"; + + const format = (n: number) => human ? n : n.toString().padStart(2, "0"); + const unit = (s: string) => human ? s : ""; + const delim = human ? " " : ":"; + + // thx copilot + const d = Math.floor(ms / 86400000); + const h = Math.floor((ms % 86400000) / 3600000); + const m = Math.floor(((ms % 86400000) % 3600000) / 60000); + const s = Math.floor((((ms % 86400000) % 3600000) % 60000) / 1000); + + let res = ""; + if (d) res += `${d}d `; + if (h || res) res += `${format(h)}${unit("h")}${delim}`; + if (m || res || !human) res += `${format(m)}${unit("m")}${delim}`; + res += `${format(s)}${unit("s")}`; + + return res; +} + +export default definePlugin({ + name: "CallTimer", + description: "Adds a timer to vcs", + authors: [Devs.Ven], + + startTime: 0, + interval: void 0 as NodeJS.Timeout | undefined, + + options: { + format: { + type: OptionType.SELECT, + description: "The timer format. This can be any valid moment.js format", + options: [ + { + label: "30d 23:00:42", + value: "stopwatch", + default: true + }, + { + label: "30d 23h 00m 42s", + value: "human" + } + ] + } + }, + + patches: [{ + find: ".renderConnectionStatus=", + replacement: { + match: /(?<=renderConnectionStatus=.+\(\)\.channel,children:)\w/, + replace: "[$&, Vencord.Plugins.plugins.CallTimer.renderTimer(this.props.channel.id)]" + } + }], + renderTimer(channelId: string) { + return <ErrorBoundary noop> + <this.Timer channelId={channelId} /> + </ErrorBoundary>; + }, + + Timer({ channelId }: { channelId: string; }) { + const [time, setTime] = React.useState(0); + const startTime = React.useMemo(() => Date.now(), [channelId]); + + React.useEffect(() => { + const interval = setInterval(() => setTime(Date.now() - startTime), 1000); + return () => { + clearInterval(interval); + setTime(0); + }; + }, [channelId]); + + return <p style={{ margin: 0 }}>Connected for {formatDuration(time)}</p>; + } +}); |