diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index d09fdfcc3..390939f6d 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -1,4 +1,3 @@ -import 'antd/dist/antd.dark.css'; import 'antd/dist/antd.compact.css'; import "../styles/globals.scss"; diff --git a/web/pages/components/log-table.tsx b/web/pages/components/log-table.tsx index 86469aa6f..6d0c01cb0 100644 --- a/web/pages/components/log-table.tsx +++ b/web/pages/components/log-table.tsx @@ -1,6 +1,6 @@ import React from "react"; import { timeFormat } from "d3-time-format"; -import { Table, } from "antd"; +import { Table, Tag} from "antd"; import Linkify from "react-linkify"; import { SortOrder } from "antd/lib/table/interface"; @@ -13,10 +13,7 @@ function renderColumnLevel(text, entry) { color = "red"; } - const style = { - color, - }; - return
{text}
; + return {text}; } function renderMessage(text) { diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx index 052cc3bc3..bd502bfd5 100644 --- a/web/pages/components/main-layout.tsx +++ b/web/pages/components/main-layout.tsx @@ -1,6 +1,7 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import Link from 'next/link'; +import { differenceInSeconds } from "date-fns"; import { useRouter } from 'next/router'; import { Layout, Menu } from 'antd'; import { @@ -12,7 +13,7 @@ import { MinusSquareFilled, } from '@ant-design/icons'; import classNames from 'classnames'; - +import {parseSecondsToDurationString} from '../../utils/format' import OwncastLogo from './logo'; import { BroadcastStatusContext } from '../../utils/broadcast-status-context'; @@ -31,10 +32,14 @@ export default function MainLayout(props) { const { Header, Footer, Content, Sider } = Layout; const { SubMenu } = Menu; + const streamDurationString = broadcastActive ? + parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(context.broadcaster.time))) : "" + const statusIcon = broadcastActive ? : ; - const statusMessage = broadcastActive ? - 'Online' : 'Offline'; + const statusMessage = broadcastActive + ? `Online ${ streamDurationString}` + : "Offline"; const appClass = classNames({ 'owncast-layout': true, diff --git a/web/pages/viewer-info.tsx b/web/pages/viewer-info.tsx index bc2d9adae..a3b367c60 100644 --- a/web/pages/viewer-info.tsx +++ b/web/pages/viewer-info.tsx @@ -1,6 +1,5 @@ /* eslint-disable react/prop-types */ import React, { useState, useEffect, useContext } from 'react'; -import { timeFormat } from "d3-time-format"; import { Table, Row } from "antd"; import { formatDistanceToNow } from "date-fns"; import { UserOutlined} from "@ant-design/icons"; diff --git a/web/utils/format.ts b/web/utils/format.ts index 4f618e16e..a34ce1773 100644 --- a/web/utils/format.ts +++ b/web/utils/format.ts @@ -17,3 +17,25 @@ export function formatIPAddress(ipAddress: string): string { export function isEmptyObject(obj) { return !obj || Object.keys(obj).length === 0; } + +export function parseSecondsToDurationString(seconds = 0) { + const finiteSeconds = Number.isFinite(+seconds) ? Math.abs(seconds) : 0; + + const days = Math.floor(finiteSeconds / 86400); + const daysString = days > 0 ? `${days} day${days > 1 ? 's' : ''} ` : ''; + + const hours = Math.floor((finiteSeconds / 3600) % 24); + const hoursString = hours || days ? padLeft(`${hours}:`, '0', 3) : ''; + + const mins = Math.floor((finiteSeconds / 60) % 60); + const minString = padLeft(`${mins}:`, '0', 3); + + const secs = Math.floor(finiteSeconds % 60); + const secsString = padLeft(`${secs}`, '0', 2); + + return daysString + hoursString + minString + secsString; +} + +export function padLeft(text, pad, size) { + return String(pad.repeat(size) + text).slice(-size); +} \ No newline at end of file