120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
import {
|
|
Dispatch,
|
|
ReducerAction,
|
|
ReducerState,
|
|
useCallback,
|
|
useEffect,
|
|
useRef
|
|
} from "react"
|
|
import {
|
|
Action,
|
|
ActionTypes,
|
|
AudioPlayerState,
|
|
reducer
|
|
} from "./audioPlayerState"
|
|
import { HowlInstanceManager } from "./HowlInstanceManager"
|
|
import { HowlErrorCallback } from "howler"
|
|
|
|
export function useHowlEventSync(
|
|
howlManager: HowlInstanceManager,
|
|
[state, dispatch]: [AudioPlayerState, Dispatch<Action>]
|
|
): [ReducerState<typeof reducer>, Dispatch<ReducerAction<typeof reducer>>] {
|
|
const onLoad = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_LOAD, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onError: HowlErrorCallback = useCallback(
|
|
(_: number, errorCode: unknown) => {
|
|
dispatch({
|
|
type: ActionTypes.ON_ERROR,
|
|
message: errorCode as string
|
|
})
|
|
},
|
|
[dispatch]
|
|
)
|
|
|
|
const onPlay = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
// TODO since this is the sync layer i should really extract the info from the howl here and pass that in with the action payload
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_PLAY, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onPause = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_PAUSE, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onEnd = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_END, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onStop = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_STOP, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onMute = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_MUTE, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onVolume = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_VOLUME, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
const onRate = useCallback(() => {
|
|
const howl = howlManager.getHowl()
|
|
if (howl === undefined) return
|
|
dispatch({ type: ActionTypes.ON_RATE, howl })
|
|
}, [dispatch, howlManager])
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
const howl = howlManager.getHowl()
|
|
// howl?.off("load", onLoad)
|
|
howl?.off("loaderror", onError)
|
|
howl?.off("playerror", onError)
|
|
howl?.off("play", onPlay)
|
|
howl?.off("pause", onPause)
|
|
howl?.off("end", onEnd)
|
|
howl?.off("stop", onStop)
|
|
howl?.off("mute", onMute)
|
|
howl?.off("volume", onVolume)
|
|
howl?.off("rate", onRate)
|
|
}
|
|
}, [])
|
|
|
|
// using ref bc we don't want identity of dispatch function to change
|
|
// see talk: https://youtu.be/nUzLlHFVXx0?t=1558
|
|
const wrappedDispatch = useRef((action: Action) => {
|
|
if (action.type === ActionTypes.START_LOAD) {
|
|
const { howl } = action
|
|
// set up event listening
|
|
howl.once("load", onLoad)
|
|
howl.on("loaderror", onError)
|
|
howl.on("playerror", onError)
|
|
howl.on("play", onPlay)
|
|
howl.on("pause", onPause)
|
|
howl.on("end", onEnd)
|
|
howl.on("stop", onStop)
|
|
howl.on("mute", onMute)
|
|
howl.on("volume", onVolume)
|
|
howl.on("rate", onRate)
|
|
}
|
|
|
|
dispatch(action)
|
|
})
|
|
|
|
return [state, wrappedDispatch.current]
|
|
}
|