Upgrading Vuetify -> .16.9 Vue -> 2.5.2

This commit is contained in:
samcm 2017-11-13 12:42:21 +11:00
parent fa8127386f
commit 0ab3424e3e
19 changed files with 163 additions and 425 deletions

View File

@ -15,9 +15,9 @@
"cors": "^2.8.3",
"socket.io": "^2.0.3",
"videojs-contrib-hls": "^5.5.2",
"vue": "^2.4.2",
"vue": "^2.5.2",
"vue-router": "^2.3.1",
"vuetify": "^0.13.1"
"vuetify": "^0.16.9"
},
"devDependencies": {
"autoprefixer": "^6.7.2",

View File

@ -1,12 +1,14 @@
<template>
<v-app dark style="height:100%" toolbar>
<v-navigation-drawer temporary v-model="drawer" disable-route-watcher>
<v-app dark style="height:100%">
<v-navigation-drawer app temporary v-model="drawer" disable-route-watcher>
<leftsidebar></leftsidebar>
</v-navigation-drawer>
<v-navigation-drawer style="padding:0" persistent v-model="drawerRight" right disable-route-watcher enable-resize-watcher>
<v-navigation-drawer app
permanent
clipped v-model="drawerRight" clipped right disable-route-watcher enable-resize-watcher>
<drawerright></drawerright>
</v-navigation-drawer>
<v-toolbar>
<v-toolbar app fixed>
<v-toolbar-side-icon @click.native.stop="drawer = !drawer"></v-toolbar-side-icon>
<v-toolbar-title class="white--text">PlexTogether</v-toolbar-title>
<v-spacer></v-spacer>
@ -14,19 +16,21 @@
<img class="ma-2 mr-3" style="height:70%;width:auto" v-bind:src="logo"/>
<v-btn primary dark raised v-if="shortUrl != null" v-clipboard="shortUrl" @success="sendNotification()">Invite</v-btn>
<v-btn small tag="a" class="hidden-sm-and-down" flat v-for="item in links" :key="item.title" :href="item.href" :target="item.target">{{ item.title }}</v-btn>
<v-toolbar-side-icon v-if="showRightDrawerButton" @click.native.stop="drawerRight = !drawerRight"></v-toolbar-side-icon>
<v-toolbar-side-icon v-if="showRightDrawerButton" @click="drawerRight = !drawerRight"></v-toolbar-side-icon>
</v-toolbar-items>
</v-toolbar>
<main v-bind:style="mainStyle">
<v-container style="padding:0; height:100%; max-width:100%" v-bind:style="containerStyle">
<router-view></router-view>
<v-snackbar
bottom
:timeout="4000"
v-model="snackbar"
> <div style="text-align:center;width:100%">{{snackbarMsg}}</div>
</v-snackbar>
</v-container>
<v-content style="padding:0; max-width:100%; margin: 0; margin-top: 64px" v-bind:style="containerStyle">
<v-container fluid class="ma-0 pa-0">
<router-view></router-view>
<v-snackbar
bottom
:timeout="4000"
v-model="snackbar"
> <div style="text-align:center;width:100%">{{snackbarMsg}}</div>
</v-snackbar>
</v-container>
</v-content>
</main>
</v-app>
</template>

View File

@ -231,6 +231,29 @@ span {
/* PTPlayer */
.video-js.vjs-fluid,
.video-js.vjs-16-9,
.video-js.vjs-4-3,
video.video-js,
video.vjs-tech, {
max-height: calc(100vh - 64px);
position: relative !important;
width: 100%;
height: auto !important;
max-width: 100% !important;
padding-top: 0 !important;
line-height: 0;
}
/* Fix the control bar due to us resetting the line-height on the video-js */
.vjs-control-bar {
line-height: 1;
}
.ptplayer .video-js {
max-height: calc(100vh - 64px) !important;
}
.ptplayer .video-js .vjs-menu-button-inline.vjs-slider-active, .video-js .vjs-menu-button-inline:focus, .video-js .vjs-menu-button-inline:hover, .video-js.vjs-no-flex .vjs-menu-button-inline {
width: 10em
}

View File

@ -1,26 +1,28 @@
<template>
<div style="margin-bottom: 0; height:100%">
<div style="margin-bottom: 0; height:100%">
<div style="margin-bottom: 0; height:100%">
<v-layout row wrap style="overflow-y: scroll">
<!-- MAIN CONTENT -->
<v-layout v-if="!validDevices" wrap row style="position:relative" class="pt-4">
<v-flex xs12 md4 offset-md4>
<div style="width:100%;text-align:center">
<v-progress-circular indeterminate v-bind:size="50" class="amber--text" style="display:inline-block"></v-progress-circular>
</div>
</v-flex>
</v-layout>
<div v-if="validDevices">
<v-flex xs12 v-if="!validDevices">
<v-layout fill-height wrap row style="position:relative" class="pt-4">
<v-flex xs12 md4 offset-md4>
<div style="width:100%;text-align:center">
<v-progress-circular indeterminate v-bind:size="50" class="amber--text" style="display:inline-block"></v-progress-circular>
</div>
</v-flex>
</v-layout>
</v-flex>
<v-flex xs12 v-if="validDevices">
<div v-if="!ptConnected || !chosenClient || !ptRoom">
<walkthrough class="pa-4"></walkthrough>
</div>
<div v-else>
<plexbrowser v-if="showBrowser" class="pa-4"></plexbrowser>
<plexbrowser v-if="showBrowser" class="pa-4"></plexbrowser>
<ptplayer v-if="isPTPlayer"></ptplayer>
<plexcontent v-if="showMetadata" class="pa-4" nowPlaying :content="chosenClient.clientPlayingMetadata" :server="nowPlayingServer"></plexcontent>
</div>
</div>
</div>
</v-flex>
</v-layout>
</div>
</div>
</template>
@ -39,12 +41,10 @@
// Components
import plexclient from './application/plexclient'
import plexserver from './application/plexserver'
import ptuser from './application/ptuser'
import joinroom from './application/joinroom'
import chatmessage from './application/chatmessage'
import walkthrough from './application/walkthrough'
import sidebar from './application/sidebar'
import ptplayer from './application/ptplayer'
import plexbrowser from './application/plexbrowser'
import plexcontent from './application/plexbrowser/plexcontent'
@ -54,9 +54,7 @@
name: 'application',
components: {
plexclient,
plexserver,
joinroom,
sidebar,
ptuser,
chatmessage,
walkthrough,

View File

@ -48,7 +48,6 @@
:autofocus="true"
v-on:keyup.enter.native="joinRoom()"
v-model="room"
class="input-group"
></v-text-field>
</v-flex>
@ -59,7 +58,6 @@
label="Room password"
v-on:keyup.enter.native="joinRoom()"
v-model="password"
class="pt-0 mt-0 input-group orange--text"
></v-text-field>
</v-flex>

View File

@ -38,7 +38,7 @@
<v-flex xs12 lg12 >
<v-subheader > Movies ({{filteredMovies.length}})</v-subheader>
</v-flex>
<v-flex xs6 md3 xl1 lg2 class="pb-3" v-for="movie in filteredMovies" :key="movie.key">
<v-flex xs6 md3 xl1 lg1 class="pb-3" v-for="movie in filteredMovies" :key="movie.key">
<plexthumb :content="movie" :server="movie.server" showServer search @contentSet="setContent(movie)"></plexthumb>
</v-flex>
</v-layout>
@ -47,7 +47,7 @@
<v-flex xs12 lg12 >
<v-subheader > TV Shows ({{filteredShows.length}})</v-subheader>
</v-flex>
<v-flex xs6 md3 xl1 lg2 class="pb-3" v-for="show in filteredShows" :key="show.key">
<v-flex xs6 md3 xl1 lg1 class="pb-3" v-for="show in filteredShows" :key="show.key">
<plexthumb :content="show" :server="show.server" showServer search @contentSet="setContent(show)"></plexthumb>
</v-flex>
</v-layout>
@ -79,7 +79,7 @@
<h4> Browse </h4>
<v-layout row wrap>
<v-flex xs12 lg4 md6 xl3 v-for="server in plex.servers" :key="server.machineIdentifier" class="pa-2">
<v-card class="white--text" v-on:click="setServer(server)" horizontal height="10em" style="cursor: pointer; z-index: 0; background: rgba(0,0,0,0.4);">
<v-card class="white--text" v-on:click.native="setServer(server)" horizontal height="10em" style="cursor: pointer; z-index: 0; background: rgba(0,0,0,0.4);">
<v-container fluid grid-list-lg>
<v-layout row>
<v-flex xs4>

View File

@ -32,9 +32,9 @@
</v-flex>
<v-flex xs12 sm6 style="position:relative">
<div style="float:right">
<v-chip bottom v-tooltip:top="{ html: 'Resolution' }" class="grey darken-1 white--text" outline left> {{ largestRes }}p</v-chip>
<v-chip bottom v-tooltip:top="{ html: 'Year' }" class="grey darken-4 white--text" outline left> {{ contents.year }}</v-chip>
<v-chip v-if="contents.contentRating" v-tooltip:top="{ html: 'Content Rating' }" class="grey darken-4 white--text" small label> {{ contents.contentRating }}</v-chip>
<v-chip bottom class="grey darken-1 white--text" outline left> {{ largestRes }}p</v-chip>
<v-chip bottom class="grey darken-4 white--text" outline left> {{ contents.year }}</v-chip>
<v-chip v-if="contents.contentRating" class="grey darken-4 white--text" small label> {{ contents.contentRating }}</v-chip>
</div>
</v-flex>
</v-layout>
@ -54,9 +54,9 @@
</v-flex>
<v-flex xs12 sm6 style="position:relative">
<div style="float:right">
<v-chip bottom v-tooltip:top="{ html: 'Resolution' }" class="grey darken-1 white--text" outline left> {{ largestRes }}p</v-chip>
<v-chip v-if="contents.contentRating" v-tooltip:top="{ html: 'Content Rating' }" class="grey darken-4 white--text" small label> {{ contents.contentRating }}</v-chip>
<v-chip v-if="contents.studio" v-tooltip:top="{ html: 'Studio' }" class="grey darken-4 white--text" small label> {{ contents.studio }}</v-chip>
<v-chip bottom class="grey darken-1 white--text" outline left> {{ largestRes }}p</v-chip>
<v-chip v-if="contents.contentRating" class="grey darken-4 white--text" small label> {{ contents.contentRating }}</v-chip>
<v-chip v-if="contents.studio" class="grey darken-4 white--text" small label> {{ contents.studio }}</v-chip>
</div>
</v-flex>
</v-layout>
@ -100,14 +100,14 @@
</v-flex>
<v-flex xs12 sm6 style="position:relative">
<div style="float:right">
<v-chip v-if="contents.year" v-tooltip:top="{ html: 'Content Rating' }" class="grey darken-4 white--text" small label> {{ contents.year }}</v-chip>
<v-chip v-for="copy in contents.Media" :key="copy.key" v-tooltip:top="{ html: 'Quality' }" class="grey darken-4 white--text" small> {{ copy.audioCodec.toUpperCase() }}</v-chip>
<v-chip v-if="contents.year" class="grey darken-4 white--text" small label> {{ contents.year }}</v-chip>
<v-chip v-for="copy in contents.Media" :key="copy.key" class="grey darken-4 white--text" small> {{ copy.audioCodec.toUpperCase() }}</v-chip>
</div>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-chip v-for="country in contents.Country" :key="country.tag" v-tooltip:top="{ html: 'Country' }"> {{ country.tag }}</v-chip>
<v-chip v-for="genre in contents.Genre" :key="genre.tag" v-tooltip:top="{ html: 'Genre' }"> {{ genre.tag }}</v-chip>
<v-chip v-for="country in contents.Country" :key="country.tag"> {{ country.tag }}</v-chip>
<v-chip v-for="genre in contents.Genre" :key="genre.tag"> {{ genre.tag }}</v-chip>
</v-flex>
</v-layout>

View File

@ -11,7 +11,7 @@
</span>
<div v-if="!browsingContent && contents" class="mt-3" style="height:90vh; overflow-y:scroll ">
<v-layout class="row" row wrap>
<v-flex xs4 md3 xl1 lg2 class="pb-3" v-for="content in contents.MediaContainer.Metadata" :key="content.key">
<v-flex xs4 md3 lg1 class="pb-3" v-for="content in contents.MediaContainer.Metadata" :key="content.key">
<plexthumb :content="content" :server="server" type="thumb" style="margin:7%" @contentSet="setContent(content)"></plexthumb>
</v-flex>
</v-layout>

View File

@ -31,8 +31,8 @@
<p style="font-style: italic" class="pt-3"> {{ content.summary }} </p>
<div>
<div style="float:right" class="pa-4">
<v-chip v-if="contents.MediaContainer.grandparentContentRating" v-tooltip:top="{ html: 'Content Rating' }" label> {{ contents.MediaContainer.grandparentContentRating }}</v-chip>
<v-chip v-if="contents.MediaContainer.grandparentStudio" v-tooltip:top="{ html: 'Studio' }" secondary> {{ contents.MediaContainer.grandparentStudio }}</v-chip>
<v-chip v-if="contents.MediaContainer.grandparentContentRating" label> {{ contents.MediaContainer.grandparentContentRating }}</v-chip>
<v-chip v-if="contents.MediaContainer.grandparentStudio" secondary> {{ contents.MediaContainer.grandparentStudio }}</v-chip>
</div>
</div>
</div>
@ -45,7 +45,7 @@
<v-divider></v-divider>
<div>
<v-layout class="row mt-3" row wrap>
<v-flex xs6 md3 xl2 lg2 class="pb-3" v-for="content in contents.MediaContainer.Metadata" :key="content.key">
<v-flex xs6 md3 lg2 class="pb-3" v-for="content in contents.MediaContainer.Metadata" :key="content.key">
<plexthumb :content="content" :server="server" type="thumb" style="margin:2%" fullTitle @contentSet="setContent(content)"></plexthumb>
</v-flex>
</v-layout>

View File

@ -53,7 +53,7 @@
</v-flex>
<h4 class="mt-3"> Seasons </h4>
<v-layout class="row" row wrap>
<v-flex xs4 md3 xl1 lg2 class="pb-3" v-for="content in contents.MediaContainer.Metadata" :key="content.key">
<v-flex xs4 md3 xl1 lg1 class="pb-3" v-for="content in contents.MediaContainer.Metadata" :key="content.key">
<plexthumb :content="content" :server="server" type="thumb" style="margin:7%" @contentSet="setContent(content)"></plexthumb>
</v-flex>
</v-layout>

View File

@ -13,9 +13,9 @@
<v-progress-circular active large></v-progress-circular>
</div>
<h4> Libraries </h4>
<v-layout row wrap>
<v-flex xs6 md3 xl2 lg2 v-if="libraries && !browsingLibrary" v-for="library in filteredLibraries" :key="library.name">
<v-card v-on:click="setLibrary(library)" :img="getArtLibrary(library)" height="10em" class="text-xs-center hoverable card" style="max-width:100%">
<v-layout row wrap v-if="libraries && !browsingLibrary">
<v-flex xs6 md3 xl2 lg2 v-for="library in filteredLibraries" class="pa-3 clickable" :key="library.name">
<v-card v-on:click.native="setLibrary(library)" :img="getArtLibrary(library)" height="10em" class="text-xs-center hoverable card" style="max-width:100%">
<div style="position:relative;width:100%;background: rgba(0,0,0,0.4); height:8em">
<img style="height: 70%;display: block; margin-left: auto; margin-right: auto " :src="getThumb(library)"/>
</div>

View File

@ -1,8 +1,6 @@
<template>
<div class="portrait" ref="root" style="cursor: pointer" @mouseover="hovering = true" @mouseout="hovering = false">
<v-card data-tilt v-on:click="emitContentClicked(content)" class="grey darken-4" style="border:solid">
<v-card data-tilt v-on:click.native="emitContentClicked(content)" class="grey darken-4" style="border:solid">
<v-card-media
class="white--text"
style="position:relative"
@ -32,7 +30,7 @@
<v-progress-linear style="position:absolute; top:0; width:100%" class="pa-0 ma-0 pt-content-progress" v-if="showProgressBar" height="2" :value="unwatchedPercent"></v-progress-linear>
<v-layout row wrap class="text-xs-left" style="margin:0; margin-left:3px; display:block; max-width:100%; height:100%">
<v-flex v-if="!onlyBottom" xs12 style="height:50%" :style="topTextStyle" ref="topText" class="pa-0 ma-0 ml-1 mt-1">
<div v-tooltip:top="{ html: getTitle(content) }" class="truncate" style="font-size:1rem">{{ getTitle(content) }}</div>
<div class="truncate" style="font-size:1rem">{{ getTitle(content) }}</div>
</v-flex>
<v-flex xs12 style="height:50%; font-size:0.8rem" :style="bottomTextStyle" ref="bottomText" class="pa-0 ma-0 mt-0 ml-1">
<div class="truncate soft-text" style=" position:absolute; bottom:0">{{ getUnder(content) }}</div>

View File

@ -1,18 +0,0 @@
<template>
<div v-tooltip="tooltipMsg" class="mdc-list-item" href="#" style="height: 30px">
{{ object.name }}
</div>
</template>
<script>
export default {
props: ['object'],
name: 'plexserver',
computed: {
tooltipMsg: function () {
return this.object.name + ' running on ' + this.object.platform + ' (Version ' + this.object.productVersion + ')'
}
}
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<div style="width:100%; height:100%">
<div style="width:100%; max-height: calc(100vh - 64px)">
<videoplayer v-if="playingMetadata && chosenServer && chosenQuality && ready"
@playerMounted="playerMounted()"
@timelineUpdate="timelineUpdate"

View File

@ -235,21 +235,6 @@
// console.log('Succesfully sent Player status to PMS')
}
})
},
computed: {
player () {
@ -272,7 +257,7 @@
// videojs options
plugins: {},
fluid: true,
fluid: false,
preload: 'auto',
volume: 0.5,
aspectRatio: '16:9',
@ -397,7 +382,7 @@
console.log(player)
},
playerStateChanged (playerCurrentState) {
console.log("Setting volume to " + this.player.volume() || 0)
// console.log("Setting volume to " + this.player.volume() || 0)
this.$store.commit('setSettingPTPLAYERVOLUME', this.player.volume() || 0)
this.bufferedTill = Math.round(this.player.buffered().end(0) * 1000)
this.duration = Math.round(this.player.duration() * 1000)
@ -421,7 +406,7 @@
})
},
playerReadied (player) {
console.log('Setting volume to ' + this.$store.getters.getSettingPTPLAYERVOLUME )
// console.log('Setting volume to ' + this.$store.getters.getSettingPTPLAYERVOLUME )
this.player.volume(this.$store.getters.getSettingPTPLAYERVOLUME || 0)
},

