diff --git a/public/manifest.json b/public/manifest.json index f90bec7..4e61f34 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -11,7 +11,8 @@ "https://*.netflix.com/*", "https://*.amazon.com/*", "https://*.disneyplus.com/*", - "https://*.youtube.com/*" + "https://*.youtube.com/*", + "https://play.hbonow.com/*" ], "content_security_policy": "script-src 'self' https://www.gstatic.com/ https://*.firebaseio.com https://www.googleapis.com; object-src 'self'", "content_scripts": [ @@ -44,6 +45,12 @@ "run_at": "document_idle", "js": ["/static/js/content.js"], "css": ["/static/css/app.css"] + }, + { + "matches": ["https://play.hbonow.com/*"], + "run_at": "document_idle", + "js": ["/static/js/content.js"], + "css": ["/static/css/app.css"] } ], "web_accessible_resources": ["android-icon-192x192.png"], diff --git a/src/Api.js b/src/Api.js index bb698b1..92bc5bb 100644 --- a/src/Api.js +++ b/src/Api.js @@ -17,6 +17,7 @@ export const PLAYER_SOURCE = { HULU: 'https://www.hulu.', DISNEY: 'https://www.disneyplus.', YOUTUBE: 'https://www.youtube.', + HBONOW: 'https://play.hbonow.', LOCAL: 'http://localhost', }; @@ -27,6 +28,7 @@ export const getPlayerSource = () => { if (HREF.startsWith(PLAYER_SOURCE.AMAZON)) return PLAYER_SOURCE.AMAZON; if (HREF.startsWith(PLAYER_SOURCE.DISNEY)) return PLAYER_SOURCE.DISNEY; if (HREF.startsWith(PLAYER_SOURCE.YOUTUBE)) return PLAYER_SOURCE.YOUTUBE; + if (HREF.startsWith(PLAYER_SOURCE.HBONOW)) return PLAYER_SOURCE.HBONOW; if (HREF.startsWith(PLAYER_SOURCE.LOCAL)) return PLAYER_SOURCE.LOCAL; }; diff --git a/src/Chat.js b/src/Chat.js index ac98bfe..c34842b 100644 --- a/src/Chat.js +++ b/src/Chat.js @@ -29,9 +29,9 @@ import Create from './Create'; import VideoListener from './VideoListener'; const giphyFetch = new GiphyFetch('ojJbIMUN6XRMn4mHiFFav3rMCpXUg8sq'); -const huluAlert = { +const alertMessage = { name: '', - text: 'Time sync is not available on Hulu yet.', + text: 'Functionality may be buggy, support on this site is in beta.', time: '', uid: '', }; @@ -216,8 +216,8 @@ export default class Chat extends Component { } render() { const { admin, name, messages, newMessage, gif } = this.state; - if (getPlayerSource() === PLAYER_SOURCE.HULU && messages[0] !== huluAlert) - messages.unshift(huluAlert); + if (getPlayerSource() === PLAYER_SOURCE.HBONOW && messages[0] !== alertMessage) + messages.unshift(alertMessage); return (
diff --git a/src/VideoListener.js b/src/VideoListener.js index 79acb73..ff250cd 100644 --- a/src/VideoListener.js +++ b/src/VideoListener.js @@ -78,6 +78,9 @@ export default class VideoListener { case PLAYER_SOURCE.YOUTUBE: this.video.element.currentTime = serverPlayer.time; break; + case PLAYER_SOURCE.HULU: + window.postMessage({ type: 'SEEK', time: serverPlayer.time }, '*'); + break; default: break; } @@ -85,12 +88,23 @@ export default class VideoListener { // TOGGLE PLAYER STATUS switch (serverPlayer.status) { case PLAYER_STATUS.PAUSED: - await this.video.element.pause(); + if ( + PLAYER_SOURCE.HULU === this.video.source || + PLAYER_SOURCE.NETFLIX === this.video.source + ) + window.postMessage({ type: 'PAUSE', time: serverPlayer.time }, '*'); + else await this.video.element.pause(); break; case PLAYER_STATUS.PLAYING: - await this.video.element - .play() - .catch((err) => console.error('WatchParty erred when syncing play.')); + if ( + PLAYER_SOURCE.HULU === this.video.source || + PLAYER_SOURCE.NETFLIX === this.video.source + ) + window.postMessage({ type: 'PLAY', time: serverPlayer.time }, '*'); + else + await this.video.element + .play() + .catch((err) => console.error('WatchParty erred when syncing play.')); break; default: break; @@ -186,7 +200,7 @@ export default class VideoListener { this.updateStatus({ source: getPlayerSource(), showName: await this.getShowName() }); switch (this.video.source) { case PLAYER_SOURCE.NETFLIX: - const seekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=window.netflix.appContext.state.playerApp.getAPI().videoPlayer,t=e.getAllPlayerSessionIds()[0];return e.getVideoPlayerBySessionId(t)},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().pause();getVideoPlayer().seek(e.data.time);}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; + const seekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=window.netflix.appContext.state.playerApp.getAPI().videoPlayer,t=e.getAllPlayerSessionIds()[0];return e.getVideoPlayerBySessionId(t)},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().pause();getVideoPlayer().seek(e.data.time);}if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; const seekInjectScript = document.createElement('script'); seekInjectScript.text = seekInject; document.head.appendChild(seekInjectScript); @@ -217,6 +231,10 @@ export default class VideoListener { } break; case PLAYER_SOURCE.HULU: + const huluSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.getElementsByClassName('content-video-player')[0].__HuluDashPlayer__;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().seek(e.data.time,e.data.time);}if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; + const huluSeekInjectScript = document.createElement('script'); + huluSeekInjectScript.text = huluSeekInject; + document.head.appendChild(huluSeekInjectScript); const videoElement = document.getElementsByClassName('content-video-player')[0]; if (videoElement) { this.firstTimeSync(videoElement); diff --git a/src/index.css b/src/index.css index 29b63c3..ea36fe5 100644 --- a/src/index.css +++ b/src/index.css @@ -25,7 +25,8 @@ body.hulu.visible .Player__container,/* HULU */ body.amazon-prime.visible #dv-web-player.dv-player-fullscreen, /* AMAZON PRIME */ body.disney.visible #hudson-wrapper, /* DISNEY */ body.youtube.visible #content.ytd-app, /* YOUTUBE */ -body.youtube.visible #masthead-container /* YOUTUBE HEADER */ { +body.youtube.visible #masthead-container, /* YOUTUBE HEADER */ +body.hbo.visible video.default { max-width: var(--body-width) !important; } /* HULU MINIMIZED VIDEO */ diff --git a/src/index.js b/src/index.js index be301c3..70335f7 100644 --- a/src/index.js +++ b/src/index.js @@ -53,6 +53,9 @@ switch (getPlayerSource()) { case PLAYER_SOURCE.YOUTUBE: document.body.classList.add('youtube'); break; + case PLAYER_SOURCE.HBONOW: + document.body.classList.add('hbo'); + break; case PLAYER_SOURCE.LOCAL: break; default: