优化自定义源调用处理逻辑

pull/1773/head
lyswhut 2024-01-30 17:40:23 +08:00
parent da2d3237b6
commit 7893814da4
7 changed files with 49 additions and 25 deletions

View File

@ -1,12 +1,7 @@
### 自定义源的不兼容变更与新增内容(源开发者需要看)
自定义源的调用方式已改变
更新前需要注意
- 为了与移动端的调用方式统一,不再推荐使用 `window.lx` 对象(移动端无`window`对象),改用 `globalThis.lx`
- `inited` 事件不再需要传递 `status` 属性,脚本运行过程中,在成功调用 `inited` 事件之前的任何首次未捕获的错误都将视为初始化失败,所以现在若想人为让脚本初始化失败,直接抛出一个错误即可
- 新增 `globalThis.lx.env` 属性,桌面端环境固定为 `desktop`,移动端环境固定为 `mobile`
- 新增 `globalThis.lx.currentScriptInfo` 对象,可以从这里获取解析后的脚本头部注释信息及脚本原始内容,具体可用属性看文档说明
- `globalThis.lx.version` 属性更新到 `2.0.0`
由于自定义源的调用方式变更可能会导致某些第三方源停止工作如果出现这种情况你需要将LX回退到 v2.5.0
### 新增
@ -45,3 +40,15 @@
- 移除所有内置源由于收到腾讯投诉要求停止提供软件内置的连接到他们平台的在线播放及下载服务所以从即日2023年10月18日起LX本身不再提供上述服务
- 更新 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` 属性获取
-

View File

@ -314,18 +314,6 @@ window.addEventListener('unhandledrejection', (event) => {
const message = typeof event.reason === 'string' ? event.reason : event.reason?.message ?? String(event.reason)
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(_ => _)

View File

@ -7,6 +7,16 @@ import apiSourceInfo from '@renderer/utils/musicSdk/api-source-info'
let prevId = ''
export const setUserApi = async(apiId: string) => {
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)) {
qualityList.value = {}
userApi.status = false
@ -17,6 +27,7 @@ export const setUserApi = async(apiId: string) => {
apiSource.value = apiId
}).catch(err => {
if (prevId != apiId) return
if (!window.lx.apiInitPromise[1]) window.lx.apiInitPromise[2](false)
console.log(err)
let api = apiSourceInfo.find(api => !api.disabled)
if (!api) return
@ -28,6 +39,7 @@ export const setUserApi = async(apiId: string) => {
qualityList.value = musicSdk.supportQuality[apiId] ?? {}
apiSource.value = apiId
void setUserApiAction(apiId)
if (!window.lx.apiInitPromise[1]) window.lx.apiInitPromise[2](true)
}
if (apiId != appSetting['common.apiSource']) setApiSource(apiId)

View File

@ -26,6 +26,7 @@ window.lx = {
worker: createWorkers(),
isProd: process.env.NODE_ENV == 'production',
rootOffset: window.dt ? 0 : 8,
apiInitPromise: [Promise.resolve(false), true, () => {}],
}
window.lxData = {}

View File

@ -53,7 +53,7 @@ export const getOtherSource = async(musicInfo: LX.Music.MusicInfo | LX.Download.
let timeout: null | NodeJS.Timeout = setTimeout(() => {
timeout = null
reject(new Error('find music timeout'))
}, 20_000)
}, 15_000)
musicSdk.findMusic(searchMusicInfo).then((otherSource) => {
resolve(otherSource.map(toNewMusicInfo) as LX.Music.MusicInfoOnline[])
}).catch(reject).finally(() => {
@ -166,6 +166,8 @@ export const getOnlineOtherSourceMusicUrl = async({ musicInfos, quality, onToggl
quality: LX.Quality
isFromCache: boolean
}> => {
if (!await window.lx.apiInitPromise[0]) throw new Error('source init failed')
let musicInfo: LX.Music.MusicInfoOnline | null = null
let itemQuality: LX.Quality | null = null
// eslint-disable-next-line no-cond-assign
@ -191,7 +193,7 @@ export const getOnlineOtherSourceMusicUrl = async({ musicInfos, quality, onToggl
} catch (err: any) {
reqPromise = Promise.reject(err)
}
retryedSource.includes(musicInfo.source)
// 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 }
@ -218,6 +220,7 @@ export const handleGetOnlineMusicUrl = async({ musicInfo, quality, onToggleSourc
quality: LX.Quality
isFromCache: boolean
}> => {
if (!await window.lx.apiInitPromise[0]) throw new Error('source init failed')
// console.log(musicInfo.source)
const targetQuality = quality ?? getPlayQuality(appSetting['player.highQuality'], musicInfo)
@ -281,7 +284,7 @@ export const getOnlineOtherSourcePicUrl = async({ musicInfos, onToggleSource, is
} catch (err: any) {
reqPromise = Promise.reject(err)
}
retryedSource.includes(musicInfo.source)
// retryedSource.includes(musicInfo.source)
return reqPromise.then((url: string) => {
return { musicInfo, url, isFromCache: false }
// eslint-disable-next-line @typescript-eslint/promise-function-async
@ -368,7 +371,7 @@ export const getOnlineOtherSourceLyricInfo = async({ musicInfos, onToggleSource,
} catch (err: any) {
reqPromise = Promise.reject(err)
}
retryedSource.includes(musicInfo.source)
// retryedSource.includes(musicInfo.source)
// eslint-disable-next-line @typescript-eslint/promise-function-async
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
return existTimeExp.test(lyricInfo.lyric) ? {

View File

@ -1,12 +1,23 @@
import { onBeforeUnmount } from '@common/utils/vueTools'
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
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 { qualityList, userApi } from '@renderer/store'
import { appSetting } from '@renderer/store/setting'
import { dialog } from '@renderer/plugins/Dialog'
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 () => {
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 } }) => {

View File

@ -27,6 +27,7 @@ interface Lx {
songlistPosition?: number
}
rootOffset: number
apiInitPromise: [Promise<boolean>, boolean, (success: boolean) => void]
}
declare global {