From 5a133e3f12d13504321565a38326e2fae82485db Mon Sep 17 00:00:00 2001 From: janis Date: Thu, 16 Nov 2023 14:35:23 +0100 Subject: [PATCH] lots more progress on apple music integration --- backend/ui/index.html | 4 ++ backend/ui/showcase.css | 11 +++- backend/ui/showcase.js | 10 ++++ frontend/src/app.js | 4 +- .../src/client/appleMusic/appleMusicIcon.svg | 56 ++++++++++++++++++ frontend/src/client/appleMusic/index.html | 23 ++++++-- frontend/src/client/appleMusic/index.js | 57 +++++++++++++++---- .../src/client/appleMusic/playerStyle.css | 28 +++++++++ frontend/src/client/appleMusic/style.css | 42 ++++++++++++++ frontend/src/components/player.vue | 2 + 10 files changed, 218 insertions(+), 19 deletions(-) create mode 100644 frontend/src/client/appleMusic/appleMusicIcon.svg diff --git a/backend/ui/index.html b/backend/ui/index.html index 10a5b4f..ecd1587 100644 --- a/backend/ui/index.html +++ b/backend/ui/index.html @@ -11,6 +11,10 @@
Designed and developed by Janis Hutz https://janishutz.com
+
+

Loading...

+

Please wait

