优化自定义源调用处理逻辑
parent
da2d3237b6
commit
7893814da4
|
@ -1,12 +1,7 @@
|
||||||
### 自定义源的不兼容变更与新增内容(源开发者需要看)
|
|
||||||
|
|
||||||
自定义源的调用方式已改变:
|
更新前需要注意:
|
||||||
|
|
||||||
- 为了与移动端的调用方式统一,不再推荐使用 `window.lx` 对象(移动端无`window`对象),改用 `globalThis.lx`
|
由于自定义源的调用方式变更,可能会导致某些第三方源停止工作,如果出现这种情况,你需要将LX回退到 v2.5.0
|
||||||
- `inited` 事件不再需要传递 `status` 属性,脚本运行过程中,在成功调用 `inited` 事件之前的任何首次未捕获的错误都将视为初始化失败,所以现在若想人为让脚本初始化失败,直接抛出一个错误即可
|
|
||||||
- 新增 `globalThis.lx.env` 属性,桌面端环境固定为 `desktop`,移动端环境固定为 `mobile`
|
|
||||||
- 新增 `globalThis.lx.currentScriptInfo` 对象,可以从这里获取解析后的脚本头部注释信息及脚本原始内容,具体可用属性看文档说明
|
|
||||||
- `globalThis.lx.version` 属性更新到 `2.0.0`
|
|
||||||
|
|
||||||
### 新增
|
### 新增
|
||||||
|
|
||||||
|
@ -45,3 +40,15 @@
|
||||||
- 移除所有内置源,由于收到腾讯投诉要求停止提供软件内置的连接到他们平台的在线播放及下载服务,所以从即日(2023年10月18日)起LX本身不再提供上述服务
|
- 移除所有内置源,由于收到腾讯投诉要求停止提供软件内置的连接到他们平台的在线播放及下载服务,所以从即日(2023年10月18日)起LX本身不再提供上述服务
|
||||||
- 更新 electron 到 v25.9.8
|
- 更新 electron 到 v25.9.8
|
||||||
- 更新许可协议的排版,使其看起来更加清晰明了,更新数据来源原理说明
|
- 更新许可协议的排版,使其看起来更加清晰明了,更新数据来源原理说明
|
||||||
|
|
||||||
|
### 自定义源的不兼容变更与新增内容(源开发者需要看)
|
||||||
|
|
||||||
|
自定义源的调用方式已改变:
|
||||||
|
|
||||||
|
- 为了与移动端的调用方式统一,不再推荐使用 `window.lx` 对象(移动端无`window`对象),改用 `globalThis.lx`
|
||||||
|
- `inited` 事件不再需要传递 `status` 属性,脚本运行过程中,在成功调用 `inited` 事件之前的任何首次未捕获的错误都将视为初始化失败,所以现在若想人为让脚本初始化失败,直接抛出一个错误即可
|
||||||
|
- 新增 `globalThis.lx.env` 属性,桌面端环境固定为 `desktop`,移动端环境固定为 `mobile`
|
||||||
|
- 新增 `globalThis.lx.currentScriptInfo` 对象,可以从这里获取解析后的脚本头部注释信息及脚本原始内容,具体可用属性看文档说明
|
||||||
|
- `globalThis.lx.version` 属性更新到 `2.0.0`
|
||||||
|
- 自定义源不再使用`script`标签的形式执行,若要获取脚本原始代码字符串需从 `globalThis.lx.currentScriptInfo.rawScript` 属性获取
|
||||||
|
-
|
||||||
|
|
|
@ -314,18 +314,6 @@ window.addEventListener('unhandledrejection', (event) => {
|
||||||
const message = typeof event.reason === 'string' ? event.reason : event.reason?.message ?? String(event.reason)
|
const message = typeof event.reason === 'string' ? event.reason : event.reason?.message ?? String(event.reason)
|
||||||
globalThis.__lx_init_error_handler__.sendError(message.replace(/^Error:\\s/, ''))
|
globalThis.__lx_init_error_handler__.sendError(message.replace(/^Error:\\s/, ''))
|
||||||
})
|
})
|
||||||
Object.defineProperty(window.document, 'getElementsByTagName', {
|
|
||||||
value: (name) => {
|
|
||||||
if (name == 'script') {
|
|
||||||
return [
|
|
||||||
Object.freeze({
|
|
||||||
innerText: lx.currentScriptInfo.rawScript,
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})()`)
|
})()`)
|
||||||
|
|
||||||
webFrame.executeJavaScript(userApi.script).catch(_ => _)
|
webFrame.executeJavaScript(userApi.script).catch(_ => _)
|
||||||
|
|
|
@ -7,6 +7,16 @@ import apiSourceInfo from '@renderer/utils/musicSdk/api-source-info'
|
||||||
let prevId = ''
|
let prevId = ''
|
||||||
export const setUserApi = async(apiId: string) => {
|
export const setUserApi = async(apiId: string) => {
|
||||||
prevId = apiId
|
prevId = apiId
|
||||||
|
if (window.lx.apiInitPromise[1]) {
|
||||||
|
window.lx.apiInitPromise[0] = new Promise(resolve => {
|
||||||
|
window.lx.apiInitPromise[1] = false
|
||||||
|
window.lx.apiInitPromise[2] = (result: boolean) => {
|
||||||
|
window.lx.apiInitPromise[1] = true
|
||||||
|
resolve(result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (/^user_api/.test(apiId)) {
|
if (/^user_api/.test(apiId)) {
|
||||||
qualityList.value = {}
|
qualityList.value = {}
|
||||||
userApi.status = false
|
userApi.status = false
|
||||||
|
@ -17,6 +27,7 @@ export const setUserApi = async(apiId: string) => {
|
||||||
apiSource.value = apiId
|
apiSource.value = apiId
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
if (prevId != apiId) return
|
if (prevId != apiId) return
|
||||||
|
if (!window.lx.apiInitPromise[1]) window.lx.apiInitPromise[2](false)
|
||||||
console.log(err)
|
console.log(err)
|
||||||
let api = apiSourceInfo.find(api => !api.disabled)
|
let api = apiSourceInfo.find(api => !api.disabled)
|
||||||
if (!api) return
|
if (!api) return
|
||||||
|
@ -28,6 +39,7 @@ export const setUserApi = async(apiId: string) => {
|
||||||
qualityList.value = musicSdk.supportQuality[apiId] ?? {}
|
qualityList.value = musicSdk.supportQuality[apiId] ?? {}
|
||||||
apiSource.value = apiId
|
apiSource.value = apiId
|
||||||
void setUserApiAction(apiId)
|
void setUserApiAction(apiId)
|
||||||
|
if (!window.lx.apiInitPromise[1]) window.lx.apiInitPromise[2](true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiId != appSetting['common.apiSource']) setApiSource(apiId)
|
if (apiId != appSetting['common.apiSource']) setApiSource(apiId)
|
||||||
|
|
|
@ -26,6 +26,7 @@ window.lx = {
|
||||||
worker: createWorkers(),
|
worker: createWorkers(),
|
||||||
isProd: process.env.NODE_ENV == 'production',
|
isProd: process.env.NODE_ENV == 'production',
|
||||||
rootOffset: window.dt ? 0 : 8,
|
rootOffset: window.dt ? 0 : 8,
|
||||||
|
apiInitPromise: [Promise.resolve(false), true, () => {}],
|
||||||
}
|
}
|
||||||
|
|
||||||
window.lxData = {}
|
window.lxData = {}
|
||||||
|
|
|
@ -53,7 +53,7 @@ export const getOtherSource = async(musicInfo: LX.Music.MusicInfo | LX.Download.
|
||||||
let timeout: null | NodeJS.Timeout = setTimeout(() => {
|
let timeout: null | NodeJS.Timeout = setTimeout(() => {
|
||||||
timeout = null
|
timeout = null
|
||||||
reject(new Error('find music timeout'))
|
reject(new Error('find music timeout'))
|
||||||
}, 20_000)
|
}, 15_000)
|
||||||
musicSdk.findMusic(searchMusicInfo).then((otherSource) => {
|
musicSdk.findMusic(searchMusicInfo).then((otherSource) => {
|
||||||
resolve(otherSource.map(toNewMusicInfo) as LX.Music.MusicInfoOnline[])
|
resolve(otherSource.map(toNewMusicInfo) as LX.Music.MusicInfoOnline[])
|
||||||
}).catch(reject).finally(() => {
|
}).catch(reject).finally(() => {
|
||||||
|
@ -166,6 +166,8 @@ export const getOnlineOtherSourceMusicUrl = async({ musicInfos, quality, onToggl
|
||||||
quality: LX.Quality
|
quality: LX.Quality
|
||||||
isFromCache: boolean
|
isFromCache: boolean
|
||||||
}> => {
|
}> => {
|
||||||
|
if (!await window.lx.apiInitPromise[0]) throw new Error('source init failed')
|
||||||
|
|
||||||
let musicInfo: LX.Music.MusicInfoOnline | null = null
|
let musicInfo: LX.Music.MusicInfoOnline | null = null
|
||||||
let itemQuality: LX.Quality | null = null
|
let itemQuality: LX.Quality | null = null
|
||||||
// eslint-disable-next-line no-cond-assign
|
// eslint-disable-next-line no-cond-assign
|
||||||
|
@ -191,7 +193,7 @@ export const getOnlineOtherSourceMusicUrl = async({ musicInfos, quality, onToggl
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
reqPromise = Promise.reject(err)
|
reqPromise = Promise.reject(err)
|
||||||
}
|
}
|
||||||
retryedSource.includes(musicInfo.source)
|
// retryedSource.includes(musicInfo.source)
|
||||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||||
return reqPromise.then(({ url, type }: { url: string, type: LX.Quality }) => {
|
return reqPromise.then(({ url, type }: { url: string, type: LX.Quality }) => {
|
||||||
return { musicInfo, url, quality: type, isFromCache: false }
|
return { musicInfo, url, quality: type, isFromCache: false }
|
||||||
|
@ -218,6 +220,7 @@ export const handleGetOnlineMusicUrl = async({ musicInfo, quality, onToggleSourc
|
||||||
quality: LX.Quality
|
quality: LX.Quality
|
||||||
isFromCache: boolean
|
isFromCache: boolean
|
||||||
}> => {
|
}> => {
|
||||||
|
if (!await window.lx.apiInitPromise[0]) throw new Error('source init failed')
|
||||||
// console.log(musicInfo.source)
|
// console.log(musicInfo.source)
|
||||||
const targetQuality = quality ?? getPlayQuality(appSetting['player.highQuality'], musicInfo)
|
const targetQuality = quality ?? getPlayQuality(appSetting['player.highQuality'], musicInfo)
|
||||||
|
|
||||||
|
@ -281,7 +284,7 @@ export const getOnlineOtherSourcePicUrl = async({ musicInfos, onToggleSource, is
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
reqPromise = Promise.reject(err)
|
reqPromise = Promise.reject(err)
|
||||||
}
|
}
|
||||||
retryedSource.includes(musicInfo.source)
|
// retryedSource.includes(musicInfo.source)
|
||||||
return reqPromise.then((url: string) => {
|
return reqPromise.then((url: string) => {
|
||||||
return { musicInfo, url, isFromCache: false }
|
return { musicInfo, url, isFromCache: false }
|
||||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||||
|
@ -368,7 +371,7 @@ export const getOnlineOtherSourceLyricInfo = async({ musicInfos, onToggleSource,
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
reqPromise = Promise.reject(err)
|
reqPromise = Promise.reject(err)
|
||||||
}
|
}
|
||||||
retryedSource.includes(musicInfo.source)
|
// retryedSource.includes(musicInfo.source)
|
||||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||||
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
|
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
|
||||||
return existTimeExp.test(lyricInfo.lyric) ? {
|
return existTimeExp.test(lyricInfo.lyric) ? {
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||||
import { useI18n } from '@renderer/plugins/i18n'
|
import { useI18n } from '@renderer/plugins/i18n'
|
||||||
import { onUserApiStatus, getUserApiList, sendUserApiRequest, userApiRequestCancel, onShowUserApiUpdateAlert } from '@renderer/utils/ipc'
|
import { onUserApiStatus, getUserApiList, sendUserApiRequest as sendUserApiRequestRemote, userApiRequestCancel, onShowUserApiUpdateAlert } from '@renderer/utils/ipc'
|
||||||
import { openUrl } from '@common/utils/electron'
|
import { openUrl } from '@common/utils/electron'
|
||||||
import { qualityList, userApi } from '@renderer/store'
|
import { qualityList, userApi } from '@renderer/store'
|
||||||
import { appSetting } from '@renderer/store/setting'
|
import { appSetting } from '@renderer/store/setting'
|
||||||
import { dialog } from '@renderer/plugins/Dialog'
|
import { dialog } from '@renderer/plugins/Dialog'
|
||||||
import { setUserApi } from '@renderer/core/apiSource'
|
import { setUserApi } from '@renderer/core/apiSource'
|
||||||
|
|
||||||
|
const sendUserApiRequest: typeof sendUserApiRequestRemote = async(data) => {
|
||||||
|
let stop: () => void
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
stop = watch(() => appSetting['common.apiSource'], () => {
|
||||||
|
reject(new Error('source changed'))
|
||||||
|
})
|
||||||
|
void sendUserApiRequestRemote(data).then(resolve).catch(reject)
|
||||||
|
}).finally(() => {
|
||||||
|
stop()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
@ -74,6 +85,7 @@ export default () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!window.lx.apiInitPromise[1]) window.lx.apiInitPromise[2](status)
|
||||||
})
|
})
|
||||||
|
|
||||||
const rUserApiShowUpdateAlert = onShowUserApiUpdateAlert(({ params: { name, log, updateUrl } }) => {
|
const rUserApiShowUpdateAlert = onShowUserApiUpdateAlert(({ params: { name, log, updateUrl } }) => {
|
||||||
|
|
|
@ -27,6 +27,7 @@ interface Lx {
|
||||||
songlistPosition?: number
|
songlistPosition?: number
|
||||||
}
|
}
|
||||||
rootOffset: number
|
rootOffset: number
|
||||||
|
apiInitPromise: [Promise<boolean>, boolean, (success: boolean) => void]
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|
Loading…
Reference in New Issue