diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx
index 390939f6d..2bd5ce96a 100644
--- a/web/pages/_app.tsx
+++ b/web/pages/_app.tsx
@@ -2,17 +2,17 @@ import 'antd/dist/antd.compact.css';
import "../styles/globals.scss";
import { AppProps } from 'next/app';
-import BroadcastStatusProvider from '../utils/broadcast-status-context';
+import ServerStatusProvider from '../utils/server-status-context';
import MainLayout from './components/main-layout';
function App({ Component, pageProps }: AppProps) {
return (
-
+
-
+
)
}
diff --git a/web/pages/broadcast-info.tsx b/web/pages/broadcast-info.tsx
index 5c3ad36bd..2cd8a7a63 100644
--- a/web/pages/broadcast-info.tsx
+++ b/web/pages/broadcast-info.tsx
@@ -1,9 +1,9 @@
import React, { useContext } from 'react';
-import { BroadcastStatusContext } from '../utils/broadcast-status-context';
+import { ServerStatusContext } from '../utils/server-status-context';
export default function BroadcastInfo() {
- const context = useContext(BroadcastStatusContext);
+ const context = useContext(ServerStatusContext);
const { broadcaster } = context || {};
const { remoteAddr, time, streamDetails } = broadcaster || {};
diff --git a/web/pages/components/main-layout.tsx b/web/pages/components/main-layout.tsx
index a100bc0e7..1b7ff11cb 100644
--- a/web/pages/components/main-layout.tsx
+++ b/web/pages/components/main-layout.tsx
@@ -18,15 +18,17 @@ import { upgradeVersionAvailable } from "../../utils/apis";
import { parseSecondsToDurationString } from '../../utils/format'
import OwncastLogo from './logo';
-import { BroadcastStatusContext } from '../../utils/broadcast-status-context';
+import { ServerStatusContext } from '../../utils/server-status-context';
import adminStyles from '../../styles/styles.module.css';
+let performedUpgradeCheck = false;
+
export default function MainLayout(props) {
const { children } = props;
- const context = useContext(BroadcastStatusContext);
- const { broadcastActive, broadcaster } = context || {};
+ const context = useContext(ServerStatusContext);
+ const { online, broadcaster, versionNumber } = context || {};
const router = useRouter();
const { route } = router || {};
@@ -34,19 +36,15 @@ export default function MainLayout(props) {
const { Header, Footer, Content, Sider } = Layout;
const { SubMenu } = Menu;
- const streamDurationString = broadcastActive ?
- parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(broadcaster.time))) : ""
+ const streamDurationString = online ? parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(broadcaster.time))) : "";
- const statusIcon = broadcastActive ?
- : ;
- const statusMessage = broadcastActive
- ? `Online ${ streamDurationString}`
- : "Offline";
+ const statusIcon = online ? : ;
+ const statusMessage = online ? `Online ${streamDurationString}` : "Offline";
const [upgradeVersion, setUpgradeVersion] = useState(null);
const checkForUpgrade = async () => {
try {
- const result = await upgradeVersionAvailable();
+ const result = await upgradeVersionAvailable(versionNumber);
setUpgradeVersion(result);
} catch (error) {
console.log("==== error", error);
@@ -54,13 +52,17 @@ export default function MainLayout(props) {
};
useEffect(() => {
- checkForUpgrade();
- }, []);
+ if (!performedUpgradeCheck && !context.disableUpgradeChecks) {
+ checkForUpgrade();
+ console.log('checking')
+ performedUpgradeCheck = true
+ }
+ });
const appClass = classNames({
- 'owncast-layout': true,
- [adminStyles.online]: broadcastActive,
- })
+ "owncast-layout": true,
+ [adminStyles.online]: online,
+ });
const upgradeMenuItemStyle = upgradeVersion ? 'block' : 'none';
const upgradeVersionString = upgradeVersion || '';
@@ -98,7 +100,7 @@ export default function MainLayout(props) {
Viewers
- {broadcastActive ? (
+ {online ? (
}>
Disconnect Stream...
@@ -151,7 +153,7 @@ export default function MainLayout(props) {
{children}
diff --git a/web/pages/index.tsx b/web/pages/index.tsx
index 1b7077f0e..112108a22 100644
--- a/web/pages/index.tsx
+++ b/web/pages/index.tsx
@@ -11,12 +11,12 @@ import React, { useState, useEffect, useContext } from "react";
import { Row, Skeleton, Result, List, Typography, Card } from "antd";
import { UserOutlined, ClockCircleOutlined } from "@ant-design/icons";
import { formatDistanceToNow, formatRelative } from "date-fns";
-import { BroadcastStatusContext } from "../utils/broadcast-status-context";
+import { ServerStatusContext } from "../utils/server-status-context";
import StatisticItem from "./components/statistic"
import LogTable from "./components/log-table";
import {
- STREAM_STATUS,
+ STATUS,
SERVER_CONFIG,
LOGS_WARN,
fetchData,
@@ -82,7 +82,7 @@ function Offline() {
}
export default function Stats() {
- const context = useContext(BroadcastStatusContext);
+ const context = useContext(ServerStatusContext);
const { broadcaster } = context || {};
const { remoteAddr, streamDetails } = broadcaster || {};
@@ -90,7 +90,7 @@ export default function Stats() {
const [stats, setStats] = useState(null);
const getStats = async () => {
try {
- const result = await fetchData(STREAM_STATUS);
+ const result = await fetchData(STATUS);
setStats(result);
} catch (error) {
console.log(error);
@@ -182,7 +182,7 @@ export default function Stats() {
});
const logTable = logs.length > 0 ? : null
- const { viewerCount, sessionMaxViewerCount, lastConnectTime } = stats;
+ const { viewerCount, sessionMaxViewerCount } = stats;
const streamVideoDetailString = `${streamDetails.videoCodec} ${streamDetails.videoBitrate} kbps ${streamDetails.width}x${streamDetails.height}`;
const streamAudioDetailString = `${streamDetails.audioCodec} ${streamDetails.audioBitrate} kpbs`;
@@ -192,10 +192,10 @@ export default function Stats() {
}
/>
-
- {release.created_at}
- {release.body};
-
- Downloads
+
+ {new Date(release.created_at).toDateString()}
+ {release.body};Downloads
);
diff --git a/web/pages/viewer-info.tsx b/web/pages/viewer-info.tsx
index fb39f6af6..04977adf3 100644
--- a/web/pages/viewer-info.tsx
+++ b/web/pages/viewer-info.tsx
@@ -7,23 +7,27 @@ import { SortOrder } from "antd/lib/table/interface";
import Chart from "./components/chart";
import StatisticItem from "./components/statistic";
-import { BroadcastStatusContext } from '../utils/broadcast-status-context';
+import { ServerStatusContext } from '../utils/server-status-context';
import {
CONNECTED_CLIENTS,
- STREAM_STATUS, VIEWERS_OVER_TIME,
+ VIEWERS_OVER_TIME,
fetchData,
} from "../utils/apis";
const FETCH_INTERVAL = 5 * 60 * 1000; // 5 mins
export default function ViewersOverTime() {
- const context = useContext(BroadcastStatusContext);
- const { broadcastActive } = context || {};
+ const context = useContext(ServerStatusContext);
+ const {
+ broadcastActive,
+ viewerCount,
+ overallPeakViewerCount,
+ sessionPeakViewerCount,
+ } = context || {};
const [viewerInfo, setViewerInfo] = useState([]);
const [clients, setClients] = useState([]);
- const [stats, setStats] = useState(null);
const getInfo = async () => {
try {
@@ -39,14 +43,6 @@ export default function ViewersOverTime() {
} catch (error) {
console.log("==== error", error);
}
-
- try {
- const result = await fetchData(STREAM_STATUS);
- setStats(result);
- } catch (error) {
- console.log(error);
- }
-
};
useEffect(() => {
@@ -111,12 +107,17 @@ export default function ViewersOverTime() {
}
/>
}
+ />
+ }
/>
diff --git a/web/utils/apis.ts b/web/utils/apis.ts
index fc581818f..4085631ba 100644
--- a/web/utils/apis.ts
+++ b/web/utils/apis.ts
@@ -8,7 +8,7 @@ const API_LOCATION = `${NEXT_PUBLIC_API_HOST}api/admin/`;
export const FETCH_INTERVAL = 15000;
// Current inbound broadcaster info
-export const BROADCASTER = `${API_LOCATION}broadcaster`;
+export const STATUS = `${API_LOCATION}status`;
// Disconnect inbound stream
export const DISCONNECT = `${API_LOCATION}disconnect`;
@@ -36,11 +36,6 @@ export const LOGS_WARN = `${API_LOCATION}logs/warnings`;
const GITHUB_RELEASE_URL = "https://api.github.com/repos/owncast/owncast/releases/latest";
-// Current Stream status.
-// This is literally the same as /api/status except it supports
-// auth.
-export const STREAM_STATUS = `${API_LOCATION}status`;
-
export async function fetchData(url) {
const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`);
@@ -81,8 +76,7 @@ export async function getGithubRelease() {
// Make a request to the server status API and the Github releases API
// and return a release if it's newer than the server version.
-export async function upgradeVersionAvailable() {
- const serverVersion = await fetchData(STREAM_STATUS)
+export async function upgradeVersionAvailable(currentVersion) {
const recentRelease = await getGithubRelease();
let recentReleaseVersion = recentRelease.tag_name;
@@ -90,7 +84,7 @@ export async function upgradeVersionAvailable() {
recentReleaseVersion = recentReleaseVersion.substr(1)
}
- if (!upToDate(serverVersion.versionNumber, recentReleaseVersion)) {
+ if (!upToDate(currentVersion, recentReleaseVersion)) {
return recentReleaseVersion
}
diff --git a/web/utils/broadcast-status-context.tsx b/web/utils/broadcast-status-context.tsx
deleted file mode 100644
index 309c2152d..000000000
--- a/web/utils/broadcast-status-context.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import PropTypes from 'prop-types';
-
-import { BROADCASTER, fetchData, FETCH_INTERVAL } from './apis';
-
-const initialState = {
- broadcastActive: false,
- message: '',
- broadcaster: null,
-};
-
-export const BroadcastStatusContext = React.createContext(initialState);
-
-const BroadcastStatusProvider = ({ children }) => {
- const [broadcasterStatus, setBroadcasterStatus] = useState(initialState);
-
- const getBroadcastStatus = async () => {
- try {
- const result = await fetchData(BROADCASTER);
- const broadcastActive = !!result.broadcaster || result.success;
- setBroadcasterStatus({ ...result, broadcastActive });
-
- } catch (error) {
- setBroadcasterStatus({ ...broadcasterStatus, message: error.message });
- }
- };
-
- useEffect(() => {
- let getStatusIntervalId = null;
-
- getBroadcastStatus();
- getStatusIntervalId = setInterval(getBroadcastStatus, FETCH_INTERVAL);
-
- // returned function will be called on component unmount
- return () => {
- clearInterval(getStatusIntervalId);
- }
- }, [])
-
- return (
-
- {children}
-
- );
-}
-
-BroadcastStatusProvider.propTypes = {
- children: PropTypes.element.isRequired,
-};
-
-export default BroadcastStatusProvider;
\ No newline at end of file
diff --git a/web/utils/server-status-context.tsx b/web/utils/server-status-context.tsx
new file mode 100644
index 000000000..f0c63aa43
--- /dev/null
+++ b/web/utils/server-status-context.tsx
@@ -0,0 +1,55 @@
+import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+
+import { STATUS, fetchData, FETCH_INTERVAL } from './apis';
+
+const initialState = {
+ broadcastActive: false,
+ broadcaster: null,
+ online: false,
+ viewerCount: 0,
+ sessionPeakViewerCount: 0,
+ overallPeakViewerCount: 0,
+ disableUpgradeChecks: true,
+ versionNumber: '0.0.0',
+};
+
+export const ServerStatusContext = React.createContext(initialState);
+
+const ServerStatusProvider = ({ children }) => {
+ const [status, setStatus] = useState(initialState);
+
+ const getStatus = async () => {
+ try {
+ const result = await fetchData(STATUS);
+ setStatus({ ...result });
+
+ } catch (error) {
+ // setBroadcasterStatus({ ...broadcasterStatus, message: error.message });
+ }
+ };
+
+ useEffect(() => {
+ let getStatusIntervalId = null;
+
+ getStatus();
+ getStatusIntervalId = setInterval(getStatus, FETCH_INTERVAL);
+
+ // returned function will be called on component unmount
+ return () => {
+ clearInterval(getStatusIntervalId);
+ }
+ }, [])
+
+ return (
+
+ {children}
+
+ );
+}
+
+ServerStatusProvider.propTypes = {
+ children: PropTypes.element.isRequired,
+};
+
+export default ServerStatusProvider;
\ No newline at end of file