-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.ts
134 lines (111 loc) · 3.09 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { useEffect, useState } from 'react'
import {
DeviceEventEmitter,
EmitterSubscription,
NativeEventEmitter,
NativeModules,
Platform,
} from 'react-native'
// @ts-ignore
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'
const { Audio } = NativeModules
const emitter =
Platform.OS === 'ios' ? new NativeEventEmitter(Audio) : DeviceEventEmitter
// MARK: - Helpers
function resolveAsset(source?: number | string) {
if (!source) return undefined
return resolveAssetSource(source)?.uri || source
}
// MARK: - Audio Controls
const play = (source?: Source): Promise<void> => {
if (!source) return Audio.play()
source = { ...source }
source.uri = resolveAsset(source.uri)
source.artwork = resolveAsset(source.artwork)
return Audio.source(source).then(() => Audio.play())
}
const seekTo = (position: number): Promise<void> => Audio.seekTo(position)
const pause = (): Promise<void> => Audio.pause()
const stop = (): Promise<void> => Audio.stop()
// MARK: - Data
export enum PlaybackState {
Unknown = Audio.PLAYER_STATE_UNKNOWN,
Buffering = Audio.PLAYER_STATE_BUFFERING,
Paused = Audio.PLAYER_STATE_PAUSED,
Playing = Audio.PLAYER_STATE_PLAYING,
Ended = Audio.PLAYER_STATE_ENDED,
}
export enum PlayerEvent {
PlaybackState = 'player-state', // eslint-disable-line @typescript-eslint/no-shadow
Progress = 'player-progress',
Duration = 'player-duration',
}
export type Source = {
uri: string
title: string
artwork?: string
album?: string
artist?: string
albumArtist?: string
}
/**
* Adds a listener to be invoked when player events are emitted.
* An optional calling context may be provided. The data arguments
* emitted will be passed to the listener function.
*
* @param event - The player event to listen to
* @param listener - Function to invoke when the specified event is
* emitted
* @param context - Optional context object to use when invoking the
* listener
*/
const addListener = (
event: PlayerEvent,
listener: (...args: any[]) => any,
context?: any
): EmitterSubscription => {
return emitter.addListener(event, listener, context)
}
/**
* @description
* Get playback state
*/
export const usePlaybackState = (): PlaybackState => {
const [state, setState] = useState(PlaybackState.Unknown)
useEffect(() => {
const subscription = addListener(PlayerEvent.PlaybackState, setState)
return () => subscription.remove()
}, [])
return state
}
/**
* @description
* Get player duration
*/
export const usePlayerDuration = (): number => {
const [duration, setDuration] = useState(-1)
useEffect(() => {
const subscription = addListener(PlayerEvent.Duration, setDuration)
return () => subscription.remove()
}, [])
return duration
}
/**
* @description
* Get player progress
*/
export const usePlayerProgress = (): number => {
const [progress, setProgress] = useState(0)
useEffect(() => {
const subscription = addListener(PlayerEvent.Progress, setProgress)
return () => subscription.remove()
}, [])
return progress
}
export default {
addListener,
play,
seekTo,
pause,
stop,
}