From 2839a5e236d04e5ffbb3ad71c282b56871b57ebe Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Thu, 22 Oct 2020 14:14:44 -0700 Subject: [PATCH] Custom thumbnail poster component (#281) * Custom thumbnail poster component * add opacity transition to thumbnail img * fix some videoonly styles * move video styles to video.css * make component out of image layers; put inline styles into css * cleanup * update videoonly ; don't render poster if video player, remove dom modification in player * revert interval Co-authored-by: Ginger Wong --- webroot/js/app-video-only.js | 38 +++++---- webroot/js/app.js | 22 +++-- webroot/js/components/player.js | 8 -- webroot/js/components/video-poster.js | 114 ++++++++++++++++++++++++++ webroot/styles/app.css | 4 + webroot/styles/chat.css | 58 +++++-------- webroot/styles/video-only.css | 1 + webroot/styles/video.css | 26 ++++++ 8 files changed, 200 insertions(+), 71 deletions(-) create mode 100644 webroot/js/components/video-poster.js diff --git a/webroot/js/app-video-only.js b/webroot/js/app-video-only.js index fb79f8759..cac5834f3 100644 --- a/webroot/js/app-video-only.js +++ b/webroot/js/app-video-only.js @@ -2,6 +2,7 @@ import { h, Component } from '/js/web_modules/preact.js'; import htm from '/js/web_modules/htm.js'; const html = htm.bind(h); +import VideoPoster from './components/video-poster.js'; import { OwncastPlayer } from './components/player.js'; import { @@ -28,6 +29,8 @@ export default class VideoOnly extends Component { playerActive: false, // player object is active streamOnline: false, // stream is active/online + isPlaying: false, + //status streamStatusMessage: MESSAGE_OFFLINE, viewerCount: '', @@ -141,12 +144,6 @@ export default class VideoOnly extends Component { // stream has just flipped offline. this.handleOfflineMode(); } - if (status.online) { - // only do this if video is paused, so no unnecessary img fetches - if (this.player.vjsPlayer && this.player.vjsPlayer.paused()) { - this.player.setPoster(); - } - } this.setState({ viewerCount, streamOnline: online, @@ -160,7 +157,9 @@ export default class VideoOnly extends Component { } handlePlayerPlaying() { - // do something? + this.setState({ + isPlaying: true, + }); } // likely called some time after stream status has gone offline. @@ -168,6 +167,7 @@ export default class VideoOnly extends Component { handlePlayerEnded() { this.setState({ playerActive: false, + isPlaying: false, }); } @@ -212,29 +212,26 @@ export default class VideoOnly extends Component { playerActive, streamOnline, streamStatusMessage, + isPlaying, } = state; const { - version: appVersion, logo = {}, - socialHandles = [], - name: streamerName, - summary, - tags = [], - title, } = configData; - const { small: smallLogo = TEMP_IMAGE, large: largeLogo = TEMP_IMAGE } = logo; - - const bgLogoLarge = { backgroundImage: `url(${largeLogo})` }; + const { large: largeLogo = TEMP_IMAGE } = logo; + const streamInfoClass = streamOnline ? 'online' : ''; // need? const mainClass = playerActive ? 'online' : ''; + + const poster = isPlaying ? null : html` + <${VideoPoster} offlineImage=${largeLogo} active=${streamOnline} /> + `; return ( html`
+ ${poster}
-
+
${streamStatusMessage} ${viewerCount} ${pluralize('viewer', viewerCount)}.
diff --git a/webroot/js/app.js b/webroot/js/app.js index 226230549..b238f088b 100644 --- a/webroot/js/app.js +++ b/webroot/js/app.js @@ -5,6 +5,7 @@ const html = htm.bind(h); import { OwncastPlayer } from './components/player.js'; import SocialIconsList from './components/social-icons-list.js'; import UsernameForm from './components/chat/username.js'; +import VideoPoster from './components/video-poster.js'; import Chat from './components/chat/chat.js'; import Websocket from './utils/websocket.js'; import { secondsToHMMSS, hasTouchScreen, getOrientation } from './utils/helpers.js'; @@ -54,6 +55,7 @@ export default class App extends Component { playerActive: false, // player object is active streamOnline: false, // stream is active/online + isPlaying: false, // player is actively playing video // status streamStatusMessage: MESSAGE_OFFLINE, @@ -191,12 +193,7 @@ export default class App extends Component { // stream has just flipped offline. this.handleOfflineMode(); } - if (status.online) { - // only do this if video is paused, so no unnecessary img fetches - if (this.player.vjsPlayer && this.player.vjsPlayer.paused()) { - this.player.setPoster(); - } - } + this.setState({ viewerCount, lastConnectTime, @@ -211,7 +208,9 @@ export default class App extends Component { } handlePlayerPlaying() { - // do something? + this.setState({ + isPlaying: true, + }); } // likely called some time after stream status has gone offline. @@ -219,6 +218,7 @@ export default class App extends Component { handlePlayerEnded() { this.setState({ playerActive: false, + isPlaying: false, }); } @@ -320,6 +320,7 @@ export default class App extends Component { chatInputEnabled, configData, displayChat, + isPlaying, orientation, playerActive, streamOnline, @@ -368,7 +369,6 @@ export default class App extends Component { const mainClass = playerActive ? 'online' : ''; const streamInfoClass = streamOnline ? 'online' : ''; // need? - const isPortrait = this.hasTouchScreen && orientation === ORIENTATION_PORTRAIT; const shortHeight = windowHeight <= HEIGHT_SHORT_WIDE && !isPortrait; const singleColMode = windowWidth <= WIDTH_SINGLE_COL && !shortHeight; @@ -382,6 +382,10 @@ export default class App extends Component { 'touch-screen': this.hasTouchScreen, }); + const poster = isPlaying ? null : html` + <${VideoPoster} offlineImage=${largeLogo} active=${streamOnline} /> + `; + return html`
+ ${poster}