diff --git a/src/room/CallClock.module.css b/src/room/CallClock.module.css new file mode 100644 index 00000000..500294e2 --- /dev/null +++ b/src/room/CallClock.module.css @@ -0,0 +1,23 @@ +/* +Copyright 2026 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +.clock { + position: fixed; + inset-block-start: var(--cpd-space-6x); + inset-inline-start: var(--cpd-space-6x); + z-index: 2147483647; + padding: var(--cpd-space-2x) var(--cpd-space-3x); + border-radius: var(--cpd-space-2x); + background: rgba(0, 0, 0, 0.6); + color: #fff; + font-size: var(--font-size-body); + font-variant-numeric: tabular-nums; + line-height: 1; + pointer-events: none; + user-select: none; +} + diff --git a/src/room/CallClock.tsx b/src/room/CallClock.tsx new file mode 100644 index 00000000..37539e36 --- /dev/null +++ b/src/room/CallClock.tsx @@ -0,0 +1,38 @@ +/* +Copyright 2026 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { type FC, useEffect, useRef, useState } from "react"; + +import styles from "./CallClock.module.css"; + +const pad = (n: number): string => n.toString().padStart(2, "0"); + +export const CallClock: FC = () => { + const startedAt = useRef(Date.now()); + const [now, setNow] = useState(() => Date.now()); + + useEffect(() => { + const id = window.setInterval(() => setNow(Date.now()), 1000); + return (): void => window.clearInterval(id); + }, []); + + const elapsed = Math.max(0, Math.floor((now - startedAt.current) / 1000)); + const h = Math.floor(elapsed / 3600); + const m = Math.floor((elapsed % 3600) / 60); + const s = elapsed % 60; + const text = h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`; + + return ( +