mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
update external fancy screen
This commit is contained in:
@@ -13,16 +13,93 @@ app.use( cors() );
|
||||
|
||||
let indexedData = {};
|
||||
let coverArtIndex = {};
|
||||
const allowedFileTypes = [ '.mp3', '.wav', '.flac' ]
|
||||
const allowedFileTypes = [ '.mp3', '.wav', '.flac' ];
|
||||
|
||||
let connectedClients = [];
|
||||
|
||||
let currentDetails = {
|
||||
'songQueue': [],
|
||||
'currentlyPlaying': '',
|
||||
'pos': 0,
|
||||
'isPlaying': false
|
||||
};
|
||||
|
||||
let connectedMain = {};
|
||||
|
||||
|
||||
app.get( '/', ( request, response ) => {
|
||||
response.send( 'Hello world' );
|
||||
response.sendFile( path.join( __dirname + '/client/showcase.html' ) );
|
||||
} );
|
||||
|
||||
app.get( '/showcase.js', ( req, res ) => {
|
||||
res.sendFile( path.join( __dirname + '/client/showcase.js' ) );
|
||||
} );
|
||||
|
||||
app.get( '/showcase.css', ( req, res ) => {
|
||||
res.sendFile( path.join( __dirname + '/client/showcase.css' ) );
|
||||
} );
|
||||
|
||||
app.get( '/clientDisplayNotifier', ( req, res ) => {
|
||||
res.writeHead( 200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive',
|
||||
} );
|
||||
res.status( 200 );
|
||||
res.flushHeaders();
|
||||
let det = { 'type': 'basics', 'data': currentDetails };
|
||||
res.write( `data: ${ JSON.stringify( det ) }\n\n` );
|
||||
connectedClients.push( res );
|
||||
} );
|
||||
|
||||
app.get( '/mainNotifier', ( req, res ) => {
|
||||
const ipRetrieved = req.headers[ 'x-forwarded-for' ];
|
||||
const ip = ipRetrieved ? ipRetrieved.split( /, / )[ 0 ] : req.connection.remoteAddress;
|
||||
if ( ip === '::ffff:127.0.0.1' ) {
|
||||
res.writeHead( 200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive',
|
||||
} );
|
||||
res.status( 200 );
|
||||
res.flushHeaders();
|
||||
let det = { 'type': 'basics', 'data': currentDetails };
|
||||
res.write( `data: ${ JSON.stringify( det ) }\n\n` );
|
||||
connectedMain = res;
|
||||
} else {
|
||||
res.send( 'wrong' );
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
app.post( '/statusUpdate', ( req, res ) => {
|
||||
if ( req.body.status === 'playingSong' ) {
|
||||
|
||||
} else if ( req.body.status === 'isPlaying' ) {
|
||||
|
||||
} else if ( req.body.status === 'songQueue' ) {
|
||||
|
||||
} else if ( req.body.status === 'pos' ) {
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
app.get( '/clientStatusUpdate/:status', ( req, res ) => {
|
||||
if ( req.params.status === 'disconnect' ) {
|
||||
|
||||
} else if ( req.params.status === 'fullScreenExit' ) {
|
||||
|
||||
} else if ( req.params.status === 'inactive' ) {
|
||||
|
||||
} else if ( req.params.status === 'reactivated' ) {
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
app.get( '/openSongs', ( req, res ) => {
|
||||
res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' );
|
||||
// res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' );
|
||||
// res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' );
|
||||
res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' );
|
||||
// res.send( { 'data': dialog.showOpenDialogSync( { properties: [ 'openDirectory' ], title: 'Open music library folder' } ) } );
|
||||
} );
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
.material-symbols-outlined {
|
||||
font-variation-settings:
|
||||
'FILL' 0,
|
||||
'wght' 400,
|
||||
'GRAD' 0,
|
||||
'opsz' 24
|
||||
}
|
||||
|
||||
.voting-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.voting {
|
||||
border-radius: 500px;
|
||||
border: 1px black solid;
|
||||
font-size: 150%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.voting-counter {
|
||||
margin: 0;
|
||||
font-size: 150%;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 30vw;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
margin-bottom: 1vh;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
border: black 2px solid;
|
||||
padding: 1% 10%;
|
||||
width: 40vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.comment {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 5vh;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
background-color: lightgray;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
padding-top: 0.5vh;
|
||||
padding-bottom: 5vh,
|
||||
}
|
||||
|
||||
.content {
|
||||
display: block !important;
|
||||
}
|
||||
@@ -8,107 +8,12 @@
|
||||
<title>Showcase - MusicPlayerV2</title>
|
||||
<link rel="stylesheet" href="/showcase.css">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
<style>
|
||||
.material-symbols-outlined {
|
||||
font-variation-settings:
|
||||
'FILL' 0,
|
||||
'wght' 400,
|
||||
'GRAD' 0,
|
||||
'opsz' 24
|
||||
}
|
||||
|
||||
.voting-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.voting {
|
||||
border-radius: 500px;
|
||||
border: 1px black solid;
|
||||
font-size: 150%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.voting-counter {
|
||||
margin: 0;
|
||||
font-size: 150%;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 30vw;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
margin-bottom: 1vh;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
border: black 2px solid;
|
||||
padding: 1% 10%;
|
||||
width: 40vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.comment {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 5vh;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
background-color: lightgray;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
padding-top: 0.5vh;
|
||||
padding-bottom: 5vh,
|
||||
}
|
||||
|
||||
.content {
|
||||
display: block !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content" id="app">
|
||||
<div class="wrapper" v-if="hasLoaded">
|
||||
<img :src="" alt="">
|
||||
<h1>Ok</h1>
|
||||
<!-- <img :src="" alt=""> -->
|
||||
</div>
|
||||
<div v-else>
|
||||
<h1>Loading...</h1>
|
||||
@@ -116,6 +21,6 @@
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
||||
<script src="/js/voting.js"></script>
|
||||
<script src="/showcase.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,179 +5,50 @@ createApp( {
|
||||
data() {
|
||||
return {
|
||||
hasLoaded: false,
|
||||
|
||||
songs: {},
|
||||
playingSong: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
orderedVotes() {
|
||||
if ( this.sorting === 'oldest' ) {
|
||||
return Object.values( this.entries );
|
||||
} else if ( this.sorting === 'newest' ) {
|
||||
const ent = Object.keys( this.entries ).reverse();
|
||||
let ret = [];
|
||||
for ( let entry in ent ) {
|
||||
ret.push( this.entries[ ent[ entry ] ] );
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
let ent = Object.keys( this.entries ).sort( ( a, b ) => {
|
||||
if ( this.sorting === 'nameUp' ) {
|
||||
return this.entries[ a ].title.localeCompare( this.entries[ b ].title );
|
||||
} else if ( this.sorting === 'nameDown' ) {
|
||||
return this.entries[ b ].title.localeCompare( this.entries[ a ].title );
|
||||
} else if ( this.sorting === 'mostVoted' ) {
|
||||
return this.entries[ b ].count - this.entries[ a ].count;
|
||||
} else if ( this.sorting === 'leastVoted' ) {
|
||||
return this.entries[ a ].count - this.entries[ b ].count;
|
||||
}
|
||||
} );
|
||||
let ret = [];
|
||||
for ( let entry in ent ) {
|
||||
ret.push( this.entries[ ent[ entry ] ] );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
fetch( '/voting/get/' + location.pathname.substring( 8 ) ).then( response => {
|
||||
response.json().then( data => {
|
||||
this.fingerprint();
|
||||
this.entries = data;
|
||||
let fetchOptions = {
|
||||
method: 'post',
|
||||
body: JSON.stringify( { 'fingerprint': this.userIdentifier } ),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'charset': 'utf-8'
|
||||
},
|
||||
};
|
||||
fetch( '/voting/getVotedOn/' + location.pathname.substring( 8 ), fetchOptions ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( json => {
|
||||
this.votedOn = JSON.parse( localStorage.getItem( 'itemsVotedOn' ) ?? '{}' );
|
||||
for ( let el in json ) {
|
||||
if ( json[ el ] === 1 ) {
|
||||
this.votedOn[ json[ el ] ] = 'up';
|
||||
} else if ( json[ el ] === -1 ) {
|
||||
this.votedOn[ json[ el ] ] = 'down';
|
||||
}
|
||||
}
|
||||
localStorage.setItem( 'itemsVotedOn', JSON.stringify( this.votedOn ) );
|
||||
this.hasLoadedVotes = true;
|
||||
} );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
fetch( '/voting/getDetails/' + location.pathname.substring( 8 ) ).then( response => {
|
||||
response.json().then( data => {
|
||||
this.votingDetails = data;
|
||||
this.hasLoadedBasics = true;
|
||||
} );
|
||||
} );
|
||||
},
|
||||
save() {
|
||||
if ( this.newSuggestion.comment && this.newSuggestion.title ) {
|
||||
let alreadyExists = false;
|
||||
for ( let el in this.entries ) {
|
||||
if ( this.entries[ el ][ 'title' ].toLocaleLowerCase() === this.newSuggestion.title.toLocaleLowerCase() ) {
|
||||
alreadyExists = true;
|
||||
}
|
||||
connect() {
|
||||
let source = new EventSource( '/clientDisplayNotifier', { withCredentials: true } );
|
||||
let self = this;
|
||||
|
||||
source.onmessage = ( e ) => {
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse( e.data );
|
||||
} catch ( err ) {
|
||||
data = { 'type': e.data };
|
||||
}
|
||||
if ( !alreadyExists ) {
|
||||
let fetchOptions = {
|
||||
method: 'post',
|
||||
body: JSON.stringify( this.newSuggestion ),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'charset': 'utf-8'
|
||||
},
|
||||
};
|
||||
fetch( '/voting/add/' + location.pathname.substring( 8 ), fetchOptions ).then( response => {
|
||||
if ( response.status === 418 ) {
|
||||
alert( 'One or more of the words in either your description or title is on our blocklist. Please make sure that you are not using any words that are NSFW, racist or similar.' );
|
||||
} else if ( response.status !== 200 ) {
|
||||
alert( 'there was an error updating' );
|
||||
} else {
|
||||
this.closePopup();
|
||||
this.getData();
|
||||
}
|
||||
} );
|
||||
this.closePopup();
|
||||
this.getData();
|
||||
} else {
|
||||
alert( 'An entry with this name exists already. Please vote on that entry.' );
|
||||
if ( data.type === 'basics' ) {
|
||||
console.log( 'basics' );
|
||||
console.log( data.data );
|
||||
} else if ( data.type === 'pos' ) {
|
||||
|
||||
} else if ( data.type === 'isPlaying' ) {
|
||||
|
||||
} else if ( data.type === 'songQueue' ) {
|
||||
|
||||
} else if ( data.type === 'currentlyPlaying' ) {
|
||||
|
||||
}
|
||||
} else {
|
||||
alert( 'Not all required fields are filled out!' );
|
||||
}
|
||||
},
|
||||
fingerprint() {
|
||||
// I am forced to do this because there are idiots in this world
|
||||
// https://stackoverflow.com/questions/27247806/generate-unique-id-for-each-device
|
||||
if ( !this.userIdentifier ) {
|
||||
const navigator_info = window.navigator;
|
||||
const screen_info = window.screen;
|
||||
let uid = navigator_info.mimeTypes.length;
|
||||
uid += navigator_info.userAgent.replace( /\D+/g, '' );
|
||||
uid += navigator_info.plugins.length;
|
||||
uid += screen_info.height || '';
|
||||
uid += screen_info.width || '';
|
||||
uid += screen_info.pixelDepth || '';
|
||||
this.userIdentifier = uid;
|
||||
}
|
||||
},
|
||||
vote( type, suggestionID ) {
|
||||
this.fingerprint();
|
||||
let voteType = type;
|
||||
let didDeactivate = false;
|
||||
if ( this.votedOn[ suggestionID ] === type ) {
|
||||
didDeactivate = true;
|
||||
if ( type === 'up' ) {
|
||||
voteType = 'down';
|
||||
} else {
|
||||
voteType = 'up';
|
||||
}
|
||||
} else if ( this.votedOn[ suggestionID ] ) {
|
||||
return;
|
||||
}
|
||||
let fetchOptions = {
|
||||
method: 'post',
|
||||
body: JSON.stringify( { 'voteType': voteType, 'id': suggestionID, 'fingerprint': this.userIdentifier } ),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'charset': 'utf-8'
|
||||
},
|
||||
};
|
||||
fetch( '/voting/vote/' + location.pathname.substring( 8 ), fetchOptions ).then( response => {
|
||||
if ( response.status === 409 ) {
|
||||
alert( 'You have already voted on this!' );
|
||||
} else if ( response.status !== 200 ) {
|
||||
alert( 'there was an error updating' );
|
||||
} else {
|
||||
this.votedOn[ suggestionID ] = didDeactivate ? undefined : voteType;
|
||||
localStorage.setItem( 'itemsVotedOn', JSON.stringify( this.votedOn ) );
|
||||
this.getData();
|
||||
|
||||
source.onopen = () => {
|
||||
this.hasLoaded = true;
|
||||
};
|
||||
|
||||
source.addEventListener( 'error', function( e ) {
|
||||
if ( e.eventPhase == EventSource.CLOSED ) source.close();
|
||||
|
||||
if ( e.target.readyState == EventSource.CLOSED ) {
|
||||
console.log( 'disconnected' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
closePopup() {
|
||||
// eslint-disable-next-line no-undef
|
||||
$( '#popup' ).fadeOut( 500 );
|
||||
// eslint-disable-next-line no-undef
|
||||
$( 'body' ).removeClass( 'menuOpen' );
|
||||
this.getData();
|
||||
},
|
||||
addSuggestion () {
|
||||
// eslint-disable-next-line no-undef
|
||||
$( '#popup' ).fadeIn( 500 );
|
||||
// eslint-disable-next-line no-undef
|
||||
$( 'body' ).addClass( 'menuOpen' );
|
||||
}, false );
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
this.connect();
|
||||
}
|
||||
} ).mount( '#app' );
|
||||
|
||||
Reference in New Issue
Block a user