自定义源添加更新地址参数

pull/930/merge
lyswhut 2022-02-17 10:13:45 +08:00
parent 48fc96226c
commit fc12a235f2
9 changed files with 54 additions and 25 deletions

2
FAQ.md
View File

@ -445,7 +445,7 @@ send(EVENT_NAMES.inited, {
| --- | ---
| `inited` | 脚本初始化完成后发送给应用的事件名,发送该事件时需要传入以下信息:`{status, sources, openDevTools}`<br>`status`:初始化结果(`true`成功,`false`失败)<br>`openDevTools`是否打开DevTools此选项可用于开发脚本时的调试<br>`sources`:支持的源信息对象,<br>`sources[kw/kg/tx/wy/mg].name`:源的名字(目前非必须)<br>`sources[kw/kg/tx/wy/mg].type`:源类型,目前固定值需为`music`<br>`sources[kw/kg/tx/wy/mg].actions`支持的actions由于目前只支持`musicUrl`,所以固定传`['musicUrl']`即可<br>`sources[kw/kg/tx/wy/mg].qualitys`:该源支持的音质列表,有效的值为`['128k', '320k', 'flac']`,该字段用于控制应用可用的音质类型
| `request` | 应用API请求事件名回调入参`handler({ source, action, info})`,回调必须返回`Promise`对象<br>`source`:音乐源,可能的值取决于初始化时传入的`sources`对象的源key值<br>`info`:请求附加信息,内容根据`action`变化<br>`action`:请求操作类型,目前只有`musicUrl`即获取音乐URL链接需要在 Promise 返回歌曲 url`info`的结构:`{type, musicInfo}``info.type`:音乐质量,可能的值有`128k` / `320k` / `flac`(取决于初始化时对应源传入的`qualitys`值中的一个),`info.musicInfo`音乐信息对象里面有音乐ID、名字等信息
| `updateAlert` | 显示源更新弹窗,发送此事件时,需要传入一个字符串(更新日志),内容可以使用`\n`换行最大长度1024超过此长度后将被截取超出的部分此事件每次运行脚本只能调用一次源版本v1.2.0新增)<br>例子:`lx.send(lx.EVENT_NAMES.updateAlert, 'hello world')`
| `updateAlert` | 显示源更新弹窗,发送该事件时的参数:`{log, updateUrl}`<br>`log`:更新日志,必传,字符串类型,内容可以使用`\n`换行最大长度1024超过此长度后将被截取超出的部分<br>`updateUrl`:更新地址用于引导用户去该地址更新源选传需为http协议的url地址最大长度1024<br>此事件每次运行脚本只能调用一次源版本v1.2.0新增)<br>例子:`lx.send(lx.EVENT_NAMES.updateAlert, { log: 'hello world', updateUrl: 'https://xxx.com' })`
#### `window.lx.on`

View File

@ -140,7 +140,7 @@
"my_list": "Your Library",
"no_item": "Nothing's here...",
"not_agree": "Not accept",
"ok": "Ok",
"ok": "OK",
"pagination__next": "Next page",
"pagination__page": "Page {num}",
"pagination__prev": "Previous page",
@ -419,5 +419,6 @@
"user_api__note": "Tip: Although we have isolated the script's running environment as much as possible, importing scripts containing malicious behaviors may still affect your system. Please import them carefully.",
"user_api__readme": "Source writing instructions: ",
"user_api__title": "Custom Source Management",
"user_api__update_alert": "Custom source [{name}] found new version:"
"user_api__update_alert": "Custom source [{name}] found new version:",
"user_api__update_alert_open_url": "Open update address"
}

View File

@ -140,7 +140,7 @@
"my_list": "我的列表",
"no_item": "列表竟然是空的...",
"not_agree": "不接受",
"ok": "好吧",
"ok": "我知道了",
"pagination__next": "下一页",
"pagination__page": "第 {num} 页",
"pagination__prev": "上一页",
@ -419,5 +419,6 @@
"user_api__note": "提示:虽然我们已经尽可能地隔离了脚本的运行环境,但导入包含恶意行为的脚本仍可能会影响你的系统,请谨慎导入。",
"user_api__readme": "源编写说明:",
"user_api__title": "自定义源管理",
"user_api__update_alert": "自定义源 [{name}] 发现新版本:"
"user_api__update_alert": "自定义源 [{name}] 发现新版本:",
"user_api__update_alert_open_url": "打开更新地址"
}

View File

@ -140,7 +140,7 @@
"my_list": "我的列表",
"no_item": "列表竟然是空的...",
"not_agree": "不接受",
"ok": "好吧",
"ok": "我知道了",
"pagination__next": "下一頁",
"pagination__page": "第 {num} 頁",
"pagination__prev": "上一頁",
@ -419,5 +419,6 @@
"user_api__note": "提示:雖然我們已經盡可能地隔離了腳本的運行環境,但導入包含惡意行為的腳本仍可能會影響你的系統,請謹慎導入。",
"user_api__readme": "源編寫說明:",
"user_api__title": "自定義源管理",
"user_api__update_alert": "自定義源 [{name}] 發現新版本:"
"user_api__update_alert": "自定義源 [{name}] 發現新版本:",
"user_api__update_alert_open_url": "打開更新地址"
}

