v2.0.0
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { apiSource, qualityList, userApi } from '@renderer/store'
|
||||
import { appSetting, setApiSource } from '@renderer/store/setting'
|
||||
import { setUserApi as setUserApiAction } from '@renderer/utils/ipc'
|
||||
import musicSdk from '@renderer/utils/musicSdk'
|
||||
import apiSourceInfo from '@renderer/utils/musicSdk/api-source-info'
|
||||
|
||||
|
||||
export const setUserApi = (apiId: string) => {
|
||||
if (/^user_api/.test(apiId)) {
|
||||
qualityList.value = {}
|
||||
userApi.status = false
|
||||
userApi.message = 'initing'
|
||||
|
||||
setUserApiAction(apiId).then(() => {
|
||||
apiSource.value = apiId
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
let api = apiSourceInfo.find(api => !api.disabled)
|
||||
if (!api) return
|
||||
apiSource.value = api.id
|
||||
if (api.id != appSetting['common.apiSource']) setApiSource(api.id)
|
||||
})
|
||||
} else {
|
||||
// @ts-expect-error
|
||||
qualityList.value = musicSdk.supportQuality[apiId] as LX.QualityList
|
||||
apiSource.value = apiId
|
||||
void setUserApiAction(apiId)
|
||||
}
|
||||
|
||||
if (apiId != appSetting['common.apiSource']) setApiSource(apiId)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// import defaultSetting from '@common/defaultSetting'
|
||||
import createWorkers from '@renderer/worker'
|
||||
|
||||
window.lx = {
|
||||
// appSetting: defaultSetting,
|
||||
isEditingHotKey: false,
|
||||
isPlayedStop: false,
|
||||
appHotKeyConfig: {
|
||||
local: {
|
||||
enable: false,
|
||||
keys: {},
|
||||
},
|
||||
global: {
|
||||
enable: false,
|
||||
keys: {},
|
||||
},
|
||||
},
|
||||
songListInfo: {
|
||||
fromName: '',
|
||||
searchKey: '',
|
||||
searchPosition: 0,
|
||||
songlistKey: '',
|
||||
songlistPosition: 0,
|
||||
},
|
||||
restorePlayInfo: null,
|
||||
worker: createWorkers(),
|
||||
isDev: process.env.NODE_ENV == 'production',
|
||||
}
|
||||
|
||||
window.lxData = {}
|
||||
|
||||
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
|
||||
@@ -0,0 +1,214 @@
|
||||
import Lyric from '@common/utils/lyric-font-player'
|
||||
import { getAnalyser, getCurrentTime as getPlayerCurrentTime } from '@renderer/plugins/player'
|
||||
import { lyric, setLines, setOffset, setTempOffset, setText } from '@renderer/store/player/lyric'
|
||||
import { isPlay, musicInfo } from '@renderer/store/player/state'
|
||||
import { setStatusText } from '@renderer/store/player/action'
|
||||
import { markRawList } from '@common/utils/vueTools'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { onNewDesktopLyricProcess } from '@renderer/utils/ipc'
|
||||
|
||||
const getCurrentTime = () => {
|
||||
return getPlayerCurrentTime() * 1000
|
||||
}
|
||||
|
||||
let lrc: Lyric
|
||||
let desktopLyricPort: Electron.IpcRendererEvent['ports'][0] | null = null
|
||||
const analyserTools: {
|
||||
dataArray: Uint8Array
|
||||
bufferLength: number
|
||||
analyser: AnalyserNode | null
|
||||
sendDataArray: () => void
|
||||
} = {
|
||||
dataArray: new Uint8Array(),
|
||||
bufferLength: 0,
|
||||
analyser: null,
|
||||
sendDataArray() {
|
||||
if (this.analyser == null) {
|
||||
this.analyser = getAnalyser()
|
||||
// console.log(this.analyser)
|
||||
if (!this.analyser) return
|
||||
this.bufferLength = this.analyser.frequencyBinCount
|
||||
}
|
||||
const dataArray = new Uint8Array(this.bufferLength)
|
||||
this.analyser.getByteFrequencyData(dataArray)
|
||||
sendDesktopLyricInfo({
|
||||
action: 'send_analyser_data_array',
|
||||
data: dataArray,
|
||||
}, [dataArray.buffer])
|
||||
},
|
||||
}
|
||||
|
||||
export const sendDesktopLyricInfo = (info: LX.DesktopLyric.LyricActions, transferList?: Transferable[]) => {
|
||||
if (desktopLyricPort == null) return
|
||||
if (transferList) desktopLyricPort.postMessage(info, transferList)
|
||||
else desktopLyricPort.postMessage(info)
|
||||
}
|
||||
const handleDesktopLyricMessage = (action: LX.DesktopLyric.WinMainActions) => {
|
||||
switch (action) {
|
||||
case 'get_info':
|
||||
sendDesktopLyricInfo({
|
||||
action: 'set_info',
|
||||
data: {
|
||||
id: musicInfo.id,
|
||||
singer: musicInfo.singer,
|
||||
name: musicInfo.name,
|
||||
album: musicInfo.album,
|
||||
lrc: musicInfo.lrc,
|
||||
tlrc: musicInfo.tlrc,
|
||||
rlrc: musicInfo.rlrc,
|
||||
lxlrc: musicInfo.lxlrc,
|
||||
// pic: musicInfo.pic,
|
||||
isPlay: isPlay.value,
|
||||
line: lyric.line,
|
||||
played_time: getCurrentTime(),
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'get_status':
|
||||
sendDesktopLyricInfo({
|
||||
action: 'set_status',
|
||||
data: {
|
||||
isPlay: isPlay.value,
|
||||
line: lyric.line,
|
||||
played_time: getCurrentTime(),
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'get_analyser_data_array':
|
||||
analyserTools.sendDataArray()
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
export const init = () => {
|
||||
lrc = new Lyric({
|
||||
shadowContent: false,
|
||||
onPlay(line, text) {
|
||||
setText(text, line)
|
||||
setStatusText(text)
|
||||
// console.log(line, text)
|
||||
},
|
||||
onSetLyric(lines, offset) { // listening lyrics seting event
|
||||
// console.log(lines) // lines is array of all lyric text
|
||||
setLines(markRawList([...lines]))
|
||||
setText(lines[0] ?? '', 0)
|
||||
setOffset(offset) // 歌词延迟
|
||||
setTempOffset(0) // 重置临时延迟
|
||||
},
|
||||
onUpdateLyric(lines) {
|
||||
setLines(markRawList([...lines]))
|
||||
setText(lines[0] ?? '', 0)
|
||||
},
|
||||
// offset: 80,
|
||||
})
|
||||
|
||||
onNewDesktopLyricProcess(({ event }) => {
|
||||
console.log('onNewDesktopLyricProcess')
|
||||
const [port] = event.ports
|
||||
desktopLyricPort = port
|
||||
|
||||
port.onmessage = ({ data }) => {
|
||||
handleDesktopLyricMessage(data.action)
|
||||
// The event data can be any serializable object (and the event could even
|
||||
// carry other MessagePorts with it!)
|
||||
// const result = doWork(event.data)
|
||||
// port.postMessage(result)
|
||||
}
|
||||
|
||||
port.onmessageerror = (event) => {
|
||||
console.log('onmessageerror', event)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const setLyricOffset = (offset: number) => {
|
||||
const tempOffset = offset - lyric.offset
|
||||
setTempOffset(tempOffset)
|
||||
lrc.setOffset(tempOffset)
|
||||
sendDesktopLyricInfo({
|
||||
action: 'set_offset',
|
||||
data: tempOffset,
|
||||
})
|
||||
|
||||
if (isPlay.value) {
|
||||
setTimeout(() => {
|
||||
const time = getCurrentTime()
|
||||
sendDesktopLyricInfo({
|
||||
action: 'set_play',
|
||||
data: time,
|
||||
})
|
||||
lrc.play(time)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const setLyric = () => {
|
||||
if (!musicInfo.id) return
|
||||
if (musicInfo.lrc) {
|
||||
const extendedLyrics = []
|
||||
if (appSetting['player.isShowLyricTranslation'] && musicInfo.tlrc) extendedLyrics.push(musicInfo.tlrc)
|
||||
if (appSetting['player.isShowLyricRoma'] && musicInfo.rlrc) extendedLyrics.push(musicInfo.rlrc)
|
||||
lrc.setLyric(
|
||||
appSetting['player.isPlayLxlrc'] && musicInfo.lxlrc ? musicInfo.lxlrc : musicInfo.lrc,
|
||||
extendedLyrics,
|
||||
)
|
||||
sendDesktopLyricInfo({
|
||||
action: 'set_lyric',
|
||||
data: {
|
||||
lrc: musicInfo.lrc,
|
||||
tlrc: musicInfo.tlrc,
|
||||
rlrc: musicInfo.rlrc,
|
||||
lxlrc: musicInfo.lxlrc,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (isPlay.value) {
|
||||
setTimeout(() => {
|
||||
const time = getCurrentTime()
|
||||
sendDesktopLyricInfo({ action: 'set_play', data: time })
|
||||
lrc.play(time)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const play = () => {
|
||||
// if (!musicInfo.lrc) return
|
||||
const currentTime = getCurrentTime()
|
||||
lrc.play(currentTime)
|
||||
sendDesktopLyricInfo({ action: 'set_play', data: currentTime })
|
||||
}
|
||||
|
||||
export const pause = () => {
|
||||
lrc.pause()
|
||||
sendDesktopLyricInfo({ action: 'set_pause' })
|
||||
}
|
||||
|
||||
export const stop = () => {
|
||||
lrc.setLyric('')
|
||||
sendDesktopLyricInfo({ action: 'set_stop' })
|
||||
// setLines([])
|
||||
setText('', 0)
|
||||
}
|
||||
|
||||
export const sendInfo = () => {
|
||||
sendDesktopLyricInfo({
|
||||
action: 'set_info',
|
||||
data: {
|
||||
id: musicInfo.id,
|
||||
singer: musicInfo.singer,
|
||||
name: musicInfo.name,
|
||||
album: musicInfo.album,
|
||||
lrc: musicInfo.lrc,
|
||||
tlrc: musicInfo.tlrc,
|
||||
rlrc: musicInfo.rlrc,
|
||||
lxlrc: musicInfo.lxlrc,
|
||||
// pic: musicInfo.pic,
|
||||
isPlay: isPlay.value,
|
||||
line: lyric.line,
|
||||
played_time: getCurrentTime(),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { getDownloadFilePath } from '@renderer/utils/music'
|
||||
|
||||
import {
|
||||
getMusicUrl as getOnlineMusicUrl,
|
||||
getPicUrl as getOnlinePicUrl,
|
||||
getLyricInfo as getOnlineLyricInfo,
|
||||
} from './online'
|
||||
import { buildLyricInfo, getCachedLyricInfo } from './utils'
|
||||
|
||||
export const getMusicUrl = async({ musicInfo, isRefresh, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Download.ListItem
|
||||
isRefresh: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if (!isRefresh) {
|
||||
const path = await getDownloadFilePath(musicInfo, appSetting['download.savePath'])
|
||||
if (path) return path
|
||||
}
|
||||
|
||||
return await getOnlineMusicUrl({ musicInfo: musicInfo.metadata.musicInfo, isRefresh, onToggleSource })
|
||||
}
|
||||
|
||||
export const getPicUrl = async({ musicInfo, isRefresh, listId, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Download.ListItem
|
||||
isRefresh: boolean
|
||||
listId?: string | null
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if (!isRefresh) {
|
||||
const onlineMusicInfo = musicInfo.metadata.musicInfo
|
||||
if (onlineMusicInfo.meta.picUrl && !isRefresh) return onlineMusicInfo.meta.picUrl
|
||||
|
||||
const path = await getDownloadFilePath(musicInfo, appSetting['download.savePath'])
|
||||
if (path) {
|
||||
const pic = await window.lx.worker.main.getMusicFilePic(path)
|
||||
if (pic) return pic
|
||||
}
|
||||
}
|
||||
|
||||
return await getOnlinePicUrl({ musicInfo: musicInfo.metadata.musicInfo, isRefresh, onToggleSource }).then((url) => {
|
||||
// TODO: when listId required save url (update downloadInfo)
|
||||
|
||||
return url
|
||||
})
|
||||
}
|
||||
|
||||
export const getLyricInfo = async({ musicInfo, isRefresh, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Download.ListItem
|
||||
isRefresh: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<LX.Player.LyricInfo> => {
|
||||
if (!isRefresh) {
|
||||
const lyricInfo = await getCachedLyricInfo(musicInfo.metadata.musicInfo)
|
||||
if (lyricInfo) return await buildLyricInfo(lyricInfo)
|
||||
}
|
||||
|
||||
return getOnlineLyricInfo({
|
||||
musicInfo: musicInfo.metadata.musicInfo,
|
||||
isRefresh,
|
||||
onToggleSource,
|
||||
}).catch(async() => {
|
||||
// 尝试读取文件内歌词
|
||||
const path = await getDownloadFilePath(musicInfo, appSetting['download.savePath'])
|
||||
if (path) {
|
||||
const rawlrcInfo = await window.lx.worker.main.getMusicFileLyric(path)
|
||||
if (rawlrcInfo) return buildLyricInfo(rawlrcInfo)
|
||||
}
|
||||
|
||||
throw new Error('failed')
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// if (targetSong.key) { // 如果是已下载的歌曲
|
||||
// const filePath = path.join(appSetting['download.savePath'], targetSong.metadata.fileName)
|
||||
// // console.log(filePath)
|
||||
|
||||
import {
|
||||
getMusicUrl as getOnlineMusicUrl,
|
||||
getPicUrl as getOnlinePicUrl,
|
||||
getLyricInfo as getOnlineLyricInfo,
|
||||
} from './online'
|
||||
import {
|
||||
getMusicUrl as getDownloadMusicUrl,
|
||||
getPicUrl as getDownloadPicUrl,
|
||||
getLyricInfo as getDownloadLyricInfo,
|
||||
} from './download'
|
||||
import {
|
||||
getMusicUrl as getLocalMusicUrl,
|
||||
getPicUrl as getLocalPicUrl,
|
||||
getLyricInfo as getLocalLyricInfo,
|
||||
} from './local'
|
||||
|
||||
|
||||
export const getMusicUrl = async({
|
||||
musicInfo,
|
||||
quality,
|
||||
isRefresh = false,
|
||||
onToggleSource,
|
||||
}: {
|
||||
musicInfo: LX.Music.MusicInfo | LX.Download.ListItem
|
||||
isRefresh?: boolean
|
||||
quality?: LX.Quality
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if ('progress' in musicInfo) {
|
||||
return await getDownloadMusicUrl({ musicInfo, isRefresh, onToggleSource })
|
||||
} else if (musicInfo.source == 'local') {
|
||||
return await getLocalMusicUrl({ musicInfo, isRefresh, onToggleSource })
|
||||
} else {
|
||||
return await getOnlineMusicUrl({ musicInfo, isRefresh, quality, onToggleSource })
|
||||
}
|
||||
}
|
||||
|
||||
export const getPicPath = async({
|
||||
musicInfo,
|
||||
isRefresh = false,
|
||||
listId,
|
||||
onToggleSource,
|
||||
}: {
|
||||
musicInfo: LX.Music.MusicInfo | LX.Download.ListItem
|
||||
listId?: string | null
|
||||
isRefresh?: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if ('progress' in musicInfo) {
|
||||
return await getDownloadPicUrl({ musicInfo, isRefresh, listId, onToggleSource })
|
||||
} else if (musicInfo.source == 'local') {
|
||||
return await getLocalPicUrl({ musicInfo, isRefresh, listId, onToggleSource })
|
||||
} else {
|
||||
return await getOnlinePicUrl({ musicInfo, isRefresh, listId, onToggleSource })
|
||||
}
|
||||
}
|
||||
|
||||
export const getLyricInfo = async({
|
||||
musicInfo,
|
||||
isRefresh = false,
|
||||
onToggleSource,
|
||||
}: {
|
||||
musicInfo: LX.Music.MusicInfo | LX.Download.ListItem
|
||||
isRefresh?: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<LX.Player.LyricInfo> => {
|
||||
if ('progress' in musicInfo) {
|
||||
return await getDownloadLyricInfo({ musicInfo, isRefresh, onToggleSource })
|
||||
} else if (musicInfo.source == 'local') {
|
||||
return await getLocalLyricInfo({ musicInfo, isRefresh, onToggleSource })
|
||||
} else {
|
||||
return await getOnlineLyricInfo({ musicInfo, isRefresh, onToggleSource })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { updateListMusics } from '@renderer/store/list/action'
|
||||
import { saveLyric, saveMusicUrl } from '@renderer/utils/ipc'
|
||||
import { getLocalFilePath } from '@renderer/utils/music'
|
||||
|
||||
import {
|
||||
buildLyricInfo,
|
||||
getCachedLyricInfo,
|
||||
getOnlineOtherSourceLyricInfo,
|
||||
getOnlineOtherSourceMusicUrl,
|
||||
getOnlineOtherSourcePicUrl,
|
||||
getOtherSource,
|
||||
} from './utils'
|
||||
|
||||
|
||||
export const getMusicUrl = async({ musicInfo, isRefresh, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Music.MusicInfoLocal
|
||||
isRefresh: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if (!isRefresh) {
|
||||
const path = await getLocalFilePath(musicInfo)
|
||||
if (path) return path
|
||||
}
|
||||
onToggleSource()
|
||||
const otherSource = await getOtherSource(musicInfo)
|
||||
if (!otherSource.length) throw new Error('source not found')
|
||||
return await getOnlineOtherSourceMusicUrl({ musicInfos: [...otherSource], onToggleSource, isRefresh }).then(({ url, quality: targetQuality, musicInfo: targetMusicInfo, isFromCache }) => {
|
||||
// saveLyric(musicInfo, data.lyricInfo)
|
||||
if (!isFromCache) void saveMusicUrl(targetMusicInfo, targetQuality, url)
|
||||
|
||||
// TODO: save url ?
|
||||
return url
|
||||
})
|
||||
}
|
||||
|
||||
export const getPicUrl = async({ musicInfo, listId, isRefresh, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Music.MusicInfoLocal
|
||||
listId?: string | null
|
||||
isRefresh: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if (!isRefresh) {
|
||||
if (musicInfo.meta.picUrl) return musicInfo.meta.picUrl
|
||||
|
||||
const pic = await window.lx.worker.main.getMusicFilePic(musicInfo.meta.filePath)
|
||||
if (pic) return pic
|
||||
}
|
||||
|
||||
onToggleSource()
|
||||
const otherSource = await getOtherSource(musicInfo)
|
||||
if (!otherSource.length) throw new Error('source not found')
|
||||
return await getOnlineOtherSourcePicUrl({ musicInfos: [...otherSource], onToggleSource, isRefresh }).then(({ url, musicInfo: targetMusicInfo, isFromCache }) => {
|
||||
if (listId) {
|
||||
musicInfo.meta.picUrl = url
|
||||
void updateListMusics([{ id: listId, musicInfo }])
|
||||
}
|
||||
|
||||
return url
|
||||
})
|
||||
}
|
||||
|
||||
export const getLyricInfo = async({ musicInfo, isRefresh, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Music.MusicInfoLocal
|
||||
isRefresh: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<LX.Player.LyricInfo> => {
|
||||
if (!isRefresh) {
|
||||
const lyricInfo = await getCachedLyricInfo(musicInfo)
|
||||
if (lyricInfo) {
|
||||
// 存在已编辑、原始歌词
|
||||
if (lyricInfo.rawlrcInfo.lyric) return await buildLyricInfo(lyricInfo)
|
||||
}
|
||||
|
||||
// 尝试读取文件内歌词
|
||||
const rawlrcInfo = await window.lx.worker.main.getMusicFileLyric(musicInfo.meta.filePath)
|
||||
if (rawlrcInfo) return buildLyricInfo(lyricInfo ? { ...lyricInfo, rawlrcInfo } : rawlrcInfo)
|
||||
}
|
||||
|
||||
onToggleSource()
|
||||
const otherSource = await getOtherSource(musicInfo)
|
||||
if (!otherSource.length) throw new Error('source not found')
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
return await getOnlineOtherSourceLyricInfo({ musicInfos: [...otherSource], onToggleSource, isRefresh }).then(({ lyricInfo, musicInfo: targetMusicInfo, isFromCache }) => {
|
||||
void saveLyric(musicInfo, lyricInfo)
|
||||
|
||||
if (isFromCache) return buildLyricInfo(lyricInfo)
|
||||
void saveLyric(targetMusicInfo, lyricInfo)
|
||||
|
||||
return buildLyricInfo(lyricInfo)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import { updateListMusics } from '@renderer/store/list/action'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import {
|
||||
saveLyric,
|
||||
saveMusicUrl,
|
||||
getMusicUrl as getStoreMusicUrl,
|
||||
} from '@renderer/utils/ipc'
|
||||
import {
|
||||
buildLyricInfo,
|
||||
getPlayQuality,
|
||||
handleGetOnlineLyricInfo,
|
||||
handleGetOnlineMusicUrl,
|
||||
handleGetOnlinePicUrl,
|
||||
getCachedLyricInfo,
|
||||
} from './utils'
|
||||
|
||||
/* export const setMusicUrl = ({ musicInfo, type, url }: {
|
||||
musicInfo: LX.Music.MusicInfo
|
||||
type: LX.Quality
|
||||
url: string
|
||||
}) => {
|
||||
saveMusicUrl(musicInfo, type, url)
|
||||
}
|
||||
|
||||
export const setPic = (datas: {
|
||||
listId: string
|
||||
musicInfo: LX.Music.MusicInfo
|
||||
url: string
|
||||
}) => {
|
||||
datas.musicInfo.img = datas.url
|
||||
updateMusicInfo({
|
||||
listId: datas.listId,
|
||||
id: datas.musicInfo.songmid,
|
||||
data: { img: datas.url },
|
||||
musicInfo: datas.musicInfo,
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
export const getMusicUrl = async({ musicInfo, quality, isRefresh, allowToggleSource = true, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
quality?: LX.Quality
|
||||
isRefresh: boolean
|
||||
allowToggleSource?: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
// if (!musicInfo._types[type]) {
|
||||
// // 兼容旧版酷我源搜索列表过滤128k音质的bug
|
||||
// if (!(musicInfo.source == 'kw' && type == '128k')) throw new Error('该歌曲没有可播放的音频')
|
||||
|
||||
// // return Promise.reject(new Error('该歌曲没有可播放的音频'))
|
||||
// }
|
||||
const targetQuality = quality ?? getPlayQuality(appSetting['player.highQuality'], musicInfo)
|
||||
const cachedUrl = await getStoreMusicUrl(musicInfo, targetQuality)
|
||||
if (cachedUrl && !isRefresh) return cachedUrl
|
||||
|
||||
return await handleGetOnlineMusicUrl({ musicInfo, quality, onToggleSource, isRefresh, allowToggleSource }).then(({ url, quality: targetQuality, musicInfo: targetMusicInfo, isFromCache }) => {
|
||||
if (targetMusicInfo.id != musicInfo.id && !isFromCache) void saveMusicUrl(targetMusicInfo, targetQuality, url)
|
||||
void saveMusicUrl(musicInfo, targetQuality, url)
|
||||
return url
|
||||
})
|
||||
}
|
||||
|
||||
export const getPicUrl = async({ musicInfo, listId, isRefresh, allowToggleSource = true, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
listId?: string | null
|
||||
isRefresh: boolean
|
||||
allowToggleSource?: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<string> => {
|
||||
if (musicInfo.meta.picUrl && !isRefresh) return musicInfo.meta.picUrl
|
||||
return await handleGetOnlinePicUrl({ musicInfo, onToggleSource, isRefresh, allowToggleSource }).then(({ url, musicInfo: targetMusicInfo, isFromCache }) => {
|
||||
// picRequest = null
|
||||
if (listId) {
|
||||
musicInfo.meta.picUrl = url
|
||||
void updateListMusics([{ id: listId, musicInfo }])
|
||||
}
|
||||
// savePic({ musicInfo, url, listId })
|
||||
return url
|
||||
})
|
||||
}
|
||||
export const getLyricInfo = async({ musicInfo, isRefresh, allowToggleSource = true, onToggleSource = () => {} }: {
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
isRefresh: boolean
|
||||
allowToggleSource?: boolean
|
||||
onToggleSource?: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<LX.Player.LyricInfo> => {
|
||||
if (!isRefresh) {
|
||||
const lyricInfo = await getCachedLyricInfo(musicInfo)
|
||||
if (lyricInfo) return await buildLyricInfo(lyricInfo)
|
||||
}
|
||||
|
||||
// lrcRequest = music[musicInfo.source].getLyric(musicInfo)
|
||||
return await handleGetOnlineLyricInfo({ musicInfo, onToggleSource, isRefresh, allowToggleSource }).then(async({ lyricInfo, musicInfo: targetMusicInfo, isFromCache }) => {
|
||||
// lrcRequest = null
|
||||
if (isFromCache) return await buildLyricInfo(lyricInfo)
|
||||
if (targetMusicInfo.id == musicInfo.id) void saveLyric(musicInfo, lyricInfo)
|
||||
else void saveLyric(targetMusicInfo, lyricInfo)
|
||||
|
||||
return await buildLyricInfo(lyricInfo)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
import { qualityList } from '@renderer/store'
|
||||
import { assertApiSupport } from '@renderer/store/utils'
|
||||
import musicSdk from '@renderer/utils/musicSdk'
|
||||
import {
|
||||
getOtherSource as getOtherSourceFromStore,
|
||||
saveOtherSource as saveOtherSourceFromStore,
|
||||
getMusicUrl as getStoreMusicUrl,
|
||||
getPlayerLyric as getStoreLyric,
|
||||
} from '@renderer/utils/ipc'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { langS2T, toNewMusicInfo, toOldMusicInfo } from '@renderer/utils'
|
||||
|
||||
|
||||
const getOtherSourcePromises = new Map()
|
||||
export const existTimeExp = /\[\d{1,2}:.*\d{1,4}\]/
|
||||
|
||||
export const getOtherSource = async(musicInfo: LX.Music.MusicInfo | LX.Download.ListItem, isRefresh = false): Promise<LX.Music.MusicInfoOnline[]> => {
|
||||
if (!isRefresh) {
|
||||
const cachedInfo = await getOtherSourceFromStore(musicInfo.id)
|
||||
if (cachedInfo.length) return cachedInfo
|
||||
}
|
||||
let key: string
|
||||
let searchMusicInfo: {
|
||||
name: string
|
||||
singer: string
|
||||
source: string
|
||||
albumName: string
|
||||
interval: string
|
||||
}
|
||||
if ('progress' in musicInfo) {
|
||||
key = `local_${musicInfo.id}`
|
||||
searchMusicInfo = {
|
||||
name: musicInfo.metadata.musicInfo.name,
|
||||
singer: musicInfo.metadata.musicInfo.singer,
|
||||
source: musicInfo.metadata.musicInfo.source,
|
||||
albumName: musicInfo.metadata.musicInfo.meta.albumName,
|
||||
interval: musicInfo.metadata.musicInfo.interval ?? '',
|
||||
}
|
||||
} else {
|
||||
key = `${musicInfo.source}_${musicInfo.id}`
|
||||
searchMusicInfo = {
|
||||
name: musicInfo.name,
|
||||
singer: musicInfo.singer,
|
||||
source: musicInfo.source,
|
||||
albumName: musicInfo.meta.albumName,
|
||||
interval: musicInfo.interval ?? '',
|
||||
}
|
||||
}
|
||||
if (getOtherSourcePromises.has(key)) return getOtherSourcePromises.get(key)
|
||||
|
||||
const promise = musicSdk.findMusic(searchMusicInfo).then((otherSource) => {
|
||||
const sources: LX.Music.MusicInfoOnline[] = otherSource.map(toNewMusicInfo)
|
||||
if (sources.length) void saveOtherSourceFromStore(musicInfo.id, sources)
|
||||
return sources
|
||||
}).finally(() => {
|
||||
if (getOtherSourcePromises.has(key)) getOtherSourcePromises.delete(key)
|
||||
})
|
||||
getOtherSourcePromises.set(key, promise)
|
||||
return promise
|
||||
}
|
||||
|
||||
|
||||
export const buildLyricInfo = async(lyricInfo: MakeOptional<LX.Player.LyricInfo, 'rawlrcInfo'>): Promise<LX.Player.LyricInfo> => {
|
||||
if (!appSetting['player.isS2t']) {
|
||||
// @ts-expect-error
|
||||
if (lyricInfo.rawlrcInfo) return lyricInfo
|
||||
return { ...lyricInfo, rawlrcInfo: { ...lyricInfo } }
|
||||
}
|
||||
|
||||
if (appSetting['player.isS2t']) {
|
||||
const tasks = [
|
||||
lyricInfo.lyric ? window.lx.worker.main.langS2t(lyricInfo.lyric) : Promise.resolve(''),
|
||||
lyricInfo.tlyric ? langS2T(lyricInfo.tlyric) : Promise.resolve(''),
|
||||
lyricInfo.rlyric ? langS2T(lyricInfo.rlyric) : Promise.resolve(''),
|
||||
lyricInfo.lxlyric ? langS2T(lyricInfo.lxlyric) : Promise.resolve(''),
|
||||
]
|
||||
if (lyricInfo.rawlrcInfo) {
|
||||
tasks.push(lyricInfo.lyric ? window.lx.worker.main.langS2t(lyricInfo.lyric) : Promise.resolve(''))
|
||||
tasks.push(lyricInfo.tlyric ? window.lx.worker.main.langS2t(lyricInfo.tlyric) : Promise.resolve(''))
|
||||
tasks.push(lyricInfo.rlyric ? window.lx.worker.main.langS2t(lyricInfo.rlyric) : Promise.resolve(''))
|
||||
tasks.push(lyricInfo.lxlyric ? window.lx.worker.main.langS2t(lyricInfo.lxlyric) : Promise.resolve(''))
|
||||
}
|
||||
return await Promise.all(tasks).then(([lyric, tlyric, rlyric, lxlyric, lyric_raw, tlyric_raw, rlyric_raw, lxlyric_raw]) => {
|
||||
const rawlrcInfo = lyric_raw ? {
|
||||
lyric: lyric_raw,
|
||||
tlyric: tlyric_raw,
|
||||
rlyric: rlyric_raw,
|
||||
lxlyric: lxlyric_raw,
|
||||
} : {
|
||||
lyric,
|
||||
tlyric,
|
||||
rlyric,
|
||||
lxlyric,
|
||||
}
|
||||
return {
|
||||
lyric,
|
||||
tlyric,
|
||||
rlyric,
|
||||
lxlyric,
|
||||
rawlrcInfo,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
return lyricInfo.rawlrcInfo ? lyricInfo : { ...lyricInfo, rawlrcInfo: { ...lyricInfo } }
|
||||
}
|
||||
|
||||
export const getCachedLyricInfo = async(musicInfo: LX.Music.MusicInfo): Promise<LX.Player.LyricInfo | null> => {
|
||||
let lrcInfo = await getStoreLyric(musicInfo)
|
||||
// lrcInfo = {}
|
||||
if (existTimeExp.test(lrcInfo.lyric) && lrcInfo.tlyric != null) {
|
||||
// if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
|
||||
// let str = musicInfo.lrc.replace('\ufeff[id:$00000000]\n', '')
|
||||
// commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc, lxlyric: musicInfo.tlrc })
|
||||
// } else if (musicInfo.lrc.startsWith('[id:$00000000]')) {
|
||||
// let str = musicInfo.lrc.replace('[id:$00000000]\n', '')
|
||||
// commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc, lxlyric: musicInfo.tlrc })
|
||||
// }
|
||||
|
||||
if (lrcInfo.lxlyric == null) {
|
||||
switch (musicInfo.source) {
|
||||
case 'kg':
|
||||
case 'kw':
|
||||
case 'mg':
|
||||
break
|
||||
default:
|
||||
return lrcInfo
|
||||
}
|
||||
} else if (lrcInfo.rlyric == null) {
|
||||
if (!['wy', 'kg'].includes(musicInfo.source)) return lrcInfo
|
||||
} else return lrcInfo
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const getPlayQuality = (highQuality: boolean, musicInfo: LX.Music.MusicInfoOnline): LX.Quality => {
|
||||
let type: LX.Quality = '128k'
|
||||
let list = qualityList.value[musicInfo.source]
|
||||
if (highQuality && musicInfo.meta._qualitys['320k'] && list && list.includes('320k')) type = '320k'
|
||||
return type
|
||||
}
|
||||
|
||||
export const getOnlineOtherSourceMusicUrl = async({ musicInfos, quality, onToggleSource, isRefresh, retryedSource = [] }: {
|
||||
musicInfos: LX.Music.MusicInfoOnline[]
|
||||
quality?: LX.Quality
|
||||
onToggleSource: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
isRefresh: boolean
|
||||
retryedSource?: LX.OnlineSource[]
|
||||
}): Promise<{
|
||||
url: string
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
quality: LX.Quality
|
||||
isFromCache: boolean
|
||||
}> => {
|
||||
let musicInfo: LX.Music.MusicInfoOnline | null = null
|
||||
let itemQuality: LX.Quality | null = null
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while (musicInfo = (musicInfos.shift() as LX.Music.MusicInfoOnline)) {
|
||||
if (retryedSource.includes(musicInfo.source)) continue
|
||||
retryedSource.push(musicInfo.source)
|
||||
if (!assertApiSupport(musicInfo.source)) continue
|
||||
itemQuality = quality ?? getPlayQuality(appSetting['player.highQuality'], musicInfo)
|
||||
if (!musicInfo.meta._qualitys[itemQuality]) continue
|
||||
|
||||
console.log('try toggle to: ', musicInfo.source, musicInfo.name, musicInfo.singer, musicInfo.interval)
|
||||
onToggleSource(musicInfo)
|
||||
break
|
||||
}
|
||||
if (!musicInfo || !itemQuality) throw new Error(window.i18n.t('toggle_source_failed'))
|
||||
|
||||
const cachedUrl = await getStoreMusicUrl(musicInfo, itemQuality)
|
||||
if (cachedUrl && !isRefresh) return { url: cachedUrl, musicInfo, quality: itemQuality, isFromCache: true }
|
||||
|
||||
let reqPromise
|
||||
try {
|
||||
reqPromise = musicSdk[musicInfo.source].getMusicUrl(toOldMusicInfo(musicInfo), itemQuality).promise
|
||||
} catch (err: any) {
|
||||
reqPromise = Promise.reject(err)
|
||||
}
|
||||
retryedSource.includes(musicInfo.source)
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
return reqPromise.then(({ url, type }: { url: string, type: LX.Quality }) => {
|
||||
return { musicInfo, url, quality: type, isFromCache: false }
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
}).catch((err: any) => {
|
||||
console.log(err)
|
||||
return getOnlineOtherSourceMusicUrl({ musicInfos, quality, onToggleSource, isRefresh, retryedSource })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线音乐URL
|
||||
*/
|
||||
export const handleGetOnlineMusicUrl = async({ musicInfo, quality, onToggleSource, isRefresh, allowToggleSource }: {
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
quality?: LX.Quality
|
||||
isRefresh: boolean
|
||||
allowToggleSource: boolean
|
||||
onToggleSource: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
}): Promise<{
|
||||
url: string
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
quality: LX.Quality
|
||||
isFromCache: boolean
|
||||
}> => {
|
||||
// console.log(musicInfo.source)
|
||||
const targetQuality = quality ?? getPlayQuality(appSetting['player.highQuality'], musicInfo)
|
||||
|
||||
let reqPromise
|
||||
try {
|
||||
reqPromise = musicSdk[musicInfo.source].getMusicUrl(toOldMusicInfo(musicInfo), targetQuality).promise
|
||||
} catch (err: any) {
|
||||
reqPromise = Promise.reject(err)
|
||||
}
|
||||
return reqPromise.then(({ url, type }: { url: string, type: LX.Quality }) => {
|
||||
return { musicInfo, url, quality: type, isFromCache: false }
|
||||
}).catch(async(err: any) => {
|
||||
console.log(err)
|
||||
if (!allowToggleSource) throw err
|
||||
onToggleSource()
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
return await getOtherSource(musicInfo).then(otherSource => {
|
||||
console.log('find otherSource', otherSource)
|
||||
if (otherSource.length) {
|
||||
return getOnlineOtherSourceMusicUrl({
|
||||
musicInfos: [...otherSource],
|
||||
onToggleSource,
|
||||
quality,
|
||||
isRefresh,
|
||||
retryedSource: [musicInfo.source],
|
||||
})
|
||||
}
|
||||
throw err
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const getOnlineOtherSourcePicUrl = async({ musicInfos, onToggleSource, isRefresh, retryedSource = [] }: {
|
||||
musicInfos: LX.Music.MusicInfoOnline[]
|
||||
onToggleSource: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
isRefresh: boolean
|
||||
retryedSource?: LX.OnlineSource[]
|
||||
}): Promise<{
|
||||
url: string
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
isFromCache: boolean
|
||||
}> => {
|
||||
let musicInfo: LX.Music.MusicInfoOnline | null = null
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while (musicInfo = (musicInfos.shift() as LX.Music.MusicInfoOnline)) {
|
||||
if (retryedSource.includes(musicInfo.source)) continue
|
||||
retryedSource.push(musicInfo.source)
|
||||
// if (!assertApiSupport(musicInfo.source)) continue
|
||||
console.log('try toggle to: ', musicInfo.source, musicInfo.name, musicInfo.singer, musicInfo.interval)
|
||||
onToggleSource(musicInfo)
|
||||
break
|
||||
}
|
||||
if (!musicInfo) throw new Error(window.i18n.t('toggle_source_failed'))
|
||||
|
||||
if (musicInfo.meta.picUrl && !isRefresh) return { musicInfo, url: musicInfo.meta.picUrl, isFromCache: true }
|
||||
|
||||
let reqPromise
|
||||
try {
|
||||
reqPromise = musicSdk[musicInfo.source].getPic(toOldMusicInfo(musicInfo)).promise
|
||||
} catch (err: any) {
|
||||
reqPromise = Promise.reject(err)
|
||||
}
|
||||
retryedSource.includes(musicInfo.source)
|
||||
return reqPromise.then((url: string) => {
|
||||
return { musicInfo, url, isFromCache: false }
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
}).catch((err: any) => {
|
||||
console.log(err)
|
||||
return getOnlineOtherSourcePicUrl({ musicInfos, onToggleSource, isRefresh, retryedSource })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线歌曲封面
|
||||
*/
|
||||
export const handleGetOnlinePicUrl = async({ musicInfo, isRefresh, onToggleSource, allowToggleSource }: {
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
onToggleSource: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
isRefresh: boolean
|
||||
allowToggleSource: boolean
|
||||
}): Promise<{
|
||||
url: string
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
isFromCache: boolean
|
||||
}> => {
|
||||
// console.log(musicInfo.source)
|
||||
let reqPromise
|
||||
try {
|
||||
reqPromise = musicSdk[musicInfo.source].getPic(toOldMusicInfo(musicInfo)).promise
|
||||
} catch (err) {
|
||||
reqPromise = Promise.reject(err)
|
||||
}
|
||||
return reqPromise.then((url: string) => {
|
||||
return { musicInfo, url, isFromCache: false }
|
||||
}).catch(async(err: any) => {
|
||||
console.log(err)
|
||||
if (!allowToggleSource) throw err
|
||||
onToggleSource()
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
return await getOtherSource(musicInfo).then(otherSource => {
|
||||
console.log('find otherSource', otherSource)
|
||||
if (otherSource.length) {
|
||||
return getOnlineOtherSourcePicUrl({
|
||||
musicInfos: [...otherSource],
|
||||
onToggleSource,
|
||||
isRefresh,
|
||||
retryedSource: [musicInfo.source],
|
||||
})
|
||||
}
|
||||
throw err
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const getOnlineOtherSourceLyricInfo = async({ musicInfos, onToggleSource, isRefresh, retryedSource = [] }: {
|
||||
musicInfos: LX.Music.MusicInfoOnline[]
|
||||
onToggleSource: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
isRefresh: boolean
|
||||
retryedSource?: LX.OnlineSource[]
|
||||
}): Promise<{
|
||||
lyricInfo: LX.Music.LyricInfo | LX.Player.LyricInfo
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
isFromCache: boolean
|
||||
}> => {
|
||||
let musicInfo: LX.Music.MusicInfoOnline | null = null
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while (musicInfo = (musicInfos.shift() as LX.Music.MusicInfoOnline)) {
|
||||
if (retryedSource.includes(musicInfo.source)) continue
|
||||
retryedSource.push(musicInfo.source)
|
||||
// if (!assertApiSupport(musicInfo.source)) continue
|
||||
console.log('try toggle to: ', musicInfo.source, musicInfo.name, musicInfo.singer, musicInfo.interval)
|
||||
onToggleSource(musicInfo)
|
||||
break
|
||||
}
|
||||
if (!musicInfo) throw new Error(window.i18n.t('toggle_source_failed'))
|
||||
|
||||
if (!isRefresh) {
|
||||
const lyricInfo = await getCachedLyricInfo(musicInfo)
|
||||
if (lyricInfo) return { musicInfo, lyricInfo, isFromCache: true }
|
||||
}
|
||||
|
||||
let reqPromise
|
||||
try {
|
||||
// TODO: remove any type
|
||||
reqPromise = (musicSdk[musicInfo.source].getLyric(toOldMusicInfo(musicInfo)) as any).promise
|
||||
} catch (err: any) {
|
||||
reqPromise = Promise.reject(err)
|
||||
}
|
||||
retryedSource.includes(musicInfo.source)
|
||||
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
|
||||
return existTimeExp.test(lyricInfo.lyric) ? {
|
||||
lyricInfo,
|
||||
musicInfo,
|
||||
isFromCache: false,
|
||||
} : Promise.reject(new Error('failed'))
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
}).catch((err: any) => {
|
||||
console.log(err)
|
||||
return getOnlineOtherSourceLyricInfo({ musicInfos, onToggleSource, isRefresh, retryedSource })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线歌词信息
|
||||
*/
|
||||
export const handleGetOnlineLyricInfo = async({ musicInfo, onToggleSource, isRefresh, allowToggleSource }: {
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
onToggleSource: (musicInfo?: LX.Music.MusicInfoOnline) => void
|
||||
isRefresh: boolean
|
||||
allowToggleSource: boolean
|
||||
}): Promise<{
|
||||
musicInfo: LX.Music.MusicInfoOnline
|
||||
lyricInfo: LX.Music.LyricInfo | LX.Player.LyricInfo
|
||||
isFromCache: boolean
|
||||
}> => {
|
||||
// console.log(musicInfo.source)
|
||||
let reqPromise
|
||||
try {
|
||||
// TODO: remove any type
|
||||
reqPromise = (musicSdk[musicInfo.source].getLyric(toOldMusicInfo(musicInfo)) as any).promise
|
||||
} catch (err) {
|
||||
reqPromise = Promise.reject(err)
|
||||
}
|
||||
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
|
||||
return existTimeExp.test(lyricInfo.lyric) ? {
|
||||
musicInfo,
|
||||
lyricInfo,
|
||||
isFromCache: false,
|
||||
} : Promise.reject(new Error('failed'))
|
||||
}).catch(async(err: any) => {
|
||||
console.log(err)
|
||||
if (!allowToggleSource) throw err
|
||||
|
||||
onToggleSource()
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
return await getOtherSource(musicInfo).then(otherSource => {
|
||||
console.log('find otherSource', otherSource)
|
||||
if (otherSource.length) {
|
||||
return getOnlineOtherSourceLyricInfo({
|
||||
musicInfos: [...otherSource],
|
||||
onToggleSource,
|
||||
isRefresh,
|
||||
retryedSource: [musicInfo.source],
|
||||
})
|
||||
}
|
||||
throw err
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
import { isEmpty, setPause, setPlay, setResource, setStop } from '@renderer/plugins/player'
|
||||
import { isPlay, playedList, playInfo, playMusicInfo, tempPlayList } from '@renderer/store/player/state'
|
||||
import {
|
||||
getList,
|
||||
clearPlayedList,
|
||||
clearTempPlayeList,
|
||||
setPlayMusicInfo,
|
||||
addPlayedList,
|
||||
setMusicInfo,
|
||||
setAllStatus,
|
||||
removeTempPlayList,
|
||||
setPlayListId,
|
||||
removePlayedList,
|
||||
} from '@renderer/store/player/action'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { getMusicUrl, getPicPath, getLyricInfo } from '../music/index'
|
||||
import { filterList } from './utils'
|
||||
import { requestMsg } from '@renderer/utils/message'
|
||||
import { getRandom } from '@renderer/utils/index'
|
||||
// import { checkMusicFileAvailable } from '@renderer/utils/music'
|
||||
|
||||
let isGettingUrl = false
|
||||
const createDelayNextTimeout = (delay: number) => {
|
||||
let timeout: NodeJS.Timeout | null
|
||||
const clearDelayNextTimeout = () => {
|
||||
// console.log(this.timeout)
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
timeout = null
|
||||
}
|
||||
}
|
||||
|
||||
const addDelayNextTimeout = () => {
|
||||
clearDelayNextTimeout()
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null
|
||||
if (window.lx.isPlayedStop) return
|
||||
console.warn('delay next timeout timeout', delay)
|
||||
void playNext(true)
|
||||
}, delay)
|
||||
}
|
||||
|
||||
return {
|
||||
clearDelayNextTimeout,
|
||||
addDelayNextTimeout,
|
||||
}
|
||||
}
|
||||
const { addDelayNextTimeout, clearDelayNextTimeout } = createDelayNextTimeout(5000)
|
||||
const { addDelayNextTimeout: addLoadTimeout, clearDelayNextTimeout: clearLoadTimeout } = createDelayNextTimeout(100000)
|
||||
|
||||
/**
|
||||
* 检查音乐信息是否已更改
|
||||
*/
|
||||
const diffCurrentMusicInfo = (curMusicInfo: LX.Music.MusicInfo | LX.Download.ListItem): boolean => {
|
||||
return curMusicInfo !== playMusicInfo.musicInfo || isPlay.value
|
||||
}
|
||||
|
||||
const getMusicPlayUrl = async(musicInfo: LX.Music.MusicInfo | LX.Download.ListItem, isRefresh = false, isRetryed = false): Promise<string | null> => {
|
||||
// this.musicInfo.url = await getMusicPlayUrl(targetSong, type)
|
||||
setAllStatus(window.i18n.t('player__geting_url'))
|
||||
|
||||
// const type = getPlayType(appSetting['player.highQuality'], musicInfo)
|
||||
|
||||
return getMusicUrl({
|
||||
musicInfo,
|
||||
isRefresh,
|
||||
onToggleSource(mInfo) {
|
||||
if (diffCurrentMusicInfo(musicInfo)) return
|
||||
setAllStatus(window.i18n.t('toggle_source_try'))
|
||||
},
|
||||
}).then(url => {
|
||||
if (window.lx.isPlayedStop || diffCurrentMusicInfo(musicInfo)) return null
|
||||
|
||||
return url
|
||||
}).catch(err => {
|
||||
// console.log('err', err.message)
|
||||
if (window.lx.isPlayedStop ||
|
||||
diffCurrentMusicInfo(musicInfo) ||
|
||||
err.message == requestMsg.cancelRequest) return null
|
||||
|
||||
if (!isRetryed) return getMusicPlayUrl(musicInfo, isRefresh, true)
|
||||
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
export const setMusicUrl = (musicInfo: LX.Music.MusicInfo | LX.Download.ListItem, isRefresh?: boolean) => {
|
||||
if (appSetting['player.autoSkipOnError']) addLoadTimeout()
|
||||
isGettingUrl = true
|
||||
void getMusicPlayUrl(musicInfo, isRefresh).then((url) => {
|
||||
if (!url) return
|
||||
setResource(url)
|
||||
}).catch((err: any) => {
|
||||
console.log(err)
|
||||
setAllStatus(err.message)
|
||||
window.app_event.error()
|
||||
if (appSetting['player.autoSkipOnError']) addDelayNextTimeout()
|
||||
}).finally(() => {
|
||||
clearLoadTimeout()
|
||||
if (musicInfo === playMusicInfo.musicInfo) isGettingUrl = false
|
||||
})
|
||||
}
|
||||
|
||||
// 恢复上次播放的状态
|
||||
const handleRestorePlay = async(restorePlayInfo: LX.Player.SavedPlayInfo) => {
|
||||
const musicInfo = playMusicInfo.musicInfo
|
||||
if (!musicInfo) return
|
||||
|
||||
setImmediate(() => {
|
||||
window.app_event.setProgress(appSetting['player.isSavePlayTime'] ? restorePlayInfo.time : 0, restorePlayInfo.maxTime)
|
||||
})
|
||||
|
||||
|
||||
void getPicPath({ musicInfo, listId: playMusicInfo.isTempPlay ? null : playMusicInfo.listId }).then((url: string) => {
|
||||
if (musicInfo.id != playMusicInfo.musicInfo?.id) return
|
||||
setMusicInfo({ pic: url })
|
||||
window.app_event.picUpdated()
|
||||
})
|
||||
|
||||
void getLyricInfo({ musicInfo }).then((lyricInfo) => {
|
||||
if (musicInfo.id != playMusicInfo.musicInfo?.id) return
|
||||
setMusicInfo({
|
||||
lrc: lyricInfo.lyric,
|
||||
tlrc: lyricInfo.tlyric,
|
||||
lxlrc: lyricInfo.lxlyric,
|
||||
rlrc: lyricInfo.rlyric,
|
||||
rawlrc: lyricInfo.rawlrcInfo.lyric,
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
if (musicInfo.id != playMusicInfo.musicInfo?.id) return
|
||||
setAllStatus(window.i18n.t('lyric__load_error'))
|
||||
}).finally(() => {
|
||||
window.app_event.lyricUpdated()
|
||||
})
|
||||
|
||||
if (appSetting['player.togglePlayMethod'] == 'random') addPlayedList({ ...playMusicInfo as LX.Player.PlayMusicInfo })
|
||||
}
|
||||
|
||||
|
||||
// 处理音乐播放
|
||||
const handlePlay = () => {
|
||||
if (window.lx.isPlayedStop) window.lx.isPlayedStop = false
|
||||
if (isGettingUrl) isGettingUrl = false
|
||||
|
||||
if (window.lx.restorePlayInfo) {
|
||||
void handleRestorePlay(window.lx.restorePlayInfo)
|
||||
window.lx.restorePlayInfo = null
|
||||
return
|
||||
}
|
||||
|
||||
setStop()
|
||||
window.app_event.pause()
|
||||
|
||||
clearDelayNextTimeout()
|
||||
clearLoadTimeout()
|
||||
|
||||
const musicInfo = playMusicInfo.musicInfo
|
||||
|
||||
if (!musicInfo) return
|
||||
|
||||
if (appSetting['player.togglePlayMethod'] == 'random' && !playMusicInfo.isTempPlay) addPlayedList({ ...(playMusicInfo as LX.Player.PlayMusicInfo) })
|
||||
|
||||
void setMusicUrl(musicInfo)
|
||||
|
||||
void getPicPath({ musicInfo, listId: playMusicInfo.isTempPlay ? null : playMusicInfo.listId }).then((url: string) => {
|
||||
if (musicInfo.id != playMusicInfo.musicInfo?.id) return
|
||||
setMusicInfo({ pic: url })
|
||||
window.app_event.picUpdated()
|
||||
})
|
||||
|
||||
void getLyricInfo({ musicInfo }).then((lyricInfo) => {
|
||||
if (musicInfo.id != playMusicInfo.musicInfo?.id) return
|
||||
setMusicInfo({
|
||||
lrc: lyricInfo.lyric,
|
||||
tlrc: lyricInfo.tlyric,
|
||||
lxlrc: lyricInfo.lxlyric,
|
||||
rlrc: lyricInfo.rlyric,
|
||||
rawlrc: lyricInfo.rawlrcInfo.lyric,
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
if (musicInfo.id != playMusicInfo.musicInfo?.id) return
|
||||
setAllStatus(window.i18n.t('lyric__load_error'))
|
||||
}).finally(() => {
|
||||
window.app_event.lyricUpdated()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放列表内歌曲
|
||||
* @param listId 列表id
|
||||
* @param index 播放的歌曲位置
|
||||
*/
|
||||
export const playList = (listId: string, index: number) => {
|
||||
setPlayListId(listId)
|
||||
setPlayMusicInfo(listId, getList(listId)[index])
|
||||
clearPlayedList()
|
||||
clearTempPlayeList()
|
||||
handlePlay()
|
||||
}
|
||||
|
||||
const handleToggleStop = () => {
|
||||
stop()
|
||||
setTimeout(() => {
|
||||
setPlayMusicInfo(null, null)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 下一曲
|
||||
* @param isAutoToggle 是否自动切换
|
||||
* @returns
|
||||
*/
|
||||
export const playNext = async(isAutoToggle = false): Promise<void> => {
|
||||
if (tempPlayList.length) { // 如果稍后播放列表存在歌曲则直接播放改列表的歌曲
|
||||
const playMusicInfo = tempPlayList[0]
|
||||
removeTempPlayList(0)
|
||||
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
||||
handlePlay()
|
||||
return
|
||||
}
|
||||
|
||||
if (playMusicInfo.musicInfo == null) return handleToggleStop()
|
||||
|
||||
// console.log(playInfo.playerListId)
|
||||
const currentListId = playInfo.playerListId
|
||||
if (!currentListId) return handleToggleStop()
|
||||
const currentList = getList(currentListId)
|
||||
|
||||
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) {
|
||||
const playMusicInfo = playedList[index]
|
||||
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
||||
handlePlay()
|
||||
return
|
||||
}
|
||||
}
|
||||
// const isCheckFile = findNum > 2 // 针对下载列表,如果超过两次都碰到无效歌曲,则过滤整个列表内的无效歌曲
|
||||
let { filteredList, playerIndex } = await filterList({ // 过滤已播放歌曲
|
||||
listId: currentListId,
|
||||
list: currentList,
|
||||
playedList,
|
||||
playerMusicInfo: currentList[playInfo.playerPlayIndex],
|
||||
})
|
||||
|
||||
if (!filteredList.length) return handleToggleStop()
|
||||
// let currentIndex: number = filteredList.indexOf(currentList[playInfo.playerPlayIndex])
|
||||
if (playerIndex == -1 && filteredList.length) playerIndex = 0
|
||||
let nextIndex = playerIndex
|
||||
|
||||
let togglePlayMethod = appSetting['player.togglePlayMethod']
|
||||
if (!isAutoToggle) {
|
||||
switch (togglePlayMethod) {
|
||||
case 'list':
|
||||
case 'singleLoop':
|
||||
case 'none':
|
||||
togglePlayMethod = 'listLoop'
|
||||
}
|
||||
}
|
||||
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:
|
||||
nextIndex = -1
|
||||
return
|
||||
}
|
||||
if (nextIndex < 0) return
|
||||
|
||||
const nextPlayMusicInfo = {
|
||||
musicInfo: filteredList[nextIndex],
|
||||
listId: currentListId,
|
||||
isTempPlay: false,
|
||||
}
|
||||
|
||||
setPlayMusicInfo(nextPlayMusicInfo.listId, nextPlayMusicInfo.musicInfo)
|
||||
handlePlay()
|
||||
}
|
||||
|
||||
/**
|
||||
* 上一曲
|
||||
*/
|
||||
export const playPrev = async(isAutoToggle = false): Promise<void> => {
|
||||
if (playMusicInfo.musicInfo == null) return handleToggleStop()
|
||||
|
||||
const currentListId = playInfo.playerListId
|
||||
if (!currentListId) return handleToggleStop()
|
||||
const currentList = getList(currentListId)
|
||||
|
||||
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 > -1; 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 > -1) {
|
||||
const playMusicInfo = playedList[index]
|
||||
setPlayMusicInfo(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
||||
handlePlay()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// const isCheckFile = findNum > 2
|
||||
let { filteredList, playerIndex } = await filterList({ // 过滤已播放歌曲
|
||||
listId: currentListId,
|
||||
list: currentList,
|
||||
playedList,
|
||||
playerMusicInfo: currentList[playInfo.playerPlayIndex],
|
||||
})
|
||||
if (!filteredList.length) return handleToggleStop()
|
||||
|
||||
// let currentIndex = filteredList.indexOf(currentList[playInfo.playerPlayIndex])
|
||||
if (playerIndex == -1 && filteredList.length) playerIndex = 0
|
||||
let nextIndex = playerIndex
|
||||
if (!playMusicInfo.isTempPlay) {
|
||||
let togglePlayMethod = appSetting['player.togglePlayMethod']
|
||||
if (!isAutoToggle) {
|
||||
switch (togglePlayMethod) {
|
||||
case 'list':
|
||||
case 'singleLoop':
|
||||
case 'none':
|
||||
togglePlayMethod = 'listLoop'
|
||||
}
|
||||
}
|
||||
switch (togglePlayMethod) {
|
||||
case 'random':
|
||||
nextIndex = getRandom(0, filteredList.length)
|
||||
break
|
||||
case 'listLoop':
|
||||
case 'list':
|
||||
nextIndex = playerIndex === 0 ? filteredList.length - 1 : playerIndex - 1
|
||||
break
|
||||
case 'singleLoop':
|
||||
break
|
||||
default:
|
||||
nextIndex = -1
|
||||
return
|
||||
}
|
||||
if (nextIndex < 0) return
|
||||
}
|
||||
|
||||
const nextPlayMusicInfo = {
|
||||
musicInfo: filteredList[nextIndex],
|
||||
listId: currentListId,
|
||||
isTempPlay: false,
|
||||
}
|
||||
|
||||
setPlayMusicInfo(nextPlayMusicInfo.listId, nextPlayMusicInfo.musicInfo)
|
||||
handlePlay()
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复播放
|
||||
*/
|
||||
export const play = () => {
|
||||
if (playMusicInfo.musicInfo == null) return
|
||||
if (isEmpty()) {
|
||||
void setMusicUrl(playMusicInfo.musicInfo)
|
||||
return
|
||||
}
|
||||
setPlay()
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停播放
|
||||
*/
|
||||
export const pause = () => {
|
||||
setPause()
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止播放
|
||||
*/
|
||||
export const stop = () => {
|
||||
setStop()
|
||||
setTimeout(() => {
|
||||
window.app_event.stop()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放、暂停播放切换
|
||||
*/
|
||||
export const togglePlay = () => {
|
||||
if (window.lx.isPlayedStop) window.lx.isPlayedStop = false
|
||||
if (isPlay.value) {
|
||||
pause()
|
||||
} else {
|
||||
play()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './action'
|
||||
export * from './timeoutStop'
|
||||
@@ -0,0 +1,99 @@
|
||||
import { ref, computed, ComputedRef } from '@common/utils/vueTools'
|
||||
import { isPlay } from '@renderer/store/player/state'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
// import { interval, intervalCancel } from '@renderer/utils/ipc'
|
||||
import { stop } from './action'
|
||||
|
||||
const time = ref(-1)
|
||||
|
||||
|
||||
const timeoutTools: {
|
||||
isRunning: boolean
|
||||
// time: number
|
||||
interval: null | number
|
||||
timeout: NodeJS.Timeout | null
|
||||
endTime: number
|
||||
exit: () => void
|
||||
clearTimeout: () => void
|
||||
start: (_time: number) => void
|
||||
} = {
|
||||
isRunning: false,
|
||||
timeout: null,
|
||||
// time: -1,
|
||||
endTime: 0,
|
||||
interval: null,
|
||||
exit() {
|
||||
window.lx.isPlayedStop = true
|
||||
if (!appSetting['player.waitPlayEndStop'] && isPlay.value) {
|
||||
stop()
|
||||
}
|
||||
},
|
||||
clearTimeout() {
|
||||
if (this.interval) {
|
||||
window.clearInterval(this.interval)
|
||||
this.interval = null
|
||||
}
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout)
|
||||
this.timeout = null
|
||||
}
|
||||
|
||||
if (!this.isRunning) return
|
||||
// this.time = -1
|
||||
time.value = -1
|
||||
this.isRunning = false
|
||||
},
|
||||
start(_time: number) {
|
||||
this.clearTimeout()
|
||||
// this.time = _time
|
||||
time.value = _time
|
||||
this.isRunning = true
|
||||
this.endTime = performance.now() + _time * 1000
|
||||
|
||||
this.interval = window.setInterval(() => {
|
||||
// this.endTime = performance.now()
|
||||
// if (this.time > 0) {
|
||||
// this.time--
|
||||
// }
|
||||
time.value = Math.max(0, Math.round((this.endTime - performance.now()) / 1000))
|
||||
}, 1000)
|
||||
this.timeout = setTimeout(() => {
|
||||
this.timeout = null
|
||||
time.value = -1
|
||||
this.clearTimeout()
|
||||
this.exit()
|
||||
}, _time * 1000)
|
||||
},
|
||||
}
|
||||
|
||||
export const startTimeoutStop = (time: number) => {
|
||||
if (window.lx.isPlayedStop) window.lx.isPlayedStop = false
|
||||
timeoutTools.start(time)
|
||||
}
|
||||
export const stopTimeoutStop = () => {
|
||||
console.warn('stopTimeoutStop')
|
||||
if (window.lx.isPlayedStop) window.lx.isPlayedStop = false
|
||||
timeoutTools.clearTimeout()
|
||||
}
|
||||
|
||||
const formatTime = (time: number): string => {
|
||||
// let d = parseInt(time / 86400)
|
||||
// d = d ? d.toString() + ':' : ''
|
||||
// time = time % 86400
|
||||
let h: number | string = Math.trunc(time / 3600)
|
||||
h = h ? h.toString() + ':' : ''
|
||||
time = time % 3600
|
||||
const m = Math.trunc(time / 60).toString().padStart(2, '0')
|
||||
const s = Math.trunc(time % 60).toString().padStart(2, '0')
|
||||
return `${h}${m}:${s}`
|
||||
}
|
||||
export const useTimeout = () => {
|
||||
const timeLabel: ComputedRef<string> = computed(() => {
|
||||
return time.value > 0 ? formatTime(time.value) : ''
|
||||
})
|
||||
|
||||
return {
|
||||
time,
|
||||
timeLabel,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { toRaw, markRawList } from '@common/utils/vueTools'
|
||||
import { qualityList } from '@renderer/store'
|
||||
import { clearPlayedList } from '@renderer/store/player/action'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
export const getPlayType = (highQuality: boolean, musicInfo: LX.Music.MusicInfo | LX.Download.ListItem): LX.Quality | null => {
|
||||
if ('progress' in musicInfo || musicInfo.source == 'local') return null
|
||||
let type: LX.Quality = '128k'
|
||||
let list = qualityList.value[musicInfo.source]
|
||||
if (highQuality && musicInfo.meta._qualitys['320k'] && list && list.includes('320k')) type = '320k'
|
||||
return type
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤列表中已播放的歌曲
|
||||
*/
|
||||
export const filterList = async({ playedList, listId, list, playerMusicInfo }: {
|
||||
playedList: LX.Player.PlayMusicInfo[]
|
||||
listId: string
|
||||
list: Array<LX.Music.MusicInfo | LX.Download.ListItem>
|
||||
playerMusicInfo?: LX.Music.MusicInfo | LX.Download.ListItem
|
||||
}) => {
|
||||
// if (this.list.listName === null) return
|
||||
// console.log(isCheckFile)
|
||||
let { filteredList, canPlayList, playerIndex } = await window.lx.worker.main.filterMusicList({
|
||||
listId,
|
||||
list: list.map(m => toRaw(m)),
|
||||
playedList: toRaw(playedList),
|
||||
savePath: appSetting['download.savePath'],
|
||||
playerMusicInfo: toRaw(playerMusicInfo),
|
||||
})
|
||||
|
||||
if (!filteredList.length && playedList.length) {
|
||||
clearPlayedList()
|
||||
return { filteredList: markRawList(canPlayList), playerIndex }
|
||||
}
|
||||
return { filteredList: markRawList(filteredList), playerIndex }
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { reactive, ref, markRaw } from '@renderer/utils/vueTools'
|
||||
|
||||
export const isInitedList = ref(false)
|
||||
|
||||
export const setInited = () => {
|
||||
isInitedList.value = true
|
||||
}
|
||||
|
||||
export const downloadList = reactive([])
|
||||
export const downloadListMap = new Map()
|
||||
|
||||
export const initDownloadList = list => {
|
||||
downloadList.splice(0, downloadList.length, ...list)
|
||||
downloadListMap.clear()
|
||||
for (const task of list) {
|
||||
downloadListMap.set(task.key, task)
|
||||
}
|
||||
}
|
||||
|
||||
export const downloadStatus = markRaw({
|
||||
RUN: 'run',
|
||||
WAITING: 'waiting',
|
||||
PAUSE: 'pause',
|
||||
ERROR: 'error',
|
||||
COMPLETED: 'completed',
|
||||
})
|
||||
@@ -1,51 +0,0 @@
|
||||
import { ref, reactive, shallowRef, markRaw } from '@renderer/utils/vueTools'
|
||||
import { windowSizeList as configWindowSizeList, themes as configThemes, themeLights as themeLightIds, themeDarks as themeDarkIds } from '@common/config'
|
||||
import { version } from '../../../../package.json'
|
||||
process.versions.app = version
|
||||
|
||||
export const apiSource = ref(null)
|
||||
export const isShowPact = window.isShowPact = ref(false)
|
||||
export const proxy = reactive({})
|
||||
export const versionInfo = window.versionInfo = reactive({
|
||||
version,
|
||||
newVersion: null,
|
||||
showModal: false,
|
||||
isError: false,
|
||||
isTimeOut: false,
|
||||
isUnknow: false,
|
||||
isDownloaded: false,
|
||||
isDownloading: false,
|
||||
isLatestVer: false,
|
||||
downloadProgress: null,
|
||||
})
|
||||
export const userApi = reactive({
|
||||
list: [],
|
||||
status: false,
|
||||
message: 'initing',
|
||||
apis: {},
|
||||
})
|
||||
export const sync = window.sync = reactive({
|
||||
enable: false,
|
||||
isShowSyncMode: false,
|
||||
deviceName: '',
|
||||
status: {
|
||||
status: false,
|
||||
message: '',
|
||||
address: [],
|
||||
code: '',
|
||||
devices: [],
|
||||
},
|
||||
})
|
||||
export const isFullscreen = ref(false)
|
||||
|
||||
export const windowSizeList = markRaw(configWindowSizeList)
|
||||
export const themes = markRaw(configThemes)
|
||||
export const themeLights = markRaw(configThemes.filter(t => themeLightIds.includes(t.id)))
|
||||
export const themeDarks = markRaw(configThemes.filter(t => themeDarkIds.includes(t.id)))
|
||||
export const themeShouldUseDarkColors = ref(window.shouldUseDarkColors)
|
||||
delete window.shouldUseDarkColors
|
||||
|
||||
export const qualityList = shallowRef({})
|
||||
export const setQualityList = _qualityList => {
|
||||
qualityList.value = _qualityList
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
import { reactive, ref, markRaw } from '@renderer/utils/vueTools'
|
||||
|
||||
// const TEMP_LIST = 'TEMP_LIST'
|
||||
|
||||
export const isInitedList = ref(false)
|
||||
|
||||
export const setInited = () => {
|
||||
isInitedList.value = true
|
||||
}
|
||||
|
||||
export const allList = window.allList = markRaw({})
|
||||
|
||||
export const allListInit = (newLists) => {
|
||||
const newIds = [defaultList.id, loveList.id, tempList.id, ...newLists.userList.map(l => l.id)]
|
||||
for (const id of Object.keys(allList)) {
|
||||
if (newIds.includes(id)) continue
|
||||
delete allList[id]
|
||||
}
|
||||
allListUpdate(defaultList.id, newLists.defaultList.list)
|
||||
allListUpdate(loveList.id, newLists.loveList.list)
|
||||
if (newLists.tempList) {
|
||||
allListUpdate(tempList.id, newLists.tempList.list)
|
||||
tempList.meta = newLists.tempList.meta ?? {}
|
||||
}
|
||||
userLists.splice(0, userLists.length)
|
||||
for (const { list, ...listInfo } of newLists.userList) {
|
||||
allListUpdate(listInfo.id, list)
|
||||
userLists.push(listInfo)
|
||||
}
|
||||
}
|
||||
export const allListUpdate = (id, list) => {
|
||||
if (allList[id]) {
|
||||
allList[id].splice(0, allList[id].length, ...list)
|
||||
} else {
|
||||
allList[id] = reactive(list)
|
||||
}
|
||||
}
|
||||
export const allListRemove = id => {
|
||||
delete allList[id]
|
||||
}
|
||||
|
||||
export const defaultList = reactive({
|
||||
id: 'default',
|
||||
name: '试听列表',
|
||||
})
|
||||
|
||||
export const loveList = reactive({
|
||||
id: 'love',
|
||||
name: '我的收藏',
|
||||
})
|
||||
|
||||
export const tempList = reactive({
|
||||
id: 'temp',
|
||||
name: '临时列表',
|
||||
meta: {},
|
||||
})
|
||||
|
||||
export const userLists = window.userLists = reactive([])
|
||||
|
||||
export const addUserList = ({
|
||||
name,
|
||||
id,
|
||||
list,
|
||||
source,
|
||||
sourceListId,
|
||||
position,
|
||||
locationUpdateTime,
|
||||
}) => {
|
||||
if (position == null) {
|
||||
userLists.push({
|
||||
name,
|
||||
id,
|
||||
source,
|
||||
sourceListId,
|
||||
locationUpdateTime,
|
||||
})
|
||||
} else {
|
||||
userLists.splice(position + 1, 0, {
|
||||
name,
|
||||
id,
|
||||
source,
|
||||
sourceListId,
|
||||
locationUpdateTime,
|
||||
})
|
||||
}
|
||||
allListUpdate(id, list)
|
||||
}
|
||||
|
||||
export const updateList = ({
|
||||
name,
|
||||
id,
|
||||
list,
|
||||
source,
|
||||
sourceListId,
|
||||
meta,
|
||||
locationUpdateTime,
|
||||
}) => {
|
||||
let targetList
|
||||
switch (id) {
|
||||
case defaultList.id:
|
||||
case loveList.id:
|
||||
break
|
||||
case tempList.id:
|
||||
tempList.meta = meta || {}
|
||||
break
|
||||
default:
|
||||
targetList = userLists.find(l => l.id == id)
|
||||
targetList.name = name
|
||||
targetList.source = source
|
||||
targetList.sourceListId = sourceListId
|
||||
if (locationUpdateTime) targetList.locationUpdateTime = locationUpdateTime
|
||||
break
|
||||
}
|
||||
allListUpdate(id, list)
|
||||
}
|
||||
|
||||
export const removeUserList = id => {
|
||||
const index = userLists.findIndex(l => l.id == id)
|
||||
if (index < 0) return
|
||||
userLists.splice(index, 1)
|
||||
allListRemove(id)
|
||||
}
|
||||
|
||||
export const getList = id => {
|
||||
return allList[id] ?? []
|
||||
}
|
||||
|
||||
export const fetchingListStatus = reactive({})
|
||||
export const setFetchingListStatus = (id, status) => {
|
||||
fetchingListStatus[id] = status
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { reactive } from '@renderer/utils/vueTools'
|
||||
|
||||
export const lyric = reactive({
|
||||
lines: [],
|
||||
text: '',
|
||||
line: 0,
|
||||
offset: 0, // 歌词延迟
|
||||
tempOffset: 0, // 歌词临时延迟
|
||||
})
|
||||
|
||||
export const setLines = lines => {
|
||||
lyric.lines = lines
|
||||
}
|
||||
export const setText = (text, line) => {
|
||||
lyric.text = text
|
||||
lyric.line = line
|
||||
}
|
||||
export const setOffset = offset => {
|
||||
lyric.offset = offset
|
||||
}
|
||||
export const setTempOffset = offset => {
|
||||
lyric.tempOffset = offset
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { reactive } from '@renderer/utils/vueTools'
|
||||
import { formatPlayTime2 } from '@renderer/utils'
|
||||
|
||||
export const playProgress = reactive({
|
||||
nowPlayTime: 0,
|
||||
maxPlayTime: 0,
|
||||
progress: 0,
|
||||
nowPlayTimeStr: '00:00',
|
||||
maxPlayTimeStr: '00:00',
|
||||
})
|
||||
|
||||
export const setNowPlayTime = time => {
|
||||
playProgress.nowPlayTime = time
|
||||
playProgress.nowPlayTimeStr = formatPlayTime2(time)
|
||||
playProgress.progress = playProgress.maxPlayTime ? time / playProgress.maxPlayTime : 0
|
||||
}
|
||||
|
||||
export const setMaxplayTime = time => {
|
||||
playProgress.maxPlayTime = time
|
||||
playProgress.maxPlayTimeStr = formatPlayTime2(time)
|
||||
playProgress.progress = time ? playProgress.nowPlayTime / time : 0
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
import { reactive, ref, shallowRef } from '@renderer/utils/vueTools'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
|
||||
export const musicInfo = window.musicInfo = reactive({
|
||||
songmid: null,
|
||||
img: null,
|
||||
lrc: null,
|
||||
tlrc: null,
|
||||
rlrc: null,
|
||||
lxlrc: null,
|
||||
rawlrc: null,
|
||||
url: null,
|
||||
name: '',
|
||||
singer: '',
|
||||
album: '',
|
||||
})
|
||||
const musicInfoKeys = Object.keys(musicInfo)
|
||||
export const setMusicInfo = _musicInfo => {
|
||||
for (const key of musicInfoKeys) {
|
||||
if (_musicInfo[key] !== undefined) {
|
||||
musicInfo[key] = _musicInfo[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const musicInfoItem = shallowRef({})
|
||||
export const setMusicInfoItem = musicInfo => {
|
||||
musicInfoItem.value = musicInfo.key ? musicInfo.metadata.musicInfo : musicInfo
|
||||
}
|
||||
|
||||
|
||||
export const isPlay = ref(false)
|
||||
export const setPlay = val => {
|
||||
isPlay.value = val
|
||||
}
|
||||
|
||||
export const status = ref('')
|
||||
export const setStatus = val => {
|
||||
status.value = val
|
||||
}
|
||||
|
||||
|
||||
export const statusText = ref('')
|
||||
export const setStatusText = val => {
|
||||
statusText.value = val
|
||||
}
|
||||
|
||||
export const setAllStatus = val => {
|
||||
status.value = val
|
||||
statusText.value = val
|
||||
}
|
||||
|
||||
|
||||
export const isShowPlayerDetail = ref(false)
|
||||
export const setShowPlayerDetail = val => {
|
||||
isShowPlayerDetail.value = val
|
||||
}
|
||||
|
||||
export const isShowPlayComment = ref(false)
|
||||
export const setShowPlayComment = val => {
|
||||
isShowPlayComment.value = val
|
||||
}
|
||||
|
||||
export const isShowLrcSelectContent = ref(false)
|
||||
export const setShowPlayLrcSelectContentLrc = val => {
|
||||
isShowLrcSelectContent.value = val
|
||||
}
|
||||
|
||||
|
||||
export const playMusicInfo = reactive({
|
||||
listId: null, // 当前播放歌曲的列表 id
|
||||
musicInfo: null, // 当前播放歌曲的歌曲信息
|
||||
isTempPlay: false, // 是否属于 “稍后播放”
|
||||
})
|
||||
export const playInfo = reactive({
|
||||
playIndex: -1, // 当前正在播放歌曲 index
|
||||
playListId: null, // 播放器的播放列表 id
|
||||
listPlayIndex: -1, // 播放器播放歌曲 index
|
||||
})
|
||||
|
||||
// 设置播放器的播放列表
|
||||
export const setPlayList = listId => {
|
||||
playInfo.playListId = listId
|
||||
}
|
||||
|
||||
// 更新播放位置
|
||||
export const updatePlayIndex = () => {
|
||||
const indexInfo = getPlayIndex(playMusicInfo.listId, playMusicInfo.musicInfo, playMusicInfo.isTempPlay)
|
||||
// console.log(indexInfo)
|
||||
playInfo.playIndex = indexInfo.playIndex
|
||||
playInfo.listPlayIndex = indexInfo.listPlayIndex
|
||||
|
||||
return indexInfo
|
||||
}
|
||||
|
||||
export const getPlayIndex = (listId, musicInfo, isTempPlay) => {
|
||||
const playerList = getList(playInfo.playListId)
|
||||
|
||||
// if (listIndex < 0) throw new Error('music info not found')
|
||||
// playInfo.playIndex = listIndex
|
||||
|
||||
let playIndex = -1
|
||||
let listPlayIndex = -1
|
||||
if (playerList?.length) {
|
||||
listPlayIndex = Math.min(playInfo.listPlayIndex, playerList.length - 1)
|
||||
}
|
||||
|
||||
const list = getList(listId)
|
||||
if (list?.length && musicInfo) {
|
||||
if (musicInfo.key) { // 已下载的歌曲
|
||||
const currentKey = musicInfo.key
|
||||
playIndex = list.findIndex(m => m.key == currentKey)
|
||||
} else {
|
||||
const currentSongmid = musicInfo.songmid
|
||||
playIndex = list.findIndex(m => m.songmid == currentSongmid)
|
||||
}
|
||||
if (!isTempPlay) {
|
||||
if (playIndex < 0) {
|
||||
listPlayIndex = listPlayIndex < 1 ? (list.length - 1) : (listPlayIndex - 1)
|
||||
} else {
|
||||
listPlayIndex = playIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
playIndex,
|
||||
listPlayIndex,
|
||||
}
|
||||
}
|
||||
|
||||
// 设置当前播放歌曲的信息
|
||||
export const setPlayMusicInfo = (listId, musicInfo, isTempPlay = false) => {
|
||||
playMusicInfo.listId = listId
|
||||
playMusicInfo.musicInfo = musicInfo
|
||||
playMusicInfo.isTempPlay = isTempPlay
|
||||
if (musicInfo == null) {
|
||||
playInfo.playIndex = -1
|
||||
playInfo.playListId = null
|
||||
playInfo.listPlayIndex = -1
|
||||
return
|
||||
}
|
||||
|
||||
const { playIndex, listPlayIndex } = getPlayIndex(listId, musicInfo, isTempPlay)
|
||||
|
||||
playInfo.playIndex = playIndex
|
||||
playInfo.listPlayIndex = listPlayIndex
|
||||
|
||||
setMusicInfoItem(musicInfo)
|
||||
// console.log(playInfo)
|
||||
}
|
||||
|
||||
export const playedList = window.playedList = reactive([])
|
||||
export const addPlayedList = (item) => {
|
||||
if (playedList.some(m => m.musicInfo === item.musicInfo)) return
|
||||
playedList.push(item)
|
||||
}
|
||||
export const removePlayedList = (index) => {
|
||||
playedList.splice(index, 1)
|
||||
}
|
||||
export const clearPlayedList = () => {
|
||||
playedList.splice(0, playedList.length)
|
||||
}
|
||||
|
||||
export const tempPlayList = reactive([])
|
||||
export const addTempPlayList = (list) => {
|
||||
const topList = []
|
||||
const bottomList = list.filter(({ isTop, ...musicInfo }) => {
|
||||
if (isTop) {
|
||||
topList.push(musicInfo)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
if (topList.length) tempPlayList.unshift(...topList.map(({ musicInfo, listId }) => ({ musicInfo, listId, isTempPlay: true })))
|
||||
if (bottomList.length) tempPlayList.push(...bottomList.map(({ musicInfo, listId }) => ({ musicInfo, listId, isTempPlay: true })))
|
||||
}
|
||||
export const removeTempPlayList = (index) => {
|
||||
tempPlayList.splice(index, 1)
|
||||
}
|
||||
export const clearTempPlayeList = () => {
|
||||
tempPlayList.splice(0, tempPlayList.length)
|
||||
}
|
||||
|
||||
window.playInfo = playInfo
|
||||
window.playMusicInfo = playMusicInfo
|
||||
@@ -1,7 +0,0 @@
|
||||
import { getList as getMyList } from './list'
|
||||
import { downloadList } from './download'
|
||||
|
||||
|
||||
export const getList = listId => {
|
||||
return listId == 'download' ? downloadList : getMyList(listId)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { ref } from '@renderer/utils/vueTools'
|
||||
|
||||
|
||||
export const volume = ref(0)
|
||||
export const isMute = ref(false)
|
||||
|
||||
export const setVolume = num => {
|
||||
volume.value = num
|
||||
}
|
||||
|
||||
export const setMute = flag => {
|
||||
isMute.value = flag
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
import { useAction, useCommit } from '@renderer/utils/vueTools'
|
||||
import { tempList } from '@renderer/core/share/list'
|
||||
|
||||
const getListPlayIndex = (list, index) => {
|
||||
if (index == null) {
|
||||
index = 1
|
||||
} else {
|
||||
index = parseInt(index)
|
||||
if (Number.isNaN(index)) {
|
||||
index = 1
|
||||
} else {
|
||||
if (index < 1) index = 1
|
||||
else if (index > list.length) index = list.length
|
||||
}
|
||||
}
|
||||
return index - 1
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const getListDetail = useAction('songList', 'getListDetail')
|
||||
const getListDetailAll = useAction('songList', 'getListDetailAll')
|
||||
const setTempList = useCommit('player', 'setTempList')
|
||||
const updateTempList = useCommit('player', 'updateTempList')
|
||||
|
||||
const playSongListDetail = async(source, link, playIndex) => {
|
||||
console.log(source, link, playIndex)
|
||||
if (link == null) return
|
||||
let isPlayingList = false
|
||||
const id = decodeURIComponent(link)
|
||||
const playListId = `${source}__${decodeURIComponent(link)}`
|
||||
let list
|
||||
try {
|
||||
list = await getListDetail({ source, id, page: 1 })
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
if (list.length > playIndex) {
|
||||
isPlayingList = true
|
||||
setTempList({
|
||||
list,
|
||||
index: getListPlayIndex(list, playIndex),
|
||||
id: playListId,
|
||||
})
|
||||
}
|
||||
getListDetailAll({ source, id }).then(list => {
|
||||
if (isPlayingList) {
|
||||
if (tempList.meta.id == id) {
|
||||
updateTempList({
|
||||
list,
|
||||
id: playListId,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
setTempList({
|
||||
list,
|
||||
index: getListPlayIndex(list, playIndex),
|
||||
id: playListId,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (source, link, playIndex) => {
|
||||
playSongListDetail(source, link, playIndex)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { playList } from '@renderer/core/player'
|
||||
import { setTempList } from '@renderer/store/list/action'
|
||||
import { tempList, tempListMeta } from '@renderer/store/list/state'
|
||||
import { getListDetail, getListDetailAll } from '@renderer/store/songList/action'
|
||||
|
||||
const getListPlayIndex = (list: LX.Music.MusicInfoOnline[], index?: number) => {
|
||||
if (index == null) {
|
||||
index = 1
|
||||
} else {
|
||||
if (index < 1) index = 1
|
||||
else if (index > list.length) index = list.length
|
||||
}
|
||||
return index - 1
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const playSongListDetail = async(source: LX.OnlineSource, link: string, playIndex?: number) => {
|
||||
// console.log(source, link, playIndex)
|
||||
if (link == null) return
|
||||
let isPlayingList = false
|
||||
const id = decodeURIComponent(link)
|
||||
const playListId = `${source}__${decodeURIComponent(link)}`
|
||||
let list = (await getListDetail(id, source, 1)).list
|
||||
if (playIndex != null && list.length > playIndex) {
|
||||
isPlayingList = true
|
||||
await setTempList(playListId, list)
|
||||
playList(tempList.id, getListPlayIndex(list, playIndex))
|
||||
}
|
||||
list = await getListDetailAll(id, source)
|
||||
if (isPlayingList) {
|
||||
if (tempListMeta.id == id) await setTempList(playListId, list)
|
||||
} else {
|
||||
await setTempList(playListId, list)
|
||||
playList(tempList.id, getListPlayIndex(list, playIndex))
|
||||
}
|
||||
}
|
||||
|
||||
return async(source: LX.OnlineSource, link: string, playIndex?: number) => {
|
||||
try {
|
||||
await playSongListDetail(source, link, playIndex)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw new Error('Get play list failed.')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
import { isLinux } from '@common/utils'
|
||||
import { getEnvParams, setIgnoreMouseEvents } from '@renderer/utils/tools'
|
||||
|
||||
import { useRefGetter } from '@renderer/utils/vueTools'
|
||||
import { sync, apiSource, proxy, isFullscreen } from '@renderer/core/share'
|
||||
|
||||
import useSync from './useSync'
|
||||
import useUpdate from './useUpdate'
|
||||
import useDataInit from './useDataInit'
|
||||
import useHandleEnvParams from './useHandleEnvParams'
|
||||
import useEventListener from './useEventListener'
|
||||
import useDeepLink from './useDeepLink'
|
||||
import usePlayer from './usePlayer'
|
||||
import useListAutoUpdate from './useListAutoUpdate'
|
||||
|
||||
|
||||
export default () => {
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
|
||||
const setting = useRefGetter('setting')
|
||||
|
||||
sync.enable = setting.value.sync.enable
|
||||
apiSource.value = setting.value.apiSource
|
||||
Object.assign(proxy, setting.value.network.proxy)
|
||||
isFullscreen.value = setting.value.startInFullscreen
|
||||
|
||||
const dieableIgnoreMouseEvents = () => {
|
||||
if (window.dt) return
|
||||
setIgnoreMouseEvents(false)
|
||||
}
|
||||
const enableIgnoreMouseEvents = () => {
|
||||
if (window.dt) return
|
||||
setIgnoreMouseEvents(true)
|
||||
}
|
||||
|
||||
useUpdate(setting)
|
||||
useSync()
|
||||
useEventListener({
|
||||
dieableIgnoreMouseEvents,
|
||||
enableIgnoreMouseEvents,
|
||||
setting,
|
||||
isProd,
|
||||
isLinux,
|
||||
})
|
||||
const initPlayer = usePlayer({ setting })
|
||||
const handleEnvParams = useHandleEnvParams()
|
||||
const initData = useDataInit({
|
||||
setting,
|
||||
})
|
||||
const initDeepLink = useDeepLink()
|
||||
const handleListAutoUpdate = useListAutoUpdate()
|
||||
|
||||
|
||||
getEnvParams().then(envParams => {
|
||||
// 移除代理相关的环境变量设置,防止请求库自动应用它们
|
||||
// eslint-disable-next-line no-undef
|
||||
const processEnv = ENVIRONMENT
|
||||
for (const key of Object.keys(processEnv)) {
|
||||
if (/^(?:http_proxy|https_proxy|NO_PROXY)$/i.test(key)) delete processEnv[key]
|
||||
}
|
||||
const envProxy = envParams.cmdParams['proxy-server']
|
||||
if (envProxy && typeof envProxy == 'string') {
|
||||
const [host, port = ''] = envProxy.split(':')
|
||||
proxy.envProxy = {
|
||||
host,
|
||||
port,
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化我的列表、下载列表等数据
|
||||
initData().then(() => {
|
||||
initPlayer()
|
||||
handleEnvParams(envParams) // 处理传入的启动参数
|
||||
initDeepLink(envParams)
|
||||
handleListAutoUpdate()
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { checkUpdate, getEnvParams, getViewPrevState, sendInited } from '@renderer/utils/ipc'
|
||||
|
||||
import { proxy, isFullscreen, themeId } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
import useSync from './useSync'
|
||||
import useUpdate from './useUpdate'
|
||||
import useDataInit from './useDataInit'
|
||||
// import useHandleEnvParams from './useHandleEnvParams'
|
||||
import useEventListener from './useEventListener'
|
||||
import useDeeplink from './useDeeplink'
|
||||
import usePlayer from './usePlayer'
|
||||
import handleListAutoUpdate from './listAutoUpdate'
|
||||
import { useRouter } from '@common/utils/vueRouter'
|
||||
import useSettingSync from './useSettingSync'
|
||||
|
||||
|
||||
export default () => {
|
||||
// apiSource.value = appSetting['common.apiSource']
|
||||
proxy.enable = appSetting['network.proxy.enable']
|
||||
proxy.host = appSetting['network.proxy.host']
|
||||
proxy.port = appSetting['network.proxy.port']
|
||||
proxy.username = appSetting['network.proxy.username']
|
||||
proxy.password = appSetting['network.proxy.password']
|
||||
isFullscreen.value = appSetting['common.startInFullscreen']
|
||||
themeId.value = appSetting['theme.id']
|
||||
|
||||
const router = useRouter()
|
||||
const initSyncService = useSync()
|
||||
useEventListener()
|
||||
const initPlayer = usePlayer()
|
||||
// const handleEnvParams = useHandleEnvParams()
|
||||
const initData = useDataInit()
|
||||
const initDeeplink = useDeeplink()
|
||||
// const handleListAutoUpdate = useListAutoUpdate()
|
||||
|
||||
useUpdate()
|
||||
useSettingSync()
|
||||
|
||||
void getEnvParams().then(envParams => {
|
||||
// 移除代理相关的环境变量设置,防止请求库自动应用它们
|
||||
// eslint-disable-next-line no-undef
|
||||
// const processEnv = ENVIRONMENT
|
||||
// for (const key of Object.keys(processEnv)) {
|
||||
// // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
// if (/^(?:http_proxy|https_proxy|NO_PROXY)$/i.test(key)) delete processEnv[key]
|
||||
// }
|
||||
const envProxy = envParams.cmdParams['proxy-server']
|
||||
if (envProxy && typeof envProxy == 'string') {
|
||||
const [host, port = ''] = envProxy.split(':')
|
||||
proxy.envProxy = {
|
||||
host,
|
||||
port,
|
||||
}
|
||||
}
|
||||
|
||||
void getViewPrevState().then(state => {
|
||||
void router.push({ path: state.url, query: state.query })
|
||||
})
|
||||
|
||||
// 初始化我的列表、下载列表等数据
|
||||
void initData().then(() => {
|
||||
initPlayer()
|
||||
// handleEnvParams(envParams) // 处理传入的启动参数
|
||||
void initDeeplink(envParams)
|
||||
void initSyncService()
|
||||
handleListAutoUpdate()
|
||||
if (window.lx.isDev) checkUpdate()
|
||||
|
||||
sendInited()
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { getListUpdateInfo } from '@renderer/utils/data'
|
||||
import { userLists } from '@renderer/store/list/state'
|
||||
import syncSourceList from '@renderer/store/list/syncSourceList'
|
||||
|
||||
const handleSyncSourceList = async(waitUpdateLists: LX.List.UserListInfo[]) => {
|
||||
if (!waitUpdateLists.length) return
|
||||
const targetListInfo = waitUpdateLists.shift() as LX.List.UserListInfo
|
||||
// console.log(targetListInfo)
|
||||
try {
|
||||
await syncSourceList(targetListInfo)
|
||||
} catch {}
|
||||
void handleSyncSourceList(waitUpdateLists)
|
||||
}
|
||||
|
||||
export default () => {
|
||||
void getListUpdateInfo().then(listUpdateInfo => {
|
||||
const waitUpdateLists = Object.entries(listUpdateInfo)
|
||||
.map(([id, info]) => info.isAutoUpdate && userLists.find(l => l.id == id))
|
||||
.filter(_ => _) as LX.List.UserListInfo[]
|
||||
for (let i = 2; i > 0; i--) {
|
||||
void handleSyncSourceList(waitUpdateLists)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
import { useCommit, useRefGetter } from '@renderer/utils/vueTools'
|
||||
import { getPlayList } from '@renderer/utils'
|
||||
import { getPlayInfo, getSearchHistoryList } from '@renderer/utils/tools'
|
||||
import { initListPosition, initListPrevSelectId, initListUpdateInfo } from '@renderer/utils/data'
|
||||
import music from '@renderer/utils/music'
|
||||
import { log } from '@common/utils'
|
||||
import {
|
||||
defaultList as stateDefaultList,
|
||||
loveList as stateloveList,
|
||||
userLists as stateUserLists,
|
||||
tempList as stateTempList,
|
||||
} from '@renderer/core/share/list'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
import { downloadStatus, downloadList } from '@renderer/core/share/download'
|
||||
|
||||
|
||||
import useSaveData from './useSaveData'
|
||||
import useInitUserApi from './useInitUserApi'
|
||||
|
||||
const useListInit = ({
|
||||
saveMyListThrottle,
|
||||
}) => {
|
||||
const initList = useCommit('list', 'initList')
|
||||
const updateDownloadList = useCommit('download', 'initDownloadList')
|
||||
|
||||
const initMyList = ({ defaultList, loveList, userList, tempList }) => {
|
||||
if (!defaultList) defaultList = { ...stateDefaultList }
|
||||
if (!loveList) loveList = { ...stateloveList }
|
||||
if (!tempList) tempList = { ...stateTempList }
|
||||
if (userList) {
|
||||
let needSave = false
|
||||
const getListId = id => id.includes('.') ? getListId(id.substring(0, id.lastIndexOf('_'))) : id
|
||||
userList.forEach(l => {
|
||||
if (!l.id.includes('__') || l.source) return
|
||||
let [source, id] = l.id.split('__')
|
||||
id = getListId(id)
|
||||
l.source = source
|
||||
l.sourceListId = id
|
||||
if (!needSave) needSave = true
|
||||
})
|
||||
if (needSave) saveMyListThrottle({ userList })
|
||||
} else {
|
||||
userList = [...stateUserLists]
|
||||
}
|
||||
|
||||
if (!defaultList.list) defaultList.list = []
|
||||
if (!loveList.list) loveList.list = []
|
||||
if (!tempList.list) tempList.list = []
|
||||
initList({ defaultList, loveList, userList, tempList })
|
||||
}
|
||||
|
||||
const initDownloadList = list => {
|
||||
if (list) {
|
||||
list = list.filter(item => item?.key)
|
||||
for (const item of list) {
|
||||
if (item.status == downloadStatus.RUN || item.status == downloadStatus.WAITING) {
|
||||
item.status = downloadStatus.PAUSE
|
||||
item.statusText = '暂停下载'
|
||||
}
|
||||
|
||||
if (!item.metadata) { // 转换v1.15.3及以前的任务信息
|
||||
if (item.name == null) {
|
||||
item.name = `${item.musicInfo.name} - ${item.musicInfo.singer}`
|
||||
item.songmid = item.musicInfo.songmid
|
||||
}
|
||||
item.metadata = {
|
||||
musicInfo: item.musicInfo,
|
||||
url: item.url,
|
||||
type: item.type,
|
||||
ext: item.ext,
|
||||
fileName: item.fileName,
|
||||
filePath: item.filePath,
|
||||
}
|
||||
delete item.musicInfo
|
||||
delete item.url
|
||||
delete item.type
|
||||
delete item.ext
|
||||
delete item.fileName
|
||||
delete item.filePath
|
||||
}
|
||||
}
|
||||
updateDownloadList(list)
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
return getPlayList().then(({ defaultList, loveList, userList, tempList, downloadList }) => {
|
||||
initMyList({ defaultList, loveList, userList, tempList })
|
||||
initDownloadList(downloadList) // 初始化下载列表
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const usePlayInfoInit = () => {
|
||||
const setPlayList = useCommit('player', 'setList')
|
||||
|
||||
return () => {
|
||||
return getPlayInfo().then(info => {
|
||||
window.restorePlayInfo = null
|
||||
if (!info?.listId || info.index < 0) return
|
||||
const list = getList(info.listId)
|
||||
if (!list || !list[info.index]) return
|
||||
window.restorePlayInfo = info
|
||||
setPlayList({
|
||||
listId: info.listId,
|
||||
index: info.index,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const useSearchHistoryInit = () => {
|
||||
const setSearchHistoryList = useCommit('search', 'setHistory')
|
||||
return saveSearchHistoryListThrottle => {
|
||||
return getSearchHistoryList().then(historyList => {
|
||||
if (historyList == null) {
|
||||
historyList = []
|
||||
saveSearchHistoryListThrottle(historyList)
|
||||
} else {
|
||||
setSearchHistoryList(historyList)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default ({
|
||||
setting,
|
||||
}) => {
|
||||
const searchHistoryList = useRefGetter('search', 'historyList')
|
||||
|
||||
// 数据保存初始化
|
||||
const { saveMyListThrottle, saveSearchHistoryListThrottle } = useSaveData({
|
||||
setting,
|
||||
searchHistoryList,
|
||||
})
|
||||
|
||||
const initUserApi = useInitUserApi({ setting })
|
||||
|
||||
// 列表初始化
|
||||
const initList = useListInit({
|
||||
saveMyListThrottle,
|
||||
})
|
||||
|
||||
|
||||
// 播放信息初始化
|
||||
const initPlayInfo = usePlayInfoInit()
|
||||
|
||||
// 搜索历史初始化
|
||||
const initSearchHistory = useSearchHistoryInit()
|
||||
|
||||
return async() => {
|
||||
await Promise.all([
|
||||
initListPosition(), // 列表位置记录
|
||||
initListPrevSelectId(), // 上次选中的列表记录
|
||||
initListUpdateInfo(), // 列表更新设置
|
||||
initUserApi(), // 自定义API
|
||||
]).catch(err => log.error(err))
|
||||
music.init() // 初始化音乐sdk
|
||||
await initList().catch(err => log.error(err)) // 初始化列表
|
||||
await initPlayInfo(downloadList).catch(err => log.error(err)) // 初始化上次的歌曲播放信息
|
||||
await initSearchHistory(saveSearchHistoryListThrottle).catch(err => log.error(err)) // 初始化搜索历史记录
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { getPlayInfo } from '@renderer/utils/ipc'
|
||||
import music from '@renderer/utils/musicSdk'
|
||||
import { log } from '@common/utils'
|
||||
import { getListMusics, getUserLists, registerAction } from '@renderer/store/list/action'
|
||||
|
||||
|
||||
import useInitUserApi from './useInitUserApi'
|
||||
import { play, playList } from '@renderer/core/player'
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
const initPrevPlayInfo = async() => {
|
||||
const info = await getPlayInfo()
|
||||
window.lx.restorePlayInfo = null
|
||||
if (!info?.listId || info.index < 0) return
|
||||
const list = await getListMusics(info.listId)
|
||||
if (!list || !list[info.index]) return
|
||||
window.lx.restorePlayInfo = info
|
||||
playList(info.listId, info.index)
|
||||
|
||||
if (appSetting['player.startupAutoPlay']) setTimeout(play)
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const initUserApi = useInitUserApi()
|
||||
|
||||
let unregister: null | (() => void) = null
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (unregister) unregister()
|
||||
})
|
||||
|
||||
return async() => {
|
||||
await Promise.all([
|
||||
initUserApi(), // 自定义API
|
||||
]).catch(err => log.error(err))
|
||||
void music.init() // 初始化音乐sdk
|
||||
unregister = registerAction((ids) => {
|
||||
window.app_event.myListUpdate(ids)
|
||||
})
|
||||
window.lxData.userLists = await getUserLists() // 获取用户列表
|
||||
await initPrevPlayInfo().catch(err => log.error(err)) // 初始化上次的歌曲播放信息
|
||||
}
|
||||
}
|
||||
+28
-26
@@ -1,6 +1,5 @@
|
||||
import { onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
import { base as eventBaseName } from '@renderer/event/names'
|
||||
import { getEnvParams, clearEnvParamsDeeplink } from '@renderer/utils/tools'
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { clearEnvParamsDeeplink, focusWindow, onDeeplink } from '@renderer/utils/ipc'
|
||||
|
||||
import { useDialog } from './utils'
|
||||
import useMusicAction from './useMusicAction'
|
||||
@@ -15,11 +14,17 @@ export default () => {
|
||||
const handleSonglistAction = useSonglistAction()
|
||||
|
||||
|
||||
const handleLinkAction = link => {
|
||||
const handleLinkAction = async(link: string) => {
|
||||
// console.log(link)
|
||||
const [url, search] = link.split('?')
|
||||
const [type, action, ...paths] = url.replace('lxmusic://', '').split('/')
|
||||
const params = {}
|
||||
const params: {
|
||||
paths: string[]
|
||||
data?: any
|
||||
[key: string]: any
|
||||
} = {
|
||||
paths: [],
|
||||
}
|
||||
if (search) {
|
||||
for (const param of search.split('&')) {
|
||||
const [key, value] = param.split('=')
|
||||
@@ -34,39 +39,36 @@ export default () => {
|
||||
handleMusicAction(action, params)
|
||||
break
|
||||
case 'songlist':
|
||||
handleSonglistAction(action, params)
|
||||
await handleSonglistAction(action, params)
|
||||
break
|
||||
default: throw new Error('Unknown type: ' + type)
|
||||
}
|
||||
}
|
||||
|
||||
const handleFocus = () => {
|
||||
const rDeeplink = onDeeplink(async({ params: link }) => {
|
||||
console.log(link)
|
||||
if (!isInited) return
|
||||
|
||||
getEnvParams().then(envParams => {
|
||||
if (!envParams.deeplink) return
|
||||
clearEnvParamsDeeplink()
|
||||
try {
|
||||
handleLinkAction(envParams.deeplink)
|
||||
} catch (err) {
|
||||
showErrorDialog(err.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.eventHub.on(eventBaseName.focus, handleFocus)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventBaseName.focus, handleFocus)
|
||||
clearEnvParamsDeeplink()
|
||||
try {
|
||||
await handleLinkAction(link)
|
||||
} catch (err: any) {
|
||||
showErrorDialog(err.message)
|
||||
focusWindow()
|
||||
}
|
||||
})
|
||||
|
||||
return envParams => {
|
||||
onBeforeUnmount(() => {
|
||||
rDeeplink()
|
||||
})
|
||||
|
||||
return async(envParams: LX.EnvParams) => {
|
||||
if (envParams.deeplink) {
|
||||
clearEnvParamsDeeplink()
|
||||
try {
|
||||
handleLinkAction(envParams.deeplink)
|
||||
} catch (err) {
|
||||
await handleLinkAction(envParams.deeplink)
|
||||
} catch (err: any) {
|
||||
showErrorDialog(err.message)
|
||||
focusWindow()
|
||||
}
|
||||
}
|
||||
isInited = true
|
||||
@@ -1,9 +1,14 @@
|
||||
import { useCommit, useAction, useRouter, markRaw } from '@renderer/utils/vueTools'
|
||||
import { decodeName } from '@renderer/utils'
|
||||
// import { allList, defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
import { playMusicInfo, isShowPlayerDetail, setShowPlayerDetail } from '@renderer/core/share/player'
|
||||
import { markRaw } from '@common/utils/vueTools'
|
||||
import { useRouter } from '@common/utils/vueRouter'
|
||||
import { decodeName } from '@common/utils/common'
|
||||
// import { allList, defaultList, loveList, userLists } from '@renderer/store/list'
|
||||
import { playMusicInfo, isShowPlayerDetail } from '@renderer/store/player/state'
|
||||
import { setShowPlayerDetail, addTempPlayList } from '@renderer/store/player/action'
|
||||
|
||||
import { dataVerify, qualityFilter, sources } from './utils'
|
||||
import { focusWindow } from '@renderer/utils/ipc'
|
||||
import { playNext } from '@renderer/core/player/action'
|
||||
import { toNewMusicInfo } from '@common/utils/tools'
|
||||
|
||||
const useSearchMusic = () => {
|
||||
const router = useRouter()
|
||||
@@ -39,13 +44,11 @@ const useSearchMusic = () => {
|
||||
source,
|
||||
},
|
||||
})
|
||||
focusWindow()
|
||||
}
|
||||
}
|
||||
|
||||
const usePlayMusic = () => {
|
||||
const setTempPlayList = useCommit('player', 'setTempPlayList')
|
||||
const playNext = useAction('player', 'playNext')
|
||||
|
||||
const filterInfoByPlayMusic = musicInfo => {
|
||||
switch (musicInfo.source) {
|
||||
case 'kw':
|
||||
@@ -131,7 +134,7 @@ const usePlayMusic = () => {
|
||||
return ({ data: _musicInfo }) => {
|
||||
_musicInfo = filterInfoByPlayMusic(_musicInfo)
|
||||
|
||||
const musicInfo = {
|
||||
let musicInfo = {
|
||||
..._musicInfo,
|
||||
singer: decodeName(_musicInfo.singer),
|
||||
name: decodeName(_musicInfo.name),
|
||||
@@ -143,9 +146,10 @@ const usePlayMusic = () => {
|
||||
for (const type of musicInfo.types) {
|
||||
musicInfo._types[type.type] = { size: type.size }
|
||||
}
|
||||
musicInfo = toNewMusicInfo(musicInfo)
|
||||
markRaw(musicInfo)
|
||||
const isPlaying = !!playMusicInfo.musicInfo
|
||||
setTempPlayList([{ listId: '__temp__', musicInfo, isTop: true }])
|
||||
addTempPlayList([{ listId: '__temp__', musicInfo, isTop: true }])
|
||||
if (isPlaying) playNext()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
import { useRouter } from '@renderer/utils/vueTools'
|
||||
import { isShowPlayerDetail, setShowPlayerDetail } from '@renderer/core/share/player'
|
||||
import { useRouter, useRoute } from '@common/utils/vueRouter'
|
||||
import { isShowPlayerDetail } from '@renderer/store/player/state'
|
||||
import { setShowPlayerDetail } from '@renderer/store/player/action'
|
||||
import usePlaySonglist from '../compositions/usePlaySonglist'
|
||||
import { focusWindow } from '@renderer/utils/ipc'
|
||||
|
||||
import { dataVerify, sourceVerify } from './utils'
|
||||
|
||||
const useOpenSonglist = () => {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const handleOpenSonglist = params => {
|
||||
if (params.id) {
|
||||
router.replace({
|
||||
path: '/songList',
|
||||
router[route.path == '/songList/detail' ? 'replace' : 'push']({
|
||||
path: '/songList/detail',
|
||||
query: {
|
||||
source: params.source,
|
||||
id: params.id,
|
||||
},
|
||||
})
|
||||
} else if (params.url) {
|
||||
router.replace({
|
||||
path: '/songList',
|
||||
router[route.path == '/songList/detail' ? 'replace' : 'push']({
|
||||
path: '/songList/detail',
|
||||
query: {
|
||||
source: params.source,
|
||||
url: params.url,
|
||||
id: params.url,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -51,12 +54,13 @@ const useOpenSonglist = () => {
|
||||
if (!songlistInfo.id && !songlistInfo.url) throw new Error('id or url missing')
|
||||
if (isShowPlayerDetail.value) setShowPlayerDetail(false)
|
||||
handleOpenSonglist(songlistInfo)
|
||||
focusWindow()
|
||||
}
|
||||
}
|
||||
const usePlaySonglistDetail = () => {
|
||||
const playSongListDetail = usePlaySonglist()
|
||||
|
||||
return ({ paths, data }) => {
|
||||
return async({ paths, data }) => {
|
||||
let songlistInfo = {
|
||||
source: null,
|
||||
id: null,
|
||||
@@ -69,7 +73,10 @@ const usePlaySonglistDetail = () => {
|
||||
songlistInfo.source = paths[0]
|
||||
songlistInfo.url = paths[1]
|
||||
songlistInfo.index = paths[2]
|
||||
if (songlistInfo.index != null) songlistInfo.index = parseInt(songlistInfo.index)
|
||||
if (songlistInfo.index != null) {
|
||||
songlistInfo.index = parseInt(songlistInfo.index)
|
||||
if (Number.isNaN(songlistInfo.index)) delete songlistInfo.index
|
||||
}
|
||||
}
|
||||
|
||||
sourceVerify(songlistInfo.source)
|
||||
@@ -83,7 +90,7 @@ const usePlaySonglistDetail = () => {
|
||||
|
||||
if (!songlistInfo.id && !songlistInfo.url) throw new Error('id or url missing')
|
||||
|
||||
playSongListDetail(songlistInfo.source, songlistInfo.id ?? songlistInfo.url, songlistInfo.index ?? 0)
|
||||
await playSongListDetail(songlistInfo.source, songlistInfo.id ?? songlistInfo.url, songlistInfo.index)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,13 +99,13 @@ export default () => {
|
||||
const handlePlaySonglist = usePlaySonglistDetail()
|
||||
|
||||
|
||||
return (action, info) => {
|
||||
return async(action, info) => {
|
||||
switch (action) {
|
||||
case 'open':
|
||||
handleOpenSonglist(info)
|
||||
break
|
||||
case 'play':
|
||||
handlePlaySonglist(info)
|
||||
await handlePlaySonglist(info)
|
||||
break
|
||||
default: throw new Error('Unknown action: ' + action)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useI18n } from '@renderer/utils/vueTools'
|
||||
import { useI18n } from '@renderer/plugins/i18n'
|
||||
import { dialog } from '@renderer/plugins/Dialog'
|
||||
|
||||
export const useDialog = () => {
|
||||
const { t } = useI18n()
|
||||
const t = useI18n()
|
||||
const errorDialog = message => {
|
||||
dialog({
|
||||
message: `${t('deep_link__handle_error_tip', { message })}`,
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
import { openUrl, getFontSizeWithScreen } from '@renderer/utils'
|
||||
import { base as eventBaseName } from '@renderer/event/names'
|
||||
import { onSetConfig, onSystemThemeChange } from '@renderer/utils/tools'
|
||||
import { isFullscreen, themeShouldUseDarkColors } from '@renderer/core/share'
|
||||
import { rendererSend, NAMES, rendererInvoke } from '@common/ipc'
|
||||
|
||||
import {
|
||||
toRaw,
|
||||
useCommit,
|
||||
onBeforeUnmount,
|
||||
watch,
|
||||
useRefGetter,
|
||||
} from '@renderer/utils/vueTools'
|
||||
|
||||
const handle_key_down = ({ event, type, key }) => {
|
||||
// console.log(key)
|
||||
if (key != 'escape' || !event || event.repeat || type == 'up' || window.isEditingHotKey || event.target.classList.contains('ignore-esc')) return
|
||||
if (event.target.tagName != 'INPUT') {
|
||||
if (isFullscreen.value) {
|
||||
event.lx_handled = true
|
||||
rendererInvoke(NAMES.mainWindow.fullscreen, false).then(fullscreen => {
|
||||
isFullscreen.value = fullscreen
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
event.target.value = ''
|
||||
event.target.blur()
|
||||
event.lx_handled = true
|
||||
}
|
||||
const handleBodyClick = event => {
|
||||
if (event.target.tagName != 'A') return
|
||||
if (event.target.host == window.location.host) return
|
||||
event.preventDefault()
|
||||
if (/^https?:\/\//.test(event.target.href)) openUrl(event.target.href)
|
||||
}
|
||||
const handle_open_devtools = event => {
|
||||
rendererSend(NAMES.mainWindow.open_dev_tools)
|
||||
}
|
||||
const handle_fullscreen = event => {
|
||||
let fullscreen = !isFullscreen.value
|
||||
if (typeof event == 'boolean') {
|
||||
fullscreen = event
|
||||
} else if (event.event.repeat) return
|
||||
rendererInvoke(NAMES.mainWindow.fullscreen, fullscreen).then(fullscreen => {
|
||||
isFullscreen.value = fullscreen
|
||||
})
|
||||
}
|
||||
|
||||
export default ({
|
||||
dieableIgnoreMouseEvents,
|
||||
enableIgnoreMouseEvents,
|
||||
setting,
|
||||
isProd,
|
||||
isLinux,
|
||||
}) => {
|
||||
const theme = useRefGetter('theme')
|
||||
const font = useRefGetter('font')
|
||||
const windowSizeActive = useRefGetter('windowSizeActive')
|
||||
const setSetting = useCommit('setSetting')
|
||||
const isShowAnimation = useRefGetter('isShowAnimation')
|
||||
|
||||
const dom_root = document.getElementById('root')
|
||||
|
||||
|
||||
watch(theme, (val) => {
|
||||
dom_root.className = val
|
||||
})
|
||||
watch(font, (val) => {
|
||||
document.documentElement.style.fontFamily = val
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
watch(isFullscreen, val => {
|
||||
if (val) {
|
||||
document.body.classList.remove(window.dt ? 'disableTransparent' : 'transparent')
|
||||
document.body.classList.add('fullscreen')
|
||||
document.documentElement.style.fontSize = getFontSizeWithScreen(window.screen.width) + 'px'
|
||||
} else {
|
||||
document.body.classList.remove('fullscreen')
|
||||
document.body.classList.add(window.dt ? 'disableTransparent' : 'transparent')
|
||||
document.documentElement.style.fontSize = windowSizeActive.value.fontSize
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
|
||||
watch(windowSizeActive, ({ fontSize }) => {
|
||||
document.documentElement.style.fontSize = fontSize
|
||||
})
|
||||
watch(isShowAnimation, val => {
|
||||
if (val) {
|
||||
if (document.body.classList.contains('disableAnimation')) {
|
||||
document.body.classList.remove('disableAnimation')
|
||||
}
|
||||
} else {
|
||||
if (!document.body.classList.contains('disableAnimation')) {
|
||||
document.body.classList.add('disableAnimation')
|
||||
}
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
|
||||
const rSetConfig = onSetConfig((event, config) => {
|
||||
// console.log(config)
|
||||
setSetting(Object.assign({}, toRaw(setting.value), config))
|
||||
window.eventHub.emit(eventBaseName.set_config, config)
|
||||
})
|
||||
|
||||
const rSystemThemeChange = onSystemThemeChange((event, isDark) => {
|
||||
// console.log(isDark)
|
||||
themeShouldUseDarkColors.value = isDark
|
||||
})
|
||||
|
||||
window.eventHub.emit(eventBaseName.bindKey)
|
||||
window.eventHub.on(eventBaseName.key_down, handle_key_down)
|
||||
window.eventHub.on('key_mod+f12_down', handle_open_devtools)
|
||||
window.eventHub.on('key_f11_down', handle_fullscreen)
|
||||
window.eventHub.on(eventBaseName.fullscreenToggle, handle_fullscreen)
|
||||
document.body.addEventListener('click', handleBodyClick, true)
|
||||
|
||||
if (isProd && !window.dt && !isLinux) {
|
||||
document.body.addEventListener('mouseenter', enableIgnoreMouseEvents)
|
||||
document.body.addEventListener('mouseleave', dieableIgnoreMouseEvents)
|
||||
const dom_root = document.getElementById('root')
|
||||
dom_root.addEventListener('mouseenter', dieableIgnoreMouseEvents)
|
||||
dom_root.addEventListener('mouseleave', enableIgnoreMouseEvents)
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventBaseName.key_down, handle_key_down)
|
||||
window.eventHub.off('key_mod+f12_down', handle_open_devtools)
|
||||
window.eventHub.off('key_f11_down', handle_fullscreen)
|
||||
window.eventHub.off(eventBaseName.fullscreenToggle, handle_fullscreen)
|
||||
document.body.removeEventListener('click', handleBodyClick)
|
||||
window.eventHub.emit(eventBaseName.unbindKey)
|
||||
rSetConfig()
|
||||
rSystemThemeChange()
|
||||
|
||||
if (isProd && !window.dt && !isLinux) {
|
||||
document.body.removeEventListener('mouseenter', enableIgnoreMouseEvents)
|
||||
document.body.removeEventListener('mouseleave', dieableIgnoreMouseEvents)
|
||||
const dom_root = document.getElementById('root')
|
||||
dom_root.removeEventListener('mouseenter', dieableIgnoreMouseEvents)
|
||||
dom_root.removeEventListener('mouseleave', enableIgnoreMouseEvents)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import { getFontSizeWithScreen } from '@renderer/utils'
|
||||
import {
|
||||
minWindow,
|
||||
onFocus,
|
||||
onSettingChanged,
|
||||
onThemeChange,
|
||||
openDevTools,
|
||||
quitApp,
|
||||
setFullScreen,
|
||||
showHideWindowToggle,
|
||||
} from '@renderer/utils/ipc'
|
||||
import {
|
||||
isFullscreen,
|
||||
themeId,
|
||||
themeShouldUseDarkColors,
|
||||
} from '@renderer/store'
|
||||
import {
|
||||
appSetting,
|
||||
isShowAnimation,
|
||||
mergeSetting,
|
||||
} from '@renderer/store/setting'
|
||||
|
||||
import {
|
||||
onBeforeUnmount,
|
||||
watch,
|
||||
} from '@common/utils/vueTools'
|
||||
// import { isLinux, isProd } from '@common/utils'
|
||||
import { openUrl } from '@common/utils/electron'
|
||||
import { HOTKEY_COMMON } from '@common/hotKey'
|
||||
import { applyTheme, getThemes } from '@renderer/store/utils'
|
||||
import { clearDownKeys } from '@renderer/event'
|
||||
|
||||
const handle_key_down = ({ event, type, key }: LX.KeyDownEevent) => {
|
||||
// console.log(key)
|
||||
if (key != 'escape' || !event || event.repeat || type == 'up' || window.lx.isEditingHotKey || (event.target as HTMLElement)?.classList.contains('ignore-esc') || event.lx_handled) return
|
||||
if ((event.target as HTMLElement).tagName != 'INPUT') {
|
||||
if (isFullscreen.value) {
|
||||
event.lx_handled = true
|
||||
void setFullScreen(false).then(fullscreen => {
|
||||
isFullscreen.value = fullscreen
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
(event.target as HTMLInputElement).value = ''
|
||||
;(event.target as HTMLInputElement).blur()
|
||||
event.lx_handled = true
|
||||
}
|
||||
|
||||
const handleBodyClick = (event: MouseEvent) => {
|
||||
if ((event?.target as HTMLElement)?.tagName != 'A') return
|
||||
if ((event?.target as HTMLAnchorElement).host == window.location.host) return
|
||||
event.preventDefault()
|
||||
if (/^https?:\/\//.test((event?.target as HTMLAnchorElement).href)) void openUrl((event?.target as HTMLAnchorElement).href)
|
||||
}
|
||||
const handle_open_devtools = () => {
|
||||
openDevTools()
|
||||
}
|
||||
const handle_fullscreen = (event: LX.KeyDownEevent) => {
|
||||
let fullscreen = !isFullscreen.value
|
||||
if (typeof event == 'boolean') {
|
||||
fullscreen = event
|
||||
} else if (event.event?.repeat) return
|
||||
void setFullScreen(fullscreen).then(fullscreen => {
|
||||
isFullscreen.value = fullscreen
|
||||
})
|
||||
}
|
||||
|
||||
export default () => {
|
||||
watch(isFullscreen, val => {
|
||||
if (val) {
|
||||
document.documentElement.classList.remove(window.dt ? 'disableTransparent' : 'transparent')
|
||||
document.documentElement.classList.add('fullscreen')
|
||||
document.documentElement.style.fontSize = `${getFontSizeWithScreen(window.screen.width)}px`
|
||||
} else {
|
||||
document.documentElement.classList.remove('fullscreen')
|
||||
document.documentElement.classList.add(window.dt ? 'disableTransparent' : 'transparent')
|
||||
document.documentElement.style.fontSize = `${appSetting['common.fontSize']}px`
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
|
||||
watch(isShowAnimation, val => {
|
||||
if (val) {
|
||||
if (document.documentElement.classList.contains('disableAnimation')) {
|
||||
document.documentElement.classList.remove('disableAnimation')
|
||||
}
|
||||
} else {
|
||||
if (!document.documentElement.classList.contains('disableAnimation')) {
|
||||
document.documentElement.classList.add('disableAnimation')
|
||||
}
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
|
||||
const rSetConfig = onSettingChanged(({ params: setting }) => {
|
||||
// console.log(config)
|
||||
mergeSetting(setting)
|
||||
window.app_event.configUpdate()
|
||||
})
|
||||
|
||||
const rFocus = onFocus(() => {
|
||||
clearDownKeys()
|
||||
})
|
||||
|
||||
const rThemeChange = onThemeChange(({ params: setting }) => {
|
||||
// console.log(setting)
|
||||
if (themeShouldUseDarkColors.value == setting.shouldUseDarkColors) {
|
||||
if (themeId.value == setting.theme.id) return
|
||||
themeId.value = setting.theme.id
|
||||
} else {
|
||||
themeShouldUseDarkColors.value = setting.shouldUseDarkColors
|
||||
if (themeId.value != 'auto') return
|
||||
}
|
||||
getThemes(({ dataPath }) => {
|
||||
applyTheme('auto', appSetting['theme.lightId'], appSetting['theme.darkId'], dataPath)
|
||||
})
|
||||
})
|
||||
|
||||
window.key_event.on(HOTKEY_COMMON.min.action, minWindow)
|
||||
window.key_event.on(HOTKEY_COMMON.hide_toggle.action, showHideWindowToggle)
|
||||
window.key_event.on(HOTKEY_COMMON.close.action, quitApp)
|
||||
|
||||
window.app_event.on('keyDown', handle_key_down)
|
||||
window.key_event.on('key_mod+f12_down', handle_open_devtools)
|
||||
window.key_event.on('key_f11_down', handle_fullscreen)
|
||||
document.body.addEventListener('click', handleBodyClick, true)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.key_event.off(HOTKEY_COMMON.min.action, minWindow)
|
||||
window.key_event.off(HOTKEY_COMMON.hide_toggle.action, showHideWindowToggle)
|
||||
window.key_event.off(HOTKEY_COMMON.close.action, quitApp)
|
||||
|
||||
window.app_event.off('keyDown', handle_key_down)
|
||||
window.key_event.off('key_mod+f12_down', handle_open_devtools)
|
||||
window.key_event.off('key_f11_down', handle_fullscreen)
|
||||
document.body.removeEventListener('click', handleBodyClick)
|
||||
rSetConfig()
|
||||
rFocus()
|
||||
rThemeChange()
|
||||
})
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
import { useCommit, useRouter } from '@renderer/utils/vueTools'
|
||||
import { parseUrlParams } from '@renderer/utils'
|
||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
import usePlaySonglist from './compositions/usePlaySonglist'
|
||||
|
||||
const getListPlayIndex = (list, index) => {
|
||||
if (index == null) {
|
||||
index = 1
|
||||
} else {
|
||||
index = parseInt(index)
|
||||
if (Number.isNaN(index)) {
|
||||
index = 1
|
||||
} else {
|
||||
if (index < 1) index = 1
|
||||
else if (index > list.length) index = list.length
|
||||
}
|
||||
}
|
||||
return index - 1
|
||||
}
|
||||
|
||||
const useInitEnvParamSearch = () => {
|
||||
const router = useRouter()
|
||||
|
||||
return search => {
|
||||
if (search == null) return
|
||||
router.push({
|
||||
path: 'search',
|
||||
query: {
|
||||
text: search,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
const useInitEnvParamPlay = () => {
|
||||
const setPlayList = useCommit('player', 'setList')
|
||||
|
||||
const playSongListDetail = usePlaySonglist()
|
||||
|
||||
return (playStr) => {
|
||||
if (playStr == null || typeof playStr != 'string') return
|
||||
// -play="source=kw&link=链接、ID"
|
||||
// -play="source=myList&name=名字"
|
||||
// -play="source=myList&name=名字&index=位置"
|
||||
const params = parseUrlParams(playStr)
|
||||
if (params.type != 'songList') return
|
||||
switch (params.source) {
|
||||
case 'myList':
|
||||
if (params.name != null) {
|
||||
let targetList
|
||||
const lists = [defaultList, loveList, ...userLists]
|
||||
for (const list of lists) {
|
||||
if (list.name === params.name) {
|
||||
targetList = list
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!targetList) return
|
||||
|
||||
setPlayList({
|
||||
listId: targetList.id,
|
||||
index: getListPlayIndex(getList(targetList.id), params.index),
|
||||
})
|
||||
}
|
||||
break
|
||||
case 'kw':
|
||||
case 'kg':
|
||||
case 'tx':
|
||||
case 'mg':
|
||||
case 'wy':
|
||||
playSongListDetail(params.source, params.link, params.index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
// 处理启动参数 search
|
||||
const initEnvParamSearch = useInitEnvParamSearch()
|
||||
|
||||
// 处理启动参数 play
|
||||
const initEnvParamPlay = useInitEnvParamPlay()
|
||||
|
||||
return envParams => {
|
||||
initEnvParamSearch(envParams.cmdParams.search)
|
||||
initEnvParamPlay(envParams.cmdParams.play)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// import { useRouter } from '@common/utils/vueTools'
|
||||
// import { parseUrlParams } from '@common/utils/renderer'
|
||||
// import { defaultList, loveList, userLists } from '@renderer/store/list'
|
||||
// import { getList } from '@renderer/store/utils'
|
||||
// import usePlaySonglist from './compositions/usePlaySonglist'
|
||||
// import { setPlayList } from '@renderer/store/player'
|
||||
|
||||
// const getListPlayIndex = (list: LX.Music.MusicInfo[], indexStr?: string): number => {
|
||||
// let index: number
|
||||
// if (indexStr == null) {
|
||||
// index = 1
|
||||
// } else {
|
||||
// index = parseInt(indexStr)
|
||||
// if (Number.isNaN(index)) {
|
||||
// index = 1
|
||||
// } else {
|
||||
// if (index < 1) index = 1
|
||||
// else if (index > list.length) index = list.length
|
||||
// }
|
||||
// }
|
||||
// return index - 1
|
||||
// }
|
||||
|
||||
// const useInitEnvParamSearch = () => {
|
||||
// const router = useRouter()
|
||||
|
||||
// return (search?: string) => {
|
||||
// if (search == null) return
|
||||
// void router.push({
|
||||
// path: 'search',
|
||||
// query: {
|
||||
// text: search,
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// const useInitEnvParamPlay = () => {
|
||||
// // const setPlayList = useCommit('player', 'setList')
|
||||
|
||||
// const playSongListDetail = usePlaySonglist()
|
||||
|
||||
// return (playStr?: string) => {
|
||||
// if (playStr == null || typeof playStr != 'string') return
|
||||
// // -play="source=kw&link=链接、ID"
|
||||
// // -play="source=myList&name=名字"
|
||||
// // -play="source=myList&name=名字&index=位置"
|
||||
// const params = parseUrlParams(playStr)
|
||||
// if (params.type != 'songList') return
|
||||
// switch (params.source) {
|
||||
// case 'myList':
|
||||
// if (params.name != null) {
|
||||
// let targetList
|
||||
// const lists = [defaultList, loveList, ...userLists]
|
||||
// for (const list of lists) {
|
||||
// if (list.name === params.name) {
|
||||
// targetList = list
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// if (!targetList) return
|
||||
|
||||
// setPlayList({
|
||||
// listId: targetList.id,
|
||||
// index: getListPlayIndex(getList(targetList.id), params.index),
|
||||
// })
|
||||
// }
|
||||
// break
|
||||
// case 'kw':
|
||||
// case 'kg':
|
||||
// case 'tx':
|
||||
// case 'mg':
|
||||
// case 'wy':
|
||||
// playSongListDetail(params.source, params.link, params.index)
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// export default () => {
|
||||
// // 处理启动参数 search
|
||||
// const initEnvParamSearch = useInitEnvParamSearch()
|
||||
|
||||
// // 处理启动参数 play
|
||||
// const initEnvParamPlay = useInitEnvParamPlay()
|
||||
|
||||
// return (envParams: LX.EnvParams) => {
|
||||
// initEnvParamSearch(envParams.cmdParams.search)
|
||||
// initEnvParamPlay(envParams.cmdParams.play)
|
||||
// }
|
||||
// }
|
||||
+34
-37
@@ -1,42 +1,38 @@
|
||||
import { onBeforeUnmount, useI18n } from '@renderer/utils/vueTools'
|
||||
import { onUserApiStatus, setUserApi, getUserApiList, userApiRequest, userApiRequestCancel, onShowUserApiUpdateAlert } from '@renderer/utils/tools'
|
||||
import { openUrl } from '@renderer/utils'
|
||||
import apiSourceInfo from '@renderer/utils/music/api-source-info'
|
||||
import music from '@renderer/utils/music'
|
||||
import { apiSource, qualityList, userApi } from '@renderer/core/share'
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { useI18n } from '@renderer/plugins/i18n'
|
||||
import { onUserApiStatus, getUserApiList, sendUserApiRequest, userApiRequestCancel, onShowUserApiUpdateAlert } from '@renderer/utils/ipc'
|
||||
import { openUrl } from '@common/utils/electron'
|
||||
import { qualityList, userApi } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { dialog } from '@renderer/plugins/Dialog'
|
||||
import { setUserApi } from '@renderer/core/apiSource'
|
||||
|
||||
|
||||
export default ({ setting }) => {
|
||||
const { t } = useI18n()
|
||||
export default () => {
|
||||
const t = useI18n()
|
||||
|
||||
if (/^user_api/.test(setting.value.apiSource)) {
|
||||
setUserApi(setting.value.apiSource)
|
||||
} else {
|
||||
qualityList.value = music.supportQuality[setting.value.apiSource]
|
||||
}
|
||||
|
||||
const rUserApiStatus = onUserApiStatus((event, { status, message, apiInfo }) => {
|
||||
const rUserApiStatus = onUserApiStatus(({ params: { status, message, apiInfo } }) => {
|
||||
// console.log({ status, message, apiInfo })
|
||||
userApi.status = status
|
||||
userApi.message = message
|
||||
|
||||
if (status) {
|
||||
if (apiInfo.id === setting.value.apiSource) {
|
||||
let apis = {}
|
||||
let qualitys = {}
|
||||
if (status && apiInfo && apiInfo.sources) {
|
||||
if (apiInfo.id === appSetting['common.apiSource']) {
|
||||
let apis: any = {}
|
||||
let qualitys: LX.QualityList = {}
|
||||
for (const [source, { actions, type, qualitys: sourceQualitys }] of Object.entries(apiInfo.sources)) {
|
||||
if (type != 'music') continue
|
||||
apis[source] = {}
|
||||
apis[source as LX.Source] = {}
|
||||
for (const action of actions) {
|
||||
switch (action) {
|
||||
case 'musicUrl':
|
||||
apis[source].getMusicUrl = (songInfo, type) => {
|
||||
apis[source].getMusicUrl = (songInfo: LX.Music.MusicInfo, type: LX.Quality) => {
|
||||
const requestKey = `request__${Math.random().toString().substring(2)}`
|
||||
return {
|
||||
canceleFn() {
|
||||
userApiRequestCancel(requestKey)
|
||||
},
|
||||
promise: userApiRequest({
|
||||
promise: sendUserApiRequest({
|
||||
requestKey,
|
||||
data: {
|
||||
source,
|
||||
@@ -50,9 +46,9 @@ export default ({ setting }) => {
|
||||
// console.log(res)
|
||||
if (!/^https?:/.test(res.data.url)) return Promise.reject(new Error('Get url failed'))
|
||||
return { type, url: res.data.url }
|
||||
}).catch(err => {
|
||||
}).catch(async err => {
|
||||
console.log(err.message)
|
||||
return Promise.reject(err)
|
||||
return await Promise.reject(err)
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -62,7 +58,7 @@ export default ({ setting }) => {
|
||||
break
|
||||
}
|
||||
}
|
||||
qualitys[source] = sourceQualitys
|
||||
qualitys[source as LX.Source] = sourceQualitys
|
||||
}
|
||||
qualityList.value = qualitys
|
||||
userApi.apis = apis
|
||||
@@ -70,9 +66,9 @@ export default ({ setting }) => {
|
||||
}
|
||||
})
|
||||
|
||||
const rUserApiShowUpdateAlert = onShowUserApiUpdateAlert((event, { name, log, updateUrl }) => {
|
||||
const rUserApiShowUpdateAlert = onShowUserApiUpdateAlert(({ params: { name, log, updateUrl } }) => {
|
||||
if (updateUrl) {
|
||||
dialog({
|
||||
void dialog({
|
||||
message: `${t('user_api__update_alert', { name })}\n${log}`,
|
||||
selection: true,
|
||||
showCancel: true,
|
||||
@@ -80,12 +76,12 @@ export default ({ setting }) => {
|
||||
cancelButtonText: t('close'),
|
||||
}).then(confirm => {
|
||||
if (!confirm) return
|
||||
setTimeout(() => {
|
||||
openUrl(updateUrl)
|
||||
window.setTimeout(() => {
|
||||
void openUrl(updateUrl)
|
||||
}, 300)
|
||||
})
|
||||
} else {
|
||||
dialog({
|
||||
void dialog({
|
||||
message: `${t('user_api__update_alert', { name })}\n${log}`,
|
||||
selection: true,
|
||||
confirmButtonText: t('ok'),
|
||||
@@ -98,14 +94,15 @@ export default ({ setting }) => {
|
||||
rUserApiShowUpdateAlert()
|
||||
})
|
||||
|
||||
return () => {
|
||||
return getUserApiList().then(list => {
|
||||
return async() => {
|
||||
void setUserApi(appSetting['common.apiSource'])
|
||||
return await getUserApiList().then(list => {
|
||||
// console.log(list)
|
||||
if (![...apiSourceInfo.map(s => s.id), ...list.map(s => s.id)].includes(setting.value.apiSource)) {
|
||||
console.warn('reset api')
|
||||
let api = apiSourceInfo.find(api => !api.disabled)
|
||||
if (api) apiSource.value = api.id
|
||||
}
|
||||
// if (![...apiSourceInfo.map(s => s.id), ...list.map(s => s.id)].includes(appSetting['common.apiSource'])) {
|
||||
// console.warn('reset api')
|
||||
// let api = apiSourceInfo.find(api => !api.disabled)
|
||||
// if (api) apiSource.value = api.id
|
||||
// }
|
||||
userApi.list = list
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
@@ -1,27 +0,0 @@
|
||||
import { getListUpdateInfo } from '@renderer/utils/data'
|
||||
import useSyncSourceList from '@renderer/utils/compositions/useSyncSourceList'
|
||||
import { userLists } from '@renderer/core/share/list'
|
||||
|
||||
export default () => {
|
||||
const syncSourceList = useSyncSourceList()
|
||||
|
||||
|
||||
const handleSyncSourceList = async(waitUpdateLists) => {
|
||||
if (!waitUpdateLists.length) return
|
||||
const targetListInfo = waitUpdateLists.shift()
|
||||
// console.log(targetListInfo)
|
||||
try {
|
||||
await syncSourceList(targetListInfo)
|
||||
} catch {}
|
||||
handleSyncSourceList(waitUpdateLists)
|
||||
}
|
||||
|
||||
return () => {
|
||||
const waitUpdateLists = Object.entries(getListUpdateInfo())
|
||||
.map(([id, info]) => info.isAutoUpdate && userLists.find(l => l.id === id))
|
||||
.filter(_ => _)
|
||||
for (let i = 2; i > 0; i--) {
|
||||
handleSyncSourceList(waitUpdateLists)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import {
|
||||
createAudio,
|
||||
} from '@renderer/plugins/player'
|
||||
import useMediaDevice from './useMediaDevice'
|
||||
import usePlayerEvent from './usePlayerEvent'
|
||||
import usePlayer from './usePlayer'
|
||||
import useTaskbar from './useTaskbar'
|
||||
import { init as initPlayTimeoutStop } from '@renderer/utils/timeoutStop'
|
||||
|
||||
export default ({ setting }) => {
|
||||
createAudio()
|
||||
|
||||
usePlayerEvent()
|
||||
useMediaDevice({ setting }) // 初始化音频驱动输出设置
|
||||
usePlayer({ setting })
|
||||
const initTaskbar = useTaskbar()
|
||||
|
||||
initPlayTimeoutStop()
|
||||
|
||||
return () => {
|
||||
initTaskbar()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import {
|
||||
createAudio,
|
||||
} from '@renderer/plugins/player'
|
||||
import useMediaDevice from './useMediaDevice'
|
||||
import usePlayerEvent from './usePlayerEvent'
|
||||
import usePlayer from './usePlayer'
|
||||
import usePlayStatus from './usePlayStatus'
|
||||
|
||||
export default () => {
|
||||
createAudio()
|
||||
|
||||
usePlayerEvent()
|
||||
useMediaDevice() // 初始化音频驱动输出设置
|
||||
usePlayer()
|
||||
const initPlayStatus = usePlayStatus()
|
||||
|
||||
return () => {
|
||||
void initPlayStatus()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
import { onBeforeUnmount, watch, markRawList } from '@renderer/utils/vueTools'
|
||||
import Lyric from '@renderer/utils/lyric-font-player'
|
||||
import { getCurrentTime as getPlayerCurrentTime } from '@renderer/plugins/player'
|
||||
import { setDesktopLyricInfo, onGetDesktopLyricInfo } from '@renderer/utils/tools'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { lyric, setText, setLines, setOffset, setTempOffset } from '@renderer/core/share/lyric'
|
||||
import { musicInfo, setStatusText, isPlay, playMusicInfo } from '@renderer/core/share/player'
|
||||
|
||||
export default ({ setting }) => {
|
||||
const lrc = window.lrc = new Lyric({
|
||||
lineClassName: 'lrc-content',
|
||||
fontClassName: 'font',
|
||||
shadowContent: false,
|
||||
activeLineClassName: 'active',
|
||||
onPlay(line, text) {
|
||||
setText(text, line)
|
||||
setStatusText(text)
|
||||
// console.log(line, text)
|
||||
},
|
||||
onSetLyric(lines, offset) { // listening lyrics seting event
|
||||
// console.log(lines) // lines is array of all lyric text
|
||||
setLines(markRawList([...lines]))
|
||||
setText(lines[0] ?? '', 0)
|
||||
setOffset(offset) // 歌词延迟
|
||||
setTempOffset(0) // 重置临时延迟
|
||||
},
|
||||
// offset: 80,
|
||||
})
|
||||
|
||||
const getCurrentTime = () => {
|
||||
return getPlayerCurrentTime() * 1000 + lyric.tempOffset
|
||||
}
|
||||
|
||||
|
||||
const setPlayInfo = ({ musicInfo }) => {
|
||||
setDesktopLyricInfo('music_info', {
|
||||
songmid: musicInfo.songmid,
|
||||
singer: musicInfo.singer,
|
||||
name: musicInfo.name,
|
||||
album: musicInfo.album,
|
||||
})
|
||||
}
|
||||
|
||||
const setLyric = () => {
|
||||
if (!musicInfo.songmid) return
|
||||
const extendedLyrics = []
|
||||
if (setting.value.player.isShowLyricTranslation && musicInfo.tlrc) extendedLyrics.push(musicInfo.tlrc)
|
||||
if (setting.value.player.isShowLyricRoma && musicInfo.rlrc) extendedLyrics.push(musicInfo.rlrc)
|
||||
lrc.setLyric(
|
||||
setting.value.player.isPlayLxlrc && musicInfo.lxlrc ? musicInfo.lxlrc : musicInfo.lrc,
|
||||
extendedLyrics,
|
||||
)
|
||||
setDesktopLyricInfo('lyric', { lrc: musicInfo.lrc, tlrc: musicInfo.tlrc, rlrc: musicInfo.rlrc, lxlrc: musicInfo.lxlrc })
|
||||
|
||||
if (isPlay.value && (musicInfo.url || playMusicInfo.listId == 'download')) {
|
||||
setTimeout(() => {
|
||||
const time = getCurrentTime()
|
||||
setDesktopLyricInfo('play', time)
|
||||
lrc.play(time)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const setLyricOffset = offset => {
|
||||
setTempOffset(offset)
|
||||
if (isPlay.value && (musicInfo.url || playMusicInfo.listId == 'download')) {
|
||||
setTimeout(() => {
|
||||
const time = getCurrentTime()
|
||||
setDesktopLyricInfo('play', time)
|
||||
lrc.play(time)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
if (!musicInfo.lrc) return
|
||||
const currentTime = getCurrentTime()
|
||||
lrc.play(currentTime)
|
||||
setDesktopLyricInfo('play', currentTime)
|
||||
}
|
||||
const handlePause = () => {
|
||||
lrc.pause()
|
||||
setDesktopLyricInfo('pause')
|
||||
}
|
||||
const handleStop = () => {
|
||||
lrc.pause()
|
||||
setDesktopLyricInfo('stop')
|
||||
setLines([])
|
||||
setText('', 0)
|
||||
}
|
||||
|
||||
watch(() => setting.value.player.isShowLyricTranslation, setLyric)
|
||||
watch(() => setting.value.player.isPlayLxlrc, setLyric)
|
||||
|
||||
const rGetDesktopLyricInfo = onGetDesktopLyricInfo((event, info) => {
|
||||
switch (info.action) {
|
||||
case 'info':
|
||||
setDesktopLyricInfo('info', {
|
||||
songmid: musicInfo.songmid,
|
||||
singer: musicInfo.singer,
|
||||
name: musicInfo.name,
|
||||
album: musicInfo.album,
|
||||
lrc: musicInfo.lrc,
|
||||
tlrc: musicInfo.tlrc,
|
||||
rlrc: musicInfo.rlrc,
|
||||
lxlrc: musicInfo.lxlrc,
|
||||
isPlay: isPlay.value,
|
||||
line: lyric.line,
|
||||
played_time: getCurrentTime(),
|
||||
}, info)
|
||||
break
|
||||
case 'status':
|
||||
setDesktopLyricInfo('status', {
|
||||
isPlay: isPlay.value,
|
||||
line: lyric.line,
|
||||
played_time: getCurrentTime(),
|
||||
}, info)
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
window.eventHub.on(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.on(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.on(eventPlayerNames.stop, handleStop)
|
||||
window.eventHub.on(eventPlayerNames.error, handlePause)
|
||||
window.eventHub.on(eventPlayerNames.setPlayInfo, setPlayInfo)
|
||||
window.eventHub.on(eventPlayerNames.updateLyric, setLyric)
|
||||
window.eventHub.on(eventPlayerNames.updateLyricOffset, setLyricOffset)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rGetDesktopLyricInfo()
|
||||
window.eventHub.off(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.off(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.off(eventPlayerNames.stop, handleStop)
|
||||
window.eventHub.off(eventPlayerNames.error, handlePause)
|
||||
window.eventHub.off(eventPlayerNames.setPlayInfo, setPlayInfo)
|
||||
window.eventHub.off(eventPlayerNames.updateLyric, setLyric)
|
||||
window.eventHub.off(eventPlayerNames.updateLyricOffset, setLyricOffset)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||
// import { setDesktopLyricInfo, onGetDesktopLyricInfo } from '@renderer/utils/ipc'
|
||||
// import { musicInfo } from '@renderer/store/player/state'
|
||||
import {
|
||||
pause,
|
||||
play,
|
||||
setLyric,
|
||||
stop,
|
||||
init,
|
||||
sendInfo,
|
||||
} from '@renderer/core/lyric'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
|
||||
export default () => {
|
||||
init()
|
||||
|
||||
const setPlayInfo = () => {
|
||||
stop()
|
||||
sendInfo()
|
||||
}
|
||||
|
||||
watch(() => appSetting['player.isShowLyricTranslation'], setLyric)
|
||||
watch(() => appSetting['player.isShowLyricRoma'], setLyric)
|
||||
watch(() => appSetting['player.isPlayLxlrc'], setLyric)
|
||||
|
||||
window.app_event.on('play', play)
|
||||
window.app_event.on('pause', pause)
|
||||
window.app_event.on('stop', stop)
|
||||
window.app_event.on('error', pause)
|
||||
window.app_event.on('musicToggled', setPlayInfo)
|
||||
window.app_event.on('lyricUpdated', setLyric)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.app_event.off('play', play)
|
||||
window.app_event.off('pause', pause)
|
||||
window.app_event.off('stop', stop)
|
||||
window.app_event.off('error', pause)
|
||||
window.app_event.off('musicToggled', setPlayInfo)
|
||||
window.app_event.off('lyricUpdated', setLyric)
|
||||
})
|
||||
}
|
||||
+22
-20
@@ -1,23 +1,21 @@
|
||||
import {
|
||||
onBeforeUnmount,
|
||||
watch,
|
||||
useCommit,
|
||||
} from '@renderer/utils/vueTools'
|
||||
} from '@common/utils/vueTools'
|
||||
import { pause } from '@renderer/core/player/action'
|
||||
import { setMediaDeviceId } from '@renderer/plugins/player'
|
||||
import { isPlay } from '@renderer/core/share/player'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { isPlay } from '@renderer/store/player/state'
|
||||
import { appSetting, saveMediaDeviceId } from '@renderer/store/setting'
|
||||
|
||||
const getDevices = async() => {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices()
|
||||
return devices.filter(({ kind }) => kind == 'audiooutput')
|
||||
}
|
||||
|
||||
export default ({ setting }) => {
|
||||
let prevDeviceLabel = null
|
||||
export default () => {
|
||||
let prevDeviceLabel: string | null = null
|
||||
|
||||
const saveMediaDeviceId = useCommit('setMediaDeviceId')
|
||||
|
||||
const setMediaDevice = async(mediaDeviceId) => {
|
||||
const setMediaDevice = async(mediaDeviceId: string) => {
|
||||
let label = prevDeviceLabel
|
||||
const devices = await getDevices()
|
||||
let device = devices.find(device => device.deviceId === mediaDeviceId)
|
||||
@@ -32,48 +30,52 @@ export default ({ setting }) => {
|
||||
|
||||
prevDeviceLabel = label
|
||||
// console.log(device)
|
||||
setMediaDeviceId(mediaDeviceId).catch(err => {
|
||||
setMediaDeviceId(mediaDeviceId).catch((err: any) => {
|
||||
console.log(err)
|
||||
saveMediaDeviceId('default')
|
||||
})
|
||||
}
|
||||
|
||||
const handleDeviceChangeStopPlay = (device, mediaDeviceId) => {
|
||||
const handleDeviceChangeStopPlay = (device: MediaDeviceInfo, mediaDeviceId: string) => {
|
||||
// console.log(device)
|
||||
// console.log(this.setting.player.isMediaDeviceRemovedStopPlay, this.isPlay, device.label, this.prevDeviceLabel)
|
||||
// console.log(this.appSetting.player['isMediaDeviceRemovedStopPlay,'] this.isPlay, device.label, this.prevDeviceLabel)
|
||||
if (
|
||||
setting.value.player.isMediaDeviceRemovedStopPlay &&
|
||||
appSetting['player.isMediaDeviceRemovedStopPlay'] &&
|
||||
isPlay.value &&
|
||||
device.label != prevDeviceLabel
|
||||
) {
|
||||
global.isPlayedStop = true
|
||||
window.eventHub.emit(eventPlayerNames.setPause)
|
||||
window.lx.isPlayedStop = true
|
||||
pause()
|
||||
}
|
||||
}
|
||||
|
||||
const handleMediaListChange = async() => {
|
||||
let mediaDeviceId = setting.value.player.mediaDeviceId
|
||||
let mediaDeviceId = appSetting['player.mediaDeviceId']
|
||||
const devices = await getDevices()
|
||||
let device = devices.find(device => device.deviceId === mediaDeviceId)
|
||||
if (!device) device = devices.find(device => device.deviceId === 'default')
|
||||
if (!device) device = { label: null, deviceId: null }
|
||||
// @ts-expect-error
|
||||
if (!device) device = { label: '', deviceId: '' }
|
||||
|
||||
// @ts-expect-error
|
||||
handleDeviceChangeStopPlay(device, mediaDeviceId)
|
||||
|
||||
setMediaDeviceId(device.deviceId).catch(err => {
|
||||
setMediaDeviceId(device!.deviceId).catch((err: any) => {
|
||||
console.log(err)
|
||||
saveMediaDeviceId('default')
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => setting.value.player.mediaDeviceId, setMediaDevice)
|
||||
watch(() => appSetting['player.mediaDeviceId'], setMediaDevice)
|
||||
|
||||
|
||||
setMediaDevice(setting.value.player.mediaDeviceId)
|
||||
void setMediaDevice(appSetting['player.mediaDeviceId'])
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
navigator.mediaDevices.addEventListener('devicechange', handleMediaListChange)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
navigator.mediaDevices.removeEventListener('devicechange', handleMediaListChange)
|
||||
})
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
import { onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
import { getDuration, getPlaybackRate, getCurrentTime } from '@renderer/plugins/player'
|
||||
import { player } from '@renderer/event/names'
|
||||
|
||||
export default ({ playPrev, playNext }) => {
|
||||
const updateMediaSessionInfo = ({ name, singer, albumName, img }) => {
|
||||
const mediaMetadata = {
|
||||
title: name,
|
||||
artist: singer,
|
||||
album: albumName,
|
||||
}
|
||||
if (img) mediaMetadata.artwork = [{ src: img }]
|
||||
navigator.mediaSession.metadata = new window.MediaMetadata(mediaMetadata)
|
||||
}
|
||||
|
||||
const updatePositionState = (state = {}) => {
|
||||
navigator.mediaSession.setPositionState({
|
||||
duration: state.duration ?? getDuration(),
|
||||
playbackRate: state.playbackRate ?? getPlaybackRate(),
|
||||
position: state.position ?? getCurrentTime(),
|
||||
})
|
||||
}
|
||||
|
||||
const setProgress = time => {
|
||||
window.eventHub.emit(player.setProgress, time)
|
||||
}
|
||||
|
||||
const setStop = () => {
|
||||
window.eventHub.emit(player.setStop)
|
||||
}
|
||||
const handlePlay = () => {
|
||||
navigator.mediaSession.playbackState = 'playing'
|
||||
}
|
||||
const handlePause = () => {
|
||||
navigator.mediaSession.playbackState = 'paused'
|
||||
}
|
||||
const handleStop = () => {
|
||||
navigator.mediaSession.playbackState = 'none'
|
||||
}
|
||||
const handleSetPlayInfo = ({ musicInfo, progress }) => {
|
||||
updateMediaSessionInfo(musicInfo)
|
||||
updatePositionState({
|
||||
position: progress.time,
|
||||
duration: progress.maxTime,
|
||||
})
|
||||
handlePause()
|
||||
}
|
||||
|
||||
// const registerMediaSessionHandler = () => {
|
||||
// navigator.mediaSession.setActionHandler('play', () => {
|
||||
// if (this.isPlay || !this.playMusicInfo) return
|
||||
// console.log('play')
|
||||
// this.startPlay()
|
||||
// })
|
||||
// navigator.mediaSession.setActionHandler('pause', () => {
|
||||
// if (!this.isPlay || !this.playMusicInfo) return
|
||||
// console.log('pause')
|
||||
// this.stopPlay()
|
||||
// })
|
||||
navigator.mediaSession.setActionHandler('stop', () => {
|
||||
console.log('stop')
|
||||
setStop()
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('seekbackward', details => {
|
||||
console.log('seekbackward')
|
||||
setProgress(Math.max(getCurrentTime() - details.seekOffset, 0))
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('seekforward', details => {
|
||||
console.log('seekforward')
|
||||
setProgress(Math.min(getCurrentTime() + details.seekOffset, getDuration()))
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('seekto', details => {
|
||||
console.log('seekto', details.seekTime)
|
||||
let time = Math.min(details.seekTime, getDuration())
|
||||
time = Math.max(time, 0)
|
||||
setProgress(time)
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
||||
console.log('previoustrack')
|
||||
playPrev()
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
||||
console.log('nexttrack')
|
||||
playNext()
|
||||
})
|
||||
// navigator.mediaSession.setActionHandler('skipad', () => {
|
||||
// console.log('')
|
||||
// })
|
||||
// }
|
||||
|
||||
window.eventHub.on(player.player_loadeddata, updatePositionState)
|
||||
window.eventHub.on(player.player_canplay, updatePositionState)
|
||||
window.eventHub.on(player.play, handlePlay)
|
||||
window.eventHub.on(player.pause, handlePause)
|
||||
window.eventHub.on(player.stop, handleStop)
|
||||
window.eventHub.on(player.error, handlePause)
|
||||
window.eventHub.on(player.setPlayInfo, handleSetPlayInfo)
|
||||
window.eventHub.on(player.updatePic, updateMediaSessionInfo)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(player.player_loadeddata, updatePositionState)
|
||||
window.eventHub.off(player.player_canplay, updatePositionState)
|
||||
window.eventHub.off(player.play, handlePlay)
|
||||
window.eventHub.off(player.pause, handlePause)
|
||||
window.eventHub.off(player.stop, handleStop)
|
||||
window.eventHub.off(player.error, handlePause)
|
||||
window.eventHub.off(player.setPlayInfo, handleSetPlayInfo)
|
||||
window.eventHub.off(player.updatePic, updateMediaSessionInfo)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { getDuration, getPlaybackRate, getCurrentTime } from '@renderer/plugins/player'
|
||||
import { musicInfo } from '@renderer/store/player/state'
|
||||
import { playProgress } from '@renderer/store/player/playProgress'
|
||||
import { playNext, playPrev, stop } from '@renderer/core/player'
|
||||
// import { } from ''
|
||||
|
||||
export default () => {
|
||||
const updateMediaSessionInfo = () => {
|
||||
const mediaMetadata: MediaMetadata = {
|
||||
title: musicInfo.name,
|
||||
artist: musicInfo.singer,
|
||||
album: musicInfo.album,
|
||||
artwork: [],
|
||||
}
|
||||
if (musicInfo.pic) mediaMetadata.artwork = [{ src: musicInfo.pic }]
|
||||
|
||||
// @ts-expect-error
|
||||
navigator.mediaSession.metadata = new window.MediaMetadata(mediaMetadata)
|
||||
}
|
||||
|
||||
const updatePositionState = (state: {
|
||||
duration?: number
|
||||
position?: number
|
||||
playbackRate?: number
|
||||
} = {}) => {
|
||||
navigator.mediaSession.setPositionState({
|
||||
duration: state.duration ?? getDuration(),
|
||||
playbackRate: state.playbackRate ?? getPlaybackRate(),
|
||||
position: state.position ?? getCurrentTime(),
|
||||
})
|
||||
}
|
||||
|
||||
const setProgress = (time: number) => {
|
||||
window.app_event.setProgress(time)
|
||||
}
|
||||
|
||||
const setStop = () => {
|
||||
stop()
|
||||
}
|
||||
const handlePlay = () => {
|
||||
navigator.mediaSession.playbackState = 'playing'
|
||||
}
|
||||
const handlePause = () => {
|
||||
navigator.mediaSession.playbackState = 'paused'
|
||||
}
|
||||
const handleStop = () => {
|
||||
navigator.mediaSession.playbackState = 'none'
|
||||
}
|
||||
const handleSetPlayInfo = () => {
|
||||
updateMediaSessionInfo()
|
||||
updatePositionState({
|
||||
position: playProgress.nowPlayTime,
|
||||
duration: playProgress.maxPlayTime,
|
||||
})
|
||||
handlePause()
|
||||
}
|
||||
|
||||
// const registerMediaSessionHandler = () => {
|
||||
// navigator.mediaSession.setActionHandler('play', () => {
|
||||
// if (this.isPlay || !this.playMusicInfo) return
|
||||
// console.log('play')
|
||||
// this.startPlay()
|
||||
// })
|
||||
// navigator.mediaSession.setActionHandler('pause', () => {
|
||||
// if (!this.isPlay || !this.playMusicInfo) return
|
||||
// console.log('pause')
|
||||
// this.stopPlay()
|
||||
// })
|
||||
navigator.mediaSession.setActionHandler('stop', () => {
|
||||
console.log('stop')
|
||||
setStop()
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('seekbackward', details => {
|
||||
console.log('seekbackward')
|
||||
const seekOffset = details.seekOffset == null ? 5 : details.seekOffset
|
||||
setProgress(Math.max(getCurrentTime() - seekOffset, 0))
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('seekforward', details => {
|
||||
console.log('seekforward')
|
||||
const seekOffset = details.seekOffset == null ? 5 : details.seekOffset
|
||||
setProgress(Math.min(getCurrentTime() + seekOffset, getDuration()))
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('seekto', details => {
|
||||
console.log('seekto', details.seekTime)
|
||||
if (details.seekTime == null) return
|
||||
let time = Math.min(details.seekTime, getDuration())
|
||||
time = Math.max(time, 0)
|
||||
setProgress(time)
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
||||
console.log('previoustrack')
|
||||
void playPrev()
|
||||
})
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
||||
console.log('nexttrack')
|
||||
void playNext()
|
||||
})
|
||||
// navigator.mediaSession.setActionHandler('skipad', () => {
|
||||
// console.log('')
|
||||
// })
|
||||
// }
|
||||
|
||||
window.app_event.on('playerLoadeddata', updatePositionState)
|
||||
window.app_event.on('playerCanplay', updatePositionState)
|
||||
window.app_event.on('play', handlePlay)
|
||||
window.app_event.on('pause', handlePause)
|
||||
window.app_event.on('stop', handleStop)
|
||||
window.app_event.on('error', handlePause)
|
||||
window.app_event.on('musicToggled', handleSetPlayInfo)
|
||||
window.app_event.on('picUpdated', updateMediaSessionInfo)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.app_event.off('playerLoadeddata', updatePositionState)
|
||||
window.app_event.off('playerCanplay', updatePositionState)
|
||||
window.app_event.off('play', handlePlay)
|
||||
window.app_event.off('pause', handlePause)
|
||||
window.app_event.off('stop', handleStop)
|
||||
window.app_event.off('error', handlePause)
|
||||
window.app_event.off('musicToggled', handleSetPlayInfo)
|
||||
window.app_event.off('picUpdated', updateMediaSessionInfo)
|
||||
})
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
import { onBeforeUnmount, useI18n } from '@renderer/utils/vueTools'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { wait, waitCancel } from '@renderer/utils/tools'
|
||||
import { musicInfo, musicInfoItem, playMusicInfo } from '@renderer/core/share/player'
|
||||
import { setStop, isEmpty } from '@renderer/plugins/player'
|
||||
|
||||
export default ({
|
||||
setting,
|
||||
playNext,
|
||||
setAllStatus,
|
||||
setUrl,
|
||||
}) => {
|
||||
const { t } = useI18n()
|
||||
let retryNum = 0
|
||||
let prevTimeoutId = null
|
||||
|
||||
let loadingTimeout
|
||||
let delayNextTimeout
|
||||
const startLoadingTimeout = () => {
|
||||
// console.log('start load timeout')
|
||||
clearLoadingTimeout()
|
||||
loadingTimeout = Math.random()
|
||||
wait(25000, loadingTimeout).then(() => {
|
||||
// 如果加载超时,则尝试刷新URL
|
||||
if (prevTimeoutId == musicInfo.songmid) {
|
||||
prevTimeoutId = null
|
||||
playNext()
|
||||
} else {
|
||||
prevTimeoutId = musicInfo.songmid
|
||||
setUrl(musicInfoItem.value, true)
|
||||
}
|
||||
}).catch(_ => _)
|
||||
}
|
||||
const clearLoadingTimeout = () => {
|
||||
if (!loadingTimeout) return
|
||||
// console.log('clear load timeout')
|
||||
waitCancel(loadingTimeout)
|
||||
loadingTimeout = null
|
||||
}
|
||||
|
||||
const clearDelayNextTimeout = () => {
|
||||
// console.log(this.delayNextTimeout)
|
||||
if (!delayNextTimeout) return
|
||||
waitCancel(delayNextTimeout)
|
||||
delayNextTimeout = null
|
||||
}
|
||||
const addDelayNextTimeout = () => {
|
||||
clearDelayNextTimeout()
|
||||
delayNextTimeout = Math.random()
|
||||
wait(5000, delayNextTimeout).then(playNext).catch(_ => _)
|
||||
}
|
||||
|
||||
const handleLoadstart = () => {
|
||||
if (global.isPlayedStop) return
|
||||
if (setting.value.player.autoSkipOnError) startLoadingTimeout()
|
||||
setAllStatus(t('player__loading'))
|
||||
}
|
||||
|
||||
const handleLoadeddata = () => {
|
||||
setAllStatus(t('player__loading'))
|
||||
}
|
||||
|
||||
const handleCanplay = () => {
|
||||
setAllStatus('')
|
||||
}
|
||||
|
||||
const handlePlaying = () => {
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
const handleEmpied = () => {
|
||||
clearDelayNextTimeout()
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
const handleWating = () => {
|
||||
setAllStatus(t('player__buffering'))
|
||||
}
|
||||
|
||||
const handleError = errCode => {
|
||||
if (!musicInfo.songmid) return
|
||||
clearLoadingTimeout()
|
||||
if (global.isPlayedStop) return
|
||||
if (!isEmpty()) setStop()
|
||||
if (playMusicInfo.listId != 'download' && errCode !== 1 && retryNum < 2) { // 若音频URL无效则尝试刷新2次URL
|
||||
// console.log(this.retryNum)
|
||||
retryNum++
|
||||
setUrl(musicInfoItem.value, true)
|
||||
setAllStatus(t('player__refresh_url'))
|
||||
return
|
||||
}
|
||||
|
||||
if (setting.value.player.autoSkipOnError) {
|
||||
if (document.hidden) {
|
||||
playNext()
|
||||
} else {
|
||||
setAllStatus(t('player__error'))
|
||||
setTimeout(addDelayNextTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleSetPlayInfo = () => {
|
||||
retryNum = 0
|
||||
prevTimeoutId = null
|
||||
clearDelayNextTimeout()
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
const handlePlayedStop = () => {
|
||||
clearDelayNextTimeout()
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
|
||||
window.eventHub.on(eventPlayerNames.player_loadstart, handleLoadstart)
|
||||
window.eventHub.on(eventPlayerNames.player_loadeddata, handleLoadeddata)
|
||||
window.eventHub.on(eventPlayerNames.player_canplay, handleCanplay)
|
||||
window.eventHub.on(eventPlayerNames.player_playing, handlePlaying)
|
||||
window.eventHub.on(eventPlayerNames.player_waiting, handleWating)
|
||||
window.eventHub.on(eventPlayerNames.player_emptied, handleEmpied)
|
||||
window.eventHub.on(eventPlayerNames.error, handleError)
|
||||
window.eventHub.on(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
window.eventHub.on(eventPlayerNames.playedStop, handlePlayedStop)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventPlayerNames.player_loadstart, handleLoadstart)
|
||||
window.eventHub.off(eventPlayerNames.player_loadeddata, handleLoadeddata)
|
||||
window.eventHub.off(eventPlayerNames.player_canplay, handleCanplay)
|
||||
window.eventHub.off(eventPlayerNames.player_playing, handlePlaying)
|
||||
window.eventHub.off(eventPlayerNames.player_waiting, handleWating)
|
||||
window.eventHub.off(eventPlayerNames.player_emptied, handleEmpied)
|
||||
window.eventHub.off(eventPlayerNames.error, handleError)
|
||||
window.eventHub.off(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
window.eventHub.off(eventPlayerNames.playedStop, handlePlayedStop)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { useI18n } from '@renderer/plugins/i18n'
|
||||
import { musicInfo, playMusicInfo } from '@renderer/store/player/state'
|
||||
import { setStop, isEmpty } from '@renderer/plugins/player'
|
||||
import { playNext, setMusicUrl } from '@renderer/core/player'
|
||||
import { setAllStatus } from '@renderer/store/player/action'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
export default () => {
|
||||
const t = useI18n()
|
||||
let retryNum = 0
|
||||
let prevTimeoutId: string | null = null
|
||||
|
||||
let loadingTimeout: NodeJS.Timeout | null = null
|
||||
let delayNextTimeout: NodeJS.Timeout | null = null
|
||||
const startLoadingTimeout = () => {
|
||||
// console.log('start load timeout')
|
||||
clearLoadingTimeout()
|
||||
loadingTimeout = setTimeout(() => {
|
||||
if (window.lx.isPlayedStop) {
|
||||
prevTimeoutId = null
|
||||
setAllStatus('')
|
||||
return
|
||||
}
|
||||
|
||||
// 如果加载超时,则尝试刷新URL
|
||||
if (prevTimeoutId == musicInfo.id) {
|
||||
prevTimeoutId = null
|
||||
void playNext(true)
|
||||
} else {
|
||||
prevTimeoutId = musicInfo.id
|
||||
if (playMusicInfo.musicInfo) setMusicUrl(playMusicInfo.musicInfo, true)
|
||||
}
|
||||
}, 25000)
|
||||
}
|
||||
const clearLoadingTimeout = () => {
|
||||
if (!loadingTimeout) return
|
||||
// console.log('clear load timeout')
|
||||
clearTimeout(loadingTimeout)
|
||||
loadingTimeout = null
|
||||
}
|
||||
|
||||
const clearDelayNextTimeout = () => {
|
||||
// console.log(this.delayNextTimeout)
|
||||
if (!delayNextTimeout) return
|
||||
clearTimeout(delayNextTimeout)
|
||||
delayNextTimeout = null
|
||||
}
|
||||
const addDelayNextTimeout = () => {
|
||||
clearDelayNextTimeout()
|
||||
delayNextTimeout = setTimeout(() => {
|
||||
if (window.lx.isPlayedStop) return setAllStatus('')
|
||||
void playNext(true)
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
const handleLoadstart = () => {
|
||||
if (window.lx.isPlayedStop) return
|
||||
if (appSetting['player.autoSkipOnError']) startLoadingTimeout()
|
||||
setAllStatus(t('player__loading'))
|
||||
}
|
||||
|
||||
const handleLoadeddata = () => {
|
||||
setAllStatus(t('player__loading'))
|
||||
}
|
||||
|
||||
const handleCanplay = () => {
|
||||
setAllStatus('')
|
||||
}
|
||||
|
||||
const handlePlaying = () => {
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
const handleEmpied = () => {
|
||||
clearDelayNextTimeout()
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
const handleWating = () => {
|
||||
setAllStatus(t('player__buffering'))
|
||||
}
|
||||
|
||||
const handleError = (errCode?: number) => {
|
||||
if (!musicInfo.id) return
|
||||
clearLoadingTimeout()
|
||||
if (window.lx.isPlayedStop) return
|
||||
if (!isEmpty()) setStop()
|
||||
if (playMusicInfo.musicInfo && errCode !== 1 && retryNum < 2) { // 若音频URL无效则尝试刷新2次URL
|
||||
// console.log(this.retryNum)
|
||||
retryNum++
|
||||
setMusicUrl(playMusicInfo.musicInfo, true)
|
||||
setAllStatus(t('player__refresh_url'))
|
||||
return
|
||||
}
|
||||
|
||||
if (appSetting['player.autoSkipOnError']) {
|
||||
if (document.hidden) {
|
||||
console.warn('error skip to next')
|
||||
void playNext(true)
|
||||
} else {
|
||||
setAllStatus(t('player__error'))
|
||||
setTimeout(addDelayNextTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleSetPlayInfo = () => {
|
||||
retryNum = 0
|
||||
prevTimeoutId = null
|
||||
clearDelayNextTimeout()
|
||||
clearLoadingTimeout()
|
||||
}
|
||||
|
||||
// const handlePlayedStop = () => {
|
||||
// clearDelayNextTimeout()
|
||||
// clearLoadingTimeout()
|
||||
// }
|
||||
|
||||
|
||||
window.app_event.on('playerLoadstart', handleLoadstart)
|
||||
window.app_event.on('playerLoadeddata', handleLoadeddata)
|
||||
window.app_event.on('playerCanplay', handleCanplay)
|
||||
window.app_event.on('playerPlaying', handlePlaying)
|
||||
window.app_event.on('playerWaiting', handleWating)
|
||||
window.app_event.on('playerEmptied', handleEmpied)
|
||||
window.app_event.on('playerError', handleError)
|
||||
window.app_event.on('musicToggled', handleSetPlayInfo)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.app_event.off('playerLoadstart', handleLoadstart)
|
||||
window.app_event.off('playerLoadeddata', handleLoadeddata)
|
||||
window.app_event.off('playerCanplay', handleCanplay)
|
||||
window.app_event.off('playerPlaying', handlePlaying)
|
||||
window.app_event.off('playerWaiting', handleWating)
|
||||
window.app_event.off('playerEmptied', handleEmpied)
|
||||
window.app_event.off('playerError', handleError)
|
||||
window.app_event.off('musicToggled', handleSetPlayInfo)
|
||||
})
|
||||
}
|
||||
+81
-58
@@ -1,55 +1,66 @@
|
||||
import { onBeforeUnmount, watch, useCommit } from '@renderer/utils/vueTools'
|
||||
import { formatPlayTime2, getRandom, throttle } from '@renderer/utils'
|
||||
import { setTaskBarProgress, wait, waitCancel, savePlayInfo } from '@renderer/utils/tools'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||
import { formatPlayTime2, getRandom } from '@common/utils/common'
|
||||
import { throttle } from '@common/utils'
|
||||
import { setTaskBarProgress, savePlayInfo } from '@renderer/utils/ipc'
|
||||
import { onTimeupdate, getCurrentTime, getDuration, setCurrentTime, onVisibilityChange } from '@renderer/plugins/player'
|
||||
import { playProgress, setNowPlayTime, setMaxplayTime } from '@renderer/core/share/playProgress'
|
||||
import { musicInfo, musicInfoItem, playMusicInfo, playInfo } from '@renderer/core/share/player'
|
||||
// import { getList } from '@renderer/core/share/utils'
|
||||
import { playProgress, setNowPlayTime, setMaxplayTime } from '@renderer/store/player/playProgress'
|
||||
import { musicInfo, playMusicInfo, playInfo } from '@renderer/store/player/state'
|
||||
// import { getList } from '@renderer/store/utils'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { playNext } from '@renderer/core/player'
|
||||
import { updateListMusics } from '@renderer/store/list/action'
|
||||
|
||||
const delaySavePlayInfo = throttle(savePlayInfo, 2000)
|
||||
|
||||
export default ({ setting, playNext }) => {
|
||||
export default () => {
|
||||
let restorePlayTime = 0
|
||||
let prevProgressStatus = 'none'
|
||||
const mediaBuffer = {
|
||||
let prevProgressStatus: Electron.ProgressBarOptions['mode'] = 'none'
|
||||
const mediaBuffer: {
|
||||
timeout: NodeJS.Timeout | null
|
||||
playTime: number
|
||||
} = {
|
||||
timeout: null,
|
||||
playTime: 0,
|
||||
}
|
||||
|
||||
const updateMusicInfo = useCommit('list', 'updateMusicInfo')
|
||||
// const updateMusicInfo = useCommit('list', 'updateMusicInfo')
|
||||
|
||||
const startBuffering = () => {
|
||||
console.log('start t')
|
||||
if (mediaBuffer.timeout) return
|
||||
mediaBuffer.timeout = Math.random()
|
||||
wait(3000, mediaBuffer.timeout).then(() => {
|
||||
mediaBuffer.timeout = setTimeout(() => {
|
||||
mediaBuffer.timeout = null
|
||||
if (window.lx.isPlayedStop) return
|
||||
const currentTime = getCurrentTime()
|
||||
|
||||
if (!mediaBuffer.playTime) mediaBuffer.playTime = currentTime
|
||||
let skipTime = currentTime + getRandom(3, 6)
|
||||
if (skipTime > playProgress.maxPlayTime) skipTime = (playProgress.maxPlayTime - currentTime) / 2
|
||||
if (skipTime - mediaBuffer.playTime < 1 || playProgress.maxPlayTime - skipTime < 1) {
|
||||
mediaBuffer.playTime = 0
|
||||
if (setting.value.player.autoSkipOnError) playNext()
|
||||
if (appSetting['player.autoSkipOnError']) {
|
||||
console.warn('buffering end')
|
||||
void playNext(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
startBuffering()
|
||||
setCurrentTime(skipTime)
|
||||
console.log(mediaBuffer.playTime)
|
||||
console.log(currentTime)
|
||||
}).catch(_ => _)
|
||||
}, 3000)
|
||||
}
|
||||
const clearBufferTimeout = () => {
|
||||
console.log('clear t')
|
||||
if (!mediaBuffer.timeout) return
|
||||
waitCancel(mediaBuffer.timeout)
|
||||
clearTimeout(mediaBuffer.timeout)
|
||||
mediaBuffer.timeout = null
|
||||
mediaBuffer.playTime = 0
|
||||
}
|
||||
|
||||
const setProgress = (time) => {
|
||||
if (!musicInfo.songmid) return
|
||||
const setProgress = (time: number, maxTime?: number) => {
|
||||
if (!musicInfo.id) return
|
||||
console.log('setProgress', time, maxTime)
|
||||
restorePlayTime = time
|
||||
if (mediaBuffer.playTime) {
|
||||
clearBufferTimeout()
|
||||
@@ -59,11 +70,13 @@ export default ({ setting, playNext }) => {
|
||||
setNowPlayTime(time)
|
||||
setCurrentTime(time)
|
||||
|
||||
if (maxTime != null) setMaxplayTime(maxTime)
|
||||
|
||||
// if (!isPlay) audio.play()
|
||||
}
|
||||
|
||||
const handleSetTaskBarState = (progress, status) => {
|
||||
if (setting.value.player.isShowTaskProgess) setTaskBarProgress(progress, status)
|
||||
const handleSetTaskBarState = (progress: number, status?: Electron.ProgressBarOptions['mode']) => {
|
||||
if (appSetting['player.isShowTaskProgess']) setTaskBarProgress(progress, status)
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
@@ -85,6 +98,7 @@ export default ({ setting, playNext }) => {
|
||||
|
||||
const handleError = () => {
|
||||
if (!restorePlayTime) restorePlayTime = getCurrentTime() // 记录出错的播放时间
|
||||
console.log('handleError')
|
||||
prevProgressStatus = 'error'
|
||||
handleSetTaskBarState(playProgress.progress, prevProgressStatus)
|
||||
}
|
||||
@@ -92,22 +106,30 @@ export default ({ setting, playNext }) => {
|
||||
const handleLoadeddata = () => {
|
||||
setMaxplayTime(getDuration())
|
||||
|
||||
console.log('handleLoadeddata', restorePlayTime)
|
||||
if (restorePlayTime) {
|
||||
setCurrentTime(restorePlayTime)
|
||||
restorePlayTime = 0
|
||||
}
|
||||
|
||||
if (!musicInfoItem.value.interval && playMusicInfo.listId != 'download') {
|
||||
updateMusicInfo({
|
||||
listId: playMusicInfo.listId,
|
||||
id: musicInfo.songmid,
|
||||
musicInfo: musicInfoItem.value,
|
||||
data: { interval: formatPlayTime2(playProgress.maxPlayTime) },
|
||||
})
|
||||
if (playMusicInfo.musicInfo && 'source' in playMusicInfo.musicInfo && !playMusicInfo.musicInfo.interval) {
|
||||
console.log(formatPlayTime2(playProgress.maxPlayTime))
|
||||
|
||||
if (playMusicInfo.listId) {
|
||||
void updateListMusics([{
|
||||
id: playMusicInfo.listId,
|
||||
musicInfo: {
|
||||
...playMusicInfo.musicInfo,
|
||||
interval: formatPlayTime2(playProgress.maxPlayTime),
|
||||
},
|
||||
}])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleCanplay = () => {
|
||||
console.log('handleCanplay', mediaBuffer.playTime)
|
||||
clearBufferTimeout()
|
||||
if (mediaBuffer.playTime) {
|
||||
let playTime = mediaBuffer.playTime
|
||||
mediaBuffer.playTime = 0
|
||||
@@ -123,11 +145,12 @@ export default ({ setting, playNext }) => {
|
||||
clearBufferTimeout()
|
||||
}
|
||||
|
||||
const handleSetPlayInfo = ({ musicInfo, progress }) => {
|
||||
setNowPlayTime(restorePlayTime = progress.time)
|
||||
setMaxplayTime(progress.maxTime)
|
||||
const handleSetPlayInfo = () => {
|
||||
// restorePlayTime = playProgress.nowPlayTime
|
||||
setCurrentTime(restorePlayTime = playProgress.nowPlayTime)
|
||||
// setMaxplayTime(playProgress.maxPlayTime)
|
||||
handlePause()
|
||||
if (!playMusicInfo.isTempPlay) {
|
||||
if (!playMusicInfo.isTempPlay && playMusicInfo.listId) {
|
||||
delaySavePlayInfo({
|
||||
time: playProgress.nowPlayTime,
|
||||
maxTime: playProgress.maxPlayTime,
|
||||
@@ -142,12 +165,12 @@ export default ({ setting, playNext }) => {
|
||||
handleSetTaskBarState(newValue, prevProgressStatus)
|
||||
})
|
||||
watch(() => playProgress.nowPlayTime, (newValue, oldValue) => {
|
||||
if (Math.abs(newValue - oldValue) > 2) window.eventHub.emit(eventPlayerNames.activeTransition)
|
||||
if (setting.value.player.isSavePlayTime && !playMusicInfo.isTempPlay) {
|
||||
if (Math.abs(newValue - oldValue) > 2) window.app_event.activePlayProgressTransition()
|
||||
if (appSetting['player.isSavePlayTime'] && !playMusicInfo.isTempPlay) {
|
||||
delaySavePlayInfo({
|
||||
time: newValue,
|
||||
maxTime: playProgress.maxPlayTime,
|
||||
listId: playMusicInfo.listId,
|
||||
listId: playMusicInfo.listId as string,
|
||||
index: playInfo.playIndex,
|
||||
})
|
||||
}
|
||||
@@ -157,23 +180,23 @@ export default ({ setting, playNext }) => {
|
||||
delaySavePlayInfo({
|
||||
time: playProgress.nowPlayTime,
|
||||
maxTime: maxPlayTime,
|
||||
listId: playMusicInfo.listId,
|
||||
listId: playMusicInfo.listId as string,
|
||||
index: playInfo.playIndex,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
window.eventHub.on(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.on(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.on(eventPlayerNames.stop, handleStop)
|
||||
window.eventHub.on(eventPlayerNames.error, handleError)
|
||||
window.eventHub.on(eventPlayerNames.setProgress, setProgress)
|
||||
// window.eventHub.on(eventPlayerNames.restorePlay, handleRestorePlay)
|
||||
window.eventHub.on(eventPlayerNames.player_loadeddata, handleLoadeddata)
|
||||
window.eventHub.on(eventPlayerNames.player_canplay, handleCanplay)
|
||||
window.eventHub.on(eventPlayerNames.player_waiting, handleWating)
|
||||
window.eventHub.on(eventPlayerNames.player_emptied, handleEmpied)
|
||||
window.eventHub.on(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
window.app_event.on('play', handlePlay)
|
||||
window.app_event.on('pause', handlePause)
|
||||
window.app_event.on('stop', handleStop)
|
||||
window.app_event.on('error', handleError)
|
||||
window.app_event.on('setProgress', setProgress)
|
||||
// window.app_event.on(eventPlayerNames.restorePlay, handleRestorePlay)
|
||||
window.app_event.on('playerLoadeddata', handleLoadeddata)
|
||||
window.app_event.on('playerCanplay', handleCanplay)
|
||||
window.app_event.on('playerWaiting', handleWating)
|
||||
window.app_event.on('playerEmptied', handleEmpied)
|
||||
window.app_event.on('musicToggled', handleSetPlayInfo)
|
||||
|
||||
const rOnTimeupdate = onTimeupdate(() => {
|
||||
setNowPlayTime(getCurrentTime())
|
||||
@@ -185,7 +208,7 @@ export default ({ setting, playNext }) => {
|
||||
currentPlayTime = playProgress.nowPlayTime
|
||||
} else {
|
||||
if (Math.abs(playProgress.nowPlayTime - currentPlayTime) > 2) {
|
||||
window.eventHub.emit(eventPlayerNames.activeTransition)
|
||||
window.app_event.activePlayProgressTransition()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -193,16 +216,16 @@ export default ({ setting, playNext }) => {
|
||||
onBeforeUnmount(() => {
|
||||
rOnTimeupdate()
|
||||
rVisibilityChange()
|
||||
window.eventHub.off(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.off(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.off(eventPlayerNames.stop, handleStop)
|
||||
window.eventHub.off(eventPlayerNames.error, handleError)
|
||||
window.eventHub.off(eventPlayerNames.setProgress, setProgress)
|
||||
// window.eventHub.off(eventPlayerNames.restorePlay, handleRestorePlay)
|
||||
window.eventHub.off(eventPlayerNames.player_loadeddata, handleLoadeddata)
|
||||
window.eventHub.off(eventPlayerNames.player_canplay, handleCanplay)
|
||||
window.eventHub.off(eventPlayerNames.player_waiting, handleWating)
|
||||
window.eventHub.off(eventPlayerNames.player_emptied, handleEmpied)
|
||||
window.eventHub.off(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
window.app_event.off('play', handlePlay)
|
||||
window.app_event.off('pause', handlePause)
|
||||
window.app_event.off('stop', handleStop)
|
||||
window.app_event.off('error', handleError)
|
||||
window.app_event.off('setProgress', setProgress)
|
||||
// window.app_event.off(eventPlayerNames.restorePlay, handleRestorePlay)
|
||||
window.app_event.off('playerLoadeddata', handleLoadeddata)
|
||||
window.app_event.off('playerCanplay', handleCanplay)
|
||||
window.app_event.off('playerWaiting', handleWating)
|
||||
window.app_event.off('playerEmptied', handleEmpied)
|
||||
window.app_event.off('musicToggled', handleSetPlayInfo)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { setPlayerAction, onPlayerAction } from '@renderer/utils/ipc'
|
||||
// import store from '@renderer/store'
|
||||
|
||||
import { loveList } from '@renderer/store/list/state'
|
||||
import { addListMusics, removeListMusics, checkListExistMusic } from '@renderer/store/list/action'
|
||||
import { playMusicInfo } from '@renderer/store/player/state'
|
||||
import { throttle } from '@common/utils'
|
||||
import { pause, play, playNext, playPrev } from '@renderer/core/player'
|
||||
|
||||
export default () => {
|
||||
// const setVisibleDesktopLyric = useCommit('setVisibleDesktopLyric')
|
||||
// const setLockDesktopLyric = useCommit('setLockDesktopLyric')
|
||||
|
||||
const buttons = {
|
||||
empty: true,
|
||||
collect: false,
|
||||
play: false,
|
||||
prev: true,
|
||||
next: true,
|
||||
lrc: false,
|
||||
lockLrc: false,
|
||||
}
|
||||
const setButtons = () => {
|
||||
setPlayerAction(buttons)
|
||||
}
|
||||
const updateCollectStatus = async() => {
|
||||
let status = !!playMusicInfo.musicInfo && await checkListExistMusic(loveList.id, playMusicInfo.musicInfo.id)
|
||||
if (buttons.collect == status) return false
|
||||
buttons.collect = status
|
||||
return true
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
if (buttons.empty) buttons.empty = false
|
||||
buttons.play = true
|
||||
setButtons()
|
||||
}
|
||||
const handlePause = () => {
|
||||
if (buttons.empty) buttons.empty = false
|
||||
buttons.play = false
|
||||
setButtons()
|
||||
}
|
||||
const handleStop = () => {
|
||||
if (playMusicInfo.musicInfo != null) return
|
||||
if (buttons.collect) buttons.collect = false
|
||||
buttons.empty = true
|
||||
setButtons()
|
||||
}
|
||||
const handleSetPlayInfo = () => {
|
||||
void updateCollectStatus().then(isExist => {
|
||||
if (isExist) setButtons()
|
||||
})
|
||||
}
|
||||
// const handleSetTaskbarThumbnailClip = (clip) => {
|
||||
// setTaskbarThumbnailClip(clip)
|
||||
// }
|
||||
const throttleListChange = throttle(async listIds => {
|
||||
if (!listIds.includes(loveList.id)) return
|
||||
if (await updateCollectStatus()) setButtons()
|
||||
})
|
||||
// const updateSetting = () => {
|
||||
// const setting = store.getters.setting
|
||||
// buttons.lrc = setting.desktopLyric.enable
|
||||
// buttons.lockLrc = setting.desktopLyric.isLock
|
||||
// setButtons()
|
||||
// }
|
||||
const rTaskbarThumbarClick = onPlayerAction(async({ params: action }) => {
|
||||
switch (action) {
|
||||
case 'play':
|
||||
play()
|
||||
break
|
||||
case 'pause':
|
||||
pause()
|
||||
break
|
||||
case 'prev':
|
||||
void playPrev()
|
||||
break
|
||||
case 'next':
|
||||
void playNext()
|
||||
break
|
||||
case 'collect':
|
||||
if (!playMusicInfo.musicInfo) return
|
||||
void addListMusics(loveList.id, ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo : playMusicInfo.musicInfo])
|
||||
if (await updateCollectStatus()) setButtons()
|
||||
break
|
||||
case 'unCollect':
|
||||
if (!playMusicInfo.musicInfo) return
|
||||
void removeListMusics({ listId: loveList.id, ids: ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo.id : playMusicInfo.musicInfo.id] })
|
||||
if (await updateCollectStatus()) setButtons()
|
||||
break
|
||||
// case 'lrc':
|
||||
// setVisibleDesktopLyric(true)
|
||||
// updateSetting()
|
||||
// break
|
||||
// case 'unLrc':
|
||||
// setVisibleDesktopLyric(false)
|
||||
// updateSetting()
|
||||
// break
|
||||
// case 'lockLrc':
|
||||
// setLockDesktopLyric(true)
|
||||
// updateSetting()
|
||||
// break
|
||||
// case 'unlockLrc':
|
||||
// setLockDesktopLyric(false)
|
||||
// updateSetting()
|
||||
// break
|
||||
}
|
||||
})
|
||||
window.app_event.on('play', handlePlay)
|
||||
window.app_event.on('pause', handlePause)
|
||||
window.app_event.on('stop', handleStop)
|
||||
window.app_event.on('musicToggled', handleSetPlayInfo)
|
||||
// window.app_event.on(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip)
|
||||
window.app_event.on('myListUpdate', throttleListChange)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rTaskbarThumbarClick()
|
||||
window.app_event.off('play', handlePlay)
|
||||
window.app_event.off('pause', handlePause)
|
||||
window.app_event.off('stop', handleStop)
|
||||
window.app_event.off('musicToggled', handleSetPlayInfo)
|
||||
// window.app_event.off(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip)
|
||||
window.app_event.off('myListUpdate', throttleListChange)
|
||||
})
|
||||
|
||||
return async() => {
|
||||
// const setting = store.getters.setting
|
||||
// buttons.lrc = setting.desktopLyric.enable
|
||||
// buttons.lockLrc = setting.desktopLyric.isLock
|
||||
await updateCollectStatus()
|
||||
if (playMusicInfo.musicInfo != null) buttons.empty = false
|
||||
setButtons()
|
||||
}
|
||||
}
|
||||
@@ -1,404 +0,0 @@
|
||||
import { onBeforeUnmount, useI18n, watch, useCommit, useAction } from '@renderer/utils/vueTools'
|
||||
import { setTitle, checkPath } from '@renderer/utils'
|
||||
import { langS2T, wait, waitCancel } from '@renderer/utils/tools'
|
||||
|
||||
import {
|
||||
setStop as setPlayerStop,
|
||||
setPause as setPlayerPause,
|
||||
setPlay as setPlayerPlay,
|
||||
setResource,
|
||||
isEmpty as isPlayerEmpty,
|
||||
setLoopPlay,
|
||||
} from '@renderer/plugins/player'
|
||||
|
||||
import { player as eventKeyPlayerNames } from '@common/hotKey'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
|
||||
import useMediaSessionInfo from './useMediaSessionInfo'
|
||||
import usePlayProgress from './usePlayProgress'
|
||||
import usePlayEvent from './usePlayEvent'
|
||||
import { requestMsg } from '@renderer/utils/message'
|
||||
|
||||
import {
|
||||
isPlay,
|
||||
setPlay,
|
||||
setAllStatus,
|
||||
musicInfo,
|
||||
setMusicInfo,
|
||||
musicInfoItem,
|
||||
playMusicInfo,
|
||||
setPlayList,
|
||||
setPlayMusicInfo,
|
||||
playedList,
|
||||
} from '@renderer/core/share/player'
|
||||
import { downloadList } from '@renderer/core/share/download'
|
||||
import { qualityList } from '@renderer/core/share'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
|
||||
import path from 'path'
|
||||
import useLyric from './useLyric'
|
||||
import useVolume from './useVolume'
|
||||
import useWatchList from './useWatchList'
|
||||
|
||||
|
||||
const getPlayType = (highQuality, songInfo) => {
|
||||
let type = '128k'
|
||||
let list = qualityList.value[songInfo.source]
|
||||
if (highQuality && songInfo._types['320k'] && list && list.includes('320k')) type = '320k'
|
||||
return type
|
||||
}
|
||||
|
||||
const useDelayNextTimeout = ({ playNext, timeout }) => {
|
||||
let delayNextTimeout
|
||||
const clearDelayNextTimeout = () => {
|
||||
// console.log(this.delayNextTimeout)
|
||||
if (delayNextTimeout) {
|
||||
waitCancel(delayNextTimeout)
|
||||
delayNextTimeout = null
|
||||
}
|
||||
}
|
||||
|
||||
const addDelayNextTimeout = () => {
|
||||
clearDelayNextTimeout()
|
||||
delayNextTimeout = Math.random()
|
||||
wait(timeout, delayNextTimeout).then(() => {
|
||||
delayNextTimeout = null
|
||||
playNext()
|
||||
}).catch(_ => _)
|
||||
}
|
||||
|
||||
return {
|
||||
clearDelayNextTimeout,
|
||||
addDelayNextTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
export default ({ setting }) => {
|
||||
const { t } = useI18n()
|
||||
|
||||
const playNext = useAction('player', 'playNext')
|
||||
const playPrev = useAction('player', 'playPrev')
|
||||
const getUrl = useAction('player', 'getUrl')
|
||||
const getPic = useAction('player', 'getPic')
|
||||
const getLrc = useAction('player', 'getLrc')
|
||||
|
||||
const clearPlayedList = useCommit('player', 'clearPlayedList')
|
||||
const setPlayedList = useCommit('player', 'setPlayedList')
|
||||
const { addDelayNextTimeout, clearDelayNextTimeout } = useDelayNextTimeout({ playNext, timeout: 5000 })
|
||||
const { addDelayNextTimeout: addLoadTimeout, clearDelayNextTimeout: clearLoadTimeout } = useDelayNextTimeout({ playNext, timeout: 123000 })
|
||||
|
||||
let isGettingUrl = false
|
||||
const setUrl = (targetSong, isRefresh, isRetryed = false) => {
|
||||
let type = getPlayType(setting.value.player.highQuality, targetSong)
|
||||
// this.musicInfo.url = await getMusicUrl(targetSong, type)
|
||||
setAllStatus(t('player__geting_url'))
|
||||
if (setting.value.player.autoSkipOnError) addLoadTimeout()
|
||||
|
||||
isGettingUrl = true
|
||||
return getUrl({
|
||||
musicInfo: targetSong,
|
||||
type,
|
||||
isRefresh,
|
||||
onToggleSource() {
|
||||
if (targetSong !== musicInfoItem.value || isPlay.value || type != getPlayType(setting.value.player.highQuality, musicInfoItem.value)) return
|
||||
setAllStatus('Try toggle source...')
|
||||
},
|
||||
}).then(url => {
|
||||
if (global.isPlayedStop) return
|
||||
if (targetSong !== musicInfoItem.value || isPlay.value || type != getPlayType(setting.value.player.highQuality, musicInfoItem.value)) return
|
||||
setMusicInfo({ url })
|
||||
setResource(url)
|
||||
}).catch(err => {
|
||||
// console.log('err', err.message)
|
||||
if (global.isPlayedStop) return
|
||||
if (targetSong !== musicInfoItem.value || isPlay.value) return
|
||||
if (err.message == requestMsg.cancelRequest) return
|
||||
if (!isRetryed) return setUrl(targetSong, isRefresh, true)
|
||||
setAllStatus(err.message)
|
||||
if (setting.value.player.autoSkipOnError) addDelayNextTimeout()
|
||||
return Promise.reject(err)
|
||||
}).finally(() => {
|
||||
clearLoadTimeout()
|
||||
if (targetSong === musicInfoItem.value) isGettingUrl = false
|
||||
})
|
||||
}
|
||||
const setImg = ({ listId, musicInfo: targetSong }) => {
|
||||
if (targetSong.img) {
|
||||
setMusicInfo({ img: targetSong.img })
|
||||
} else {
|
||||
getPic({ musicInfo: targetSong, listId }).then(() => {
|
||||
if (targetSong.songmid !== musicInfo.songmid) return
|
||||
setMusicInfo({ img: targetSong.img })
|
||||
|
||||
window.eventHub.emit(eventPlayerNames.updatePic, musicInfo)
|
||||
})
|
||||
}
|
||||
}
|
||||
const setLrc = (targetSong) => {
|
||||
getLrc(targetSong).then(({ lyric, tlyric, rlyric, lxlyric, rawInfo }) => {
|
||||
if (targetSong.songmid !== musicInfo.songmid) return
|
||||
return (
|
||||
setting.value.player.isS2t
|
||||
? Promise.all([
|
||||
lyric ? langS2T(lyric) : Promise.resolve(''),
|
||||
tlyric ? langS2T(tlyric) : Promise.resolve(''),
|
||||
rlyric ? langS2T(rlyric) : Promise.resolve(''),
|
||||
lxlyric ? langS2T(lxlyric) : Promise.resolve(''),
|
||||
])
|
||||
: Promise.resolve([lyric, tlyric, rlyric, lxlyric])
|
||||
).then(([lyric, tlyric, rlyric, lxlyric]) => {
|
||||
setMusicInfo({
|
||||
lrc: lyric,
|
||||
tlrc: tlyric,
|
||||
rlrc: rlyric,
|
||||
lxlrc: lxlyric,
|
||||
rawlrc: rawInfo.lyric,
|
||||
})
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
if (targetSong.songmid !== musicInfo.songmid) return
|
||||
setAllStatus(t('lyric__load_error'))
|
||||
}).finally(() => {
|
||||
if (targetSong.songmid !== musicInfo.songmid) return
|
||||
window.eventHub.emit(eventPlayerNames.updateLyric, musicInfo)
|
||||
})
|
||||
}
|
||||
|
||||
usePlayProgress({ setting, playNext })
|
||||
useMediaSessionInfo({ playPrev, playNext })
|
||||
usePlayEvent({
|
||||
setting,
|
||||
playNext,
|
||||
setAllStatus,
|
||||
setUrl,
|
||||
})
|
||||
useLyric({
|
||||
setting,
|
||||
})
|
||||
useVolume({ setting })
|
||||
useWatchList({ playNext })
|
||||
|
||||
// 恢复上次播放的状态
|
||||
const handleRestorePlay = async(restorePlayInfo) => {
|
||||
if (!restorePlayInfo.listId) return
|
||||
const list = getList(restorePlayInfo.listId)
|
||||
setPlayList(restorePlayInfo.listId)
|
||||
setPlayMusicInfo(restorePlayInfo.listId, list[restorePlayInfo.index])
|
||||
|
||||
window.eventHub.emit(eventPlayerNames.setPlayInfo, {
|
||||
musicInfo: musicInfoItem.value,
|
||||
progress: {
|
||||
time: setting.value.player.isSavePlayTime ? (restorePlayInfo.time || 0) : 0,
|
||||
maxTime: restorePlayInfo.maxTime || 0,
|
||||
},
|
||||
})
|
||||
|
||||
setImg({ musicInfo: musicInfoItem.value, listId: playMusicInfo.listId })
|
||||
setLrc(musicInfoItem.value)
|
||||
if (setting.value.player.togglePlayMethod == 'random') setPlayedList({ ...playMusicInfo })
|
||||
}
|
||||
|
||||
const setPlayStatus = () => {
|
||||
setPlay(true)
|
||||
}
|
||||
const setPauseStatus = () => {
|
||||
setPlay(false)
|
||||
if (global.isPlayedStop) handlePause()
|
||||
}
|
||||
const setStopStatus = () => {
|
||||
setPlay(false)
|
||||
setTitle()
|
||||
setAllStatus('')
|
||||
setMusicInfo({
|
||||
songmid: null,
|
||||
img: null,
|
||||
lrc: null,
|
||||
tlrc: null,
|
||||
rlrc: null,
|
||||
lxlrc: null,
|
||||
rawlrc: null,
|
||||
url: null,
|
||||
name: '',
|
||||
singer: '',
|
||||
album: '',
|
||||
})
|
||||
}
|
||||
|
||||
// 播放音乐
|
||||
const playMusic = async() => {
|
||||
// console.log('playMusic')
|
||||
isGettingUrl = false
|
||||
setStopStatus()
|
||||
if (window.restorePlayInfo) {
|
||||
handleRestorePlay(window.restorePlayInfo)
|
||||
window.restorePlayInfo = null
|
||||
return
|
||||
}
|
||||
|
||||
if (playMusicInfo.musicInfo) {
|
||||
setPlayerStop()
|
||||
window.eventHub.emit(eventPlayerNames.pause)
|
||||
setStopStatus()
|
||||
} else {
|
||||
window.eventHub.emit(eventPlayerNames.setStop)
|
||||
}
|
||||
|
||||
clearDelayNextTimeout()
|
||||
|
||||
let targetSong = playMusicInfo.musicInfo
|
||||
|
||||
if (setting.value.player.togglePlayMethod == 'random' && !playMusicInfo.isTempPlay) setPlayedList({ ...playMusicInfo })
|
||||
|
||||
if (targetSong.key) { // 如果是已下载的歌曲
|
||||
const filePath = path.join(setting.value.download.savePath, targetSong.metadata.fileName)
|
||||
// console.log(filePath)
|
||||
|
||||
if (!await checkPath(filePath) || !targetSong.isComplate || /\.ape$/.test(filePath)) {
|
||||
return getList(playMusicInfo.listId).length == 1 ? null : playNext()
|
||||
}
|
||||
window.eventHub.emit(eventPlayerNames.setPlayInfo, {
|
||||
musicInfo: musicInfoItem.value,
|
||||
progress: {
|
||||
time: 0,
|
||||
maxTime: 0,
|
||||
},
|
||||
})
|
||||
setResource(filePath)
|
||||
// console.log(filePath)
|
||||
} else {
|
||||
// if (!this.assertApiSupport(targetSong.source)) return this.playNext()
|
||||
window.eventHub.emit(eventPlayerNames.setPlayInfo, {
|
||||
musicInfo: musicInfoItem.value,
|
||||
progress: {
|
||||
time: 0,
|
||||
maxTime: 0,
|
||||
},
|
||||
})
|
||||
setUrl(musicInfoItem.value)
|
||||
}
|
||||
|
||||
setImg({ musicInfo: musicInfoItem.value, listId: playMusicInfo.listId })
|
||||
setLrc(musicInfoItem.value)
|
||||
}
|
||||
|
||||
const handleSetPlayInfo = ({ musicInfo }) => {
|
||||
setMusicInfo({
|
||||
songmid: musicInfo.songmid,
|
||||
singer: musicInfo.singer,
|
||||
name: musicInfo.name,
|
||||
album: musicInfo.albumName,
|
||||
})
|
||||
setTitle(`${musicInfo.name} - ${musicInfo.singer}`)
|
||||
}
|
||||
|
||||
const handelStop = () => {
|
||||
setPlayerStop()
|
||||
setPlayMusicInfo(playMusicInfo.listId, null)
|
||||
window.eventHub.emit(eventPlayerNames.stop)
|
||||
}
|
||||
|
||||
const handleEnded = () => {
|
||||
setAllStatus(t('player__end'))
|
||||
|
||||
if (global.isPlayedStop) return
|
||||
playNext()
|
||||
}
|
||||
|
||||
const handlePause = () => {
|
||||
setPlayerPause()
|
||||
}
|
||||
|
||||
const handlePlay = async() => {
|
||||
if (playMusicInfo.musicInfo == null) return
|
||||
if (isPlayerEmpty()) {
|
||||
if (playMusicInfo.listId == 'download') {
|
||||
const musicInfo = playMusicInfo.musicInfo
|
||||
const filePath = path.join(setting.value.download.savePath, musicInfo.metadata.fileName)
|
||||
if (!await checkPath(filePath) || !musicInfo.isComplate || /\.ape$/.test(filePath)) {
|
||||
if (downloadList.length == 1) {
|
||||
window.eventHub.emit(eventPlayerNames.setStop)
|
||||
} else {
|
||||
playNext()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!isGettingUrl) setResource(filePath)
|
||||
} else {
|
||||
// if (!this.assertApiSupport(this.targetSong.source)) return this.playNext()
|
||||
if (!isGettingUrl) setUrl(musicInfoItem.value)
|
||||
}
|
||||
return
|
||||
}
|
||||
setPlayerPlay()
|
||||
}
|
||||
|
||||
// 播放、暂停播放切换
|
||||
const handleTogglePlay = () => {
|
||||
if (global.isPlayedStop) global.isPlayedStop = false
|
||||
if (isPlay.value) {
|
||||
handlePause()
|
||||
} else {
|
||||
handlePlay()
|
||||
}
|
||||
}
|
||||
|
||||
const handlePlayedStop = () => {
|
||||
clearDelayNextTimeout()
|
||||
clearLoadTimeout()
|
||||
}
|
||||
|
||||
watch(() => setting.value.player.togglePlayMethod, newValue => {
|
||||
setLoopPlay(newValue === 'singleLoop')
|
||||
if (playedList.length) clearPlayedList()
|
||||
if (newValue == 'random' && playMusicInfo.musicInfo && !playMusicInfo.isTempPlay) setPlayedList({ ...playMusicInfo })
|
||||
})
|
||||
|
||||
setLoopPlay(setting.value.player.togglePlayMethod === 'singleLoop')
|
||||
|
||||
|
||||
window.eventHub.on(eventKeyPlayerNames.next.action, playNext)
|
||||
window.eventHub.on(eventKeyPlayerNames.prev.action, playPrev)
|
||||
window.eventHub.on(eventKeyPlayerNames.toggle_play.action, handleTogglePlay)
|
||||
|
||||
window.eventHub.on(eventPlayerNames.play, setPlayStatus)
|
||||
window.eventHub.on(eventPlayerNames.pause, setPauseStatus)
|
||||
window.eventHub.on(eventPlayerNames.error, setPauseStatus)
|
||||
window.eventHub.on(eventPlayerNames.stop, setStopStatus)
|
||||
|
||||
window.eventHub.on(eventPlayerNames.playMusic, playMusic)
|
||||
window.eventHub.on(eventPlayerNames.setPlay, handlePlay)
|
||||
window.eventHub.on(eventPlayerNames.setPause, handlePause)
|
||||
window.eventHub.on(eventPlayerNames.setStop, handelStop)
|
||||
window.eventHub.on(eventPlayerNames.setTogglePlay, handleTogglePlay)
|
||||
window.eventHub.on(eventPlayerNames.setPlayPrev, playPrev)
|
||||
window.eventHub.on(eventPlayerNames.setPlayNext, playNext)
|
||||
window.eventHub.on(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
|
||||
window.eventHub.on(eventPlayerNames.player_ended, handleEnded)
|
||||
window.eventHub.on(eventPlayerNames.playedStop, handlePlayedStop)
|
||||
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventKeyPlayerNames.next.action, playNext)
|
||||
window.eventHub.off(eventKeyPlayerNames.prev.action, playPrev)
|
||||
window.eventHub.off(eventKeyPlayerNames.toggle_play.action, handleTogglePlay)
|
||||
|
||||
window.eventHub.off(eventPlayerNames.play, setPlayStatus)
|
||||
window.eventHub.off(eventPlayerNames.pause, setPauseStatus)
|
||||
window.eventHub.off(eventPlayerNames.error, setPauseStatus)
|
||||
window.eventHub.off(eventPlayerNames.stop, setStopStatus)
|
||||
|
||||
window.eventHub.off(eventPlayerNames.playMusic, playMusic)
|
||||
window.eventHub.off(eventPlayerNames.setTogglePlay, handleTogglePlay)
|
||||
window.eventHub.off(eventPlayerNames.setPlay, handlePlay)
|
||||
window.eventHub.off(eventPlayerNames.setPause, handlePause)
|
||||
window.eventHub.off(eventPlayerNames.setStop, handelStop)
|
||||
window.eventHub.off(eventPlayerNames.setPlayPrev, playPrev)
|
||||
window.eventHub.off(eventPlayerNames.setPlayNext, playNext)
|
||||
window.eventHub.off(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
|
||||
window.eventHub.off(eventPlayerNames.player_ended, handleEnded)
|
||||
window.eventHub.off(eventPlayerNames.playedStop, handlePlayedStop)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||
import { useI18n } from '@renderer/plugins/i18n'
|
||||
import { setTitle } from '@renderer/utils'
|
||||
|
||||
import {
|
||||
setLoopPlay, setPause, setStop,
|
||||
} from '@renderer/plugins/player'
|
||||
|
||||
import useMediaSessionInfo from './useMediaSessionInfo'
|
||||
import usePlayProgress from './usePlayProgress'
|
||||
import usePlayEvent from './usePlayEvent'
|
||||
|
||||
import {
|
||||
musicInfo,
|
||||
playMusicInfo,
|
||||
playedList,
|
||||
} from '@renderer/store/player/state'
|
||||
import {
|
||||
setPlay,
|
||||
setAllStatus,
|
||||
addPlayedList,
|
||||
clearPlayedList,
|
||||
resetPlayerMusicInfo,
|
||||
} from '@renderer/store/player/action'
|
||||
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
import useLyric from './useLyric'
|
||||
import useVolume from './useVolume'
|
||||
import useWatchList from './useWatchList'
|
||||
import { HOTKEY_PLAYER } from '@common/hotKey'
|
||||
import { playNext, pause, playPrev, togglePlay } from '@renderer/core/player'
|
||||
|
||||
|
||||
export default () => {
|
||||
const t = useI18n()
|
||||
|
||||
usePlayProgress()
|
||||
useMediaSessionInfo()
|
||||
usePlayEvent()
|
||||
useLyric()
|
||||
useVolume()
|
||||
useWatchList()
|
||||
|
||||
const handlePlayNext = () => {
|
||||
void playNext()
|
||||
}
|
||||
const handlePlayPrev = () => {
|
||||
void playPrev()
|
||||
}
|
||||
|
||||
const setPlayStatus = () => {
|
||||
setPlay(true)
|
||||
}
|
||||
const setPauseStatus = () => {
|
||||
setPlay(false)
|
||||
if (window.lx.isPlayedStop) pause()
|
||||
}
|
||||
|
||||
const handleUpdatePlayInfo = () => {
|
||||
setTitle(musicInfo.id ? `${musicInfo.name} - ${musicInfo.singer}` : null)
|
||||
}
|
||||
|
||||
const handleCanplay = () => {
|
||||
if (window.lx.isPlayedStop) {
|
||||
setPause()
|
||||
}
|
||||
}
|
||||
const handleEnded = () => {
|
||||
// setTimeout(() => {
|
||||
if (window.lx.isPlayedStop) return setAllStatus(t('player__end'))
|
||||
resetPlayerMusicInfo()
|
||||
window.app_event.stop()
|
||||
setAllStatus(t('player__end'))
|
||||
void playNext(true)
|
||||
// })
|
||||
}
|
||||
|
||||
const setStopStatus = () => {
|
||||
setPlay(false)
|
||||
setTitle(null)
|
||||
setAllStatus('')
|
||||
setStop()
|
||||
}
|
||||
|
||||
watch(() => appSetting['player.togglePlayMethod'], newValue => {
|
||||
setLoopPlay(newValue == 'singleLoop')
|
||||
if (playedList.length) clearPlayedList()
|
||||
if (newValue == 'random' && playMusicInfo.musicInfo && !playMusicInfo.isTempPlay) addPlayedList({ ...(playMusicInfo as LX.Player.PlayMusicInfo) })
|
||||
})
|
||||
|
||||
setLoopPlay(appSetting['player.togglePlayMethod'] == 'singleLoop')
|
||||
|
||||
|
||||
window.key_event.on(HOTKEY_PLAYER.next.action, handlePlayNext)
|
||||
window.key_event.on(HOTKEY_PLAYER.prev.action, handlePlayPrev)
|
||||
window.key_event.on(HOTKEY_PLAYER.toggle_play.action, togglePlay)
|
||||
|
||||
window.app_event.on('play', setPlayStatus)
|
||||
window.app_event.on('pause', setPauseStatus)
|
||||
window.app_event.on('error', setPauseStatus)
|
||||
window.app_event.on('stop', setStopStatus)
|
||||
window.app_event.on('musicToggled', handleUpdatePlayInfo)
|
||||
window.app_event.on('playerCanplay', handleCanplay)
|
||||
|
||||
window.app_event.on('playerEnded', handleEnded)
|
||||
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
window.key_event.off(HOTKEY_PLAYER.next.action, handlePlayNext)
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
window.key_event.off(HOTKEY_PLAYER.prev.action, handlePlayPrev)
|
||||
window.key_event.off(HOTKEY_PLAYER.toggle_play.action, togglePlay)
|
||||
|
||||
window.app_event.off('play', setPlayStatus)
|
||||
window.app_event.off('pause', setPauseStatus)
|
||||
window.app_event.off('error', setPauseStatus)
|
||||
window.app_event.off('stop', setStopStatus)
|
||||
window.app_event.off('musicToggled', handleUpdatePlayInfo)
|
||||
window.app_event.on('playerCanplay', handleCanplay)
|
||||
|
||||
window.app_event.off('playerEnded', handleEnded)
|
||||
})
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import { onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
import {
|
||||
onPlaying,
|
||||
onPause,
|
||||
onEnded,
|
||||
onError,
|
||||
onLoadeddata,
|
||||
onLoadstart,
|
||||
onCanplay,
|
||||
onEmptied,
|
||||
onWaiting,
|
||||
getErrorCode,
|
||||
} from '@renderer/plugins/player'
|
||||
import { player } from '@renderer/event/names'
|
||||
|
||||
|
||||
export default () => {
|
||||
const rOnPlaying = onPlaying(() => {
|
||||
// console.log('onPlaying')
|
||||
window.eventHub.emit(player.player_playing)
|
||||
window.eventHub.emit(player.play)
|
||||
})
|
||||
const rOnPause = onPause(() => {
|
||||
// console.log('onPause')
|
||||
window.eventHub.emit(player.player_pause)
|
||||
window.eventHub.emit(player.pause)
|
||||
})
|
||||
const rOnEnded = onEnded(() => {
|
||||
// console.log('onEnded')
|
||||
window.eventHub.emit(player.player_ended)
|
||||
window.eventHub.emit(player.pause)
|
||||
})
|
||||
const rOnError = onError(() => {
|
||||
// console.log('onError')
|
||||
const errorCode = getErrorCode()
|
||||
window.eventHub.emit(player.player_error, errorCode)
|
||||
window.eventHub.emit(player.error, errorCode)
|
||||
})
|
||||
const rOnLoadeddata = onLoadeddata(() => {
|
||||
// console.log('onLoadeddata')
|
||||
window.eventHub.emit(player.player_loadeddata)
|
||||
})
|
||||
const rOnLoadstart = onLoadstart(() => {
|
||||
// console.log('onLoadstart')
|
||||
window.eventHub.emit(player.player_loadstart)
|
||||
})
|
||||
const rOnCanplay = onCanplay(() => {
|
||||
// console.log('onCanplay')
|
||||
window.eventHub.emit(player.player_canplay)
|
||||
})
|
||||
const rOnEmptied = onEmptied(() => {
|
||||
// console.log('onEmptied')
|
||||
window.eventHub.emit(player.player_emptied)
|
||||
// window.eventHub.emit(player.stop)
|
||||
})
|
||||
const rOnWaiting = onWaiting(() => {
|
||||
// console.log('onWaiting')
|
||||
window.eventHub.emit(player.player_waiting)
|
||||
window.eventHub.emit(player.pause)
|
||||
})
|
||||
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rOnPlaying()
|
||||
rOnPause()
|
||||
rOnEnded()
|
||||
rOnError()
|
||||
rOnLoadeddata()
|
||||
rOnLoadstart()
|
||||
rOnCanplay()
|
||||
rOnEmptied()
|
||||
rOnWaiting()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import {
|
||||
onPlaying,
|
||||
onPause,
|
||||
onEnded,
|
||||
onError,
|
||||
onLoadeddata,
|
||||
onLoadstart,
|
||||
onCanplay,
|
||||
onEmptied,
|
||||
onWaiting,
|
||||
getErrorCode,
|
||||
} from '@renderer/plugins/player'
|
||||
|
||||
|
||||
export default () => {
|
||||
const rOnPlaying = onPlaying(() => {
|
||||
console.log('onPlaying')
|
||||
window.app_event.playerPlaying()
|
||||
window.app_event.play()
|
||||
})
|
||||
const rOnPause = onPause(() => {
|
||||
console.log('onPause')
|
||||
window.app_event.playerPause()
|
||||
window.app_event.pause()
|
||||
})
|
||||
const rOnEnded = onEnded(() => {
|
||||
console.log('onEnded')
|
||||
window.app_event.playerEnded()
|
||||
// window.app_event.pause()
|
||||
})
|
||||
const rOnError = onError(() => {
|
||||
console.log('onError')
|
||||
const errorCode = getErrorCode()
|
||||
window.app_event.error(errorCode)
|
||||
window.app_event.playerError(errorCode)
|
||||
})
|
||||
const rOnLoadeddata = onLoadeddata(() => {
|
||||
console.log('onLoadeddata')
|
||||
window.app_event.playerLoadeddata()
|
||||
})
|
||||
const rOnLoadstart = onLoadstart(() => {
|
||||
console.log('onLoadstart')
|
||||
window.app_event.playerLoadstart()
|
||||
})
|
||||
const rOnCanplay = onCanplay(() => {
|
||||
console.log('onCanplay')
|
||||
window.app_event.playerCanplay()
|
||||
})
|
||||
const rOnEmptied = onEmptied(() => {
|
||||
console.log('onEmptied')
|
||||
window.app_event.playerEmptied()
|
||||
// window.app_event.stop()
|
||||
})
|
||||
const rOnWaiting = onWaiting(() => {
|
||||
console.log('onWaiting')
|
||||
window.app_event.pause()
|
||||
window.app_event.playerWaiting()
|
||||
})
|
||||
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rOnPlaying()
|
||||
rOnPause()
|
||||
rOnEnded()
|
||||
rOnError()
|
||||
rOnLoadeddata()
|
||||
rOnLoadstart()
|
||||
rOnCanplay()
|
||||
rOnEmptied()
|
||||
rOnWaiting()
|
||||
})
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
import { onBeforeUnmount, useCommit } from '@renderer/utils/vueTools'
|
||||
import { player as eventPlayerNames, taskbar as eventTaskbarNames, list as eventListNames } from '@renderer/event/names'
|
||||
import { onTaskbarThumbarClick, setTaskbarThumbnailClip, setTaskbarThumbarButtons } from '@renderer/utils/tools'
|
||||
// import store from '@renderer/store'
|
||||
|
||||
import { loveList, getList } from '@renderer/core/share/list'
|
||||
import { playMusicInfo, musicInfoItem } from '@renderer/core/share/player'
|
||||
import { throttle } from '@renderer/utils'
|
||||
|
||||
export default () => {
|
||||
const listAdd = useCommit('list', 'listAdd')
|
||||
const listRemove = useCommit('list', 'listRemove')
|
||||
// const setVisibleDesktopLyric = useCommit('setVisibleDesktopLyric')
|
||||
// const setLockDesktopLyric = useCommit('setLockDesktopLyric')
|
||||
|
||||
const buttons = {
|
||||
empty: true,
|
||||
collect: false,
|
||||
play: false,
|
||||
prev: true,
|
||||
next: true,
|
||||
lrc: false,
|
||||
lockLrc: false,
|
||||
}
|
||||
const setButtons = () => {
|
||||
setTaskbarThumbarButtons(buttons)
|
||||
}
|
||||
const updateCollectStatus = () => {
|
||||
let status = !!playMusicInfo.musicInfo && getList(loveList.id).some(musicInfo => playMusicInfo.musicInfo.songmid == musicInfo.songmid)
|
||||
if (buttons.collect == status) return false
|
||||
buttons.collect = status
|
||||
return true
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
if (buttons.empty) buttons.empty = false
|
||||
buttons.play = true
|
||||
setButtons()
|
||||
}
|
||||
const handlePause = () => {
|
||||
if (buttons.empty) buttons.empty = false
|
||||
buttons.play = false
|
||||
setButtons()
|
||||
}
|
||||
const handleStop = async() => {
|
||||
if (playMusicInfo.musicInfo != null) return
|
||||
if (buttons.collect) buttons.collect = false
|
||||
buttons.empty = true
|
||||
setButtons()
|
||||
}
|
||||
const handleSetPlayInfo = () => {
|
||||
if (!updateCollectStatus()) return
|
||||
setButtons()
|
||||
}
|
||||
const handleSetTaskbarThumbnailClip = (clip) => {
|
||||
setTaskbarThumbnailClip(clip)
|
||||
}
|
||||
const throttleListChange = throttle(listIds => {
|
||||
if (!listIds.includes(loveList.id)) return
|
||||
if (!updateCollectStatus()) return
|
||||
setButtons()
|
||||
})
|
||||
// const updateSetting = () => {
|
||||
// const setting = store.getters.setting
|
||||
// buttons.lrc = setting.desktopLyric.enable
|
||||
// buttons.lockLrc = setting.desktopLyric.isLock
|
||||
// setButtons()
|
||||
// }
|
||||
const rTaskbarThumbarClick = onTaskbarThumbarClick((event, action) => {
|
||||
switch (action) {
|
||||
case 'play':
|
||||
window.eventHub.emit(eventPlayerNames.setPlay)
|
||||
break
|
||||
case 'pause':
|
||||
window.eventHub.emit(eventPlayerNames.setPause)
|
||||
break
|
||||
case 'prev':
|
||||
window.eventHub.emit(eventPlayerNames.setPlayPrev)
|
||||
break
|
||||
case 'next':
|
||||
window.eventHub.emit(eventPlayerNames.setPlayNext)
|
||||
break
|
||||
case 'collect':
|
||||
if (!playMusicInfo.musicInfo) return
|
||||
listAdd({ id: loveList.id, musicInfo: musicInfoItem.value })
|
||||
if (updateCollectStatus()) setButtons()
|
||||
break
|
||||
case 'unCollect':
|
||||
if (!playMusicInfo.musicInfo) return
|
||||
listRemove({ listId: loveList.id, id: musicInfoItem.value.songmid })
|
||||
if (updateCollectStatus()) setButtons()
|
||||
break
|
||||
// case 'lrc':
|
||||
// setVisibleDesktopLyric(true)
|
||||
// updateSetting()
|
||||
// break
|
||||
// case 'unLrc':
|
||||
// setVisibleDesktopLyric(false)
|
||||
// updateSetting()
|
||||
// break
|
||||
// case 'lockLrc':
|
||||
// setLockDesktopLyric(true)
|
||||
// updateSetting()
|
||||
// break
|
||||
// case 'unlockLrc':
|
||||
// setLockDesktopLyric(false)
|
||||
// updateSetting()
|
||||
// break
|
||||
}
|
||||
})
|
||||
window.eventHub.on(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.on(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.on(eventPlayerNames.stop, handleStop)
|
||||
window.eventHub.on(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
window.eventHub.on(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip)
|
||||
window.eventHub.on(eventListNames.listChange, throttleListChange)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rTaskbarThumbarClick()
|
||||
window.eventHub.off(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.off(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.off(eventPlayerNames.stop, handleStop)
|
||||
window.eventHub.off(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
|
||||
window.eventHub.off(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip)
|
||||
window.eventHub.off(eventListNames.listChange, throttleListChange)
|
||||
})
|
||||
|
||||
return () => {
|
||||
// const setting = store.getters.setting
|
||||
// buttons.lrc = setting.desktopLyric.enable
|
||||
// buttons.lockLrc = setting.desktopLyric.isLock
|
||||
updateCollectStatus()
|
||||
if (playMusicInfo.musicInfo != null) buttons.empty = false
|
||||
setButtons()
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { onBeforeUnmount, watch, useCommit } from '@renderer/utils/vueTools'
|
||||
import { setVolume as setPlayerVolume, setMute as setPlayerMute } from '@renderer/plugins/player'
|
||||
|
||||
import { debounce } from '@renderer/utils'
|
||||
import { player as eventKeyPlayerNames } from '@common/hotKey'
|
||||
// import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { volume, isMute, setMute, setVolume } from '@renderer/core/share/volume'
|
||||
|
||||
export default ({ setting }) => {
|
||||
const saveVolume = useCommit('setVolume')
|
||||
|
||||
const handleSaveVolume = debounce(saveVolume, 300)
|
||||
|
||||
const handleToggleVolumeMute = (_isMute) => {
|
||||
let muteStatus = _isMute ?? !isMute.value
|
||||
saveVolume(muteStatus)
|
||||
setMute(muteStatus)
|
||||
}
|
||||
|
||||
const handleSetVolume = num => {
|
||||
const _volume = num < 0 ? 0 : num > 1 ? 1 : num
|
||||
setVolume(_volume)
|
||||
}
|
||||
|
||||
const handleSetVolumeUp = (step = 0.02) => {
|
||||
handleSetVolume(volume.value + step)
|
||||
}
|
||||
const handleSetVolumeDown = (step = 0.02) => {
|
||||
handleSetVolume(volume.value - step)
|
||||
}
|
||||
|
||||
watch(volume, _volume => {
|
||||
handleSaveVolume(_volume)
|
||||
setPlayerVolume(_volume)
|
||||
})
|
||||
watch(isMute, mute => {
|
||||
handleSaveVolume(mute)
|
||||
setPlayerMute(mute)
|
||||
})
|
||||
watch(() => setting.value.player.volume, _volume => {
|
||||
setVolume(_volume)
|
||||
})
|
||||
watch(() => setting.value.player.isMute, muteStatus => {
|
||||
setMute(muteStatus)
|
||||
})
|
||||
|
||||
setVolume(setting.value.player.volume)
|
||||
setMute(setting.value.player.isMute)
|
||||
|
||||
window.eventHub.on(eventKeyPlayerNames.volume_up.action, handleSetVolumeUp)
|
||||
window.eventHub.on(eventKeyPlayerNames.volume_down.action, handleSetVolumeDown)
|
||||
window.eventHub.on(eventKeyPlayerNames.volume_mute.action, handleToggleVolumeMute)
|
||||
// window.eventHub.on(eventPlayerNames.setVolume, handleSetVolume)
|
||||
// window.eventHub.on(eventPlayerNames.toggleMute, handleToggleVolumeMute)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventKeyPlayerNames.volume_up.action, handleSetVolumeUp)
|
||||
window.eventHub.off(eventKeyPlayerNames.volume_down.action, handleSetVolumeDown)
|
||||
window.eventHub.off(eventKeyPlayerNames.volume_mute.action, handleToggleVolumeMute)
|
||||
// window.eventHub.off(eventPlayerNames.setVolume, handleSetVolume)
|
||||
// window.eventHub.off(eventPlayerNames.toggleMute, handleToggleVolumeMute)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||
import { setVolume as setPlayerVolume, setMute as setPlayerMute } from '@renderer/plugins/player'
|
||||
|
||||
import { debounce } from '@common/utils'
|
||||
import { HOTKEY_PLAYER } from '@common/hotKey'
|
||||
// import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { volume, isMute, setMute, setVolume } from '@renderer/store/player/volume'
|
||||
import { appSetting, saveVolume, saveVolumeIsMute } from '@renderer/store/setting'
|
||||
|
||||
export default () => {
|
||||
const handleSaveVolume = debounce(saveVolume, 300)
|
||||
|
||||
setVolume(appSetting['player.volume'])
|
||||
setMute(appSetting['player.isMute'])
|
||||
setPlayerVolume(appSetting['player.volume'])
|
||||
setPlayerMute(appSetting['player.isMute'])
|
||||
|
||||
const handleToggleVolumeMute = (_isMute?: boolean) => {
|
||||
let muteStatus = _isMute ?? !isMute.value
|
||||
saveVolumeIsMute(muteStatus)
|
||||
setMute(muteStatus)
|
||||
}
|
||||
|
||||
const handleSetVolume = (num: number) => {
|
||||
const _volume = num < 0 ? 0 : num > 1 ? 1 : num
|
||||
setVolume(_volume)
|
||||
}
|
||||
|
||||
const handleSetVolumeUp = (step = 0.02) => {
|
||||
handleSetVolume(volume.value + step)
|
||||
}
|
||||
const handleSetVolumeDown = (step = 0.02) => {
|
||||
handleSetVolume(volume.value - step)
|
||||
}
|
||||
|
||||
const hotkeyVolumeUp = () => {
|
||||
handleSetVolumeUp()
|
||||
}
|
||||
const hotkeyVolumeDown = () => {
|
||||
handleSetVolumeDown()
|
||||
}
|
||||
const hotkeyVolumeMute = () => {
|
||||
handleToggleVolumeMute()
|
||||
}
|
||||
|
||||
watch(volume, _volume => {
|
||||
handleSaveVolume(_volume)
|
||||
setPlayerVolume(_volume)
|
||||
})
|
||||
watch(isMute, mute => {
|
||||
saveVolumeIsMute(mute)
|
||||
setPlayerMute(mute)
|
||||
})
|
||||
watch(() => appSetting['player.volume'], _volume => {
|
||||
setVolume(_volume)
|
||||
})
|
||||
watch(() => appSetting['player.isMute'], muteStatus => {
|
||||
setMute(muteStatus)
|
||||
})
|
||||
|
||||
|
||||
window.key_event.on(HOTKEY_PLAYER.volume_up.action, hotkeyVolumeUp)
|
||||
window.key_event.on(HOTKEY_PLAYER.volume_down.action, hotkeyVolumeDown)
|
||||
window.key_event.on(HOTKEY_PLAYER.volume_mute.action, hotkeyVolumeMute)
|
||||
window.app_event.on('setVolume', handleSetVolume)
|
||||
window.app_event.on('setVolumeIsMute', handleToggleVolumeMute)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.key_event.off(HOTKEY_PLAYER.volume_up.action, hotkeyVolumeUp)
|
||||
window.key_event.off(HOTKEY_PLAYER.volume_down.action, hotkeyVolumeDown)
|
||||
window.key_event.off(HOTKEY_PLAYER.volume_mute.action, hotkeyVolumeMute)
|
||||
window.app_event.off('setVolume', handleSetVolume)
|
||||
window.app_event.off('setVolumeIsMute', handleToggleVolumeMute)
|
||||
})
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import { onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
|
||||
import { player as eventPlayerNames, list as eventListNames, download as eventDownloadNames } from '@renderer/event/names'
|
||||
import { playInfo, playMusicInfo, updatePlayIndex } from '@renderer/core/share/player'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
import { throttle } from '@renderer/utils'
|
||||
|
||||
const changedListIds = new Set()
|
||||
|
||||
export default ({ playNext }) => {
|
||||
const throttleListChange = throttle(() => {
|
||||
const isSkip = !changedListIds.has(playInfo.playListId) && !changedListIds.has(playMusicInfo.listId)
|
||||
changedListIds.clear()
|
||||
if (isSkip) return
|
||||
|
||||
const { playIndex } = updatePlayIndex()
|
||||
if (playIndex < 0 && !playMusicInfo.isTempPlay) { // 歌曲被移除
|
||||
if (getList(playMusicInfo.listId).length && !global.isPlayedStop) {
|
||||
playNext()
|
||||
} else {
|
||||
window.eventHub.emit(eventPlayerNames.setStop)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const handleListChange = listIds => {
|
||||
for (const id of listIds) {
|
||||
changedListIds.add(id)
|
||||
}
|
||||
throttleListChange()
|
||||
}
|
||||
|
||||
const handleDownloadListChange = () => {
|
||||
handleListChange(['download'])
|
||||
}
|
||||
|
||||
window.eventHub.on(eventListNames.listChange, handleListChange)
|
||||
window.eventHub.on(eventDownloadNames.listChange, handleDownloadListChange)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventListNames.listChange, handleListChange)
|
||||
window.eventHub.off(eventDownloadNames.listChange, handleDownloadListChange)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
|
||||
import { playInfo, playMusicInfo } from '@renderer/store/player/state'
|
||||
import { setPlayMusicInfo, updatePlayIndex } from '@renderer/store/player/action'
|
||||
import { throttle } from '@common/utils'
|
||||
import { playNext, stop } from '@renderer/core/player'
|
||||
|
||||
const changedListIds = new Set<string | null>()
|
||||
|
||||
export default () => {
|
||||
const throttleListChange = throttle(() => {
|
||||
const isSkip = !changedListIds.has(playInfo.playerListId) && !changedListIds.has(playMusicInfo.listId)
|
||||
changedListIds.clear()
|
||||
if (isSkip) return
|
||||
|
||||
const { playIndex } = updatePlayIndex()
|
||||
if (playIndex < 0) { // 歌曲被移除
|
||||
if (window.lx.isPlayedStop) {
|
||||
stop()
|
||||
setTimeout(() => {
|
||||
setPlayMusicInfo(null, null)
|
||||
})
|
||||
} else {
|
||||
console.log('current music removed')
|
||||
void playNext(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const handleListChange = (listIds: string[]) => {
|
||||
for (const id of listIds) {
|
||||
changedListIds.add(id)
|
||||
}
|
||||
throttleListChange()
|
||||
}
|
||||
|
||||
const handleDownloadListChange = () => {
|
||||
handleListChange(['download'])
|
||||
}
|
||||
|
||||
window.app_event.on('myListUpdate', handleListChange)
|
||||
window.app_event.on('downloadListUpdate', handleDownloadListChange)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.app_event.off('myListUpdate', handleListChange)
|
||||
window.app_event.off('downloadListUpdate', handleDownloadListChange)
|
||||
})
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
import { throttle, saveSetting } from '@renderer/utils'
|
||||
import { saveMyList, saveDownloadList, saveSearchHistoryList, setUserApi } from '@renderer/utils/tools'
|
||||
import music from '@renderer/utils/music'
|
||||
|
||||
import { useCommit, watch, toRaw, onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
|
||||
import { apiSource, qualityList, userApi, proxy } from '@renderer/core/share'
|
||||
import { allList, defaultList, loveList, userLists, tempList } from '@renderer/core/share/list'
|
||||
import { downloadList } from '@renderer/core/share/download'
|
||||
|
||||
import { list as eventListNames, download as eventDownloadNames } from '@renderer/event/names'
|
||||
|
||||
const listThrottle = (fn, delay = 100) => {
|
||||
let timer = null
|
||||
let _data = {}
|
||||
return function(data) {
|
||||
Object.assign(_data, data)
|
||||
if (timer) return
|
||||
timer = setTimeout(() => {
|
||||
timer = null
|
||||
fn.call(this, _data)
|
||||
_data = {}
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
const saveMyListThrottle = listThrottle(data => saveMyList(data), 300)
|
||||
const saveDownloadListThrottle = throttle(list => saveDownloadList(list), 1000)
|
||||
const saveSearchHistoryListThrottle = throttle(list => saveSearchHistoryList(list), 500)
|
||||
|
||||
export default ({
|
||||
setting,
|
||||
searchHistoryList,
|
||||
}) => {
|
||||
watch(setting, (newValue, oldValue) => {
|
||||
saveSetting(toRaw(newValue))
|
||||
global.appSetting = newValue
|
||||
}, { deep: true })
|
||||
|
||||
// watch(defaultList, (newValue, oldValue) => {
|
||||
// saveMyListThrottle({ defaultList: toRaw(newValue) })
|
||||
// }, { deep: true })
|
||||
// watch(loveList, (newValue, oldValue) => {
|
||||
// saveMyListThrottle({ loveList: toRaw(newValue) })
|
||||
// }, { deep: true })
|
||||
// watch(userList, (newValue, oldValue) => {
|
||||
// saveMyListThrottle({ userList: toRaw(newValue) })
|
||||
// }, { deep: true })
|
||||
|
||||
// watch(downloadList, (newValue, oldValue) => {
|
||||
// saveDownloadListThrottle(window.downloadListFull)
|
||||
// }, { deep: true })
|
||||
|
||||
watch(searchHistoryList, (newValue, oldValue) => {
|
||||
saveSearchHistoryListThrottle(toRaw(newValue))
|
||||
}, { deep: true })
|
||||
|
||||
|
||||
const setApiSource = useCommit('setApiSource')
|
||||
watch(apiSource, (apiSource, oldValue) => {
|
||||
if (/^user_api/.test(apiSource)) {
|
||||
qualityList.value = {}
|
||||
userApi.status = false
|
||||
userApi.message = 'initing'
|
||||
} else {
|
||||
qualityList.value = music.supportQuality[apiSource]
|
||||
}
|
||||
if (oldValue === null) return
|
||||
|
||||
setUserApi(apiSource)
|
||||
|
||||
if (apiSource != setting.value.apiSource) {
|
||||
setApiSource(apiSource)
|
||||
}
|
||||
})
|
||||
|
||||
const setProxyEnable = useCommit('setProxyEnable')
|
||||
watch(() => proxy.enable, (enable, oldValue) => {
|
||||
if (enable != setting.value.network.proxy.enable) setProxyEnable(enable)
|
||||
})
|
||||
|
||||
const handelListChange = ids => {
|
||||
const lists = {}
|
||||
let isUserList = false
|
||||
for (const id of ids) {
|
||||
switch (id) {
|
||||
case defaultList.id:
|
||||
lists.defaultList = { ...toRaw(defaultList), list: toRaw(allList[id]) }
|
||||
break
|
||||
case loveList.id:
|
||||
lists.loveList = { ...toRaw(loveList), list: toRaw(allList[id]) }
|
||||
break
|
||||
case tempList.id:
|
||||
lists.tempList = { ...toRaw(tempList), list: toRaw(allList[id]) }
|
||||
break
|
||||
default:
|
||||
isUserList = true
|
||||
}
|
||||
}
|
||||
if (isUserList) {
|
||||
lists.userList = userLists.map(l => ({ ...toRaw(l), list: toRaw(allList[l.id]) }))
|
||||
}
|
||||
|
||||
saveMyListThrottle(lists)
|
||||
}
|
||||
const handelSaveList = ({ id }) => {
|
||||
handelListChange([id])
|
||||
}
|
||||
|
||||
const handelDownloadListChange = () => {
|
||||
saveDownloadListThrottle(toRaw(downloadList))
|
||||
}
|
||||
|
||||
window.eventHub.on(eventListNames.listChange, handelListChange)
|
||||
window.eventHub.on(eventListNames.musicInfoChange, handelSaveList)
|
||||
window.eventHub.on(eventDownloadNames.listChange, handelDownloadListChange)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventListNames.listChange, handelListChange)
|
||||
window.eventHub.off(eventListNames.musicInfoChange, handelSaveList)
|
||||
window.eventHub.off(eventDownloadNames.listChange, handelDownloadListChange)
|
||||
})
|
||||
|
||||
return {
|
||||
saveMyListThrottle,
|
||||
saveSearchHistoryListThrottle,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { watch } from '@common/utils/vueTools'
|
||||
import { isFullscreen, proxy, sync, windowSizeList } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { sendSyncAction, setTaskBarProgress, setWindowSize } from '@renderer/utils/ipc'
|
||||
import { setLanguage } from '@/lang'
|
||||
import { setUserApi } from '../apiSource'
|
||||
// import { applyTheme, getThemes } from '@renderer/store/utils'
|
||||
|
||||
|
||||
export default () => {
|
||||
watch(() => appSetting['common.windowSizeId'], (index) => {
|
||||
let info = index == null ? windowSizeList[2] : windowSizeList[index]
|
||||
setWindowSize(info.width, info.height)
|
||||
})
|
||||
watch(() => appSetting['common.fontSize'], (fontSize) => {
|
||||
if (isFullscreen.value) return
|
||||
document.documentElement.style.fontSize = `${fontSize}px`
|
||||
})
|
||||
|
||||
watch(() => appSetting['common.langId'], (id) => {
|
||||
if (!id) return
|
||||
setLanguage(id)
|
||||
})
|
||||
|
||||
watch(() => appSetting['common.apiSource'], apiSource => {
|
||||
setUserApi(apiSource)
|
||||
})
|
||||
|
||||
watch(() => appSetting['common.font'], (val) => {
|
||||
document.documentElement.style.fontFamily = val
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
|
||||
watch(() => appSetting['sync.enable'], enable => {
|
||||
void sendSyncAction({
|
||||
action: 'enable',
|
||||
data: {
|
||||
enable,
|
||||
port: appSetting['sync.port'],
|
||||
},
|
||||
})
|
||||
sync.enable = enable
|
||||
})
|
||||
watch(() => appSetting['sync.port'], port => {
|
||||
void sendSyncAction({
|
||||
action: 'enable',
|
||||
data: {
|
||||
enable: appSetting['sync.enable'],
|
||||
port: appSetting['sync.port'],
|
||||
},
|
||||
})
|
||||
sync.port = port
|
||||
})
|
||||
|
||||
watch(() => appSetting['network.proxy.enable'], enable => {
|
||||
proxy.enable = enable
|
||||
})
|
||||
watch(() => appSetting['network.proxy.enable'], enable => {
|
||||
proxy.enable = enable
|
||||
})
|
||||
watch(() => appSetting['network.proxy.host'], host => {
|
||||
proxy.host = host
|
||||
})
|
||||
watch(() => appSetting['network.proxy.port'], port => {
|
||||
proxy.port = port
|
||||
})
|
||||
watch(() => appSetting['network.proxy.username'], username => {
|
||||
proxy.username = username
|
||||
})
|
||||
watch(() => appSetting['network.proxy.password'], password => {
|
||||
proxy.password = password
|
||||
})
|
||||
|
||||
watch(() => appSetting['player.isShowTaskProgess'], val => {
|
||||
if (val) return
|
||||
setTimeout(() => {
|
||||
setTaskBarProgress(-1, 'normal')
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
import { useCommit, useRefGetter, onBeforeUnmount, toRaw } from '@renderer/utils/vueTools'
|
||||
import { sync as eventSyncName } from '@renderer/event/names'
|
||||
import { syncEnable, onSyncStatus } from '@renderer/utils/tools'
|
||||
import { sync } from '@renderer/core/share'
|
||||
import { allList, defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
|
||||
export default () => {
|
||||
const setList = useCommit('list', 'setList')
|
||||
const listAdd = useCommit('list', 'listAdd')
|
||||
const listMove = useCommit('list', 'listMove')
|
||||
const listAddMultiple = useCommit('list', 'listAddMultiple')
|
||||
const listMoveMultiple = useCommit('list', 'listMoveMultiple')
|
||||
const listRemove = useCommit('list', 'listRemove')
|
||||
const listRemoveMultiple = useCommit('list', 'listRemoveMultiple')
|
||||
const listClear = useCommit('list', 'listClear')
|
||||
const updateMusicInfo = useCommit('list', 'updateMusicInfo')
|
||||
const createUserList = useCommit('list', 'createUserList')
|
||||
const removeUserList = useCommit('list', 'removeUserList')
|
||||
const setUserListName = useCommit('list', 'setUserListName')
|
||||
const setMusicPosition = useCommit('list', 'setMusicPosition')
|
||||
const setSyncListData = useCommit('list', 'setSyncListData')
|
||||
const setUserListPosition = useCommit('list', 'setUserListPosition')
|
||||
|
||||
const setting = useRefGetter('setting')
|
||||
|
||||
const handleSyncAction = ({ action, data }) => {
|
||||
if (typeof data == 'object') data.isSync = true
|
||||
// console.log(action, data)
|
||||
|
||||
switch (action) {
|
||||
case 'set_list':
|
||||
setList(data)
|
||||
break
|
||||
case 'list_add':
|
||||
listAdd(data)
|
||||
break
|
||||
case 'list_move':
|
||||
listMove(data)
|
||||
break
|
||||
case 'list_add_multiple':
|
||||
listAddMultiple(data)
|
||||
break
|
||||
case 'list_move_multiple':
|
||||
listMoveMultiple(data)
|
||||
break
|
||||
case 'list_remove':
|
||||
listRemove(data)
|
||||
break
|
||||
case 'list_remove_multiple':
|
||||
listRemoveMultiple(data)
|
||||
break
|
||||
case 'list_clear':
|
||||
listClear(data)
|
||||
break
|
||||
case 'update_music_info':
|
||||
updateMusicInfo(data)
|
||||
break
|
||||
case 'create_user_list':
|
||||
createUserList(data)
|
||||
break
|
||||
case 'remove_user_list':
|
||||
removeUserList(data)
|
||||
break
|
||||
case 'set_user_list_name':
|
||||
setUserListName(data)
|
||||
break
|
||||
case 'set_user_list_position':
|
||||
setUserListPosition(data)
|
||||
break
|
||||
case 'set_music_position':
|
||||
setMusicPosition(data)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const handleSyncList = ({ action, data }) => {
|
||||
switch (action) {
|
||||
case 'getData':
|
||||
global.eventHub.emit(eventSyncName.send_sync_list, {
|
||||
action: 'getData',
|
||||
data: {
|
||||
defaultList: { ...toRaw(defaultList), list: toRaw(allList[defaultList.id]) },
|
||||
loveList: { ...toRaw(loveList), list: toRaw(allList[loveList.id]) },
|
||||
userList: userLists.map(l => ({ ...toRaw(l), list: toRaw(allList[l.id]) })),
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'setData':
|
||||
setSyncListData(data)
|
||||
break
|
||||
case 'selectMode':
|
||||
sync.deviceName = data.deviceName
|
||||
sync.isShowSyncMode = true
|
||||
break
|
||||
case 'closeSelectMode':
|
||||
sync.isShowSyncMode = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
window.eventHub.on(eventSyncName.handle_action_list, handleSyncAction)
|
||||
window.eventHub.on(eventSyncName.handle_sync_list, handleSyncList)
|
||||
|
||||
const rSyncStatus = onSyncStatus((event, status) => {
|
||||
sync.status.status = status.status
|
||||
sync.status.message = status.message
|
||||
sync.status.address = status.address
|
||||
sync.status.code = status.code
|
||||
sync.status.devices = status.devices
|
||||
})
|
||||
|
||||
if (setting.value.sync.enable && setting.value.sync.port) {
|
||||
syncEnable({
|
||||
enable: setting.value.sync.enable,
|
||||
port: setting.value.sync.port,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rSyncStatus()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { markRaw, onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { onSyncAction, sendSyncAction } from '@renderer/utils/ipc'
|
||||
import { sync } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
export default () => {
|
||||
const handleSyncList = (event: LX.Sync.SyncMainWindowActions) => {
|
||||
switch (event.action) {
|
||||
case 'select_mode':
|
||||
sync.deviceName = event.data.deviceName
|
||||
sync.isShowSyncMode = true
|
||||
break
|
||||
case 'close_select_mode':
|
||||
sync.isShowSyncMode = false
|
||||
break
|
||||
case 'status':
|
||||
sync.status.status = event.data.status
|
||||
sync.status.message = event.data.message
|
||||
sync.status.address = markRaw(event.data.address)
|
||||
sync.status.code = event.data.code
|
||||
sync.status.devices = markRaw(event.data.devices)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const rSyncAction = onSyncAction(({ params }) => {
|
||||
handleSyncList(params)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
rSyncAction()
|
||||
})
|
||||
|
||||
return async() => {
|
||||
sync.enable = appSetting['sync.enable']
|
||||
sync.port = appSetting['sync.port']
|
||||
if (appSetting['sync.enable'] && appSetting['sync.port']) {
|
||||
void sendSyncAction({
|
||||
action: 'enable',
|
||||
data: {
|
||||
enable: appSetting['sync.enable'],
|
||||
port: appSetting['sync.port'],
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,22 @@
|
||||
import { useAction, nextTick, onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
import { onUpdateAvailable, onUpdateDownloaded, onUpdateError, onUpdateNotAvailable, onUpdateProgress } from '@renderer/utils/tools'
|
||||
import { compareVer } from '@renderer/utils'
|
||||
import { versionInfo } from '@renderer/core/share'
|
||||
|
||||
export default (setting) => {
|
||||
const getVersionInfo = useAction('getVersionInfo')
|
||||
import { nextTick, onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import {
|
||||
onUpdateAvailable,
|
||||
onUpdateDownloaded,
|
||||
onUpdateError,
|
||||
onUpdateNotAvailable,
|
||||
onUpdateProgress,
|
||||
getIgnoreVersion,
|
||||
} from '@renderer/utils/ipc'
|
||||
import { compareVer } from '@common/utils'
|
||||
import { versionInfo } from '@renderer/store'
|
||||
import { getVersionInfo } from '@renderer/utils/update'
|
||||
|
||||
export default () => {
|
||||
// 更新超时定时器
|
||||
let updateTimeout = setTimeout(() => {
|
||||
let updateTimeout: number | null = window.setTimeout(() => {
|
||||
updateTimeout = null
|
||||
versionInfo.isTimeOut = true
|
||||
nextTick(() => {
|
||||
void nextTick(() => {
|
||||
showUpdateModal()
|
||||
})
|
||||
}, 60 * 30 * 1000)
|
||||
@@ -22,7 +28,7 @@ export default (setting) => {
|
||||
}
|
||||
|
||||
const showUpdateModal = () => {
|
||||
(versionInfo.newVersion && versionInfo.newVersion.history
|
||||
void (versionInfo.newVersion?.history
|
||||
? Promise.resolve(versionInfo.newVersion)
|
||||
: getVersionInfo().then(body => {
|
||||
versionInfo.newVersion = body
|
||||
@@ -33,11 +39,11 @@ export default (setting) => {
|
||||
versionInfo.isUnknow = true
|
||||
let result = {
|
||||
version: '0.0.0',
|
||||
desc: null,
|
||||
desc: '',
|
||||
}
|
||||
versionInfo.newVersion = result
|
||||
return result
|
||||
}).then(result => {
|
||||
}).then((result: LX.VersionInfo) => {
|
||||
if (result.version == '0.0.0') {
|
||||
versionInfo.isUnknow = true
|
||||
versionInfo.showModal = true
|
||||
@@ -48,49 +54,51 @@ export default (setting) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (result.version === setting.value.ignoreVersion) return
|
||||
// console.log(this.version)
|
||||
nextTick(() => {
|
||||
versionInfo.showModal = true
|
||||
return getIgnoreVersion().then((ignoreVersion) => {
|
||||
if (result.version === ignoreVersion) return
|
||||
// console.log(this.version)
|
||||
void nextTick(() => {
|
||||
versionInfo.showModal = true
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const rUpdateAvailable = onUpdateAvailable((event, info) => {
|
||||
const rUpdateAvailable = onUpdateAvailable(({ params: info }) => {
|
||||
versionInfo.isDownloading = true
|
||||
getVersionInfo().catch(() => ({
|
||||
void getVersionInfo().catch(() => ({
|
||||
version: info.version,
|
||||
desc: info.releaseNotes,
|
||||
})).then(body => {
|
||||
// console.log(body)
|
||||
versionInfo.newVersion = body
|
||||
nextTick(() => {
|
||||
void nextTick(() => {
|
||||
versionInfo.showModal = true
|
||||
})
|
||||
})
|
||||
})
|
||||
const rUpdateNotAvailable = onUpdateNotAvailable((event, info) => {
|
||||
const rUpdateNotAvailable = onUpdateNotAvailable(({ params: info }) => {
|
||||
clearUpdateTimeout()
|
||||
versionInfo.newVersion = {
|
||||
version: info.version,
|
||||
desc: info.releaseNotes,
|
||||
desc: info.releaseNotes as string,
|
||||
}
|
||||
versionInfo.isLatestVer = true
|
||||
})
|
||||
const rUpdateError = onUpdateError((event, info) => {
|
||||
const rUpdateError = onUpdateError(() => {
|
||||
clearUpdateTimeout()
|
||||
versionInfo.isError = true
|
||||
nextTick(() => {
|
||||
void nextTick(() => {
|
||||
showUpdateModal()
|
||||
})
|
||||
})
|
||||
const rUpdateProgress = onUpdateProgress((event, progress) => {
|
||||
const rUpdateProgress = onUpdateProgress(({ params: progress }) => {
|
||||
versionInfo.downloadProgress = progress
|
||||
})
|
||||
const rUpdateDownloaded = onUpdateDownloaded((event, info) => {
|
||||
const rUpdateDownloaded = onUpdateDownloaded(({ params: info }) => {
|
||||
clearUpdateTimeout()
|
||||
versionInfo.isDownloaded = true
|
||||
nextTick(() => {
|
||||
void nextTick(() => {
|
||||
showUpdateModal()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user