Browse Source

display last online time (#1125)

* - if offline calculate and display last online time to address https://github.com/owncast/owncast/issues/1111
- clean up status bar styles

* clean up console
pull/1106/head
gingervitis 4 years ago committed by GitHub
parent
commit
c45e43c378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      webroot/js/app-video-only.js
  2. 35
      webroot/js/app.js
  3. 3
      webroot/js/components/chat/chat-message-view.js
  4. 23
      webroot/js/utils/helpers.js
  5. 11
      webroot/styles/app.css
  6. 5
      webroot/styles/video-only.css

25
webroot/js/app-video-only.js

@ -12,7 +12,7 @@ import { OwncastPlayer } from './components/player.js';
import Websocket from './utils/websocket.js'; import Websocket from './utils/websocket.js';
const websocket = new Websocket(); const websocket = new Websocket();
import { addNewlines, pluralize } from './utils/helpers.js'; import { addNewlines, makeLastOnlineString, pluralize } from './utils/helpers.js';
import { import {
URL_CONFIG, URL_CONFIG,
URL_STATUS, URL_STATUS,
@ -38,6 +38,7 @@ export default class VideoOnly extends Component {
//status //status
streamStatusMessage: MESSAGE_OFFLINE, streamStatusMessage: MESSAGE_OFFLINE,
viewerCount: '', viewerCount: '',
lastDisconnectTime: null,
}; };
// timers // timers
@ -134,9 +135,7 @@ export default class VideoOnly extends Component {
if (!status) { if (!status) {
return; return;
} }
const { viewerCount, online } = status; const { viewerCount, online, lastDisconnectTime } = status;
this.lastDisconnectTime = status.lastDisconnectTime;
if (status.online && !curStreamOnline) { if (status.online && !curStreamOnline) {
// stream has just come online. // stream has just come online.
@ -148,6 +147,7 @@ export default class VideoOnly extends Component {
this.setState({ this.setState({
viewerCount, viewerCount,
streamOnline: online, streamOnline: online,
lastDisconnectTime,
}); });
} }
@ -215,15 +215,18 @@ export default class VideoOnly extends Component {
playerActive, playerActive,
streamOnline, streamOnline,
streamStatusMessage, streamStatusMessage,
lastDisconnectTime,
isPlaying, isPlaying,
} = state; } = state;
const { logo = TEMP_IMAGE, customStyles } = configData; const { logo = TEMP_IMAGE, customStyles } = configData;
const viewerCountMessage = let viewerCountMessage = '';
streamOnline && viewerCount > 0 if (streamOnline && viewerCount > 0) {
? html`${viewerCount} ${pluralize('viewer', viewerCount)}` viewerCountMessage = html`${viewerCount} ${pluralize('viewer', viewerCount)}`;
: null; } else if (lastDisconnectTime) {
viewerCountMessage = makeLastOnlineString(lastDisconnectTime);
}
const mainClass = playerActive ? 'online' : ''; const mainClass = playerActive ? 'online' : '';
@ -252,10 +255,10 @@ export default class VideoOnly extends Component {
<section <section
id="stream-info" id="stream-info"
aria-label="Stream status" aria-label="Stream status"
class="flex text-center flex-row justify-between font-mono py-2 px-8 bg-gray-900 text-indigo-200 shadow-md border-b border-gray-100 border-solid" class="flex flex-row justify-between font-mono py-2 px-4 bg-gray-900 text-indigo-200 shadow-md border-b border-gray-100 border-solid"
> >
<span>${streamStatusMessage}</span> <span class="text-xs">${streamStatusMessage}</span>
<span id="stream-viewer-count">${viewerCountMessage}</span> <span id="stream-viewer-count" class="text-xs text-right">${viewerCountMessage}</span>
</section> </section>
</main> </main>
`; `;

35
webroot/js/app.js

@ -8,11 +8,6 @@ import UsernameForm from './components/chat/username.js';
import VideoPoster from './components/video-poster.js'; import VideoPoster from './components/video-poster.js';
import Chat from './components/chat/chat.js'; import Chat from './components/chat/chat.js';
import Websocket from './utils/websocket.js'; import Websocket from './utils/websocket.js';
import {
parseSecondsToDurationString,
hasTouchScreen,
getOrientation,
} from './utils/helpers.js';
import ExternalActionModal, { import ExternalActionModal, {
ExternalActionButton, ExternalActionButton,
} from './components/external-action-modal.js'; } from './components/external-action-modal.js';
@ -24,6 +19,10 @@ import {
debounce, debounce,
generateUsername, generateUsername,
getLocalStorage, getLocalStorage,
getOrientation,
hasTouchScreen,
makeLastOnlineString,
parseSecondsToDurationString,
pluralize, pluralize,
setLocalStorage, setLocalStorage,
} from './utils/helpers.js'; } from './utils/helpers.js';
@ -72,6 +71,7 @@ export default class App extends Component {
// status // status
streamStatusMessage: MESSAGE_OFFLINE, streamStatusMessage: MESSAGE_OFFLINE,
viewerCount: '', viewerCount: '',
lastDisconnectTime: null,
// dom // dom
windowWidth: window.innerWidth, windowWidth: window.innerWidth,
@ -208,9 +208,7 @@ export default class App extends Component {
if (!status) { if (!status) {
return; return;
} }
const { viewerCount, online, lastConnectTime, streamTitle } = status; const { viewerCount, online, lastConnectTime, streamTitle, lastDisconnectTime } = status;
this.lastDisconnectTime = status.lastDisconnectTime;
if (status.online && !curStreamOnline) { if (status.online && !curStreamOnline) {
// stream has just come online. // stream has just come online.
@ -225,6 +223,7 @@ export default class App extends Component {
lastConnectTime, lastConnectTime,
streamOnline: online, streamOnline: online,
streamTitle, streamTitle,
lastDisconnectTime,
}); });
} }
@ -260,7 +259,7 @@ export default class App extends Component {
clearInterval(this.streamDurationTimer); clearInterval(this.streamDurationTimer);
const remainingChatTime = const remainingChatTime =
TIMER_DISABLE_CHAT_AFTER_OFFLINE - TIMER_DISABLE_CHAT_AFTER_OFFLINE -
(Date.now() - new Date(this.lastDisconnectTime)); (Date.now() - new Date(this.state.lastDisconnectTime));
const countdown = remainingChatTime < 0 ? 0 : remainingChatTime; const countdown = remainingChatTime < 0 ? 0 : remainingChatTime;
this.disableChatTimer = setTimeout(this.disableChatInput, countdown); this.disableChatTimer = setTimeout(this.disableChatInput, countdown);
this.setState({ this.setState({
@ -501,6 +500,7 @@ export default class App extends Component {
windowHeight, windowHeight,
windowWidth, windowWidth,
externalAction, externalAction,
lastDisconnectTime,
} = state; } = state;
const { const {
@ -520,10 +520,13 @@ export default class App extends Component {
const tagList = tags !== null && tags.length > 0 && tags.join(' #'); const tagList = tags !== null && tags.length > 0 && tags.join(' #');
const viewerCountMessage = let viewerCountMessage = '';
streamOnline && viewerCount > 0 if (streamOnline && viewerCount > 0) {
? html`${viewerCount} ${pluralize('viewer', viewerCount)}` viewerCountMessage = html`${viewerCount} ${pluralize('viewer', viewerCount)}`;
: null; } else if (lastDisconnectTime) {
viewerCountMessage = makeLastOnlineString(lastDisconnectTime);
}
const mainClass = playerActive ? 'online' : ''; const mainClass = playerActive ? 'online' : '';
const isPortrait = const isPortrait =
@ -647,10 +650,10 @@ export default class App extends Component {
<section <section
id="stream-info" id="stream-info"
aria-label="Stream status" aria-label="Stream status"
class="flex text-center flex-row justify-between font-mono py-2 px-8 bg-gray-900 text-indigo-200 shadow-md border-b border-gray-100 border-solid" class="flex text-center flex-row justify-between font-mono py-2 px-4 bg-gray-900 text-indigo-200 shadow-md border-b border-gray-100 border-solid"
> >
<span>${streamStatusMessage}</span> <span class="text-xs">${streamStatusMessage}</span>
<span id="stream-viewer-count">${viewerCountMessage}</span> <span id="stream-viewer-count" class="text-xs text-right">${viewerCountMessage}</span>
</section> </section>
</main> </main>

3
webroot/js/components/chat/chat-message-view.js

@ -9,6 +9,7 @@ import {
} from '../../utils/user-colors.js'; } from '../../utils/user-colors.js';
import { convertToText } from '../../utils/chat.js'; import { convertToText } from '../../utils/chat.js';
import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js'; import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js';
import { getDiffInDaysFromNow } from '../../utils/helpers.js';
export default class ChatMessageView extends Component { export default class ChatMessageView extends Component {
constructor(props) { constructor(props) {
@ -155,7 +156,7 @@ function formatTimestamp(sentAt) {
return ''; return '';
} }
let diffInDays = (new Date() - sentAt) / (24 * 3600 * 1000); let diffInDays = getDiffInDaysFromNow(sentAt); //(new Date() - sentAt) / (24 * 3600 * 1000);
if (diffInDays >= 1) { if (diffInDays >= 1) {
return ( return (
`Sent at ${sentAt.toLocaleDateString('en-US', { `Sent at ${sentAt.toLocaleDateString('en-US', {

23
webroot/js/utils/helpers.js

@ -156,3 +156,26 @@ export function debounce(fn, time) {
timeout = setTimeout(functionCall, time); timeout = setTimeout(functionCall, time);
} }
} }
export function getDiffInDaysFromNow(timestamp) {
const time = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
return (new Date() - time) / (24 * 3600 * 1000);
}
// "Last live today at [time]" or "last live [date]"
export function makeLastOnlineString(timestamp) {
if (!timestamp) {
return '';
}
let string = '';
const time = new Date(timestamp);
let diffInDays = getDiffInDaysFromNow(time);
if (diffInDays > 1) {
string = time.toLocaleDateString();
} else {
const atTime = time.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
string = `Today ${atTime}`;
}
return `Last live: ${string}`;
}

11
webroot/styles/app.css

@ -78,17 +78,6 @@ header {
display: none; display: none;
} }
#stream-info span {
font-size: .70rem;
}
#stream-viewer-count {
display: none;
}
.online #stream-viewer-count {
display: inline;
}
#external-actions-container { #external-actions-container {
margin: 1em 0; margin: 1em 0;

5
webroot/styles/video-only.css

@ -24,8 +24,3 @@ The styles in this file mostly ovveride those coming from chat.css
opacity: 1; opacity: 1;
pointer-events: auto; pointer-events: auto;
} }
#video-only #stream-info {
height: 3rem;
}

Loading…
Cancel
Save