This commit is contained in:
rushiiMachine 2024-06-23 12:43:55 -07:00
parent 33058f6703
commit a8cdeb10bf
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
3 changed files with 93 additions and 79 deletions

View file

@ -8,13 +8,10 @@ import * as DataStore from "@api/DataStore";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
import { React, SearchableSelect, Text, Toasts, UserStore } from "@webpack/common"; import { SearchableSelect, Text, Toasts, useEffect, UserStore, useState } from "@webpack/common";
import { Message, User } from "discord-types/general"; import { Message, User } from "discord-types/general";
import settings from "./settings"; import settings from "./settings";
const classNames = findByPropsLazy("customStatusSection");
import { CogWheel, DeleteIcon } from "@components/Icons"; import { CogWheel, DeleteIcon } from "@components/Icons";
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent"; import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
import { makeLazy } from "@utils/lazy"; import { makeLazy } from "@utils/lazy";
@ -22,6 +19,9 @@ import { classes } from "@utils/misc";
import { useForceUpdater } from "@utils/react"; import { useForceUpdater } from "@utils/react";
import { API_URL, DATASTORE_KEY, getAllTimezones, getTimeString, getUserTimezone, TimezoneDB } from "./utils"; import { API_URL, DATASTORE_KEY, getAllTimezones, getTimeString, getUserTimezone, TimezoneDB } from "./utils";
const classNames = findByPropsLazy("customStatusSection");
const styles = findByPropsLazy("timestampInline"); const styles = findByPropsLazy("timestampInline");
const useTimezones = makeLazy(getAllTimezones); const useTimezones = makeLazy(getAllTimezones);
@ -30,58 +30,59 @@ export default definePlugin({
settings, settings,
name: "Timezones", name: "Timezones",
description: "Allows you to see and set the timezones of other users.", description: "Set and display the local times of you and other users via TimezoneDB",
authors: [Devs.mantikafasi, Devs.Arjix], authors: [Devs.rushii, Devs.mantikafasi, Devs.Aria, Devs.Arjix],
commands: [ commands: [
{ {
name: "timezone", name: "timezone",
description: "Sends link to a website that shows timezone string, useful if you want to know your friends timezone", description: "Sends a link to a utility website that shows your current timezone identifier",
execute: () => { execute: () => ({ content: "https://gh.lewisakura.moe/timezone/" }),
return { content: "https://gh.lewisakura.moe/timezone/" }; },
}
}
], ],
// TODO: show button to authorize tzdb and manage public tz
settingsAboutComponent: () => { settingsAboutComponent: () => {
const href = `${API_URL}?client_mod=${encodeURIComponent(VENCORD_USER_AGENT)}`; const href = `${API_URL}?client_mod=${encodeURIComponent(VENCORD_USER_AGENT)}`;
return ( return (
<Text variant="text-md/normal"> <Text variant="text-md/normal">
A plugin that displays the local time for specific users using their timezone. <br /> <br/>
Timezones can either be set manually or fetched automatically from the <a href={href}>TimezoneDB</a> This plugin supports setting your own Timezone publicly for others to fetch and display via <a href={href}>TimezoneDB</a>.
You can override other users' timezones locally if they haven't set their own.
</Text> </Text>
); );
}, },
patches: [ patches: [
// {
// find: "copyMetaData:\"User Tag\"",
// replacement: {
// match: /return(\(0.+?}\)}\)]}\))}/,
// replace: "return [$1, $self.getProfileTimezonesComponent(arguments[0])] }",
// },
// },
{ {
find: "copyMetaData:\"User Tag\"", // TODO: fix this
replacement: {
match: /return(\(0,.\.jsx\)\(.\.default,{className:.+?}\)]}\)}\))/,
replace: "return [$1, $self.getProfileTimezonesComponent(arguments[0])]"
},
},
{
// thank you https://github.com/Syncxv/vc-timezones/blob/master/index.tsx for saving me from painful work // thank you https://github.com/Syncxv/vc-timezones/blob/master/index.tsx for saving me from painful work
find: ".badgesContainer,", find: ".badgesContainer,{",
replacement: { replacement: {
match: /id:\(0,\i\.getMessageTimestampId\)\(\i\),timestamp.{1,50}}\),/, match: /id:\(0,\i\.getMessageTimestampId\)\(\i\),timestamp.{1,50}}\),/,
replace: "$&,$self.getTimezonesComponent(arguments[0])," replace: "$&,$self.getTimezonesComponent(arguments[0]),",
} },
} },
], ],
// TODO: make this not ugly (port vc-timezones plugin)
getProfileTimezonesComponent: ({ user }: { user: User; }) => { getProfileTimezonesComponent: ({ user }: { user: User; }) => {
const { preference, showTimezonesInProfile } = settings.use(["preference", "showTimezonesInProfile"]); const { preference, showInProfile } = settings.use(["preference", "showInProfile"]);
const [timezone, setTimezone] = React.useState<string | undefined>(); const [timezone, setTimezone] = useState<string | undefined>();
const [isInEditMode, setIsInEditMode] = React.useState(false); const [isInEditMode, setIsInEditMode] = useState(false);
const [timezones, setTimezones] = React.useState<string[]>([]); const [timezones, setTimezones] = useState<string[]>([]);
const forceUpdate = useForceUpdater(); const forceUpdate = useForceUpdater();
React.useEffect(() => { useEffect(() => {
useTimezones().then(setTimezones); useTimezones().then(setTimezones);
getUserTimezone(user.id, preference).then(tz => setTimezone(tz)); getUserTimezone(user.id, preference).then(tz => setTimezone(tz));
@ -91,7 +92,7 @@ export default definePlugin({
return () => clearInterval(interval); return () => clearInterval(interval);
}, [preference]); }, [preference]);
if (!showTimezonesInProfile) if (!showInProfile)
return null; return null;
return ( return (
@ -103,7 +104,7 @@ export default definePlugin({
...(isInEditMode ? { ...(isInEditMode ? {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
} : {}) } : {}),
}} }}
> >
{!isInEditMode && {!isInEditMode &&
@ -114,7 +115,7 @@ export default definePlugin({
Toasts.show({ Toasts.show({
type: Toasts.Type.MESSAGE, type: Toasts.Type.MESSAGE,
message: timezone, message: timezone,
id: Toasts.genId() id: Toasts.genId(),
}); });
} }
}} }}
@ -129,7 +130,9 @@ export default definePlugin({
placeholder="Pick a timezone" placeholder="Pick a timezone"
options={timezones.map(tz => ({ label: tz, value: tz }))} options={timezones.map(tz => ({ label: tz, value: tz }))}
value={timezone ? { label: timezone, value: timezone } : undefined} value={timezone ? { label: timezone, value: timezone } : undefined}
onChange={value => { setTimezone(value); }} onChange={value => {
setTimezone(value);
}}
/> />
</span> </span>
)} )}
@ -141,10 +144,10 @@ export default definePlugin({
alignItems: "center", alignItems: "center",
justifyContent: "space-around", justifyContent: "space-around",
width: "60%", width: "60%",
marginTop: "5%" marginTop: "5%",
} : { } : {
marginLeft: "2%", marginLeft: "2%",
display: "flex" display: "flex",
}} }}
> >
<CogWheel <CogWheel
@ -168,7 +171,7 @@ export default definePlugin({
Toasts.show({ Toasts.show({
type: Toasts.Type.SUCCESS, type: Toasts.Type.SUCCESS,
message: "Timezone set!", message: "Timezone set!",
id: Toasts.genId() id: Toasts.genId(),
}); });
setIsInEditMode(false); setIsInEditMode(false);
@ -177,7 +180,7 @@ export default definePlugin({
Toasts.show({ Toasts.show({
type: Toasts.Type.FAILURE, type: Toasts.Type.FAILURE,
message: "Something went wrong, please try again later.", message: "Something went wrong, please try again later.",
id: Toasts.genId() id: Toasts.genId(),
}); });
}); });
}} }}
@ -188,7 +191,12 @@ export default definePlugin({
{isInEditMode && {isInEditMode &&
<DeleteIcon <DeleteIcon
style={{ cursor: "pointer", padding: "2px", border: "2px solid grey", borderRadius: "50px" }} style={{
cursor: "pointer",
padding: "2px",
border: "2px solid grey",
borderRadius: "50px",
}}
onClick={() => { onClick={() => {
DataStore.update(DATASTORE_KEY, (oldValue: TimezoneDB | undefined) => { DataStore.update(DATASTORE_KEY, (oldValue: TimezoneDB | undefined) => {
oldValue = oldValue || {}; oldValue = oldValue || {};
@ -198,7 +206,7 @@ export default definePlugin({
Toasts.show({ Toasts.show({
type: Toasts.Type.SUCCESS, type: Toasts.Type.SUCCESS,
message: "Timezone removed!", message: "Timezone removed!",
id: Toasts.genId() id: Toasts.genId(),
}); });
setIsInEditMode(false); setIsInEditMode(false);
setTimezone(await getUserTimezone(user.id, preference)); setTimezone(await getUserTimezone(user.id, preference));
@ -207,7 +215,7 @@ export default definePlugin({
Toasts.show({ Toasts.show({
type: Toasts.Type.FAILURE, type: Toasts.Type.FAILURE,
message: "Something went wrong, please try again later.", message: "Something went wrong, please try again later.",
id: Toasts.genId() id: Toasts.genId(),
}); });
}); });
}} }}
@ -222,26 +230,28 @@ export default definePlugin({
}, },
getTimezonesComponent: ({ message }: { message: Message; }) => { getTimezonesComponent: ({ message }: { message: Message; }) => {
console.log(message);
const { showTimezonesInChat, preference } = settings.use(["preference", "showTimezonesInChat"]); const { showInChat, preference } = settings.use(["preference", "showInChat"]);
const [timezone, setTimezone] = React.useState<string | undefined>(); const [timeString, setTimeString] = useState<string>();
React.useEffect(() => { if (!showInChat || message.author.id === UserStore.getCurrentUser()?.id)
if (!showTimezonesInChat) return;
getUserTimezone(message.author.id, preference).then(tz => setTimezone(tz));
}, [showTimezonesInChat, preference]);
if (!showTimezonesInChat || message.author.id === UserStore.getCurrentUser()?.id)
return null; return null;
return ( useEffect(() => {
if (!showInChat) return;
(async function() {
const timezone = await getUserTimezone(message.author.id, preference);
const timestamp = (message.timestamp as unknown) as Date; // discord-types is outdated
setTimeString(timezone && "• " + getTimeString(timezone, timestamp));
})();
}, [showInChat, preference]);
return <>
<span className={classes(styles.timestampInline, styles.timestamp)}> <span className={classes(styles.timestampInline, styles.timestamp)}>
{ {timeString}
timezone && "• " + getTimeString(timezone, </span>
/* message.timestamp is actually Date but as discord-types is outdated I had to do this */ </>;
((message.timestamp as unknown) as Date)) },
}
</span>);
}
}); });

View file

@ -46,14 +46,14 @@ export default definePluginSettings({
], ],
default: CustomTimezonePreference.Secondary, default: CustomTimezonePreference.Secondary,
}, },
showTimezonesInChat: { showInChat: {
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
description: "Show timezones in chat", description: "Show local time on messages in chat",
default: true, default: true,
}, },
showTimezonesInProfile: { showInProfile: {
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
description: "Show timezones in profile", description: "Show timezones in user profiles",
default: true, default: true,
}, },
}); });

