mStream/public/remote.html
2017-02-08 14:28:27 -05:00

420 lines
9.9 KiB
HTML

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta content="yes" name="mobile-web-app-capable">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<link rel="apple-touch-icon" href="/public/img/apple-icon/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="76x76" href="/public/img/apple-icon/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="120x120" href="/public/img/apple-icon/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="152x152" href="/public/img/apple-icon/apple-touch-icon-152x152.png">
<link rel="shortcut icon" sizes="120x120" href="/public/img/apple-icon/apple-touch-icon-120x120.png">
<link rel="shortcut icon" type="image/png" href="/public/favicon.png" />
<title>mStream Media Player - All your media. Everywhere you go.</title>
<!-- mStream CSS -->
<link rel="stylesheet" href="/public/css/remote.css">
<!-- Pure CSS -->
<link rel="stylesheet" href="https://unpkg.com/purecss@0.6.1/build/pure-min.css"
integrity="sha384-CCTZv2q9I9m3UOxRLaJneXrrqKwUNOzZ6NGEUMwHtShDJ+nCoiXJCAgi05KfkLGY"
crossorigin="anonymous">
<script src="/public/js/mstream.api.js"></script>
<!-- https://github.com/js-cookie/js-cookie -->
<script type="text/javascript" src="/public/js/lib/cookie.js"></script>
<!-- Vue JS -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<style>
.remote-controls{
position:absolute;
bottom:0;
width:100%;
height: 50px;
overflow: hidden;
}
.previous-button{
position:relative;
height: 100%;
width:34%;
background-color: #333333;
float:left;
overflow:hidden;
box-shadow: 5px 0 8px -2px rgba(31, 73, 125, 0.8), -5px 0 8px -2px rgba(31, 73, 125, 0.8);
cursor:pointer;
}
.play-pause-button{
height: 100%;
width:33%;
background-color: rgb(102, 132, 178);
float:left;
overflow:hidden;
cursor:pointer;
}
.next-border{
height: 100%;
padding: 8px;
}
.previous-border{
height: 100%;
padding: 8px;
}
.play-pause-border{
border-left: 5px solid rgb(102, 132, 178);
border-top: 5px solid rgb(102, 132, 178);
height: 100%;
padding: 3px;
}
.next-button{
height: 100%;
width:33%;
background-color: #333333;
float:left;
position: relative;
overflow:hidden;
box-shadow: 5px 0 8px -2px rgba(31, 73, 125, 0.8), -5px 0 8px -2px rgba(31, 73, 125, 0.8);
cursor:pointer;
}
.center{
top:50%;
left:50%;
position: absolute;
transform: translate(-50%, -50%);
}
.login-overlay{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:rgba(255,255,255,0.9);
z-index:9;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0
}
</style>
<!--TODO: This needs to be removed before feature goes live -->
<script>
var remoteProperties = {
code: 0,
guest: false,
error: false,
token: false
};
// Auto Focus
Vue.directive('focus', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
})
window.onload = function(){
$.ajaxPrefilter(function( options ) {
options.beforeSend = function (xhr) {
xhr.setRequestHeader('x-access-token', remoteProperties.token);
}
});
// TODO: Handle guest controls
// TODO: Pull code from cookies and try it
function tryToGetCookieAndEatIt(){
var token = Cookies.get('code');
}
// Prompt user for code
// Check code against server
// Store code
// Function to send commands to server
function sendCommandToServer(command, file = false){
var sendData = JSON.stringify({
code: remoteProperties.code,
command: command,
file: file,
});
var request = $.ajax({
url: "jukebox/push-to-client",
type: "POST",
data: { json : sendData },
});
request.done(function( msg ) {
var parsedMessage = $.parseJSON(msg);
// TODO:
});
request.fail(function( jqXHR, textStatus ) {
// TODO: IF you get an access denied error, try re-validating the code. It could be the token expired
// TODO: clear remoteProperties if token doesn't exist anymore
});
}
$('#next-button').on('click', function(){
sendCommandToServer('next');
});
$('#play-pause-button').on('click', function(){
sendCommandToServer('playPause');
});
$('#previous-button').on('click', function(){
sendCommandToServer('previous');
});
var loginPanel = new Vue({
el: '#login-overlay',
data: {
remote: remoteProperties,
},
methods: {
submitCode: function(e){
// Get Code
var loginCode = $('#login-code').val();
// Check Code Against Server
var request = $.ajax({
url: "jukebox/does-code-exist",
type: "POST",
data: {code: loginCode},
});
request.done(function( msg ) {
// var parsedMessage = $.parseJSON(msg);
if(msg.status === true){
remoteProperties.error = false;
remoteProperties.code = loginCode;
remoteProperties.guest = msg.guestStatus;
remoteProperties.token = msg.token;
// Load up the panel
MSTREAMAPI.getCurrentDirectoryContents();
}else{
remoteProperties.error = 'Code Not Found';
}
});
request.fail(function( jqXHR, textStatus ) {
remoteProperties.error = 'Failed To Connect To Server';
});
}
}
});
// Template for data items
Vue.component('browser-item', {
template: '<div v-on:click="handleClick($event)" class="browser-item">{{displayText}}</div>',
props: ['type', 'item'],
// We need the positionCache to track the currently playing song
data: function(){
return {
// positionCache: MSTREAM.positionCache,
}
},
// Methods used by playlist item events
methods: {
// On Click
handleClick: function(event){
console.log('CLICK');
// get data type
var thisType = this.type;
// TODO: do something based on data type
if(this.type === 'file'){
console.log('FILE CLICK!');
// TODO: Send to remote
}else if( this.type === 'directory'){
console.log('DIRECTORY CLICK!');
MSTREAMAPI.goToNextDirectory(this.item.name);
}
},
},
computed: {
displayText: function(){
// Get Type
// render based on type
// FIXME: Temp workaround
return this.item.name;
}
}
});
var browserPanel = new Vue({
el: '#browser-container',
data: {
dataList: MSTREAMAPI.dataList,
currentProperties: MSTREAMAPI.currentProperties
},
computed: {
titleText: function(){
// FIXME: Temp workaround
return 'File Explorer';
}
}
});
// MSTREAMAPI.getCurrentDirectoryContents();
}
</script>
</head>
<body>
<div v-if="remote.code === 0" id="login-overlay" class="login-overlay">
<div class="pure-g">
<div class="pure-u-1-3"><p></p></div>
<div class="pure-u-1-3">
<img class="login-icon" src="/public/img/mstream-icon.svg">
<form id="login-form" class="login-form" v-on:submit.prevent="submitCode($event)">
<div>
<label>Code</label>
<input v-focus required type="text" class="form-control" id="login-code">
</div>
<button id="login-submit" type="submit" class="btn">Login</button
</form>
<div v-show="remote.error !== false" id="login-alert" class="">{{remote.error}}</div>
</div>
<div class="pure-u-1-3"><p></p></div>
</div>
</div>
<!-- Header -->
<div class="header">
<div class="logo-box">
<img class="mstream-image" src="/public/img/mstream-logo.svg">
</div>
</div>
<!-- Browser -->
<div id="browser-container" class="browser-container">
<!-- Browser Header -->
<div class="browser-header">
<div class="browser-header-text">{{titleText}}</div>
<div class="button-group">
<div class="repeat"></div>
<div></div>
<div></div>
</div>
</div>
<!-- ToolBar -->
<div class="browser-tools">
</div>
<!-- List Area -->
<div id="browser" class="browser">
<div v-for="(item, index) in dataList" :item="item" :type="item.type" is="browser-item" :key="index">
</div>
</div>
</div>
<!-- Controls -->
<div class="remote-controls">
<div id="previous-button" class="previous-button">
<img class="previous-image center" src="/public/img/previous-white.svg">
</div>
<div id="play-pause-button" class="play-pause-button">
<img id="play-pause-image" class="play-pause-image center" src="/public/img/play-white.svg" >
</div>
<div id="next-button" class="next-button">
<img class="mext-image center" src="/public/img/next-white.svg">
</div>
</div>
</body>