commit
d695cdef08
|
@ -8,7 +8,7 @@ body:
|
||||||
label: 解决方案检查
|
label: 解决方案检查
|
||||||
description: 请确保你已完成以下所有操作
|
description: 请确保你已完成以下所有操作
|
||||||
options:
|
options:
|
||||||
- label: 我已阅读常见问题(<https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md>),但没有找到解决方案
|
- label: 我已阅读常见问题(<https://lyswhut.github.io/lx-music-doc/desktop/faq>),但没有找到解决方案
|
||||||
required: true
|
required: true
|
||||||
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),但没有发现类似的问题
|
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),但没有发现类似的问题
|
||||||
required: true
|
required: true
|
||||||
|
|
|
@ -8,7 +8,7 @@ body:
|
||||||
label: 解决方案检查
|
label: 解决方案检查
|
||||||
description: 请确保你已完成以下所有操作
|
description: 请确保你已完成以下所有操作
|
||||||
options:
|
options:
|
||||||
- label: 我已阅读常见问题(<https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md>),并没有找到解决方案
|
- label: 我已阅读常见问题(<https://lyswhut.github.io/lx-music-doc/desktop/faq>),并没有找到解决方案
|
||||||
required: true
|
required: true
|
||||||
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),并没有发现类似的问题
|
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),并没有发现类似的问题
|
||||||
required: true
|
required: true
|
||||||
|
|
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -6,6 +6,35 @@ Project versioning adheres to [Semantic Versioning](http://semver.org/).
|
||||||
Commit convention is based on [Conventional Commits](http://conventionalcommits.org).
|
Commit convention is based on [Conventional Commits](http://conventionalcommits.org).
|
||||||
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
|
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
|
||||||
|
|
||||||
|
## [1.22.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.21.0...v1.22.0) - 2022-06-19
|
||||||
|
|
||||||
|
### 新增
|
||||||
|
|
||||||
|
- 新增设置-以全屏模式启动设置
|
||||||
|
- 新增设置-桌面歌词设置-鼠标移入歌词区域时降低歌词透明度(#883),默认关闭,此设置不支持linux,注:此功能存在兼容性问题,若鼠标移出后无法恢复到正常透明度,可尝试再移入移出即可恢复
|
||||||
|
|
||||||
|
### 优化
|
||||||
|
|
||||||
|
- 添加歌曲到“我的列表”时,若按住`ctrl`键(Mac对应`Command`),则不会自动关闭添加窗口,这对想要将同一首(一批)歌曲添加到多个列表时会很有用
|
||||||
|
- 支持mg源逐字歌词的播放,感谢 @mozbugbox 提供的帮助
|
||||||
|
- 添加歌曲列表更新操作的二次确认
|
||||||
|
- 添加导入文件错误时的指引提示
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
|
||||||
|
- 修复若配置了`http_proxy`环境变量时,会意外使用此代理配置的问题
|
||||||
|
- 修复多选后切换列表后不会清空多选内容的问题
|
||||||
|
- 修复设置快捷键时的处理逻辑问题
|
||||||
|
- 修复在新建歌单输入框、歌单内歌曲搜索输入框会意外触发设置的全局快捷键的问题(#879)
|
||||||
|
|
||||||
|
### 文档
|
||||||
|
|
||||||
|
桌面版文档已迁移到:<https://lyswhut.github.io/lx-music-doc/desktop>
|
||||||
|
|
||||||
|
### 其他
|
||||||
|
|
||||||
|
- 更新 Electron 到 v17.4.7
|
||||||
|
|
||||||
## [1.21.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.20.0...v1.21.0) - 2022-05-22
|
## [1.21.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.20.0...v1.21.0) - 2022-05-22
|
||||||
|
|
||||||
### 新增
|
### 新增
|
||||||
|
|
15
FAQ.md
15
FAQ.md
|
@ -1,5 +1,7 @@
|
||||||
# lx-music-desktop 常见问题
|
# lx-music-desktop 常见问题
|
||||||
|
|
||||||
|
本文档已迁移到:<https://lyswhut.github.io/lx-music-doc/desktop/faq>
|
||||||
|
|
||||||
在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题!
|
在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题!
|
||||||
|
|
||||||
## ~~软件为什么没有桌面歌词与自定义列表功能~~
|
## ~~软件为什么没有桌面歌词与自定义列表功能~~
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
- 在我的列表按住`Ctrl`键可以进入列表拖动模式,此时可以用鼠标拖动列表调整列表的位置
|
- 在我的列表按住`Ctrl`键可以进入列表拖动模式,此时可以用鼠标拖动列表调整列表的位置
|
||||||
- 编辑列表名时按`Esc`键可以取消编辑
|
- 编辑列表名时按`Esc`键可以取消编辑
|
||||||
- 按`F11`可以进入、退出全屏状态(v1.19.0新增)
|
- 按`F11`可以进入、退出全屏状态(v1.19.0新增)
|
||||||
|
- 在歌曲添加弹窗中,若按住`Ctrl`键后再点击列表名,将不会自动关闭添加窗口,这对想要将同一首(一批)歌曲添加到多个列表时会很有用(v1.22.0新增)
|
||||||
|
|
||||||
注:在macOS上`Ctrl`键对应`Command`键
|
注:在macOS上`Ctrl`键对应`Command`键
|
||||||
|
|
||||||
|
@ -71,6 +74,16 @@
|
||||||
1. 将DNS改成自动获取试试
|
1. 将DNS改成自动获取试试
|
||||||
2. 手动把DNS改一下,不要用360的DNS,可以把DNS改成`223.6.6.6`、`8.8.8.8`
|
2. 手动把DNS改一下,不要用360的DNS,可以把DNS改成`223.6.6.6`、`8.8.8.8`
|
||||||
|
|
||||||
|
### Windows版所有歌曲都提示 `音频加载错误,5秒后切换下一首`
|
||||||
|
|
||||||
|
尝试关闭 Internet选项 的代理设置。
|
||||||
|
|
||||||
|
如果你不知道怎么做,可以尝试按以下步骤去做:
|
||||||
|
|
||||||
|
按<kbd>windows</kbd>+<kbd>r</kbd>键打开“运行”窗口,输入`inetcpl.cpl`后回车,在打开的 Internet选项 对话框中,切换到 连接 -> 局域网设置,在弹出的新窗口中把代理服务器下的勾去掉,如果自动配置下的勾也有被勾选,那么建议也去掉,最后按确定关闭所有弹窗。
|
||||||
|
|
||||||
|
> 来源:<https://github.com/lyswhut/lx-music-desktop/issues/873#issuecomment-1146945724>
|
||||||
|
|
||||||
## 列表多选
|
## 列表多选
|
||||||
|
|
||||||
从v0.18.0起,列表多选需要键盘配合,想要多选前需按下`Shift`或`Ctrl`键然后再鼠标点击想要选中的内容即可触发多选机制,其中`Shift`键用于连续选择,`Ctrl`键用于不连续选择,`Ctrl+a`用于快速全选。
|
从v0.18.0起,列表多选需要键盘配合,想要多选前需按下`Shift`或`Ctrl`键然后再鼠标点击想要选中的内容即可触发多选机制,其中`Shift`键用于连续选择,`Ctrl`键用于不连续选择,`Ctrl+a`用于快速全选。
|
||||||
|
@ -114,7 +127,7 @@
|
||||||
|
|
||||||
这些浏览器打开此窗口时界面可能是中文也可能是英文,英文的话按括号里的来
|
这些浏览器打开此窗口时界面可能是中文也可能是英文,英文的话按括号里的来
|
||||||
|
|
||||||
1. 点击窗口顶部`应用程序(application)`
|
1. 点击窗口顶部`应用程序(application)`(若找不到此选项,则可能是被折叠起来了,看看顶部菜单的`>>`)
|
||||||
2. 展开左侧 `Cookies`
|
2. 展开左侧 `Cookies`
|
||||||
3. 点击 `https://music.163.com`
|
3. 点击 `https://music.163.com`
|
||||||
4. 在右侧窗口找到 `名称(Name)` 为 `MUSIC_U` 的这行,这行的第二列(`值(Value)`)内的那串内容就是`token`,双击它进入编辑状态,然后按`ctrl + c`键就可以将它复制
|
4. 在右侧窗口找到 `名称(Name)` 为 `MUSIC_U` 的这行,这行的第二列(`值(Value)`)内的那串内容就是`token`,双击它进入编辑状态,然后按`ctrl + c`键就可以将它复制
|
||||||
|
|
10
README.md
10
README.md
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
所用技术栈:
|
所用技术栈:
|
||||||
|
|
||||||
- Electron 13
|
- Electron 17
|
||||||
- Vue 3
|
- Vue 3
|
||||||
|
|
||||||
已支持的平台:
|
已支持的平台:
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
软件变化请查看:[更新日志](https://github.com/lyswhut/lx-music-desktop/blob/master/CHANGELOG.md)<br>
|
软件变化请查看:[更新日志](https://github.com/lyswhut/lx-music-desktop/blob/master/CHANGELOG.md)<br>
|
||||||
软件下载请转到:[发布页面](https://github.com/lyswhut/lx-music-desktop/releases)<br>
|
软件下载请转到:[发布页面](https://github.com/lyswhut/lx-music-desktop/releases)<br>
|
||||||
或者到网盘下载(网盘内有MAC、windows版):`https://www.lanzoui.com/b0bf2cfa/` 密码:`glqw`(若链接无法打开请百度:蓝奏云链接打不开)<br>
|
或者到网盘下载(网盘内有MAC、windows版):`https://www.lanzoui.com/b0bf2cfa/` 密码:`glqw`(若链接无法打开请百度:蓝奏云链接打不开)<br>
|
||||||
使用常见问题请转至:[常见问题](https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md)<br>
|
使用常见问题请转至:[常见问题](https://lyswhut.github.io/lx-music-doc/desktop/faq)<br>
|
||||||
移动版项目地址:<https://github.com/lyswhut/lx-music-mobile>
|
移动版项目地址:<https://github.com/lyswhut/lx-music-mobile>
|
||||||
|
|
||||||
#### Scheme URL支持
|
#### Scheme URL支持
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
从v1.17.0起支持 Scheme URL,可以使用此功能从浏览器等场景下调用LX Music,我们开发了一个[油猴脚本](https://github.com/lyswhut/lx-music-script#readme)配套使用,<br>
|
从v1.17.0起支持 Scheme URL,可以使用此功能从浏览器等场景下调用LX Music,我们开发了一个[油猴脚本](https://github.com/lyswhut/lx-music-script#readme)配套使用,<br>
|
||||||
脚本安装地址:<https://greasyfork.org/zh-CN/scripts/438148><br>
|
脚本安装地址:<https://greasyfork.org/zh-CN/scripts/438148><br>
|
||||||
|
|
||||||
若你想自己调用LX Music,可以看[Scheme URL支持](https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md#scheme-url%E6%94%AF%E6%8C%81)
|
若你想自己调用LX Music,可以看[Scheme URL支持](https://lyswhut.github.io/lx-music-doc/desktop/scheme-url)
|
||||||
|
|
||||||
#### 启动参数
|
#### 启动参数
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
- `-dt` 以非透明模式启动(Disable Transparent)
|
- `-dt` 以非透明模式启动(Disable Transparent)
|
||||||
- `-dhmkh` 禁用硬件媒体密钥处理(Disable Hardware Media Key Handling)
|
- `-dhmkh` 禁用硬件媒体密钥处理(Disable Hardware Media Key Handling)
|
||||||
|
|
||||||
启动参数的详细说明请看[启动参数说明](https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md#%E5%90%AF%E5%8A%A8%E5%8F%82%E6%95%B0)
|
启动参数的详细说明请看[启动参数说明](https://lyswhut.github.io/lx-music-doc/desktop/run-params)
|
||||||
|
|
||||||
#### 数据存储路径
|
#### 数据存储路径
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ npm run pack:linux
|
||||||
|
|
||||||
### 常见问题
|
### 常见问题
|
||||||
|
|
||||||
常见问题已移至:<https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md>
|
常见问题已移至:<https://lyswhut.github.io/lx-music-doc/desktop/faq>
|
||||||
|
|
||||||
### 项目协议
|
### 项目协议
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ module.exports = merge(baseConfig, {
|
||||||
NODE_ENV: '"development"',
|
NODE_ENV: '"development"',
|
||||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
||||||
},
|
},
|
||||||
|
ENVIRONMENT: 'process.env',
|
||||||
__VUE_OPTIONS_API__: 'true',
|
__VUE_OPTIONS_API__: 'true',
|
||||||
__VUE_PROD_DEVTOOLS__: 'false',
|
__VUE_PROD_DEVTOOLS__: 'false',
|
||||||
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||||
|
|
|
@ -31,6 +31,7 @@ module.exports = merge(baseConfig, {
|
||||||
'process.env': {
|
'process.env': {
|
||||||
NODE_ENV: '"production"',
|
NODE_ENV: '"production"',
|
||||||
},
|
},
|
||||||
|
ENVIRONMENT: 'process.env',
|
||||||
__VUE_OPTIONS_API__: 'true',
|
__VUE_OPTIONS_API__: 'true',
|
||||||
__VUE_PROD_DEVTOOLS__: 'false',
|
__VUE_PROD_DEVTOOLS__: 'false',
|
||||||
}),
|
}),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
50
package.json
50
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lx-music-desktop",
|
"name": "lx-music-desktop",
|
||||||
"version": "1.21.0",
|
"version": "1.22.0",
|
||||||
"description": "一个免费的音乐查找助手",
|
"description": "一个免费的音乐查找助手",
|
||||||
"main": "./dist/main.js",
|
"main": "./dist/main.js",
|
||||||
"productName": "lx-music-desktop",
|
"productName": "lx-music-desktop",
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
"up": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://localhost:1081 npm i"
|
"up": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://localhost:1081 npm i"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"Electron 13.6.8"
|
"Electron 17.4.7"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16",
|
"node": ">= 16",
|
||||||
|
@ -178,32 +178,32 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
|
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.18.0",
|
"@babel/core": "^7.18.5",
|
||||||
"@babel/eslint-parser": "^7.17.0",
|
"@babel/eslint-parser": "^7.18.2",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-transform-modules-umd": "^7.18.0",
|
"@babel/plugin-transform-modules-umd": "^7.18.0",
|
||||||
"@babel/plugin-transform-runtime": "^7.18.0",
|
"@babel/plugin-transform-runtime": "^7.18.5",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
"@babel/preset-env": "^7.18.0",
|
"@babel/preset-env": "^7.18.2",
|
||||||
"babel-loader": "^8.2.5",
|
"babel-loader": "^8.2.5",
|
||||||
"babel-preset-minify": "^0.5.2",
|
"babel-preset-minify": "^0.5.2",
|
||||||
"browserslist": "^4.20.3",
|
"browserslist": "^4.20.4",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"changelog-parser": "^2.8.1",
|
"changelog-parser": "^2.8.1",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"core-js": "^3.22.5",
|
"core-js": "^3.23.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.7.1",
|
"css-loader": "^6.7.1",
|
||||||
"css-minimizer-webpack-plugin": "^4.0.0",
|
"css-minimizer-webpack-plugin": "^4.0.0",
|
||||||
"del": "^6.1.0",
|
"del": "^6.1.1",
|
||||||
"electron": "^13.6.9",
|
"electron": "^17.4.7",
|
||||||
"electron-builder": "^23.0.9",
|
"electron-builder": "^23.1.0",
|
||||||
"electron-debug": "^3.2.0",
|
"electron-debug": "^3.2.0",
|
||||||
"electron-devtools-installer": "^3.2.0",
|
"electron-devtools-installer": "^3.2.0",
|
||||||
"electron-to-chromium": "^1.4.137",
|
"electron-to-chromium": "^1.4.161",
|
||||||
"electron-updater": "^5.0.4",
|
"electron-updater": "^5.0.5",
|
||||||
"eslint": "^8.16.0",
|
"eslint": "^8.18.0",
|
||||||
"eslint-config-standard": "^17.0.0",
|
"eslint-config-standard": "^17.0.0",
|
||||||
"eslint-formatter-friendly": "git+https://github.com/lyswhut/eslint-friendly-formatter.git#2170d1320e2fad13615a9dcf229669f0bb473a53",
|
"eslint-formatter-friendly": "git+https://github.com/lyswhut/eslint-friendly-formatter.git#2170d1320e2fad13615a9dcf229669f0bb473a53",
|
||||||
"eslint-plugin-html": "^6.2.0",
|
"eslint-plugin-html": "^6.2.0",
|
||||||
|
@ -214,9 +214,9 @@
|
||||||
"eslint-webpack-plugin": "^3.1.1",
|
"eslint-webpack-plugin": "^3.1.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"less": "^4.1.2",
|
"less": "^4.1.3",
|
||||||
"less-loader": "^11.0.0",
|
"less-loader": "^11.0.0",
|
||||||
"mini-css-extract-plugin": "^2.6.0",
|
"mini-css-extract-plugin": "^2.6.1",
|
||||||
"node-loader": "^2.0.0",
|
"node-loader": "^2.0.0",
|
||||||
"postcss": "^8.4.14",
|
"postcss": "^8.4.14",
|
||||||
"postcss-loader": "^7.0.0",
|
"postcss-loader": "^7.0.0",
|
||||||
|
@ -229,14 +229,14 @@
|
||||||
"spinnies": "git+https://github.com/lyswhut/spinnies.git#233305c58694aa3b053e3ab9af9049993f918b9d",
|
"spinnies": "git+https://github.com/lyswhut/spinnies.git#233305c58694aa3b053e3ab9af9049993f918b9d",
|
||||||
"svg-sprite-loader": "^6.0.11",
|
"svg-sprite-loader": "^6.0.11",
|
||||||
"svg-transform-loader": "^2.0.13",
|
"svg-transform-loader": "^2.0.13",
|
||||||
"svgo-loader": "^3.0.0",
|
"svgo-loader": "^3.0.1",
|
||||||
"terser-webpack-plugin": "^5.3.1",
|
"terser-webpack-plugin": "^5.3.3",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"vue-loader": "^17.0.0",
|
"vue-loader": "^17.0.0",
|
||||||
"vue-template-compiler": "^2.6.14",
|
"vue-template-compiler": "^2.7.0-beta.2",
|
||||||
"webpack": "^5.72.1",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.10.0",
|
||||||
"webpack-dev-server": "^4.9.0",
|
"webpack-dev-server": "^4.9.2",
|
||||||
"webpack-hot-middleware": "git+https://github.com/lyswhut/webpack-hot-middleware.git#329c4375134b89d39da23a56a94db651247c74a1",
|
"webpack-hot-middleware": "git+https://github.com/lyswhut/webpack-hot-middleware.git#329c4375134b89d39da23a56a94db651247c74a1",
|
||||||
"webpack-merge": "^5.8.0"
|
"webpack-merge": "^5.8.0"
|
||||||
},
|
},
|
||||||
|
@ -244,7 +244,7 @@
|
||||||
"bufferutil": "^4.0.6",
|
"bufferutil": "^4.0.6",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"electron-log": "^4.4.7",
|
"electron-log": "^4.4.7",
|
||||||
"electron-store": "^8.0.1",
|
"electron-store": "^8.0.2",
|
||||||
"font-list": "git+https://github.com/lyswhut/node-font-list.git#4edbb1933b49a9bac1eedd63a31da16b487fe57d",
|
"font-list": "git+https://github.com/lyswhut/node-font-list.git#4edbb1933b49a9bac1eedd63a31da16b487fe57d",
|
||||||
"http-terminator": "^3.2.0",
|
"http-terminator": "^3.2.0",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
|
@ -259,8 +259,8 @@
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"tunnel": "^0.0.6",
|
"tunnel": "^0.0.6",
|
||||||
"utf-8-validate": "^5.0.9",
|
"utf-8-validate": "^5.0.9",
|
||||||
"vue": "^3.2.35",
|
"vue": "^3.2.37",
|
||||||
"vue-i18n": "^9.2.0-beta.35",
|
"vue-i18n": "^9.2.0-beta.36",
|
||||||
"vue-router": "^4.1.0-aabe509",
|
"vue-router": "^4.1.0-aabe509",
|
||||||
"vuex": "^4.0.2"
|
"vuex": "^4.0.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
### 新增
|
### 新增
|
||||||
|
|
||||||
- 新增设置-播放设置-显示歌词罗马音,默认关闭,注:目前只有网易源能获取到罗马音歌词(得益于 Binaryify/NeteaseCloudMusicApi/pull/1523),如果你知道其他源的歌词罗马音获取方式,欢迎PR或开issue交流!
|
- 新增设置-以全屏模式启动设置
|
||||||
|
- 新增设置-桌面歌词设置-鼠标移入歌词区域时降低歌词透明度(#883),默认关闭,此设置不支持linux,注:此功能存在兼容性问题,若鼠标移出后无法恢复到正常透明度,可尝试再移入移出即可恢复
|
||||||
|
|
||||||
### 优化
|
### 优化
|
||||||
|
|
||||||
- 同时删除一首歌以上时将需要二次确认删除
|
- 添加歌曲到“我的列表”时,若按住`ctrl`键(Mac对应`Command`),则不会自动关闭添加窗口,这对想要将同一首(一批)歌曲添加到多个列表时会很有用
|
||||||
- 禁用透明窗口时右侧不再偏移5px距离(在win7、Ubuntu等系统上测试发现不偏移也不影响滚动条的拖动了)
|
- 支持mg源逐字歌词的播放,感谢 @mozbugbox 提供的帮助
|
||||||
- 删除未下载完成的任务时,只同时尝试删除已有下载进度的本地文件
|
- 添加歌曲列表更新操作的二次确认
|
||||||
- 在全屏状态下使用`Esc`键可以退出全屏(#827)
|
- 添加导入文件错误时的指引提示
|
||||||
|
|
||||||
### 修复
|
### 修复
|
||||||
|
|
||||||
- 修复某些情况下歌曲播放出错时不会自动切歌的问题
|
- 修复若配置了`http_proxy`环境变量时,会意外使用此代理配置的问题
|
||||||
- 修复关闭“显示切换动画”设置后,在应用启动时该设置没有被应用的问题
|
- 修复多选后切换列表后不会清空多选内容的问题
|
||||||
- 修复原始歌词存在偏移时,歌词偏移设置的重置未按预期工作的问题
|
- 修复设置快捷键时的处理逻辑问题
|
||||||
- 修复长度大于一行的歌词在使用歌词调整播放进度时的时间不准问题
|
- 修复在新建歌单输入框、歌单内歌曲搜索输入框会意外触发设置的全局快捷键的问题(#879)
|
||||||
- 修复潜在歌单更新失败的问题
|
|
||||||
|
|
||||||
### 文档
|
### 文档
|
||||||
|
|
||||||
- 将歌曲添加“稍后播放”后,它们会被放在一个优先级最高的特殊队列中,点击“下一曲”时会消耗该队列中的歌曲,并且无法通过“上一曲”功能播放该队列的上一首歌曲
|
桌面版文档已迁移到:<https://lyswhut.github.io/lx-music-doc/desktop>
|
||||||
- 在切歌时若不是通过“上一曲”、“下一曲”功能切歌(例如直接点击“排行榜列表”、“我的列表”中的歌曲切歌),“稍后播放”队列将会被清空
|
|
||||||
|
### 其他
|
||||||
|
|
||||||
|
- 更新 Electron 到 v17.4.7
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@ const path = require('path')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
|
|
||||||
const defaultSetting = {
|
const defaultSetting = {
|
||||||
version: '1.0.57',
|
version: '1.0.59',
|
||||||
player: {
|
player: {
|
||||||
togglePlayMethod: 'listLoop',
|
togglePlayMethod: 'listLoop',
|
||||||
highQuality: false,
|
highQuality: false,
|
||||||
|
@ -41,6 +41,7 @@ const defaultSetting = {
|
||||||
theme: 0,
|
theme: 0,
|
||||||
isLockScreen: true,
|
isLockScreen: true,
|
||||||
isDelayScroll: true,
|
isDelayScroll: true,
|
||||||
|
isHoverHide: false,
|
||||||
style: {
|
style: {
|
||||||
font: '',
|
font: '',
|
||||||
fontSize: 120,
|
fontSize: 120,
|
||||||
|
@ -108,6 +109,7 @@ const defaultSetting = {
|
||||||
port: '23332',
|
port: '23332',
|
||||||
},
|
},
|
||||||
windowSizeId: 2,
|
windowSizeId: 2,
|
||||||
|
startInFullscreen: false,
|
||||||
theme: {
|
theme: {
|
||||||
id: 0,
|
id: 0,
|
||||||
lightId: 0,
|
lightId: 0,
|
||||||
|
|
|
@ -95,6 +95,11 @@
|
||||||
"list_add__title_first_add": "Add",
|
"list_add__title_first_add": "Add",
|
||||||
"list_add__title_first_move": "Move",
|
"list_add__title_first_move": "Move",
|
||||||
"list_add__title_last": "to...",
|
"list_add__title_last": "to...",
|
||||||
|
"list_import_tip__alldata": "Import failed, this is an all data backup file, you need to go here to import: \nSettings -> Backup and Restore -> All Data -> Import",
|
||||||
|
"list_import_tip__playlist": "Import failed, this is a list backup file, you need to go here to import: \nSettings -> Backup and Restore -> Import List",
|
||||||
|
"list_import_tip__playlist_part": "The import failed, this is a single-list file, you need to go here to import: \nMy List -> Right-click on any list name -> Select Import in the pop-up menu",
|
||||||
|
"list_import_tip__setting": "Import failed, this is a settings backup file, you need to go here to import: \nSettings -> Backup and Restore -> Partial Data -> Settings Import",
|
||||||
|
"list_import_tip__unknown": "Import failed, unknown file type, please try to upgrade to the latest version and try again",
|
||||||
"list_sort_modal_by_album": "Album name",
|
"list_sort_modal_by_album": "Album name",
|
||||||
"list_sort_modal_by_down": "Descending",
|
"list_sort_modal_by_down": "Descending",
|
||||||
"list_sort_modal_by_field": "Sort field",
|
"list_sort_modal_by_field": "Sort field",
|
||||||
|
@ -127,6 +132,7 @@
|
||||||
"lists__sort_list": "Sort songs",
|
"lists__sort_list": "Sort songs",
|
||||||
"lists__source_detail": "Playlist Page",
|
"lists__source_detail": "Playlist Page",
|
||||||
"lists__sync": "Update",
|
"lists__sync": "Update",
|
||||||
|
"lists__sync_confirm_tip": "This will replace the songs in {name} with the songs in the online list, are you sure you want to update?",
|
||||||
"load_list_file_error_detail": "We have helped you back up the old list file to {path}\nIt is stored in JSON format, you can try to repair and restore it manually\n\nError details: {detail}",
|
"load_list_file_error_detail": "We have helped you back up the old list file to {path}\nIt is stored in JSON format, you can try to repair and restore it manually\n\nError details: {detail}",
|
||||||
"load_list_file_error_title": "Error loading playlist data",
|
"load_list_file_error_title": "Error loading playlist data",
|
||||||
"loding_list": "Loading...",
|
"loding_list": "Loading...",
|
||||||
|
@ -246,6 +252,7 @@
|
||||||
"setting__basic_sourcename_alias": "Aliases",
|
"setting__basic_sourcename_alias": "Aliases",
|
||||||
"setting__basic_sourcename_real": "Original",
|
"setting__basic_sourcename_real": "Original",
|
||||||
"setting__basic_sourcename_title": "Select the name of music source",
|
"setting__basic_sourcename_title": "Select the name of music source",
|
||||||
|
"setting__basic_start_in_fullscreen": "Start in fullscreen mode",
|
||||||
"setting__basic_theme": "Theme",
|
"setting__basic_theme": "Theme",
|
||||||
"setting__basic_theme_auto_tip": "This is a dynamic theme, you can preset a light theme and a dark theme, and then it will automatically switch to the corresponding theme you preset according to the system's light and dark theme colors.\nNote: Right-click this theme item to open the light and dark theme setting window.",
|
"setting__basic_theme_auto_tip": "This is a dynamic theme, you can preset a light theme and a dark theme, and then it will automatically switch to the corresponding theme you preset according to the system's light and dark theme colors.\nNote: Right-click this theme item to open the light and dark theme setting window.",
|
||||||
"setting__basic_to_tray": "Do not exit the software when closing the software and minimize it to the system tray",
|
"setting__basic_to_tray": "Do not exit the software when closing the software and minimize it to the system tray",
|
||||||
|
@ -267,6 +274,7 @@
|
||||||
"setting__desktop_lyric_enable": "Display lyrics",
|
"setting__desktop_lyric_enable": "Display lyrics",
|
||||||
"setting__desktop_lyric_font": "Lyric font",
|
"setting__desktop_lyric_font": "Lyric font",
|
||||||
"setting__desktop_lyric_font_default": "Default",
|
"setting__desktop_lyric_font_default": "Default",
|
||||||
|
"setting__desktop_lyric_hover_hide": "Reduce the transparency of lyrics when the mouse moves into the lyrics area (this feature has platform compatibility issues)",
|
||||||
"setting__desktop_lyric_lock": "Lock lyrics",
|
"setting__desktop_lyric_lock": "Lock lyrics",
|
||||||
"setting__desktop_lyric_lock_screen": "It is not allowed to drag the lyrics window out of the main screen",
|
"setting__desktop_lyric_lock_screen": "It is not allowed to drag the lyrics window out of the main screen",
|
||||||
"setting__download": "Download",
|
"setting__download": "Download",
|
||||||
|
|
|
@ -95,6 +95,11 @@
|
||||||
"list_add__title_first_add": "添加",
|
"list_add__title_first_add": "添加",
|
||||||
"list_add__title_first_move": "移动",
|
"list_add__title_first_move": "移动",
|
||||||
"list_add__title_last": "到...",
|
"list_add__title_last": "到...",
|
||||||
|
"list_import_tip__alldata": "导入失败,这是一个所有数据备份文件,你需要去这里导入:\n设置 -> 备份与恢复 -> 所有数据 -> 导入",
|
||||||
|
"list_import_tip__playlist": "导入失败,这是一个列表备份文件,你需要去这里导入:\n设置 -> 备份与恢复 -> 部分数据 -> 导入列表",
|
||||||
|
"list_import_tip__playlist_part": "导入失败,这是一个单列表文件,你需要去这里导入:\n我的列表 -> 右击任意一个列表名 -> 在弹出的菜单中选择导入",
|
||||||
|
"list_import_tip__setting": "导入失败,这是一个设置备份文件,你需要去这里导入:\n设置 -> 备份与恢复 -> 部分数据 -> 设置导入",
|
||||||
|
"list_import_tip__unknown": "导入失败,未知的文件类型,请尝试升级到最新版本后再试",
|
||||||
"list_sort_modal_by_album": "专辑名",
|
"list_sort_modal_by_album": "专辑名",
|
||||||
"list_sort_modal_by_down": "降序",
|
"list_sort_modal_by_down": "降序",
|
||||||
"list_sort_modal_by_field": "排序字段",
|
"list_sort_modal_by_field": "排序字段",
|
||||||
|
@ -127,6 +132,7 @@
|
||||||
"lists__sort_list": "排序歌曲",
|
"lists__sort_list": "排序歌曲",
|
||||||
"lists__source_detail": "歌单详情页",
|
"lists__source_detail": "歌单详情页",
|
||||||
"lists__sync": "更新",
|
"lists__sync": "更新",
|
||||||
|
"lists__sync_confirm_tip": "这将会把 {name} 内的歌曲替换成在线列表的歌曲,你确认要更新吗?",
|
||||||
"load_list_file_error_detail": "我们已经帮你把旧的列表文件备份到{path}\n它以 JSON 格式存储,你可以尝试手动修复并恢复它\n\n错误详情:{detail}",
|
"load_list_file_error_detail": "我们已经帮你把旧的列表文件备份到{path}\n它以 JSON 格式存储,你可以尝试手动修复并恢复它\n\n错误详情:{detail}",
|
||||||
"load_list_file_error_title": "播放列表数据加载错误(建议到GitHub或加群反馈)",
|
"load_list_file_error_title": "播放列表数据加载错误(建议到GitHub或加群反馈)",
|
||||||
"loding": "加载中...",
|
"loding": "加载中...",
|
||||||
|
@ -246,6 +252,7 @@
|
||||||
"setting__basic_sourcename_alias": "别名",
|
"setting__basic_sourcename_alias": "别名",
|
||||||
"setting__basic_sourcename_real": "原名",
|
"setting__basic_sourcename_real": "原名",
|
||||||
"setting__basic_sourcename_title": "选择音源名字类型",
|
"setting__basic_sourcename_title": "选择音源名字类型",
|
||||||
|
"setting__basic_start_in_fullscreen": "以全屏模式启动",
|
||||||
"setting__basic_theme": "主题颜色",
|
"setting__basic_theme": "主题颜色",
|
||||||
"setting__basic_theme_auto_tip": "此乃动态主题,你可以预先设置一个亮色主题及暗色主题,此后将根据系统的亮、暗主题色自动切换为你预先设置的相应主题。\n注:鼠标 右击 此主题项即可打开亮、暗色主题设置窗口。",
|
"setting__basic_theme_auto_tip": "此乃动态主题,你可以预先设置一个亮色主题及暗色主题,此后将根据系统的亮、暗主题色自动切换为你预先设置的相应主题。\n注:鼠标 右击 此主题项即可打开亮、暗色主题设置窗口。",
|
||||||
"setting__basic_to_tray": "关闭软件时不退出软件将其最小化到系统托盘",
|
"setting__basic_to_tray": "关闭软件时不退出软件将其最小化到系统托盘",
|
||||||
|
@ -267,6 +274,7 @@
|
||||||
"setting__desktop_lyric_enable": "显示歌词",
|
"setting__desktop_lyric_enable": "显示歌词",
|
||||||
"setting__desktop_lyric_font": "歌词字体",
|
"setting__desktop_lyric_font": "歌词字体",
|
||||||
"setting__desktop_lyric_font_default": "默认",
|
"setting__desktop_lyric_font_default": "默认",
|
||||||
|
"setting__desktop_lyric_hover_hide": "鼠标移入歌词区域时降低歌词透明度(此功能存在平台兼容性问题)",
|
||||||
"setting__desktop_lyric_lock": "锁定歌词",
|
"setting__desktop_lyric_lock": "锁定歌词",
|
||||||
"setting__desktop_lyric_lock_screen": "不允许歌词窗口拖出主屏幕之外",
|
"setting__desktop_lyric_lock_screen": "不允许歌词窗口拖出主屏幕之外",
|
||||||
"setting__download": "下载设置",
|
"setting__download": "下载设置",
|
||||||
|
|
|
@ -95,6 +95,11 @@
|
||||||
"list_add__title_first_add": "添加",
|
"list_add__title_first_add": "添加",
|
||||||
"list_add__title_first_move": "移動",
|
"list_add__title_first_move": "移動",
|
||||||
"list_add__title_last": "到...",
|
"list_add__title_last": "到...",
|
||||||
|
"list_import_tip__alldata": "導入失敗,這是一個所有數據備份文件,你需要去這裡導入:\n設置 -> 備份與恢復 -> 所有數據 -> 導入",
|
||||||
|
"list_import_tip__playlist": "導入失敗,這是一個列表備份文件,你需要去這裡導入:\n設置 -> 備份與恢復 -> 部分數據 -> 導入列表",
|
||||||
|
"list_import_tip__playlist_part": "導入失敗,這是一個單列表文件,你需要去這裡導入:\n我的列表 -> 右擊任意一個列表名 -> 在彈出的菜單中選擇導入",
|
||||||
|
"list_import_tip__setting": "導入失敗,這是一個設置備份文件,你需要去這裡導入:\n設置 -> 備份與恢復 -> 部分數據 -> 設置導入",
|
||||||
|
"list_import_tip__unknown": "導入失敗,未知的文件類型,請嘗試升級到最新版本後再試",
|
||||||
"list_sort_modal_by_album": "專輯名",
|
"list_sort_modal_by_album": "專輯名",
|
||||||
"list_sort_modal_by_down": "降序",
|
"list_sort_modal_by_down": "降序",
|
||||||
"list_sort_modal_by_field": "排序字段",
|
"list_sort_modal_by_field": "排序字段",
|
||||||
|
@ -127,6 +132,7 @@
|
||||||
"lists__sort_list": "排序歌曲",
|
"lists__sort_list": "排序歌曲",
|
||||||
"lists__source_detail": "歌單詳情頁",
|
"lists__source_detail": "歌單詳情頁",
|
||||||
"lists__sync": "更新",
|
"lists__sync": "更新",
|
||||||
|
"lists__sync_confirm_tip": "這將會把 {name} 內的歌曲替換成在線列表的歌曲,你確認要更新嗎?",
|
||||||
"load_list_file_error_detail": "我們已經幫你把舊的列表文件備份到{path}\n它以 JSON 格式存儲,你可以嘗試手動修復並恢復它\n\n錯誤詳情:{detail}",
|
"load_list_file_error_detail": "我們已經幫你把舊的列表文件備份到{path}\n它以 JSON 格式存儲,你可以嘗試手動修復並恢復它\n\n錯誤詳情:{detail}",
|
||||||
"load_list_file_error_title": "播放列表數據加載錯誤",
|
"load_list_file_error_title": "播放列表數據加載錯誤",
|
||||||
"loding": "加載中...",
|
"loding": "加載中...",
|
||||||
|
@ -246,6 +252,7 @@
|
||||||
"setting__basic_sourcename_alias": "別名",
|
"setting__basic_sourcename_alias": "別名",
|
||||||
"setting__basic_sourcename_real": "原名",
|
"setting__basic_sourcename_real": "原名",
|
||||||
"setting__basic_sourcename_title": "選擇音源名字類型",
|
"setting__basic_sourcename_title": "選擇音源名字類型",
|
||||||
|
"setting__basic_start_in_fullscreen": "以全屏模式啟動",
|
||||||
"setting__basic_theme": "主題顏色",
|
"setting__basic_theme": "主題顏色",
|
||||||
"setting__basic_theme_auto_tip": "此乃動態主題,你可以預先設置一個亮色主題及暗色主題,此後將根據系統的亮、暗主題色自動切換為你預先設置的相應主題。\n注:鼠標 右擊 此主題項即可打開亮、暗色主題設置窗口。",
|
"setting__basic_theme_auto_tip": "此乃動態主題,你可以預先設置一個亮色主題及暗色主題,此後將根據系統的亮、暗主題色自動切換為你預先設置的相應主題。\n注:鼠標 右擊 此主題項即可打開亮、暗色主題設置窗口。",
|
||||||
"setting__basic_to_tray": "關閉軟件時不退出軟件將其最小化到系統托盤",
|
"setting__basic_to_tray": "關閉軟件時不退出軟件將其最小化到系統托盤",
|
||||||
|
@ -267,6 +274,7 @@
|
||||||
"setting__desktop_lyric_enable": "顯示歌詞",
|
"setting__desktop_lyric_enable": "顯示歌詞",
|
||||||
"setting__desktop_lyric_font": "歌詞字體",
|
"setting__desktop_lyric_font": "歌詞字體",
|
||||||
"setting__desktop_lyric_font_default": "默認",
|
"setting__desktop_lyric_font_default": "默認",
|
||||||
|
"setting__desktop_lyric_hover_hide": "鼠標移入歌詞區域時降低歌詞透明度(此功能存在平台兼容性問題)",
|
||||||
"setting__desktop_lyric_lock": "鎖定歌詞",
|
"setting__desktop_lyric_lock": "鎖定歌詞",
|
||||||
"setting__desktop_lyric_lock_screen": "不允許歌詞窗口拖出主屏幕之外",
|
"setting__desktop_lyric_lock_screen": "不允許歌詞窗口拖出主屏幕之外",
|
||||||
"setting__download": "下載設置",
|
"setting__download": "下載設置",
|
||||||
|
|
|
@ -160,7 +160,7 @@ function createWindow() {
|
||||||
/**
|
/**
|
||||||
* Initial window options
|
* Initial window options
|
||||||
*/
|
*/
|
||||||
global.modules.mainWindow = new BrowserWindow({
|
const options = {
|
||||||
height: windowSizeInfo.height,
|
height: windowSizeInfo.height,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
width: windowSizeInfo.width,
|
width: windowSizeInfo.width,
|
||||||
|
@ -178,7 +178,12 @@ function createWindow() {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
spellcheck: false, // 禁用拼写检查器
|
spellcheck: false, // 禁用拼写检查器
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
if (global.appSetting.startInFullscreen) {
|
||||||
|
options.fullscreen = true
|
||||||
|
if (isLinux) options.resizable = true
|
||||||
|
}
|
||||||
|
global.modules.mainWindow = new BrowserWindow(options)
|
||||||
|
|
||||||
const shouldUseDarkColors = nativeTheme.shouldUseDarkColors
|
const shouldUseDarkColors = nativeTheme.shouldUseDarkColors
|
||||||
const themeId = global.appSetting.theme.id == 'auto'
|
const themeId = global.appSetting.theme.id == 'auto'
|
||||||
|
@ -190,6 +195,7 @@ function createWindow() {
|
||||||
global.modules.mainWindow.loadURL(winURL + `?dt=${!!global.envParams.cmdParams.dt}&dark=${shouldUseDarkColors}&theme=${themeClass}`)
|
global.modules.mainWindow.loadURL(winURL + `?dt=${!!global.envParams.cmdParams.dt}&dark=${shouldUseDarkColors}&theme=${themeClass}`)
|
||||||
|
|
||||||
winEvent(global.modules.mainWindow)
|
winEvent(global.modules.mainWindow)
|
||||||
|
if (global.envParams.cmdParams.odt) require('@main/utils').openDevTools(global.modules.mainWindow.webContents)
|
||||||
// global.modules.mainWindow.webContents.openDevTools()
|
// global.modules.mainWindow.webContents.openDevTools()
|
||||||
|
|
||||||
if (!isDev) autoUpdate()
|
if (!isDev) autoUpdate()
|
||||||
|
|
|
@ -3,6 +3,10 @@ const needle = require('needle')
|
||||||
const { createCipheriv, publicEncrypt, constants, randomBytes, createHash } = require('crypto')
|
const { createCipheriv, publicEncrypt, constants, randomBytes, createHash } = require('crypto')
|
||||||
const USER_API_RENDERER_EVENT_NAME = require('../rendererEvent/name')
|
const USER_API_RENDERER_EVENT_NAME = require('../rendererEvent/name')
|
||||||
|
|
||||||
|
for (const key of Object.keys(process.env)) {
|
||||||
|
if (/^(?:http_proxy|https_proxy|NO_PROXY)$/i.test(key)) delete process.env[key]
|
||||||
|
}
|
||||||
|
|
||||||
const sendMessage = (action, data, status, message) => {
|
const sendMessage = (action, data, status, message) => {
|
||||||
ipcRenderer.send(action, { data, status, message })
|
ipcRenderer.send(action, { data, status, message })
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ const { common: COMMON_EVENT_NAME, winLyric: WIN_LYRIC_EVENT_NAME, hotKey: HOT_K
|
||||||
const { mainSend, NAMES: { winLyric: ipcWinLyricNames } } = require('../../../common/ipc')
|
const { mainSend, NAMES: { winLyric: ipcWinLyricNames } } = require('../../../common/ipc')
|
||||||
const { desktop_lyric } = require('../../../common/hotKey')
|
const { desktop_lyric } = require('../../../common/hotKey')
|
||||||
const { getLyricWindowBounds } = require('./utils')
|
const { getLyricWindowBounds } = require('./utils')
|
||||||
|
const { isLinux } = require('@common/utils')
|
||||||
|
|
||||||
let isLock = null
|
let isLock = null
|
||||||
let isEnable = null
|
let isEnable = null
|
||||||
|
@ -47,9 +48,9 @@ const setLrcConfig = () => {
|
||||||
if (isLock != desktopLyric.isLock) {
|
if (isLock != desktopLyric.isLock) {
|
||||||
isLock = desktopLyric.isLock
|
isLock = desktopLyric.isLock
|
||||||
if (desktopLyric.isLock) {
|
if (desktopLyric.isLock) {
|
||||||
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: false })
|
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: !isLinux })
|
||||||
} else {
|
} else {
|
||||||
global.modules.lyricWindow.setIgnoreMouseEvents(false)
|
global.modules.lyricWindow.setIgnoreMouseEvents(false, { forward: !isLinux })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isAlwaysOnTop != desktopLyric.isAlwaysOnTop) {
|
if (isAlwaysOnTop != desktopLyric.isAlwaysOnTop) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ const winEvent = lyricWindow => {
|
||||||
lyricWindow.once('ready-to-show', () => {
|
lyricWindow.once('ready-to-show', () => {
|
||||||
lyricWindow.show()
|
lyricWindow.show()
|
||||||
if (global.appSetting.desktopLyric.isLock) {
|
if (global.appSetting.desktopLyric.isLock) {
|
||||||
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: false })
|
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: !isLinux })
|
||||||
}
|
}
|
||||||
// linux下每次重开时貌似要重新设置置顶
|
// linux下每次重开时貌似要重新设置置顶
|
||||||
if (isLinux && global.appSetting.desktopLyric.isAlwaysOnTop) {
|
if (isLinux && global.appSetting.desktopLyric.isAlwaysOnTop) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
#container(:class="[theme, lrcConfig.isLock ? 'lock' : null]")
|
#container(:class="[theme, { lock: lrcConfig.isLock }, { hide: isHoverHide && isMouseEnter }]")
|
||||||
#main
|
#main(@mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @mousemove="handleMouseMoveMain")
|
||||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||||
.control-bar(v-show="!lrcConfig.isLock")
|
.control-bar(v-show="!lrcConfig.isLock")
|
||||||
core-control-bar(:lrcConfig="lrcConfig" :themes="themeList")
|
core-control-bar(:lrcConfig="lrcConfig" :themes="themeList")
|
||||||
|
@ -21,6 +21,51 @@ import { rendererOn, rendererInvoke, rendererSend, NAMES } from '../common/ipc'
|
||||||
|
|
||||||
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
|
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
|
||||||
|
|
||||||
|
let mouseCheckTools = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
preX: 0,
|
||||||
|
preY: 0,
|
||||||
|
timeout: null,
|
||||||
|
handleCheck(setShow) {
|
||||||
|
let xDiff = Math.abs(this.x - this.preX)
|
||||||
|
let yDiff = Math.abs(this.y - this.preY)
|
||||||
|
if (xDiff > 8) {
|
||||||
|
if (this.x > this.preX) {
|
||||||
|
if (this.x + xDiff * 1.25 > window.innerWidth - 16) return setShow()
|
||||||
|
} else {
|
||||||
|
if (this.x - xDiff * 1.25 < 8) return setShow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (yDiff > 8) {
|
||||||
|
if (this.y > this.preY) {
|
||||||
|
if (this.y + yDiff * 1.25 > window.innerHeight - 16) return setShow()
|
||||||
|
} else {
|
||||||
|
if (this.y - yDiff * 1.25 < 8) return setShow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setShow(false)
|
||||||
|
},
|
||||||
|
handleMove(x, y, setShow) {
|
||||||
|
// console.log(x, y, this.x, this.y)
|
||||||
|
this.preX = this.x
|
||||||
|
this.preY = this.y
|
||||||
|
this.x = x
|
||||||
|
this.y = y
|
||||||
|
this.startTimeout(setShow)
|
||||||
|
},
|
||||||
|
startTimeout(setShow) {
|
||||||
|
this.stopTimeout()
|
||||||
|
this.timeout = setTimeout(this.handleCheck.bind(this), 200, setShow)
|
||||||
|
},
|
||||||
|
stopTimeout() {
|
||||||
|
if (!this.timeout) return
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
this.timeout = null
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -39,6 +84,7 @@ export default {
|
||||||
x: -1,
|
x: -1,
|
||||||
y: -1,
|
y: -1,
|
||||||
theme: 0,
|
theme: 0,
|
||||||
|
isHoverHide: false,
|
||||||
style: {
|
style: {
|
||||||
font: '',
|
font: '',
|
||||||
fontSize: 125,
|
fontSize: 125,
|
||||||
|
@ -91,6 +137,7 @@ export default {
|
||||||
className: 'blue2',
|
className: 'blue2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
isMouseEnter: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -98,6 +145,9 @@ export default {
|
||||||
let theme = this.themeList.find(t => t.id == this.lrcConfig.theme) || this.themeList[0]
|
let theme = this.themeList.find(t => t.id == this.lrcConfig.theme) || this.themeList[0]
|
||||||
return theme.className
|
return theme.className
|
||||||
},
|
},
|
||||||
|
isHoverHide() {
|
||||||
|
return this.lrcConfig.isLock && this.lrcConfig.isHoverHide
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
rendererOn(NAMES.winLyric.set_lyric_config, (event, config) => this.handleUpdateConfig(config))
|
rendererOn(NAMES.winLyric.set_lyric_config, (event, config) => this.handleUpdateConfig(config))
|
||||||
|
@ -147,7 +197,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleMove(clientX, clientY) {
|
handleMove(clientX, clientY) {
|
||||||
if (!this.resize.origin) return
|
if (!this.resize.origin || this.lrcConfig.isLock) return
|
||||||
// if (!event.target.classList.contains('resize-' + this.resize.origin)) return
|
// if (!event.target.classList.contains('resize-' + this.resize.origin)) return
|
||||||
// console.log(event.target)
|
// console.log(event.target)
|
||||||
let bounds = {
|
let bounds = {
|
||||||
|
@ -211,6 +261,24 @@ export default {
|
||||||
// handleMouseOver() {
|
// handleMouseOver() {
|
||||||
// // this.handleMouseUp()
|
// // this.handleMouseUp()
|
||||||
// },
|
// },
|
||||||
|
handleMouseMoveMain(event) {
|
||||||
|
if (!this.isHoverHide) return
|
||||||
|
this.handleMouseEnter()
|
||||||
|
mouseCheckTools.handleMove(event.clientX, event.clientY, () => {
|
||||||
|
this.handleMouseLeave()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleMouseEnter() {
|
||||||
|
// console.log('enter - >')
|
||||||
|
if (!this.isHoverHide || this.isMouseEnter) return
|
||||||
|
this.isMouseEnter = true
|
||||||
|
},
|
||||||
|
handleMouseLeave() {
|
||||||
|
// console.log('leave - <')
|
||||||
|
if (!this.isHoverHide) return
|
||||||
|
this.isMouseEnter = false
|
||||||
|
mouseCheckTools.stopTimeout()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -240,11 +308,16 @@ body {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
transition: opacity .3s ease;
|
||||||
|
opacity: 1;
|
||||||
&.lock {
|
&.lock {
|
||||||
#main {
|
#main {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.hide {
|
||||||
|
opacity: .05;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-left {
|
.resize-left {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 0 42 42" space="preserve">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 0 42 42" space="preserve">
|
||||||
<use xlink:href="#icon-addTo"></use>
|
<use xlink:href="#icon-addTo"></use>
|
||||||
</svg>
|
</svg>
|
||||||
<input class="key-bind" :class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('lists__new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)"/>
|
<input :class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('lists__new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)"/>
|
||||||
</base-btn>
|
</base-btn>
|
||||||
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,7 @@ import { mapMutations } from 'vuex'
|
||||||
import { computed } from '@renderer/utils/vueTools'
|
import { computed } from '@renderer/utils/vueTools'
|
||||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||||
import { getList } from '@renderer/core/share/utils'
|
import { getList } from '@renderer/core/share/utils'
|
||||||
|
import useKeyDown from '@renderer/utils/compositions/useKeyDown'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
@ -57,6 +58,8 @@ export default {
|
||||||
},
|
},
|
||||||
emits: ['update:show'],
|
emits: ['update:show'],
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
const keyModDown = useKeyDown('mod')
|
||||||
|
|
||||||
const lists = computed(() => {
|
const lists = computed(() => {
|
||||||
if (!props.musicInfo) return []
|
if (!props.musicInfo) return []
|
||||||
const targetMid = props.musicInfo.songmid
|
const targetMid = props.musicInfo.songmid
|
||||||
|
@ -67,6 +70,7 @@ export default {
|
||||||
].filter(l => !props.excludeListId.includes(l.id)).map(l => ({ ...l, isExist: getList(l.id).some(s => s.songmid == targetMid) }))
|
].filter(l => !props.excludeListId.includes(l.id)).map(l => ({ ...l, isExist: getList(l.id).some(s => s.songmid == targetMid) }))
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
|
keyModDown,
|
||||||
lists,
|
lists,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -103,6 +107,8 @@ export default {
|
||||||
this.isMove
|
this.isMove
|
||||||
? this.listMove({ fromId: this.fromListId, toId: this.lists[index].id, musicInfo: this.musicInfo })
|
? this.listMove({ fromId: this.fromListId, toId: this.lists[index].id, musicInfo: this.musicInfo })
|
||||||
: this.listAdd({ id: this.lists[index].id, musicInfo: this.musicInfo })
|
: this.listAdd({ id: this.lists[index].id, musicInfo: this.musicInfo })
|
||||||
|
|
||||||
|
if (this.keyModDown && !this.isMove) return
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.handleClose()
|
this.handleClose()
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 0 42 42" space="preserve">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 0 42 42" space="preserve">
|
||||||
<use xlink:href="#icon-addTo"></use>
|
<use xlink:href="#icon-addTo"></use>
|
||||||
</svg>
|
</svg>
|
||||||
<input class="key-bind" :class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('lists__new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)"/>
|
<input :class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('lists__new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)"/>
|
||||||
</base-btn>
|
</base-btn>
|
||||||
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
import { mapMutations } from 'vuex'
|
import { mapMutations } from 'vuex'
|
||||||
import { computed } from '@renderer/utils/vueTools'
|
import { computed } from '@renderer/utils/vueTools'
|
||||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||||
|
import useKeyDown from '@renderer/utils/compositions/useKeyDown'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
@ -59,6 +60,8 @@ export default {
|
||||||
},
|
},
|
||||||
emits: ['update:show', 'confirm'],
|
emits: ['update:show', 'confirm'],
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
const keyModDown = useKeyDown('mod')
|
||||||
|
|
||||||
const lists = computed(() => {
|
const lists = computed(() => {
|
||||||
return [
|
return [
|
||||||
defaultList,
|
defaultList,
|
||||||
|
@ -67,6 +70,7 @@ export default {
|
||||||
].filter(l => !props.excludeListId.includes(l.id))
|
].filter(l => !props.excludeListId.includes(l.id))
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
|
keyModDown,
|
||||||
lists,
|
lists,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -104,6 +108,8 @@ export default {
|
||||||
this.isMove
|
this.isMove
|
||||||
? this.listMoveMultiple({ fromId: this.fromListId, toId: this.lists[index].id, list: this.musicList })
|
? this.listMoveMultiple({ fromId: this.fromListId, toId: this.lists[index].id, list: this.musicList })
|
||||||
: this.listAddMultiple({ id: this.lists[index].id, list: this.musicList })
|
: this.listAddMultiple({ id: this.lists[index].id, list: this.musicList })
|
||||||
|
|
||||||
|
if (this.keyModDown && !this.isMove) return
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.handleClose()
|
this.handleClose()
|
||||||
this.$emit('confirm')
|
this.$emit('confirm')
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { isLinux } from '@common/utils'
|
||||||
import { getEnvParams, setIgnoreMouseEvents } from '@renderer/utils/tools'
|
import { getEnvParams, setIgnoreMouseEvents } from '@renderer/utils/tools'
|
||||||
|
|
||||||
import { useRefGetter } from '@renderer/utils/vueTools'
|
import { useRefGetter } from '@renderer/utils/vueTools'
|
||||||
import { sync, apiSource, proxy } from '@renderer/core/share'
|
import { sync, apiSource, proxy, isFullscreen } from '@renderer/core/share'
|
||||||
|
|
||||||
import useSync from './useSync'
|
import useSync from './useSync'
|
||||||
import useUpdate from './useUpdate'
|
import useUpdate from './useUpdate'
|
||||||
|
@ -22,6 +22,7 @@ export default () => {
|
||||||
sync.enable = setting.value.sync.enable
|
sync.enable = setting.value.sync.enable
|
||||||
apiSource.value = setting.value.apiSource
|
apiSource.value = setting.value.apiSource
|
||||||
Object.assign(proxy, setting.value.network.proxy)
|
Object.assign(proxy, setting.value.network.proxy)
|
||||||
|
isFullscreen.value = setting.value.startInFullscreen
|
||||||
|
|
||||||
const dieableIgnoreMouseEvents = () => {
|
const dieableIgnoreMouseEvents = () => {
|
||||||
if (window.dt) return
|
if (window.dt) return
|
||||||
|
@ -51,6 +52,12 @@ export default () => {
|
||||||
|
|
||||||
|
|
||||||
getEnvParams().then(envParams => {
|
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']
|
const envProxy = envParams.cmdParams['proxy-server']
|
||||||
if (envProxy && typeof envProxy == 'string') {
|
if (envProxy && typeof envProxy == 'string') {
|
||||||
const [host, port = ''] = envProxy.split(':')
|
const [host, port = ''] = envProxy.split(':')
|
||||||
|
|
|
@ -12,9 +12,10 @@ import {
|
||||||
useRefGetter,
|
useRefGetter,
|
||||||
} from '@renderer/utils/vueTools'
|
} from '@renderer/utils/vueTools'
|
||||||
|
|
||||||
const handle_key_esc_down = ({ event }) => {
|
const handle_key_down = ({ event, type, key }) => {
|
||||||
if (event.repeat) return
|
// console.log(key)
|
||||||
if (event.target.tagName != 'INPUT' || event.target.classList.contains('ignore-esc')) {
|
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) {
|
if (isFullscreen.value) {
|
||||||
event.lx_handled = true
|
event.lx_handled = true
|
||||||
rendererInvoke(NAMES.mainWindow.fullscreen, false).then(fullscreen => {
|
rendererInvoke(NAMES.mainWindow.fullscreen, false).then(fullscreen => {
|
||||||
|
@ -113,7 +114,7 @@ export default ({
|
||||||
})
|
})
|
||||||
|
|
||||||
window.eventHub.emit(eventBaseName.bindKey)
|
window.eventHub.emit(eventBaseName.bindKey)
|
||||||
window.eventHub.on('key_escape_down', handle_key_esc_down)
|
window.eventHub.on(eventBaseName.key_down, handle_key_down)
|
||||||
window.eventHub.on('key_mod+f12_down', handle_open_devtools)
|
window.eventHub.on('key_mod+f12_down', handle_open_devtools)
|
||||||
window.eventHub.on('key_f11_down', handle_fullscreen)
|
window.eventHub.on('key_f11_down', handle_fullscreen)
|
||||||
window.eventHub.on(eventBaseName.fullscreenToggle, handle_fullscreen)
|
window.eventHub.on(eventBaseName.fullscreenToggle, handle_fullscreen)
|
||||||
|
@ -128,7 +129,7 @@ export default ({
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.eventHub.off('key_escape_down', handle_key_esc_down)
|
window.eventHub.off(eventBaseName.key_down, handle_key_down)
|
||||||
window.eventHub.off('key_mod+f12_down', handle_open_devtools)
|
window.eventHub.off('key_mod+f12_down', handle_open_devtools)
|
||||||
window.eventHub.off('key_f11_down', handle_fullscreen)
|
window.eventHub.off('key_f11_down', handle_fullscreen)
|
||||||
window.eventHub.off(eventBaseName.fullscreenToggle, handle_fullscreen)
|
window.eventHub.off(eventBaseName.fullscreenToggle, handle_fullscreen)
|
||||||
|
|
|
@ -18,8 +18,7 @@ export default () => {
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const waitUpdateLists = Object.entries(getListUpdateInfo())
|
const waitUpdateLists = Object.entries(getListUpdateInfo())
|
||||||
.filter(([id, info]) => info.isAutoUpdate)
|
.map(([id, info]) => info.isAutoUpdate && userLists.find(l => l.id === id))
|
||||||
.map(([id]) => userLists.find(l => l.id === id))
|
|
||||||
.filter(_ => _)
|
.filter(_ => _)
|
||||||
for (let i = 2; i > 0; i--) {
|
for (let i = 2; i > 0; i--) {
|
||||||
handleSyncSourceList(waitUpdateLists)
|
handleSyncSourceList(waitUpdateLists)
|
||||||
|
|
|
@ -20,11 +20,14 @@ rendererInvoke(NAMES.mainWindow.get_hot_key).then(({ local, global }) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
eventHub.on(baseName.bindKey, () => {
|
eventHub.on(baseName.bindKey, () => {
|
||||||
keyBind.bindKey((key, eventKey, type, event, keys) => {
|
keyBind.bindKey((key, eventKey, type, event, keys, isEditing) => {
|
||||||
// console.log(`key_${key}_${type}`)
|
// console.log(`key_${key}_${type}`)
|
||||||
eventHub.emit(baseName.key_down, { event, keys, key, type })
|
eventHub.emit(baseName.key_down, { event, keys, key, type })
|
||||||
// console.log(event, key)
|
// console.log(event, key)
|
||||||
if (!window.isEditingHotKey && appHotKeyConfig.local.enable && appHotKeyConfig.local.keys[key]) {
|
// console.log(key, eventKey, type, event, keys)
|
||||||
|
if (window.isEditingHotKey || (isEditing && type == 'down') || event?.lx_handled) return
|
||||||
|
if (event && appHotKeyConfig.local.enable && appHotKeyConfig.local.keys[key] && (key != 'escape' || !event.target.classList.contains('ignore-esc'))) {
|
||||||
|
// console.log(key, eventKey, type, keys, isEditing)
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
if (type == 'up') return
|
if (type == 'up') return
|
||||||
|
|
||||||
|
@ -38,6 +41,7 @@ eventHub.on(baseName.bindKey, () => {
|
||||||
eventHub.emit(appHotKeyConfig.local.keys[key].action)
|
eventHub.emit(appHotKeyConfig.local.keys[key].action)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// console.log(`key_${key}_${type}`)
|
||||||
eventHub.emit(`key_${key}_${type}`, { event, keys, key, eventKey, type })
|
eventHub.emit(`key_${key}_${type}`, { event, keys, key, eventKey, type })
|
||||||
if (key != eventKey) eventHub.emit(`key_${eventKey}_${type}`, { event, keys, key, eventKey, type })
|
if (key != eventKey) eventHub.emit(`key_${eventKey}_${type}`, { event, keys, key, eventKey, type })
|
||||||
})
|
})
|
||||||
|
|
|
@ -222,8 +222,8 @@ const actions = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async getLrc({ commit, state }, musicInfo) {
|
async getLrc({ commit, state }, musicInfo) {
|
||||||
const lrcInfo = await getStoreLyric(musicInfo)
|
let lrcInfo = await getStoreLyric(musicInfo)
|
||||||
// let lrcInfo = {}
|
// lrcInfo = {}
|
||||||
// if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
|
// if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
|
||||||
if (existTimeExp.test(lrcInfo.lyric) && lrcInfo.tlyric != null) {
|
if (existTimeExp.test(lrcInfo.lyric) && lrcInfo.tlyric != null) {
|
||||||
// if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
|
// if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
|
||||||
|
@ -238,6 +238,7 @@ const actions = {
|
||||||
switch (musicInfo.source) {
|
switch (musicInfo.source) {
|
||||||
case 'kg':
|
case 'kg':
|
||||||
case 'kw':
|
case 'kw':
|
||||||
|
case 'mg':
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return buildLyricInfo(lrcInfo, musicInfo)
|
return buildLyricInfo(lrcInfo, musicInfo)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { useI18n } from '@renderer/utils/vueTools'
|
||||||
|
import { dialog } from '@renderer/plugins/Dialog'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
|
||||||
|
return (type) => {
|
||||||
|
let message
|
||||||
|
switch (type) {
|
||||||
|
case 'defautlList':
|
||||||
|
case 'playList':
|
||||||
|
message = t('list_import_tip__playlist')
|
||||||
|
break
|
||||||
|
case 'setting':
|
||||||
|
message = t('list_import_tip__setting')
|
||||||
|
break
|
||||||
|
case 'allData':
|
||||||
|
message = t('list_import_tip__alldata')
|
||||||
|
break
|
||||||
|
case 'playListPart':
|
||||||
|
message = t('list_import_tip__playlist_part')
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
message = t('list_import_tip__unknown')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog({
|
||||||
|
message,
|
||||||
|
confirmButtonText: t('ok'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { onMounted, onBeforeUnmount, ref } from '@renderer/utils/vueTools'
|
||||||
|
|
||||||
|
export default name => {
|
||||||
|
const keyDown = ref(false)
|
||||||
|
const down = `key_${name}_down`
|
||||||
|
const up = `key_${name}_up`
|
||||||
|
|
||||||
|
const handle_key_down = event => {
|
||||||
|
if (!keyDown.value) {
|
||||||
|
// console.log(event)
|
||||||
|
switch (event.event.target.tagName) {
|
||||||
|
case 'INPUT':
|
||||||
|
case 'SELECT':
|
||||||
|
case 'TEXTAREA':
|
||||||
|
return
|
||||||
|
default: if (event.event.target.isContentEditable) return
|
||||||
|
}
|
||||||
|
|
||||||
|
keyDown.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handle_key_up = () => {
|
||||||
|
if (keyDown.value) keyDown.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.eventHub.on(down, handle_key_down)
|
||||||
|
window.eventHub.on(up, handle_key_up)
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.eventHub.off(down, handle_key_down)
|
||||||
|
window.eventHub.off(up, handle_key_up)
|
||||||
|
})
|
||||||
|
|
||||||
|
return keyDown
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import { isMac } from '../../common/utils'
|
||||||
|
|
||||||
const downKeys = new Set()
|
const downKeys = new Set()
|
||||||
|
|
||||||
const handleEvent = (type, event, keys) => {
|
const handleEvent = (type, event, keys, isEditing) => {
|
||||||
let eventKey = event.key
|
let eventKey = event.key
|
||||||
if (isMac) {
|
if (isMac) {
|
||||||
let index = keys.indexOf('meta')
|
let index = keys.indexOf('meta')
|
||||||
|
@ -23,7 +23,7 @@ const handleEvent = (type, event, keys) => {
|
||||||
downKeys.delete(key)
|
downKeys.delete(key)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
handleSendEvent(key, eventKey, type, event, keys)
|
handleSendEvent(key, eventKey, type, event, keys, isEditing)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修饰键处理
|
// 修饰键处理
|
||||||
|
@ -54,7 +54,7 @@ const assertStopCallback = element => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyDown = event => {
|
const handleKeyDown = event => {
|
||||||
if (assertStopCallback(event.target)) return
|
// if (assertStopCallback(event.target)) return
|
||||||
// event.preventDefault()
|
// event.preventDefault()
|
||||||
let keys = eventModifiers(event)
|
let keys = eventModifiers(event)
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
|
@ -70,11 +70,11 @@ const handleKeyDown = event => {
|
||||||
keys.push((event.code.includes('Numpad') ? event.code.replace(/^Numpad(\w{1,3})\w*$/i, 'num$1') : event.key).toLowerCase())
|
keys.push((event.code.includes('Numpad') ? event.code.replace(/^Numpad(\w{1,3})\w*$/i, 'num$1') : event.key).toLowerCase())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
handleEvent('down', event, keys)
|
handleEvent('down', event, keys, assertStopCallback(event.target))
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyUp = event => {
|
const handleKeyUp = event => {
|
||||||
if (assertStopCallback(event.target)) return
|
// if (assertStopCallback(event.target)) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
let keys = eventModifiers(event)
|
let keys = eventModifiers(event)
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
|
@ -88,7 +88,7 @@ const handleKeyUp = event => {
|
||||||
keys.push((event.code.includes('Numpad') ? event.code.replace(/^Numpad(\w{1,3})\w*$/i, 'num$1') : event.key).toLowerCase())
|
keys.push((event.code.includes('Numpad') ? event.code.replace(/^Numpad(\w{1,3})\w*$/i, 'num$1') : event.key).toLowerCase())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
handleEvent('up', event, keys)
|
handleEvent('up', event, keys, assertStopCallback(event.target))
|
||||||
}
|
}
|
||||||
|
|
||||||
let handleSendEvent
|
let handleSendEvent
|
||||||
|
@ -107,7 +107,7 @@ const unbindKey = () => {
|
||||||
const clearDownKeys = () => {
|
const clearDownKeys = () => {
|
||||||
let keys = Array.from(downKeys)
|
let keys = Array.from(downKeys)
|
||||||
for (let i = keys.length - 1; i > -1; i--) {
|
for (let i = keys.length - 1; i > -1; i--) {
|
||||||
handleSendEvent(keys[i], 'up')
|
handleSendEvent(keys[i], keys[i], 'up', null, [keys[i]])
|
||||||
}
|
}
|
||||||
downKeys.clear()
|
downKeys.clear()
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,8 @@ export default {
|
||||||
const item = arr[i]
|
const item = arr[i]
|
||||||
if (callback(item)) {
|
if (callback(item)) {
|
||||||
delete item.sortedSinger
|
delete item.sortedSinger
|
||||||
|
delete item.lowerCaseName
|
||||||
|
delete item.lowerCaseAlbumName
|
||||||
tempResult.push(item)
|
tempResult.push(item)
|
||||||
arr.splice(i, 1)
|
arr.splice(i, 1)
|
||||||
}
|
}
|
||||||
|
@ -80,10 +82,11 @@ export default {
|
||||||
const musicName = trimStr(musicInfo.name)
|
const musicName = trimStr(musicInfo.name)
|
||||||
const lowerCaseName = String(musicName).toLowerCase()
|
const lowerCaseName = String(musicName).toLowerCase()
|
||||||
const lowerCaseAlbumName = String(musicInfo.albumName).toLowerCase()
|
const lowerCaseAlbumName = String(musicInfo.albumName).toLowerCase()
|
||||||
|
const excludeSource = ['xm']
|
||||||
for (const source of sources.sources) {
|
for (const source of sources.sources) {
|
||||||
if (!sources[source.id].musicSearch || source.id === musicInfo.source || source.id === 'xm') continue
|
if (!sources[source.id].musicSearch || source.id === musicInfo.source || excludeSource.includes(source.id)) continue
|
||||||
|
|
||||||
tasks.push(sources[source.id].musicSearch.search(`${musicName} ${musicInfo.singer || ''}`.trim(), 1, { limit: 10 }).then(res => {
|
tasks.push(sources[source.id].musicSearch.search(`${musicName} ${musicInfo.singer || ''}`.trim(), 1, { limit: 25 }).then(res => {
|
||||||
for (const item of res.list) {
|
for (const item of res.list) {
|
||||||
item.sortedSinger = String(sortSingle(item.singer)).toLowerCase()
|
item.sortedSinger = String(sortSingle(item.singer)).toLowerCase()
|
||||||
item.name = trimStr(item.name)
|
item.name = trimStr(item.name)
|
||||||
|
@ -110,18 +113,6 @@ export default {
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const item of res.list) {
|
|
||||||
item.sortedSinger = String(sortSingle(item.singer)).toLowerCase()
|
|
||||||
item.name = trimStr(item.name)
|
|
||||||
item.lowerCaseName = String(item.name).toLowerCase()
|
|
||||||
item.lowerCaseAlbumName = String(item.albumName).toLowerCase()
|
|
||||||
// console.log(lowerCaseName, item.lowerCaseName)
|
|
||||||
if (
|
|
||||||
item.sortedSinger === sortedSinger && item.interval === musicInfo.interval
|
|
||||||
) {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
return null
|
||||||
}).catch(_ => null))
|
}).catch(_ => null))
|
||||||
}
|
}
|
||||||
|
@ -135,6 +126,7 @@ export default {
|
||||||
for (const item of result) {
|
for (const item of result) {
|
||||||
delete item.sortedSinger
|
delete item.sortedSinger
|
||||||
delete item.lowerCaseName
|
delete item.lowerCaseName
|
||||||
|
delete item.lowerCaseAlbumName
|
||||||
}
|
}
|
||||||
newResult.push(...result)
|
newResult.push(...result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,8 +192,10 @@ export default {
|
||||||
let result = timeExp.exec(line)
|
let result = timeExp.exec(line)
|
||||||
if (result) {
|
if (result) {
|
||||||
const text = line.replace(timeExp, '').trim()
|
const text = line.replace(timeExp, '').trim()
|
||||||
|
let time = RegExp.$1
|
||||||
|
if (/\.\d\d$/.test(time)) time += '0'
|
||||||
lrcArr.push({
|
lrcArr.push({
|
||||||
time: RegExp.$1,
|
time,
|
||||||
text,
|
text,
|
||||||
})
|
})
|
||||||
} else if (lrcTools.rxps.tagLine.test(line)) {
|
} else if (lrcTools.rxps.tagLine.test(line)) {
|
||||||
|
|
|
@ -89,14 +89,26 @@ export const lrcTools = {
|
||||||
isOK: false,
|
isOK: false,
|
||||||
lines: [],
|
lines: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
getWordInfo(str, str2) {
|
getWordInfo(str, str2, prevWord) {
|
||||||
const offset = parseInt(str)
|
const offset = parseInt(str)
|
||||||
const offset2 = parseInt(str2)
|
const offset2 = parseInt(str2)
|
||||||
const startTime = Math.floor((offset + offset2) / (this.offset * 2))
|
let startTime = Math.abs((offset + offset2) / (this.offset * 2))
|
||||||
const timeLength = Math.floor((offset - offset2) / (this.offset2 * 2))
|
let endTime = Math.abs((offset - offset2) / (this.offset2 * 2)) + startTime
|
||||||
|
if (prevWord) {
|
||||||
|
if (startTime < prevWord.endTime) {
|
||||||
|
prevWord.endTime = startTime
|
||||||
|
if (prevWord.startTime > prevWord.endTime) {
|
||||||
|
prevWord.startTime = prevWord.endTime
|
||||||
|
}
|
||||||
|
|
||||||
|
prevWord.newTimeStr = `<${prevWord.startTime},${prevWord.endTime - prevWord.startTime}>`
|
||||||
|
// console.log(prevWord)
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
startTime,
|
startTime,
|
||||||
timeLength,
|
endTime,
|
||||||
|
timeStr: `<${startTime},${endTime - startTime}>`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
parseLine(line) {
|
parseLine(line) {
|
||||||
|
@ -111,10 +123,13 @@ export const lrcTools = {
|
||||||
const wordTimes = words.match(this.rxps.wordTimeAll)
|
const wordTimes = words.match(this.rxps.wordTimeAll)
|
||||||
if (!wordTimes) return
|
if (!wordTimes) return
|
||||||
// console.log(wordTimes)
|
// console.log(wordTimes)
|
||||||
|
let preTimeInfo
|
||||||
for (const timeStr of wordTimes) {
|
for (const timeStr of wordTimes) {
|
||||||
const result = this.rxps.wordTime.exec(timeStr)
|
const result = this.rxps.wordTime.exec(timeStr)
|
||||||
const wordInfo = this.getWordInfo(result[1], result[2])
|
const wordInfo = this.getWordInfo(result[1], result[2], preTimeInfo)
|
||||||
words = words.replace(timeStr, `<${wordInfo.startTime},${wordInfo.timeLength}>`)
|
words = words.replace(timeStr, wordInfo.timeStr)
|
||||||
|
if (preTimeInfo?.newTimeStr) words = words.replace(preTimeInfo.timeStr, preTimeInfo.newTimeStr)
|
||||||
|
preTimeInfo = wordInfo
|
||||||
}
|
}
|
||||||
this.lines.push(time + words)
|
this.lines.push(time + words)
|
||||||
return
|
return
|
||||||
|
@ -127,8 +142,8 @@ export const lrcTools = {
|
||||||
content = content.substring(0, content.indexOf(']['))
|
content = content.substring(0, content.indexOf(']['))
|
||||||
}
|
}
|
||||||
const valueOf = parseInt(content, 8)
|
const valueOf = parseInt(content, 8)
|
||||||
this.offset = Math.floor(valueOf / 10)
|
this.offset = Math.trunc(valueOf / 10)
|
||||||
this.offset2 = Math.floor(valueOf % 10)
|
this.offset2 = Math.trunc(valueOf % 10)
|
||||||
if (this.offset == 0 || Number.isNaN(this.offset) || this.offset2 == 0 || Number.isNaN(this.offset2)) {
|
if (this.offset == 0 || Number.isNaN(this.offset) || this.offset2 == 0 || Number.isNaN(this.offset2)) {
|
||||||
this.isOK = false
|
this.isOK = false
|
||||||
}
|
}
|
||||||
|
@ -147,12 +162,13 @@ export const lrcTools = {
|
||||||
tools.tags = []
|
tools.tags = []
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (!tools.isOK) return ''
|
if (!tools.isOK) throw new Error('failed')
|
||||||
tools.parseLine(line)
|
tools.parseLine(line)
|
||||||
}
|
}
|
||||||
if (!tools.lines.length) return ''
|
if (!tools.lines.length) return ''
|
||||||
let lrcs = tools.lines.join('\n')
|
let lrcs = tools.lines.join('\n')
|
||||||
if (tools.tags.length) lrcs = `${tools.tags.join('\n')}\n${lrcs}`
|
if (tools.tags.length) lrcs = `${tools.tags.join('\n')}\n${lrcs}`
|
||||||
|
// console.log(lrcs)
|
||||||
return lrcs
|
return lrcs
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,8 @@ export default {
|
||||||
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
||||||
lrc: null,
|
lrc: null,
|
||||||
lrcUrl: item.lrcUrl,
|
lrcUrl: item.lrcUrl,
|
||||||
|
mrcUrl: item.mrcUrl,
|
||||||
|
trcUrl: item.trcUrl,
|
||||||
otherSource: null,
|
otherSource: null,
|
||||||
types,
|
types,
|
||||||
_types,
|
_types,
|
||||||
|
|
|
@ -1,14 +1,112 @@
|
||||||
import { httpFetch } from '../../request'
|
import { httpFetch } from '../../request'
|
||||||
|
import musicSearch from './musicSearch'
|
||||||
|
import { decrypt } from './mrc'
|
||||||
|
|
||||||
|
const mrcTools = {
|
||||||
|
rxps: {
|
||||||
|
lineTime: /^\s*\[(\d+),\d+\]/,
|
||||||
|
wordTime: /\(\d+,\d+\)/,
|
||||||
|
wordTimeAll: /(\(\d+,\d+\))/g,
|
||||||
|
},
|
||||||
|
parseLyric(str) {
|
||||||
|
str = str.replace(/\r/g, '')
|
||||||
|
const lines = str.split('\n')
|
||||||
|
const lxlrcLines = []
|
||||||
|
const lrcLines = []
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (line.length < 6) continue
|
||||||
|
let result = this.rxps.lineTime.exec(line)
|
||||||
|
if (!result) continue
|
||||||
|
|
||||||
|
const startTime = parseInt(result[1])
|
||||||
|
let time = startTime
|
||||||
|
let ms = time % 1000
|
||||||
|
time /= 1000
|
||||||
|
let m = parseInt(time / 60).toString().padStart(2, '0')
|
||||||
|
time %= 60
|
||||||
|
let s = parseInt(time).toString().padStart(2, '0')
|
||||||
|
time = `${m}:${s}.${ms}`
|
||||||
|
|
||||||
|
let words = line.replace(this.rxps.lineTime, '')
|
||||||
|
|
||||||
|
lrcLines.push(`[${time}]${words.replace(this.rxps.wordTimeAll, '')}`)
|
||||||
|
|
||||||
|
let times = words.match(this.rxps.wordTimeAll)
|
||||||
|
if (!times) continue
|
||||||
|
times = times.map(time => {
|
||||||
|
const result = /\((\d+),(\d+)\)/.exec(time)
|
||||||
|
return `<${parseInt(result[1]) - startTime},${result[2]}>`
|
||||||
|
})
|
||||||
|
const wordArr = words.split(this.rxps.wordTime)
|
||||||
|
const newWords = times.map((time, index) => `${time}${wordArr[index]}`).join('')
|
||||||
|
lxlrcLines.push(`[${time}]${newWords}`)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
lyric: lrcLines.join('\n'),
|
||||||
|
lxlyric: lxlrcLines.join('\n'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getText(url, tryNum = 0) {
|
||||||
|
const requestObj = httpFetch(url, {
|
||||||
|
headers: {
|
||||||
|
Referer: 'https://app.c.nf.migu.cn/',
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36',
|
||||||
|
channel: '0146921',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return requestObj.promise.then(({ statusCode, body }) => {
|
||||||
|
if (statusCode == 200) return body
|
||||||
|
if (tryNum > 5 || statusCode == 404) return Promise.reject('歌词获取失败')
|
||||||
|
return this.getText(url, ++tryNum)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getMrc(url) {
|
||||||
|
return this.getText(url).then(text => {
|
||||||
|
return this.parseLyric(decrypt(text))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getLrc(url) {
|
||||||
|
return this.getText(url).then(text => ({ lxlyric: '', lyric: text }))
|
||||||
|
},
|
||||||
|
getTrc(url) {
|
||||||
|
if (!url) return Promise.resolve('')
|
||||||
|
return this.getText(url)
|
||||||
|
},
|
||||||
|
getMusicInfo(songInfo) {
|
||||||
|
return songInfo.mrcUrl == null
|
||||||
|
? musicSearch.search(`${songInfo.name} ${songInfo.singer || ''}`.trim(), 1, { limit: 25 }).then(({ list }) => {
|
||||||
|
const targetSong = list.find(s => s.songmid == songInfo.songmid)
|
||||||
|
return targetSong ? { lrcUrl: targetSong.lrcUrl, mrcUrl: targetSong.mrcUrl, trcUrl: targetSong.trcUrl } : Promise.reject('获取歌词失败')
|
||||||
|
})
|
||||||
|
: Promise.resolve({ lrcUrl: songInfo.lrcUrl, mrcUrl: songInfo.mrcUrl, trcUrl: songInfo.trcUrl })
|
||||||
|
},
|
||||||
|
getLyric(songInfo) {
|
||||||
|
return {
|
||||||
|
promise: this.getMusicInfo(songInfo).then(info => {
|
||||||
|
let p
|
||||||
|
if (info.mrcUrl) p = this.getMrc(info.mrcUrl)
|
||||||
|
else if (info.lrcUrl) p = this.getLrc(info.lrcUrl)
|
||||||
|
if (p == null) return Promise.reject('获取歌词失败')
|
||||||
|
return Promise.all([p, this.getTrc(info.trcUrl)]).then(([lrcInfo, tlyric]) => {
|
||||||
|
lrcInfo.tlyric = tlyric
|
||||||
|
return lrcInfo
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
cancelHttp() {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getLyric(songInfo, tryNum = 0) {
|
getLyricWeb(songInfo, tryNum = 0) {
|
||||||
// console.log(songInfo.copyrightId)
|
// console.log(songInfo.copyrightId)
|
||||||
if (songInfo.lrcUrl) {
|
if (songInfo.lrcUrl) {
|
||||||
let requestObj = httpFetch(songInfo.lrcUrl)
|
let requestObj = httpFetch(songInfo.lrcUrl)
|
||||||
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
|
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
|
||||||
if (statusCode !== 200) {
|
if (statusCode !== 200) {
|
||||||
if (tryNum > 5) return Promise.reject('歌词获取失败')
|
if (tryNum > 5) return Promise.reject('歌词获取失败')
|
||||||
let tryRequestObj = this.getLyric(songInfo, ++tryNum)
|
let tryRequestObj = this.getLyricWeb(songInfo, ++tryNum)
|
||||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||||
return tryRequestObj.promise
|
return tryRequestObj.promise
|
||||||
}
|
}
|
||||||
|
@ -19,15 +117,15 @@ export default {
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
} else {
|
} else {
|
||||||
let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId=${songInfo.copyrightId}`, {
|
let requestObj = httpFetch(`https://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId=${songInfo.copyrightId}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu',
|
Referer: 'https://music.migu.cn/v3/music/player/audio?from=migu',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
if (body.returnCode !== '000000' || !body.lyric) {
|
if (body.returnCode !== '000000' || !body.lyric) {
|
||||||
if (tryNum > 5) return Promise.reject(new Error('Get lyric failed'))
|
if (tryNum > 5) return Promise.reject(new Error('Get lyric failed'))
|
||||||
let tryRequestObj = this.getLyric(songInfo, ++tryNum)
|
let tryRequestObj = this.getLyricWeb(songInfo, ++tryNum)
|
||||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||||
return tryRequestObj.promise
|
return tryRequestObj.promise
|
||||||
}
|
}
|
||||||
|
@ -39,4 +137,14 @@ export default {
|
||||||
return requestObj
|
return requestObj
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getLyric(songInfo) {
|
||||||
|
let requestObj = mrcTools.getLyric(songInfo)
|
||||||
|
requestObj.promise = requestObj.promise.catch(() => {
|
||||||
|
let webRequestObj = this.getLyricWeb(songInfo)
|
||||||
|
requestObj.cancelHttp = webRequestObj.cancelHttp.bind(webRequestObj)
|
||||||
|
return webRequestObj.promise
|
||||||
|
})
|
||||||
|
return requestObj
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
// const key = 'karakal@123Qcomyidongtiantianhaoting'
|
||||||
|
const DELTA = 2654435769n
|
||||||
|
const MIN_LENGTH = 32
|
||||||
|
// const SPECIAL_CHAR = '0'
|
||||||
|
const keyArr = [
|
||||||
|
27303562373562475n,
|
||||||
|
18014862372307051n,
|
||||||
|
22799692160172081n,
|
||||||
|
34058940340699235n,
|
||||||
|
30962724186095721n,
|
||||||
|
27303523720101991n,
|
||||||
|
27303523720101998n,
|
||||||
|
31244139033526382n,
|
||||||
|
28992395054481524n,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
const teaDecrypt = (data, key) => {
|
||||||
|
const length = data.length
|
||||||
|
const lengthBitint = BigInt(length)
|
||||||
|
if (length >= 1) {
|
||||||
|
// let j = data[data.length - 1];
|
||||||
|
let j2 = data[0]
|
||||||
|
let j3 = toLong((6n + (52n / lengthBitint)) * DELTA)
|
||||||
|
while (true) {
|
||||||
|
let j4 = j3
|
||||||
|
if (j4 == 0n) break
|
||||||
|
let j5 = toLong(3n & toLong(j4 >> 2n))
|
||||||
|
let j6 = lengthBitint
|
||||||
|
while (true) {
|
||||||
|
j6--
|
||||||
|
if (j6 > 0n) {
|
||||||
|
let j7 = data[(j6 - 1n)]
|
||||||
|
let i = j6
|
||||||
|
j2 = toLong(data[i] - (toLong(toLong(j2 ^ j4) + toLong(j7 ^ key[toLong(toLong(3n & j6) ^ j5)])) ^ toLong(toLong(toLong(j7 >> 5n) ^ toLong(j2 << 2n)) + toLong(toLong(j2 >> 3n) ^ toLong(j7 << 4n)))))
|
||||||
|
data[i] = j2
|
||||||
|
} else break
|
||||||
|
}
|
||||||
|
let j8 = data[lengthBitint - 1n]
|
||||||
|
j2 = toLong(data[0n] - toLong(toLong(toLong(key[toLong(toLong(j6 & 3n) ^ j5)] ^ j8) + toLong(j2 ^ j4)) ^ toLong(toLong(toLong(j8 >> 5n) ^ toLong(j2 << 2n)) + toLong(toLong(j2 >> 3n) ^ toLong(j8 << 4n)))))
|
||||||
|
data[0] = j2
|
||||||
|
j3 = toLong(j4 - DELTA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
const longArrToString = (data) => {
|
||||||
|
const arrayList = []
|
||||||
|
for (const j of data) arrayList.push(longToBytes(j).toString('utf16le'))
|
||||||
|
return arrayList.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/29132118
|
||||||
|
const longToBytes = (l) => {
|
||||||
|
const result = Buffer.alloc(8)
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
result[i] = parseInt(l & 0xFFn)
|
||||||
|
l >>= 8n
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const toBigintArray = (data) => {
|
||||||
|
const length = Math.floor(data.length / 16)
|
||||||
|
const jArr = Array(length)
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
jArr[i] = toLong(data.substring(i * 16, (i * 16) + 16))
|
||||||
|
}
|
||||||
|
return jArr
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/lyswhut/lx-music-desktop/issues/445#issuecomment-1139338682
|
||||||
|
const MAX = 9223372036854775807n
|
||||||
|
const MIN = -9223372036854775808n
|
||||||
|
const toLong = str => {
|
||||||
|
const num = typeof str == 'string' ? BigInt('0x' + str) : str
|
||||||
|
if (num > MAX) return toLong(num - (1n << 64n))
|
||||||
|
else if (num < MIN) return toLong(num + (1n << 64n))
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
export const decrypt = (data) => {
|
||||||
|
// console.log(data.length)
|
||||||
|
// -3551594764563790630
|
||||||
|
// console.log(toLongArrayFromArr(Buffer.from(key)))
|
||||||
|
// console.log(teaDecrypt(toBigintArray(data), keyArr))
|
||||||
|
// console.log(longArrToString(teaDecrypt(toBigintArray(data), keyArr)))
|
||||||
|
// console.log(toByteArray(teaDecrypt(toBigintArray(data), keyArr)))
|
||||||
|
return (data == null || data.length < MIN_LENGTH)
|
||||||
|
? data
|
||||||
|
: longArrToString(teaDecrypt(toBigintArray(data), keyArr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(14895149309145760986n - )
|
||||||
|
// console.log(toLong('14895149309145760986'))
|
||||||
|
// console.log(decrypt(str))
|
||||||
|
// console.log(decrypt(str))
|
||||||
|
// console.log(toByteArray([6048138644744000495n]))
|
||||||
|
// console.log(toByteArray([16325999628386395n]))
|
||||||
|
// console.log(toLong(90994076459972177136n))
|
||||||
|
|
|
@ -89,7 +89,7 @@ export default {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
albumName: albumNInfo.name,
|
albumName: albumNInfo.name,
|
||||||
albumId: albumNInfo.id,
|
albumId: albumNInfo.id,
|
||||||
songmid: item.id,
|
songmid: item.copyrightId,
|
||||||
songId: item.songId,
|
songId: item.songId,
|
||||||
copyrightId: item.copyrightId,
|
copyrightId: item.copyrightId,
|
||||||
source: 'mg',
|
source: 'mg',
|
||||||
|
@ -97,6 +97,8 @@ export default {
|
||||||
img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null,
|
img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null,
|
||||||
lrc: null,
|
lrc: null,
|
||||||
lrcUrl: item.lyricUrl,
|
lrcUrl: item.lyricUrl,
|
||||||
|
mrcUrl: item.mrcurl,
|
||||||
|
trcUrl: item.trcUrl,
|
||||||
otherSource: null,
|
otherSource: null,
|
||||||
types,
|
types,
|
||||||
_types,
|
_types,
|
||||||
|
|
|
@ -212,6 +212,8 @@ export default {
|
||||||
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
||||||
lrc: null,
|
lrc: null,
|
||||||
lrcUrl: item.lrcUrl,
|
lrcUrl: item.lrcUrl,
|
||||||
|
mrcUrl: item.mrcUrl,
|
||||||
|
trcUrl: item.trcUrl,
|
||||||
otherSource: null,
|
otherSource: null,
|
||||||
types,
|
types,
|
||||||
_types,
|
_types,
|
||||||
|
|
|
@ -90,7 +90,7 @@ export default {
|
||||||
listItemHeight,
|
listItemHeight,
|
||||||
handleSelectData,
|
handleSelectData,
|
||||||
removeAllSelect,
|
removeAllSelect,
|
||||||
} = useList({ list, setting, emit })
|
} = useList({ list, setting })
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handlePlayMusic,
|
handlePlayMusic,
|
||||||
|
|
|
@ -94,7 +94,7 @@ export default ({ list, setting }) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => list, removeAllSelect)
|
watch(list, removeAllSelect)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedList,
|
selectedList,
|
||||||
|
|
|
@ -30,12 +30,12 @@
|
||||||
@contextmenu="handleListsItemRigthClick($event, index)" :aria-label="item.name" v-for="(item, index) in userLists" :key="item.id" :aria-selected="defaultList.id == listId"
|
@contextmenu="handleListsItemRigthClick($event, index)" :aria-label="item.name" v-for="(item, index) in userLists" :key="item.id" :aria-selected="defaultList.id == listId"
|
||||||
>
|
>
|
||||||
<span :class="$style.listsLabel" @click="handleListToggle(item.id, index + 2)">{{item.name}}</span>
|
<span :class="$style.listsLabel" @click="handleListToggle(item.id, index + 2)">{{item.name}}</span>
|
||||||
<input class="key-bind" :class="$style.listsInput" @contextmenu.stop type="text"
|
<input :class="$style.listsInput" @contextmenu.stop type="text"
|
||||||
@keyup.enter="handleListsSave(index, $event)" @blur="handleListsSave(index, $event)" :value="item.name" :placeholder="item.name"/>
|
@keyup.enter="handleListsSave(index, $event)" @blur="handleListsSave(index, $event)" :value="item.name" :placeholder="item.name"/>
|
||||||
</li>
|
</li>
|
||||||
<transition enter-active-class="animated-fast slideInLeft" leave-active-class="animated-fast fadeOut" @after-leave="handleListsNewAfterLeave" @after-enter="$refs.dom_listsNewInput.focus()">
|
<transition enter-active-class="animated-fast slideInLeft" leave-active-class="animated-fast fadeOut" @after-leave="handleListsNewAfterLeave" @after-enter="$refs.dom_listsNewInput.focus()">
|
||||||
<li :class="[$style.listsItem, $style.listsNew, listsData.isNewLeave ? $style.newLeave : null]" v-if="listsData.isShowNewList">
|
<li :class="[$style.listsItem, $style.listsNew, listsData.isNewLeave ? $style.newLeave : null]" v-if="listsData.isShowNewList">
|
||||||
<input class="key-bind" :class="$style.listsInput" @contextmenu.stop ref="dom_listsNewInput" type="text" @keyup.enter="handleListsCreate"
|
<input :class="$style.listsInput" @contextmenu.stop ref="dom_listsNewInput" type="text" @keyup.enter="handleListsCreate"
|
||||||
@blur="handleListsCreate" :placeholder="$t('lists__new_list_input')"/>
|
@blur="handleListsCreate" :placeholder="$t('lists__new_list_input')"/>
|
||||||
</li>
|
</li>
|
||||||
</transition>
|
</transition>
|
||||||
|
@ -60,6 +60,7 @@ import { getList } from '@renderer/core/share/utils'
|
||||||
import useDarg from '@renderer/utils/compositions/useDrag'
|
import useDarg from '@renderer/utils/compositions/useDrag'
|
||||||
import { getListUpdateInfo } from '@renderer/utils/data'
|
import { getListUpdateInfo } from '@renderer/utils/data'
|
||||||
import useSyncSourceList from '@renderer/utils/compositions/useSyncSourceList'
|
import useSyncSourceList from '@renderer/utils/compositions/useSyncSourceList'
|
||||||
|
import useImportTip from '@renderer/utils/compositions/useImportTip'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MyLists',
|
name: 'MyLists',
|
||||||
|
@ -78,6 +79,7 @@ export default {
|
||||||
const dom_lists_list = ref(null)
|
const dom_lists_list = ref(null)
|
||||||
const lists = computed(() => [defaultList, loveList, ...userLists])
|
const lists = computed(() => [defaultList, loveList, ...userLists])
|
||||||
const setUserListPosition = useCommit('list', 'setUserListPosition')
|
const setUserListPosition = useCommit('list', 'setUserListPosition')
|
||||||
|
const showImportTip = useImportTip()
|
||||||
|
|
||||||
const syncSourceList = useSyncSourceList()
|
const syncSourceList = useSyncSourceList()
|
||||||
|
|
||||||
|
@ -100,6 +102,7 @@ export default {
|
||||||
dom_lists_list,
|
dom_lists_list,
|
||||||
setDisabledSort: setDisabled,
|
setDisabledSort: setDisabled,
|
||||||
syncSourceList,
|
syncSourceList,
|
||||||
|
showImportTip,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['show-menu'],
|
emits: ['show-menu'],
|
||||||
|
@ -352,7 +355,13 @@ export default {
|
||||||
this.handleExportList(index)
|
this.handleExportList(index)
|
||||||
break
|
break
|
||||||
case 'sync':
|
case 'sync':
|
||||||
|
this.$dialog.confirm({
|
||||||
|
message: this.$t('lists__sync_confirm_tip', { name: userLists[index].name }),
|
||||||
|
confirmButtonText: this.$t('lists__remove_tip_button'),
|
||||||
|
}).then(isSync => {
|
||||||
|
if (!isSync) return
|
||||||
this.handleSyncSourceList(userLists[index])
|
this.handleSyncSourceList(userLists[index])
|
||||||
|
})
|
||||||
break
|
break
|
||||||
case 'remove':
|
case 'remove':
|
||||||
this.$dialog.confirm({
|
this.$dialog.confirm({
|
||||||
|
@ -449,7 +458,7 @@ export default {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (listData.type !== 'playListPart') return
|
if (listData.type !== 'playListPart') return this.showImportTip(listData.type)
|
||||||
const targetList = this.lists.find(l => l.id == listData.data.id)
|
const targetList = this.lists.find(l => l.id == listData.data.id)
|
||||||
if (targetList) {
|
if (targetList) {
|
||||||
const confirm = await this.$dialog.confirm({
|
const confirm = await this.$dialog.confirm({
|
||||||
|
|
|
@ -4,12 +4,16 @@ teleport(to="#view")
|
||||||
transition(enter-active-class="animated-fast zoomIn" leave-active-class="animated zoomOut" @after-leave="handleAnimated")
|
transition(enter-active-class="animated-fast zoomIn" leave-active-class="animated zoomOut" @after-leave="handleAnimated")
|
||||||
div(:class="$style.search" v-show="visible")
|
div(:class="$style.search" v-show="visible")
|
||||||
div(:class="$style.form")
|
div(:class="$style.form")
|
||||||
input.key-bind.ignore-esc(:placeholder="placeholder" v-model.trim="text" ref="dom_input"
|
input.ignore-esc(:placeholder="placeholder" v-model.trim="text" ref="dom_input"
|
||||||
@input="handleDelaySearch"
|
@input="handleDelaySearch"
|
||||||
@keyup.enter="handleTemplistClick(selectIndex)"
|
@keyup.enter="handleTemplistClick(selectIndex)"
|
||||||
@keyup.arrow-down.prevent="handleKeyDown"
|
@keyup.arrow-down.prevent="handleKeyDown"
|
||||||
@keyup.arrow-up.prevent="handleKeyUp"
|
@keyup.arrow-up.prevent="handleKeyUp"
|
||||||
@keyup.escape.prevent="handleKeyEsc"
|
@keyup.escape.prevent="handleKeyEsc"
|
||||||
|
@keydown.control.prevent="handle_key_mod_down"
|
||||||
|
@keydown.meta.prevent="handle_key_mod_down"
|
||||||
|
@keyup.control.prevent="handle_key_mod_up"
|
||||||
|
@keyup.meta.prevent="handle_key_mod_up"
|
||||||
@contextmenu="handleContextMenu")
|
@contextmenu="handleContextMenu")
|
||||||
button(type="button" @click="handleHide")
|
button(type="button" @click="handleHide")
|
||||||
slot
|
slot
|
||||||
|
@ -147,13 +151,13 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.init()
|
||||||
window.eventHub.on('key_mod_down', this.handle_key_mod_down)
|
// window.eventHub.on('key_mod_down', this.handle_key_mod_down)
|
||||||
window.eventHub.on('key_mod_up', this.handle_key_mod_up)
|
// window.eventHub.on('key_mod_up', this.handle_key_mod_up)
|
||||||
window.eventHub.on('key_mod+f_down', this.handle_key_mod_f_down)
|
window.eventHub.on('key_mod+f_down', this.handle_key_mod_f_down)
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
window.eventHub.off('key_mod_down', this.handle_key_mod_down)
|
// window.eventHub.off('key_mod_down', this.handle_key_mod_down)
|
||||||
window.eventHub.off('key_mod_up', this.handle_key_mod_up)
|
// window.eventHub.off('key_mod_up', this.handle_key_mod_up)
|
||||||
window.eventHub.off('key_mod+f_down', this.handle_key_mod_f_down)
|
window.eventHub.off('key_mod+f_down', this.handle_key_mod_f_down)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -11,7 +11,7 @@ dd
|
||||||
span.hover(:aria-label="$t('setting__click_copy')" @click="clipboardWriteText('glqw')") glqw
|
span.hover(:aria-label="$t('setting__click_copy')" @click="clipboardWriteText('glqw')") glqw
|
||||||
p.small
|
p.small
|
||||||
| 软件的常见问题可转至:
|
| 软件的常见问题可转至:
|
||||||
span.hover.underline(:aria-label="$t('setting__click_open')" @click="openUrl('https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md')") 常见问题
|
span.hover.underline(:aria-label="$t('setting__click_open')" @click="openUrl('https://lyswhut.github.io/lx-music-doc/desktop/faq')") 常见问题
|
||||||
p.small
|
p.small
|
||||||
strong 本软件没有客服
|
strong 本软件没有客服
|
||||||
| ,但我们整理了一些常见的使用问题,
|
| ,但我们整理了一些常见的使用问题,
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { getList } from '@renderer/core/share/utils'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { dialog } from '@renderer/plugins/Dialog'
|
import { dialog } from '@renderer/plugins/Dialog'
|
||||||
import iconv from 'iconv-lite'
|
import iconv from 'iconv-lite'
|
||||||
|
import useImportTip from '@renderer/utils/compositions/useImportTip'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SettingUpdate',
|
name: 'SettingUpdate',
|
||||||
|
@ -48,6 +49,7 @@ export default {
|
||||||
const settingVersion = useRefGetter('settingVersion')
|
const settingVersion = useRefGetter('settingVersion')
|
||||||
const setSettingVersion = useCommit('setSettingVersion')
|
const setSettingVersion = useCommit('setSettingVersion')
|
||||||
const setList = useCommit('list', 'setList')
|
const setList = useCommit('list', 'setList')
|
||||||
|
const showImportTip = useImportTip()
|
||||||
|
|
||||||
const handleUpdateSetting = (config) => {
|
const handleUpdateSetting = (config) => {
|
||||||
currentStting.value = JSON.parse(JSON.stringify(config))
|
currentStting.value = JSON.parse(JSON.stringify(config))
|
||||||
|
@ -66,7 +68,7 @@ export default {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (allData.type !== 'allData') return
|
if (allData.type !== 'allData') return showImportTip(allData.type)
|
||||||
|
|
||||||
// 兼容0.6.2及以前版本的列表数据
|
// 兼容0.6.2及以前版本的列表数据
|
||||||
if (allData.defaultList) return setList({ id: 'default', list: allData.defaultList.list, name: '试听列表' })
|
if (allData.defaultList) return setList({ id: 'default', list: allData.defaultList.list, name: '试听列表' })
|
||||||
|
@ -145,7 +147,7 @@ export default {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (settingData.type !== 'setting') return
|
if (settingData.type !== 'setting') return showImportTip(settingData.type)
|
||||||
const { version: settingVersion, setting } = mergeSetting(settingData.data)
|
const { version: settingVersion, setting } = mergeSetting(settingData.data)
|
||||||
setting.isAgreePact = false
|
setting.isAgreePact = false
|
||||||
refreshSetting(setting, settingVersion)
|
refreshSetting(setting, settingVersion)
|
||||||
|
@ -202,7 +204,7 @@ export default {
|
||||||
// 兼容0.6.2及以前版本的列表数据
|
// 兼容0.6.2及以前版本的列表数据
|
||||||
if (listData.type === 'defautlList') return setList({ id: 'default', list: listData.data.list, name: '试听列表' })
|
if (listData.type === 'defautlList') return setList({ id: 'default', list: listData.data.list, name: '试听列表' })
|
||||||
|
|
||||||
if (listData.type !== 'playList') return
|
if (listData.type !== 'playList') return showImportTip(listData.type)
|
||||||
|
|
||||||
for (const list of listData.data) {
|
for (const list of listData.data) {
|
||||||
setList(list)
|
setList(list)
|
||||||
|
|
|
@ -20,6 +20,8 @@ dd
|
||||||
base-checkbox(id="setting_show_animate" v-model="currentStting.isShowAnimation" :label="$t('setting__basic_show_animation')")
|
base-checkbox(id="setting_show_animate" v-model="currentStting.isShowAnimation" :label="$t('setting__basic_show_animation')")
|
||||||
.gap-top
|
.gap-top
|
||||||
base-checkbox(id="setting_animate" v-model="currentStting.randomAnimate" :label="$t('setting__basic_animation')")
|
base-checkbox(id="setting_animate" v-model="currentStting.randomAnimate" :label="$t('setting__basic_animation')")
|
||||||
|
.gap-top
|
||||||
|
base-checkbox(id="setting_start_in_fullscreen" v-model="currentStting.startInFullscreen" :label="$t('setting__basic_start_in_fullscreen')")
|
||||||
.gap-top
|
.gap-top
|
||||||
base-checkbox(id="setting_to_tray" v-model="currentStting.tray.isShow" :label="$t('setting__basic_to_tray')")
|
base-checkbox(id="setting_to_tray" v-model="currentStting.tray.isShow" :label="$t('setting__basic_to_tray')")
|
||||||
p.gap-top
|
p.gap-top
|
||||||
|
|
|
@ -13,6 +13,8 @@ dd
|
||||||
base-checkbox(id="setting_desktop_lyric_alwaysOnTopLoop" v-model="currentStting.desktopLyric.isAlwaysOnTopLoop" :label="$t('setting__desktop_lyric_always_on_top_loop')")
|
base-checkbox(id="setting_desktop_lyric_alwaysOnTopLoop" v-model="currentStting.desktopLyric.isAlwaysOnTopLoop" :label="$t('setting__desktop_lyric_always_on_top_loop')")
|
||||||
.gap-top
|
.gap-top
|
||||||
base-checkbox(id="setting_desktop_lyric_lockScreen" v-model="currentStting.desktopLyric.isLockScreen" :label="$t('setting__desktop_lyric_lock_screen')")
|
base-checkbox(id="setting_desktop_lyric_lockScreen" v-model="currentStting.desktopLyric.isLockScreen" :label="$t('setting__desktop_lyric_lock_screen')")
|
||||||
|
.gap-top(v-if="!isLinux")
|
||||||
|
base-checkbox(id="setting_desktop_lyric_hoverHide" v-model="currentStting.desktopLyric.isHoverHide" :label="$t('setting__desktop_lyric_hover_hide')")
|
||||||
dd
|
dd
|
||||||
h3#desktop_lyric_font {{$t('setting__desktop_lyric_font')}}
|
h3#desktop_lyric_font {{$t('setting__desktop_lyric_font')}}
|
||||||
div
|
div
|
||||||
|
@ -23,6 +25,7 @@ dd
|
||||||
import { ref, computed, useI18n } from '@renderer/utils/vueTools'
|
import { ref, computed, useI18n } from '@renderer/utils/vueTools'
|
||||||
import { getSystemFonts } from '@renderer/utils/tools'
|
import { getSystemFonts } from '@renderer/utils/tools'
|
||||||
import { currentStting } from '../setting'
|
import { currentStting } from '../setting'
|
||||||
|
import { isLinux } from '@common/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SettingDesktopLyric',
|
name: 'SettingDesktopLyric',
|
||||||
|
@ -39,6 +42,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
currentStting,
|
currentStting,
|
||||||
fontList,
|
fontList,
|
||||||
|
isLinux,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ dd
|
||||||
div(:class="$style.hotKeyContainer" :style="{ opacity: current_hot_key.local.enable ? 1 : .6 }")
|
div(:class="$style.hotKeyContainer" :style="{ opacity: current_hot_key.local.enable ? 1 : .6 }")
|
||||||
div(:class="$style.hotKeyItem" v-for="item in allHotKeys.local")
|
div(:class="$style.hotKeyItem" v-for="item in allHotKeys.local")
|
||||||
h4(:class="$style.hotKeyItemTitle") {{$t('setting__hot_key_' + item.name)}}
|
h4(:class="$style.hotKeyItemTitle") {{$t('setting__hot_key_' + item.name)}}
|
||||||
base-input.key-bind(:class="$style.hotKeyItemInput" readonly @keyup.prevent :placeholder="$t('setting__hot_key_unset_input')"
|
base-input(:class="$style.hotKeyItemInput" readonly @keyup.prevent :placeholder="$t('setting__hot_key_unset_input')"
|
||||||
:value="hotKeyConfig.local[item.name] && formatHotKeyName(hotKeyConfig.local[item.name].key)"
|
:value="hotKeyConfig.local[item.name] && formatHotKeyName(hotKeyConfig.local[item.name].key)"
|
||||||
@focus="handleHotKeyFocus($event, item, 'local')"
|
@focus="handleHotKeyFocus($event, item, 'local')"
|
||||||
@blur="handleHotKeyBlur($event, item, 'local')")
|
@blur="handleHotKeyBlur($event, item, 'local')")
|
||||||
|
@ -18,7 +18,7 @@ dd
|
||||||
div(:class="$style.hotKeyContainer" :style="{ opacity: current_hot_key.global.enable ? 1 : .6 }")
|
div(:class="$style.hotKeyContainer" :style="{ opacity: current_hot_key.global.enable ? 1 : .6 }")
|
||||||
div(:class="$style.hotKeyItem" v-for="item in allHotKeys.global")
|
div(:class="$style.hotKeyItem" v-for="item in allHotKeys.global")
|
||||||
h4(:class="$style.hotKeyItemTitle") {{$t('setting__hot_key_' + item.name)}}
|
h4(:class="$style.hotKeyItemTitle") {{$t('setting__hot_key_' + item.name)}}
|
||||||
base-input.key-bind(:class="[$style.hotKeyItemInput, hotKeyConfig.global[item.name] && hotKeyStatus[hotKeyConfig.global[item.name].key] && hotKeyStatus[hotKeyConfig.global[item.name].key].status === false ? $style.hotKeyFailed : null]"
|
base-input(:class="[$style.hotKeyItemInput, hotKeyConfig.global[item.name] && hotKeyStatus[hotKeyConfig.global[item.name].key] && hotKeyStatus[hotKeyConfig.global[item.name].key].status === false ? $style.hotKeyFailed : null]"
|
||||||
:value="hotKeyConfig.global[item.name] && formatHotKeyName(hotKeyConfig.global[item.name].key)" @input.prevent readonly :placeholder="$t('setting__hot_key_unset_input')"
|
:value="hotKeyConfig.global[item.name] && formatHotKeyName(hotKeyConfig.global[item.name].key)" @input.prevent readonly :placeholder="$t('setting__hot_key_unset_input')"
|
||||||
@focus="handleHotKeyFocus($event, item, 'global')"
|
@focus="handleHotKeyFocus($event, item, 'global')"
|
||||||
@blur="handleHotKeyBlur($event, item, 'global')")
|
@blur="handleHotKeyBlur($event, item, 'global')")
|
||||||
|
@ -102,13 +102,14 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleHotKeyBlur = async(event, info, type) => {
|
const handleHotKeyBlur = (event, info, type) => {
|
||||||
|
setTimeout(async() => {
|
||||||
await hotKeySetEnable(true)
|
await hotKeySetEnable(true)
|
||||||
window.isEditingHotKey = false
|
window.isEditingHotKey = false
|
||||||
isEditHotKey = false
|
isEditHotKey = false
|
||||||
const prevInput = hotKeyTargetInput
|
const prevInput = hotKeyTargetInput
|
||||||
hotKeyTargetInput = null
|
hotKeyTargetInput = null
|
||||||
if (prevInput.value == t('setting__hot_key_tip_input')) {
|
if (prevInput?.value == t('setting__hot_key_tip_input')) {
|
||||||
prevInput.value = newHotKey ? formatHotKeyName(newHotKey) : ''
|
prevInput.value = newHotKey ? formatHotKeyName(newHotKey) : ''
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -161,6 +162,7 @@ export default {
|
||||||
}
|
}
|
||||||
await handleHotKeySaveConfig()
|
await handleHotKeySaveConfig()
|
||||||
await getHotKeyStatus()
|
await getHotKeyStatus()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyDown = ({ event, keys, key, type }) => {
|
const handleKeyDown = ({ event, keys, key, type }) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
dt#sync
|
dt#sync
|
||||||
| {{$t('setting__sync')}}
|
| {{$t('setting__sync')}}
|
||||||
button(class="help-btn" @click="openUrl('https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md#%E5%90%8C%E6%AD%A5%E5%8A%9F%E8%83%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E5%AE%9E%E9%AA%8C%E6%80%A7%E9%A6%96%E6%AC%A1%E4%BD%BF%E7%94%A8%E5%89%8D%E5%BB%BA%E8%AE%AE%E5%85%88%E5%A4%87%E4%BB%BD%E4%B8%80%E6%AC%A1%E5%88%97%E8%A1%A8')" :aria-label="$t('setting__sync_tip')")
|
button(class="help-btn" @click="openUrl('https://lyswhut.github.io/lx-music-doc/desktop/faq/sync')" :aria-label="$t('setting__sync_tip')")
|
||||||
svg-icon(name="help-circle-outline")
|
svg-icon(name="help-circle-outline")
|
||||||
dd
|
dd
|
||||||
base-checkbox(id="setting_sync_enable" v-model="currentStting.sync.enable" :label="syncEnableTitle")
|
base-checkbox(id="setting_sync_enable" v-model="currentStting.sync.enable" :label="syncEnableTitle")
|
||||||
|
|
|
@ -3,7 +3,7 @@ dt#update {{$t('setting__update')}}
|
||||||
dd
|
dd
|
||||||
p.small
|
p.small
|
||||||
| {{$t('setting__update_latest_label')}}{{versionInfo.newVersion ? versionInfo.newVersion.version : $t('setting__update_unknown')}}
|
| {{$t('setting__update_latest_label')}}{{versionInfo.newVersion ? versionInfo.newVersion.version : $t('setting__update_unknown')}}
|
||||||
p.small {{$t('setting__update_current_label')}}{{versionInfo.version}}
|
p.small(@click="handleOPenDevTools") {{$t('setting__update_current_label')}}{{versionInfo.version}}
|
||||||
p.small(v-if="versionInfo.downloadProgress" style="line-height: 1.5;")
|
p.small(v-if="versionInfo.downloadProgress" style="line-height: 1.5;")
|
||||||
| {{$t('setting__update_downloading')}}
|
| {{$t('setting__update_downloading')}}
|
||||||
br
|
br
|
||||||
|
@ -20,12 +20,30 @@ import { versionInfo } from '@renderer/core/share'
|
||||||
import { sizeFormate } from '@renderer/utils/tools'
|
import { sizeFormate } from '@renderer/utils/tools'
|
||||||
// import { openDirInExplorer, selectDir } from '@renderer/utils'
|
// import { openDirInExplorer, selectDir } from '@renderer/utils'
|
||||||
import { currentStting } from '../setting'
|
import { currentStting } from '../setting'
|
||||||
|
import { rendererSend, NAMES } from '@common/ipc'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SettingUpdate',
|
name: 'SettingUpdate',
|
||||||
setup() {
|
setup() {
|
||||||
|
let lastClickTime = 0
|
||||||
|
let clickNum = 0
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const handleOPenDevTools = () => {
|
||||||
|
if (window.performance.now() - lastClickTime > 1000) {
|
||||||
|
if (clickNum > 0) clickNum = 0
|
||||||
|
} else {
|
||||||
|
if (clickNum > 6) {
|
||||||
|
rendererSend(NAMES.mainWindow.open_dev_tools)
|
||||||
|
clickNum = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clickNum++
|
||||||
|
lastClickTime = window.performance.now()
|
||||||
|
}
|
||||||
|
|
||||||
const downloadProgress = computed(() => {
|
const downloadProgress = computed(() => {
|
||||||
return versionInfo.downloadProgress
|
return versionInfo.downloadProgress
|
||||||
? `${versionInfo.downloadProgress.percent.toFixed(2)}% - ${sizeFormate(versionInfo.downloadProgress.transferred)}/${sizeFormate(versionInfo.downloadProgress.total)} - ${sizeFormate(versionInfo.downloadProgress.bytesPerSecond)}/s`
|
? `${versionInfo.downloadProgress.percent.toFixed(2)}% - ${sizeFormate(versionInfo.downloadProgress.transferred)}/${sizeFormate(versionInfo.downloadProgress.total)} - ${sizeFormate(versionInfo.downloadProgress.bytesPerSecond)}/s`
|
||||||
|
@ -40,6 +58,7 @@ export default {
|
||||||
currentStting,
|
currentStting,
|
||||||
versionInfo,
|
versionInfo,
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
|
handleOPenDevTools,
|
||||||
showUpdateModal,
|
showUpdateModal,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,7 +17,7 @@ material-modal(:show="modelValue" bg-close @close="handleClose" teleport="#view"
|
||||||
div(:class="$style.note")
|
div(:class="$style.note")
|
||||||
p(:class="[$style.ruleLink]")
|
p(:class="[$style.ruleLink]")
|
||||||
| {{$t('user_api__readme')}}
|
| {{$t('user_api__readme')}}
|
||||||
span.hover.underline(@click="handleOpenUrl('https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%BA%90%E8%84%9A%E6%9C%AC%E7%BC%96%E5%86%99%E8%AF%B4%E6%98%8E')" aria-label="https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md") FAQ.md
|
span.hover.underline(@click="handleOpenUrl('https://lxmusic.toside.cn/desktop/custom-source')" aria-label="https://lxmusic.toside.cn/desktop/custom-source") FAQ
|
||||||
p {{$t('user_api__note')}}
|
p {{$t('user_api__note')}}
|
||||||
div(:class="$style.footer")
|
div(:class="$style.footer")
|
||||||
base-btn(:class="$style.footerBtn" @click="handleImport") {{$t('user_api__btn_import')}}
|
base-btn(:class="$style.footerBtn" @click="handleImport") {{$t('user_api__btn_import')}}
|
||||||
|
|
|
@ -36,6 +36,7 @@ export const currentStting = ref({
|
||||||
theme: '',
|
theme: '',
|
||||||
isLockScreen: true,
|
isLockScreen: true,
|
||||||
isDelayScroll: true,
|
isDelayScroll: true,
|
||||||
|
isHoverHide: false,
|
||||||
style: {
|
style: {
|
||||||
font: '',
|
font: '',
|
||||||
fontSize: 125,
|
fontSize: 125,
|
||||||
|
@ -87,6 +88,7 @@ export const currentStting = ref({
|
||||||
port: '23332',
|
port: '23332',
|
||||||
},
|
},
|
||||||
windowSizeId: 1,
|
windowSizeId: 1,
|
||||||
|
startInFullscreen: false,
|
||||||
langId: 'cns',
|
langId: 'cns',
|
||||||
theme: {
|
theme: {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
|
Loading…
Reference in New Issue