Merge branch 'dev'

This commit is contained in:
lyswhut 2020-11-21 19:01:16 +08:00
commit a3493a6c74
32 changed files with 415 additions and 241 deletions

View File

@ -6,6 +6,24 @@ Project versioning adheres to [Semantic Versioning](http://semver.org/).
Commit convention is based on [Conventional Commits](http://conventionalcommits.org).
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
## [1.4.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.3.0...v1.4.0) - 2020-11-21
### 新增
- 托盘菜单新增显示、隐藏主界面选项为Linux、MAC版添加托盘菜单
- 新增播放进度信息保存
### 优化
- 移除kg源的歌词文件开头的空白字符串
### 修复
- 修复专辑图片无法嵌入的问题
- 修复播放状态栏切换“上一首”歌曲按钮提示错误的问题
- 修复移动单首歌曲时,如果目标列表存在该歌曲,会导致将源列表与目标列表里的目标歌曲移除
- 修复kg源歌曲信息带有单引号等特殊字符被转义的问题
## [1.3.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.2.2...v1.3.0) - 2020-11-01
### 新增

94
FAQ.md
View File

@ -2,7 +2,7 @@
在阅读本常见问题后仍然无法解决你的问题请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题!
## 软件为什么没有桌面歌词与自定义列表功能
## ~~软件为什么没有桌面歌词与自定义列表功能~~
洛雪音乐的最初定位不是作为播放器开发的,它主要用于**查找歌曲**,软件的播放功能仅用于试听,不建议用作为常用播放器使用。
@ -33,10 +33,56 @@
用`Shift`或`Ctrl`选择时,鼠标点击未选中的内容会将其选中,点击已选择的内容会将其取消选择,若想全部取消选择,在不按`Shift`或`Alt`键的情况下,随意点击列表里的一项内容即可全部取消选择。(P.S`Ctrl`键对应Mac OS上的`Command`键)
注:选完后可用鼠标右击弹出右键菜单操作已选的内容
## 播放整个歌单或排行榜
播放在线列表内的歌曲需要将它们都添加到我的列表才能播放,你可以全选列表内的歌曲然后添加到现有列表或者新创建的列表,然后去播放该列表内的歌曲。
## Windows 7 下界面异常(界面显示不完整)
由于软件默认使用了透明窗口根据Electron官方文档的[说明](https://electronjs.org/docs/api/frameless-window#%E5%B1%80%E9%99%90%E6%80%A7)
> 在 windows 操作系统上, 当 DWM 被禁用时, 透明窗口将无法工作。
因此,当 win7 没有使用**AERO**主题时界面将会显示异常开启AERO的方法请自行百度`win7开启aero效果`(开启后可看到任务栏变透明)。<br>
从`0.14.0`版本起不再强制要求开启透明效果,若你实在不想开启(若非电脑配置太低,墙裂建议开启!),可通过添加运行参数`-nt`来运行程序即可,例如:`.\lx-music-desktop.exe -nt`,添加方法可自行百度“给快捷方式加参数”,该参数的作用是用来控制程序是否使用非透明窗口运行。
对于一些完全无法正常显示界面、开启了AERO后问题仍未解决的情况请阅读下面的 **软件启动后,界面无法显示** 解决
## 软件启动后,界面无法显示
对于软件启动后,可以在任务栏看到软件,但软件界面在桌面上无任何显示,或者整个界面偶尔闪烁的情况。<br>
原始问题看:<https://github.com/electron/electron/issues/19569#issuecomment-522231083><br>
解决办法:下载`.NET Framework 4.7.1`或**更高**版本安装即可(建议安装最新版,若安装过程中遇到问题可尝试自行百度解决)。<br>
微软官方下载地址:<https://dotnet.microsoft.com/download/dotnet-framework><br>
下载`Runtime(运行时)`版即可,安装完成后可能需要重启才生效。
若还是不行可尝试以下操作:
- 更新显卡驱动
- 尝试将绿色版的软件放在**桌面**或**我的文档**运行
## 安装版安装失败,提示安装程序并未成功地运行完成
对于部分电脑出现安装失败的问题,可以做出以下尝试:
- 若你之前可以安装成功,但现在安装失败,就去**控制面板-程序和功能**或用第三方卸载工具看下有没有之前的版本残留,若同时在不同路径下安装了多个版本就可能会出现该问题,这种情况卸载掉所有版本重新安装即可
- 清理安装路径下的残留文件
- 清理注册表(建议用清理工具清理)
## 无法打开外部歌单
不支持垮源打开歌单,请**确认**你需要打开的歌单平台是否与软件标签所写的**歌单源**对应(不一样的话请通过右上角切换歌单源);<br>
对于分享出来的歌单若打开失败可尝试先在浏览器中打开后再从浏览器地址栏复制URL地址到软件打开<br>
或者如果你知道歌单 id 也可以直接输入歌单 id 打开。<br>
## 软件无法联网
软件的排行榜、歌单、搜索列表**都**无法加载:
- 检查是否在设置界面开启了代理(当代理乱设置时软件将无法联网)
- 检查软件是否被第三方软件/防火墙阻止联网
## 桌面歌词显示异常
### Windows 7 系统桌面歌词显示异常
@ -79,37 +125,6 @@ Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看下面的
注意:**绿色版**的软件自动更新功能**不可用**,建议使用安装版!!<br>
注意:**Mac版**、**Linux deb**版不支持自动更新!
## Windows 7 下界面异常(界面显示不完整)
由于软件默认使用了透明窗口根据Electron官方文档的[说明](https://electronjs.org/docs/api/frameless-window#%E5%B1%80%E9%99%90%E6%80%A7)
> 在 windows 操作系统上, 当 DWM 被禁用时, 透明窗口将无法工作。
因此,当 win7 没有使用**AERO**主题时界面将会显示异常开启AERO的方法请自行百度`win7开启aero效果`(开启后可看到任务栏变透明)。<br>
从`0.14.0`版本起不再强制要求开启透明效果,若你实在不想开启(若非电脑配置太低,墙裂建议开启!),可通过添加运行参数`-nt`来运行程序即可,例如:`.\lx-music-desktop.exe -nt`,添加方法可自行百度“给快捷方式加参数”,该参数的作用是用来控制程序是否使用非透明窗口运行。
对于一些完全无法正常显示界面、开启了AERO后问题仍未解决的情况请阅读下面的 **软件启动后,界面无法显示** 解决
## 软件启动后,界面无法显示
对于软件启动后,可以在任务栏看到软件,但软件界面在桌面上无任何显示,或者整个界面偶尔闪烁的情况。<br>
原始问题看:<https://github.com/electron/electron/issues/19569#issuecomment-522231083><br>
解决办法:下载`.NET Framework 4.7.1`或**更高**版本安装即可(建议安装最新版,若安装过程中遇到问题可尝试自行百度解决)。<br>
微软官方下载地址:<https://dotnet.microsoft.com/download/dotnet-framework><br>
下载`Runtime(运行时)`版即可,安装完成后可能需要重启才生效。
若还是不行可尝试以下操作:
- 更新显卡驱动
- 尝试将绿色版的软件放在**桌面**或**我的文档**运行
## 安装版安装失败,提示安装程序并未成功地运行完成
对于部分电脑出现安装失败的问题,可以做出以下尝试:
- 若你之前可以安装成功,但现在安装失败,就去**控制面板-程序和功能**或用第三方卸载工具看下有没有之前的版本残留,若同时在不同路径下安装了多个版本就可能会出现该问题,这种情况卸载掉所有版本重新安装即可
- 清理安装路径下的残留文件
- 清理注册表(建议用清理工具清理)
## 缺少`xxx.dll`
这个是电脑缺少某些dll导致的正常的系统是没有这个问题的可以尝试如下几个解决办法
@ -123,19 +138,6 @@ Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看下面的
尽管如此但这不意味着软件是100%安全的,由于软件使用了第三方依赖,当这些依赖存在恶意行为时([供应链攻击](https://docs.microsoft.com/zh-cn/windows/security/threat-protection/intelligence/supply-chain-malware)),软件也将会受到牵连,所以我只能尽量选择使用较多人用、信任度较高的依赖。<br>
当然,以上说明建立的前提是在你所用的安装包是从**本项目主页上写的链接**下载的,或者有相关能力者还可以下载源代码自己构建安装包。
从`0.17.0`起,由于加入了音频输出设备切换功能,该功能调用了 [MediaDevices.enumerateDevices()](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices),可能导致安全软件提示洛雪要访问摄像头(目前发现卡巴斯基会提示),但实际上没有用到摄像头,并且摄像头的提示灯也不会亮,你可以选择阻止访问。
从`v0.17.0`起,由于加入了音频输出设备切换功能,该功能调用了 [MediaDevices.enumerateDevices()](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices),可能导致安全软件提示洛雪要访问摄像头(目前发现卡巴斯基会提示),但实际上没有用到摄像头,并且摄像头的提示灯也不会亮,你可以选择阻止访问。
最后,若出现杀毒软件报毒、存在恶意行为,请自行判断选择是否继续使用本软件!
## 软件无法联网
软件的排行榜、歌单、搜索列表**都**无法加载:
- 检查是否在设置界面开启了代理(当代理乱设置时软件将无法联网)
- 检查软件是否被第三方软件/防火墙阻止联网
## 无法打开外部歌单
不支持垮源打开歌单,请确认你需要打开的歌单平台是否与软件标签所写的歌单源对应;<br>
对于分享出来的歌单若打开失败可尝试先在浏览器中打开后再从浏览器地址栏复制URL地址到软件打开<br>
或者如果你知道歌单 id 也可以直接输入歌单 id 打开。<br>

View File

@ -36,7 +36,7 @@
所用技术栈:
- Electron 10
- Electron 9
- Vue 2
已支持的平台:

206
package-lock.json generated
View File

@ -3966,22 +3966,38 @@
}
},
"babel-loader": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
"integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==",
"version": "8.2.1",
"resolved": "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.2.1.tgz?cache=0&sync_timestamp=1605043148864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-loader%2Fdownload%2Fbabel-loader-8.2.1.tgz",
"integrity": "sha1-5TMTJUZ36G8nU29QcdgH4B0k7AA=",
"dev": true,
"requires": {
"find-cache-dir": "^2.1.0",
"loader-utils": "^1.4.0",
"mkdirp": "^0.5.3",
"make-dir": "^2.1.0",
"pify": "^4.0.1",
"schema-utils": "^2.6.5"
},
"dependencies": {
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz",
"integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=",
"dev": true,
"requires": {
"pify": "^4.0.1",
"semver": "^5.6.0"
}
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz",
"integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=",
"dev": true
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz",
"integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=",
"dev": true
}
}
@ -4703,9 +4719,9 @@
"dev": true
},
"boolean": {
"version": "3.0.1",
"resolved": "https://registry.npm.taobao.org/boolean/download/boolean-3.0.1.tgz",
"integrity": "sha1-NezytKLuGRsLRJhvFOtfBSpcu08=",
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/boolean/download/boolean-3.0.2.tgz",
"integrity": "sha1-3xuqGLaisOcIQEdeHZPsj+dbJXA=",
"dev": true,
"optional": true
},
@ -5950,9 +5966,9 @@
"dev": true
},
"copy-webpack-plugin": {
"version": "6.2.1",
"resolved": "https://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-6.2.1.tgz",
"integrity": "sha1-gBXk1cXmN6t7Ocdtqp4Dx6S/GuU=",
"version": "6.3.1",
"resolved": "https://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-6.3.1.tgz",
"integrity": "sha1-zrbpw+SRDmOndP1KJ0URVndfbio=",
"dev": true,
"requires": {
"cacache": "^15.0.5",
@ -5970,7 +5986,7 @@
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1602353715225&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1604996837320&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
"integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=",
"dev": true,
"requires": {
@ -5982,7 +5998,7 @@
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1595908717940&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1604565113393&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
"integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=",
"dev": true
},
@ -6087,7 +6103,7 @@
},
"pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz",
"resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-4.2.0.tgz",
"integrity": "sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM=",
"dev": true,
"requires": {
@ -6117,9 +6133,9 @@
}
},
"core-js": {
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
"version": "3.7.0",
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.7.0.tgz?cache=0&sync_timestamp=1604675498528&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-3.7.0.tgz",
"integrity": "sha1-sKdhoCSIV3r7+XF55Ggb9JVoUg8=",
"dev": true
},
"core-js-compat": {
@ -7081,9 +7097,9 @@
}
},
"electron": {
"version": "9.3.3",
"resolved": "https://registry.npm.taobao.org/electron/download/electron-9.3.3.tgz",
"integrity": "sha1-maZhnV32j5dpel0dgu86imP83zY=",
"version": "9.3.4",
"resolved": "https://registry.npm.taobao.org/electron/download/electron-9.3.4.tgz?cache=0&sync_timestamp=1604968518869&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron%2Fdownload%2Felectron-9.3.4.tgz",
"integrity": "sha1-1i3Z+KvJPACYeHFN6eYNsDA2GgU=",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@ -7092,9 +7108,9 @@
},
"dependencies": {
"@types/node": {
"version": "12.19.2",
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-12.19.2.tgz",
"integrity": "sha1-lWXtXHK6lgOPw63WQ+3V54IFmOc=",
"version": "12.19.4",
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-12.19.4.tgz?cache=0&sync_timestamp=1604951079891&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-12.19.4.tgz",
"integrity": "sha1-zfu2LibHQ17ZqrnJQTk8w1mOm0Y=",
"dev": true
}
}
@ -7205,9 +7221,9 @@
}
},
"electron-log": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.2.4.tgz",
"integrity": "sha512-CXbDU+Iwi+TjKzugKZmTRIORIPe3uQRqgChUl19fkW/reFUn5WP7dt+cNGT3bkLV8xfPilpkPFv33HgtmLLewQ=="
"version": "4.3.0",
"resolved": "https://registry.npm.taobao.org/electron-log/download/electron-log-4.3.0.tgz?cache=0&sync_timestamp=1604284727663&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-log%2Fdownload%2Felectron-log-4.3.0.tgz",
"integrity": "sha1-boQaXJrzTtPKg+WopBVv3Dm+1GQ="
},
"electron-publish": {
"version": "22.9.1",
@ -7521,9 +7537,9 @@
"dev": true
},
"eslint": {
"version": "7.12.1",
"resolved": "https://registry.npm.taobao.org/eslint/download/eslint-7.12.1.tgz?cache=0&sync_timestamp=1603768145986&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint%2Fdownload%2Feslint-7.12.1.tgz",
"integrity": "sha1-vZqB+memz9UWVs24iBLOSczsWAE=",
"version": "7.13.0",
"resolved": "https://registry.npm.taobao.org/eslint/download/eslint-7.13.0.tgz",
"integrity": "sha1-fxgBJsDc3vMnv7VLIR14At7MCNo=",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@ -7632,8 +7648,8 @@
},
"eslint-config-standard": {
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz",
"integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==",
"resolved": "https://registry.npm.taobao.org/eslint-config-standard/download/eslint-config-standard-14.1.1.tgz?cache=0&sync_timestamp=1604090914442&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-config-standard%2Fdownload%2Feslint-config-standard-14.1.1.tgz",
"integrity": "sha1-gwqOROeu995nRkl5rQa0BgJsVuo=",
"dev": true
},
"eslint-formatter-friendly": {
@ -7900,18 +7916,18 @@
}
},
"eslint-plugin-html": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.1.0.tgz",
"integrity": "sha512-xcqithhnjUxoEDRL0hYci4RSS8EZ1NGr3/H8x3BxJvxgbu4R3YaEUea9i93j95NuAgoAbOUfNmybta8fqi4UbA==",
"version": "6.1.1",
"resolved": "https://registry.npm.taobao.org/eslint-plugin-html/download/eslint-plugin-html-6.1.1.tgz?cache=0&sync_timestamp=1605104716026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-html%2Fdownload%2Feslint-plugin-html-6.1.1.tgz",
"integrity": "sha1-la7hUZALm7LaX6AXtFzGRFagp04=",
"dev": true,
"requires": {
"htmlparser2": "^4.1.0"
"htmlparser2": "^5.0.1"
},
"dependencies": {
"dom-serializer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.0.1.tgz",
"integrity": "sha512-1Aj1Qy3YLbdslkI75QEOfdp9TkQ3o8LRISAzxOibjBs/xWwr1WxZFOQphFkZuepHFGo+kB8e5FVJSS0faAJ4Rw==",
"version": "1.1.0",
"resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-1.1.0.tgz",
"integrity": "sha1-X3yCjxv8RIh9wqMVq1xFaR1US1g=",
"dev": true,
"requires": {
"domelementtype": "^2.0.1",
@ -7920,46 +7936,46 @@
}
},
"domelementtype": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
"version": "2.0.2",
"resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-2.0.2.tgz?cache=0&sync_timestamp=1600028495728&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-2.0.2.tgz",
"integrity": "sha1-87blSSAeRvWItZRj3XcYcTH+aXE=",
"dev": true
},
"domhandler": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz",
"integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==",
"version": "3.3.0",
"resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-3.3.0.tgz",
"integrity": "sha1-bbfqRuRhfrFc+HXfaLK4UkzgA3o=",
"dev": true,
"requires": {
"domelementtype": "^2.0.1"
}
},
"domutils": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.2.0.tgz",
"integrity": "sha512-0haAxVr1PR0SqYwCH7mxMpHZUwjih9oPPedqpR/KufsnxPyZ9dyVw1R5093qnJF3WXSbjBkdzRWLw/knJV/fAg==",
"version": "2.4.2",
"resolved": "https://registry.npm.taobao.org/domutils/download/domutils-2.4.2.tgz",
"integrity": "sha1-fuW+JhlE4a1IfZqgYWcgAQEjkis=",
"dev": true,
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0"
"domhandler": "^3.3.0"
}
},
"entities": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/entities/download/entities-2.1.0.tgz?cache=0&sync_timestamp=1602897029273&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-2.1.0.tgz",
"integrity": "sha1-mS0xKc999ocLlsV4WMJJoSD4uLU=",
"dev": true
},
"htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"version": "5.0.1",
"resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-5.0.1.tgz?cache=0&sync_timestamp=1603668161350&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-5.0.1.tgz",
"integrity": "sha1-fapvw+NdYQeslaT8CHgfCRZk9uc=",
"dev": true,
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"domhandler": "^3.3.0",
"domutils": "^2.4.2",
"entities": "^2.0.0"
}
}
@ -8060,9 +8076,9 @@
"dev": true
},
"eslint-plugin-standard": {
"version": "4.0.2",
"resolved": "https://registry.npm.taobao.org/eslint-plugin-standard/download/eslint-plugin-standard-4.0.2.tgz?cache=0&sync_timestamp=1603323739415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-standard%2Fdownload%2Feslint-plugin-standard-4.0.2.tgz",
"integrity": "sha1-AhIRqfB35jpoR+e7mrQkcyesjgw=",
"version": "4.1.0",
"resolved": "https://registry.npm.taobao.org/eslint-plugin-standard/download/eslint-plugin-standard-4.1.0.tgz?cache=0&sync_timestamp=1604979354814&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-standard%2Fdownload%2Feslint-plugin-standard-4.1.0.tgz",
"integrity": "sha1-DDvzpn6FP4u7xYD7SUX78W9Bt8U=",
"dev": true
},
"eslint-scope": {
@ -11170,9 +11186,9 @@
}
},
"less-loader": {
"version": "7.0.2",
"resolved": "https://registry.npm.taobao.org/less-loader/download/less-loader-7.0.2.tgz?cache=0&sync_timestamp=1602250118610&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fless-loader%2Fdownload%2Fless-loader-7.0.2.tgz",
"integrity": "sha1-DXOknsMqnT/xJhRZjm4rR/sqNcQ=",
"version": "7.1.0",
"resolved": "https://registry.npm.taobao.org/less-loader/download/less-loader-7.1.0.tgz",
"integrity": "sha1-lY1B6G194Ly0kHEe4PI1qp3Flqo=",
"dev": true,
"requires": {
"klona": "^2.0.4",
@ -11182,7 +11198,7 @@
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1602353715225&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1604996837320&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
"integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=",
"dev": true,
"requires": {
@ -11194,7 +11210,7 @@
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1595908717940&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1604565113393&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
"integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=",
"dev": true
},
@ -11428,18 +11444,24 @@
}
},
"markdown-it": {
"version": "11.0.1",
"resolved": "https://registry.npm.taobao.org/markdown-it/download/markdown-it-11.0.1.tgz?cache=0&sync_timestamp=1600069708850&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmarkdown-it%2Fdownload%2Fmarkdown-it-11.0.1.tgz",
"integrity": "sha1-tU8V7Cohk++mbdoetBc7rqCJk9Y=",
"version": "12.0.2",
"resolved": "https://registry.npm.taobao.org/markdown-it/download/markdown-it-12.0.2.tgz?cache=0&sync_timestamp=1603472606302&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmarkdown-it%2Fdownload%2Fmarkdown-it-12.0.2.tgz",
"integrity": "sha1-RAG+ro34qiIh/GVlpxiOYKBu8O0=",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"argparse": "^2.0.1",
"entities": "~2.0.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/argparse/download/argparse-2.0.1.tgz",
"integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=",
"dev": true
},
"entities": {
"version": "2.0.3",
"resolved": "https://registry.npm.taobao.org/entities/download/entities-2.0.3.tgz",
@ -11945,11 +11967,21 @@
"dev": true
},
"node-id3": {
"version": "0.2.1",
"resolved": "https://registry.npm.taobao.org/node-id3/download/node-id3-0.2.1.tgz",
"integrity": "sha1-QYNSONdoe4dbCMzguxYMXOoLurw=",
"version": "0.1.21",
"resolved": "https://registry.npm.taobao.org/node-id3/download/node-id3-0.1.21.tgz",
"integrity": "sha1-bp+8x68J9lEUkJoR90otcLVFu/M=",
"requires": {
"iconv-lite": "0.6.2"
"iconv-lite": "0.5.1"
},
"dependencies": {
"iconv-lite": {
"version": "0.5.1",
"resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.5.1.tgz?cache=0&sync_timestamp=1594184250387&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.5.1.tgz",
"integrity": "sha1-skJdPHsY9yGfLKZj0QO925FxjWQ=",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
}
}
},
"node-libs-browser": {
@ -15530,9 +15562,9 @@
}
},
"stylus-loader": {
"version": "4.2.0",
"resolved": "https://registry.npm.taobao.org/stylus-loader/download/stylus-loader-4.2.0.tgz?cache=0&sync_timestamp=1603977404318&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstylus-loader%2Fdownload%2Fstylus-loader-4.2.0.tgz",
"integrity": "sha1-7EzzQIpS0H5tPBX/4aDlwkhLrMc=",
"version": "4.3.0",
"resolved": "https://registry.npm.taobao.org/stylus-loader/download/stylus-loader-4.3.0.tgz",
"integrity": "sha1-1Lq1pNlX9LH1Z74QgYX/I74hatQ=",
"dev": true,
"requires": {
"fast-glob": "^3.2.4",
@ -15544,7 +15576,7 @@
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1603561547443&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1604996837320&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
"integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=",
"dev": true,
"requires": {
@ -15556,7 +15588,7 @@
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1603566069729&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
"resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1604565113393&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
"integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=",
"dev": true
},
@ -16716,9 +16748,9 @@
"integrity": "sha1-ud0Jihfh9a25G9+WEfA4UxDafLE="
},
"vue-loader": {
"version": "15.9.4",
"resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-15.9.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-15.9.4.tgz",
"integrity": "sha1-wuzvihoIAqx2xtaGZBtd3lIq4mc=",
"version": "15.9.5",
"resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-15.9.5.tgz?cache=0&sync_timestamp=1604764636407&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-15.9.5.tgz",
"integrity": "sha1-epYNxCCjQ53qrN2gOP3Nv3xDJwY=",
"dev": true,
"requires": {
"@vue/component-compiler-utils": "^3.1.0",
@ -16729,9 +16761,9 @@
}
},
"vue-router": {
"version": "3.4.8",
"resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.4.8.tgz?cache=0&sync_timestamp=1603710629657&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.4.8.tgz",
"integrity": "sha1-LAYmHTXYB1iTRwNS1C1wtih7gZQ="
"version": "3.4.9",
"resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.4.9.tgz?cache=0&sync_timestamp=1604611494091&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.4.9.tgz",
"integrity": "sha1-wBb0IDCuKTLxTkdIs5odmg4lDmY="
},
"vue-style-loader": {
"version": "4.1.2",
@ -17580,9 +17612,9 @@
}
},
"webpack-merge": {
"version": "5.3.0",
"resolved": "https://registry.npm.taobao.org/webpack-merge/download/webpack-merge-5.3.0.tgz",
"integrity": "sha1-qA30TTX6us5oC/QwoZ/ansSe2Os=",
"version": "5.4.0",
"resolved": "https://registry.npm.taobao.org/webpack-merge/download/webpack-merge-5.4.0.tgz?cache=0&sync_timestamp=1605175039097&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-merge%2Fdownload%2Fwebpack-merge-5.4.0.tgz",
"integrity": "sha1-gb7wp9I/webCSwati/It3rUzo6M=",
"dev": true,
"requires": {
"clone-deep": "^4.0.1",

View File

@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
"version": "1.3.0",
"version": "1.4.0",
"description": "一个免费的音乐下载助手",
"main": "./dist/electron/main.js",
"productName": "lx-music-desktop",
@ -59,7 +59,7 @@
"lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-formatter-friendly --fix src"
},
"browserslist": [
"Electron 10.1.3"
"Electron 9.3.4"
],
"engines": {
"node": ">= 12"
@ -165,36 +165,36 @@
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"babel-loader": "^8.2.1",
"babel-minify-webpack-plugin": "^0.3.1",
"babel-preset-minify": "^0.5.1",
"cfonts": "^2.8.6",
"chalk": "^4.1.0",
"changelog-parser": "^2.8.0",
"copy-webpack-plugin": "^6.2.1",
"core-js": "^3.6.5",
"copy-webpack-plugin": "^6.3.1",
"core-js": "^3.7.0",
"cross-env": "^7.0.2",
"css-loader": "^4.3.0",
"del": "^6.0.0",
"electron": "^9.3.3",
"electron": "^9.3.4",
"electron-builder": "^22.9.1",
"electron-debug": "^3.1.0",
"electron-devtools-installer": "^3.1.1",
"eslint": "^7.12.1",
"eslint": "^7.13.0",
"eslint-config-standard": "^14.1.1",
"eslint-formatter-friendly": "^7.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-html": "^6.1.0",
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.2",
"eslint-plugin-standard": "^4.1.0",
"file-loader": "^6.2.0",
"friendly-errors-webpack-plugin": "^1.7.0",
"html-webpack-plugin": "^4.5.0",
"less": "^3.12.2",
"less-loader": "^7.0.2",
"markdown-it": "^11.0.1",
"less-loader": "^7.1.0",
"markdown-it": "^12.0.2",
"mini-css-extract-plugin": "^0.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-loader": "^4.0.4",
@ -206,21 +206,21 @@
"rimraf": "^3.0.2",
"spinnies": "^0.5.1",
"stylus": "^0.54.8",
"stylus-loader": "^4.2.0",
"stylus-loader": "^4.3.0",
"terser-webpack-plugin": "^4.2.3",
"url-loader": "^4.1.1",
"vue-loader": "^15.9.4",
"vue-loader": "^15.9.5",
"vue-template-compiler": "^2.6.12",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-hot-middleware": "^2.25.0",
"webpack-merge": "^5.3.0"
"webpack-merge": "^5.4.0"
},
"dependencies": {
"crypto-js": "^4.0.0",
"dnscache": "^1.0.2",
"electron-log": "^4.2.4",
"electron-log": "^4.3.0",
"electron-store": "^6.0.1",
"electron-updater": "^4.3.5",
"iconv-lite": "^0.6.2",
@ -228,11 +228,11 @@
"js-htmlencode": "^0.3.0",
"lrc-file-parser": "^1.0.5",
"needle": "^2.5.2",
"node-id3": "^0.2.1",
"node-id3": "^0.1.21",
"request": "^2.88.2",
"vue": "^2.6.12",
"vue-i18n": "^8.22.1",
"vue-router": "^3.4.8",
"vue-router": "^3.4.9",
"vuex": "^3.5.1",
"vuex-router-sync": "^5.0.0"
}

View File

@ -1,11 +1,15 @@
### 新增
- 播放详情页新增歌曲评论加载显示(某些平台暂不支持显示子评论)
- 托盘菜单新增显示、隐藏主界面选项为Linux、MAC版添加托盘菜单
- 新增播放进度信息保存
### 优化
- 修改播放详情页的歌曲图片的显示效果
- 移除kg源的歌词文件开头的空白字符串
### 修复
- 修复小芸源音乐搜索结果最多只有20条搜索结果的问题
- 修复专辑图片无法嵌入的问题
- 修复播放状态栏切换“上一首”歌曲按钮提示错误的问题
- 修复移动单首歌曲时,如果目标列表存在该歌曲,会导致将源列表与目标列表里的目标歌曲移除
- 修复kg源歌曲信息带有单引号等特殊字符被转义的问题

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,18 @@ class MainWindow extends EventEmitter {
toggleHide() {
this.emit(MAIN_WINDOW_EVENT_NAME.toggle_hide)
}
readyToShow() {
this.emit(MAIN_WINDOW_EVENT_NAME.ready_to_show)
}
show() {
this.emit(MAIN_WINDOW_EVENT_NAME.show)
}
hide() {
this.emit(MAIN_WINDOW_EVENT_NAME.hide)
}
}
module.exports = MainWindow

View File

@ -10,6 +10,9 @@ exports.mainWindow = {
quit: 'quit',
toggle_minimize: 'toggle_minimize',
toggle_hide: 'toggle_hide',
ready_to_show: 'ready_to_show',
show: 'show',
hide: 'hide',
}
exports.tray = {

View File

@ -82,7 +82,7 @@ if (isDev) {
winURL = 'http://localhost:9080'
} else {
global.__static = path.join(__dirname, '/static')
winURL = `file://${__dirname}/index.html`
winURL = `file://${path.join(__dirname, 'index.html')}`
}
function createWindow() {

View File

@ -23,9 +23,11 @@ exports.registerHotkey = ({ key, info }) => {
}
}
global.appHotKey.state[key].info = info
let status = global.appHotKey.state[key].status = globalShortcut.isRegistered(transKey) ? false : globalShortcut.register(transKey, () => {
handleKeyDown(key)
})
let status = global.appHotKey.state[key].status = globalShortcut.isRegistered(transKey)
? false
: globalShortcut.register(transKey, () => {
handleKeyDown(key)
})
return status
}

View File

@ -1,6 +1,6 @@
const { app, Tray, Menu } = require('electron')
const { isWin } = require('../../common/utils')
const { tray: TRAY_EVENT_NAME, common: COMMON_EVENT_NAME } = require('../events/_name')
const { tray: TRAY_EVENT_NAME, common: COMMON_EVENT_NAME, mainWindow: MAIN_WINDOW_NAME } = require('../events/_name')
const path = require('path')
let isEnableTray = null
let themeId = null
@ -29,6 +29,16 @@ global.lx_event.common.on(COMMON_EVENT_NAME.config, sourceName => {
createMenu(global.modules.tray)
})
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.ready_to_show, () => {
createMenu(global.modules.tray)
})
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.show, () => {
createMenu(global.modules.tray)
})
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.hide, () => {
createMenu(global.modules.tray)
})
const createTray = () => {
if ((global.modules.tray && !global.modules.tray.isDestroyed()) || !global.appSetting.tray || !global.appSetting.tray.isShow) return
@ -58,8 +68,24 @@ const destroyTray = () => {
}
const createMenu = tray => {
if (!global.modules.tray || !isWin) return
if (!global.modules.tray) return
let menu = []
global.modules.mainWindow && menu.push(global.modules.mainWindow.isVisible() ? {
label: '隐藏主界面',
click() {
global.modules.mainWindow.hide()
},
} : {
label: '显示主界面',
click() {
if (!global.modules.mainWindow) return
if (!global.modules.mainWindow.isVisible()) {
global.modules.mainWindow.show()
}
global.modules.mainWindow.restore()
global.modules.mainWindow.focus()
},
})
menu.push(global.appSetting.desktopLyric.enable ? {
label: '关闭桌面歌词',
click() {

View File

@ -1,3 +1,4 @@
const path = require('path')
const { BrowserWindow } = require('electron')
const { winLyric: WIN_LYRIC_EVENT_NAME } = require('../../events/_name')
const { debounce } = require('../../../common/utils')
@ -13,7 +14,7 @@ global.lx_event.winLyric.on(WIN_LYRIC_EVENT_NAME.close, () => {
closeWindow()
})
let winURL = global.isDev ? 'http://localhost:9081/lyric.html' : `file://${__dirname}/lyric.html`
let winURL = global.isDev ? 'http://localhost:9081/lyric.html' : `file://${path.join(__dirname, 'lyric.html')}`
const setLyricsConfig = debounce(config => {
// if (x != null) bounds.x = x

View File

@ -29,5 +29,13 @@ module.exports = mainWindow => {
mainWindow.once('ready-to-show', () => {
mainWindow.show()
global.lx_event.mainWindow.readyToShow()
})
mainWindow.on('show', () => {
global.lx_event.mainWindow.show()
})
mainWindow.on('hide', () => {
global.lx_event.mainWindow.hide()
})
}

View File

@ -47,6 +47,9 @@ module.exports = (filePath, meta) => {
if (err) console.log(err.message)
delete meta.APIC
handleWriteMeta(meta, filePath)
fs.unlink(picPath, err => {
if (err) console.log(err.message)
})
})
})
.on('error', err => {

View File

@ -174,6 +174,9 @@ export default {
...mapMutations('search', {
setSearchHistoryList: 'setHistory',
}),
...mapMutations('player', {
setPlayList: 'setList',
}),
init() {
document.documentElement.style.fontSize = this.windowSizeActive.fontSize
@ -276,6 +279,7 @@ export default {
if (!loveList.list) loveList.list = []
this.initList({ defaultList, loveList, userList })
this.initDownloadList(downloadList) //
this.initPlayInfo()
})
},
initDownloadList(downloadList) {
@ -299,6 +303,27 @@ export default {
}
})
},
initPlayInfo() {
rendererInvoke(NAMES.mainWindow.get_data, 'playInfo').then(info => {
// console.log(info, window.allList)
if (!info) return
if (info.listId) {
const list = window.allList[info.listId]
// console.log(list)
if (!list) return
info.list = list.list
}
window.restorePlayInfo = info
this.setPlayList({
list: {
list: info.list,
id: info.listId,
},
index: info.index,
})
})
},
showUpdateModal() {
(this.version.newVersion && this.version.newVersion.history
? Promise.resolve(this.version.newVersion)

View File

@ -49,7 +49,7 @@ div(:class="$style.player")
span(style="margin: 0 5px;") /
span {{maxPlayTimeStr}}
div(:class="$style.right")
div(:class="$style.playBtn" @click='handlePrev' :tips="$t('core.player.next')" style="transform: rotate(180deg);")
div(:class="$style.playBtn" @click='handlePrev' :tips="$t('core.player.prev')" style="transform: rotate(180deg);")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 220.847 220.847' space='preserve')
use(xlink:href='#icon-nextMusic')
div(:class="$style.playBtn" :tips="isPlay ? $t('core.player.pause') : $t('core.player.play')" @click='togglePlay')
@ -87,7 +87,7 @@ div(:class="$style.player")
<script>
import Lyric from 'lrc-file-parser'
import { rendererSend, rendererOn, NAMES } from '../../../common/ipc'
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText, debounce, assertApiSupport } from '../../utils'
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText, debounce, throttle, assertApiSupport } from '../../utils'
import { mapGetters, mapActions, mapMutations } from 'vuex'
import { requestMsg } from '../../utils/message'
import { isMac } from '../../../common/utils'
@ -130,7 +130,7 @@ export default {
line: 0,
},
delayNextTimeout: null,
audioErrorTime: 0,
restorePlayTime: 0,
retryNum: 0,
isMac,
volumeEvent: {
@ -195,6 +195,12 @@ export default {
this.handleSaveVolume = debounce(volume => {
this.setVolume(volume)
}, 300)
this.savePlayInfo = throttle(n => {
rendererSend(NAMES.mainWindow.save_data, {
path: 'playInfo',
data: n,
})
}, 2000)
rendererOn(NAMES.mainWindow.get_lyric_info, (event, info) => {
switch (info.action) {
@ -287,6 +293,12 @@ export default {
},
nowPlayTime(n, o) {
if (Math.abs(n - o) > 2) this.isActiveTransition = true
this.savePlayInfo({
time: n,
listId: this.listId,
list: this.listId == null ? this.list : null,
index: this.playIndex,
})
},
},
methods: {
@ -299,6 +311,7 @@ export default {
'clearPlayedList',
'setPlayedList',
'removePlayedList',
'setList',
]),
...mapMutations(['setVolume', 'setPlayNextMode', 'setVisibleDesktopLyric', 'setLockDesktopLyric']),
...mapMutations('list', ['updateMusicInfo']),
@ -348,7 +361,7 @@ export default {
this.stopPlay()
if (this.listId != 'download' && audio.error.code !== 1 && this.retryNum < 2) { // URL2URL
// console.log(this.retryNum)
if (!this.audioErrorTime) this.audioErrorTime = audio.currentTime //
if (!this.restorePlayTime) this.restorePlayTime = audio.currentTime //
this.retryNum++
this.setUrl(this.list[this.playIndex], true)
this.status = this.statusText = this.$t('core.player.refresh_url')
@ -360,15 +373,23 @@ export default {
this.addDelayNextTimeout()
})
audio.addEventListener('loadeddata', () => {
// console.log('loadeddata')
this.status = this.statusText = this.$t('core.player.loading')
this.maxPlayTime = audio.duration
if (this.audioErrorTime) {
audio.currentTime = this.audioErrorTime
this.audioErrorTime = 0
if (window.restorePlayInfo) {
audio.currentTime = window.restorePlayInfo.time
window.restorePlayInfo = null
audio.pause()
this.stopPlay()
} else if (this.restorePlayTime) {
audio.currentTime = this.restorePlayTime
this.restorePlayTime = 0
}
if (!this.targetSong.interval && this.listId != 'download') this.updateMusicInfo({ id: this.listId, index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) } })
this.status = this.statusText = this.$t('core.player.loading')
})
audio.addEventListener('loadstart', () => {
// console.log('loadstart')
this.startBuffering()
this.status = this.statusText = this.$t('core.player.loading')
})
audio.addEventListener('canplay', () => {
@ -382,7 +403,7 @@ export default {
this.clearBufferTimeout()
}
// if (this.musicInfo.lrc) window.lrc.play(audio.currentTime * 1000)
this.status = this.statusText = this.$t('core.player.loading')
this.status = this.statusText = ''
})
// audio.addEventListener('canplaythrough', () => {
// console.log('')
@ -432,7 +453,7 @@ export default {
let targetSong = this.targetSong = this.list[this.playIndex]
if (this.setting.player.togglePlayMethod == 'random') this.setPlayedList(targetSong)
this.retryNum = 0
this.audioErrorTime = 0
this.restorePlayTime = 0
if (this.listId == 'download') {
const filePath = path.join(this.setting.download.savePath, targetSong.fileName)
@ -517,14 +538,17 @@ export default {
if (this.setting.player.togglePlayMethod == 'random' && this.playedList.length) {
let index = this.playedList.indexOf(this.targetSong)
index -= 1
if (index > -1) {
let listIndex = this.list.indexOf(this.playedList[index])
if (listIndex < 0) {
this.removePlayedList(index)
return this.handlePrev()
while (true) {
if (index > -1) {
let listIndex = this.list.indexOf(this.playedList[index])
if (listIndex < 0) {
this.removePlayedList(index)
continue
}
this.setPlayIndex(listIndex)
return
}
this.setPlayIndex(listIndex)
return
break
}
}
let list = await this.filterList()
@ -552,14 +576,17 @@ export default {
if (this.setting.player.togglePlayMethod == 'random' && this.playedList.length) {
let index = this.playedList.indexOf(this.targetSong)
index += 1
if (index < this.playedList.length) {
let listIndex = this.list.indexOf(this.playedList[index])
if (listIndex < 0) {
this.removePlayedList(index)
return this.handleNext()
while (true) {
if (index < this.playedList.length) {
let listIndex = this.list.indexOf(this.playedList[index])
if (listIndex < 0) {
this.removePlayedList(index)
continue
}
this.setPlayIndex(listIndex)
return
}
this.setPlayIndex(listIndex)
return
break
}
}
let list = await this.filterList()
@ -607,7 +634,7 @@ export default {
setProgress(pregress) {
if (!audio.src) return
const time = pregress * this.maxPlayTime
if (this.audioErrorTime) this.audioErrorTime = time
if (this.restorePlayTime) this.restorePlayTime = time
if (this.mediaBuffer.playTime) {
this.clearBufferTimeout()
this.mediaBuffer.playTime = time
@ -667,23 +694,15 @@ export default {
}
},
setLrc(targetSong) {
this.musicInfo.lrc = targetSong.lrc
this.musicInfo.tlrc = targetSong.tlrc
let lrcP = this.musicInfo.lrc && this.musicInfo.tlrc != null
? Promise.resolve()
: this.getLrc(targetSong).then(() => {
this.musicInfo.lrc = targetSong.lrc
this.musicInfo.tlrc = targetSong.tlrc
})
lrcP
.catch(() => {
this.status = this.statusText = this.$t('core.player.lyric_error')
}).finally(() => {
this.handleUpdateWinLyricInfo('lyric', { lrc: this.musicInfo.lrc, tlrc: this.musicInfo.tlrc })
this.setLyric()
})
this.getLrc(targetSong).then(() => {
this.musicInfo.lrc = targetSong.lrc
this.musicInfo.tlrc = targetSong.tlrc
}).catch(() => {
this.status = this.statusText = this.$t('core.player.lyric_error')
}).finally(() => {
this.handleUpdateWinLyricInfo('lyric', { lrc: this.musicInfo.lrc, tlrc: this.musicInfo.tlrc })
this.setLyric()
})
},
handleRemoveMusic() {
this.stopPlay()

View File

@ -29,7 +29,7 @@
"play_toggle_mode_single_loop": "Single Loop",
"play_toggle_mode_off": "Disable",
"comment_show": "Show song comments",
"comment_show": "Song comments",
"comment_hot_loading": "Hot comments are loading",
"comment_new_loading": "Latest comments are loading",
"comment_hot_load_error": "Hot comments failed to load, click to try to reload",

View File

@ -29,7 +29,7 @@
"play_toggle_mode_single_loop": "单曲循环",
"play_toggle_mode_off": "禁用",
"comment_show": "显示歌曲评论",
"comment_show": "歌曲评论",
"comment_hot_loading": "热门评论加载中",
"comment_new_loading": "最新评论加载中",
"comment_hot_load_error": "热门评论加载失败,点击尝试重新加载",

View File

@ -29,7 +29,7 @@
"play_toggle_mode_single_loop": "單曲循環",
"play_toggle_mode_off": "禁用",
"comment_show": "顯示歌曲評論",
"comment_show": "歌曲評論",
"comment_hot_loading": "熱門評論加載中",
"comment_new_loading": "最新評論加載中",
"comment_hot_load_error": "熱門評論加載失敗,點擊嘗試重新加載",

View File

@ -377,11 +377,13 @@ const actions = {
},
}
commit('setStatusText', { downloadInfo, text: '获取URL中...' })
let p = options.url ? Promise.resolve() : getUrl(downloadInfo).then(result => {
commit('updateUrl', { downloadInfo, url: result.url })
if (!result.url) return Promise.reject(new Error('获取URL失败'))
options.url = result.url
})
let p = options.url
? Promise.resolve()
: getUrl(downloadInfo).then(result => {
commit('updateUrl', { downloadInfo, url: result.url })
if (!result.url) return Promise.reject(new Error('获取URL失败'))
options.url = result.url
})
p.then(() => {
tryNum[downloadInfo.key] = 0
dls[downloadInfo.key] = download(options)

View File

@ -92,8 +92,7 @@ const mutations = {
if (!fromList || !toList) return
fromList.list.splice(fromList.list.indexOf(musicInfo), 1)
let index = toList.list.findIndex(s => s.songmid === musicInfo.songmid)
if (index > -1) return toList.list.splice(index, 1)
toList.list.push(musicInfo)
if (index < 0) toList.list.push(musicInfo)
},
listAddMultiple(state, { id, list }) {
let targetList = allList[id]
@ -110,7 +109,7 @@ const mutations = {
},
// { fromId, toId, list }
listMoveMultiple(state, { fromId, toId, list }) {
console.log(state.commit)
// console.log(state.commit)
this.commit('list/listRemoveMultiple', { id: fromId, list })
this.commit('list/listAddMultiple', { id: toId, list })
},

View File

@ -59,6 +59,15 @@ const actions = {
},
getLrc({ commit, state }, musicInfo) {
if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
if (musicInfo.lrc && musicInfo.tlrc != null) {
if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
let str = musicInfo.lrc.replace('\ufeff[id:$00000000]\n', '')
commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc })
}
return Promise.resolve()
}
lrcRequest = music[musicInfo.source].getLyric(musicInfo)
return lrcRequest.promise.then(({ lyric, tlyric }) => {
lrcRequest = null

View File

@ -85,10 +85,12 @@ const actions = {
let source = rootState.setting.songList.source
const loadData = (id, page) => {
let key = `sdetail__${source}__${id}__${page}`
return cache.has(key) ? Promise.resolve(cache.get(key)) : music[source].songList.getListDetail(id, page).then(result => {
cache.set(key, result)
return result
})
return cache.has(key)
? Promise.resolve(cache.get(key))
: music[source].songList.getListDetail(id, page).then(result => {
cache.set(key, result)
return result
})
}
return loadData(id, 1).then(result => {
if (result.total <= result.limit) return result.list

View File

@ -78,8 +78,9 @@ const encodeNames = {
'&gt;': '>',
'&quot;': '"',
'&apos;': "'",
'&#039;': "'",
}
export const decodeName = str => str.replace(/(?:&amp;|&lt;|&gt;|&quot;|&apos;)/g, s => encodeNames[s])
export const decodeName = str => str.replace(/(?:&amp;|&lt;|&gt;|&quot;|&apos;|&#039;)/gm, s => encodeNames[s])
const easeInOutQuad = (t, b, c, d) => {
t /= d / 2
@ -132,7 +133,7 @@ const handleScroll = (element, to, duration = 300, fn = () => {}) => {
* @param {*} fn 滚动完成后的回调
* @param {*} delay 延迟执行时间
*/
export const scrollTo = (element, to, duration = 300, fn = () => {}, delay) => {
export const scrollTo = (element, to, duration = 300, fn = () => {}, delay = 0) => {
let cancelFn
let timeout
if (delay) {

View File

@ -1,5 +1,5 @@
import { httpFetch } from '../../request'
import { dateFormat2 } from '../../'
import { decodeName, dateFormat2 } from '../../'
export default {
_requestObj: null,
@ -48,7 +48,7 @@ export default {
return rawList.map(item => {
let data = {
id: item.id,
text: item.content.split('\n'),
text: decodeName(item.content || '').split('\n'),
time: item.addtime,
timeStr: dateFormat2(new Date(item.addtime).getTime()),
userName: item.user_name,
@ -61,7 +61,7 @@ export default {
return item.pcontent ? {
id: item.id,
text: item.pcontent.split('\n'),
text: decodeName(item.pcontent).split('\n'),
time: null,
userName: item.puser,
avatar: null,

View File

@ -1,4 +1,5 @@
import { httpFetch } from '../../request'
import { decodeName } from '../..'
export default {
_requestObj: null,
@ -25,7 +26,7 @@ export default {
filterList(rawList) {
const list = []
rawList.forEach(item => {
item.keywords.map(k => list.push(k.keyword))
item.keywords.map(k => list.push(decodeName(k.keyword)))
})
return list
},

View File

@ -1,5 +1,5 @@
import { httpGet, cancelHttp, httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
let boardList = [{ id: 'kg__8888', name: '酷狗TOP500', bangid: '8888' }, { id: 'kg__6666', name: '酷狗飙升榜', bangid: '6666' }, { id: 'kg__37361', name: '酷狗雷达榜', bangid: '37361' }, { id: 'kg__23784', name: '网络红歌榜', bangid: '23784' }, { id: 'kg__24971', name: 'DJ热歌榜', bangid: '24971' }, { id: 'kg__35811', name: '会员专享热歌榜', bangid: '35811' }, { id: 'kg__31308', name: '华语新歌榜', bangid: '31308' }, { id: 'kg__31310', name: '欧美新歌榜', bangid: '31310' }, { id: 'kg__31311', name: '韩国新歌榜', bangid: '31311' }, { id: 'kg__31312', name: '日本新歌榜', bangid: '31312' }, { id: 'kg__31313', name: '粤语新歌榜', bangid: '31313' }, { id: 'kg__33162', name: 'ACG新歌榜', bangid: '33162' }, { id: 'kg__21101', name: '酷狗分享榜', bangid: '21101' }, { id: 'kg__30972', name: '腾讯音乐人原创榜', bangid: '30972' }, { id: 'kg__22603', name: '5sing音乐榜', bangid: '22603' }, { id: 'kg__33160', name: '电音热歌榜', bangid: '33160' }, { id: 'kg__21335', name: '繁星音乐榜', bangid: '21335' }, { id: 'kg__33161', name: '古风新歌榜', bangid: '33161' }, { id: 'kg__33163', name: '影视金曲榜', bangid: '33163' }, { id: 'kg__33166', name: '欧美金曲榜', bangid: '33166' }, { id: 'kg__33165', name: '粤语金曲榜', bangid: '33165' }, { id: 'kg__36107', name: '小语种热歌榜', bangid: '36107' }, { id: 'kg__4681', name: '美国BillBoard榜', bangid: '4681' }, { id: 'kg__4680', name: '英国单曲榜', bangid: '4680' }, { id: 'kg__4673', name: '日本公信榜', bangid: '4673' }, { id: 'kg__38623', name: '韩国Melon音乐榜', bangid: '38623' }, { id: 'kg__42807', name: 'joox本地热歌榜', bangid: '42807' }, { id: 'kg__42808', name: '台湾KKBOX风云榜', bangid: '42808' }]
@ -134,9 +134,9 @@ export default {
}
}
return {
singer: item.singername,
name: item.songname,
albumName: item.album_name,
singer: decodeName(item.singername),
name: decodeName(item.songname),
albumName: decodeName(item.album_name),
albumId: item.album_id,
songmid: item.audio_id,
source: 'kg',

View File

@ -1,8 +1,10 @@
import { httpFetch } from '../../request'
import { decodeLyric } from './util'
import { decodeName } from '../..'
const parseLyric = str => {
str = str.replace(/(?:<\d+,\d+,\d+>|\r)/g, '')
if (str.startsWith('\ufeff[id:$00000000]')) str = str.replace('\ufeff[id:$00000000]\n', '')
let trans = str.match(/\[language:([\w=\\/+]+)\]/)
let tlyric
if (trans) {
@ -29,6 +31,8 @@ const parseLyric = str => {
return str.replace(result[1], time)
})
tlyric = tlyric ? tlyric.join('\n') : ''
lyric = decodeName(lyric)
tlyric = decodeName(tlyric)
return {
lyric,
tlyric,

View File

@ -1,7 +1,7 @@
// import '../../polyfill/array.find'
// import jshtmlencode from 'js-htmlencode'
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
// import { debug } from '../../utils/env'
// import { formatSinger } from './util'
@ -50,9 +50,9 @@ export default {
}
}
list.push({
singer: item.singername,
name: item.songname,
albumName: item.album_name,
singer: decodeName(item.singername),
name: decodeName(item.songname),
albumName: decodeName(item.album_name),
albumId: item.album_id,
songmid: item.audio_id,
source: 'kg',

View File

@ -1,5 +1,5 @@
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
import { toMD5 } from '../utils'
export default {
@ -454,9 +454,9 @@ export default {
}
}
return {
singer: item.singername,
name: item.songname,
albumName: item.album_name,
singer: decodeName(item.singername),
name: decodeName(item.songname),
albumName: decodeName(item.album_name),
albumId: item.album_id,
songmid: item.audio_id,
source: 'kg',
@ -507,9 +507,9 @@ export default {
}
}
list.push({
singer: item.author_name,
name: item.ori_audio_name,
albumName: item.album_info.album_name,
singer: decodeName(item.author_name),
name: decodeName(item.ori_audio_name),
albumName: decodeName(item.album_info.album_name),
albumId: item.album_info.album_id,
songmid: item.audio_info.audio_id,
source: 'kg',

View File

@ -382,7 +382,8 @@ export default {
return this.searchSourceId == 'all'
? list.filter(s => this.assertApiSupport(s.source))
: this.assertApiSupport(this.searchSourceId)
? [...list] : []
? [...list]
: []
},
handleListAddModalClose() {
this.isShowListAdd = false