+
diff --git a/backend/ui/showcase.css b/backend/ui/showcase.css index adb209a..24bdd56 100644 --- a/backend/ui/showcase.css +++ b/backend/ui/showcase.css @@ -21,12 +21,21 @@ body { .content { width: 100%; - display: flex; + display: none; justify-content: center; align-items: center; flex-direction: column; } +.loaded { + display: block; +} + +.loading { + display: flex; + height: 100vh; +} + .playing-symbols { position: absolute; left: 10vw; diff --git a/backend/ui/showcase.js b/backend/ui/showcase.js index 84325a8..e9d6e83 100644 --- a/backend/ui/showcase.js +++ b/backend/ui/showcase.js @@ -98,6 +98,16 @@ createApp( { source.onopen = () => { 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; diff --git a/frontend/src/app.js b/frontend/src/app.js index 79e799c..69abcd2 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -82,8 +82,8 @@ app.get( '/useAppleMusic', ( req, res ) => { app.get( '/openSongs', ( req, res ) => { // 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' } ) } ); + // res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' ); + res.send( { 'data': dialog.showOpenDialogSync( { properties: [ 'openDirectory' ], title: 'Open music library folder' } ) } ); } ); app.get( '/showcase.js', ( req, res ) => { diff --git a/frontend/src/client/appleMusic/appleMusicIcon.svg b/frontend/src/client/appleMusic/appleMusicIcon.svg new file mode 100644 index 0000000..7fcf6a0 --- /dev/null +++ b/frontend/src/client/appleMusic/appleMusicIcon.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/client/appleMusic/index.html b/frontend/src/client/appleMusic/index.html index 0cdc334..2d534c9 100644 --- a/frontend/src/client/appleMusic/index.html +++ b/frontend/src/client/appleMusic/index.html @@ -11,12 +11,25 @@
-
-

Apple Music

- +
+ autorenew +

Loading player...

+
+
+
+ Music player icon + +
+

Apple Music integration

+
+

Your playlists

+
+ autorenew +

Loading playlists...

+

{{ playlist.title }}

@@ -82,9 +95,9 @@
-
+
-
+
diff --git a/frontend/src/client/appleMusic/index.js b/frontend/src/client/appleMusic/index.js index 6caf85d..426bb06 100644 --- a/frontend/src/client/appleMusic/index.js +++ b/frontend/src/client/appleMusic/index.js @@ -19,6 +19,9 @@ const app = Vue.createApp( { playbackPosBeautified: '', durationBeautified: '', isShowingRemainingTime: false, + localIP: '', + hasLoadedPlaylists: false, + isPreparingToPlay: false, // slider offset: 0, @@ -35,10 +38,13 @@ const app = Vue.createApp( { if ( !this.musicKit.isAuthorized ) { this.musicKit.authorize().then( () => { this.isLoggedIn = true; + this.initMusicKit(); } ); } else { this.musicKit.authorize().then( () => { + this.isLoggedIn = true; this.musicKit.play(); + this.initMusicKit(); } ); } }, @@ -60,6 +66,23 @@ const app = Vue.createApp( { this.isLoggedIn = true; 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 ); } ); } @@ -76,6 +99,7 @@ const app = Vue.createApp( { playParams: d[ el ].attributes.playParams, } } + this.hasLoadedPlaylists = true; } }, apiGetRequest( url, callback ) { @@ -102,13 +126,16 @@ const app = Vue.createApp( { } else return false; }, selectPlaylist( id ) { + this.isPreparingToPlay = true; this.musicKit.api.library.playlist( id ).then( playlist => { const tracks = playlist.relationships.tracks.data.map( tracks => tracks.id ); this.musicKit.setQueue( { songs: tracks } ).then( () => { try { this.musicKit.play(); + this.songQueue = this.musicKit.player.queue.items; this.hasSelectedPlaylist = true; + this.isPreparingToPlay = false; } catch( err ) { this.hasSelectedPlaylist = false; console.error( err ); @@ -223,32 +250,33 @@ const app = Vue.createApp( { this.sendUpdate( 'isPlaying' ); } else if ( action === 'replay10' ) { this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? musicPlayer.currentPlaybackTime - 10 : 0 ); - this.playbackPos = musicPlayer.currentTime; + this.pos = musicPlayer.currentTime; this.sendUpdate( 'pos' ); } else if ( action === 'forward10' ) { - if ( musicPlayer.currentTime < ( musicPlayer.duration - 10 ) ) { - musicPlayer.currentTime = musicPlayer.currentTime + 10; - this.playbackPos = musicPlayer.currentTime; + if ( this.musicKit.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) { + this.musicKit.seekToTime( this.musicKit.currentTime + 10 ); + this.pos = this.musicKit.currentPlaybackTime; this.sendUpdate( 'pos' ); + // Get currently playing song and get duration from there } else { if ( this.repeatMode !== 'one' ) { this.control( 'next' ); } else { - musicPlayer.currentTime = 0; - this.playbackPos = musicPlayer.currentTime; + this.musicKit.seekToTime( 0 ); + this.pos = this.musicKit.currentPlaybackTime; this.sendUpdate( 'pos' ); } } } else if ( action === 'reset' ) { clearInterval( this.progressTracker ); - this.playbackPos = 0; - musicPlayer.currentTime = 0; + this.pos = 0; + this.musicKit.seekToTime( 0 ); this.sendUpdate( 'pos' ); } else if ( action === 'next' ) { this.$emit( 'update', { 'type': 'next' } ); } else if ( action === 'previous' ) { - if ( this.playbackPos > 3 ) { - this.playbackPos = 0; + if ( this.pos > 3 ) { + this.pos = 0; musicPlayer.currentTime = 0; this.sendUpdate( 'pos' ); } else { @@ -275,7 +303,7 @@ const app = Vue.createApp( { } }, watch: { - position() { + pos() { if ( !this.isDragging ) { 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 ) ); @@ -290,5 +318,12 @@ const app = Vue.createApp( { } else { this.initMusicKit(); } + fetch( '/getLocalIP' ).then( res => { + if ( res.status === 200 ) { + res.text().then( ip => { + this.localIP = ip; + } ); + } + } ); }, } ).mount( '#app' ); \ No newline at end of file diff --git a/frontend/src/client/appleMusic/playerStyle.css b/frontend/src/client/appleMusic/playerStyle.css index 8ac667a..2d8bd6e 100644 --- a/frontend/src/client/appleMusic/playerStyle.css +++ b/frontend/src/client/appleMusic/playerStyle.css @@ -105,4 +105,32 @@ border-width: 10px; border-style: solid; 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 ); + } } \ No newline at end of file diff --git a/frontend/src/client/appleMusic/style.css b/frontend/src/client/appleMusic/style.css index 3c8c1ca..c2b7aa3 100644 --- a/frontend/src/client/appleMusic/style.css +++ b/frontend/src/client/appleMusic/style.css @@ -17,6 +17,48 @@ body, html { 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 */ .home { diff --git a/frontend/src/components/player.vue b/frontend/src/components/player.vue index 2a3699b..0db63e6 100644 --- a/frontend/src/components/player.vue +++ b/frontend/src/components/player.vue @@ -443,6 +443,8 @@ export default { this.localIP = ip; } ); } + } ).catch( err => { + this.localIP = 'ERROR fetching'; } ); } }