@roitium/expo-orpheus 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +5 -0
- package/README.md +11 -0
- package/android/build.gradle +51 -0
- package/android/src/main/AndroidManifest.xml +21 -0
- package/android/src/main/java/expo/modules/orpheus/ExpoOrpheusModule.kt +365 -0
- package/android/src/main/java/expo/modules/orpheus/NetworkModule.kt +46 -0
- package/android/src/main/java/expo/modules/orpheus/OrpheusConfig.kt +5 -0
- package/android/src/main/java/expo/modules/orpheus/OrpheusService.kt +142 -0
- package/android/src/main/java/expo/modules/orpheus/TrackRecord.kt +28 -0
- package/android/src/main/java/expo/modules/orpheus/bilibili/BilibiliApi.kt +24 -0
- package/android/src/main/java/expo/modules/orpheus/bilibili/BilibiliModels.kt +68 -0
- package/android/src/main/java/expo/modules/orpheus/bilibili/BilibiliRepository.kt +144 -0
- package/android/src/main/java/expo/modules/orpheus/bilibili/WbiUtil.kt +73 -0
- package/build/ExpoOrpheusModule.d.ts +98 -0
- package/build/ExpoOrpheusModule.d.ts.map +1 -0
- package/build/ExpoOrpheusModule.js +23 -0
- package/build/ExpoOrpheusModule.js.map +1 -0
- package/build/hooks/index.d.ts +7 -0
- package/build/hooks/index.d.ts.map +1 -0
- package/build/hooks/index.js +7 -0
- package/build/hooks/index.js.map +1 -0
- package/build/hooks/useCurrentTrack.d.ts +6 -0
- package/build/hooks/useCurrentTrack.d.ts.map +1 -0
- package/build/hooks/useCurrentTrack.js +41 -0
- package/build/hooks/useCurrentTrack.js.map +1 -0
- package/build/hooks/useIsPlaying.d.ts +2 -0
- package/build/hooks/useIsPlaying.d.ts.map +1 -0
- package/build/hooks/useIsPlaying.js +22 -0
- package/build/hooks/useIsPlaying.js.map +1 -0
- package/build/hooks/useOrpheus.d.ts +10 -0
- package/build/hooks/useOrpheus.d.ts.map +1 -0
- package/build/hooks/useOrpheus.js +20 -0
- package/build/hooks/useOrpheus.js.map +1 -0
- package/build/hooks/usePlaybackState.d.ts +3 -0
- package/build/hooks/usePlaybackState.d.ts.map +1 -0
- package/build/hooks/usePlaybackState.js +18 -0
- package/build/hooks/usePlaybackState.js.map +1 -0
- package/build/hooks/useProgress.d.ts +6 -0
- package/build/hooks/useProgress.d.ts.map +1 -0
- package/build/hooks/useProgress.js +59 -0
- package/build/hooks/useProgress.js.map +1 -0
- package/build/hooks/useShuffleMode.d.ts +2 -0
- package/build/hooks/useShuffleMode.d.ts.map +1 -0
- package/build/hooks/useShuffleMode.js +22 -0
- package/build/hooks/useShuffleMode.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +3 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +6 -0
- package/package.json +44 -0
- package/src/ExpoOrpheusModule.ts +114 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useCurrentTrack.ts +46 -0
- package/src/hooks/useIsPlaying.ts +25 -0
- package/src/hooks/useOrpheus.ts +21 -0
- package/src/hooks/usePlaybackState.ts +21 -0
- package/src/hooks/useProgress.ts +71 -0
- package/src/hooks/useShuffleMode.ts +26 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package expo.modules.orpheus.bilibili
|
|
2
|
+
|
|
3
|
+
import retrofit2.Call
|
|
4
|
+
import retrofit2.http.GET
|
|
5
|
+
import retrofit2.http.Header
|
|
6
|
+
import retrofit2.http.Query
|
|
7
|
+
import retrofit2.http.QueryMap
|
|
8
|
+
|
|
9
|
+
interface BilibiliApi {
|
|
10
|
+
@GET("/x/web-interface/nav")
|
|
11
|
+
fun getNavInfo(): Call<BilibiliNavResponse>
|
|
12
|
+
|
|
13
|
+
@GET("/x/player/wbi/playurl")
|
|
14
|
+
fun getPlayUrl(
|
|
15
|
+
@Header("Cookie") cookie: String? = null,
|
|
16
|
+
@QueryMap params: Map<String, String>
|
|
17
|
+
): Call<BilibiliApiResponse<BilibiliAudioStreamResponse>>
|
|
18
|
+
|
|
19
|
+
@GET("/x/player/pagelist")
|
|
20
|
+
fun getPageList(
|
|
21
|
+
@Header("Cookie") cookie: String? = null,
|
|
22
|
+
@Query("bvid") bvid: String
|
|
23
|
+
): Call<BilibiliApiResponse<List<BilibiliPageListResponse>>>
|
|
24
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package expo.modules.orpheus.bilibili
|
|
2
|
+
|
|
3
|
+
import com.google.gson.annotations.SerializedName
|
|
4
|
+
|
|
5
|
+
data class BilibiliApiResponse<TData>(
|
|
6
|
+
val code: Int,
|
|
7
|
+
val message: String,
|
|
8
|
+
val data: TData?
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
data class BilibiliAudioStreamResponse(
|
|
12
|
+
val durl: List<DurlItem>?,
|
|
13
|
+
|
|
14
|
+
val dash: DashData?,
|
|
15
|
+
|
|
16
|
+
val volume: VolumeData?
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
data class DurlItem(
|
|
20
|
+
val order: Int,
|
|
21
|
+
val url: String,
|
|
22
|
+
@SerializedName("backup_url") val backupUrl: List<String>?
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
data class DashData(
|
|
26
|
+
val audio: List<DashAudioItem>?,
|
|
27
|
+
val dolby: DolbyData?,
|
|
28
|
+
val flac: FlacData?
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
data class DashAudioItem(
|
|
32
|
+
val id: Int,
|
|
33
|
+
@SerializedName("base_url") val baseUrl: String,
|
|
34
|
+
@SerializedName("backup_url") val backupUrl: List<String>?
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
data class DolbyData(
|
|
38
|
+
val type: Int,
|
|
39
|
+
val audio: List<DashAudioItem>?
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
data class FlacData(
|
|
43
|
+
val display: Boolean,
|
|
44
|
+
val audio: DashAudioItem?
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
data class VolumeData(
|
|
48
|
+
@SerializedName("measured_i") val measuredI: Double,
|
|
49
|
+
@SerializedName("target_i") val targetI: Double
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
data class BilibiliNavResponse(
|
|
53
|
+
val code: Int,
|
|
54
|
+
val data: NavData?
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
data class NavData(
|
|
58
|
+
@SerializedName("wbi_img") val wbiImg: WbiImgData?
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
data class WbiImgData(
|
|
62
|
+
@SerializedName("img_url") val imgUrl: String,
|
|
63
|
+
@SerializedName("sub_url") val subUrl: String
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
data class BilibiliPageListResponse(
|
|
67
|
+
val cid: Long
|
|
68
|
+
)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
package expo.modules.orpheus.bilibili
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import expo.modules.orpheus.NetworkModule
|
|
5
|
+
import java.io.IOException
|
|
6
|
+
import java.text.SimpleDateFormat
|
|
7
|
+
import java.util.Date
|
|
8
|
+
import java.util.Locale
|
|
9
|
+
|
|
10
|
+
object BilibiliRepository {
|
|
11
|
+
val TAG = "Orpheus/BilibiliRepo"
|
|
12
|
+
|
|
13
|
+
private val api: BilibiliApi by lazy {
|
|
14
|
+
NetworkModule.retrofit.create(BilibiliApi::class.java)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private var cachedImgKey: String? = null
|
|
18
|
+
private var cachedSubKey: String? = null
|
|
19
|
+
private var cachedDateStr: String? = null
|
|
20
|
+
|
|
21
|
+
private fun getTodayDateStr(): String {
|
|
22
|
+
val sdf = SimpleDateFormat("yyyyMMdd", Locale.getDefault())
|
|
23
|
+
return sdf.format(Date())
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Synchronized
|
|
27
|
+
private fun getWbiKeys(): Pair<String, String> {
|
|
28
|
+
val today = getTodayDateStr()
|
|
29
|
+
|
|
30
|
+
if (cachedImgKey != null && cachedSubKey != null && today == cachedDateStr) {
|
|
31
|
+
return cachedImgKey!! to cachedSubKey!!
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
val response = api.getNavInfo().execute()
|
|
35
|
+
val wbiData = response.body()?.data?.wbiImg
|
|
36
|
+
|
|
37
|
+
if (!response.isSuccessful || wbiData == null) {
|
|
38
|
+
throw IOException("Failed to fetch Wbi Keys: ${response.code()}")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
val imgKey = WbiUtil.extractKey(wbiData.imgUrl)
|
|
42
|
+
val subKey = WbiUtil.extractKey(wbiData.subUrl)
|
|
43
|
+
|
|
44
|
+
cachedImgKey = imgKey
|
|
45
|
+
cachedSubKey = subKey
|
|
46
|
+
cachedDateStr = today
|
|
47
|
+
|
|
48
|
+
return imgKey to subKey
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 解析音频 URL
|
|
53
|
+
*/
|
|
54
|
+
fun resolveAudioUrl(
|
|
55
|
+
bvid: String,
|
|
56
|
+
cid: Long?,
|
|
57
|
+
audioQuality: Int,
|
|
58
|
+
enableDolby: Boolean,
|
|
59
|
+
enableHiRes: Boolean,
|
|
60
|
+
cookie: String?
|
|
61
|
+
): String {
|
|
62
|
+
var cidInternal = cid
|
|
63
|
+
val (imgKey, subKey) = getWbiKeys()
|
|
64
|
+
if (cidInternal === null) {
|
|
65
|
+
cidInternal = getFirstCid(bvid, cookie)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Log.e(TAG, "resolve url: bvid: $bvid, cid: $cid, enableDolby: ")
|
|
69
|
+
|
|
70
|
+
val rawParams = mapOf(
|
|
71
|
+
"bvid" to bvid,
|
|
72
|
+
"cid" to cidInternal,
|
|
73
|
+
"fnval" to 4048,
|
|
74
|
+
"fnver" to 0,
|
|
75
|
+
"fourk" to 1,
|
|
76
|
+
"qlt" to audioQuality,
|
|
77
|
+
"voice_balance" to 1
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
val signedParams = WbiUtil.sign(rawParams, imgKey, subKey)
|
|
81
|
+
|
|
82
|
+
val call = api.getPlayUrl(cookie, signedParams)
|
|
83
|
+
val response = call.execute()
|
|
84
|
+
|
|
85
|
+
if (!response.isSuccessful) {
|
|
86
|
+
throw IOException("Bilibili API Http Error: ${response.code()}")
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
val apiResponse = response.body()
|
|
90
|
+
if (apiResponse?.code != 0 || apiResponse.data == null) {
|
|
91
|
+
throw IOException("Bilibili API Logic Error: code=${apiResponse?.code} msg=${apiResponse?.message}")
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
val data = apiResponse.data
|
|
95
|
+
val dash = data.dash
|
|
96
|
+
val durl = data.durl
|
|
97
|
+
|
|
98
|
+
if (dash == null) {
|
|
99
|
+
if (durl.isNullOrEmpty()) {
|
|
100
|
+
throw IOException("AudioStreamError: 请求到的流数据不包含 dash 或 durl 任一字段")
|
|
101
|
+
}
|
|
102
|
+
return durl[0].url
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (enableDolby && dash.dolby?.audio?.isNotEmpty() == true) {
|
|
106
|
+
Log.d(TAG, "select dolby source")
|
|
107
|
+
return dash.dolby.audio[0].baseUrl
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (enableHiRes && dash.flac?.audio != null) {
|
|
111
|
+
Log.d(TAG, "select hires source")
|
|
112
|
+
return dash.flac.audio.baseUrl
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (dash.audio.isNullOrEmpty()) {
|
|
116
|
+
throw IOException("AudioStreamError: 未找到有效的音频流数据")
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
val targetAudio = dash.audio.find { it.id == audioQuality }
|
|
120
|
+
|
|
121
|
+
if (targetAudio != null) {
|
|
122
|
+
return targetAudio.baseUrl
|
|
123
|
+
} else {
|
|
124
|
+
val highestQualityAudio = dash.audio[0]
|
|
125
|
+
return highestQualityAudio.baseUrl
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fun getFirstCid(bvid: String, cookie: String?): Long {
|
|
130
|
+
val call = api.getPageList(cookie = cookie, bvid = bvid)
|
|
131
|
+
val response = call.execute()
|
|
132
|
+
|
|
133
|
+
if (!response.isSuccessful) {
|
|
134
|
+
throw IOException("Bilibili API Http Error: ${response.code()}")
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
val apiResponse = response.body()
|
|
138
|
+
if (apiResponse?.code != 0 || apiResponse.data == null) {
|
|
139
|
+
throw IOException("Bilibili API Logic Error: code=${apiResponse?.code} msg=${apiResponse?.message}")
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return apiResponse.data[0].cid
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package expo.modules.orpheus.bilibili
|
|
2
|
+
|
|
3
|
+
import java.net.URLEncoder
|
|
4
|
+
import java.security.MessageDigest
|
|
5
|
+
import java.util.TreeMap
|
|
6
|
+
|
|
7
|
+
object WbiUtil {
|
|
8
|
+
private val mixinKeyEncTab = intArrayOf(
|
|
9
|
+
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
|
|
10
|
+
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
|
|
11
|
+
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
|
|
12
|
+
36, 20, 34, 44, 52
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
private fun String.toMD5(): String {
|
|
16
|
+
val md = MessageDigest.getInstance("MD5")
|
|
17
|
+
val digest = md.digest(this.toByteArray())
|
|
18
|
+
return digest.joinToString("") { "%02x".format(it) }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private fun Any?.encodeURIComponent(): String {
|
|
22
|
+
if (this == null) return ""
|
|
23
|
+
return URLEncoder.encode(this.toString(), "UTF-8")
|
|
24
|
+
.replace("+", "%20")
|
|
25
|
+
.replace("*", "%2A")
|
|
26
|
+
.replace("%7E", "~")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 计算 WBI 混淆键
|
|
31
|
+
*/
|
|
32
|
+
private fun getMixinKey(orig: String): String {
|
|
33
|
+
return buildString {
|
|
34
|
+
repeat(32) {
|
|
35
|
+
if (it < mixinKeyEncTab.size && mixinKeyEncTab[it] < orig.length) {
|
|
36
|
+
append(orig[mixinKeyEncTab[it]])
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 核心签名方法
|
|
44
|
+
* @param params 原始参数 Map
|
|
45
|
+
* @param imgKey 来自 /nav 接口
|
|
46
|
+
* @param subKey 来自 /nav 接口
|
|
47
|
+
* @return 包含 w_rid 和 wts 的完整参数 Map
|
|
48
|
+
*/
|
|
49
|
+
fun sign(params: Map<String, Any?>, imgKey: String, subKey: String): Map<String, String> {
|
|
50
|
+
val mixinKey = getMixinKey(imgKey + subKey)
|
|
51
|
+
val currTime = System.currentTimeMillis() / 1000
|
|
52
|
+
|
|
53
|
+
val sortedParams = TreeMap<String, Any?>()
|
|
54
|
+
params.forEach { (k, v) -> if (v != null) sortedParams[k] = v }
|
|
55
|
+
sortedParams["wts"] = currTime
|
|
56
|
+
|
|
57
|
+
val queryStr = sortedParams.entries.joinToString("&") { (k, v) ->
|
|
58
|
+
"${k.encodeURIComponent()}=${v.encodeURIComponent()}"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
val w_rid = (queryStr + mixinKey).toMD5()
|
|
62
|
+
|
|
63
|
+
val finalMap = HashMap<String, String>()
|
|
64
|
+
sortedParams.forEach { (k, v) -> finalMap[k] = v.toString() }
|
|
65
|
+
finalMap["w_rid"] = w_rid
|
|
66
|
+
|
|
67
|
+
return finalMap
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun extractKey(url: String): String {
|
|
71
|
+
return url.substringAfterLast("/").substringBeforeLast(".")
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { NativeModule } from "expo-modules-core";
|
|
2
|
+
export declare enum PlaybackState {
|
|
3
|
+
IDLE = 1,
|
|
4
|
+
BUFFERING = 2,
|
|
5
|
+
READY = 3,
|
|
6
|
+
ENDED = 4
|
|
7
|
+
}
|
|
8
|
+
export declare enum RepeatMode {
|
|
9
|
+
OFF = 0,
|
|
10
|
+
TRACK = 1,
|
|
11
|
+
QUEUE = 2
|
|
12
|
+
}
|
|
13
|
+
export declare enum TransitionReason {
|
|
14
|
+
REPEAT = 0,
|
|
15
|
+
AUTO = 1,
|
|
16
|
+
SEEK = 2,
|
|
17
|
+
PLAYLIST_CHANGED = 3
|
|
18
|
+
}
|
|
19
|
+
export interface Track {
|
|
20
|
+
id: string;
|
|
21
|
+
url: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
artist?: string;
|
|
24
|
+
artwork?: string;
|
|
25
|
+
duration?: number;
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
}
|
|
28
|
+
export type OrpheusEvents = {
|
|
29
|
+
onPlaybackStateChanged(event: {
|
|
30
|
+
state: PlaybackState;
|
|
31
|
+
}): void;
|
|
32
|
+
onTrackTransition(event: {
|
|
33
|
+
currentTrackId: string;
|
|
34
|
+
previousTrackId?: string;
|
|
35
|
+
reason: TransitionReason;
|
|
36
|
+
}): void;
|
|
37
|
+
onPlayerError(event: {
|
|
38
|
+
code: string;
|
|
39
|
+
message: string;
|
|
40
|
+
}): void;
|
|
41
|
+
onPositionUpdate(event: {
|
|
42
|
+
position: number;
|
|
43
|
+
duration: number;
|
|
44
|
+
buffered: number;
|
|
45
|
+
}): void;
|
|
46
|
+
onIsPlayingChanged(event: {
|
|
47
|
+
status: boolean;
|
|
48
|
+
}): void;
|
|
49
|
+
};
|
|
50
|
+
declare class OrpheusModule extends NativeModule<OrpheusEvents> {
|
|
51
|
+
/**
|
|
52
|
+
* 获取当前进度(秒)
|
|
53
|
+
*/
|
|
54
|
+
getPosition(): Promise<number>;
|
|
55
|
+
/**
|
|
56
|
+
* 获取总时长(秒)
|
|
57
|
+
*/
|
|
58
|
+
getDuration(): Promise<number>;
|
|
59
|
+
/**
|
|
60
|
+
* 获取是否正在播放
|
|
61
|
+
*/
|
|
62
|
+
getIsPlaying(): Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* 获取当前播放索引
|
|
65
|
+
*/
|
|
66
|
+
getCurrentIndex(): Promise<number>;
|
|
67
|
+
/**
|
|
68
|
+
* 获取当前播放的 Track 对象
|
|
69
|
+
*/
|
|
70
|
+
getCurrentTrack(): Promise<Track | null>;
|
|
71
|
+
/**
|
|
72
|
+
* 获取随机模式状态
|
|
73
|
+
*/
|
|
74
|
+
getShuffleMode(): Promise<boolean>;
|
|
75
|
+
/**
|
|
76
|
+
* 获取指定索引的 Track
|
|
77
|
+
*/
|
|
78
|
+
getIndexTrack(index: number): Promise<Track | null>;
|
|
79
|
+
setBilibiliCookie(cookie: string): void;
|
|
80
|
+
play(): Promise<void>;
|
|
81
|
+
pause(): Promise<void>;
|
|
82
|
+
clear(): Promise<void>;
|
|
83
|
+
skipTo(index: number): Promise<void>;
|
|
84
|
+
skipToNext(): Promise<void>;
|
|
85
|
+
skipToPrevious(): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* 跳转进度
|
|
88
|
+
* @param seconds 秒数
|
|
89
|
+
*/
|
|
90
|
+
seekTo(seconds: number): Promise<void>;
|
|
91
|
+
setRepeatMode(mode: RepeatMode): Promise<void>;
|
|
92
|
+
setShuffleMode(enabled: boolean): Promise<void>;
|
|
93
|
+
getQueue(): Promise<Track[]>;
|
|
94
|
+
add(tracks: Track[]): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
export declare const Orpheus: OrpheusModule;
|
|
97
|
+
export {};
|
|
98
|
+
//# sourceMappingURL=ExpoOrpheusModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoOrpheusModule.d.ts","sourceRoot":"","sources":["../src/ExpoOrpheusModule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { requireNativeModule } from "expo-modules-core";
|
|
2
|
+
export var PlaybackState;
|
|
3
|
+
(function (PlaybackState) {
|
|
4
|
+
PlaybackState[PlaybackState["IDLE"] = 1] = "IDLE";
|
|
5
|
+
PlaybackState[PlaybackState["BUFFERING"] = 2] = "BUFFERING";
|
|
6
|
+
PlaybackState[PlaybackState["READY"] = 3] = "READY";
|
|
7
|
+
PlaybackState[PlaybackState["ENDED"] = 4] = "ENDED";
|
|
8
|
+
})(PlaybackState || (PlaybackState = {}));
|
|
9
|
+
export var RepeatMode;
|
|
10
|
+
(function (RepeatMode) {
|
|
11
|
+
RepeatMode[RepeatMode["OFF"] = 0] = "OFF";
|
|
12
|
+
RepeatMode[RepeatMode["TRACK"] = 1] = "TRACK";
|
|
13
|
+
RepeatMode[RepeatMode["QUEUE"] = 2] = "QUEUE";
|
|
14
|
+
})(RepeatMode || (RepeatMode = {}));
|
|
15
|
+
export var TransitionReason;
|
|
16
|
+
(function (TransitionReason) {
|
|
17
|
+
TransitionReason[TransitionReason["REPEAT"] = 0] = "REPEAT";
|
|
18
|
+
TransitionReason[TransitionReason["AUTO"] = 1] = "AUTO";
|
|
19
|
+
TransitionReason[TransitionReason["SEEK"] = 2] = "SEEK";
|
|
20
|
+
TransitionReason[TransitionReason["PLAYLIST_CHANGED"] = 3] = "PLAYLIST_CHANGED";
|
|
21
|
+
})(TransitionReason || (TransitionReason = {}));
|
|
22
|
+
export const Orpheus = requireNativeModule("Orpheus");
|
|
23
|
+
//# sourceMappingURL=ExpoOrpheusModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoOrpheusModule.js","sourceRoot":"","sources":["../src/ExpoOrpheusModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgB,MAAM,mBAAmB,CAAC;AAEtE,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,iDAAQ,CAAA;IACR,2DAAa,CAAA;IACb,mDAAS,CAAA;IACT,mDAAS,CAAA;AACX,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAED,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,yCAAO,CAAA;IACP,6CAAS,CAAA;IACT,6CAAS,CAAA;AACX,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAED,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IAC1B,2DAAU,CAAA;IACV,uDAAQ,CAAA;IACR,uDAAQ,CAAA;IACR,+EAAoB,CAAA;AACtB,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B;AA6FD,MAAM,CAAC,MAAM,OAAO,GAAG,mBAAmB,CAAgB,SAAS,CAAC,CAAC","sourcesContent":["import { requireNativeModule, NativeModule } from \"expo-modules-core\";\n\nexport enum PlaybackState {\n IDLE = 1,\n BUFFERING = 2,\n READY = 3,\n ENDED = 4,\n}\n\nexport enum RepeatMode {\n OFF = 0,\n TRACK = 1,\n QUEUE = 2,\n}\n\nexport enum TransitionReason {\n REPEAT = 0,\n AUTO = 1,\n SEEK = 2,\n PLAYLIST_CHANGED = 3,\n}\n\nexport interface Track {\n id: string;\n url: string;\n title?: string;\n artist?: string;\n artwork?: string;\n duration?: number;\n [key: string]: any;\n}\n\nexport type OrpheusEvents = {\n onPlaybackStateChanged(event: { state: PlaybackState }): void;\n onTrackTransition(event: {\n currentTrackId: string;\n previousTrackId?: string;\n reason: TransitionReason;\n }): void;\n onPlayerError(event: { code: string; message: string }): void;\n onPositionUpdate(event: {\n position: number;\n duration: number;\n buffered: number;\n }): void;\n onIsPlayingChanged(event: { status: boolean }): void;\n};\n\ndeclare class OrpheusModule extends NativeModule<OrpheusEvents> {\n /**\n * 获取当前进度(秒)\n */\n getPosition(): Promise<number>;\n\n /**\n * 获取总时长(秒)\n */\n getDuration(): Promise<number>;\n\n /**\n * 获取是否正在播放\n */\n getIsPlaying(): Promise<boolean>;\n\n /**\n * 获取当前播放索引\n */\n getCurrentIndex(): Promise<number>;\n\n /**\n * 获取当前播放的 Track 对象\n */\n getCurrentTrack(): Promise<Track | null>;\n\n /**\n * 获取随机模式状态\n */\n getShuffleMode(): Promise<boolean>;\n\n /**\n * 获取指定索引的 Track\n */\n getIndexTrack(index: number): Promise<Track | null>;\n\n setBilibiliCookie(cookie: string): void;\n\n play(): Promise<void>;\n\n pause(): Promise<void>;\n\n clear(): Promise<void>;\n\n skipTo(index: number): Promise<void>;\n\n skipToNext(): Promise<void>;\n\n skipToPrevious(): Promise<void>;\n\n /**\n * 跳转进度\n * @param seconds 秒数\n */\n seekTo(seconds: number): Promise<void>;\n\n setRepeatMode(mode: RepeatMode): Promise<void>;\n\n setShuffleMode(enabled: boolean): Promise<void>;\n\n getQueue(): Promise<Track[]>;\n\n add(tracks: Track[]): Promise<void>;\n}\n\nexport const Orpheus = requireNativeModule<OrpheusModule>(\"Orpheus\");\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC","sourcesContent":["export * from './useProgress';\nexport * from './usePlaybackState';\nexport * from './useIsPlaying';\nexport * from './useCurrentTrack';\nexport * from './useShuffleMode';\nexport * from './useOrpheus';"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCurrentTrack.d.ts","sourceRoot":"","sources":["../../src/hooks/useCurrentTrack.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAW,MAAM,sBAAsB,CAAC;AAEtD,wBAAgB,eAAe;;;EA0C9B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { Orpheus } from "../ExpoOrpheusModule";
|
|
3
|
+
export function useCurrentTrack() {
|
|
4
|
+
const [track, setTrack] = useState(null);
|
|
5
|
+
const [index, setIndex] = useState(-1);
|
|
6
|
+
const fetchTrack = async () => {
|
|
7
|
+
try {
|
|
8
|
+
const [currentTrack, currentIndex] = await Promise.all([
|
|
9
|
+
Orpheus.getCurrentTrack(),
|
|
10
|
+
Orpheus.getCurrentIndex(),
|
|
11
|
+
]);
|
|
12
|
+
return { currentTrack, currentIndex };
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.warn("Failed to fetch current track", e);
|
|
16
|
+
return { currentTrack: null, currentIndex: -1 };
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
let isMounted = true;
|
|
21
|
+
fetchTrack().then(({ currentTrack, currentIndex }) => {
|
|
22
|
+
if (isMounted) {
|
|
23
|
+
setTrack(currentTrack);
|
|
24
|
+
setIndex(currentIndex);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const sub = Orpheus.addListener("onTrackTransition", async () => {
|
|
28
|
+
const { currentTrack, currentIndex } = await fetchTrack();
|
|
29
|
+
if (isMounted) {
|
|
30
|
+
setTrack(currentTrack);
|
|
31
|
+
setIndex(currentIndex);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return () => {
|
|
35
|
+
isMounted = false;
|
|
36
|
+
sub.remove();
|
|
37
|
+
};
|
|
38
|
+
}, []);
|
|
39
|
+
return { track, index };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=useCurrentTrack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCurrentTrack.js","sourceRoot":"","sources":["../../src/hooks/useCurrentTrack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAS,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACrD,OAAO,CAAC,eAAe,EAAE;gBACzB,OAAO,CAAC,eAAe,EAAE;aAC1B,CAAC,CAAC;YACH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;QACxC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAC;YACjD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC;QAClD,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,IAAI,CAAC;QAErB,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,EAAE;YACnD,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACvB,QAAQ,CAAC,YAAY,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;YAC1D,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACvB,QAAQ,CAAC,YAAY,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,KAAK,CAAC;YAClB,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC","sourcesContent":["import { useState, useEffect } from \"react\";\nimport { Track, Orpheus } from \"../ExpoOrpheusModule\";\n\nexport function useCurrentTrack() {\n const [track, setTrack] = useState<Track | null>(null);\n const [index, setIndex] = useState<number>(-1);\n\n const fetchTrack = async () => {\n try {\n const [currentTrack, currentIndex] = await Promise.all([\n Orpheus.getCurrentTrack(),\n Orpheus.getCurrentIndex(),\n ]);\n return { currentTrack, currentIndex };\n } catch (e) {\n console.warn(\"Failed to fetch current track\", e);\n return { currentTrack: null, currentIndex: -1 };\n }\n };\n\n useEffect(() => {\n let isMounted = true;\n\n fetchTrack().then(({ currentTrack, currentIndex }) => {\n if (isMounted) {\n setTrack(currentTrack);\n setIndex(currentIndex);\n }\n });\n\n const sub = Orpheus.addListener(\"onTrackTransition\", async () => {\n const { currentTrack, currentIndex } = await fetchTrack();\n if (isMounted) {\n setTrack(currentTrack);\n setIndex(currentIndex);\n }\n });\n\n return () => {\n isMounted = false;\n sub.remove();\n };\n }, []);\n\n return { track, index };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsPlaying.d.ts","sourceRoot":"","sources":["../../src/hooks/useIsPlaying.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,YAqB3B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { Orpheus } from "../ExpoOrpheusModule";
|
|
3
|
+
export function useIsPlaying() {
|
|
4
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
let isMounted = true;
|
|
7
|
+
Orpheus.getIsPlaying().then((val) => {
|
|
8
|
+
if (isMounted)
|
|
9
|
+
setIsPlaying(val);
|
|
10
|
+
});
|
|
11
|
+
const sub = Orpheus.addListener("onIsPlayingChanged", (event) => {
|
|
12
|
+
if (isMounted)
|
|
13
|
+
setIsPlaying(event.status);
|
|
14
|
+
});
|
|
15
|
+
return () => {
|
|
16
|
+
isMounted = false;
|
|
17
|
+
sub.remove();
|
|
18
|
+
};
|
|
19
|
+
}, []);
|
|
20
|
+
return isPlaying;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=useIsPlaying.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsPlaying.js","sourceRoot":"","sources":["../../src/hooks/useIsPlaying.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,IAAI,CAAC;QAErB,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YAClC,IAAI,SAAS;gBAAE,YAAY,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9D,IAAI,SAAS;gBAAE,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,KAAK,CAAC;YAClB,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import { useState, useEffect } from \"react\";\nimport { Orpheus } from \"../ExpoOrpheusModule\";\n\nexport function useIsPlaying() {\n const [isPlaying, setIsPlaying] = useState(false);\n\n useEffect(() => {\n let isMounted = true;\n\n Orpheus.getIsPlaying().then((val) => {\n if (isMounted) setIsPlaying(val);\n });\n\n const sub = Orpheus.addListener(\"onIsPlayingChanged\", (event) => {\n if (isMounted) setIsPlaying(event.status);\n });\n\n return () => {\n isMounted = false;\n sub.remove();\n };\n }, []);\n\n return isPlaying;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function useOrpheus(): {
|
|
2
|
+
state: import("..").PlaybackState;
|
|
3
|
+
isPlaying: boolean;
|
|
4
|
+
position: number;
|
|
5
|
+
duration: number;
|
|
6
|
+
buffered: number;
|
|
7
|
+
currentTrack: import("..").Track | null;
|
|
8
|
+
currentIndex: number;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=useOrpheus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOrpheus.d.ts","sourceRoot":"","sources":["../../src/hooks/useOrpheus.ts"],"names":[],"mappings":"AAKA,wBAAgB,UAAU;;;;;;;;EAezB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useCurrentTrack } from "./useCurrentTrack";
|
|
2
|
+
import { useIsPlaying } from "./useIsPlaying";
|
|
3
|
+
import { usePlaybackState } from "./usePlaybackState";
|
|
4
|
+
import { useProgress } from "./useProgress";
|
|
5
|
+
export function useOrpheus() {
|
|
6
|
+
const state = usePlaybackState();
|
|
7
|
+
const isPlaying = useIsPlaying();
|
|
8
|
+
const progress = useProgress();
|
|
9
|
+
const { track, index } = useCurrentTrack();
|
|
10
|
+
return {
|
|
11
|
+
state,
|
|
12
|
+
isPlaying,
|
|
13
|
+
position: progress.position,
|
|
14
|
+
duration: progress.duration,
|
|
15
|
+
buffered: progress.buffered,
|
|
16
|
+
currentTrack: track,
|
|
17
|
+
currentIndex: index,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=useOrpheus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOrpheus.js","sourceRoot":"","sources":["../../src/hooks/useOrpheus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,UAAU,UAAU;IACxB,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAE3C,OAAO;QACL,KAAK;QACL,SAAS;QACT,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,YAAY,EAAE,KAAK;QACnB,YAAY,EAAE,KAAK;KACpB,CAAC;AACJ,CAAC","sourcesContent":["import { useCurrentTrack } from \"./useCurrentTrack\";\nimport { useIsPlaying } from \"./useIsPlaying\";\nimport { usePlaybackState } from \"./usePlaybackState\";\nimport { useProgress } from \"./useProgress\";\n\nexport function useOrpheus() {\n const state = usePlaybackState();\n const isPlaying = useIsPlaying();\n const progress = useProgress();\n const { track, index } = useCurrentTrack();\n\n return {\n state,\n isPlaying,\n position: progress.position,\n duration: progress.duration,\n buffered: progress.buffered,\n currentTrack: track,\n currentIndex: index,\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlaybackState.d.ts","sourceRoot":"","sources":["../../src/hooks/usePlaybackState.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE9D,wBAAgB,gBAAgB,kBAiB/B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { Orpheus, PlaybackState } from "../ExpoOrpheusModule";
|
|
3
|
+
export function usePlaybackState() {
|
|
4
|
+
const [state, setState] = useState(PlaybackState.IDLE);
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
let isMounted = true;
|
|
7
|
+
const sub = Orpheus.addListener("onPlaybackStateChanged", (event) => {
|
|
8
|
+
if (isMounted)
|
|
9
|
+
setState(event.state);
|
|
10
|
+
});
|
|
11
|
+
return () => {
|
|
12
|
+
isMounted = false;
|
|
13
|
+
sub.remove();
|
|
14
|
+
};
|
|
15
|
+
}, []);
|
|
16
|
+
return state;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=usePlaybackState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlaybackState.js","sourceRoot":"","sources":["../../src/hooks/usePlaybackState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,aAAa,CAAC,IAAI,CAAC,CAAC;IAEtE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,IAAI,CAAC;QAErB,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,wBAAwB,EAAE,CAAC,KAAK,EAAE,EAAE;YAClE,IAAI,SAAS;gBAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,KAAK,CAAC;YAClB,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { useEffect, useState } from \"react\";\nimport { Orpheus, PlaybackState } from \"../ExpoOrpheusModule\";\n\nexport function usePlaybackState() {\n const [state, setState] = useState<PlaybackState>(PlaybackState.IDLE);\n\n useEffect(() => {\n let isMounted = true;\n\n const sub = Orpheus.addListener(\"onPlaybackStateChanged\", (event) => {\n if (isMounted) setState(event.state);\n });\n\n return () => {\n isMounted = false;\n sub.remove();\n };\n }, []);\n\n return state;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useProgress.d.ts","sourceRoot":"","sources":["../../src/hooks/useProgress.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW;;;;EAgE1B"}
|