mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 04:54:23 +00:00
lots more progress on apple music integration
This commit is contained in:
@@ -11,6 +11,10 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="info">Designed and developed by Janis Hutz <a href="https://janishutz.com" target="_blank" style="text-decoration: none; color: white;">https://janishutz.com</a></div>
|
<div class="info">Designed and developed by Janis Hutz <a href="https://janishutz.com" target="_blank" style="text-decoration: none; color: white;">https://janishutz.com</a></div>
|
||||||
|
<div class="content loading" id="loading">
|
||||||
|
<h1>Loading...</h1>
|
||||||
|
<p>Please wait</p>
|
||||||
|
</div>
|
||||||
<div class="content" id="app">
|
<div class="content" id="app">
|
||||||
<div v-if="hasLoaded" style="width: 100%">
|
<div v-if="hasLoaded" style="width: 100%">
|
||||||
<div class="current-song-wrapper">
|
<div class="current-song-wrapper">
|
||||||
|
|||||||
@@ -21,12 +21,21 @@ body {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: none;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loaded {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
.playing-symbols {
|
.playing-symbols {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10vw;
|
left: 10vw;
|
||||||
|
|||||||
@@ -98,6 +98,16 @@ createApp( {
|
|||||||
|
|
||||||
source.onopen = () => {
|
source.onopen = () => {
|
||||||
this.hasLoaded = true;
|
this.hasLoaded = true;
|
||||||
|
if ( document.fonts.status === 'loaded' ) {
|
||||||
|
document.getElementById( 'loading' ).classList.remove( 'loading' );
|
||||||
|
document.getElementById( 'app' ).classList.add( 'loaded' );
|
||||||
|
} else {
|
||||||
|
document.fonts.onloadingdone = () => {
|
||||||
|
document.getElementById( 'loading' ).classList.remove( 'loading' );
|
||||||
|
document.getElementById( 'app' ).classList.add( 'loaded' );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ app.get( '/useAppleMusic', ( req, res ) => {
|
|||||||
|
|
||||||
app.get( '/openSongs', ( req, res ) => {
|
app.get( '/openSongs', ( req, res ) => {
|
||||||
// res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' );
|
// res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' );
|
||||||
res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' );
|
// res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' );
|
||||||
// res.send( { 'data': dialog.showOpenDialogSync( { properties: [ 'openDirectory' ], title: 'Open music library folder' } ) } );
|
res.send( { 'data': dialog.showOpenDialogSync( { properties: [ 'openDirectory' ], title: 'Open music library folder' } ) } );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
app.get( '/showcase.js', ( req, res ) => {
|
app.get( '/showcase.js', ( req, res ) => {
|
||||||
|
|||||||
56
frontend/src/client/appleMusic/appleMusicIcon.svg
Normal file
56
frontend/src/client/appleMusic/appleMusicIcon.svg
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="361px" height="361px" viewBox="0 0 361 361" style="enable-background:new 0 0 361 361;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_1_);}
|
||||||
|
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<g id="Layer_5">
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="180" y1="358.6047" x2="180" y2="7.7586">
|
||||||
|
<stop offset="0" style="stop-color:#FA233B"/>
|
||||||
|
<stop offset="1" style="stop-color:#FB5C74"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path class="st0" d="M360,112.61c0-4.3,0-8.6-0.02-12.9c-0.02-3.62-0.06-7.24-0.16-10.86c-0.21-7.89-0.68-15.84-2.08-23.64
|
||||||
|
c-1.42-7.92-3.75-15.29-7.41-22.49c-3.6-7.07-8.3-13.53-13.91-19.14c-5.61-5.61-12.08-10.31-19.15-13.91
|
||||||
|
c-7.19-3.66-14.56-5.98-22.47-7.41c-7.8-1.4-15.76-1.87-23.65-2.08c-3.62-0.1-7.24-0.14-10.86-0.16C255.99,0,251.69,0,247.39,0
|
||||||
|
H112.61c-4.3,0-8.6,0-12.9,0.02c-3.62,0.02-7.24,0.06-10.86,0.16C80.96,0.4,73,0.86,65.2,2.27c-7.92,1.42-15.28,3.75-22.47,7.41
|
||||||
|
c-7.07,3.6-13.54,8.3-19.15,13.91c-5.61,5.61-10.31,12.07-13.91,19.14c-3.66,7.2-5.99,14.57-7.41,22.49
|
||||||
|
c-1.4,7.8-1.87,15.76-2.08,23.64c-0.1,3.62-0.14,7.24-0.16,10.86C0,104.01,0,108.31,0,112.61v134.77c0,4.3,0,8.6,0.02,12.9
|
||||||
|
c0.02,3.62,0.06,7.24,0.16,10.86c0.21,7.89,0.68,15.84,2.08,23.64c1.42,7.92,3.75,15.29,7.41,22.49c3.6,7.07,8.3,13.53,13.91,19.14
|
||||||
|
c5.61,5.61,12.08,10.31,19.15,13.91c7.19,3.66,14.56,5.98,22.47,7.41c7.8,1.4,15.76,1.87,23.65,2.08c3.62,0.1,7.24,0.14,10.86,0.16
|
||||||
|
c4.3,0.03,8.6,0.02,12.9,0.02h134.77c4.3,0,8.6,0,12.9-0.02c3.62-0.02,7.24-0.06,10.86-0.16c7.89-0.21,15.85-0.68,23.65-2.08
|
||||||
|
c7.92-1.42,15.28-3.75,22.47-7.41c7.07-3.6,13.54-8.3,19.15-13.91c5.61-5.61,10.31-12.07,13.91-19.14
|
||||||
|
c3.66-7.2,5.99-14.57,7.41-22.49c1.4-7.8,1.87-15.76,2.08-23.64c0.1-3.62,0.14-7.24,0.16-10.86c0.03-4.3,0.02-8.6,0.02-12.9V112.61
|
||||||
|
z"/>
|
||||||
|
</g>
|
||||||
|
<g id="Glyph_2_">
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M254.5,55c-0.87,0.08-8.6,1.45-9.53,1.64l-107,21.59l-0.04,0.01c-2.79,0.59-4.98,1.58-6.67,3
|
||||||
|
c-2.04,1.71-3.17,4.13-3.6,6.95c-0.09,0.6-0.24,1.82-0.24,3.62c0,0,0,109.32,0,133.92c0,3.13-0.25,6.17-2.37,8.76
|
||||||
|
c-2.12,2.59-4.74,3.37-7.81,3.99c-2.33,0.47-4.66,0.94-6.99,1.41c-8.84,1.78-14.59,2.99-19.8,5.01
|
||||||
|
c-4.98,1.93-8.71,4.39-11.68,7.51c-5.89,6.17-8.28,14.54-7.46,22.38c0.7,6.69,3.71,13.09,8.88,17.82
|
||||||
|
c3.49,3.2,7.85,5.63,12.99,6.66c5.33,1.07,11.01,0.7,19.31-0.98c4.42-0.89,8.56-2.28,12.5-4.61c3.9-2.3,7.24-5.37,9.85-9.11
|
||||||
|
c2.62-3.75,4.31-7.92,5.24-12.35c0.96-4.57,1.19-8.7,1.19-13.26l0-116.15c0-6.22,1.76-7.86,6.78-9.08c0,0,88.94-17.94,93.09-18.75
|
||||||
|
c5.79-1.11,8.52,0.54,8.52,6.61l0,79.29c0,3.14-0.03,6.32-2.17,8.92c-2.12,2.59-4.74,3.37-7.81,3.99
|
||||||
|
c-2.33,0.47-4.66,0.94-6.99,1.41c-8.84,1.78-14.59,2.99-19.8,5.01c-4.98,1.93-8.71,4.39-11.68,7.51
|
||||||
|
c-5.89,6.17-8.49,14.54-7.67,22.38c0.7,6.69,3.92,13.09,9.09,17.82c3.49,3.2,7.85,5.56,12.99,6.6c5.33,1.07,11.01,0.69,19.31-0.98
|
||||||
|
c4.42-0.89,8.56-2.22,12.5-4.55c3.9-2.3,7.24-5.37,9.85-9.11c2.62-3.75,4.31-7.92,5.24-12.35c0.96-4.57,1-8.7,1-13.26V64.46
|
||||||
|
C263.54,58.3,260.29,54.5,254.5,55z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -11,12 +11,25 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div v-if="!isLoggedIn">
|
<div v-if="isPreparingToPlay" class="preparingToPlay">
|
||||||
<h1>Apple Music</h1>
|
<span class="material-symbols-outlined loading-spinner">autorenew</span>
|
||||||
<button @click="logInto()">Log in</button>
|
<h1>Loading player...</h1>
|
||||||
|
</div>
|
||||||
|
<div v-if="!isLoggedIn" class="start-page">
|
||||||
|
<div class="image-wrapper">
|
||||||
|
<img src="/logo.png" alt="Music player icon" id="logo-main">
|
||||||
|
<img src="/apple-music/helpers/appleMusicIcon.svg" alt="Apple Music Icon" id="apple-music-logo">
|
||||||
|
</div>
|
||||||
|
<h1>Apple Music integration</h1>
|
||||||
|
<button @click="logInto()" class="button">Log in</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="home">
|
<div v-else class="home">
|
||||||
<div v-if="!hasSelectedPlaylist" class="song-list-wrapper">
|
<div v-if="!hasSelectedPlaylist" class="song-list-wrapper">
|
||||||
|
<h1>Your playlists</h1>
|
||||||
|
<div v-if="!hasLoadedPlaylists" style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
|
||||||
|
<span class="material-symbols-outlined loading-spinner">autorenew</span>
|
||||||
|
<h3>Loading playlists...</h3>
|
||||||
|
</div>
|
||||||
<div v-for="playlist in playlists" class="song-list" @click="selectPlaylist( playlist.id )">
|
<div v-for="playlist in playlists" class="song-list" @click="selectPlaylist( playlist.id )">
|
||||||
<h3>{{ playlist.title }}</h3>
|
<h3>{{ playlist.title }}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -82,9 +95,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pool-wrapper">
|
<div class="pool-wrapper">
|
||||||
<div style="width: 100%;" class="song-list-wrapper">
|
<div style="width: 100%;" class="song-list-wrapper">
|
||||||
<div v-for="song in songQueue" class="song-list" :class="[ isPlaying ? ( currentlyPlaying === song.filename ? 'playing': 'not-playing' ) : 'not-playing', !isPlaying && currentlyPlaying === song.filename ? 'active-song': undefined ]">
|
<div v-for="song in songQueue" class="song-list" :class="[ isPlaying ? ( playingSong.filename === song.filename ? 'playing': 'not-playing' ) : 'not-playing', !isPlaying && playingSong.filename === song.filename ? 'active-song': undefined ]">
|
||||||
<img :src="song.coverArtURL" class="song-image">
|
<img :src="song.coverArtURL" class="song-image">
|
||||||
<div v-if="currentlyPlaying === song.filename && isPlaying" class="playing-symbols">
|
<div v-if="playingSong.filename === song.filename && isPlaying" class="playing-symbols">
|
||||||
<div class="playing-symbols-wrapper">
|
<div class="playing-symbols-wrapper">
|
||||||
<div class="playing-bar" id="bar-1"></div>
|
<div class="playing-bar" id="bar-1"></div>
|
||||||
<div class="playing-bar" id="bar-2"></div>
|
<div class="playing-bar" id="bar-2"></div>
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ const app = Vue.createApp( {
|
|||||||
playbackPosBeautified: '',
|
playbackPosBeautified: '',
|
||||||
durationBeautified: '',
|
durationBeautified: '',
|
||||||
isShowingRemainingTime: false,
|
isShowingRemainingTime: false,
|
||||||
|
localIP: '',
|
||||||
|
hasLoadedPlaylists: false,
|
||||||
|
isPreparingToPlay: false,
|
||||||
|
|
||||||
// slider
|
// slider
|
||||||
offset: 0,
|
offset: 0,
|
||||||
@@ -35,10 +38,13 @@ const app = Vue.createApp( {
|
|||||||
if ( !this.musicKit.isAuthorized ) {
|
if ( !this.musicKit.isAuthorized ) {
|
||||||
this.musicKit.authorize().then( () => {
|
this.musicKit.authorize().then( () => {
|
||||||
this.isLoggedIn = true;
|
this.isLoggedIn = true;
|
||||||
|
this.initMusicKit();
|
||||||
} );
|
} );
|
||||||
} else {
|
} else {
|
||||||
this.musicKit.authorize().then( () => {
|
this.musicKit.authorize().then( () => {
|
||||||
|
this.isLoggedIn = true;
|
||||||
this.musicKit.play();
|
this.musicKit.play();
|
||||||
|
this.initMusicKit();
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -60,6 +66,23 @@ const app = Vue.createApp( {
|
|||||||
this.isLoggedIn = true;
|
this.isLoggedIn = true;
|
||||||
this.config.userToken = this.musicKit.musicUserToken;
|
this.config.userToken = this.musicKit.musicUserToken;
|
||||||
}
|
}
|
||||||
|
this.musicKit.addEventListener( 'mediaItemDidChange', ( e ) => {
|
||||||
|
// Assemble this.playingSong
|
||||||
|
// Also add additional items to queue if there are new
|
||||||
|
// items that weren't previously shown (limitation of MusicKitJS).
|
||||||
|
this.playingSong = {
|
||||||
|
'artist': e.item.attributes.artistName,
|
||||||
|
'title': e.item.attributes.name,
|
||||||
|
'year': e.item.attributes.releaseDate,
|
||||||
|
// Think about bpm analysis
|
||||||
|
// 'bpm': metadata[ 'common' ][ 'bpm' ],
|
||||||
|
'genre': e.item.attributes.genreNames,
|
||||||
|
'duration': Math.round( e.item.attributes.durationInMillis / 1000 ),
|
||||||
|
'filename': e.item.id,
|
||||||
|
'coverArtOrigin': 'api',
|
||||||
|
'coverArtURL': e.item.attributes.artwork.url,
|
||||||
|
}
|
||||||
|
} );
|
||||||
this.apiGetRequest( 'https://api.music.apple.com/v1/me/library/playlists', this.playlistHandler );
|
this.apiGetRequest( 'https://api.music.apple.com/v1/me/library/playlists', this.playlistHandler );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
@@ -76,6 +99,7 @@ const app = Vue.createApp( {
|
|||||||
playParams: d[ el ].attributes.playParams,
|
playParams: d[ el ].attributes.playParams,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.hasLoadedPlaylists = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
apiGetRequest( url, callback ) {
|
apiGetRequest( url, callback ) {
|
||||||
@@ -102,13 +126,16 @@ const app = Vue.createApp( {
|
|||||||
} else return false;
|
} else return false;
|
||||||
},
|
},
|
||||||
selectPlaylist( id ) {
|
selectPlaylist( id ) {
|
||||||
|
this.isPreparingToPlay = true;
|
||||||
this.musicKit.api.library.playlist( id ).then( playlist => {
|
this.musicKit.api.library.playlist( id ).then( playlist => {
|
||||||
const tracks = playlist.relationships.tracks.data.map( tracks => tracks.id );
|
const tracks = playlist.relationships.tracks.data.map( tracks => tracks.id );
|
||||||
|
|
||||||
this.musicKit.setQueue( { songs: tracks } ).then( () => {
|
this.musicKit.setQueue( { songs: tracks } ).then( () => {
|
||||||
try {
|
try {
|
||||||
this.musicKit.play();
|
this.musicKit.play();
|
||||||
|
this.songQueue = this.musicKit.player.queue.items;
|
||||||
this.hasSelectedPlaylist = true;
|
this.hasSelectedPlaylist = true;
|
||||||
|
this.isPreparingToPlay = false;
|
||||||
} catch( err ) {
|
} catch( err ) {
|
||||||
this.hasSelectedPlaylist = false;
|
this.hasSelectedPlaylist = false;
|
||||||
console.error( err );
|
console.error( err );
|
||||||
@@ -223,32 +250,33 @@ const app = Vue.createApp( {
|
|||||||
this.sendUpdate( 'isPlaying' );
|
this.sendUpdate( 'isPlaying' );
|
||||||
} else if ( action === 'replay10' ) {
|
} else if ( action === 'replay10' ) {
|
||||||
this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? musicPlayer.currentPlaybackTime - 10 : 0 );
|
this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? musicPlayer.currentPlaybackTime - 10 : 0 );
|
||||||
this.playbackPos = musicPlayer.currentTime;
|
this.pos = musicPlayer.currentTime;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
} else if ( action === 'forward10' ) {
|
} else if ( action === 'forward10' ) {
|
||||||
if ( musicPlayer.currentTime < ( musicPlayer.duration - 10 ) ) {
|
if ( this.musicKit.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) {
|
||||||
musicPlayer.currentTime = musicPlayer.currentTime + 10;
|
this.musicKit.seekToTime( this.musicKit.currentTime + 10 );
|
||||||
this.playbackPos = musicPlayer.currentTime;
|
this.pos = this.musicKit.currentPlaybackTime;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
|
// Get currently playing song and get duration from there
|
||||||
} else {
|
} else {
|
||||||
if ( this.repeatMode !== 'one' ) {
|
if ( this.repeatMode !== 'one' ) {
|
||||||
this.control( 'next' );
|
this.control( 'next' );
|
||||||
} else {
|
} else {
|
||||||
musicPlayer.currentTime = 0;
|
this.musicKit.seekToTime( 0 );
|
||||||
this.playbackPos = musicPlayer.currentTime;
|
this.pos = this.musicKit.currentPlaybackTime;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( action === 'reset' ) {
|
} else if ( action === 'reset' ) {
|
||||||
clearInterval( this.progressTracker );
|
clearInterval( this.progressTracker );
|
||||||
this.playbackPos = 0;
|
this.pos = 0;
|
||||||
musicPlayer.currentTime = 0;
|
this.musicKit.seekToTime( 0 );
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
} else if ( action === 'next' ) {
|
} else if ( action === 'next' ) {
|
||||||
this.$emit( 'update', { 'type': 'next' } );
|
this.$emit( 'update', { 'type': 'next' } );
|
||||||
} else if ( action === 'previous' ) {
|
} else if ( action === 'previous' ) {
|
||||||
if ( this.playbackPos > 3 ) {
|
if ( this.pos > 3 ) {
|
||||||
this.playbackPos = 0;
|
this.pos = 0;
|
||||||
musicPlayer.currentTime = 0;
|
musicPlayer.currentTime = 0;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
} else {
|
} else {
|
||||||
@@ -275,7 +303,7 @@ const app = Vue.createApp( {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
position() {
|
pos() {
|
||||||
if ( !this.isDragging ) {
|
if ( !this.isDragging ) {
|
||||||
this.sliderProgress = Math.ceil( this.position / this.duration * 1000 + 2 );
|
this.sliderProgress = Math.ceil( this.position / this.duration * 1000 + 2 );
|
||||||
this.originalPos = Math.ceil( this.position / this.duration * ( document.getElementById( 'progress-slider-' + this.name ).scrollWidth - 5 ) );
|
this.originalPos = Math.ceil( this.position / this.duration * ( document.getElementById( 'progress-slider-' + this.name ).scrollWidth - 5 ) );
|
||||||
@@ -290,5 +318,12 @@ const app = Vue.createApp( {
|
|||||||
} else {
|
} else {
|
||||||
this.initMusicKit();
|
this.initMusicKit();
|
||||||
}
|
}
|
||||||
|
fetch( '/getLocalIP' ).then( res => {
|
||||||
|
if ( res.status === 200 ) {
|
||||||
|
res.text().then( ip => {
|
||||||
|
this.localIP = ip;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} );
|
||||||
},
|
},
|
||||||
} ).mount( '#app' );
|
} ).mount( '#app' );
|
||||||
@@ -105,4 +105,32 @@
|
|||||||
border-width: 10px;
|
border-width: 10px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: transparent transparent rgb(63, 63, 63) transparent;
|
border-color: transparent transparent rgb(63, 63, 63) transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare to play */
|
||||||
|
|
||||||
|
.preparingToPlay {
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
position: fixed;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
animation: spin 2s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate( 0deg );
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate( 720deg );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,48 @@ body, html {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Start page style */
|
||||||
|
.start-page {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-wrapper {
|
||||||
|
height: 50vh;
|
||||||
|
width: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo-main {
|
||||||
|
height: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#apple-music-logo {
|
||||||
|
height: 10vh;
|
||||||
|
position: relative;
|
||||||
|
bottom: 10vh;
|
||||||
|
left: 41vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: rgb(1, 1, 88);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50px;
|
||||||
|
transition: all 1s;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: rgb(1, 1, 120);
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Main style */
|
/* Main style */
|
||||||
|
|
||||||
.home {
|
.home {
|
||||||
|
|||||||
@@ -443,6 +443,8 @@ export default {
|
|||||||
this.localIP = ip;
|
this.localIP = ip;
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
} ).catch( err => {
|
||||||
|
this.localIP = 'ERROR fetching';
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user