View File

@ -1,253 +0,0 @@
<template>
<div v-if="chosenClient && plex" class="col l2 s12" v-bind:style="{ position: isMobile }"
style="border-right-color: rgba(0,0,0,0.1); border-right-width: 1px; border-right-style: solid; border-bottom-color: rgba(0,0,0,0.1); border-bottom-width: 1px; border-bottom-style: solid; width: 100% min-height: 50%;">
<div style="overflow-y: auto;max-height: 50%;">
<div class="mdc-list">
<li v-if="chosenClient" class="mdc-list-item mdc-permanent-drawer--selected plex-gamboge-text truncate"
href="#">
Plex Players {{playercount}}
</li>
<li v-if="plex && chosenClient" v-for="client in clients" id="plexPlayers">
<plexclient :sidebar="true" :object="client"></plexclient>
</li>
</div>
<div v-if="ptConnected" style="margin-bottom: 20px">
<div class="mdc-list">
<li class="mdc-list-item mdc-permanent-drawer--selected plex-gamboge-text" href="#">
PT Server
</li>
<li class="mdc-list-item truncate" style="height: 30px" id="plexTogetherServerAddress">
{{ ptServer }}
</li>
</div>
<div class="mdc-list">
<li class="mdc-list-item mdc-permanent-drawer--selected plex-gamboge-text" href="#">
PT Room
</li>
<li class="mdc-list-item truncate" style="height: 30px" id="plexTogetherRoomName">
{{ ptRoom }}
</li>
</div>
<div v-if="ptPassword" class="mdc-list">
<li class="mdc-list-item mdc-permanent-drawer--selected plex-gamboge-text" href="#">
PT Password
</li>
<li class="mdc-list-item truncate" style="height: 30px" id="plexTogetherRoomPassword">
{{ ptPassword }}
</li>
</div>
</div>
</div>
<div class="row" style="position: absolute;left: 0; margin-bottom: 0; width:100%" v-bind:style="mobileStyle">
<div v-if="plex && chosenClient" class="plexTogetherInfo col l12 s12"
style="padding-top: 11.25px; min-height:30%; max-height:50%; padding-left: 0; padding-right: 0">
<div class="row" v-if="chosenClient.clientPlayingMetadata" style="margin-bottom: 0;" id="userMetadata">
<div class="col s12 center">
<img id="metaThumb" :src="metadataThumb" style="max-height: 30%; max-width: 100%">
</div>
<div class="col s12 center white-text" id="metaUnder" style="padding-bottom: 10px;">
{{ metadataTitle }}
<br> {{ metadataInfo }}
<br> <label>Playing on {{ metadataServer }}</label>
</div>
</div>
<div v-if="ptConnected" class="col s12" style="padding:0">
<button class="mdc-button mdc-button--raised mdc-button--accent plex-gamboge ptSettings disconnect"
id="plexTogetherLeaveButton" style="width: 100%;" v-on:click="handleDisconnect()">
Disconnect
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import plexclient from './plexclient'
import plexserver from './plexserver'
export default {
props: ['object', 'mobile'],
name: 'sidebar',
data () {
return {
testClient: null
}
},
components: {
plexclient,
plexserver,
},
computed: {
mobileStyle: function () {
if (!this.mobile) {
return {
bottom: '0px'
}
}
return {}
},
chosenClient: function () {
return this.$store.getters.getChosenClient
},
plex: function () {
return this.$store.getters.getPlex
},
clients: function () {
return this.$store.getters.getPlex.clients
},
context: function () {
return this.$store
},
logo: function () {
if (this.$store.getters.getSettingDARKMODE) {
return 'ptweb/logo-long-light.png'
}
return 'ptweb/logo-long-dark.png'
},
ptConnected: function () {
return this.$store.getters.getConnected
},
ptServer: function () {
return this.$store.getters.getServer
},
ptRoom: function () {
return this.$store.getters.getRoom
},
ptPassword: function () {
return this.$store.getters.getPassword
},
validPlex: function () {
if (!this.$store.state.plex) {
return false
}
return true
},
playercount: function () {
if (this.$store.state.plex && this.$store.state.plex.gotDevices) {
return '(' + this.$store.state.plex.clients.length + ')'
}
return ''
},
servercount: function () {
if (this.$store.state.plex && this.$store.state.plex.gotDevices) {
return '(' + this.$store.state.plex.servers.length + ')'
}
return ''
},
metadataThumb: function () {
if (!this.validPlex) {
return ''
}
let plexObj = this.$store.state.plex
if (!this.$store.getters.getChosenClient) {
return ''
}
let metadata = this.$store.getters.getChosenClient.clientPlayingMetadata
if (!metadata) {
return ''
}
let server;
let content = metadata.thumb;
if (metadata.parentThumb) {
content = metadata.parentThumb
}
if (!plexObj.getServerById(metadata.machineIdentifier)) {
return ''
}
return plexObj.getServerById(metadata.machineIdentifier).getUrlForLibraryLoc(content)
},
metadataServer: function () {
if (!this.validPlex) {
return ''
}
if (!this.$store.getters.getChosenClient) {
return ''
}
let metadata = this.$store.getters.getChosenClient.clientPlayingMetadata
if (!metadata) {
return ''
}
return (this.plex.getServerById(this.chosenClient.clientPlayingMetadata.machineIdentifier).name)
},
metadataTitle: function () {
if (!this.validPlex) {
return ''
}
if (!this.$store.getters.getChosenClient) {
return ''
}
let metadata = this.$store.getters.getChosenClient.clientPlayingMetadata
if (!metadata) {
return ''
}
if (metadata.type == 'movie') {
return metadata.title
}
if (metadata.type == 'episode') {
return metadata.grandparentTitle
}
return metadata.index
},
metadataInfo: function () {
if (!this.validPlex) {
return ''
}
if (!this.$store.getters.getChosenClient) {
return ''
}
let metadata = this.$store.getters.getChosenClient.clientPlayingMetadata
if (!metadata) {
return ''
}
if (metadata.type == 'movie') {
return metadata.year
}
if (metadata.type == 'episode') {
return metadata.title + ' (S' + metadata.parentIndex + '·E' + metadata.index + ')'
}
return metadata.index
},
isMobile: function () {
if (!this.mobile) {
return 'relative'
}
return ''
},
},
methods: {
previewClient: function (client) {
this.testClient = client
},
clientClicked: function (client) {
let clients = this.$store.getters.getPlex.clients
for (let i = 0; i < clients.length; i++) {
let _client = clients[i]
_client.connectedstatus = 'fresh'
}
//this.$store.state.plex.chosenClient = null
client.connectedstatus = 'waiting'
let that = this
client.findConnection(function (res) {
let plexObj = that.$store.state.plex
if (res) {
client.connectedstatus = 'connected'
that.$store.commit('SET_CHOSENCLIENT', client)
} else {
client.connectedstatus = 'failed'
}
})
},
handleDisconnect: function () {
this.$store.dispatch('disconnectServer')
},
openJoinRoomModal: function () {
return this.$parent.$refs.joinroomModal.open()
},
}
}
</script>

