mindboost-rnbo-test-project/composables/usePlayerControls.js

173 lines
5.0 KiB
JavaScript

import { useAudioStore } from '~/stores/audio'
import { useUserStore } from '~/stores/user'
import tracksConfig, { getSoundcapeList } from '~/tracks.config'
import { useArtWorkManager } from '~/composables/useArtWorkManager'
export const usePlayerControls = () => {
// State Management
const audio = useAudioStore()
const userStore = useUserStore()
const { $changeTrack } = useNuxtApp()
const currentIndex = computed(() => getSoundcapeList().indexOf(userStore.user.settings.soundscape))
const currentSoundscape = computed(() => useUserStore().user.settings.soundscape)
const playing = computed(() => audio.getPlaying)
const togglePlayingState = () => {
if (playing.value) {
audio.setPlaying(false)
} else {
audio.setPlaying(true)
}
}
// Listeners
const addSpaceListener = () => {
window.addEventListener('keydown', handleSpace)
}
const removeSpaceListener = () => {
window.removeEventListener('keydown', null)
}
const addMediaControls = () => {
for (const [action, handler] of actionHandlers) {
try {
navigator.mediaSession.setActionHandler(action, handler)
} catch (error) {
useNuxtApp().$logger.error(error)
}
}
}
// Helper functions
const getNextSoundscape = () => {
const list = getSoundcapeList()
const current = currentSoundscape.value
const index = list.indexOf(current)
return list[(index + 1) % list.length]
}
const getPreviousSoundscape = () => {
const list = getSoundcapeList()
const current = currentSoundscape.value
const index = list.indexOf(current)
return list[(index - 1) % list.length]
}
// Handlers
const handleSpace = (e) => {
const activeElement = document.activeElement
const tagName = activeElement.tagName.toLowerCase()
// List of elements where spacebar interaction should be preserved
const interactiveElements = [
'input', 'textarea', 'button', 'select', 'option',
'video', 'audio', 'a', 'summary'
]
// Check for contenteditable attribute
const isContentEditable = activeElement.getAttribute('contenteditable') === 'true'
// Check for custom data attribute that might indicate spacebar interaction
const usesSpacebar = activeElement.getAttribute('data-uses-spacebar') === 'true'
if (e.code === 'Space' &&
!interactiveElements.includes(tagName) &&
!isContentEditable &&
!usesSpacebar) {
e.preventDefault() // Prevent the default action (scrolling)
navigator.mediaSession.playbackState = computed(() => (audio.getPlaying || false) ? 'playing' : 'paused').value
togglePlayingState()
}
}
const handlePlay = () => {
if (!playing.value) { togglePlayingState() }
}
const handlePause = () => {
if (playing.value) { togglePlayingState() }
}
const handleStop = () => {
if (playing.value) { togglePlayingState() }
}
const handleNext = () => {
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('nexttrack', async () => {
const nextTrack = getNextSoundscape()
await $changeTrack(nextTrack)
useArtWorkManager().addMusicArtWork(nextTrack)
})
}
}
const handlePrev = () => {
if ('mediaSession' in navigator) {
// Set the handler for the next track action
navigator.mediaSession.setActionHandler('previoustrack', async () => {
const nextTrack = getNextSoundscape()
await $changeTrack(nextTrack)
useArtWorkManager().addMusicArtWork(nextTrack)
})
}
}
// Set the handler for the previous track action
const actionHandlers = [
[
'play', handlePlay
],
[
'pause', handlePause
],
[
'stop', handleStop
],
[
'nexttrack', handleNext
],
[
'previoustrack', handlePrev
]
]
const removeMediaNavigationHandling = () => {
if ('mediaSession' in navigator) {
// Remove Play action handler
navigator.mediaSession.setActionHandler('play', null)
// Remove Pause action handler
navigator.mediaSession.setActionHandler('pause', null)
// Remove Previous track action handler
navigator.mediaSession.setActionHandler('previoustrack', null)
// Remove Next track action handler
navigator.mediaSession.setActionHandler('nexttrack', null)
}
}
const addPlayPauseHandling = () => {
if ('mediaSession' in navigator) {
// Previous track action
navigator.mediaSession.setActionHandler('previoustrack', () => {
this.skipTo(this.playlist.index - 1)
// useNuxtApp().$logger.log('Previous track button pressed')
})
// Next track action
navigator.mediaSession.setActionHandler('nexttrack', () => {
// Your next track action here
this.skipTo(this.playlist.index + 1)
// useNuxtApp().$logger.log('Next track button pressed')
})
}
}
return {
addSpaceListener,
addMediaControls,
getNextSoundscape,
getPreviousSoundscape
}
}