diff --git a/chat/global.d.ts b/chat/global.d.ts index 189c388360..e448caa9d8 100644 --- a/chat/global.d.ts +++ b/chat/global.d.ts @@ -11,7 +11,6 @@ declare interface ChatSpeakResponse { text_censored: string; text_html: string; time: number; - timestamp: string; } declare interface EmojiModSelection { diff --git a/chat/package.json b/chat/package.json index fb7fed922f..2071eaf195 100644 --- a/chat/package.json +++ b/chat/package.json @@ -4,6 +4,7 @@ "main": "index.js", "license": "MIT", "dependencies": { + "@types/humanize-duration": "^3.27.1", "@types/lodash.debounce": "^4.0.7", "@types/lozad": "^1.16.1", "@types/react": "^18.0.20", @@ -13,6 +14,7 @@ "classnames": "^2.3.2", "dotenv": "^16.0.2", "esbuild": "^0.15.7", + "humanize-duration": "^3.27.3", "lodash.debounce": "^4.0.8", "lozad": "^1.16.0", "react": "^18.2.0", diff --git a/chat/src/App.tsx b/chat/src/App.tsx index ab72f99a30..63e13cba31 100644 --- a/chat/src/App.tsx +++ b/chat/src/App.tsx @@ -35,8 +35,6 @@ function AppInner() { const initiallyScrolledDown = useRef(false); const { messages, quote } = useChat(); - console.log({ quote }); - useEffect(() => { if (messages.length > 0) { if (initiallyScrolledDown.current) { diff --git a/chat/src/features/chat/ChatMessage.tsx b/chat/src/features/chat/ChatMessage.tsx index 935e38638d..d930a6a1f2 100644 --- a/chat/src/features/chat/ChatMessage.tsx +++ b/chat/src/features/chat/ChatMessage.tsx @@ -1,6 +1,7 @@ -import React, { useCallback, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import cx from "classnames"; import key from "weak-key"; +import humanizeDuration from "humanize-duration"; import { Username } from "./Username"; import { useChat, useRootContext } from "../../hooks"; import "./ChatMessage.css"; @@ -9,6 +10,8 @@ interface ChatMessageProps extends ChatSpeakResponse { showUser?: boolean; } +const TIMESTAMP_UPDATE_INTERVAL = 20000; + export function ChatMessage({ avatar, showUser = true, @@ -19,7 +22,6 @@ export function ChatMessage({ text_html, text_censored, time, - timestamp, }: ChatMessageProps) { const message = { avatar, @@ -30,7 +32,6 @@ export function ChatMessage({ text_html, text_censored, time, - timestamp, }; const { username: loggedInUsername, @@ -57,6 +58,18 @@ export function ChatMessage({ setConfirmedDelete(true); } }, [text, confirmedDelete]); + const [timestamp, setTimestamp] = useState(formatTimeAgo(time)); + + useEffect(() => { + const updatingTimestamp = setInterval( + () => setTimestamp(formatTimeAgo(time)), + TIMESTAMP_UPDATE_INTERVAL + ); + + return () => { + clearInterval(updatingTimestamp); + }; + }, []); return (
@@ -117,3 +130,13 @@ export function ChatMessageList() {
); } + +function formatTimeAgo(time: number) { + const now = new Date().getTime(); + + return `${humanizeDuration(time * 1000 - now, { + round: true, + units: ["h", "m", "s"], + largest: 2, + })} ago`; +} diff --git a/chat/yarn.lock b/chat/yarn.lock index fa774b4bac..2555ae9355 100644 --- a/chat/yarn.lock +++ b/chat/yarn.lock @@ -34,6 +34,11 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== +"@types/humanize-duration@^3.27.1": + version "3.27.1" + resolved "https://registry.yarnpkg.com/@types/humanize-duration/-/humanize-duration-3.27.1.tgz#f14740d1f585a0a8e3f46359b62fda8b0eaa31e7" + integrity sha512-K3e+NZlpCKd6Bd/EIdqjFJRFHbrq5TzPPLwREk5Iv/YoIjQrs6ljdAUCo+Lb2xFlGNOjGSE0dqsVD19cZL137w== + "@types/lodash.debounce@^4.0.7": version "4.0.7" resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.7.tgz#0285879defb7cdb156ae633cecd62d5680eded9f" @@ -362,6 +367,11 @@ hoist-non-react-statics@^3.3.2: dependencies: react-is "^16.7.0" +humanize-duration@^3.27.3: + version "3.27.3" + resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.27.3.tgz#db654e72ebf5ccfe232c7f56bc58aa3a6fe4df88" + integrity sha512-iimHkHPfIAQ8zCDQLgn08pRqSVioyWvnGfaQ8gond2wf7Jq2jJ+24ykmnRyiz3fIldcn4oUuQXpjqKLhSVR7lw== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"