View File

@ -1,8 +1,8 @@
<template>
<v-layout >
<v-flex xs12 lg8 offset-lg2 xl6 offset-xl3 style="background: rgba(0,0,0,0.1); border-radius: 10px" class="pa-4">
<v-layout row wrap>
<v-flex xs12 md8 offset-md2 lg4 offset-lg4 xl6 offset-xl3>
<v-layout row wrap justify-center>
<v-flex xs12 lg8 xl6 style="background: rgba(0,0,0,0.1); border-radius: 10px" class="pa-4">
<v-layout row wrap justify-center>
<v-flex xs12 md8 lg4 xl6>
<img style="width:100%" v-bind:src="logo">
</v-flex>
</v-layout>
@ -28,7 +28,7 @@
<v-divider></v-divider>
<v-layout row wrap>
<v-flex xs12 md6 lg7>
<v-subheader light>Plex Players {{ playercount }}</v-subheader>
<v-subheader>Plex Players {{ playercount }}</v-subheader>
<div v-for="i in plex.clients" :key="i.clientIdentifier">
<div v-on:click="previewClient(i)">
<plexclient :startup="testClient" :sidebar="false" :selected="isClientSelected(i)" :object="i" style="cursor: pointer"></plexclient>
@ -37,11 +37,11 @@
</v-flex>
<v-flex xs12 md6 lg5>
<div v-if="testClient">
<v-subheader light>
<v-subheader>
Selected Player
</v-subheader>
<div class="pl-1">
<h6 light style="opacity:1">{{ testClient.name }}</h6>
<h6 style="opacity:1">{{ testClient.name }}</h6>
<div>
<label >Last seen</label><span style="opacity:0.8"> {{ lastSeenAgo(testClient.lastSeenAt) }}</span>
</div>
@ -98,7 +98,6 @@
<script>
import plexclient from './plexclient'
import plexserver from './plexserver'
import joinroom from './joinroom'
import moment from '../../../node_modules/moment/moment.js'
@ -115,7 +114,6 @@
},
components: {
plexclient,
plexserver,
joinroom
},
computed: {

View File

@ -10,13 +10,13 @@
<h1 style="color:white">G'day</h1>
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs12 md6 offset-md3>
<v-layout row wrap justify-center>
<v-flex xs12 md6>
<p> PlexTogether is a tool to sync Plex playback with friends and family anywhere in the world.
We started off with a Python script which we distributed amongst our friends. With a command line based UI we quickly realised this was too difficult for our friends to use reliably.
After playing around with the concept we decided to make a version that we could release that all Plex users could enjoy.
</p>
<h2> How it works </h2>
<h4> How it works </h4>
<p>
PlexTogether aims to keep multiple viewing sessions in sync regardless of whether the clients are in the same room or across the globe. To do this PlexTogether utilizes a middle-man server to communicate between each of PlexTogether clients.
Users choose their Plex client, decide on a PlexTogether Server and Room name and join up. Your friends/family can do the same. Whoever joins the room first will become the host.

View File

@ -1,70 +1,75 @@
<template>
<div v-if="ptRoom" class="pl-1 pr-1" style="height:100%; overflow-x:hidden;">
<div style="height:60%">
<h6 style="text-align:center" class="mb-0 pb-0 pt-3"> Room {{ ptRoom }}</h6>
<v-subheader>Users ({{ ptUsers.length }})</v-subheader>
<v-list dense style="height:90%; overflow-y:scroll">
<div v-for="user in ptUsers" v-bind:key="user.username" style="position:relative;height:7em">
<v-list-item style="height:4em" class="mb-0 pb-0">
<v-list-tile avatar class="pb-0 mb-0" tag="div" >
<v-list-tile-avatar>
<img v-bind:src="user.avatarUrl"/>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title> {{ user.username }}</v-list-tile-title>
<v-list-tile-sub-title style="opacity:0.6;color:white;font-size:70%"><v-icon style="font-size:90%">{{playerState(user)}}</v-icon> - {{getTitle(user)}}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action v-if="isHost(user)">
<v-icon v-if="isHost(user)" style="color: #E5A00D">star</v-icon>
</v-list-tile-action>
</v-list-tile>
</v-list-item>
<div style="width:100%;" class="pl-2 pr-2 pt-2 mt-0 pb-0 mb-0">
<span style="float: left;font-size:70%" class="ptuser-time pl-2">{{ getCurrent(user) }}</span>
<span style="float: right;font-size:70%" class="ptuser-maxTime pr-2">{{ getMax(user) }}</span>
<v-progress-linear class="pt-content-progress " :height="2" :value="percent(user)"></v-progress-linear>
<v-container class="pa-0" fill-height>
<v-layout column v-if="ptRoom" class="pl-2 pr-2" style="">
<v-flex xs12 style="height: 50vh">
<h6 style="text-align:center" class="mb-0 pb-0 pt-3"> Room {{ ptRoom }}</h6>
<v-subheader>Users ({{ ptUsers.length }})</v-subheader>
<v-list dense style="overflow-y:scroll">
<div v-for="user in ptUsers" v-bind:key="user.username" style="position:relative;height:7em">
<v-list-item style="height:4em" class="mb-0 pb-0">
<v-list-tile avatar class="pb-0 mb-0" tag="div" >
<v-list-tile-avatar>
<img v-bind:src="user.avatarUrl"/>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title> {{ user.username }}</v-list-tile-title>
<v-list-tile-sub-title style="opacity:0.6;color:white;font-size:70%"><v-icon style="font-size:90%">{{playerState(user)}}</v-icon> - {{getTitle(user)}}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action v-if="isHost(user)">
<v-icon v-if="isHost(user)" style="color: #E5A00D">star</v-icon>
</v-list-tile-action>
</v-list-tile>
</v-list-item>
<div class="pl-2 pr-2 pt-2 mt-0 pb-0 mb-0">
<span style="float: left;font-size:70%" class="ptuser-time pl-2">{{ getCurrent(user) }}</span>
<span style="float: right;font-size:70%" class="ptuser-maxTime pr-2">{{ getMax(user) }}</span>
<v-progress-linear class="pt-content-progress " :height="2" :value="percent(user)"></v-progress-linear>
</div>
<v-divider class="mt-0 pt-0" style="height:2px; color:white"></v-divider>
</div>
<v-divider class="mt-0 pt-0" style="height:2px; color:white" light></v-divider>
</div>
</v-list>
</div>
<div style="overflow-y: auto; height: 30%">
<div style="height:100%">
<v-divider></v-divider>
<v-subheader style="height:10%" light>Messages</v-subheader>
<v-list id="chatbox" :style="chatboxStyle" style="overflow-y:scroll; height:90%">
<v-list-item style="min-height:50px" v-bind:id="getMsgId(msg)" v-for="msg in messages" v-bind:key="msg.msg + msg.time">
<v-list-tile style="height:initial; position:relative" tag="div">
<v-list-tile-avatar>
<img v-bind:src="msg.user.thumb || msg.user.avatarUrl" style="position:absolute;top:0"/>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title style="color:white; position:relative; height:35%">
<span style="opacity:1;font-size:80%; float:left"> {{ msg.user.username }}</span>
<span style="opacity:0.6;font-size:60%; float:right"> {{ msg.time}}</span>
</v-list-tile-title>
<v-list-tile-sub-title style="opacity:0.8;color:white;font-size:70%; height:65%"> {{ msg.msg }}</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list-item>
</v-list>
</div>
</div>
<div style="height: 10%; position:relative" class="pt-2">
<v-text-field
class="pa-1 ma-0"
name="input-1"
prepend-icon="message"
:label="'Send a message to ' + '#'+ptRoom"
autoGrow
v-on:keyup.enter.native="sendMessage()"
v-model="messageToBeSent"
></v-text-field>
<v-btn style="width:100%; position:absolute; bottom:0" v-on:click.native="handleDisconnect()" class="ma-0 mt-1" primary>Leave room </v-btn>
</div>
</div>
</v-flex>
<v-flex xs12 style="overflow-y: auto; max-height: 50vh">
<v-container class="ma-0 pa-0" fill-height>
<v-layout column>
<v-flex xs12>
<v-divider></v-divider>
<v-subheader>Messages</v-subheader>
<v-list id="chatbox" :style="chatboxStyle" style="overflow-y:scroll; max-height: 34vh">
<v-list-item style="min-height:50px" v-bind:id="getMsgId(msg)" v-for="msg in messages" v-bind:key="msg.msg + msg.time">
<v-list-tile style="height:initial; position:relative" tag="div">
<v-list-tile-avatar>
<img v-bind:src="msg.user.thumb || msg.user.avatarUrl" style="position:absolute;top:0; width: 36px; height: 36px"/>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title style="color:white; position:relative;">
<span style="opacity:1;font-size:80%; float:left"> {{ msg.user.username }}</span>
<span style="opacity:0.6;font-size:60%; float:right"> {{ msg.time}}</span>
</v-list-tile-title>
<v-list-tile-sub-title style="opacity:0.8;color:white;font-size:70%;"> {{ msg.msg }}</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list-item>
</v-list>
</v-flex>
<v-flex xs12 style="position:relative" class="pt-2">
<div style="position:absolute; bottom:0; width: 100%" class="ma-0 pa-0">
<v-text-field
prepend-icon="message"
:label="'Send a message to ' + '#'+ptRoom"
autoGrow
v-on:keyup.enter.native="sendMessage()"
v-model="messageToBeSent"
></v-text-field>
<v-btn block v-on:click.native="handleDisconnect()" class="ma-0 mt-1" primary>Leave room </v-btn>
</div>
</v-flex>
</v-layout>
</v-container>
</v-flex>
</v-layout>
</v-container>
</template>
<script>