Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/web/src/components/now-playing/NowPlaying.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ import { LockedStatusBadge } from 'components/locked-status-badge'
import PlayButton from 'components/play-bar/PlayButton'
import NextButtonProvider from 'components/play-bar/next-button/NextButtonProvider'
import PreviousButtonProvider from 'components/play-bar/previous-button/PreviousButtonProvider'
import RepeatButtonProvider from 'components/play-bar/repeat-button/RepeatButtonProvider'
import ShuffleButtonProvider from 'components/play-bar/shuffle-button/ShuffleButtonProvider'
import RepeatButton from 'components/play-bar/repeat-button/RepeatButton'
import ShuffleButton from 'components/play-bar/shuffle-button/ShuffleButton'
import { PlayButtonStatus } from 'components/play-bar/types'
import { GatedConditionsPill } from 'components/track/GatedConditionsPill'
import { TrackDogEar } from 'components/track/TrackDogEar'
Expand Down Expand Up @@ -472,7 +472,7 @@ const NowPlaying = g(
</div>
<div className={styles.controls}>
<div className={styles.repeatButton}>
<RepeatButtonProvider
<RepeatButton
onRepeatOff={() => repeat(RepeatMode.OFF)}
onRepeatAll={() => repeat(RepeatMode.ALL)}
onRepeatSingle={() => repeat(RepeatMode.SINGLE)}
Expand All @@ -492,7 +492,7 @@ const NowPlaying = g(
<NextButtonProvider isMobile onClick={onNext} />
</div>
<div className={styles.shuffleButton}>
<ShuffleButtonProvider
<ShuffleButton
onShuffleOn={() => shuffle(true)}
onShuffleOff={() => shuffle(false)}
/>
Expand Down
8 changes: 4 additions & 4 deletions packages/web/src/components/play-bar/desktop/PlayBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import PlayButton from 'components/play-bar/PlayButton'
import VolumeBar from 'components/play-bar/VolumeBar'
import NextButtonProvider from 'components/play-bar/next-button/NextButtonProvider'
import PreviousButtonProvider from 'components/play-bar/previous-button/PreviousButtonProvider'
import RepeatButtonProvider from 'components/play-bar/repeat-button/RepeatButtonProvider'
import ShuffleButtonProvider from 'components/play-bar/shuffle-button/ShuffleButtonProvider'
import RepeatButton from 'components/play-bar/repeat-button/RepeatButton'
import ShuffleButton from 'components/play-bar/shuffle-button/ShuffleButton'
import { audioPlayer } from 'services/audio-player'
import { push } from 'utils/navigation'

Expand Down Expand Up @@ -305,7 +305,7 @@ const PlayBar = () => {
<div className={styles.buttonControls}>
<div className={styles.shuffleButton}>
{isLongFormContent ? null : (
<ShuffleButtonProvider
<ShuffleButton
onShuffleOn={shuffleOn}
onShuffleOff={shuffleOff}
/>
Expand All @@ -328,7 +328,7 @@ const PlayBar = () => {
{isLongFormContent ? (
<PlaybackRateButton isMobile={false} />
) : (
<RepeatButtonProvider
<RepeatButton
onRepeatOff={repeatOff}
onRepeatAll={repeatAll}
onRepeatSingle={repeatSingle}
Expand Down
95 changes: 73 additions & 22 deletions packages/web/src/components/play-bar/repeat-button/RepeatButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { useState, useEffect, useCallback, useRef } from 'react'
import cn from 'classnames'
import Lottie, { LottieRefCurrentProps } from 'lottie-react'

import { useIsMobile } from 'hooks/useIsMobile'
import { applyThemeToLottie } from 'utils/lottieTheme'
import { useLottieThemeColors } from 'utils/theme/theme'

import styles from '../PlayBarButton.module.css'

enum RepeatStates {
Expand All @@ -28,40 +32,83 @@ const getRepeatState = (defaultState: RepeatStates) => {
}
}

type AnimationStates = {
pbIconRepeatAll: object
pbIconRepeatSingle: object
pbIconRepeatOff: object
}

type RepeatButtonProps = {
animations: {
pbIconRepeatAll: object
pbIconRepeatSingle: object
pbIconRepeatOff: object
}
repeatOff: () => void
repeatSingle: () => void
repeatAll: () => void
isMobile: boolean
onRepeatOff: () => void
onRepeatAll: () => void
onRepeatSingle: () => void
}

const RepeatButton = ({
animations,
repeatOff = () => {},
repeatSingle = () => {},
repeatAll = () => {},
isMobile = false
onRepeatOff = () => {},
onRepeatAll = () => {},
onRepeatSingle = () => {}
}: RepeatButtonProps) => {
const themeColors = useLottieThemeColors()
const isMobile = useIsMobile()
const [animations, setAnimations] = useState<AnimationStates | null>(null)
const baseAnimations = useRef<AnimationStates | null>(null)

const [state, setState] = useState({
repeatState: getRepeatState(RepeatStates.OFF),
isPaused: true,
icon: animations ? animations.pbIconRepeatAll : null
icon: null as object | null
})

useEffect(() => {
const loadAnimations = async () => {
if (!baseAnimations.current) {
const { default: pbIconRepeatAll } = (await import(
'../../../assets/animations/pbIconRepeatAll.json'
)) as { default: object }
const { default: pbIconRepeatSingle } = (await import(
'../../../assets/animations/pbIconRepeatSingle.json'
)) as { default: object }
const { default: pbIconRepeatOff } = (await import(
'../../../assets/animations/pbIconRepeatOff.json'
)) as { default: object }
baseAnimations.current = {
pbIconRepeatAll,
pbIconRepeatSingle,
pbIconRepeatOff
}
}
setAnimations({
pbIconRepeatAll: applyThemeToLottie(
baseAnimations.current.pbIconRepeatAll,
themeColors,
'neutral'
),
pbIconRepeatSingle: applyThemeToLottie(
baseAnimations.current.pbIconRepeatSingle,
themeColors,
'primary'
),
pbIconRepeatOff: applyThemeToLottie(
baseAnimations.current.pbIconRepeatOff,
themeColors,
'primary'
)
})
}
loadAnimations()
}, [themeColors])

const handleChange = useCallback(
(repeatState: RepeatStates) => {
if (!animations) return
const { pbIconRepeatAll, pbIconRepeatSingle, pbIconRepeatOff } =
animations
// Go to the next state.
let icon, isPaused
let icon: object
let isPaused: boolean
switch (repeatState) {
case RepeatStates.OFF:
repeatOff()
onRepeatOff()
icon = pbIconRepeatAll
isPaused = true
break
Expand All @@ -70,7 +117,7 @@ const RepeatButton = ({
isPaused = false
break
case RepeatStates.ALL:
repeatAll()
onRepeatAll()
icon = pbIconRepeatSingle
isPaused = true
break
Expand All @@ -79,7 +126,7 @@ const RepeatButton = ({
isPaused = false
break
case RepeatStates.SINGLE:
repeatSingle()
onRepeatSingle()
icon = pbIconRepeatOff
isPaused = true
break
Expand All @@ -98,15 +145,17 @@ const RepeatButton = ({
repeatState
})
},
[animations, repeatOff, repeatAll, repeatSingle]
[animations, onRepeatOff, onRepeatAll, onRepeatSingle]
)

useEffect(() => {
handleChange(state.repeatState)
}, [handleChange, state.repeatState])

useEffect(() => {
handleChange(state.repeatState)
if (animations) {
handleChange(state.repeatState)
}
}, [animations, handleChange, state.repeatState])

const nextState = () => {
Expand All @@ -125,6 +174,8 @@ const RepeatButton = ({
}
}, [lottieRef, state.isPaused])

if (!animations || !state.icon) return null

return (
<button
className={cn(styles.button, {
Expand Down

This file was deleted.

Loading