diff --git a/publish/changeLog.md b/publish/changeLog.md index c06fdaa8..e1d73dd7 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -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` 属性获取 +- diff --git a/src/main/modules/userApi/renderer/preload.js b/src/main/modules/userApi/renderer/preload.js index ee4e97b0..ac416c6d 100644 --- a/src/main/modules/userApi/renderer/preload.js +++ b/src/main/modules/userApi/renderer/preload.js @@ -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(_ => _) diff --git a/src/renderer/core/apiSource.ts b/src/renderer/core/apiSource.ts index 20493d58..8c0b4d87 100644 --- a/src/renderer/core/apiSource.ts +++ b/src/renderer/core/apiSource.ts @@ -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) diff --git a/src/renderer/core/globalData.ts b/src/renderer/core/globalData.ts index c600e31f..c9d27171 100644 --- a/src/renderer/core/globalData.ts +++ b/src/renderer/core/globalData.ts @@ -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 = {} diff --git a/src/renderer/core/music/utils.ts b/src/renderer/core/music/utils.ts index 0042e3dc..c7a0b451 100644 --- a/src/renderer/core/music/utils.ts +++ b/src/renderer/core/music/utils.ts @@ -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) ? { diff --git a/src/renderer/core/useApp/useInitUserApi.ts b/src/renderer/core/useApp/useInitUserApi.ts index b2e02032..dfdf1672 100644 --- a/src/renderer/core/useApp/useInitUserApi.ts +++ b/src/renderer/core/useApp/useInitUserApi.ts @@ -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((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 } }) => { diff --git a/src/renderer/types/app.d.ts b/src/renderer/types/app.d.ts index 6aacb692..c6d7372a 100644 --- a/src/renderer/types/app.d.ts +++ b/src/renderer/types/app.d.ts @@ -27,6 +27,7 @@ interface Lx { songlistPosition?: number } rootOffset: number + apiInitPromise: [Promise, boolean, (success: boolean) => void] } declare global {