View File

@ -121,10 +121,16 @@ const handleInit = (context, info) => {
})
}
const handleShowUpdateAlert = (message) => {
if (!message || typeof message != 'string') return
if (message.length > 1024) message = message.substring(0, 1024) + '...'
sendMessage(USER_API_RENDERER_EVENT_NAME.showUpdateAlert, message)
const handleShowUpdateAlert = (data, resolve, reject) => {
if (!data || typeof data != 'object') return reject(new Error('parameter format error.'))
if (!data.log || typeof data.log != 'string') return reject(new Error('log is required.'))
if (data.updateUrl && !/^https?:\/\/[^\s$.?#].[^\s]*$/.test(data.updateUrl) && data.updateUrl.length > 1024) delete data.updateUrl
if (data.log.length > 1024) data.log = data.log.substring(0, 1024) + '...'
sendMessage(USER_API_RENDERER_EVENT_NAME.showUpdateAlert, {
log: data.log,
updateUrl: data.updateUrl,
})
resolve()
}
contextBridge.exposeInMainWorld('lx', {
@ -179,10 +185,9 @@ contextBridge.exposeInMainWorld('lx', {
resolve()
break
case EVENT_NAMES.updateAlert:
if (isShowedUpdateAlert) return reject(new Error('The update alert can only be called once'))
if (isShowedUpdateAlert) return reject(new Error('The update alert can only be called once.'))
isShowedUpdateAlert = true
handleShowUpdateAlert(data)
resolve()
handleShowUpdateAlert(data, resolve, reject)
break
default:
reject(new Error('Unknown event name: ' + eventName))

View File

@ -42,7 +42,8 @@ const handleShowUpdateAlert = (event, { data }) => {
global.lx_event.userApi.showUpdateAlert({
name: userApi.name,
description: userApi.description,
message: data,
log: data.log,
updateUrl: data.updateUrl,
})
}
mainOn(USER_API_RENDERER_EVENT_NAME.init, handleInit)

View File

@ -1,5 +1,6 @@
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'
@ -69,11 +70,27 @@ export default ({ setting }) => {
}
})
const rUserApiShowUpdateAlert = onShowUserApiUpdateAlert((event, { name, message }) => {
dialog({
message: `${t('user_api__update_alert', { name })}\n${message}`,
confirmButtonText: t('ok'),
})
const rUserApiShowUpdateAlert = onShowUserApiUpdateAlert((event, { name, log, updateUrl }) => {
if (updateUrl) {
dialog({
message: `${t('user_api__update_alert', { name })}\n${log}`,
selection: true,
showCancel: true,
confirmButtonText: t('user_api__update_alert_open_url'),
cancelButtonText: t('close'),
}).then(confirm => {
if (!confirm) return
setTimeout(() => {
openUrl(updateUrl)
}, 300)
})
} else {
dialog({
message: `${t('user_api__update_alert', { name })}\n${log}`,
selection: true,
confirmButtonText: t('ok'),
})
}
})
onBeforeUnmount(() => {

View File

@ -1,6 +1,6 @@
<template>
<Modal :show="visible" @close="handleCancel" @after-leave="afterLeave" :closeBtn="false" :teleport="teleport">
<main :class="$style.main">{{message}}</main>
<main class="scroll" :class="[$style.main, { 'select': selection }]">{{message}}</main>
<footer :class="$style.footer">
<Btn :class="$style.btn" v-if="showCancel" @click="handleCancel">{{cancelBtnText}}</Btn>
<Btn :class="$style.btn" @click="handleComfirm">{{confirmBtnText}}</Btn>
@ -30,6 +30,7 @@ export default {
cancelButtonText: '',
confirmButtonText: '',
teleport: '#root',
selection: false,
}
},
computed: {
@ -58,9 +59,9 @@ export default {
.main {
flex: auto;
min-height: 40px;
padding: 15px;
padding: 15px 15px 0;
font-size: 14px;
max-width: 320px;
// max-width: 320px;
min-width: 220px;
line-height: 1.5;
white-space: pre-line;
@ -68,7 +69,7 @@ export default {
.footer {
flex: none;
padding: 0 15px 15px;
padding: 15px;
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;

View File

@ -10,10 +10,11 @@ const defaultOptions = {
showCancel: false,
cancelButtonText: '',
confirmButtonText: '',
selection: false,
}
export const dialog = function(options) {
const { message, showCancel, cancelButtonText, confirmButtonText, teleport } =
const { message, showCancel, cancelButtonText, confirmButtonText, teleport, selection } =
Object.assign({}, defaultOptions, typeof options == 'string' ? { message: options } : options || {})
return new Promise((resolve, reject) => {
let app = createApp(Dialog, {
@ -32,6 +33,7 @@ export const dialog = function(options) {
instance.cancelButtonText = cancelButtonText
instance.confirmButtonText = confirmButtonText
instance.teleport = teleport
instance.selection = selection
// 挂载
document.getElementById('container').appendChild(instance.$el)