diff --git a/package.json b/package.json index 38e505a..0acaad6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lx-music-mobile", - "version": "8.8.8-肥猫宝贝", + "version": "8.8.8", "versionCode": 63, "private": true, "scripts": { @@ -64,7 +64,8 @@ "react-native-quick-base64": "^2.0.8", "react-native-quick-md5": "^3.0.6", "react-native-track-player": "github:lyswhut/react-native-track-player#ddfb984ec12efb0d6ae84c924e027f872bb1481f", - "react-native-vector-icons": "^10.0.3" + "react-native-vector-icons": "^10.0.3", + "rn-fetch-blob": "^0.12.0" }, "devDependencies": { "@babel/core": "^7.24.0", diff --git a/src/components/OnlineList/ListMenu.tsx b/src/components/OnlineList/ListMenu.tsx index 9a5a617..32d00c3 100644 --- a/src/components/OnlineList/ListMenu.tsx +++ b/src/components/OnlineList/ListMenu.tsx @@ -17,6 +17,7 @@ export interface ListMenuProps { onAdd: (selectInfo: SelectInfo) => void onCopyName: (selectInfo: SelectInfo) => void onDislikeMusic: (selectInfo: SelectInfo) => void + onDownload: (selectInfo: SelectInfo) => void } export interface ListMenuType { show: (selectInfo: SelectInfo, position: Position) => void @@ -51,7 +52,7 @@ export default forwardRef((props: ListMenuProps, re return [ { action: 'play', label: t('play') }, { action: 'playLater', label: t('play_later') }, - // { action: 'download', label: '下载' }, + { action: 'download', label: '下载' }, { action: 'add', label: t('add_to') }, { action: 'copyName', label: t('copy_name') }, { action: 'dislike', label: t('dislike'), disabled: isDislikeMusic }, @@ -76,6 +77,8 @@ export default forwardRef((props: ListMenuProps, re case 'dislike': props.onDislikeMusic(selectInfo) break + case 'download': + props.onDownload(selectInfo) default: break } diff --git a/src/components/OnlineList/index.tsx b/src/components/OnlineList/index.tsx index 7b082af..8818425 100644 --- a/src/components/OnlineList/index.tsx +++ b/src/components/OnlineList/index.tsx @@ -109,6 +109,7 @@ export default forwardRef(({ onPlayLater={info => { hancelExitSelect(); handlePlayLater(info.musicInfo, info.selectedList, hancelExitSelect) }} onCopyName={info => { handleShare(info.musicInfo) }} onAdd={handleAddMusic} + onDownload={info => { handelDownload(info.musicInfo) }} onDislikeMusic={info => { void handleDislikeMusic(info.musicInfo) }} /> {/* */} diff --git a/src/components/OnlineList/listAction.ts b/src/components/OnlineList/listAction.ts index b778d94..286060d 100644 --- a/src/components/OnlineList/listAction.ts +++ b/src/components/OnlineList/listAction.ts @@ -7,6 +7,8 @@ import { getListMusicSync } from '@/utils/listManage' import { confirmDialog, shareMusic, toast } from '@/utils/tools' import { addDislikeInfo, hasDislike } from '@/core/dislikeList' import playerState from '@/store/player/state' +import RNFetchBlob from 'rn-fetch-blob' +import { getMusicUrl } from '@/core/music' export const handlePlay = (musicInfo: LX.Music.MusicInfoOnline) => { void addListMusics(LIST_IDS.DEFAULT, [musicInfo], settingState.setting['list.addMusicLocationType']).then(() => { @@ -15,6 +17,49 @@ export const handlePlay = (musicInfo: LX.Music.MusicInfoOnline) => { void playList(LIST_IDS.DEFAULT, index) }) } + +export function getFileExtension(url: string) { + // 使用正则表达式匹配URL中的文件扩展名 + const match = url.match(/\.([0-9a-z]+)(?=[?#]|$)/i); + + // 如果匹配到扩展名,则返回该扩展名,否则返回默认值'mp3' + return match ? match[1] : 'mp3'; +} + +// export const handelDownload = (musicInfo: LX.Music.MusicInfoOnline) => { +export const handelDownload = (musicInfo: any) => { + let quality: LX.Quality = "128k" + if (musicInfo.meta._qualitys['320k']) { + quality = "320k" + } + getMusicUrl({ musicInfo, quality, isRefresh: true }).then(url => { + console.log(url); + const extension = getFileExtension(url); + const fileName = musicInfo.name; + const downloadDir = RNFetchBlob.fs.dirs.DownloadDir + "/lx.music"; + const path = `${downloadDir}/${fileName}.${extension}` + const config = { + fileCache: true, + addAndroidDownloads: { + useDownloadManager: true, + notification: true, + path: path, + description: '正在下载文件...', + }, + }; + RNFetchBlob.config(config) + .fetch('GET', url) + .then((res) => { + console.log('文件下载成功!路径:', res.path()); + toast("文件下载成功!", 'long') + }) + .catch((error) => { + console.log('文件下载失败:', error); + }); + }); +} + + export const handlePlayLater = (musicInfo: LX.Music.MusicInfoOnline, selectedList: LX.Music.MusicInfoOnline[], onCancelSelect: () => void) => { if (selectedList.length) { addTempPlayList(selectedList.map(s => ({ listId: '', musicInfo: s }))) @@ -29,7 +74,7 @@ export const handleShare = (musicInfo: LX.Music.MusicInfoOnline) => { shareMusic(settingState.setting['common.shareType'], settingState.setting['download.fileName'], musicInfo) } -export const handleDislikeMusic = async(musicInfo: LX.Music.MusicInfoOnline) => { +export const handleDislikeMusic = async (musicInfo: LX.Music.MusicInfoOnline) => { const confirm = await confirmDialog({ message: global.i18n.t('lists_dislike_music_tip', { name: musicInfo.name }), cancelButtonText: global.i18n.t('cancel_button_text_2'),