From 88ad4f1b0597a06695aae4166fb8ac1024f31c4c Mon Sep 17 00:00:00 2001 From: V Date: Sat, 15 Apr 2023 04:42:18 +0200 Subject: [PATCH] SendTimestamps (#891) Co-authored-by: Tyler Flowers --- src/plugins/gifPaste.ts | 4 +- .../components/EncryptionModal.tsx | 5 +- src/plugins/quickMention.tsx | 5 +- src/plugins/sendTimestamps/index.tsx | 219 ++++++++++++++++++ src/plugins/sendTimestamps/styles.css | 48 ++++ src/utils/constants.ts | 4 + src/utils/discord.ts | 12 + src/webpack/common/utils.ts | 1 + 8 files changed, 288 insertions(+), 10 deletions(-) create mode 100644 src/plugins/sendTimestamps/index.tsx create mode 100644 src/plugins/sendTimestamps/styles.css diff --git a/src/plugins/gifPaste.ts b/src/plugins/gifPaste.ts index 9b6e8a99b..fa64f304f 100644 --- a/src/plugins/gifPaste.ts +++ b/src/plugins/gifPaste.ts @@ -18,12 +18,12 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { filters, findLazy, mapMangledModuleLazy } from "@webpack"; +import { filters, mapMangledModuleLazy } from "@webpack"; +import { ComponentDispatch } from "@webpack/common"; const ExpressionPickerState = mapMangledModuleLazy('name:"expression-picker-last-active-view"', { close: filters.byCode("activeView:null", "setState") }); -const ComponentDispatch = findLazy(m => m.emitter?._events?.INSERT_TEXT); export default definePlugin({ name: "GifPaste", diff --git a/src/plugins/invisibleChat/components/EncryptionModal.tsx b/src/plugins/invisibleChat/components/EncryptionModal.tsx index f650f28c5..c4f1f35d6 100644 --- a/src/plugins/invisibleChat/components/EncryptionModal.tsx +++ b/src/plugins/invisibleChat/components/EncryptionModal.tsx @@ -24,13 +24,10 @@ import { ModalRoot, openModal, } from "@utils/modal"; -import { findLazy } from "@webpack"; -import { Button, Forms, React, Switch, TextInput } from "@webpack/common"; +import { Button, ComponentDispatch, Forms, React, Switch, TextInput } from "@webpack/common"; import { encrypt } from "../index"; -const ComponentDispatch = findLazy(m => m.emitter?._events?.INSERT_TEXT); - function EncModal(props: ModalProps) { const [secret, setSecret] = React.useState(""); const [cover, setCover] = React.useState(""); diff --git a/src/plugins/quickMention.tsx b/src/plugins/quickMention.tsx index 6e00dd0c7..fe3da56dd 100644 --- a/src/plugins/quickMention.tsx +++ b/src/plugins/quickMention.tsx @@ -19,10 +19,7 @@ import { addButton, removeButton } from "@api/MessagePopover"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findLazy } from "@webpack"; -import { ChannelStore } from "@webpack/common"; - -const ComponentDispatch = findLazy(m => m.emitter?._events?.INSERT_TEXT); +import { ChannelStore, ComponentDispatch } from "@webpack/common"; export default definePlugin({ name: "QuickMention", diff --git a/src/plugins/sendTimestamps/index.tsx b/src/plugins/sendTimestamps/index.tsx new file mode 100644 index 000000000..9eaa8be1f --- /dev/null +++ b/src/plugins/sendTimestamps/index.tsx @@ -0,0 +1,219 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import "./styles.css"; + +import { addPreSendListener, removePreSendListener } from "@api/MessageEvents"; +import { classNameFactory } from "@api/Styles"; +import { Devs } from "@utils/constants"; +import { getTheme, Theme } from "@utils/discord"; +import { Margins } from "@utils/margins"; +import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; +import definePlugin from "@utils/types"; +import { Button, ButtonLooks, ButtonWrapperClasses, ComponentDispatch, Forms, Parser, Select, Tooltip, useMemo, useState } from "@webpack/common"; + +function parseTime(time: string) { + const cleanTime = time.slice(1, -1).replace(/(\d)(AM|PM)$/i, "$1 $2"); + + let ms = new Date(`${new Date().toDateString()} ${cleanTime}`).getTime() / 1000; + if (isNaN(ms)) return time; + + // add 24h if time is in the past + if (Date.now() / 1000 > ms) ms += 86400; + + return ``; +} + +const Formats = ["", "t", "T", "d", "D", "f", "F", "R"] as const; +type Format = typeof Formats[number]; + +const cl = classNameFactory("vc-st-"); + +function PickerModal({ rootProps, close }: { rootProps: ModalProps, close(): void; }) { + const [value, setValue] = useState(); + const [format, setFormat] = useState(""); + const time = Math.round((new Date(value!).getTime() || Date.now()) / 1000); + + const formatTimestamp = (time: number, format: Format) => ``; + + const [formatted, rendered] = useMemo(() => { + const formatted = formatTimestamp(time, format); + return [formatted, Parser.parse(formatted)]; + }, [time, format]); + + return ( + + + + Timestamp Picker + + + + + + + setValue(e.currentTarget.value)} + style={{ + colorScheme: getTheme() === Theme.Light ? "light" : "dark", + }} + /> + + Timestamp Format +