mirror of
https://github.com/owntone/owntone-server.git
synced 2025-07-16 12:21:59 -04:00
[web] Improve the initialisation of stores
This commit is contained in:
parent
6b5f4ff4d7
commit
f91189d93b
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
993
web-src/package-lock.json
generated
993
web-src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@
|
|||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"reconnectingwebsocket": "^1.0.0",
|
"reconnectingwebsocket": "^1.0.0",
|
||||||
"spotify-web-api-js": "^1.5.2",
|
"spotify-web-api-js": "^1.5.2",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.14",
|
||||||
"vue-i18n": "^11.1.3",
|
"vue-i18n": "^11.1.3",
|
||||||
"vue-router": "^4.5.1",
|
"vue-router": "^4.5.1",
|
||||||
"vue3-click-away": "^1.2.4",
|
"vue3-click-away": "^1.2.4",
|
||||||
@ -32,11 +32,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
||||||
"@vitejs/plugin-vue": "^5.2.4",
|
"@vitejs/plugin-vue": "^5.2.4",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.27.0",
|
||||||
"eslint-config-prettier": "^10.1.5",
|
"eslint-config-prettier": "^10.1.5",
|
||||||
"eslint-plugin-vue": "^10.1.0",
|
"eslint-plugin-vue": "^10.1.0",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"sass": "^1.88.0",
|
"sass": "^1.89.0",
|
||||||
"vite": "^6.3.5"
|
"vite": "^6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ import NavbarBottom from '@/components/NavbarBottom.vue'
|
|||||||
import NavbarTop from '@/components/NavbarTop.vue'
|
import NavbarTop from '@/components/NavbarTop.vue'
|
||||||
import ReconnectingWebSocket from 'reconnectingwebsocket'
|
import ReconnectingWebSocket from 'reconnectingwebsocket'
|
||||||
import configuration from '@/api/configuration'
|
import configuration from '@/api/configuration'
|
||||||
import services from '@/api/services'
|
|
||||||
import { useConfigurationStore } from '@/stores/configuration'
|
import { useConfigurationStore } from '@/stores/configuration'
|
||||||
import { useLibraryStore } from '@/stores/library'
|
import { useLibraryStore } from '@/stores/library'
|
||||||
import { useNotificationsStore } from '@/stores/notifications'
|
import { useNotificationsStore } from '@/stores/notifications'
|
||||||
@ -66,7 +65,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
timerId: 0
|
updateThrottled: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -114,79 +113,33 @@ export default {
|
|||||||
},
|
},
|
||||||
openWebsocket() {
|
openWebsocket() {
|
||||||
const socket = this.createWebsocket()
|
const socket = this.createWebsocket()
|
||||||
|
const events = [
|
||||||
|
'database',
|
||||||
|
'lastfm',
|
||||||
|
'options',
|
||||||
|
'outputs',
|
||||||
|
'pairing',
|
||||||
|
'player',
|
||||||
|
'queue',
|
||||||
|
'settings',
|
||||||
|
'spotify',
|
||||||
|
'update',
|
||||||
|
'volume'
|
||||||
|
]
|
||||||
socket.onopen = () => {
|
socket.onopen = () => {
|
||||||
socket.send(
|
socket.send(JSON.stringify({ notify: events }))
|
||||||
JSON.stringify({
|
this.handleEvents(events)
|
||||||
notify: [
|
|
||||||
'update',
|
|
||||||
'database',
|
|
||||||
'player',
|
|
||||||
'options',
|
|
||||||
'outputs',
|
|
||||||
'volume',
|
|
||||||
'queue',
|
|
||||||
'spotify',
|
|
||||||
'lastfm',
|
|
||||||
'pairing'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
)
|
|
||||||
this.updateOutputs()
|
|
||||||
this.updatePlayer()
|
|
||||||
this.updateLibrary()
|
|
||||||
this.updateSettings()
|
|
||||||
this.updateQueue()
|
|
||||||
this.updateSpotify()
|
|
||||||
this.updateLastfm()
|
|
||||||
this.updateRemotes()
|
|
||||||
}
|
}
|
||||||
|
window.addEventListener('focus', () => {
|
||||||
let updateThrottled = false
|
this.handleEvents(events)
|
||||||
const updateInfo = () => {
|
})
|
||||||
if (updateThrottled) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.updateOutputs()
|
|
||||||
this.updatePlayer()
|
|
||||||
this.updateLibrary()
|
|
||||||
this.updateSettings()
|
|
||||||
this.updateQueue()
|
|
||||||
this.updateSpotify()
|
|
||||||
this.updateLastfm()
|
|
||||||
this.updateRemotes()
|
|
||||||
updateThrottled = true
|
|
||||||
setTimeout(() => {
|
|
||||||
updateThrottled = false
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('focus', updateInfo)
|
|
||||||
document.addEventListener('visibilitychange', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
if (document.visibilityState === 'visible') {
|
if (document.visibilityState === 'visible') {
|
||||||
updateInfo()
|
this.handleEvents(events)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.onmessage = (response) => {
|
socket.onmessage = (response) => {
|
||||||
const data = JSON.parse(response.data)
|
this.handleEvents(JSON.parse(response.data).notify)
|
||||||
const notify = new Set(data.notify || [])
|
|
||||||
const handlers = [
|
|
||||||
{ events: ['update', 'database'], handler: this.updateLibrary },
|
|
||||||
{
|
|
||||||
events: ['player', 'options', 'volume'],
|
|
||||||
handler: this.updatePlayer
|
|
||||||
},
|
|
||||||
{ events: ['outputs', 'volume'], handler: this.updateOutputs },
|
|
||||||
{ events: ['queue'], handler: this.updateQueue },
|
|
||||||
{ events: ['spotify'], handler: this.updateSpotify },
|
|
||||||
{ events: ['lastfm'], handler: this.updateLastfm },
|
|
||||||
{ events: ['pairing'], handler: this.updateRemotes }
|
|
||||||
]
|
|
||||||
handlers.forEach(({ handler, events }) => {
|
|
||||||
if (events.some((key) => notify.has(key))) {
|
|
||||||
handler.call(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createWebsocket() {
|
createWebsocket() {
|
||||||
@ -203,50 +156,46 @@ export default {
|
|||||||
reconnectInterval: 1000
|
reconnectInterval: 1000
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleEvents(notifications = []) {
|
||||||
|
if (this.updateThrottled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const handlers = [
|
||||||
|
{
|
||||||
|
events: ['update', 'database'],
|
||||||
|
handler: this.libraryStore.initialise
|
||||||
|
},
|
||||||
|
{
|
||||||
|
events: ['player', 'options', 'volume'],
|
||||||
|
handler: this.playerStore.initialise
|
||||||
|
},
|
||||||
|
{
|
||||||
|
events: ['outputs', 'volume'],
|
||||||
|
handler: this.outputsStore.initialise
|
||||||
|
},
|
||||||
|
{ events: ['queue'], handler: this.queueStore.initialise },
|
||||||
|
{ events: ['settings'], handler: this.settingsStore.initialise },
|
||||||
|
{ events: ['spotify'], handler: this.servicesStore.initialiseSpotify },
|
||||||
|
{ events: ['lastfm'], handler: this.servicesStore.initialiseLastfm },
|
||||||
|
{ events: ['pairing'], handler: this.remotesStore.initialise }
|
||||||
|
]
|
||||||
|
const notificationSet = new Set(notifications)
|
||||||
|
handlers.forEach(({ handler, events }) => {
|
||||||
|
if (events.some((key) => notificationSet.has(key))) {
|
||||||
|
handler.call(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.updateThrottled = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.updateThrottled = false
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
updateClipping() {
|
updateClipping() {
|
||||||
if (this.uiStore.showBurgerMenu || this.uiStore.showPlayerMenu) {
|
if (this.uiStore.showBurgerMenu || this.uiStore.showPlayerMenu) {
|
||||||
document.querySelector('html').classList.add('is-clipped')
|
document.querySelector('html').classList.add('is-clipped')
|
||||||
} else {
|
} else {
|
||||||
document.querySelector('html').classList.remove('is-clipped')
|
document.querySelector('html').classList.remove('is-clipped')
|
||||||
}
|
}
|
||||||
},
|
|
||||||
updateLastfm() {
|
|
||||||
services.lastfm().then((data) => {
|
|
||||||
this.servicesStore.lastfm = data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateLibrary() {
|
|
||||||
this.libraryStore.initialise()
|
|
||||||
},
|
|
||||||
updateOutputs() {
|
|
||||||
this.outputsStore.initialise()
|
|
||||||
},
|
|
||||||
updateRemotes() {
|
|
||||||
this.remotesStore.initialise()
|
|
||||||
},
|
|
||||||
updatePlayer() {
|
|
||||||
this.playerStore.initialise()
|
|
||||||
},
|
|
||||||
updateQueue() {
|
|
||||||
this.queueStore.initialise()
|
|
||||||
},
|
|
||||||
updateSettings() {
|
|
||||||
this.settingsStore.initialise()
|
|
||||||
},
|
|
||||||
updateSpotify() {
|
|
||||||
services.spotify().then((data) => {
|
|
||||||
this.servicesStore.spotify = data
|
|
||||||
if (this.timerId > 0) {
|
|
||||||
window.clearTimeout(this.timerId)
|
|
||||||
this.timerId = 0
|
|
||||||
}
|
|
||||||
if (data.webapi_token_expires_in > 0 && data.webapi_token) {
|
|
||||||
this.timerId = window.setTimeout(
|
|
||||||
this.updateSpotify,
|
|
||||||
1000 * data.webapi_token_expires_in
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<button :class="{ 'is-dark': playerStore.lyrics }" @click="toggle">
|
<button :class="{ 'is-dark': playerStore.showLyrics }" @click="toggle">
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon"
|
class="icon"
|
||||||
:name="icon"
|
:name="icon"
|
||||||
@ -21,14 +21,14 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
icon() {
|
icon() {
|
||||||
return this.playerStore.lyrics
|
return this.playerStore.showLyrics
|
||||||
? 'script-text-play'
|
? 'script-text-play'
|
||||||
: 'script-text-outline'
|
: 'script-text-outline'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggle() {
|
toggle() {
|
||||||
this.playerStore.lyrics = !this.playerStore.lyrics
|
this.playerStore.showLyrics = !this.playerStore.showLyrics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="lyrics is-overlay">
|
<div
|
||||||
<div v-for="(verse, index) in visibleLyrics" :key="index">
|
class="lyrics is-overlay"
|
||||||
|
@wheel.prevent="onScroll"
|
||||||
|
@touchmove.prevent="onScroll"
|
||||||
|
>
|
||||||
|
<div v-for="(verse, index) in visibleVerses" :key="index">
|
||||||
<div v-if="verse">
|
<div v-if="verse">
|
||||||
<div v-if="index === 3" class="title is-5 my-5 lh-2">
|
<div v-if="index === MIDDLE_POSITION" class="title is-5 my-5 lh-2">
|
||||||
<span
|
<span
|
||||||
v-for="(word, wordIndex) in verse.words"
|
v-for="(word, wordIndex) in verse.words"
|
||||||
:key="wordIndex"
|
:key="wordIndex"
|
||||||
@ -19,36 +23,40 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { usePlayerStore } from '@/stores/player'
|
import { usePlayerStore } from '@/stores/player'
|
||||||
import { useQueueStore } from '@/stores/queue'
|
|
||||||
|
|
||||||
const VISIBLE_VERSES = 7
|
|
||||||
const MIDDLE_POSITION = Math.floor(VISIBLE_VERSES / 2)
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PaneLyrics',
|
name: 'PaneLyrics',
|
||||||
setup() {
|
setup() {
|
||||||
return { playerStore: usePlayerStore(), queueStore: useQueueStore() }
|
const VISIBLE_VERSES = 7
|
||||||
|
const MIDDLE_POSITION = Math.floor(VISIBLE_VERSES / 2)
|
||||||
|
const SCROLL_THRESHOLD = 10
|
||||||
|
return {
|
||||||
|
MIDDLE_POSITION,
|
||||||
|
playerStore: usePlayerStore(),
|
||||||
|
SCROLL_THRESHOLD,
|
||||||
|
VISIBLE_VERSES
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
lastIndex: -1,
|
|
||||||
time: 0,
|
|
||||||
timerId: null,
|
|
||||||
lastProgress: 0,
|
|
||||||
lastUpdateTime: 0,
|
lastUpdateTime: 0,
|
||||||
lyrics: []
|
lyrics: { synchronised: false, verses: [] },
|
||||||
|
scrollIndex: 0,
|
||||||
|
scrollDelta: 0,
|
||||||
|
time: 0,
|
||||||
|
timerId: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
verseIndex() {
|
verseIndex() {
|
||||||
const currentTime = this.time
|
const currentTime = this.time
|
||||||
const { lyrics } = this
|
const { verses } = this.lyrics
|
||||||
let start = 0
|
let start = 0
|
||||||
let end = lyrics.length - 1
|
let end = verses.length - 1
|
||||||
while (start <= end) {
|
while (start <= end) {
|
||||||
const mid = Math.floor((start + end) / 2)
|
const mid = Math.floor((start + end) / 2)
|
||||||
const midTime = lyrics[mid].time
|
const midTime = verses[mid].time
|
||||||
const nextTime = lyrics[mid + 1]?.time
|
const nextTime = verses[mid + 1]?.time
|
||||||
if (midTime <= currentTime && (!nextTime || nextTime > currentTime)) {
|
if (midTime <= currentTime && (!nextTime || nextTime > currentTime)) {
|
||||||
return mid
|
return mid
|
||||||
} else if (midTime < currentTime) {
|
} else if (midTime < currentTime) {
|
||||||
@ -59,13 +67,13 @@ export default {
|
|||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
},
|
},
|
||||||
visibleLyrics() {
|
visibleVerses() {
|
||||||
const current = this.verseIndex
|
const { verses, synchronised } = this.lyrics
|
||||||
const total = this.lyrics.length
|
const index = synchronised ? this.verseIndex : this.scrollIndex
|
||||||
return Array.from({ length: VISIBLE_VERSES }, (_, i) => {
|
return Array.from(
|
||||||
const index = current - MIDDLE_POSITION + i
|
{ length: this.VISIBLE_VERSES },
|
||||||
return index >= 0 && index < total ? this.lyrics[index] : null
|
(_, i) => verses[index - this.MIDDLE_POSITION + i] ?? null
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -78,7 +86,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'playerStore.item_progress_ms'(progress) {
|
'playerStore.item_progress_ms'(progress) {
|
||||||
this.lastProgress = progress
|
|
||||||
this.lastUpdateTime = Date.now()
|
this.lastUpdateTime = Date.now()
|
||||||
if (!this.playerStore.isPlaying) {
|
if (!this.playerStore.isPlaying) {
|
||||||
this.time = progress
|
this.time = progress
|
||||||
@ -86,13 +93,10 @@ export default {
|
|||||||
},
|
},
|
||||||
'playerStore.lyricsContent'() {
|
'playerStore.lyricsContent'() {
|
||||||
this.lyrics = this.parseLyrics()
|
this.lyrics = this.parseLyrics()
|
||||||
},
|
|
||||||
verseIndex(index) {
|
|
||||||
this.lastIndex = index
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.lastProgress = this.playerStore.item_progress_ms
|
this.playerStore.initialise()
|
||||||
this.lastUpdateTime = Date.now()
|
this.lastUpdateTime = Date.now()
|
||||||
this.lyrics = this.parseLyrics()
|
this.lyrics = this.parseLyrics()
|
||||||
this.updateTime()
|
this.updateTime()
|
||||||
@ -101,11 +105,24 @@ export default {
|
|||||||
this.stopTimer()
|
this.stopTimer()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
onScroll(event) {
|
||||||
|
if (this.verseIndex >= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.scrollDelta += event.deltaY
|
||||||
|
if (Math.abs(this.scrollDelta) >= this.SCROLL_THRESHOLD) {
|
||||||
|
const newIndex = this.scrollIndex + Math.sign(this.scrollDelta)
|
||||||
|
if (newIndex >= -1 && newIndex < this.lyrics.verses.length) {
|
||||||
|
this.scrollIndex = newIndex
|
||||||
|
}
|
||||||
|
this.scrollDelta = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
isWordHighlighted(word) {
|
isWordHighlighted(word) {
|
||||||
return this.time >= word.start && this.time < word.end
|
return this.time >= word.start && this.time < word.end
|
||||||
},
|
},
|
||||||
parseLyrics() {
|
parseLyrics() {
|
||||||
const verses = []
|
const lyrics = { synchronised: false, verses: [] }
|
||||||
const regex =
|
const regex =
|
||||||
/(?:\[(?<minutes>\d+):(?<seconds>\d+)(?:\.(?<hundredths>\d+))?\])?\s*(?<text>\S.*\S)?\s*/u
|
/(?:\[(?<minutes>\d+):(?<seconds>\d+)(?:\.(?<hundredths>\d+))?\])?\s*(?<text>\S.*\S)?\s*/u
|
||||||
this.playerStore.lyricsContent.split('\n').forEach((line) => {
|
this.playerStore.lyricsContent.split('\n').forEach((line) => {
|
||||||
@ -117,25 +134,25 @@ export default {
|
|||||||
const time =
|
const time =
|
||||||
(Number(minutes) * 60 + Number(`${seconds}.${hundredths ?? 0}`)) *
|
(Number(minutes) * 60 + Number(`${seconds}.${hundredths ?? 0}`)) *
|
||||||
1000
|
1000
|
||||||
verses.push({ text: verse, time })
|
lyrics.synchronised = !isNaN(time)
|
||||||
|
lyrics.verses.push({ text: verse, time })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
verses.forEach((verse, index, lyrics) => {
|
lyrics.verses.forEach((verse, index, verses) => {
|
||||||
const nextTime = lyrics[index + 1]?.time ?? verse.time + 3000
|
const nextTime = verses[index + 1]?.time ?? verse.time + 3000
|
||||||
const totalDuration = nextTime - verse.time
|
const totalDuration = nextTime - verse.time
|
||||||
const words = verse.text.match(/\S+\s*/gu) || []
|
const words = verse.text.match(/\S+\s*/gu) || []
|
||||||
const totalLength = words.reduce((sum, word) => sum + word.length, 0)
|
const totalLength = words.reduce((sum, word) => sum + word.length, 0)
|
||||||
let currentTime = verse.time
|
let currentTime = verse.time
|
||||||
verse.words = words.map((text) => {
|
verse.words = words.map((text) => {
|
||||||
const duration = totalDuration * (text.length / totalLength)
|
|
||||||
const start = currentTime
|
const start = currentTime
|
||||||
const end = start + duration
|
const end = start + totalDuration * (text.length / totalLength)
|
||||||
currentTime = end
|
currentTime = end
|
||||||
return { text, start, end }
|
return { text, start, end }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return verses
|
return lyrics
|
||||||
},
|
},
|
||||||
startTimer() {
|
startTimer() {
|
||||||
if (this.timerId) {
|
if (this.timerId) {
|
||||||
@ -150,13 +167,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
tick() {
|
tick() {
|
||||||
this.time = this.lastProgress + Date.now() - this.lastUpdateTime
|
this.time =
|
||||||
|
this.playerStore.item_progress_ms + Date.now() - this.lastUpdateTime
|
||||||
},
|
},
|
||||||
updateTime() {
|
updateTime() {
|
||||||
|
this.lastUpdateTime = Date.now()
|
||||||
if (this.playerStore.isPlaying) {
|
if (this.playerStore.isPlaying) {
|
||||||
this.startTimer()
|
this.startTimer()
|
||||||
} else {
|
} else {
|
||||||
this.time = this.lastProgress
|
this.time = this.playerStore.item_progress_ms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
:url="track.artwork_url"
|
:url="track.artwork_url"
|
||||||
:caption="track.album"
|
:caption="track.album"
|
||||||
class="is-clickable is-big"
|
class="is-clickable is-big"
|
||||||
:class="{ 'is-masked': playerStore.lyrics }"
|
:class="{ 'is-masked': playerStore.showLyrics }"
|
||||||
@click="openDetails(track)"
|
@click="openDetails(track)"
|
||||||
/>
|
/>
|
||||||
<pane-lyrics v-if="playerStore.lyrics" />
|
<pane-lyrics v-if="playerStore.showLyrics" />
|
||||||
</div>
|
</div>
|
||||||
<control-slider
|
<control-slider
|
||||||
v-model:value="trackProgress"
|
v-model:value="trackProgress"
|
||||||
|
@ -123,7 +123,7 @@
|
|||||||
class="help"
|
class="help"
|
||||||
scope="global"
|
scope="global"
|
||||||
>
|
>
|
||||||
<br />
|
<slot><br /></slot>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
</template>
|
</template>
|
||||||
</control-setting-text-field>
|
</control-setting-text-field>
|
||||||
|
@ -27,9 +27,9 @@ export const usePlayerStore = defineStore('PlayerStore', {
|
|||||||
item_id: 0,
|
item_id: 0,
|
||||||
item_length_ms: 0,
|
item_length_ms: 0,
|
||||||
item_progress_ms: 0,
|
item_progress_ms: 0,
|
||||||
lyrics: false,
|
|
||||||
lyricsContent: '',
|
lyricsContent: '',
|
||||||
repeat: 'off',
|
repeat: 'off',
|
||||||
|
showLyrics: false,
|
||||||
shuffle: false,
|
shuffle: false,
|
||||||
state: 'stop',
|
state: 'stop',
|
||||||
volume: 0
|
volume: 0
|
||||||
|
@ -1,6 +1,27 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import services from '@/api/services'
|
||||||
|
|
||||||
export const useServicesStore = defineStore('ServicesStore', {
|
export const useServicesStore = defineStore('ServicesStore', {
|
||||||
|
actions: {
|
||||||
|
async initialiseLastfm() {
|
||||||
|
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.updateSpotify(),
|
||||||
|
1000 * data.webapi_token_expires_in
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
getters: {
|
getters: {
|
||||||
hasMissingSpotifyScopes: (state) => state.missingSpotifyScopes.length > 0,
|
hasMissingSpotifyScopes: (state) => state.missingSpotifyScopes.length > 0,
|
||||||
isAuthorizationRequired: (state) =>
|
isAuthorizationRequired: (state) =>
|
||||||
@ -22,6 +43,7 @@ export const useServicesStore = defineStore('ServicesStore', {
|
|||||||
},
|
},
|
||||||
state: () => ({
|
state: () => ({
|
||||||
lastfm: {},
|
lastfm: {},
|
||||||
spotify: {}
|
spotify: {},
|
||||||
|
spotifyTimerId: 0
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user