From 6fb9ad714a06592fec4a0790976389ece3672e05 Mon Sep 17 00:00:00 2001 From: Suffocate <70031311+lolsuffocate@users.noreply.github.com> Date: Fri, 31 Jan 2025 01:02:17 +0000 Subject: [PATCH 1/5] New Plugin: CustomMessageTimestamps --- src/plugins/customMessageTimestamps/README.md | 30 +++ src/plugins/customMessageTimestamps/index.tsx | 237 ++++++++++++++++++ src/utils/constants.ts | 8 + 3 files changed, 275 insertions(+) create mode 100644 src/plugins/customMessageTimestamps/README.md create mode 100644 src/plugins/customMessageTimestamps/index.tsx diff --git a/src/plugins/customMessageTimestamps/README.md b/src/plugins/customMessageTimestamps/README.md new file mode 100644 index 00000000000..ce79e0dac73 --- /dev/null +++ b/src/plugins/customMessageTimestamps/README.md @@ -0,0 +1,30 @@ +# CustomMessageTimestamps + +This plugin allows you to customize the timestamps in chat messages and tooltips. + +## Formats + +- Cozy: The timestamp by your username when chat is in cozy mode. +![cozy](https://github.com/user-attachments/assets/a883b21b-346b-4e36-9660-771eff6898c9) + + +- Compact: The timestamp to the left of messages when chat is in compact mode when you send multiple messages in cozy mode. +![compact](https://github.com/user-attachments/assets/9944495f-ff21-4da5-b6f2-0ee0e0a7bf99) + + +- Tooltip: The timestamp in the tooltip when hovering over a message. +![tootip](https://github.com/user-attachments/assets/5fcc6c0e-ad52-4a4e-8660-b373f5020d11) + +## Placeholders + +- **[calendar]**: Replaced with moment.js's calendar time, which dynamically adjusts based on the date. +- **[relative]**: Replaced with moment.js's relative time, such as "4 hours ago". + +## Timeframes for Calendar Time + +- **Same day**: Format for today's dates (e.g., "Today, 2:30 PM"). +- **Last day**: Format for yesterday's dates (e.g., "Yesterday, 2:30 PM"). +- **Last week**: Format for dates within the last week (e.g., "Monday, 2:30 PM"). +- **Same else**: Format for older dates (e.g., "01/01/2024, 2:30 PM"). + +For more information on formatting options, refer to the [Moment.js formatting documentation](https://momentjs.com/docs/#/displaying/format/). diff --git a/src/plugins/customMessageTimestamps/index.tsx b/src/plugins/customMessageTimestamps/index.tsx new file mode 100644 index 00000000000..532d3a60563 --- /dev/null +++ b/src/plugins/customMessageTimestamps/index.tsx @@ -0,0 +1,237 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings, useSettings } from "@api/Settings"; +import { Link } from "@components/Link"; +import { Devs } from "@utils/constants"; +import { useForceUpdater } from "@utils/react"; +import definePlugin, { OptionType } from "@utils/types"; +import { Forms, moment, TextInput, useEffect, useState } from "@webpack/common"; + +type TimeFormat = { + name: string; + description: string; + default: string; + offset: number; +}; +type TimeRowProps = { + id: string; + format: TimeFormat; + onChange: (key: string, value: string) => void; + pluginSettings: any; +}; + +const timeFormats: Record = { + cozyFormat: { + name: "Cozy mode", + description: "Time format to use in messages on cozy mode", + default: "[calendar]", + offset: 0, + }, + compactFormat: { + name: "Compact mode", + description: "Time format on compact mode and hovering messages", + default: "LT", + offset: 0, + }, + tooltipFormat: { + name: "Tooltip", + description: "Time format to use on tooltips", + default: "LLLL • [relative]", + offset: 0, + }, + sameDayFormat: { + name: "Same day", + description: "[calendar] format for today", + default: "HH:mm:ss", + offset: 0, + }, + lastDayFormat: { + name: "Last day", + description: "[calendar] format for yesterday", + default: "[yesterday] HH:mm:ss", + offset: -1000 * 60 * 60 * 24, + }, + lastWeekFormat: { + name: "Last week", + description: "[calendar] format for last week", + default: "ddd DD.MM.YYYY HH:mm:ss", + offset: -1000 * 60 * 60 * 24 * 7, + }, + sameElseFormat: { + name: "Same else", + description: "[calendar] format for older dates", + default: "ddd DD.MM.YYYY HH:mm:ss", + offset: -1000 * 60 * 60 * 24 * 31, + } +}; + +const format = (date: Date, formatTemplate: string): string => { + const mmt = moment(date); + + const sameDayFormat = settings.store?.formats?.sameDayFormat || timeFormats.sameDayFormat.default; + const lastDayFormat = settings.store?.formats?.lastDayFormat || timeFormats.lastDayFormat.default; + const lastWeekFormat = settings.store?.formats?.lastWeekFormat || timeFormats.lastWeekFormat.default; + const sameElseFormat = settings.store?.formats?.sameElseFormat || timeFormats.sameElseFormat.default; + + return mmt.format(formatTemplate) + .replace("calendar", () => mmt.calendar(null, { + sameDay: sameDayFormat, + lastDay: lastDayFormat, + lastWeek: lastWeekFormat, + sameElse: sameElseFormat + })) + .replace("relative", () => mmt.fromNow()); +}; + +const TimeRow = (props: TimeRowProps) => { + const [state, setState] = useState(props.pluginSettings?.[props.id] || props.format.default); + const [preview, setPreview] = useState(""); + + const handleChange = (value: string) => { + setState(value); + props.onChange(props.id, value); + }; + + const updatePreview = () => setPreview(format(new Date(Date.now() + props.format.offset), state || props.format.default)); + + useEffect(() => { + updatePreview(); + const interval = setInterval(updatePreview, 1000); + return () => clearInterval(interval); + }, [state]); + + return ( +
+ {props.format.name} + {props.format.description} + + {preview} +
+ ); +}; + +const settings = definePluginSettings({ + formats: { + type: OptionType.COMPONENT, + description: "Customize the timestamp formats", + component: componentProps => { + const [settingsState, setSettingsState] = useState(useSettings().plugins?.CustomMessageTimestamps?.formats ?? {}); + + const setNewValue = (key: string, value: string) => { + const newSettings = { ...settingsState, [key]: value }; + setSettingsState(newSettings); + componentProps.setValue(newSettings); + }; + + return ( + + {Object.entries(timeFormats).map(([key, value]) => ( +
+ {key === "sameDayFormat" && ( +
+ + Calendar formats + + How to format the [calendar] value if used in the above timestamps. + +
+ )} + +
+ ))} +
+ ); + } + } +}).withPrivateSettings<{ + formats: { + cozyFormat: string; + compactFormat: string; + tooltipFormat: string; + sameDayFormat: string; + lastDayFormat: string; + lastWeekFormat: string; + sameElseFormat: string; + }; +}>(); + +export default definePlugin({ + name: "CustomMessageTimestamps", + description: "Custom timestamps on messages and tooltips", + authors: [ + Devs.Rini, + Devs.nvhhr, + Devs.Suffocate + ], + settings, + settingsAboutComponent: () => ( +
+ How to use: + + Moment.js formatting documentation +

+ Additionally you can use these in your inputs:
+ [calendar] enables dynamic date formatting such + as "Today" or "Yesterday".
+ [relative] gives you times such as "4 hours ago".
+

+
+
+ ), + patches: [{ + find: "#{intl::MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL}", + replacement: [ + { + match: /(\i)\?\(0,\i\.\i\)\((\i),"LT"\):\(0,\i\.\i\)\(\i\)/, + replace: "$self.renderTimestamp($2,$1?'compact':'cozy')", + }, + { + match: /(?<=text:)\(0,\i.\i\)\((\i),"LLLL"\)(?=,)/, + replace: "$self.renderTimestamp($1,'tooltip')", + }, + ] + }], + + renderTimestamp: (date: Date, type: "cozy" | "compact" | "tooltip") => { + const forceUpdater = useForceUpdater(); + let formatTemplate: string; + + switch (type) { + case "cozy": + formatTemplate = settings.use(["formats"]).formats?.cozyFormat || timeFormats.cozyFormat.default; + break; + case "compact": + formatTemplate = settings.use(["formats"]).formats?.compactFormat || timeFormats.compactFormat.default; + break; + case "tooltip": + formatTemplate = settings.use(["formats"]).formats?.tooltipFormat || timeFormats.tooltipFormat.default; + } + + useEffect(() => { + if (formatTemplate.includes("calendar") || formatTemplate.includes("relative")) { + const interval = setInterval(forceUpdater, 30000); + return () => clearInterval(interval); + } + }, []); + + return format(date, formatTemplate); + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e7582591257..a2be9d37175 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -579,6 +579,14 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "jamesbt365", id: 158567567487795200n, }, + nvhhr: { + name: "nvhhr", + id: 165098921071345666n + }, + Suffocate: { + name: "Suffocate", + id: 772601756776923187n + }, } satisfies Record); // iife so #__PURE__ works correctly From d6e93a6d25f71f2432ed135538a54ac21f9536c3 Mon Sep 17 00:00:00 2001 From: Suffocate <70031311+lolsuffocate@users.noreply.github.com> Date: Fri, 31 Jan 2025 01:07:57 +0000 Subject: [PATCH 2/5] Add settings preview --- src/plugins/customMessageTimestamps/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/customMessageTimestamps/README.md b/src/plugins/customMessageTimestamps/README.md index ce79e0dac73..71521045555 100644 --- a/src/plugins/customMessageTimestamps/README.md +++ b/src/plugins/customMessageTimestamps/README.md @@ -27,4 +27,6 @@ This plugin allows you to customize the timestamps in chat messages and tooltips - **Last week**: Format for dates within the last week (e.g., "Monday, 2:30 PM"). - **Same else**: Format for older dates (e.g., "01/01/2024, 2:30 PM"). +![settings](https://github.com/user-attachments/assets/daf4bd95-5a52-4376-9226-2a3afd043368) + For more information on formatting options, refer to the [Moment.js formatting documentation](https://momentjs.com/docs/#/displaying/format/). From 87a4bd9fd1305b50b881bc1aa06a71287ddc98d4 Mon Sep 17 00:00:00 2001 From: Suffocate <70031311+lolsuffocate@users.noreply.github.com> Date: Fri, 31 Jan 2025 01:26:52 +0000 Subject: [PATCH 3/5] Typo --- src/plugins/customMessageTimestamps/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/customMessageTimestamps/README.md b/src/plugins/customMessageTimestamps/README.md index 71521045555..95ed264fb23 100644 --- a/src/plugins/customMessageTimestamps/README.md +++ b/src/plugins/customMessageTimestamps/README.md @@ -8,7 +8,7 @@ This plugin allows you to customize the timestamps in chat messages and tooltips ![cozy](https://github.com/user-attachments/assets/a883b21b-346b-4e36-9660-771eff6898c9) -- Compact: The timestamp to the left of messages when chat is in compact mode when you send multiple messages in cozy mode. +- Compact: The timestamp to the left of messages when chat is in compact mode and when you send multiple messages in cozy mode. ![compact](https://github.com/user-attachments/assets/9944495f-ff21-4da5-b6f2-0ee0e0a7bf99) From 2e7db45eb9accf5336acfa809bc601735b2bc305 Mon Sep 17 00:00:00 2001 From: Suffocate <70031311+lolsuffocate@users.noreply.github.com> Date: Fri, 31 Jan 2025 02:27:22 +0000 Subject: [PATCH 4/5] Make compatible with reply timestamps --- src/plugins/replyTimestamp/index.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/plugins/replyTimestamp/index.tsx b/src/plugins/replyTimestamp/index.tsx index 0be5dfec276..41713da9ace 100644 --- a/src/plugins/replyTimestamp/index.tsx +++ b/src/plugins/replyTimestamp/index.tsx @@ -44,14 +44,7 @@ function ReplyTimestamp({ compact={DateUtils.isSameDay(refTimestamp, baseTimestamp)} timestamp={refTimestamp} isInline={false} - > - [ - {DateUtils.isSameDay(refTimestamp, baseTimestamp) - ? DateUtils.dateFormat(refTimestamp, "LT") - : DateUtils.calendarFormat(refTimestamp) - } - ] - + /> ); } From c39c652c8b8629899a1a97f60c197fd1ff241a04 Mon Sep 17 00:00:00 2001 From: Suffocate <70031311+lolsuffocate@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:55:05 +0000 Subject: [PATCH 5/5] Remove unused component --- src/plugins/replyTimestamp/index.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/plugins/replyTimestamp/index.tsx b/src/plugins/replyTimestamp/index.tsx index 41713da9ace..ae7940c8cde 100644 --- a/src/plugins/replyTimestamp/index.tsx +++ b/src/plugins/replyTimestamp/index.tsx @@ -9,16 +9,8 @@ import "./style.css"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; import { DateUtils, Timestamp } from "@webpack/common"; import type { Message } from "discord-types/general"; -import type { HTMLAttributes } from "react"; - -const MessageClasses = findByPropsLazy("separator", "latin24CompactTimeStamp"); - -function Sep(props: HTMLAttributes) { - return ; -} const enum ReferencedMessageState { LOADED = 0,