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 } }