Merge branch 'dev' into immediate-finds

This commit is contained in:
Nuckyz 2024-05-12 20:46:39 -03:00
commit 7e1524362c
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
2 changed files with 51 additions and 21 deletions

View file

@ -24,19 +24,27 @@ interface Diff {
seconds: number; seconds: number;
} }
const DISCORD_KT_DELAY = 1471228.928;
const HiddenVisually = findExportedComponent("HiddenVisually"); const HiddenVisually = findExportedComponent("HiddenVisually");
export default definePlugin({ export default definePlugin({
name: "MessageLatency", name: "MessageLatency",
description: "Displays an indicator for messages that took ≥n seconds to send", description: "Displays an indicator for messages that took ≥n seconds to send",
authors: [Devs.arHSM], authors: [Devs.arHSM],
settings: definePluginSettings({ settings: definePluginSettings({
latency: { latency: {
type: OptionType.NUMBER, type: OptionType.NUMBER,
description: "Threshold in seconds for latency indicator", description: "Threshold in seconds for latency indicator",
default: 2 default: 2
},
detectDiscordKotlin: {
type: OptionType.BOOLEAN,
description: "Detect old Discord Android clients",
default: true
} }
}), }),
patches: [ patches: [
{ {
find: "showCommunicationDisabledStyles", find: "showCommunicationDisabledStyles",
@ -46,6 +54,7 @@ export default definePlugin({
} }
} }
], ],
stringDelta(delta: number) { stringDelta(delta: number) {
const diff: Diff = { const diff: Diff = {
days: Math.round(delta / (60 * 60 * 24)), days: Math.round(delta / (60 * 60 * 24)),
@ -71,15 +80,25 @@ export default definePlugin({
); );
}, ""); }, "");
return [ts || "0 seconds", diff.days === 17 && diff.hours === 1] as const; return ts || "0 seconds";
}, },
latencyTooltipData(message: Message) { latencyTooltipData(message: Message) {
const { latency, detectDiscordKotlin } = this.settings.store;
const { id, nonce } = message; const { id, nonce } = message;
// Message wasn't received through gateway // Message wasn't received through gateway
if (!isNonNullish(nonce)) return null; if (!isNonNullish(nonce)) return null;
const delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000); let isDiscordKotlin = false;
let delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000);
// Old Discord Android clients have a delay of around 17 days
// This is a workaround for that
if (-delta >= DISCORD_KT_DELAY - 86400) { // One day of padding for good measure
isDiscordKotlin = detectDiscordKotlin;
delta += DISCORD_KT_DELAY;
}
// Thanks dziurwa (I hate you) // Thanks dziurwa (I hate you)
// This is when the user's clock is ahead // This is when the user's clock is ahead
@ -87,15 +106,13 @@ export default definePlugin({
const abs = Math.abs(delta); const abs = Math.abs(delta);
const ahead = abs !== delta; const ahead = abs !== delta;
const [stringDelta, isSuspectedKotlinDiscord] = this.stringDelta(abs); const stringDelta = abs >= latency ? this.stringDelta(abs) : null;
const isKotlinDiscord = ahead && isSuspectedKotlinDiscord;
// Also thanks dziurwa // Also thanks dziurwa
// 2 minutes // 2 minutes
const TROLL_LIMIT = 2 * 60; const TROLL_LIMIT = 2 * 60;
const { latency } = this.settings.store;
const fill: Fill = isKotlinDiscord const fill: Fill = isDiscordKotlin
? ["status-positive", "status-positive", "text-muted"] ? ["status-positive", "status-positive", "text-muted"]
: delta >= TROLL_LIMIT || ahead : delta >= TROLL_LIMIT || ahead
? ["text-muted", "text-muted", "text-muted"] ? ["text-muted", "text-muted", "text-muted"]
@ -103,17 +120,24 @@ export default definePlugin({
? ["status-danger", "text-muted", "text-muted"] ? ["status-danger", "text-muted", "text-muted"]
: ["status-warning", "status-warning", "text-muted"]; : ["status-warning", "status-warning", "text-muted"];
return abs >= latency ? { delta: stringDelta, ahead, fill, isKotlinDiscord } : null; return (abs >= latency || isDiscordKotlin) ? { delta: stringDelta, ahead, fill, isDiscordKotlin } : null;
}, },
Tooltip() { Tooltip() {
return ErrorBoundary.wrap(({ message }: { message: Message; }) => { return ErrorBoundary.wrap(({ message }: { message: Message; }) => {
const d = this.latencyTooltipData(message); const d = this.latencyTooltipData(message);
if (!isNonNullish(d)) return null; if (!isNonNullish(d)) return null;
let text: string;
if (!d.delta) {
text = "User is suspected to be on an old Discord Android client";
} else {
text = (d.ahead ? `This user's clock is ${d.delta} ahead.` : `This message was sent with a delay of ${d.delta}.`) + (d.isDiscordKotlin ? " User is suspected to be on an old Discord Android client." : "");
}
return <Tooltip return <Tooltip
text={d.ahead ? `This user's clock is ${d.delta} ahead. ${d.isKotlinDiscord ? "User is suspected to be on an old mobile client" : ""}` : `This message was sent with a delay of ${d.delta}.`} text={text}
position="top" position="top"
> >
{ {
@ -126,8 +150,9 @@ export default definePlugin({
</Tooltip>; </Tooltip>;
}); });
}, },
Icon({ delta, fill, props }: { Icon({ delta, fill, props }: {
delta: string; delta: string | null;
fill: Fill, fill: Fill,
props: { props: {
onClick(): void; onClick(): void;
@ -147,7 +172,7 @@ export default definePlugin({
role="img" role="img"
fill="none" fill="none"
style={{ marginRight: "8px", verticalAlign: -1 }} style={{ marginRight: "8px", verticalAlign: -1 }}
aria-label={delta} aria-label={delta ?? "Old Discord Android client"}
aria-hidden="false" aria-hidden="false"
{...props} {...props}
> >

View file

@ -68,7 +68,6 @@ interface Call {
ringing: string[]; ringing: string[];
} }
const MuteStore = findByProps("isSuppressEveryoneEnabled");
const Notifs = findByProps("makeTextChatNotification"); const Notifs = findByProps("makeTextChatNotification");
const XSLog = new Logger("XSOverlay"); const XSLog = new Logger("XSOverlay");
@ -115,13 +114,13 @@ const settings = definePluginSettings({
}, },
timeout: { timeout: {
type: OptionType.NUMBER, type: OptionType.NUMBER,
description: "Notif duration (secs)", description: "Notification duration (secs)",
default: 1.0, default: 3,
}, },
timeoutPerCharacter: { lengthBasedTimeout: {
type: OptionType.NUMBER, type: OptionType.BOOLEAN,
description: "Duration multiplier per character", description: "Extend duration with message length",
default: 0.5 default: true
}, },
opacity: { opacity: {
type: OptionType.SLIDER, type: OptionType.SLIDER,
@ -262,12 +261,11 @@ function shouldIgnoreForChannelType(channel: Channel) {
} }
function sendMsgNotif(titleString: string, content: string, message: Message) { function sendMsgNotif(titleString: string, content: string, message: Message) {
const timeout = Math.max(settings.store.timeout, content.length * settings.store.timeoutPerCharacter);
fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => { fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => {
const msgData = { const msgData = {
messageType: 1, messageType: 1,
index: 0, index: 0,
timeout, timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout,
height: calculateHeight(content), height: calculateHeight(content),
opacity: settings.store.opacity, opacity: settings.store.opacity,
volume: settings.store.volume, volume: settings.store.volume,
@ -286,7 +284,7 @@ function sendOtherNotif(content: string, titleString: string) {
const msgData = { const msgData = {
messageType: 1, messageType: 1,
index: 0, index: 0,
timeout: settings.store.timeout, timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout,
height: calculateHeight(content), height: calculateHeight(content),
opacity: settings.store.opacity, opacity: settings.store.opacity,
volume: settings.store.volume, volume: settings.store.volume,
@ -313,3 +311,10 @@ function calculateHeight(content: string) {
if (content.length <= 300) return 200; if (content.length <= 300) return 200;
return 250; return 250;
} }
function calculateTimeout(content: string) {
if (content.length <= 100) return 3;
if (content.length <= 200) return 4;
if (content.length <= 300) return 5;
return 6;
}