From b1cc67a860fe2b6546900797dfa49a936b97f7dd Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 23:42:04 +0200 Subject: [PATCH 1/7] fix(BetterSettings): do not catch errors of other ui --- src/plugins/betterSettings/index.tsx | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 7d81c6f5..5836734e 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -6,8 +6,8 @@ import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common"; @@ -124,12 +124,23 @@ export default definePlugin({ } ], + // This is the very outer layer of the entire ui, so we can't wrap this in an ErrorBoundary + // without possibly also catching unrelated errors of children. + // + // Thus, we sanity check webpack modules & do this really hacky try catch to hopefully prevent hard crashes if something goes wrong. + // try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but + // not in children Layer(props: LayerProps) { - return ( - props.children as any}> - - - ); + try { + if (!FocusLock || !ComponentDispatch) + throw new Error("Failed to fetch some webpack modules"); + + return Layer(props); + } catch (e) { + new Logger("BetterSettings").error("Failed to render Layer", e); + } + + return props.children; }, wrapMenu(list: SettingsEntry[]) { From 025193533d1baf0e37df236cbda97f2f539e8b20 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 23:49:47 +0200 Subject: [PATCH 2/7] VoiceDownload: fix doing nothing on discord desktop app --- src/plugins/voiceDownload/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx index 8586b9f9..571c3d0e 100644 --- a/src/plugins/voiceDownload/index.tsx +++ b/src/plugins/voiceDownload/index.tsx @@ -28,9 +28,12 @@ export default definePlugin({ e.stopPropagation()} aria-label="Download voice message" + {...IS_DISCORD_DESKTOP + ? { target: "_blank" } // open externally + : { download: "voice-message.ogg" } // download directly (not supported on discord desktop) + } > From 6bd0898efe489901178e45012a586c991947a068 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 23:52:28 +0200 Subject: [PATCH 3/7] fix(SupportHelper): dont flag vencord web as externally updated --- src/plugins/_core/supportHelper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index 63f32cbd..c7377833 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -139,7 +139,7 @@ ${makeCodeblock(enabledPlugins.join(", "))} const roles = GuildMemberStore.getSelfMember(VENCORD_GUILD_ID)?.roles; if (!roles || TrustedRolesIds.some(id => roles.includes(id))) return; - if (IS_UPDATER_DISABLED) { + if (!IS_WEB && IS_UPDATER_DISABLED) { return Alerts.show({ title: "Hold on!", body:
From 840a8f1fdd6e9f16c8ac44a2f21b09fb873a141f Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 18:37:27 -0300 Subject: [PATCH 4/7] CrashHandler: Increment timeout for trying to recover --- src/plugins/crashHandler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index f8c76d7f..10053021 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -104,7 +104,7 @@ export default definePlugin({ shouldAttemptRecover = false; // This is enough to avoid a crash loop - setTimeout(() => shouldAttemptRecover = true, 500); + setTimeout(() => shouldAttemptRecover = true, 1000); } catch { } try { From a2acce55c34ddf3e0eafdfe7ecf747dcee859fb5 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:04:03 +0200 Subject: [PATCH 5/7] BetterSettings: fix error handling crashing in some niche cases --- src/plugins/betterSettings/index.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 5836734e..c9bf070f 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -131,16 +131,11 @@ export default definePlugin({ // try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but // not in children Layer(props: LayerProps) { - try { - if (!FocusLock || !ComponentDispatch) - throw new Error("Failed to fetch some webpack modules"); - - return Layer(props); - } catch (e) { - new Logger("BetterSettings").error("Failed to render Layer", e); + if (!FocusLock || !ComponentDispatch) { + new Logger("BetterSettings").error("Failed to find some components"); } - return props.children; + return ; }, wrapMenu(list: SettingsEntry[]) { From 251ee32e01ab70a6ec1c6a6a003c89682edca21b Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:10:07 +0200 Subject: [PATCH 6/7] new plugin ShowTimeoutDuration ~ shows how much longer a user's timeout will last --- src/plugins/showTimeoutDuration/README.md | 8 ++ src/plugins/showTimeoutDuration/index.tsx | 106 +++++++++++++++++++++ src/plugins/showTimeoutDuration/styles.css | 4 + 3 files changed, 118 insertions(+) create mode 100644 src/plugins/showTimeoutDuration/README.md create mode 100644 src/plugins/showTimeoutDuration/index.tsx create mode 100644 src/plugins/showTimeoutDuration/styles.css diff --git a/src/plugins/showTimeoutDuration/README.md b/src/plugins/showTimeoutDuration/README.md new file mode 100644 index 00000000..13780247 --- /dev/null +++ b/src/plugins/showTimeoutDuration/README.md @@ -0,0 +1,8 @@ +# ShowTimeoutDuration + +Displays how much longer a user's timeout will last. +Either in the timeout icon tooltip, or next to it, configurable via settings! + +![indicator in tooltip](https://github.com/Vendicated/Vencord/assets/45497981/606588a3-2646-40d9-8800-b6307f650136) + +![indicator next to timeout icon](https://github.com/Vendicated/Vencord/assets/45497981/ab9d2101-0fdc-4143-9310-9488f056eeee) diff --git a/src/plugins/showTimeoutDuration/index.tsx b/src/plugins/showTimeoutDuration/index.tsx new file mode 100644 index 00000000..f57ee0fc --- /dev/null +++ b/src/plugins/showTimeoutDuration/index.tsx @@ -0,0 +1,106 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./styles.css"; + +import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import { Margins } from "@utils/margins"; +import definePlugin, { OptionType } from "@utils/types"; +import { findComponentLazy } from "@webpack"; +import { ChannelStore, Forms, GuildMemberStore, i18n, Text, Tooltip } from "@webpack/common"; +import { Message } from "discord-types/general"; + +const CountDown = findComponentLazy(m => m.prototype?.render?.toString().includes(".MAX_AGE_NEVER")); + +const enum DisplayStyle { + Tooltip = "tooltip", + Inline = "ssalggnikool" +} + +const settings = definePluginSettings({ + displayStyle: { + description: "How to display the timeout duration", + type: OptionType.SELECT, + restartNeeded: true, + options: [ + { label: "In the Tooltip", value: DisplayStyle.Tooltip }, + { label: "Next to the timeout icon", value: DisplayStyle.Inline, default: true }, + ], + } +}); + +function renderTimeout(message: Message, inline: boolean) { + const guildId = ChannelStore.getChannel(message.channel_id)?.guild_id; + if (!guildId) return null; + + const member = GuildMemberStore.getMember(guildId, message.author.id); + if (!member?.communicationDisabledUntil) return null; + + const countdown = () => ( + + ); + + return inline + ? countdown() + : i18n.Messages.GUILD_ENABLE_COMMUNICATION_TIME_REMAINING.format({ + username: message.author.username, + countdown + }); +} + +export default definePlugin({ + name: "ShowTimeoutDuration", + description: "Shows how much longer a user's timeout will last, either in the timeout icon tooltip or next to it", + authors: [Devs.Ven], + + settings, + + patches: [ + { + find: ".GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY", + replacement: [ + { + match: /(\i)\.Tooltip,{(text:.{0,30}\.Messages\.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY)/, + get replace() { + if (settings.store.displayStyle === DisplayStyle.Inline) + return "$self.TooltipWrapper,{vcProps:arguments[0],$2"; + + return "$1.Tooltip,{text:$self.renderTimeoutDuration(arguments[0])"; + } + } + ] + } + ], + + renderTimeoutDuration: ErrorBoundary.wrap(({ message }: { message: Message; }) => { + return ( + <> + {i18n.Messages.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY} + + {renderTimeout(message, false)} + + + ); + }, { noop: true }), + + TooltipWrapper: ErrorBoundary.wrap(({ vcProps: { message }, ...tooltipProps }: { vcProps: { message: Message; }; }) => { + return ( +
+ + + + {renderTimeout(message, true)} timeout remaining + +
+ ); + }, { noop: true }) +}); diff --git a/src/plugins/showTimeoutDuration/styles.css b/src/plugins/showTimeoutDuration/styles.css new file mode 100644 index 00000000..70a826e1 --- /dev/null +++ b/src/plugins/showTimeoutDuration/styles.css @@ -0,0 +1,4 @@ +.vc-std-wrapper { + display: flex; + align-items: center; +} From 14e68d9a246006122d2b1a4e2a17a53d955cbbca Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:12:11 +0200 Subject: [PATCH 7/7] im the dumbest dumdum --- src/plugins/betterSettings/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index c9bf070f..5064bd53 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -9,14 +9,15 @@ import { classNameFactory } from "@api/Styles"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { waitFor } from "@webpack"; import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common"; import type { HTMLAttributes, ReactElement } from "react"; type SettingsEntry = { section: string, label: string; }; const cl = classNameFactory(""); -const Classes = findByPropsLazy("animating", "baseLayer", "bg", "layer", "layers"); +let Classes: Record; +waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => Classes = m); const settings = definePluginSettings({ disableFade: { @@ -131,8 +132,9 @@ export default definePlugin({ // try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but // not in children Layer(props: LayerProps) { - if (!FocusLock || !ComponentDispatch) { + if (!FocusLock || !ComponentDispatch || !Classes) { new Logger("BetterSettings").error("Failed to find some components"); + return props.children; } return ;