Plugin
SendTimestamps
Send timestamps easily via chat box button & text shortcuts. Read the extended description!
1
import "./styles.css";2
3
import { ChatBarButton, ChatBarButtonFactory } from "@api/ChatButtons";4
import { definePluginSettings } from "@api/Settings";5
import { Devs } from "@utils/constants";6
import { classNameFactory } from "@utils/css";7
import { getTheme, insertTextIntoChatInputBox, Theme } from "@utils/discord";8
import { Margins } from "@utils/margins";9
import definePlugin, { IconComponent, OptionType } from "@utils/types";10
import { RenderModalProps } from "@vencord/discord-types";11
import { Forms, Modal,openModal, Parser, Select, useMemo, useState } from "@webpack/common";12
13
const settings = definePluginSettings({14
replaceMessageContents: {15
description: "Replace timestamps in message contents",16
type: OptionType.BOOLEAN,17
default: true,18
},19
});20
21
function parseTime(time: string) {22
const cleanTime = time.slice(1, -1).replace(/(\d)(AM|PM)$/i, "$1 $2");23
24
let ms = new Date(`${new Date().toDateString()} ${cleanTime}`).getTime() / 1000;25
if (isNaN(ms)) return time;26
27
// add 24h if time is in the past28
if (Date.now() / 1000 > ms) ms += 86400;29
30
return `<t:${Math.round(ms)}:t>`;31
}32
33
const Formats = ["", "t", "T", "d", "D", "f", "F", "s", "S", "R"] as const;34
type Format = typeof Formats[number];35
36
const cl = classNameFactory("vc-st-");37
38
function PickerModal(props: RenderModalProps) {39
const [value, setValue] = useState<string>();40
const [format, setFormat] = useState<Format>("");41
const time = Math.round((new Date(value!).getTime() || Date.now()) / 1000);42
43
const formatTimestamp = (time: number, format: Format) => `<t:${time}${format && `:${format}`}>`;44
45
const [formatted, rendered] = useMemo(() => {46
const formatted = formatTimestamp(time, format);47
return [formatted, Parser.parse(formatted)];48
}, [time, format]);49
50
return (51
<Modal52
{...props}53
title="Timestamp Picker"54
actions={[{55
text: "Insert",56
variant: "primary",57
onClick() {58
insertTextIntoChatInputBox(formatted + " ");59
props.onClose();60
}61
}]}62
>63
<input64
className={cl("date-picker")}65
type="datetime-local"66
value={value}67
onChange={e => setValue(e.currentTarget.value)}68
style={{69
colorScheme: getTheme() === Theme.Light ? "light" : "dark",70
}}71
/>72
73
<Forms.FormTitle>Timestamp Format</Forms.FormTitle>74
<div className={cl("format-select")}>75
<Select76
options={77
Formats.map(m => ({78
label: m,79
value: m80
}))81
}82
isSelected={v => v === format}83
select={v => setFormat(v)}84
serialize={v => v}85
renderOptionLabel={o => (86
<div className={cl("format-label")}>87
{Parser.parse(formatTimestamp(time, o.value))}88
</div>89
)}90
renderOptionValue={() => rendered}91
/>92
</div>93
94
<Forms.FormTitle className={Margins.bottom8}>Preview</Forms.FormTitle>95
<Forms.FormText className={cl("preview-text")}>96
{rendered} ({formatted})97
</Forms.FormText>98
</Modal>99
);100
}101
102
const SendTimestampIcon: IconComponent = ({ height = 20, width = 20, className }) => {103
return (104
<svg105
aria-hidden="true"106
role="img"107
width={width}108
height={height}109
className={className}110
viewBox="0 0 24 24"111
style={{ scale: "1.2" }}112
>113
<g fill="none" fillRule="evenodd">114
<path fill="currentColor" d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7v-5z" />115
<rect width="24" height="24" />116
</g>117
</svg>118
);119
};120
121
const SendTimestampButton: ChatBarButtonFactory = ({ isAnyChat }) => {122
if (!isAnyChat) return null;123
124
return (125
<ChatBarButton126
tooltip="Insert Timestamp"127
onClick={() => openModal(props => <PickerModal {...props} />)}128
buttonProps={{ "aria-haspopup": "dialog" }}129
>130
<SendTimestampIcon />131
</ChatBarButton>132
);133
};134
135
export default definePlugin({136
name: "SendTimestamps",137
description: "Send timestamps easily via chat box button & text shortcuts. Read the extended description!",138
tags: ["Chat", "Commands"],139
authors: [Devs.Ven, Devs.Tyler, Devs.Grzesiek11],140
settings,141
142
chatBarButton: {143
icon: SendTimestampIcon,144
render: SendTimestampButton145
},146
147
onBeforeMessageSend(_, msg) {148
if (settings.store.replaceMessageContents) {149
msg.content = msg.content.replace(/`\d{1,2}:\d{2} ?(?:AM|PM)?`/gi, parseTime);150
}151
},152
153
settingsAboutComponent() {154
const samples = [155
"12:00",156
"3:51",157
"17:59",158
"24:00",159
"12:00 AM",160
"0:13PM"161
].map(s => `\`${s}\``);162
163
return (164
<>165
<Forms.FormText>166
To quickly send time only timestamps, include timestamps formatted as `HH:MM` (including the backticks!) in your message167
</Forms.FormText>168
<Forms.FormText>169
See below for examples.170
If you need anything more specific, use the Date button in the chat bar!171
</Forms.FormText>172
<Forms.FormText>173
Examples:174
<ul>175
{samples.map(s => (176
<li key={s}>177
<code>{s}</code> {"->"} {Parser.parse(parseTime(s))}178
</li>179
))}180
</ul>181
</Forms.FormText>182
</>183
);184
},185
});186