mirror of
https://github.com/owntone/owntone-server.git
synced 2025-10-30 00:05:05 -04:00
[web] Switch to Spotify Web SDK
This commit is contained in:
parent
b612e12aca
commit
978a9b6a96
585
web-src/package-lock.json
generated
585
web-src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
||||
"dependencies": {
|
||||
"@aacassandra/vue3-progressbar": "^1.0.3",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@spotify/web-api-ts-sdk": "^1.2.0",
|
||||
"@ts-pro/vue-eternal-loading": "^1.3.1",
|
||||
"axios": "^1.11.0",
|
||||
"bulma": "^1.0.4",
|
||||
@ -21,7 +22,6 @@
|
||||
"mdi-vue": "^3.0.13",
|
||||
"pinia": "^3.0.3",
|
||||
"reconnectingwebsocket": "^1.0.0",
|
||||
"spotify-web-api-js": "^1.5.2",
|
||||
"vue": "^3.5.18",
|
||||
"vue-i18n": "^11.1.11",
|
||||
"vue-router": "^4.5.1",
|
||||
@ -31,12 +31,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"eslint": "^9.32.0",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"eslint": "^9.33.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-vue": "^10.3.0",
|
||||
"eslint-plugin-vue": "^10.4.0",
|
||||
"prettier": "^3.6.2",
|
||||
"sass": "^1.89.2",
|
||||
"vite": "^7.0.6"
|
||||
"sass": "^1.90.0",
|
||||
"vite": "^7.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { SpotifyApi } from '@spotify/web-api-ts-sdk'
|
||||
import api from '@/api'
|
||||
|
||||
export default {
|
||||
@ -14,6 +15,11 @@ export default {
|
||||
return api.get('./api/spotify-logout')
|
||||
},
|
||||
spotify() {
|
||||
return api.get('./api/spotify')
|
||||
return api.get('./api/spotify').then((configuration) => {
|
||||
const sdk = SpotifyApi.withAccessToken(configuration.webapi_client_id, {
|
||||
access_token: configuration.webapi_token
|
||||
})
|
||||
return { api: sdk, configuration }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,9 +14,9 @@
|
||||
<script>
|
||||
import ListProperties from '@/components/ListProperties.vue'
|
||||
import ModalDialog from '@/components/ModalDialog.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import player from '@/api/player'
|
||||
import queue from '@/api/queue'
|
||||
import services from '@/api/services'
|
||||
import { useServicesStore } from '@/stores/services'
|
||||
|
||||
export default {
|
||||
@ -90,16 +90,17 @@ export default {
|
||||
watch: {
|
||||
item() {
|
||||
if (this.item?.data_kind === 'spotify') {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(this.servicesStore.spotify.webapi_token)
|
||||
spotifyApi
|
||||
.getTrack(this.item.path.slice(this.item.path.lastIndexOf(':') + 1))
|
||||
.then((response) => {
|
||||
return services.spotify().then(({ api }) => {
|
||||
const trackId = this.item.path.slice(
|
||||
this.item.path.lastIndexOf(':') + 1
|
||||
)
|
||||
return api.tracks.get(trackId).then((response) => {
|
||||
this.spotifyTrack = response
|
||||
})
|
||||
} else {
|
||||
this.spotifyTrack = {}
|
||||
})
|
||||
}
|
||||
this.spotifyTrack = {}
|
||||
return {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@ -28,7 +28,6 @@ import ControlImage from '@/components/ControlImage.vue'
|
||||
import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
|
||||
import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue'
|
||||
import PaneHero from '@/components/PaneHero.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import queue from '@/api/queue'
|
||||
import services from '@/api/services'
|
||||
import { useServicesStore } from '@/stores/services'
|
||||
@ -43,13 +42,9 @@ export default {
|
||||
PaneHero
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
services.spotify().then((data) => {
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
spotifyApi
|
||||
.getAlbum(to.params.id, {
|
||||
market: useServicesStore().spotify.webapi_country
|
||||
})
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
api.albums
|
||||
.get(to.params.id, configuration.webapi_country)
|
||||
.then((album) => {
|
||||
next((vm) => {
|
||||
vm.album = album
|
||||
|
||||
@ -28,10 +28,8 @@ import ControlButton from '@/components/ControlButton.vue'
|
||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||
import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue'
|
||||
import PaneTitle from '@/components/PaneTitle.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import queue from '@/api/queue'
|
||||
import services from '@/api/services'
|
||||
import { useServicesStore } from '@/stores/services'
|
||||
|
||||
const PAGE_SIZE = 50
|
||||
|
||||
@ -45,17 +43,16 @@ export default {
|
||||
PaneTitle
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
services.spotify().then((data) => {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
Promise.all([
|
||||
spotifyApi.getArtist(to.params.id),
|
||||
spotifyApi.getArtistAlbums(to.params.id, {
|
||||
include_groups: 'album,single',
|
||||
limit: PAGE_SIZE,
|
||||
market: useServicesStore().spotify.webapi_country,
|
||||
offset: 0
|
||||
})
|
||||
api.artists.get(to.params.id),
|
||||
api.artists.albums(
|
||||
to.params.id,
|
||||
'album,single',
|
||||
configuration.webapi_country,
|
||||
PAGE_SIZE,
|
||||
0
|
||||
)
|
||||
]).then(([artist, albums]) => {
|
||||
next((vm) => {
|
||||
vm.artist = artist
|
||||
@ -66,9 +63,6 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
setup() {
|
||||
return { servicesStore: useServicesStore() }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
albums: [],
|
||||
@ -93,15 +87,15 @@ export default {
|
||||
this.offset += data.limit
|
||||
},
|
||||
load({ loaded }) {
|
||||
services.spotify().then((data) => {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
spotifyApi
|
||||
.getArtistAlbums(this.artist.id, {
|
||||
include_groups: 'album,single',
|
||||
limit: PAGE_SIZE,
|
||||
offset: this.offset
|
||||
})
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
api.artists
|
||||
.albums(
|
||||
this.artist.id,
|
||||
'album,single',
|
||||
configuration.webapi_country,
|
||||
PAGE_SIZE,
|
||||
this.offset
|
||||
)
|
||||
.then((albums) => {
|
||||
this.appendAlbums(albums)
|
||||
loaded(albums.items.length, PAGE_SIZE)
|
||||
|
||||
@ -41,7 +41,6 @@ import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
||||
import PaneTitle from '@/components/PaneTitle.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import TabsMusic from '@/components/TabsMusic.vue'
|
||||
import services from '@/api/services'
|
||||
|
||||
@ -55,18 +54,15 @@ export default {
|
||||
TabsMusic
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
services.spotify().then((data) => {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
Promise.all([
|
||||
spotifyApi.getNewReleases({
|
||||
country: data.webapi_country,
|
||||
limit: 3
|
||||
}),
|
||||
spotifyApi.getFeaturedPlaylists({
|
||||
country: data.webapi_country,
|
||||
limit: 3
|
||||
})
|
||||
api.browse.getNewReleases(configuration.webapi_country, 3),
|
||||
api.browse.getFeaturedPlaylists(
|
||||
configuration.webapi_country,
|
||||
null,
|
||||
null,
|
||||
3
|
||||
)
|
||||
]).then((response) => {
|
||||
next((vm) => {
|
||||
vm.albums = response[0].albums.items
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
||||
import PaneTitle from '@/components/PaneTitle.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import TabsMusic from '@/components/TabsMusic.vue'
|
||||
import services from '@/api/services'
|
||||
|
||||
@ -27,14 +26,9 @@ export default {
|
||||
TabsMusic
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
services.spotify().then((data) => {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
spotifyApi
|
||||
.getFeaturedPlaylists({
|
||||
country: data.webapi_country,
|
||||
limit: 50
|
||||
})
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
api.browse
|
||||
.getFeaturedPlaylists(configuration.webapi_country, null, null, 50)
|
||||
.then((response) => {
|
||||
next((vm) => {
|
||||
vm.playlists = response.playlists.items
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||
import PaneTitle from '@/components/PaneTitle.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import TabsMusic from '@/components/TabsMusic.vue'
|
||||
import services from '@/api/services'
|
||||
|
||||
@ -27,14 +26,9 @@ export default {
|
||||
TabsMusic
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
services.spotify().then((data) => {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
spotifyApi
|
||||
.getNewReleases({
|
||||
country: data.webapi_country,
|
||||
limit: 50
|
||||
})
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
api.browse
|
||||
.getNewReleases(configuration.webapi_country, 50)
|
||||
.then((response) => {
|
||||
next((vm) => {
|
||||
vm.albums = response.albums.items
|
||||
|
||||
@ -37,9 +37,8 @@ import ControlButton from '@/components/ControlButton.vue'
|
||||
import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
|
||||
import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue'
|
||||
import PaneTitle from '@/components/PaneTitle.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import queue from '@/api/queue'
|
||||
import { useServicesStore } from '@/stores/services'
|
||||
import services from '@/api/services'
|
||||
|
||||
const PAGE_SIZE = 50
|
||||
|
||||
@ -53,28 +52,27 @@ export default {
|
||||
PaneTitle
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(useServicesStore().spotify.webapi_token)
|
||||
Promise.all([
|
||||
spotifyApi.getPlaylist(to.params.id),
|
||||
spotifyApi.getPlaylistTracks(to.params.id, {
|
||||
limit: PAGE_SIZE,
|
||||
market: useServicesStore().$state.spotify.webapi_country,
|
||||
offset: 0
|
||||
})
|
||||
]).then(([playlist, tracks]) => {
|
||||
next((vm) => {
|
||||
vm.playlist = playlist
|
||||
vm.tracks = []
|
||||
vm.total = 0
|
||||
vm.offset = 0
|
||||
vm.appendTracks(tracks)
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
Promise.all([
|
||||
api.playlists.getPlaylist(to.params.id),
|
||||
api.playlists.getPlaylistItems(
|
||||
to.params.id,
|
||||
configuration.webapi_country,
|
||||
null,
|
||||
PAGE_SIZE,
|
||||
0
|
||||
)
|
||||
]).then(([playlist, tracks]) => {
|
||||
next((vm) => {
|
||||
vm.playlist = playlist
|
||||
vm.tracks = []
|
||||
vm.total = 0
|
||||
vm.offset = 0
|
||||
vm.appendTracks(tracks)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
setup() {
|
||||
return { servicesStore: useServicesStore() }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
offset: 0,
|
||||
@ -118,18 +116,20 @@ export default {
|
||||
this.offset += data.limit
|
||||
},
|
||||
load({ loaded }) {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(this.servicesStore.spotify.webapi_token)
|
||||
spotifyApi
|
||||
.getPlaylistTracks(this.playlist.id, {
|
||||
limit: PAGE_SIZE,
|
||||
market: this.servicesStore.spotify.webapi_country,
|
||||
offset: this.offset
|
||||
})
|
||||
.then((data) => {
|
||||
this.appendTracks(data)
|
||||
loaded(data.items.length, PAGE_SIZE)
|
||||
})
|
||||
services.spotify().then(({ api, configuration }) => {
|
||||
api.playlists
|
||||
.getPlaylistItems(
|
||||
this.playlist.id,
|
||||
configuration.webapi_country,
|
||||
null,
|
||||
PAGE_SIZE,
|
||||
this.offset
|
||||
)
|
||||
.then((data) => {
|
||||
this.appendTracks(data)
|
||||
loaded(data.items.length, PAGE_SIZE)
|
||||
})
|
||||
})
|
||||
},
|
||||
play() {
|
||||
this.showDetailsModal = false
|
||||
|
||||
@ -20,7 +20,6 @@ import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
|
||||
import ListArtistsSpotify from '@/components/ListArtistsSpotify.vue'
|
||||
import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
|
||||
import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import services from '@/api/services'
|
||||
import { useSearchStore } from '@/stores/search'
|
||||
|
||||
@ -95,16 +94,17 @@ export default {
|
||||
}
|
||||
},
|
||||
searchItems() {
|
||||
return services.spotify().then((data) => {
|
||||
this.parameters.market = data.webapi_country
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(data.webapi_token)
|
||||
return spotifyApi.search(
|
||||
this.searchStore.query,
|
||||
this.types,
|
||||
this.parameters
|
||||
return services
|
||||
.spotify()
|
||||
.then(({ api, configuration }) =>
|
||||
api.search(
|
||||
this.searchStore.query,
|
||||
this.types,
|
||||
configuration.webapi_country,
|
||||
this.parameters.limit,
|
||||
this.parameters.offset
|
||||
)
|
||||
)
|
||||
})
|
||||
},
|
||||
searchLibrary() {
|
||||
this.$router.push({ name: 'search-library' })
|
||||
|
||||
@ -7,18 +7,8 @@ export const useServicesStore = defineStore('ServicesStore', {
|
||||
this.lastfm = await services.lastfm()
|
||||
},
|
||||
initialiseSpotify() {
|
||||
services.spotify().then((data) => {
|
||||
this.spotify = data
|
||||
if (this.spotifyTimerId > 0) {
|
||||
clearTimeout(this.spotifyTimerId)
|
||||
this.spotifyTimerId = 0
|
||||
}
|
||||
if (data.webapi_token_expires_in > 0 && data.webapi_token) {
|
||||
this.spotifyTimerId = setTimeout(
|
||||
() => this.initialiseSpotify(),
|
||||
1000 * data.webapi_token_expires_in
|
||||
)
|
||||
}
|
||||
services.spotify().then(({ configuration }) => {
|
||||
this.spotify = configuration
|
||||
})
|
||||
}
|
||||
},
|
||||
@ -41,5 +31,5 @@ export const useServicesStore = defineStore('ServicesStore', {
|
||||
requiredSpotifyScopes: (state) =>
|
||||
state.spotify.webapi_required_scope?.split(' ') ?? []
|
||||
},
|
||||
state: () => ({ lastfm: {}, spotify: {}, spotifyTimerId: 0 })
|
||||
state: () => ({ lastfm: {}, spotify: {} })
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user