Merge remote-tracking branch 'upstream/dev'

This commit is contained in:
thororen 2024-05-08 22:16:37 -04:00
commit 75433e88d9
7 changed files with 140 additions and 11 deletions

View file

@ -156,7 +156,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: <div>

View file

@ -6,17 +6,18 @@
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 { 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<string, string>;
waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => Classes = m);
const settings = definePluginSettings({
disableFade: {
@ -124,12 +125,19 @@ 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 (
<ErrorBoundary fallback={() => props.children as any}>
<Layer {...props} />
</ErrorBoundary>
);
if (!FocusLock || !ComponentDispatch || !Classes) {
new Logger("BetterSettings").error("Failed to find some components");
return props.children;
}
return <Layer {...props} />;
},
wrapMenu(list: SettingsEntry[]) {

View file

@ -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 {

View file

@ -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)

View file

@ -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 = () => (
<CountDown
deadline={new Date(member.communicationDisabledUntil!)}
showUnits
stopAtOneSec
/>
);
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 (
<>
<Forms.FormText>{i18n.Messages.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY}</Forms.FormText>
<Forms.FormText className={Margins.top8}>
{renderTimeout(message, false)}
</Forms.FormText>
</>
);
}, { noop: true }),
TooltipWrapper: ErrorBoundary.wrap(({ vcProps: { message }, ...tooltipProps }: { vcProps: { message: Message; }; }) => {
return (
<div className="vc-std-wrapper">
<Tooltip {...tooltipProps as any} />
<Text variant="text-md/normal" color="status-danger">
{renderTimeout(message, true)} timeout remaining
</Text>
</div>
);
}, { noop: true })
});

View file

@ -0,0 +1,4 @@
.vc-std-wrapper {
display: flex;
align-items: center;
}

View file

@ -28,9 +28,12 @@ export default definePlugin({
<a
className="vc-voice-download"
href={src}
download="voice-message.ogg"
onClick={e => 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)
}
>
<this.Icon />
</a>