Skip to content

Commit

Permalink
Merge pull request #118 from ufosc/feature/tracks-state
Browse files Browse the repository at this point in the history
Tracks store, tracks queue
  • Loading branch information
IkeHunter authored Nov 2, 2024
2 parents c7eee30 + 005f70e commit 6d122b2
Show file tree
Hide file tree
Showing 29 changed files with 413 additions and 92 deletions.
13 changes: 6 additions & 7 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ import { useEffect } from 'react'
import { useSelector } from 'react-redux'
import { Outlet, useNavigate } from 'react-router-dom'
import { SocketProvider, Theme } from './context'
import { SpotifyPlayerProvider } from './context/PlayerContext'
import { SpotifyPlayer } from './SpotifyPlayer'
import {
fetchCurrentClubInfo,
fetchJukeboxes,
fetchUserInfo,
initializeUser,
logoutUser,
selectClubSpotifyAuth,
selectUser,
selectUserLoggedIn,
setAllClubs,
Expand All @@ -19,7 +18,6 @@ import {
export const App = () => {
const userIsLoggedIn = useSelector(selectUserLoggedIn)
const userInfo = useSelector(selectUser)
const spotifyAuth = useSelector(selectClubSpotifyAuth)

const navigate = useNavigate()

Expand Down Expand Up @@ -51,10 +49,11 @@ export const App = () => {

return (
<Theme>
<SpotifyPlayerProvider token={spotifyAuth?.access_token}>
<SocketProvider />
<Outlet />
</SpotifyPlayerProvider>
<SocketProvider>
<SpotifyPlayer>
<Outlet />
</SpotifyPlayer>
</SocketProvider>
</Theme>
)
}
49 changes: 49 additions & 0 deletions src/SpotifyPlayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useCallback, useContext, useEffect, type ReactNode } from 'react'
import { useSelector } from 'react-redux'
import { SocketContext, SpotifyPlayerProvider } from './context'
import { selectClubSpotifyAuth, setCurrentTrack, setNextTracks } from './store'
import { selectCurrentJukebox } from './store/jukebox'

export const SpotifyPlayer = (props: { children?: ReactNode }) => {
const { children } = props
const spotifyAuth = useSelector(selectClubSpotifyAuth)
const currentJukebox = useSelector(selectCurrentJukebox)
const {
emitMessage,
onEvent,
isConnected: socketIsConnected,
} = useContext(SocketContext)

// Passes updates from player context to server
const handlePlayerTrackChange = useCallback(
(newTrack: ITrack, prevTrack?: ITrack) => {
emitMessage<IPlayerUpdate>('player-update', {
current_track: newTrack,
jukebox_id: currentJukebox!.id,
})
},
[currentJukebox],
)

// Receives track updates from server, updates store
useEffect(() => {
onEvent<ITrackStateUpdate>('track-state-update', (data) => {
if (data.current_track) {
setCurrentTrack(data.current_track)
}
if (data.next_tracks) {
setNextTracks(data.next_tracks)
}
})
}, [currentJukebox, socketIsConnected])

return (
<SpotifyPlayerProvider
token={spotifyAuth?.access_token}
jukebox={currentJukebox}
onTrackChange={handlePlayerTrackChange}
>
{children}
</SpotifyPlayerProvider>
)
}
14 changes: 8 additions & 6 deletions src/apps/admin/pages/Overview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,18 @@
min-height: 49.5vh;

flex-direction: column;
padding-top: 4vh;
padding-bottom: 4vh;
padding-left: 0.5vw;
padding-right: 0.5vw;
border-radius: 10px;
margin-top: -10.5vh;

padding: 2.5rem;
border-radius: 1rem;
margin-top: -11.2rem;

position: relative;
z-index: 3;
overflow: overlay;

&__title {
@include font-headline('xs');
}
}

.curr-song {
Expand Down
73 changes: 60 additions & 13 deletions src/apps/admin/pages/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,50 @@ import { AudioPlayer } from 'src/components'
import './Overview.scss'

import Disk from 'src/assets/svg/Disk.svg?react'
import { SpotifyPlayerContext } from 'src/context'
import { mockTrack } from 'src/mock'

import { useSelector } from 'react-redux'
import { REACT_ENV, SPOTIFY_PLAYER_NAME } from 'src/config'
import { SpotifyPlayerContext } from 'src/context'
import { selectCurrentTrack, selectNextTracks } from 'src/store/track'
import { Track } from './Track'

export const Overview = () => {
const [song, setSong] = useState('')
const [author, setAuthor] = useState('')
const { currentTrack } = useContext(SpotifyPlayerContext)
// const { currentTrack } = useContext(SpotifyPlayerContext)
const storeCurrentTrack = useSelector(selectCurrentTrack)
const queuedTracks = useSelector(selectNextTracks)
const [currentTrackImage, setCurrentTrackImage] = useState('')
const songTitleRef = useRef<HTMLHeadingElement>(null)

const {
nextTracks: playerNextTracks,
currentTrack: playerCurrentTrack,
isActive,
isConnected,
connectDevice,
} = useContext(SpotifyPlayerContext)

useEffect(() => {
if (currentTrack == undefined) {
if (!playerCurrentTrack) {
setSong('No song Playing')
setAuthor('No Author')
setCurrentTrackImage(track?.album?.images[0].url)
} else {
setSong(currentTrack.name)
setSong(playerCurrentTrack.name)
setAuthor(
currentTrack.artists
playerCurrentTrack.artists
.map((artist: { name: any }) => artist.name)
.join(', '),
)
setCurrentTrackImage(currentTrack?.album?.images[0].url)
setCurrentTrackImage(playerCurrentTrack?.album?.images[0].url)

if (currentTrack.name.length > 15) {
if (playerCurrentTrack.name.length > 15) {
songTitleRef.current?.classList.add('song-title--small')
}
}
}, [currentTrack])
}, [playerCurrentTrack])

const track = mockTrack
return (
Expand Down Expand Up @@ -67,11 +80,45 @@ export const Overview = () => {
<div className="col-12">
<div className="song-queue scrollbar">
<ol className="board__queue__list track-list scrollbar">
<Track track={track} />
<Track track={track} />
<Track track={track} />
<Track track={track} />
<Track track={track} />
{(queuedTracks.length > 0 && (
<>
<h2 className="song-queue__title">Queued Tracks</h2>
{queuedTracks.map((track) => (
<Track track={track} />
))}
</>
)) ||
(playerNextTracks.length > 0 && (
<>
<h2 className="song-queue__title">Next Up</h2>
{playerNextTracks.map((track) => (
<Track track={track} />
))}
</>
)) || (
<>
<h2 className="song-queue__title">Setup Spotify</h2>

{(isConnected && !isActive && (
<>
<p>
Your account is connected to Spotify, transfer
playback to "{SPOTIFY_PLAYER_NAME}" to get started.
</p>
{REACT_ENV !== 'dev' && (
<p>
<button
className="button-solid"
onClick={connectDevice}
>
Connect
</button>
</p>
)}
</>
)) || <p>Connect your Spotify account to get started.</p>}
</>
)}
</ol>
</div>
</div>
Expand Down
12 changes: 10 additions & 2 deletions src/apps/admin/pages/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useContext } from 'react'
import { useSelector } from 'react-redux'
import { SpotifyPlayerContext } from 'src/context'
import { selectAllClubs, selectUser } from 'src/store'
import { selectAllJukeboxes } from 'src/store/jukebox'
import { selectAllJukeboxes, selectCurrentJukebox } from 'src/store/jukebox'

export const Settings = () => {
const clubs = useSelector(selectAllClubs)
const user = useSelector(selectUser)
const jukeboxes = useSelector(selectAllJukeboxes)
const currentJukebox = useSelector(selectCurrentJukebox)
const { connectDevice } = useContext(SpotifyPlayerContext)

return (
<div>
Expand Down Expand Up @@ -33,13 +37,17 @@ export const Settings = () => {
<ul>
{jukeboxes.map((jbx) => (
<li key={jbx.id}>
{jbx.name} (
{jbx.name}
{jbx.id === currentJukebox?.id ? '(active)' : ''} (
{clubs.find((club) => +club.id === +jbx.club_id)?.name ??
'No Club Found'}
)
</li>
))}
</ul>
{currentJukebox && (
<button onClick={connectDevice}>Transfer Playback</button>
)}
</section>
</div>
)
Expand Down
38 changes: 35 additions & 3 deletions src/components/audio/AudioPlayer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* @fileoverview Audio Player Component
*/
import { createContext, useContext, useEffect, useRef } from 'react'
import type { ChangeEvent } from 'react'
import { createContext, useContext, useEffect, useRef, useState } from 'react'
import { SpotifyPlayerContext } from 'src/context'
import './AudioPlayer.scss'
import { Controls } from './Controls'
Expand All @@ -24,6 +25,7 @@ export const AudioPlayerContext = createContext({
export const AudioPlayer = () => {
const {
nextTrack,
play,
pause,
player,
previousTrack,
Expand All @@ -32,8 +34,10 @@ export const AudioPlayer = () => {
currentTrack,
progress: timeProgress,
duration,
setTimeProgress,
} = useContext(SpotifyPlayerContext)
const progressBarRef = useRef<HTMLInputElement>(null)
const [editMode, setEditMode] = useState(false)

useEffect(() => {
if (progressBarRef.current) {
Expand All @@ -46,11 +50,39 @@ export const AudioPlayer = () => {
'--range-progress',
`${(timeProgress / duration) * 100}%`,
)

if (!editMode && progressBarRef.current) {
progressBarRef.current.value = String(timeProgress)
}
}, [timeProgress])

const setTimeProgress = () => {}
const onSetTimeProgress = (e: ChangeEvent<HTMLInputElement>) => {
console.log('Progress:', e.target.value)
setTimeProgress(+e.target.value)
}
const setDuration = () => {}

useEffect(() => {
const onMouseDown = () => {
pause()
setEditMode(true)
console.log('Mouse down')
}
const onMouseUp = () => {
play()
setEditMode(false)
console.log('Mouse up')
}

progressBarRef.current?.addEventListener('mousedown', onMouseDown)
progressBarRef.current?.addEventListener('mouseup', onMouseUp)

return () => {
progressBarRef.current?.removeEventListener('mousedown', onMouseDown)
progressBarRef.current?.removeEventListener('mouseup', onMouseUp)
}
}, [])

// Refs
const containerRef = useRef<HTMLDivElement>(null)

Expand All @@ -73,7 +105,7 @@ export const AudioPlayer = () => {
<div className="audio-player__inner">
<Controls />
<ProgressBar
onProgressChange={setTimeProgress}
onProgressChange={onSetTimeProgress}
ref={progressBarRef}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/audio/ProgressBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const ProgressBarComponent = (
type="range"
ref={ref}
onChange={onProgressChange}
value={timeProgress}
// value={timeProgress}
/>
<span className="time">{formatDuration(duration)}</span>
</div>
Expand Down
Loading

0 comments on commit 6d122b2

Please sign in to comment.