diff --git a/src/App.vue b/src/App.vue index c0d76ca2..a6e140e7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -24,7 +24,7 @@ - + @@ -119,7 +119,12 @@ }, mounted: async function () { // Verify route changes - + chrome.runtime.sendMessage('mlmjjfdcbemagmnjahllphjnohbmhcnf', { command: 'heartbeat' }, (response) => { + console.log(response) + if (response) { + this.$store.commit('SET_EXTAVAILABLE', true) + } + }) if (this.$route.query.ptserver && this.$route.query.ptroom) { console.log('We should auto join') // Looks like a valid request... @@ -133,6 +138,12 @@ this.snackbarMsg = msg this.snackbar = true }) + window.EventBus.$on('PLAYBACK_CHANGE', (ratingKey) => { + // this.$store.dispatch('PLAYBACK_CHANGE', ratingKey) + }) + window.EventBus.$on('NEW_TIMELINE', (timeline) => { + this.$store.dispatch('NEW_TIMELINE', timeline) + }) if (window['localStorage'].getItem('plexuser') == null) { console.log('User isnt signed in - sending to signin') this.$router.push('/signin') @@ -144,7 +155,11 @@ } console.log('Logging in to Plex.Tv') let plexstorage = JSON.parse(window['localStorage'].getItem('plexuser')) - await this.$store.dispatch('PLEX_LOGIN_TOKEN', plexstorage.authToken) + try { + await this.$store.dispatch('PLEX_LOGIN_TOKEN', plexstorage.authToken) + } catch (e) { + this.$router.push('/signin') + } this.loading = false }, @@ -164,7 +179,10 @@ }, libraryCache: function () { return this.$store.getters.getLibraryCache - }, + }, + extAvailable: function () { + return this.$store.getters.getExtAvailable + }, crumbs: function () { if (this.$route.path.indexOf('browse') === -1) { return [] diff --git a/src/components/application/walkthrough.vue b/src/components/application/walkthrough.vue index 8456ba0a..94cdc728 100644 --- a/src/components/application/walkthrough.vue +++ b/src/components/application/walkthrough.vue @@ -145,8 +145,8 @@ } }, watch: { - chosenClient: function () { - if (this.chosenClient) { + chosenClient: function (to, from) { + if (this.chosenClient && !from) { this.$router.push('/joinroom') } } diff --git a/src/components/signin.vue b/src/components/signin.vue index b458d574..483e0d75 100644 --- a/src/components/signin.vue +++ b/src/components/signin.vue @@ -2,7 +2,7 @@ -

Sign in to Plex.tv

+

Sign in to Plex.tv

@@ -13,7 +13,7 @@
- done + done

Signed in!

@@ -21,11 +21,11 @@
-

{{ pin }}

+

{{ pin }}

- - content_copy + + content_copy Copy @@ -95,8 +95,8 @@ this.$http.post('https://plex.tv/pins.xml', null, { headers: { 'X-Plex-Device': 'Web', - 'X-Plex-Device-Name': 'PlexTogether', - 'X-Plex-Product': 'PlexTogether', + 'X-Plex-Device-Name': 'SyncLounge', + 'X-Plex-Product': 'SyncLounge', 'X-Plex-Version': '1.2', 'X-Plex-Platform': sBrowser, 'X-Plex-Platform-Version': '', @@ -107,7 +107,7 @@ if (!err) { this.pin = result.pin.code[0] this.ID = result.pin.id[0]._ - let checker = setInterval(function () { + let checker = setInterval(() => { var options = { url: 'https://plex.tv/pins/' + result.pin.id[0]._ + '.xml', headers: { @@ -130,14 +130,14 @@ if (!err) { if (result.pin.auth_token[0] != null && result.pin.auth_token[0].length > 1) { console.log('GOT TOKEN!', this) - that.token = result.pin.auth_token[0] + this.token = result.pin.auth_token[0] let jsonObj = { authToken: this.token } storage.setItem('plexuser', JSON.stringify(jsonObj)) - await that.$store.dispatch('PLEX_LOGIN_TOKEN', token) - setTimeout(function () { - that.$router.push('/sync') + await this.$store.dispatch('PLEX_LOGIN_TOKEN', this.token) + setTimeout(() => { + this.$router.push('/browse') }, 2500) clearInterval(checker) } diff --git a/src/main.js b/src/main.js index bdad63a0..af822b17 100644 --- a/src/main.js +++ b/src/main.js @@ -74,18 +74,29 @@ Vue.mixin({ plexserver: function () { return this.plex.servers[this.$route.params.machineIdentifier] }, + route: function () { + return this.$route + }, fontSizes: function () { var w = Math.round(Math.max(document.documentElement.clientWidth, window.innerWidth || 0)) var h = Math.round(Math.max(document.documentElement.clientHeight, window.innerHeight || 0)) let maxPx = 94 let maxRes = 3000 return { - largest: { 'font-size': ((w / maxRes) * maxPx) + 'px' } + largest: { 'font-size': ((w / maxRes) * maxPx) + 'px' }, + medium: { 'font-size': ((w / maxRes) * maxPx) * 0.6 + 'px' } } } } }) + + +// var data = { type: "FROM_PAGE", text: "Hello from the webpage!", callback: (res) => { +// console.log('Result callback!', res) +// }}; +// window.postMessage(data, "*"); + router.beforeEach((to, from, next) => { console.log('Route change', to, this, store) if (to.matched.some(record => record.meta.protected)) { @@ -112,7 +123,9 @@ router.beforeEach((to, from, next) => { console.log('Valid route change!') next() } else { - next() // make sure to always call next()! + if (!to.meta.protected) { + return next() // make sure to always call next()! + } router.push('/browse') } }) diff --git a/src/router/index.js b/src/router/index.js index fe4bea6a..dd419e25 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -15,14 +15,13 @@ export default new Router({ base: '/ptweb/', routes: [ { path: '/', meta: { protected: true } }, - { path: '/signin', component: signin }, - { path: '/signout', component: signout }, - { path: '/join', component: join }, - { path: '/clientselect', component: require('../components/application/walkthrough.vue') }, - { path: '/joinroom', component: require('../components/application/joinroom.vue') }, + { path: '/signin', meta: { noload: true }, component: signin }, + { path: '/signout', meta: { noload: true }, component: signout }, + { path: '/join', meta: { noload: true }, component: join }, + { path: '/clientselect', meta: { noload: false }, component: require('../components/application/walkthrough.vue') }, + { path: '/joinroom', meta: { noload: false }, component: require('../components/application/joinroom.vue') }, { path: '/player', meta: { protected: true }, component: require('../components/application/ptplayer.vue') }, - { path: '/browse', meta: { protected: true }, name: 'browse', component: require('../components/application/plexbrowser.vue') }, { path: '/browse/:machineIdentifier', meta: { protected: true }, name: 'server', component: require('../components/application/plexbrowser/plexserver.vue'), }, diff --git a/src/store.js b/src/store.js index 5dfa0fcd..b3227d05 100644 --- a/src/store.js +++ b/src/store.js @@ -76,6 +76,8 @@ const state = { autoJoinPassword: null, shortLink: null, webapp_socket: _webapp_socket, + extAvailable: false, + lastRatingKey: null, // SETTINGS DARKMODE: JSON.parse(getSetting('DARKMODE')), CLIENTPOLLINTERVAL: getSetting('CLIENTPOLLINTERVAL'), @@ -91,77 +93,9 @@ const state = { } const mutations = { + SET_CHOSENCLIENT (state, client) { - async function playbackChange (ratingKey) { - // console.log('Playback change!', ratingKey) - if (ratingKey != null) { - // Playing something different! - let server = state.plex.servers[state.chosenClient.lastTimelineObject.machineIdentifier] - state.LASTSERVER = state.chosenClient.lastTimelineObject.machineIdentifier - window['localStorage'].setItem('LASTSERVER', state.chosenClient.lastTimelineObject.machineIdentifier) - if (!server) { - return - } - // Fetch our metadata from this server - // console.log('Loading content metadata from store ' + ratingKey) - server.getMediaByRatingKey(ratingKey.replace('/library/metadata/', '')).then((data) => { - let metadata = data.MediaContainer.Metadata[0] - if (!metadata) { - return - } - if (metadata.type == 'movie') { - sendNotification('Now Playing: ' + metadata.title + ' from ' + state.plex.servers[metadata.machineIdentifier].name) - } - if (metadata.type == 'episode') { - sendNotification('Now Playing: ' + metadata.grandparentTitle + ' S' + metadata.parentIndex + 'E' + metadata.index + ' from ' + state.plex.servers[metadata.machineIdentifier].name) - } - state.chosenClient.clientPlayingMetadata = metadata - var w = Math.round(Math.max(document.documentElement.clientWidth, window.innerWidth || 0)); - var h = Math.round(Math.max(document.documentElement.clientHeight, window.innerHeight || 0)); - state.background = state.plex.servers[metadata.machineIdentifier].getUrlForLibraryLoc(metadata.thumb, w / 4, h / 4, 4) - }) - } else { - let thumb = await state.plex.getRandomThumb(state.plex) - if (thumb) { - state.background = thumb - } - state.chosenClient.clientPlayingMetadata = null - } - } - - function newTimeline (timeline) { - // console.log('Got timeline') - // Lets send this to our PTServer - state.ourClientResponseTime = timeline.lastResponseTime - let title = null - let rawTitle = null - if (state.chosenClient.clientPlayingMetadata) { - let metadata = state.chosenClient.clientPlayingMetadata - rawTitle = metadata.title - if (metadata.type == 'episode') { - title = metadata.grandparentTitle + ' - ' + metadata.title + ' S' + metadata.parentIndex + '-' + 'E' + metadata.index - } else { - title = metadata.title - } - } - let end_obj = { - time: timeline.time, - maxTime: timeline.duration, - title: title, - rawTitle: rawTitle, - playerState: timeline.state, - clientResponseTime: state.chosenClient.lastResponseTime - } - let time = -1 - let maxTime = -1 - let playerState = null - let showName = null - - if (state.synclounge._socket) { - state.synclounge._socket.pollStartTime = (new Date).getTime() - state.synclounge._socket.emit('poll', end_obj) - } - } + // Set up our client poller function clientPoller (time) { @@ -191,8 +125,6 @@ const mutations = { if (state.chosenClient == null) { return } - state.chosenClient.events.on('new_timeline', newTimeline) - state.chosenClient.events.on('playback_change', playbackChange) state.chosenClientTimeSet = (new Date).getTime() clientPoller(state.chosenClientTimeSet) state.chosenClient.getTimeline(function (timeline) {}) @@ -298,6 +230,14 @@ const mutations = { }, SET_HOSTPTSERVERRESPONSETIME (state, value) { state.stats.hostPTServerResponseTime = value + }, + SET_EXTAVAILABLE (state, value) { + state.extAvailable = value + }, + SET_VALUE (state, data) { + let [ key, value ] = data + console.log('Setting state', key, 'to', value) + state[key] = value } } const getters = { @@ -368,6 +308,9 @@ const getters = { }, getSettingLASTSERVER: state => { return state.LASTSERVER + }, + getExtAvailable: state => { + return state.extAvailable } } const actions = { @@ -375,7 +318,89 @@ const actions = { setTimeout(() => { commit('INCREMENT') }, 200) - } + }, + async PLAYBACK_CHANGE ({ commit, state, dispatch }, data) { + console.log('Playback change!', state.chosenClient) + let [ client, ratingKey, mediaContainer ] = data + if (ratingKey) { + // Playing something different! + console.log(mediaContainer) + let server = state.plex.servers[mediaContainer.machineIdentifier] + state.LASTSERVER = mediaContainer.machineIdentifier + window['localStorage'].setItem('LASTSERVER', mediaContainer.machineIdentifier) + if (!server) { + console.log('Playing off a server we do not have access to') + return + } + // Fetch our metadata from this server + // console.log('Loading content metadata from store ' + ratingKey) + server.getMediaByRatingKey(ratingKey.replace('/library/metadata/', '')).then((data) => { + console.log('Metadata:', data) + let metadata = data.MediaContainer.Metadata[0] + if (!metadata) { + return + } + if (metadata.type == 'movie') { + sendNotification('Now Playing: ' + metadata.title + ' from ' + state.plex.servers[metadata.machineIdentifier].name) + } + if (metadata.type == 'episode') { + sendNotification('Now Playing: ' + metadata.grandparentTitle + ' S' + metadata.parentIndex + 'E' + metadata.index + ' from ' + state.plex.servers[metadata.machineIdentifier].name) + } + state.chosenClient.clientPlayingMetadata = metadata + var w = Math.round(Math.max(document.documentElement.clientWidth, window.innerWidth || 0)); + var h = Math.round(Math.max(document.documentElement.clientHeight, window.innerHeight || 0)); + state.background = state.plex.servers[metadata.machineIdentifier].getUrlForLibraryLoc(metadata.thumb, w / 4, h / 4, 4) + }) + } else { + let thumb = await state.plex.getRandomThumb(state.plex) + if (thumb) { + state.background = thumb + } + state.chosenClient.clientPlayingMetadata = null + } + }, + NEW_TIMELINE ({ commit, state, dispatch }, data) { + // return true + let [ client, timeline, mediaContainer ] = data + // console.log(state) + if (!state.chosenClient || (client.clientIdentifier !== state.chosenClient.clientIdentifier)) { + console.log('Invalid client') + return false + } + if (state.lastRatingKey !== timeline.ratingKey) { + commit('SET_VALUE', ['lastRatingKey', timeline.ratingKey]) + dispatch('PLAYBACK_CHANGE', [ client, timeline.ratingKey, timeline]) + } + // state.ourClientResponseTime = timeline.lastResponseTime + let title = null + let rawTitle = null + if (state.chosenClient.clientPlayingMetadata) { + let metadata = state.chosenClient.clientPlayingMetadata + rawTitle = metadata.title + if (metadata.type == 'episode') { + title = metadata.grandparentTitle + ' - ' + metadata.title + ' S' + metadata.parentIndex + '-' + 'E' + metadata.index + } else { + title = metadata.title + } + } + let end_obj = { + time: timeline.time, + maxTime: timeline.duration, + title: title, + rawTitle: rawTitle, + playerState: timeline.state, + clientResponseTime: state.chosenClient.lastResponseTime + } + let time = -1 + let maxTime = -1 + let playerState = null + let showName = null + + if (state.synclounge._socket) { + state.synclounge._socket.pollStartTime = (new Date).getTime() + state.synclounge._socket.emit('poll', end_obj) + } + }, } diff --git a/src/store/modules/plex/actions.js b/src/store/modules/plex/actions.js index 75a41f30..617efc51 100644 --- a/src/store/modules/plex/actions.js +++ b/src/store/modules/plex/actions.js @@ -173,7 +173,8 @@ export default { PLEX_ADD_CLIENT: ({ state, commit, dispatch }, client) => { commit('PLEX_CLIENT_SET', client) - commit('PLEX_CLIENT_SET_VALUE', [client, 'commit', commit]) + commit('PLEX_CLIENT_SET_VALUE', [client, 'commit', commit]) + commit('PLEX_CLIENT_SET_VALUE', [client, 'dispatch', dispatch]) }, PLEX_ADD_SERVER: ({ state, commit, dispatch }, server) => { commit('PLEX_SERVER_SET', server) diff --git a/src/store/modules/plex/helpers/PlexClient.js b/src/store/modules/plex/helpers/PlexClient.js index 17ac39f9..16f03e4c 100644 --- a/src/store/modules/plex/helpers/PlexClient.js +++ b/src/store/modules/plex/helpers/PlexClient.js @@ -44,6 +44,9 @@ module.exports = function PlexClient () { this.eventbus = window.EventBus // Assigned early on - we will use this to communicate with the PT Player this.commit = null + this.dispatch = null + + let previousTimeline = {} this.setValue = function (key, value) { this[key] = value @@ -88,7 +91,9 @@ module.exports = function PlexClient () { if (!connection) { return reject('No connection specified') } - var query = 'type=video&X-Plex-Device-Name=SyncLounge&' + var query = '' + Object.assign(params, { type: 'video', 'X-Plex-Device-Name': 'SyncLounge'}) + // console.log(params) for (let key in params) { query += encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) + '&' } @@ -100,21 +105,49 @@ module.exports = function PlexClient () { var _url = connection.uri + command + '?' + query this.setValue('commandId', this.commandId + 1) var options = PlexAuth.getClientApiOptions(_url, this.clientIdentifier, this.uuid, 5000) - console.log('sending api request', options) - request(options, (error, response, body) => { - // console.log('response data', response) - if (error) { - return reject(error) - - } else { - parseXMLString(body, function (err, result) { - if (err || (response.statusCode != 200 && response.statusCode != 201)) { - return reject(err) + // console.log('sending api request', options) + + chrome.runtime.sendMessage('mlmjjfdcbemagmnjahllphjnohbmhcnf', { + command: 'client', + data: { + url: _url, + query: params, + options: options + }, + client_command: command, + query: query + }, (response) => { + // console.log('SyncLoungePlus response', response) + if (response) { + parseXMLString(response, (err, result) => { + resolve(result) + if (command === '/player/timeline/poll') { + this.updateTimelineObject(result) } - return resolve(result) - }) - } + return + }) + } else { + // request(options, (error, response, body) => { + // // console.log('response data', response) + // if (error) { + // return reject(error) + + // } else { + // parseXMLString(body, function (err, result) { + // if (err || (response.statusCode != 200 && response.statusCode != 201)) { + // return reject(err) + // } + // return resolve(result) + // }) + // } + // }) + } }) + + + + + } if ((new Date().getTime() - this.lastSubscribe) > 29000) { // We need to subscribe first! @@ -152,10 +185,9 @@ module.exports = function PlexClient () { } this.updateTimelineObject = function (result) { - this.setValue('lastTimelineObject', result) - this.lastTimelineObject = result - this.events.emit('new_timeline', result) - + + // this.events.emit('new_timeline', result) + // console.log('New timeline', result) // Check if we are the SLPlayer if (this.clientIdentifier === 'PTPLAYER9PLUS10') { // SLPLAYER @@ -190,40 +222,47 @@ module.exports = function PlexClient () { // Valid timeline data // Standard player let timelines = result.MediaContainer.Timeline - let videoTimeline = null + let videoTimeline = {} for (let i = 0; i < timelines.length; i++) { let _timeline = timelines[i]['$'] if (_timeline.type == 'video'){ videoTimeline = _timeline - } - if ((_timeline.state && _timeline.state != 'stopped') || i == (timelines.length - 1)) { - this.events.emit('new_timeline', timelines[i]['$']) - var clonetimeline = this.lastTimelineObject - this.lastTimelineObject = timelines[i]['$'] - this.setValue('lastTimelineObject', timelines[i]['$']) - if (!this.oldTimelineObject) { - // First time we've got data! - if (!this.lastTimelineObject.ratingKey) { - this.events.emit('playback_change', null) - } else { - this.events.emit('playback_change', this.lastTimelineObject.ratingKey) - } - this.setValue('oldTimelineObject', timelines[i]['$']) - // this.oldTimelineObject = timelines[i]['$'] - return timelines[i]['$'] + console.log('Does', videoTimeline.ratingKey + ' equal ' + previousTimeline.ratingKey) + if (videoTimeline.ratingKey !== previousTimeline.ratingKey) { + window.EventBus.$emit('PLAYBACK_CHANGE', [this, videoTimeline.ratingKey, result.MediaContainer]) } - this.setValue('oldTimelineObject', clonetimeline) - this.oldTimelineObject = clonetimeline - if (this.oldTimelineObject.ratingKey != result.ratingKey) { - if (!this.lastTimelineObject.ratingKey) { - this.events.emit('playback_change', null) - } else { - this.events.emit('playback_change', result.ratingKey) - } - } - return timelines[i]['$'] } + // if ((_timeline.state && _timeline.state != 'stopped') || i == (timelines.length - 1)) { + // this.events.emit('new_timeline', timelines[i]['$']) + // var clonetimeline = this.lastTimelineObject + // this.lastTimelineObject = timelines[i]['$'] + // this.setValue('lastTimelineObject', timelines[i]['$']) + // if (!this.oldTimelineObject) { + // // First time we've got data! + // if (!this.lastTimelineObject.ratingKey) { + // this.events.emit('playback_change', null) + // } else { + // this.events.emit('playback_change', this.lastTimelineObject.ratingKey) + // } + // this.setValue('oldTimelineObject', timelines[i]['$']) + // // this.oldTimelineObject = timelines[i]['$'] + // return timelines[i]['$'] + // } + // this.setValue('oldTimelineObject', clonetimeline) + // this.oldTimelineObject = clonetimeline + // if (this.oldTimelineObject.ratingKey != result.ratingKey) { + // if (!this.lastTimelineObject.ratingKey) { + // this.events.emit('playback_change', null) + // } else { + // this.events.emit('playback_change', result.ratingKey) + // } + // } + // return timelines[i]['$'] + // } } + window.EventBus.$emit('NEW_TIMELINE', [this, videoTimeline, result.MediaContainer]) + previousTimeline = videoTimeline + // this.setValue('lastTimelineObject', videoTimeline) return videoTimeline } this.pressPlay = function (callback) {