mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-05-23 22:37:41 +08:00
Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
21b6838263
@ -182,7 +182,7 @@ dependencies {
|
|||||||
implementation("com.facebook.react:flipper-integration")
|
implementation("com.facebook.react:flipper-integration")
|
||||||
// implementation "androidx.javascriptengine:javascriptengine:1.0.0-alpha07"
|
// implementation "androidx.javascriptengine:javascriptengine:1.0.0-alpha07"
|
||||||
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
||||||
implementation group: 'wang.harlon.quickjs', name: 'wrapper-android', version: '1.0.0'
|
implementation 'wang.harlon.quickjs:wrapper-android:2.4.0'
|
||||||
|
|
||||||
if (hermesEnabled.toBoolean()) {
|
if (hermesEnabled.toBoolean()) {
|
||||||
implementation("com.facebook.react:hermes-android")
|
implementation("com.facebook.react:hermes-android")
|
||||||
|
@ -30,6 +30,7 @@ public class Lyric extends LyricPlayer {
|
|||||||
boolean isShowRoma;
|
boolean isShowRoma;
|
||||||
boolean isShowLyricView = false;
|
boolean isShowLyricView = false;
|
||||||
boolean isSendLyricTextEvent = false;
|
boolean isSendLyricTextEvent = false;
|
||||||
|
boolean isScreenOff = false;
|
||||||
String lyricText = "";
|
String lyricText = "";
|
||||||
String translationText = "";
|
String translationText = "";
|
||||||
String romaLyricText = "";
|
String romaLyricText = "";
|
||||||
@ -102,22 +103,20 @@ public class Lyric extends LyricPlayer {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private void handleScreenOff() {
|
private boolean isDisableAutoPause() {
|
||||||
if (!isRunPlayer || !isShowLyricView) return;
|
return !isRunPlayer || isSendLyricTextEvent;
|
||||||
setTempPause(true);
|
|
||||||
|
|
||||||
if (lyricView != null) {
|
|
||||||
lyricView.runOnUiThread(() -> {
|
|
||||||
lyricView.destroyView();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
private void handleScreenOff() {
|
||||||
|
isScreenOff = true;
|
||||||
|
if (isDisableAutoPause()) return;
|
||||||
|
setTempPause(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleScreenOn() {
|
private void handleScreenOn() {
|
||||||
if (!isRunPlayer || !isShowLyricView) return;
|
isScreenOff = false;
|
||||||
|
if (isDisableAutoPause()) return;
|
||||||
if (lyricView == null) lyricView = new LyricView(reactAppContext, lyricEvent);
|
if (lyricView == null) lyricView = new LyricView(reactAppContext, lyricEvent);
|
||||||
lyricView.runOnUiThread(() -> {
|
lyricView.runOnUiThread(() -> {
|
||||||
lyricView.showLyricView();
|
|
||||||
handleGetCurrentLyric(lastLine);
|
handleGetCurrentLyric(lastLine);
|
||||||
setTempPause(false);
|
setTempPause(false);
|
||||||
});
|
});
|
||||||
@ -130,7 +129,7 @@ public class Lyric extends LyricPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setCurrentLyric(String lyric, ArrayList<String> extendedLyrics) {
|
private void setCurrentLyric(String lyric, ArrayList<String> extendedLyrics) {
|
||||||
if (isShowLyricView && lyricView != null) {
|
if (isShowLyricView && !isScreenOff && lyricView != null) {
|
||||||
lyricView.setLyric(lyric, extendedLyrics);
|
lyricView.setLyric(lyric, extendedLyrics);
|
||||||
}
|
}
|
||||||
if (isSendLyricTextEvent) {
|
if (isSendLyricTextEvent) {
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
buildToolsVersion = "34.0.0"
|
buildToolsVersion = "35.0.0"
|
||||||
minSdkVersion = 21
|
minSdkVersion = 21
|
||||||
compileSdkVersion = 34
|
compileSdkVersion = 35
|
||||||
targetSdkVersion = 29
|
targetSdkVersion = 29
|
||||||
|
|
||||||
ndkVersion = "25.1.8937393"
|
ndkVersion = "25.1.8937393"
|
||||||
|
9860
package-lock.json
generated
9860
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -45,15 +45,15 @@
|
|||||||
"homepage": "https://github.com/ikunshare/ikun-music-mobile#readme",
|
"homepage": "https://github.com/ikunshare/ikun-music-mobile#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@craftzdog/react-native-buffer": "^6.0.5",
|
"@craftzdog/react-native-buffer": "^6.0.5",
|
||||||
"@react-native-async-storage/async-storage": "^2.0.0",
|
"@react-native-async-storage/async-storage": "^2.1.0",
|
||||||
"@react-native-clipboard/clipboard": "^1.14.3",
|
"@react-native-clipboard/clipboard": "^1.15.0",
|
||||||
"@react-native-community/slider": "^4.5.5",
|
"@react-native-community/slider": "^4.5.5",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"lrc-file-parser": "^2.4.1",
|
"lrc-file-parser": "^2.4.1",
|
||||||
"message2call": "^0.1.3",
|
"message2call": "^0.1.3",
|
||||||
"pako": "^2.1.0",
|
"pako": "^2.1.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.73.9",
|
"react-native": "0.73.11",
|
||||||
"react-native-background-timer": "github:lyswhut/react-native-background-timer#55ecaa80880e9cec1fff81f3ce10e6250ab3c40c",
|
"react-native-background-timer": "github:lyswhut/react-native-background-timer#55ecaa80880e9cec1fff81f3ce10e6250ab3c40c",
|
||||||
"react-native-exception-handler": "^2.10.10",
|
"react-native-exception-handler": "^2.10.10",
|
||||||
"react-native-fast-image": "^8.6.3",
|
"react-native-fast-image": "^8.6.3",
|
||||||
@ -64,9 +64,8 @@
|
|||||||
"react-native-pager-view": "6.3.0",
|
"react-native-pager-view": "6.3.0",
|
||||||
"react-native-quick-base64": "^2.1.2",
|
"react-native-quick-base64": "^2.1.2",
|
||||||
"react-native-quick-md5": "^3.0.6",
|
"react-native-quick-md5": "^3.0.6",
|
||||||
"react-native-track-player": "github:lyswhut/react-native-track-player#930681ab40fdb50f3d0eedff6ecd29b1666fd3ff",
|
"rn-fetch-blob": "^0.12.0",
|
||||||
"react-native-vector-icons": "^10.2.0",
|
"react-native-track-player": "github:lyswhut/react-native-track-player#01873f81e30de85ab96363ad7351cf4bdcd39e37"
|
||||||
"rn-fetch-blob": "^0.12.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.26.0",
|
"@babel/core": "^7.26.0",
|
||||||
@ -88,6 +87,6 @@
|
|||||||
"eslint-config-standard-with-typescript": "^43.0.1",
|
"eslint-config-standard-with-typescript": "^43.0.1",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
|
为了防止歌曲缓存被第三方软件当做垃圾意外清理,歌曲缓存地址不再存储到缓存目录,若想清理缓存,需去 设置-其他-资源缓存管理 清理。
|
||||||
|
|
||||||
|
更新到该版本首次播放歌曲时,会将之前的歌曲缓存迁移到新位置,需要等待的时间取决于你已缓存资源的大小。
|
||||||
|
|
||||||
### 新增
|
### 新增
|
||||||
|
|
||||||
- 新增蓝牙歌词支持,可以去 设置-播放设置-显示蓝牙歌词 启用(#615)
|
- 新增蓝牙歌词支持,可以去 设置-播放设置-显示蓝牙歌词 启用(#615)
|
||||||
|
|
||||||
### 优化
|
### 优化
|
||||||
|
|
||||||
|
- 防止歌曲缓存被第三方软件当做垃圾意外清理
|
||||||
|
- 优化正常播放结束时的下一首歌曲播放衔接度,在歌曲即将播放结束时将预获取下一首歌曲的播放链接,减少自动切歌时的等待时间
|
||||||
|
- 优化歌曲换源机制,提升换源正确率
|
||||||
- 首次使用的提示窗口可以点击背景或者返回键关闭(#577)
|
- 首次使用的提示窗口可以点击背景或者返回键关闭(#577)
|
||||||
- 上移 Toast 位置避免遮挡播放模式图标(#603 @sibojia)
|
- 上移 Toast 位置避免遮挡播放模式图标(#603 @sibojia)
|
||||||
|
|
||||||
### 变更
|
### 变更
|
||||||
|
|
||||||
- 不再缓存换源歌曲信息
|
- 歌曲缓存地址不再存储到缓存目录
|
||||||
|
- 不再长期缓存换源歌曲信息
|
||||||
|
|
||||||
### 其他
|
### 其他
|
||||||
|
|
||||||
react-native → 0.73.10
|
react-native → 0.73.11
|
||||||
|
@ -4,6 +4,7 @@ import initPlayStatus from './playStatus'
|
|||||||
import initPlayerEvent from './playerEvent'
|
import initPlayerEvent from './playerEvent'
|
||||||
import initWatchList from './watchList'
|
import initWatchList from './watchList'
|
||||||
import initPlayProgress from './playProgress'
|
import initPlayProgress from './playProgress'
|
||||||
|
import initPreloadNextMusic from './preloadNextMusic'
|
||||||
import initLyric from './lyric'
|
import initLyric from './lyric'
|
||||||
|
|
||||||
export default async(setting: LX.AppSetting) => {
|
export default async(setting: LX.AppSetting) => {
|
||||||
@ -14,4 +15,5 @@ export default async(setting: LX.AppSetting) => {
|
|||||||
initPlayerEvent()
|
initPlayerEvent()
|
||||||
initWatchList()
|
initWatchList()
|
||||||
initPlayProgress()
|
initPlayProgress()
|
||||||
|
initPreloadNextMusic()
|
||||||
}
|
}
|
||||||
|
67
src/core/init/player/preloadNextMusic.ts
Normal file
67
src/core/init/player/preloadNextMusic.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { getMusicUrl } from '@/core/music'
|
||||||
|
import { getNextPlayMusicInfo, resetRandomNextMusicInfo } from '@/core/player/player'
|
||||||
|
import { checkUrl } from '@/utils/request'
|
||||||
|
import playerState from '@/store/player/state'
|
||||||
|
import { isCached } from '@/plugins/player/utils'
|
||||||
|
|
||||||
|
|
||||||
|
const preloadMusicInfo = {
|
||||||
|
isLoading: false,
|
||||||
|
preProgress: 0,
|
||||||
|
info: null as LX.Player.PlayMusicInfo | null,
|
||||||
|
}
|
||||||
|
const resetPreloadInfo = () => {
|
||||||
|
preloadMusicInfo.preProgress = 0
|
||||||
|
preloadMusicInfo.info = null
|
||||||
|
preloadMusicInfo.isLoading = false
|
||||||
|
}
|
||||||
|
const preloadNextMusicUrl = async(curTime: number) => {
|
||||||
|
if (preloadMusicInfo.isLoading || curTime - preloadMusicInfo.preProgress < 3) return
|
||||||
|
preloadMusicInfo.isLoading = true
|
||||||
|
console.log('preload next music url')
|
||||||
|
const info = await getNextPlayMusicInfo()
|
||||||
|
if (info) {
|
||||||
|
preloadMusicInfo.info = info
|
||||||
|
const url = await getMusicUrl({ musicInfo: info.musicInfo }).catch(() => '')
|
||||||
|
if (url) {
|
||||||
|
console.log('preload url', url)
|
||||||
|
const [cached, available] = await Promise.all([isCached(url), checkUrl(url).then(() => true).catch(() => false)])
|
||||||
|
if (!cached && !available) {
|
||||||
|
const url = await getMusicUrl({ musicInfo: info.musicInfo, isRefresh: true }).catch(() => '')
|
||||||
|
console.log('preload url refresh', url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preloadMusicInfo.isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const setProgress = (time: number) => {
|
||||||
|
if (!playerState.musicInfo.id) return
|
||||||
|
preloadMusicInfo.preProgress = time
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetPlayInfo = () => {
|
||||||
|
resetPreloadInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfigUpdated: typeof global.state_event.configUpdated = (keys, settings) => {
|
||||||
|
if (!keys.includes('player.togglePlayMethod')) return
|
||||||
|
if (!preloadMusicInfo.info || preloadMusicInfo.info.isTempPlay) return
|
||||||
|
resetRandomNextMusicInfo()
|
||||||
|
preloadMusicInfo.info = null
|
||||||
|
preloadMusicInfo.preProgress = playerState.progress.nowPlayTime
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePlayProgressChanged: typeof global.state_event.playProgressChanged = (progress) => {
|
||||||
|
const duration = progress.maxPlayTime
|
||||||
|
if (duration > 10 && duration - progress.nowPlayTime < 10 && !preloadMusicInfo.info) {
|
||||||
|
void preloadNextMusicUrl(progress.nowPlayTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global.app_event.on('setProgress', setProgress)
|
||||||
|
global.app_event.on('musicToggled', handleSetPlayInfo)
|
||||||
|
global.state_event.on('configUpdated', handleConfigUpdated)
|
||||||
|
global.state_event.on('playProgressChanged', handlePlayProgressChanged)
|
||||||
|
}
|
@ -71,7 +71,7 @@ const blobToBuffer = (blob) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchData = (url, { timeout = 15000, ...options }) => {
|
export const fetchData = (url, { timeout = 13_000, ...options }) => {
|
||||||
// console.log('---start---', url)
|
// console.log('---start---', url)
|
||||||
|
|
||||||
const controller = new global.AbortController()
|
const controller = new global.AbortController()
|
||||||
|
@ -15,12 +15,14 @@ import { apis } from '@/utils/musicSdk/api-source'
|
|||||||
|
|
||||||
const getOtherSourcePromises = new Map()
|
const getOtherSourcePromises = new Map()
|
||||||
export const existTimeExp = /\[\d{1,2}:.*\d{1,4}\]/
|
export const existTimeExp = /\[\d{1,2}:.*\d{1,4}\]/
|
||||||
|
const otherSourceCache = new Map<LX.Music.MusicInfo | LX.Download.ListItem, LX.Music.MusicInfoOnline[]>()
|
||||||
|
|
||||||
export const getOtherSource = async(musicInfo: LX.Music.MusicInfo | LX.Download.ListItem, isRefresh = false): Promise<LX.Music.MusicInfoOnline[]> => {
|
export const getOtherSource = async(musicInfo: LX.Music.MusicInfo | LX.Download.ListItem, isRefresh = false): Promise<LX.Music.MusicInfoOnline[]> => {
|
||||||
// if (!isRefresh) {
|
// if (!isRefresh) {
|
||||||
// const cachedInfo = await getOtherSourceFromStore(musicInfo.id)
|
// const cachedInfo = await getOtherSourceFromStore(musicInfo.id)
|
||||||
// if (cachedInfo.length) return cachedInfo
|
// if (cachedInfo.length) return cachedInfo
|
||||||
// }
|
// }
|
||||||
|
if (otherSourceCache.has(musicInfo)) return otherSourceCache.get(musicInfo)!
|
||||||
let key: string
|
let key: string
|
||||||
let searchMusicInfo: {
|
let searchMusicInfo: {
|
||||||
name: string
|
name: string
|
||||||
@ -54,9 +56,12 @@ export const getOtherSource = async(musicInfo: LX.Music.MusicInfo | LX.Download.
|
|||||||
let timeout: null | number = BackgroundTimer.setTimeout(() => {
|
let timeout: null | number = BackgroundTimer.setTimeout(() => {
|
||||||
timeout = null
|
timeout = null
|
||||||
reject(new Error('find music timeout'))
|
reject(new Error('find music timeout'))
|
||||||
}, 15_000)
|
}, 12_000)
|
||||||
findMusic(searchMusicInfo).then((otherSource) => {
|
findMusic(searchMusicInfo).then((otherSource) => {
|
||||||
resolve(otherSource.map(toNewMusicInfo) as LX.Music.MusicInfoOnline[])
|
if (otherSourceCache.size > 10) otherSourceCache.clear()
|
||||||
|
const source = otherSource.map(toNewMusicInfo) as LX.Music.MusicInfoOnline[]
|
||||||
|
otherSourceCache.set(musicInfo, source)
|
||||||
|
resolve(source)
|
||||||
}).catch(reject).finally(() => {
|
}).catch(reject).finally(() => {
|
||||||
if (timeout) BackgroundTimer.clearTimeout(timeout)
|
if (timeout) BackgroundTimer.clearTimeout(timeout)
|
||||||
})
|
})
|
||||||
|
@ -238,6 +238,7 @@ const handlePlay = async() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
global.lx.isPlayedStop &&= false
|
global.lx.isPlayedStop &&= false
|
||||||
|
resetRandomNextMusicInfo()
|
||||||
|
|
||||||
if (global.lx.restorePlayInfo) {
|
if (global.lx.restorePlayInfo) {
|
||||||
void handleRestorePlay(global.lx.restorePlayInfo)
|
void handleRestorePlay(global.lx.restorePlayInfo)
|
||||||
@ -284,6 +285,108 @@ const handleToggleStop = async() => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const randomNextMusicInfo = {
|
||||||
|
info: null as LX.Player.PlayMusicInfo | null,
|
||||||
|
index: -1,
|
||||||
|
}
|
||||||
|
export const resetRandomNextMusicInfo = () => {
|
||||||
|
if (randomNextMusicInfo.info) {
|
||||||
|
randomNextMusicInfo.info = null
|
||||||
|
randomNextMusicInfo.index = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getNextPlayMusicInfo = async(): Promise<LX.Player.PlayMusicInfo | null> => {
|
||||||
|
if (playerState.tempPlayList.length) { // 如果稍后播放列表存在歌曲则直接播放改列表的歌曲
|
||||||
|
const playMusicInfo = playerState.tempPlayList[0]
|
||||||
|
return playMusicInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerState.playMusicInfo.musicInfo == null) return null
|
||||||
|
|
||||||
|
if (randomNextMusicInfo.info) return randomNextMusicInfo.info
|
||||||
|
|
||||||
|
const playMusicInfo = playerState.playMusicInfo
|
||||||
|
const playInfo = playerState.playInfo
|
||||||
|
// console.log(playInfo.playerListId)
|
||||||
|
const currentListId = playInfo.playerListId
|
||||||
|
if (!currentListId) return null
|
||||||
|
const currentList = getList(currentListId)
|
||||||
|
|
||||||
|
const playedList = playerState.playedList
|
||||||
|
if (playedList.length) { // 移除已播放列表内不存在原列表的歌曲
|
||||||
|
let currentId: string
|
||||||
|
if (playMusicInfo.isTempPlay) {
|
||||||
|
const musicInfo = currentList[playInfo.playerPlayIndex]
|
||||||
|
if (musicInfo) currentId = musicInfo.id
|
||||||
|
} else {
|
||||||
|
currentId = playMusicInfo.musicInfo!.id
|
||||||
|
}
|
||||||
|
// 从已播放列表移除播放列表已删除的歌曲
|
||||||
|
let index
|
||||||
|
for (index = playedList.findIndex(m => m.musicInfo.id === currentId) + 1; index < playedList.length; index++) {
|
||||||
|
const playMusicInfo = playedList[index]
|
||||||
|
const currentId = playMusicInfo.musicInfo.id
|
||||||
|
if (playMusicInfo.listId == currentListId && !currentList.some(m => m.id === currentId)) {
|
||||||
|
removePlayedList(index)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < playedList.length) return playedList[index]
|
||||||
|
}
|
||||||
|
// const isCheckFile = findNum > 2 // 针对下载列表,如果超过两次都碰到无效歌曲,则过滤整个列表内的无效歌曲
|
||||||
|
let { filteredList, playerIndex } = await filterList({ // 过滤已播放歌曲
|
||||||
|
listId: currentListId,
|
||||||
|
list: currentList,
|
||||||
|
playedList,
|
||||||
|
playerMusicInfo: currentList[playInfo.playerPlayIndex],
|
||||||
|
isNext: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!filteredList.length) return null
|
||||||
|
// let currentIndex: number = filteredList.indexOf(currentList[playInfo.playerPlayIndex])
|
||||||
|
if (playerIndex == -1 && filteredList.length) playerIndex = 0
|
||||||
|
let nextIndex = playerIndex
|
||||||
|
|
||||||
|
let togglePlayMethod = settingState.setting['player.togglePlayMethod']
|
||||||
|
switch (togglePlayMethod) {
|
||||||
|
case 'listLoop':
|
||||||
|
nextIndex = playerIndex === filteredList.length - 1 ? 0 : playerIndex + 1
|
||||||
|
break
|
||||||
|
case 'random':
|
||||||
|
nextIndex = getRandom(0, filteredList.length)
|
||||||
|
break
|
||||||
|
case 'list':
|
||||||
|
nextIndex = playerIndex === filteredList.length - 1 ? -1 : playerIndex + 1
|
||||||
|
break
|
||||||
|
case 'singleLoop':
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (nextIndex < 0) return null
|
||||||
|
|
||||||
|
const nextPlayMusicInfo = {
|
||||||
|
musicInfo: filteredList[nextIndex],
|
||||||
|
listId: currentListId,
|
||||||
|
isTempPlay: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (togglePlayMethod == 'random') {
|
||||||
|
randomNextMusicInfo.info = nextPlayMusicInfo
|
||||||
|
randomNextMusicInfo.index = nextIndex
|
||||||
|
}
|
||||||
|
return nextPlayMusicInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePlayNext = async(playMusicInfo: LX.Player.PlayMusicInfo) => {
|
||||||
|
await pause()
|
||||||
|
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
||||||
|
await handlePlay()
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 下一曲
|
* 下一曲
|
||||||
* @param isAutoToggle 是否自动切换
|
* @param isAutoToggle 是否自动切换
|
||||||
@ -293,9 +396,7 @@ export const playNext = async(isAutoToggle = false): Promise<void> => {
|
|||||||
if (playerState.tempPlayList.length) { // 如果稍后播放列表存在歌曲则直接播放改列表的歌曲
|
if (playerState.tempPlayList.length) { // 如果稍后播放列表存在歌曲则直接播放改列表的歌曲
|
||||||
const playMusicInfo = playerState.tempPlayList[0]
|
const playMusicInfo = playerState.tempPlayList[0]
|
||||||
removeTempPlayList(0)
|
removeTempPlayList(0)
|
||||||
await pause()
|
await handlePlayNext(playMusicInfo)
|
||||||
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
|
||||||
await handlePlay()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,13 +432,14 @@ export const playNext = async(isAutoToggle = false): Promise<void> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (index < playedList.length) {
|
if (index < playedList.length) {
|
||||||
const playMusicInfo = playedList[index]
|
await handlePlayNext(playedList[index])
|
||||||
await pause()
|
|
||||||
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
|
||||||
await handlePlay()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (randomNextMusicInfo.info) {
|
||||||
|
await handlePlayNext(randomNextMusicInfo.info)
|
||||||
|
return
|
||||||
|
}
|
||||||
// const isCheckFile = findNum > 2 // 针对下载列表,如果超过两次都碰到无效歌曲,则过滤整个列表内的无效歌曲
|
// const isCheckFile = findNum > 2 // 针对下载列表,如果超过两次都碰到无效歌曲,则过滤整个列表内的无效歌曲
|
||||||
let { filteredList, playerIndex } = await filterList({ // 过滤已播放歌曲
|
let { filteredList, playerIndex } = await filterList({ // 过滤已播放歌曲
|
||||||
listId: currentListId,
|
listId: currentListId,
|
||||||
@ -379,15 +481,11 @@ export const playNext = async(isAutoToggle = false): Promise<void> => {
|
|||||||
}
|
}
|
||||||
if (nextIndex < 0) return
|
if (nextIndex < 0) return
|
||||||
|
|
||||||
const nextPlayMusicInfo = {
|
await handlePlayNext({
|
||||||
musicInfo: filteredList[nextIndex],
|
musicInfo: filteredList[nextIndex],
|
||||||
listId: currentListId,
|
listId: currentListId,
|
||||||
isTempPlay: false,
|
isTempPlay: false,
|
||||||
}
|
})
|
||||||
|
|
||||||
await pause()
|
|
||||||
setPlayMusicInfo(nextPlayMusicInfo.listId, nextPlayMusicInfo.musicInfo)
|
|
||||||
await handlePlay()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -424,10 +522,7 @@ export const playPrev = async(isAutoToggle = false): Promise<void> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
const playMusicInfo = playedList[index]
|
await handlePlayNext(playedList[index])
|
||||||
await pause()
|
|
||||||
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
|
||||||
await handlePlay()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,15 +567,12 @@ export const playPrev = async(isAutoToggle = false): Promise<void> => {
|
|||||||
if (nextIndex < 0) return
|
if (nextIndex < 0) return
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextPlayMusicInfo = {
|
|
||||||
|
await handlePlayNext({
|
||||||
musicInfo: filteredList[nextIndex],
|
musicInfo: filteredList[nextIndex],
|
||||||
listId: currentListId,
|
listId: currentListId,
|
||||||
isTempPlay: false,
|
isTempPlay: false,
|
||||||
}
|
})
|
||||||
|
|
||||||
await pause()
|
|
||||||
setPlayMusicInfo(nextPlayMusicInfo.listId, nextPlayMusicInfo.musicInfo)
|
|
||||||
await handlePlay()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,6 +202,7 @@
|
|||||||
"player__geting_url_delay_retry": "The server is busy, try again in {time} seconds...",
|
"player__geting_url_delay_retry": "The server is busy, try again in {time} seconds...",
|
||||||
"player__loading": "Music loading...",
|
"player__loading": "Music loading...",
|
||||||
"player__refresh_url": "The URL has expired, refreshing the URL...",
|
"player__refresh_url": "The URL has expired, refreshing the URL...",
|
||||||
|
"player_cache_migrating": "Song cache is being migrated, please wait ⌛️",
|
||||||
"quality_high_quality": "HQ",
|
"quality_high_quality": "HQ",
|
||||||
"quality_lossless": "SQ",
|
"quality_lossless": "SQ",
|
||||||
"quality_lossless_24bit": "Hires",
|
"quality_lossless_24bit": "Hires",
|
||||||
|
@ -202,6 +202,7 @@
|
|||||||
"player__geting_url_delay_retry": "服务器繁忙,{time}秒后重试...",
|
"player__geting_url_delay_retry": "服务器繁忙,{time}秒后重试...",
|
||||||
"player__loading": "音乐加载中...",
|
"player__loading": "音乐加载中...",
|
||||||
"player__refresh_url": "URL过期,正在刷新URL...",
|
"player__refresh_url": "URL过期,正在刷新URL...",
|
||||||
|
"player_cache_migrating": "歌曲缓存迁移中,请稍等 ⌛️",
|
||||||
"quality_high_quality": "HQ",
|
"quality_high_quality": "HQ",
|
||||||
"quality_lossless": "SQ",
|
"quality_lossless": "SQ",
|
||||||
"quality_lossless_24bit": "Hires",
|
"quality_lossless_24bit": "Hires",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import TrackPlayer from 'react-native-track-player'
|
import TrackPlayer from 'react-native-track-player'
|
||||||
import { updateOptions, setVolume, setPlaybackRate } from './utils'
|
import { updateOptions, setVolume, setPlaybackRate, migratePlayerCache } from './utils'
|
||||||
|
|
||||||
// const listenEvent = () => {
|
// const listenEvent = () => {
|
||||||
// TrackPlayer.addEventListener('playback-error', err => {
|
// TrackPlayer.addEventListener('playback-error', err => {
|
||||||
@ -26,6 +26,7 @@ const initial = async({ volume, playRate, cacheSize, isHandleAudioFocus, isEnabl
|
|||||||
if (global.lx.playerStatus.isIniting || global.lx.playerStatus.isInitialized) return
|
if (global.lx.playerStatus.isIniting || global.lx.playerStatus.isInitialized) return
|
||||||
global.lx.playerStatus.isIniting = true
|
global.lx.playerStatus.isIniting = true
|
||||||
console.log('Cache Size', cacheSize * 1024)
|
console.log('Cache Size', cacheSize * 1024)
|
||||||
|
await migratePlayerCache()
|
||||||
await TrackPlayer.setupPlayer({
|
await TrackPlayer.setupPlayer({
|
||||||
maxCacheSize: cacheSize * 1024,
|
maxCacheSize: cacheSize * 1024,
|
||||||
maxBuffer: 1000,
|
maxBuffer: 1000,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import TrackPlayer, { Capability, Event, RepeatMode, State } from 'react-native-track-player'
|
import TrackPlayer, { Capability, Event, RepeatMode, State } from 'react-native-track-player'
|
||||||
import BackgroundTimer from 'react-native-background-timer'
|
import BackgroundTimer from 'react-native-background-timer'
|
||||||
import { playMusic as handlePlayMusic } from './playList'
|
import { playMusic as handlePlayMusic } from './playList'
|
||||||
|
import { existsFile, moveFile, privateStorageDirectoryPath, temporaryDirectoryPath } from '@/utils/fs'
|
||||||
|
import { toast } from '@/utils/tools'
|
||||||
// import { PlayerMusicInfo } from '@/store/modules/player/playInfo'
|
// import { PlayerMusicInfo } from '@/store/modules/player/playInfo'
|
||||||
|
|
||||||
|
|
||||||
@ -173,6 +175,23 @@ export const updateNowPlayingTitles = async(duration: number, title: string, art
|
|||||||
|
|
||||||
export const resetPlay = async() => Promise.all([setPause(), setCurrentTime(0)])
|
export const resetPlay = async() => Promise.all([setPause(), setCurrentTime(0)])
|
||||||
|
|
||||||
|
export const isCached = async(url: string) => TrackPlayer.isCached(url)
|
||||||
|
export const getCacheSize = async() => TrackPlayer.getCacheSize()
|
||||||
|
export const clearCache = async() => TrackPlayer.clearCache()
|
||||||
|
export const migratePlayerCache = async() => {
|
||||||
|
const newCachePath = privateStorageDirectoryPath + '/TrackPlayer'
|
||||||
|
if (await existsFile(newCachePath)) return
|
||||||
|
const oldCachePath = temporaryDirectoryPath + '/TrackPlayer'
|
||||||
|
if (!await existsFile(oldCachePath)) return
|
||||||
|
let timeout: number | null = BackgroundTimer.setTimeout(() => {
|
||||||
|
timeout = null
|
||||||
|
toast(global.i18n.t('player_cache_migrating'), 'long')
|
||||||
|
}, 2_000)
|
||||||
|
await moveFile(oldCachePath, newCachePath).finally(() => {
|
||||||
|
if (timeout) BackgroundTimer.clearTimeout(timeout)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const destroy = async() => {
|
export const destroy = async() => {
|
||||||
if (global.lx.playerStatus.isIniting || !global.lx.playerStatus.isInitialized) return
|
if (global.lx.playerStatus.isIniting || !global.lx.playerStatus.isInitialized) return
|
||||||
await TrackPlayer.destroy()
|
await TrackPlayer.destroy()
|
||||||
|
@ -19,6 +19,9 @@ export default memo(() => {
|
|||||||
const openHomePage = () => {
|
const openHomePage = () => {
|
||||||
void openUrl('https://github.com/ikunshare/ikun-music-mobile#readme')
|
void openUrl('https://github.com/ikunshare/ikun-music-mobile#readme')
|
||||||
}
|
}
|
||||||
|
const openIssuePage = () => {
|
||||||
|
void openUrl('https://github.com/lyswhut/lx-music-mobile/issues')
|
||||||
|
}
|
||||||
const openNetdiskPage = () => {
|
const openNetdiskPage = () => {
|
||||||
void openUrl('https://www.lanzoui.com/s/LXMusic')
|
void openUrl('https://www.lanzoui.com/s/LXMusic')
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import SubTitle from '../../components/SubTitle'
|
|||||||
import Button from '../../components/Button'
|
import Button from '../../components/Button'
|
||||||
import { toast, resetNotificationPermissionCheck, confirmDialog, resetIgnoringBatteryOptimizationCheck } from '@/utils/tools'
|
import { toast, resetNotificationPermissionCheck, confirmDialog, resetIgnoringBatteryOptimizationCheck } from '@/utils/tools'
|
||||||
import { getAppCacheSize, clearAppCache } from '@/utils/nativeModules/cache'
|
import { getAppCacheSize, clearAppCache } from '@/utils/nativeModules/cache'
|
||||||
|
import { getCacheSize, clearCache } from '@/plugins/player/utils'
|
||||||
import { sizeFormate } from '@/utils'
|
import { sizeFormate } from '@/utils'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
@ -21,8 +22,9 @@ export default memo(() => {
|
|||||||
// const clearCache = useDispatch('list', 'clearCache')
|
// const clearCache = useDispatch('list', 'clearCache')
|
||||||
|
|
||||||
const handleGetAppCacheSize = () => {
|
const handleGetAppCacheSize = () => {
|
||||||
void getAppCacheSize().then(size => {
|
void Promise.all([getAppCacheSize(), getCacheSize()]).then(([size, size2]) => {
|
||||||
setCacheSize(sizeFormate(size))
|
const count = size + size2
|
||||||
|
setCacheSize(sizeFormate(count as number))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ export default memo(() => {
|
|||||||
setCleaning(true)
|
setCleaning(true)
|
||||||
void Promise.all([
|
void Promise.all([
|
||||||
clearAppCache(),
|
clearAppCache(),
|
||||||
|
clearCache(),
|
||||||
clearMusicUrl(),
|
clearMusicUrl(),
|
||||||
resetNotificationPermissionCheck(),
|
resetNotificationPermissionCheck(),
|
||||||
resetIgnoringBatteryOptimizationCheck(),
|
resetIgnoringBatteryOptimizationCheck(),
|
||||||
|
@ -43,7 +43,7 @@ export const readFile = async(path: string, encoding?: Encoding) => FileSystem.r
|
|||||||
|
|
||||||
// export const copyFile = async(fromPath: string, toPath: string) => FileSystem.cp(fromPath, toPath)
|
// export const copyFile = async(fromPath: string, toPath: string) => FileSystem.cp(fromPath, toPath)
|
||||||
|
|
||||||
// export const moveFile = async(fromPath: string, toPath: string) => FileSystem.mv(fromPath, toPath)
|
export const moveFile = async(fromPath: string, toPath: string) => FileSystem.mv(fromPath, toPath)
|
||||||
export const gzipFile = async(fromPath: string, toPath: string) => FileSystem.gzipFile(fromPath, toPath)
|
export const gzipFile = async(fromPath: string, toPath: string) => FileSystem.gzipFile(fromPath, toPath)
|
||||||
export const unGzipFile = async(fromPath: string, toPath: string) => FileSystem.unGzipFile(fromPath, toPath)
|
export const unGzipFile = async(fromPath: string, toPath: string) => FileSystem.unGzipFile(fromPath, toPath)
|
||||||
export const gzipString = async(data: string, encoding?: Encoding) => FileSystem.gzipString(data, encoding)
|
export const gzipString = async(data: string, encoding?: Encoding) => FileSystem.gzipString(data, encoding)
|
||||||
|
@ -30,6 +30,14 @@ export const toNewMusicInfo = (oldMusicInfo: any): LX.Music.MusicInfo => {
|
|||||||
albumName: oldMusicInfo.albumName, // 歌曲专辑名称
|
albumName: oldMusicInfo.albumName, // 歌曲专辑名称
|
||||||
picUrl: oldMusicInfo.img, // 歌曲图片链接
|
picUrl: oldMusicInfo.img, // 歌曲图片链接
|
||||||
}
|
}
|
||||||
|
const newInfo = {
|
||||||
|
id: `${oldMusicInfo.source as string}_${oldMusicInfo.songmid as string}`,
|
||||||
|
name: oldMusicInfo.name,
|
||||||
|
singer: oldMusicInfo.singer,
|
||||||
|
source: oldMusicInfo.source,
|
||||||
|
interval: oldMusicInfo.interval,
|
||||||
|
meta: meta as LX.Music.MusicInfoOnline['meta'],
|
||||||
|
}
|
||||||
|
|
||||||
if (oldMusicInfo.source == 'local') {
|
if (oldMusicInfo.source == 'local') {
|
||||||
meta.filePath = oldMusicInfo.filePath ?? oldMusicInfo.songmid ?? ''
|
meta.filePath = oldMusicInfo.filePath ?? oldMusicInfo.songmid ?? ''
|
||||||
@ -51,6 +59,7 @@ export const toNewMusicInfo = (oldMusicInfo: any): LX.Music.MusicInfo => {
|
|||||||
switch (oldMusicInfo.source) {
|
switch (oldMusicInfo.source) {
|
||||||
case 'kg':
|
case 'kg':
|
||||||
meta.hash = oldMusicInfo.hash
|
meta.hash = oldMusicInfo.hash
|
||||||
|
newInfo.id = oldMusicInfo.songmid + '_' + oldMusicInfo.hash
|
||||||
break
|
break
|
||||||
case 'tx':
|
case 'tx':
|
||||||
meta.strMediaMid = oldMusicInfo.strMediaMid
|
meta.strMediaMid = oldMusicInfo.strMediaMid
|
||||||
@ -66,14 +75,7 @@ export const toNewMusicInfo = (oldMusicInfo: any): LX.Music.MusicInfo => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return newInfo
|
||||||
id: `${oldMusicInfo.source as string}_${oldMusicInfo.songmid as string}`,
|
|
||||||
name: oldMusicInfo.name,
|
|
||||||
singer: oldMusicInfo.singer,
|
|
||||||
source: oldMusicInfo.source,
|
|
||||||
interval: oldMusicInfo.interval,
|
|
||||||
meta: meta as LX.Music.MusicInfoOnline['meta'],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const toOldMusicInfo = (minfo: LX.Music.MusicInfo): any => {
|
export const toOldMusicInfo = (minfo: LX.Music.MusicInfo): any => {
|
||||||
|
@ -70,15 +70,16 @@ export const findMusic = async(musicInfo) => {
|
|||||||
const singersRxp = /、|&|;|;|\/|,|,|\|/
|
const singersRxp = /、|&|;|;|\/|,|,|\|/
|
||||||
const sortSingle = singer => singersRxp.test(singer)
|
const sortSingle = singer => singersRxp.test(singer)
|
||||||
? singer.split(singersRxp).sort((a, b) => a.localeCompare(b)).join('、')
|
? singer.split(singersRxp).sort((a, b) => a.localeCompare(b)).join('、')
|
||||||
: singer
|
: (singer || '')
|
||||||
const sortMusic = (arr, callback) => {
|
const sortMusic = (arr, callback) => {
|
||||||
const tempResult = []
|
const tempResult = []
|
||||||
for (let i = arr.length - 1; i > -1; i--) {
|
for (let i = arr.length - 1; i > -1; i--) {
|
||||||
const item = arr[i]
|
const item = arr[i]
|
||||||
if (callback(item)) {
|
if (callback(item)) {
|
||||||
delete item.sortedSinger
|
delete item.fSinger
|
||||||
delete item.lowerCaseName
|
delete item.fMusicName
|
||||||
delete item.lowerCaseAlbumName
|
delete item.fAlbumName
|
||||||
|
delete item.fInterval
|
||||||
tempResult.push(item)
|
tempResult.push(item)
|
||||||
arr.splice(i, 1)
|
arr.splice(i, 1)
|
||||||
}
|
}
|
||||||
@ -86,55 +87,68 @@ export const findMusic = async(musicInfo) => {
|
|||||||
tempResult.reverse()
|
tempResult.reverse()
|
||||||
return tempResult
|
return tempResult
|
||||||
}
|
}
|
||||||
const trimStr = str => typeof str == 'string' ? str.trim() : str
|
const getIntv = (interval) => {
|
||||||
const filterStr = str => typeof str == 'string' ? str.replace(/\s|'|\.|,|,|&|"|、|\(|\)|(|)|`|~|-|<|>|\||\/|\]|\[/g, '') : str
|
if (!interval) return 0
|
||||||
const musicName = trimStr(name)
|
// if (musicInfo._interval) return musicInfo._interval
|
||||||
const sortedSinger = filterStr(String(sortSingle(singer)).toLowerCase())
|
let intvArr = interval.split(':')
|
||||||
const lowerCaseName = filterStr(String(musicName).toLowerCase())
|
let intv = 0
|
||||||
const lowerCaseAlbumName = filterStr(String(albumName).toLowerCase())
|
let unit = 1
|
||||||
|
while (intvArr.length) {
|
||||||
|
intv += parseInt(intvArr.pop()) * unit
|
||||||
|
unit *= 60
|
||||||
|
}
|
||||||
|
return intv
|
||||||
|
}
|
||||||
|
const trimStr = str => typeof str == 'string' ? str.trim() : (str || '')
|
||||||
|
const filterStr = str => typeof str == 'string' ? str.replace(/\s|'|\.|,|,|&|"|、|\(|\)|(|)|`|~|-|<|>|\||\/|\]|\[|!|!/g, '') : String(str || '')
|
||||||
|
const fMusicName = filterStr(name).toLowerCase()
|
||||||
|
const fSinger = filterStr(sortSingle(singer)).toLowerCase()
|
||||||
|
const fAlbumName = filterStr(albumName).toLowerCase()
|
||||||
|
const fInterval = getIntv(interval)
|
||||||
|
const isEqualsInterval = (intv) => Math.abs((fInterval || intv) - (intv || fInterval)) < 5
|
||||||
|
const isIncludesName = (name) => (fMusicName.includes(name) || name.includes(fMusicName))
|
||||||
|
const isIncludesSinger = (singer) => fSinger ? (fSinger.includes(singer) || singer.includes(fSinger)) : true
|
||||||
|
const isEqualsAlbum = (album) => fAlbumName ? fAlbumName == album : true
|
||||||
|
|
||||||
const result = lists.map(source => {
|
const result = lists.map(source => {
|
||||||
for (const item of source.list) {
|
for (const item of source.list) {
|
||||||
item.name = trimStr(item.name)
|
item.name = trimStr(item.name)
|
||||||
item.sortedSinger = filterStr(String(sortSingle(item.singer)).toLowerCase())
|
item.singer = trimStr(item.singer)
|
||||||
item.lowerCaseName = filterStr(String(item.name ?? '').toLowerCase())
|
item.fSinger = filterStr(sortSingle(item.singer).toLowerCase())
|
||||||
item.lowerCaseAlbumName = filterStr(String(item.albumName ?? '').toLowerCase())
|
item.fMusicName = filterStr(String(item.name ?? '').toLowerCase())
|
||||||
// console.log(lowerCaseName, item.lowerCaseName, item.source)
|
item.fAlbumName = filterStr(String(item.albumName ?? '').toLowerCase())
|
||||||
if (
|
item.fInterval = getIntv(item.interval)
|
||||||
(
|
// console.log(fMusicName, item.fMusicName, item.source)
|
||||||
item.sortedSinger == sortedSinger && item.lowerCaseName == lowerCaseName
|
if (!isEqualsInterval(item.fInterval)) {
|
||||||
) ||
|
item.name = null
|
||||||
(
|
continue
|
||||||
(interval ? item.interval == interval : true) && item.lowerCaseName == lowerCaseName &&
|
|
||||||
(item.sortedSinger.includes(sortedSinger) || sortedSinger.includes(item.sortedSinger))
|
|
||||||
) ||
|
|
||||||
(
|
|
||||||
item.lowerCaseName == lowerCaseName && (lowerCaseAlbumName ? item.lowerCaseAlbumName == lowerCaseAlbumName : true) &&
|
|
||||||
(interval ? item.interval == interval : true)
|
|
||||||
) ||
|
|
||||||
(
|
|
||||||
item.lowerCaseName == lowerCaseName && (lowerCaseAlbumName ? item.lowerCaseAlbumName == lowerCaseAlbumName : true) &&
|
|
||||||
(item.sortedSinger.includes(sortedSinger) || sortedSinger.includes(item.sortedSinger))
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return item
|
|
||||||
}
|
}
|
||||||
if (!singer) {
|
if (item.fMusicName == fMusicName && isIncludesSinger(item.fSinger)) return item
|
||||||
if (item.lowerCaseName == lowerCaseName && (interval ? item.interval == interval : true)) return item
|
|
||||||
}
|
}
|
||||||
|
for (const item of source.list) {
|
||||||
|
if (item.name == null) continue
|
||||||
|
if (item.fSinger == fSinger && isIncludesName(item.fMusicName)) return item
|
||||||
|
}
|
||||||
|
for (const item of source.list) {
|
||||||
|
if (item.name == null) continue
|
||||||
|
if (isEqualsAlbum(item.fAlbumName) && isIncludesSinger(item.fSinger) && isIncludesName(item.fMusicName)) return item
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}).filter(s => s)
|
}).filter(s => s)
|
||||||
const newResult = []
|
const newResult = []
|
||||||
if (result.length) {
|
if (result.length) {
|
||||||
newResult.push(...sortMusic(result, item => item.sortedSinger == sortedSinger && item.lowerCaseName == lowerCaseName && item.interval == interval))
|
newResult.push(...sortMusic(result, item => item.fSinger == fSinger && item.fMusicName == fMusicName && item.interval == interval))
|
||||||
newResult.push(...sortMusic(result, item => item.lowerCaseName == lowerCaseName && item.sortedSinger == sortedSinger && item.lowerCaseAlbumName == lowerCaseAlbumName))
|
newResult.push(...sortMusic(result, item => item.fMusicName == fMusicName && item.fSinger == fSinger && item.fAlbumName == fAlbumName))
|
||||||
newResult.push(...sortMusic(result, item => item.sortedSinger == sortedSinger && item.lowerCaseName == lowerCaseName))
|
newResult.push(...sortMusic(result, item => item.fSinger == fSinger && item.fMusicName == fMusicName))
|
||||||
newResult.push(...sortMusic(result, item => item.sortedSinger == sortedSinger && item.interval == interval))
|
newResult.push(...sortMusic(result, item => item.fMusicName == fMusicName))
|
||||||
|
newResult.push(...sortMusic(result, item => item.fSinger == fSinger))
|
||||||
|
newResult.push(...sortMusic(result, item => item.fAlbumName == fAlbumName))
|
||||||
|
newResult.push(...sortMusic(result, item => item.interval == interval))
|
||||||
for (const item of result) {
|
for (const item of result) {
|
||||||
delete item.sortedSinger
|
delete item.fSinger
|
||||||
delete item.lowerCaseName
|
delete item.fMusicName
|
||||||
delete item.lowerCaseAlbumName
|
delete item.fAlbumName
|
||||||
|
delete item.fInterval
|
||||||
}
|
}
|
||||||
newResult.push(...result)
|
newResult.push(...result)
|
||||||
}
|
}
|
||||||
|
@ -215,3 +215,13 @@ const fetchData = (url, { timeout = 15000, ...options }) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const checkUrl = async(url, options = {}) => {
|
||||||
|
return fetchData(url, { method: 'head', ...options }).request.then(resp => {
|
||||||
|
if (resp.statusCode === 200) {
|
||||||
|
return Promise.resolve()
|
||||||
|
} else {
|
||||||
|
throw new Error(resp.statusCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user