View file

@ -6,13 +6,13 @@
import * as DataStore from "@api/DataStore"; import * as DataStore from "@api/DataStore";
import { findStoreLazy } from "@webpack"; import { findStoreLazy } from "@webpack";
export const DATASTORE_KEY = "plugins.timezones.savedTimezones";
import { debounce } from "@shared/debounce"; import { debounce } from "@shared/debounce";
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent"; import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
import { CustomTimezonePreference } from "./settings"; import { CustomTimezonePreference } from "./settings";
export const DATASTORE_KEY = "plugins.timezones.savedTimezones";
export interface TimezoneDB { export interface TimezoneDB {
[userId: string]: string; [userId: string]: string;
} }
@ -25,8 +25,13 @@ const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore");
export function getTimeString(timezone: string, timestamp = new Date()): string { export function getTimeString(timezone: string, timestamp = new Date()): string {
try { try {
const locale = UserSettingsProtoStore.settings.localization.locale.value; const locale = UserSettingsProtoStore.settings.localization.locale.value;
return new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "numeric", timeZone: timezone }).format(timestamp); // we hate javascript return new Intl.DateTimeFormat(locale, {
hour: "numeric",
minute: "numeric",
timeZone: timezone,
}).format(timestamp); // we hate javascript
} catch (e) { } catch (e) {
// TODO: log error
return "Error"; // incase it gets invalid timezone from api, probably not gonna happen but if it does this will prevent discord from crashing return "Error"; // incase it gets invalid timezone from api, probably not gonna happen but if it does this will prevent discord from crashing
} }
} }
@ -42,7 +47,7 @@ async function bulkFetchTimezones(ids: string[]): Promise<TimezoneDB | undefined
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-User-Agent": VENCORD_USER_AGENT "X-User-Agent": VENCORD_USER_AGENT,
}, },
body: JSON.stringify(ids), body: JSON.stringify(ids),
}); });
@ -106,15 +111,14 @@ export function getUserTimezone(discordID: string, strategy: CustomTimezonePrefe
}); });
} }
const gist = "e321f856f98676505efb90aad82feff1"; const timezonesLink = "https://gist.githubusercontent.com/ArjixWasTaken/e321f856f98676505efb90aad82feff1/raw/91034ee32eff93a7cb62d10702f6b1d01e0309e6/timezones.json";
const revision = "91034ee32eff93a7cb62d10702f6b1d01e0309e6";
const timezonesLink = `https://gist.githubusercontent.com/ArjixWasTaken/${gist}/raw/${revision}/timezones.json`;
export const getAllTimezones = async (): Promise<string[]> => { export const getAllTimezones = async (): Promise<string[]> => {
if (typeof Intl !== "undefined" && "supportedValuesOf" in Intl) { if (typeof Intl !== "undefined" && "supportedValuesOf" in Intl) {
try { try {
return Intl.supportedValuesOf("timeZone"); return Intl.supportedValuesOf("timeZone");
} catch { } } catch {
}
} }
return await fetch(timezonesLink).then(tzs => tzs.json()); return await fetch(timezonesLink).then(tzs => tzs.json());