mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/lyswhut/lx-music-desktop.git
synced 2026-09-20 08:04:00 +08:00
Compare commits
298 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41f4130e5d | ||
|
|
8e19f3fc0b | ||
|
|
c4b8ac8b0b | ||
|
|
0ac2df1297 | ||
|
|
251450fd50 | ||
|
|
85c5595f43 | ||
|
|
ca3188c930 | ||
|
|
2f47f82b0f | ||
|
|
0e09598b10 | ||
|
|
a705420528 | ||
|
|
4089887514 | ||
|
|
a3d02e5f39 | ||
|
|
6e09363832 | ||
|
|
1c58a64847 | ||
|
|
2a716e4d5a | ||
|
|
a2c613d380 | ||
|
|
aa4b09436c | ||
|
|
9521bba4ba | ||
|
|
55d10021f8 | ||
|
|
7fe35748d0 | ||
|
|
ff9efbd4ea | ||
|
|
23b8c325f4 | ||
|
|
ecfccb4c40 | ||
|
|
2472574cde | ||
|
|
bf81c8facc | ||
|
|
9bf0d69ab6 | ||
|
|
cf9d98d434 | ||
|
|
da8e67d4e5 | ||
|
|
d695cdef08 | ||
|
|
d7a7701c09 | ||
|
|
a31180260b | ||
|
|
f33947287c | ||
|
|
c054ceeab5 | ||
|
|
c8dce1bcb6 | ||
|
|
6195c10646 | ||
|
|
535cbbbd16 | ||
|
|
fa99f35bc0 | ||
|
|
5800f0e354 | ||
|
|
aa5e621184 | ||
|
|
283bdd6246 | ||
|
|
2884e67109 | ||
|
|
4542f9b2e3 | ||
|
|
9d08f91079 | ||
|
|
0704a4ad12 | ||
|
|
bb8509a21c | ||
|
|
f2e3d4a53d | ||
|
|
b8a221e67e | ||
|
|
f4147cce37 | ||
|
|
01f9fd502f | ||
|
|
5d20adc81e | ||
|
|
6a78f659e3 | ||
|
|
211f584bf8 | ||
|
|
fcfba8b12c | ||
|
|
85e4c7555a | ||
|
|
19dccffdde | ||
|
|
359514a83c | ||
|
|
90ea0dc857 | ||
|
|
ae18db45a4 | ||
|
|
4783c9be8d | ||
|
|
ff41fa9829 | ||
|
|
aa56dafd5f | ||
|
|
f2f2008d5d | ||
|
|
15d2589db8 | ||
|
|
47a8da49ca | ||
|
|
2250cac7f9 | ||
|
|
94e3063307 | ||
|
|
88691b3f18 | ||
|
|
3851880007 | ||
|
|
e5d2e089f4 | ||
|
|
bfe7f24a4b | ||
|
|
0d1e2c3349 | ||
|
|
bc6272a0ed | ||
|
|
56a752dc26 | ||
|
|
0fe443c92a | ||
|
|
74afdb2a46 | ||
|
|
ebd6ff36ed | ||
|
|
a5ec36bf89 | ||
|
|
c65802c1c3 | ||
|
|
784515e411 | ||
|
|
e859d39b2b | ||
|
|
62c4bfb9eb | ||
|
|
8ab1bdf30a | ||
|
|
c758066e25 | ||
|
|
06b7f69b3c | ||
|
|
c3c43a2645 | ||
|
|
343395a5de | ||
|
|
3c9bb74b61 | ||
|
|
c9cf30692f | ||
|
|
c979339c4e | ||
|
|
9393906eb9 | ||
|
|
1b4c910264 | ||
|
|
4db5d26b1e | ||
|
|
c09a4131db | ||
|
|
ce6f3f23c6 | ||
|
|
7b898c2d91 | ||
|
|
3da797a0ad | ||
|
|
517899cd03 | ||
|
|
1d6a14685e | ||
|
|
737d00f550 | ||
|
|
68798a9627 | ||
|
|
5b1dfee05c | ||
|
|
e75863e99d | ||
|
|
1c542a9b17 | ||
|
|
729ac5a0d7 | ||
|
|
ff8195df46 | ||
|
|
692ab6dacb | ||
|
|
128039d678 | ||
|
|
bb5de056d4 | ||
|
|
d927ac90e7 | ||
|
|
f61099ecad | ||
|
|
f96b663bbe | ||
|
|
f65213f8aa | ||
|
|
2e5adeb50c | ||
|
|
6de84d3b9b | ||
|
|
65ae08add6 | ||
|
|
3c970c24c1 | ||
|
|
93f3507dc8 | ||
|
|
e92e291409 | ||
|
|
4b4de8937e | ||
|
|
27a036bc00 | ||
|
|
1eb2540c67 | ||
|
|
3a5bd6029f | ||
|
|
249ff7f2d2 | ||
|
|
9afa965d5d | ||
|
|
28b7b5581d | ||
|
|
26aab15e50 | ||
|
|
92351049f1 | ||
|
|
47d3c50863 | ||
|
|
36ac3532e6 | ||
|
|
dee16f6943 | ||
|
|
3541b568c9 | ||
|
|
4dfa4d9525 | ||
|
|
5938f4e591 | ||
|
|
9ac26be65d | ||
|
|
5099ba9c96 | ||
|
|
bca5b13516 | ||
|
|
6ceb984393 | ||
|
|
17b29f376a | ||
|
|
36bef673d3 | ||
|
|
c2fa4e5220 | ||
|
|
ddf06d20c2 | ||
|
|
e51f640371 | ||
|
|
e302f53d5c | ||
|
|
b2058b9581 | ||
|
|
35501d328b | ||
|
|
cb746c64db | ||
|
|
e2f6d117bc | ||
|
|
9fd9449eca | ||
|
|
1f97af6ff1 | ||
|
|
f1a7862a9c | ||
|
|
8aeac3ed2e | ||
|
|
469832a598 | ||
|
|
e0e65e4374 | ||
|
|
66f78d6979 | ||
|
|
efc58f7dd1 | ||
|
|
bc301c27c2 | ||
|
|
82ea1935de | ||
|
|
226fb05337 | ||
|
|
be219f03d5 | ||
|
|
f10c1e923e | ||
|
|
66121e5ff3 | ||
|
|
478b71172d | ||
|
|
e7370f12ae | ||
|
|
b844a577c7 | ||
|
|
9bf33fdb25 | ||
|
|
8b988b227b | ||
|
|
8b2be019c6 | ||
|
|
4d7d92759f | ||
|
|
798b840472 | ||
|
|
48db75a995 | ||
|
|
7072541ba7 | ||
|
|
7119c915ec | ||
|
|
5e3035cc15 | ||
|
|
7cf2e4c4ed | ||
|
|
674a3a0a3f | ||
|
|
7486a99494 | ||
|
|
783d96bd7d | ||
|
|
64eea42092 | ||
|
|
8453ad0fb4 | ||
|
|
0acfeff006 | ||
|
|
a338b7ef39 | ||
|
|
e821660124 | ||
|
|
bad6045164 | ||
|
|
6779fd7ae5 | ||
|
|
04858cc42c | ||
|
|
916975b0a9 | ||
|
|
644db88e58 | ||
|
|
b025af45fa | ||
|
|
0f11731c01 | ||
|
|
ea1d21a3ef | ||
|
|
545ba6521b | ||
|
|
1fd3e6c9fa | ||
|
|
2913c0c7de | ||
|
|
a4c851899f | ||
|
|
df1c58e79b | ||
|
|
67edeab09b | ||
|
|
fe07ac025a | ||
|
|
fc72d99ab3 | ||
|
|
377f665361 | ||
|
|
4e458ec4cb | ||
|
|
6f4500f31a | ||
|
|
a363c5525b | ||
|
|
65027fceba | ||
|
|
2b0c75a649 | ||
|
|
bcc79541c1 | ||
|
|
081d6dc91e | ||
|
|
09a5111e36 | ||
|
|
253746843c | ||
|
|
5d2fac9247 | ||
|
|
3c2a1093a0 | ||
|
|
88b3d8ee4a | ||
|
|
d35a6f504f | ||
|
|
4965dad6a2 | ||
|
|
3ad4584159 | ||
|
|
5e291255bb | ||
|
|
205c99372e | ||
|
|
a05f3a969b | ||
|
|
3acc0931d8 | ||
|
|
05f6a953ea | ||
|
|
6253368f05 | ||
|
|
9483f2f178 | ||
|
|
8df6e7ef90 | ||
|
|
b09dba0a95 | ||
|
|
cfee4a0b24 | ||
|
|
34febf4949 | ||
|
|
6aed9dfb9f | ||
|
|
c7360993c9 | ||
|
|
34a072bada | ||
|
|
dda0d54f20 | ||
|
|
d710c31d48 | ||
|
|
02c74f7d96 | ||
|
|
5bdccba29e | ||
|
|
cdc819fbe8 | ||
|
|
4629d4cd3e | ||
|
|
ba3a70c524 | ||
|
|
52b985dd8e | ||
|
|
b51c8e1552 | ||
|
|
86f9c03707 | ||
|
|
e61c84ee08 | ||
|
|
2f39808275 | ||
|
|
f5aee4cbd0 | ||
|
|
9fd9bb4eef | ||
|
|
685cae8993 | ||
|
|
ec14aadec6 | ||
|
|
b934770e1e | ||
|
|
2f76433f34 | ||
|
|
535c63be2b | ||
|
|
53d4f08ee7 | ||
|
|
81b72fe72b | ||
|
|
e496794052 | ||
|
|
442b4fb30f | ||
|
|
9528b10d01 | ||
|
|
a9f9c887b5 | ||
|
|
6105a331aa | ||
|
|
0f0be95c12 | ||
|
|
d6ca9e4539 | ||
|
|
d3b5171237 | ||
|
|
cf501ac19e | ||
|
|
4fd4746ddf | ||
|
|
61c1476823 | ||
|
|
e28b8bb6e8 | ||
|
|
5eb9107adf | ||
|
|
83ddf74890 | ||
|
|
6aa7f2a0ee | ||
|
|
d801d55c3c | ||
|
|
491e644c3c | ||
|
|
5844232a00 | ||
|
|
abbf067625 | ||
|
|
806c882965 | ||
|
|
3fe5a85ffe | ||
|
|
95dae62bb3 | ||
|
|
f7edd54ea7 | ||
|
|
78ae89199e | ||
|
|
fc12a235f2 | ||
|
|
48fc96226c | ||
|
|
3534dd27dc | ||
|
|
a7e3c1a0c4 | ||
|
|
43c5051158 | ||
|
|
2f56a7090a | ||
|
|
13ffcfbbcd | ||
|
|
1aeb8e29e2 | ||
|
|
a3b844d2e3 | ||
|
|
5aa027f1a9 | ||
|
|
c12be6a1c8 | ||
|
|
c891ed81e1 | ||
|
|
c48921990d | ||
|
|
54bfd945e5 | ||
|
|
1d8c4db5eb | ||
|
|
055ab98d4c | ||
|
|
777551cb43 | ||
|
|
68827f7697 | ||
|
|
8e5b144f00 | ||
|
|
748a420b64 | ||
|
|
80fc43a075 | ||
|
|
0588f2846b | ||
|
|
8e4e7d9efa | ||
|
|
6df01edc7a | ||
|
|
996396c943 |
@@ -30,5 +30,5 @@
|
||||
"settings": {
|
||||
"html/html-extensions": [".html", ".vue"]
|
||||
},
|
||||
"ignorePatterns": ["vendors", "*.min.js"]
|
||||
"ignorePatterns": ["vendors", "*.min.js", "dist", "node_modules"]
|
||||
}
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/----.yml
vendored
2
.github/ISSUE_TEMPLATE/----.yml
vendored
@@ -8,7 +8,7 @@ body:
|
||||
label: 解决方案检查
|
||||
description: 请确保你已完成以下所有操作
|
||||
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
|
||||
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),但没有发现类似的问题
|
||||
required: true
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/--bug.yml
vendored
2
.github/ISSUE_TEMPLATE/--bug.yml
vendored
@@ -8,7 +8,7 @@ body:
|
||||
label: 解决方案检查
|
||||
description: 请确保你已完成以下所有操作
|
||||
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
|
||||
- label: 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>),并没有发现类似的问题
|
||||
required: true
|
||||
|
||||
35
.github/workflows/beta-pack.yml
vendored
35
.github/workflows/beta-pack.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
@@ -31,7 +31,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
@@ -92,6 +94,11 @@ jobs:
|
||||
name: lx-music-desktop-win_arm64-green
|
||||
path: build/*win_arm64 green.7z
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
Get-FileHash *.exe,*.7z -Algorithm MD5 | Format-List
|
||||
|
||||
Mac:
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
@@ -102,7 +109,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
@@ -117,7 +124,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
@@ -143,12 +152,17 @@ jobs:
|
||||
name: lx-music-desktop-mac-dmg-arm64
|
||||
path: build/*-arm64.dmg
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
md5 *.dmg
|
||||
|
||||
Linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install package
|
||||
run: sudo apt-get install -y rpm libarchive-tools
|
||||
run: sudo apt-get update && sudo apt-get install -y rpm libarchive-tools
|
||||
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
@@ -156,7 +170,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
@@ -171,7 +185,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
@@ -231,3 +247,8 @@ jobs:
|
||||
with:
|
||||
name: lx-music-desktop-x64-pacman
|
||||
path: build/* x64.pacman
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
md5sum *.deb *.rpm *.pacman *.AppImage
|
||||
|
||||
35
.github/workflows/release.yml
vendored
35
.github/workflows/release.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
@@ -31,7 +31,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
@@ -49,6 +51,11 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BT_TOKEN: ${{ secrets.BT_TOKEN }}
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
Get-FileHash *.exe,*.7z -Algorithm MD5 | Format-List
|
||||
|
||||
Mac:
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
@@ -59,7 +66,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
@@ -74,7 +81,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
@@ -89,12 +98,17 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BT_TOKEN: ${{ secrets.BT_TOKEN }}
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
md5 *.dmg
|
||||
|
||||
Linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install package
|
||||
run: sudo apt-get install -y rpm libarchive-tools
|
||||
run: sudo apt-get update && sudo apt-get install -y rpm libarchive-tools
|
||||
|
||||
- name: Check out git repository
|
||||
uses: actions/checkout@v2
|
||||
@@ -102,7 +116,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache file
|
||||
uses: actions/cache@v2
|
||||
@@ -117,7 +131,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: |
|
||||
npm install npm@8.5 -g
|
||||
npm install
|
||||
|
||||
- name: Build src code
|
||||
run: npm run build:src
|
||||
@@ -134,3 +150,8 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BT_TOKEN: ${{ secrets.BT_TOKEN }}
|
||||
|
||||
- name: Generate file MD5
|
||||
run: |
|
||||
cd build
|
||||
md5sum *.deb *.rpm *.pacman *.AppImage
|
||||
|
||||
@@ -2,11 +2,13 @@ module.exports = {
|
||||
upgrade: true,
|
||||
reject: [
|
||||
'electron',
|
||||
'electron-builder',
|
||||
'chalk',
|
||||
'del',
|
||||
],
|
||||
// target: 'newest',
|
||||
// filter: [
|
||||
// /^vue/,
|
||||
// 'electron-builder',
|
||||
// 'electron-updater',
|
||||
// ],
|
||||
}
|
||||
|
||||
205
CHANGELOG.md
205
CHANGELOG.md
@@ -6,6 +6,211 @@ 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.22.2](https://github.com/lyswhut/lx-music-desktop/compare/v1.22.1...v1.22.2) - 2022-08-18
|
||||
|
||||
### 优化
|
||||
|
||||
- 为tx、kw源添加 Flac 24bit 音质显示,注:由于之前没有记录此音质,所以之前收藏的歌曲信息中不包含它
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复无法批量排序歌曲的问题
|
||||
- 修复某些缺失的繁体中文翻译
|
||||
- 修复企鹅音乐搜索失效的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 降级electron到v15.5.7
|
||||
|
||||
## [1.22.1](https://github.com/lyswhut/lx-music-desktop/compare/v1.22.0...v1.22.1) - 2022-07-09
|
||||
|
||||
### 优化
|
||||
|
||||
- 歌单列表添加歌单内歌曲数量显示,注:目前只有kw、mg、wy、tx(部分)源支持显示
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复处于不支持的源时,歌单、排行榜的右键下载菜单没有禁用的问题
|
||||
- 修复若桌面歌词窗口与主窗口重叠时,鼠标划过重叠区域鼠标会闪烁的问题,注:此修复只对未启用“鼠标移入歌词区域时降低歌词透明度”时有效
|
||||
- 修复tx源搜索失效的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 升级Electron到 v17.4.10
|
||||
|
||||
## [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
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增设置-播放设置-显示歌词罗马音,默认关闭,注:目前只有网易源能获取到罗马音歌词(得益于 Binaryify/NeteaseCloudMusicApi/pull/1523),如果你知道其他源的歌词罗马音获取方式,欢迎PR或开issue交流!
|
||||
|
||||
### 优化
|
||||
|
||||
- 同时删除一首歌以上时将需要二次确认删除
|
||||
- 禁用透明窗口时右侧不再偏移5px距离(在win7、Ubuntu等系统上测试发现不偏移也不影响滚动条的拖动了)
|
||||
- 删除未下载完成的任务时,只同时尝试删除已有下载进度的本地文件
|
||||
- 在全屏状态下使用`Esc`键可以退出全屏(#827)
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复某些情况下歌曲播放出错时不会自动切歌的问题
|
||||
- 修复关闭“显示切换动画”设置后,在应用启动时该设置没有被应用的问题
|
||||
- 修复原始歌词存在偏移时,歌词偏移设置的重置未按预期工作的问题
|
||||
- 修复长度大于一行的歌词在使用歌词调整播放进度时的时间不准问题
|
||||
- 修复潜在歌单更新失败的问题
|
||||
|
||||
### 文档
|
||||
|
||||
- 将歌曲添加“稍后播放”后,它们会被放在一个优先级最高的特殊队列中,点击“下一曲”时会消耗该队列中的歌曲,并且无法通过“上一曲”功能播放该队列的上一首歌曲
|
||||
- 在切歌时若不是通过“上一曲”、“下一曲”功能切歌(例如直接点击“排行榜列表”、“我的列表”中的歌曲切歌),“稍后播放”队列将会被清空
|
||||
|
||||
## [1.20.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.19.0...v1.20.0) - 2022-04-17
|
||||
|
||||
特别说明:Scheme URL其实是支持Linux系统的,但好像需要deb之类的安装包创建出`.desktop`文件才行。
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增播放详情页歌词右键菜单,原来设置-播放详情页设置的字体重置已迁移到此菜单内
|
||||
- 新增歌词偏移设置,可以在播放详情页歌词右键菜单中使用
|
||||
- 新增设置-播放设置-播放错误时自动切换歌曲设置,默认开启(原来的行为),若你不想在遇到音频加载失败、url获取失败等错误时自动切歌可以关闭此设置
|
||||
- 新增设置-桌面歌词设置-自动刷新歌词置顶(当歌词置顶后仍被某些程序遮挡时可尝试启用此设置)
|
||||
- 新增列表更新管理,可以在鼠标移入“我的列表”标题时出现的按钮中进入,这可以用来设置启动软件时需要自动从原平台更新的列表
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化播放详情页背景显示,现在有背景图片的主题可以在播放详情页显示它的图片了
|
||||
- 播放详情页在全屏状态下仍会显示退出播放详情页按钮,同时在其旁边添加退出全屏按钮
|
||||
- 播放详情页在全屏状态下鼠标在空白处静止不动3秒后自动将其隐藏
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复Linux无法全屏的问题
|
||||
- 修复播放下载列表的歌曲时,使用Windows任务栏缩略图工具栏控制按钮的收藏按钮收藏歌曲时的异常问题
|
||||
- 修复启用搜索历史但不启用热门搜索时,搜索历史不显示的问题
|
||||
- 修复窗口尺寸设置对应的字体大小在启动后不生效的问题
|
||||
- 修复wy源搜索某些歌曲时第一页之后的歌曲无法加载的问题
|
||||
- 修复使用Scheme URL搜索歌曲时,不会自动关闭播放详情页(若处于打开状态)的问题
|
||||
- 修复换源失败时的处理问题
|
||||
- 修复启用代理时,https请求可能被挂起或被转为http的问题
|
||||
- 修复正在下载的歌曲暂停任务后,再开始会导致程序卡死的问题
|
||||
|
||||
### 变更
|
||||
|
||||
- 播放详情页的任意地方右键双击隐藏详情页的行为,“任意区域”改为在“非歌词区域”
|
||||
|
||||
### 移除
|
||||
|
||||
- 移除设置-播放详情页设置-歌词字体重置,此设置项已迁移到播放详情页的歌词菜单中
|
||||
- 移除播放详情页使用+-快捷键调整字体大小的功能,改用歌词右键菜单的字体大小调整功能
|
||||
|
||||
## [1.19.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.18.0...v1.19.0) - 2022-03-20
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增对播放详情页歌词大小、是否缩放、对齐方式的设置,可以去设置-播放详情页设置查看
|
||||
- 新增播放详情页通过歌词调整播放进度,默认关闭,需要到设置-播放详情页设置开启,开启后在播放详情页拖动歌词时将会出现跳转当前行歌词播放的按钮
|
||||
- 新增全屏状态,按F11可以进入、退出全屏状态,由于全屏时会隐藏控制栏按钮,所以需要使用鼠标右键双击(详情页的任意地方都可以)来关闭播放详情页
|
||||
- 新增动态主题“道法自然”,你可以预先设置一个亮色主题及暗色主题,此后将根据系统的亮、暗主题色自动切换为你预先设置的相应主题。注:鼠标 右击 此主题项即可打开亮、暗色主题设置窗口。
|
||||
- 新增对kw源卡拉OK歌词的支持
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化Windows任务栏缩略图工具栏控制按钮在浅色任务栏下的显示效果
|
||||
- 添加音频可视化与音频输出设备冲突的提示
|
||||
- 优化歌词的播放偏移
|
||||
- 优化托盘菜单操作(#686)
|
||||
- 优化播放下载列表时的切歌性能
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复“当前的声音输出设备被改变时暂停播放歌曲”设置无效的问题
|
||||
- 修复桌面歌词没有处理停止播放状态的问题
|
||||
- 修复AppImage包无法运行的问题
|
||||
- 修复Windows任务栏缩略图工具栏控制按钮的歌曲收藏按钮状态更新问题
|
||||
- 修复使用链接导入的歌单无法在我的列表打开原歌单详情页的问题
|
||||
- 修复播放下载列表的歌曲时增删下载任务导致正在的歌曲序号改变时,不会更新到新增序号的问题
|
||||
|
||||
### 文档
|
||||
|
||||
添加LX中定义的快捷操作汇总说明到常见问题中,这是目前可用的鼠标、键盘快捷操作,它们都可以在更新日志中找到
|
||||
|
||||
- 鼠标右击播放栏的歌曲图片封面可以定位当前播放的歌曲
|
||||
- 鼠标右击播放栏进度条上的LRC按钮可以锁定/解锁桌面歌词
|
||||
- 歌曲搜索框、歌单链接输入框内鼠标右击可以将当前剪贴板上的文字粘贴到输入框内
|
||||
- 鼠标右击搜索界面中的单条搜索历史可以将其移除
|
||||
- 歌曲列表内的文字在选中后,鼠标右击可以复制已选中的文字,此功能只对搜索、歌单、排行榜、我的列表中的列表有效
|
||||
- 鼠标在播放详情页内右键双击可以关闭播放详情页
|
||||
- 鼠标左击播放栏上的歌曲名字可以将它复制
|
||||
- 鼠标右击“道法自然(英文Auto)”主题可以打开亮、暗主题设置窗口
|
||||
- 歌曲搜索框的候选内容可以用键盘上下方向键选择,按回车键搜索已选内容
|
||||
- 在歌单详情页按退格键可以返回歌单列表
|
||||
- 歌曲列表中可以使用Ctrl、Shift键进行多选,这类似Windows下的文件选择,详情看常见问题列表多选部分
|
||||
- 在我的列表内可以使用Ctrl+f键打开搜索框进行列表内歌曲搜索,搜索框按Esc键可以关闭搜索框,搜索框内按上下方向键可以选择歌曲,按回车键跳转到已选歌曲,按Ctrl+回车可以跳转并播放已选歌曲
|
||||
- 在我的列表按住Ctrl键可以进入列表拖动模式,此时可以用鼠标拖动列表调整列表的位置
|
||||
- 编辑列表名时按Esc键可以取消编辑
|
||||
- 按F11可以进入、退出全屏状态
|
||||
|
||||
## [1.18.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.17.1...v1.18.0) - 2022-02-26
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增“双击列表里的歌曲时自动切换到当前列表播放”设置,此功能仅对歌单、排行榜有效,默认关闭
|
||||
- 新增打开收藏的在线列表的对应平台详情页功能,可以在我的列表-列表右键菜单中使用
|
||||
- 新增定时暂停播放功能,由于此功能大多数人可能不常用,所以将其放在设置-基本设置中
|
||||
- 新增任务栏缩略图工具栏控制按钮(此功能仅在Windows平台可用),按钮分别为收藏/取消收藏(将歌曲添加到“我的收藏”列表)、上一曲、播放/暂停、下一曲
|
||||
- 新增设置-基本设置-软件字体设置,此设置可用于设置主界面的字体(已知的问题:Windows 7 下可能会出现字体列表为空的情况,这是当前系统的 Powershell 版本小于5.1导致的,请自行尝试看常见解决)
|
||||
- 新增Scheme URL对音乐搜索的调用支持,详情看常见问题-Scheme URL支持
|
||||
- 新增Scheme URL以url传参的方式调用,详情看常见问题-Scheme URL支持
|
||||
- 自定义源新增更新弹窗方法,同时自定义源管理新增是否允许源显示更新弹窗设置(出于防止滥用考虑),当源作者想要通知用户源已更新时,可以调用此方法弹窗告诉用户,调用说明看常见问题-自定义源部分
|
||||
|
||||
### 优化
|
||||
|
||||
- 过滤tx源某些不支持播放的歌曲,解决播放此类内容会导致意外的问题
|
||||
- 把歌曲的热门评论与最新评论拆分成两个列表显示
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复排行榜名字右击菜单的播放功能在播放非激活的列表时的列表获取问题
|
||||
- 修复修改列表名时无法使用`Ctrl`键的问题
|
||||
- 修复wy源某些歌曲获取歌词翻译的问题处理
|
||||
- 修复下载功能的歌词换源时会进入死循环的问题
|
||||
- 修复某些歌曲无法下载的问题
|
||||
- 修复windows平台下软件目录存在`portable`文件夹时,仍会创建`C:\Users\<user>\AppData\Roaming\lx-music-desktop\Dictionaries\en-US-9-0.bdic`文件的问题,现在不会再创建文件,但仍会创建空目录(Electron的问题,目前暂无解决方法)
|
||||
- 修复播放器的停止逻辑问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新electron到v13.6.9
|
||||
|
||||
## [1.17.1](https://github.com/lyswhut/lx-music-desktop/compare/v1.17.0...v1.17.1) - 2022-01-28
|
||||
|
||||
### 优化
|
||||
|
||||
73
FAQ.md
73
FAQ.md
@@ -1,11 +1,45 @@
|
||||
# lx-music-desktop 常见问题
|
||||
|
||||
本文档已迁移到:<https://lyswhut.github.io/lx-music-doc/desktop/faq>
|
||||
|
||||
在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题!
|
||||
|
||||
## ~~软件为什么没有桌面歌词与自定义列表功能~~
|
||||
|
||||
洛雪音乐的最初定位不是作为播放器开发的,它主要用于**查找歌曲**,软件的播放功能仅用于试听,不建议用作为常用播放器使用。
|
||||
|
||||
## 音乐播放列表机制
|
||||
|
||||
1. 默认情况下,播放搜索列表、歌单列表、排行榜列表的歌曲时会自动将该歌曲添加到“我的列表”的试听列表后再播放,这与手动将歌曲添加到试听列表,再去试听列表找到这首歌点播放是等价的
|
||||
2. 如果你想要播放多首歌曲,需要使用多选功能(若不知道如何多选请看常见问题)多选后,将这些歌曲添加到“我的列表”播放,或使用稍后播放功能播放
|
||||
3. 第2条适用于搜索列表、歌单列表、排行榜列表、我的列表中的歌曲
|
||||
4. 对于歌单详情列表,除了可以使用第2条的方式播放外,你可以点击详情页上面的播放按钮临时播放当前歌单,或点击收藏将当前歌单收藏到“我的列表”后再去播放
|
||||
5. 对于排行榜详情列表,除了可以使用第2条的方式播放外,你可以在右击排行榜名字后弹出的菜单中,播放或收藏整个排行榜,这与第四条的歌单中的播放、与收藏按钮功能一致
|
||||
6. v1.18.0及之后新增了“双击列表里的歌曲时自动切换到当前列表播放”设置,默认关闭,此功能仅对歌单、排行榜有效
|
||||
7. 将歌曲添加“稍后播放”后,它们会被放在一个优先级最高的特殊队列中,点击“下一曲”时会消耗该队列中的歌曲,并且无法通过“上一曲”功能播放该队列的上一首歌曲
|
||||
8. 在切歌时若不是通过“上一曲”、“下一曲”功能切歌(例如直接点击“排行榜列表”、“我的列表”中的歌曲切歌),“稍后播放”队列将会被清空
|
||||
|
||||
## 可用的鼠标、键盘快捷操作
|
||||
|
||||
- 鼠标右击播放栏的歌曲图片封面可以定位当前播放的歌曲
|
||||
- 鼠标右击播放栏进度条上的`LRC`按钮可以锁定/解锁桌面歌词
|
||||
- 歌曲搜索框、歌单链接输入框内鼠标右击可以将当前剪贴板上的文字粘贴到输入框内
|
||||
- 鼠标右击搜索界面中的单条搜索历史可以将其移除
|
||||
- 歌曲列表内的文字在选中后,鼠标右击可以复制已选中的文字,此功能只对搜索、歌单、排行榜、我的列表中的列表有效
|
||||
- 鼠标在播放详情页内右键双击可以关闭播放详情页
|
||||
- 鼠标左击播放栏上的歌曲名字可以将它复制
|
||||
- 鼠标右击设置-主题设置的“道法自然(英文Auto)”主题可以打开亮、暗主题设置窗口
|
||||
- 歌曲搜索框的候选内容可以用键盘上下方向键选择,按回车键搜索已选内容
|
||||
- 在歌单详情页按退格键可以返回歌单列表
|
||||
- 歌曲列表中可以使用`Ctrl`、`Shift`键进行多选,这类似Windows下的文件选择,详情看常见问题列表多选部分
|
||||
- 在我的列表内可以使用`Ctrl + f`键打开搜索框进行列表内歌曲搜索,搜索框按`Esc`键可以关闭搜索框,搜索框内按上下方向键可以选择歌曲,按`回车`键跳转到已选歌曲,按`Ctrl + 回车`可以跳转并播放已选歌曲
|
||||
- 在我的列表按住`Ctrl`键可以进入列表拖动模式,此时可以用鼠标拖动列表调整列表的位置
|
||||
- 编辑列表名时按`Esc`键可以取消编辑
|
||||
- 按`F11`可以进入、退出全屏状态(v1.19.0新增)
|
||||
- 在歌曲添加弹窗中,若按住`Ctrl`键后再点击列表名,将不会自动关闭添加窗口,这对想要将同一首(一批)歌曲添加到多个列表时会很有用(v1.22.0新增)
|
||||
|
||||
注:在macOS上`Ctrl`键对应`Command`键
|
||||
|
||||
## 歌曲无法试听与下载
|
||||
|
||||
### 所有歌曲都提示 `请求异常😮,可以多试几次,若还是不行就换一首吧。。。`
|
||||
@@ -40,6 +74,16 @@
|
||||
1. 将DNS改成自动获取试试
|
||||
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`用于快速全选。
|
||||
@@ -83,7 +127,7 @@
|
||||
|
||||
这些浏览器打开此窗口时界面可能是中文也可能是英文,英文的话按括号里的来
|
||||
|
||||
1. 点击窗口顶部`应用程序(application)`
|
||||
1. 点击窗口顶部`应用程序(application)`(若找不到此选项,则可能是被折叠起来了,看看顶部菜单的`>>`)
|
||||
2. 展开左侧 `Cookies`
|
||||
3. 点击 `https://music.163.com`
|
||||
4. 在右侧窗口找到 `名称(Name)` 为 `MUSIC_U` 的这行,这行的第二列(`值(Value)`)内的那串内容就是`token`,双击它进入编辑状态,然后按`ctrl + c`键就可以将它复制
|
||||
@@ -101,6 +145,9 @@
|
||||
|
||||
需要注意的是:这将会覆盖本地的目标列表,歌曲将被替换成最新的在线列表。
|
||||
|
||||
## 调整我的列表的列表顺序
|
||||
|
||||
按住Ctrl键(Mac上对应Command键)的时候将进入“拖动模式”,此时可以拖动列表的位置来调整顺序。
|
||||
|
||||
## 同步功能的使用(实验性,首次使用前建议先备份一次列表)
|
||||
|
||||
@@ -133,7 +180,7 @@
|
||||
|
||||
### Windows 7 下界面异常
|
||||
|
||||
由于软件默认使用了透明窗口,根据Electron官方文档的[说明](https://electronjs.org/docs/api/frameless-window#%E5%B1%80%E9%99%90%E6%80%A7):
|
||||
由于软件默认使用了透明窗口,根据Electron官方文档的[说明](https://www.electronjs.org/docs/latest/tutorial/window-customization#limitations):
|
||||
> 在 windows 操作系统上, 当 DWM 被禁用时, 透明窗口将无法工作。
|
||||
|
||||
因此,当 win7 没有使用**Aero**主题时界面将会显示异常,开启AERO的方法请自行百度:`win7开启Aero效果`(开启后可看到任务栏变透明)。<br>
|
||||
@@ -304,17 +351,34 @@ Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看上面的
|
||||
以下是目前可用的Scheme URL调用方式:
|
||||
|
||||
- URL统一以`lxmusic://`开头
|
||||
- 此技术目前只支持 Windows、Mac系统
|
||||
- URL传参以经过URL编码的JSON数据传参,例:`lxmusic://music/play?data=xxxx`,其中`xxxx`为经过URL编码后的JSON数据
|
||||
- 若无特别说明,源的可用值为:`kw/kg/tx/wy/mg`
|
||||
- 若无特别说明,音质的可用值为:`128k/320k/flac/flac32bit`
|
||||
|
||||
目前支持两种传参方式:
|
||||
|
||||
- 通过`data`传参,以经过URL编码的JSON数据传参,例:`lxmusic://music/play?data=xxxx`,其中`xxxx`为经过URL编码后的JSON数据,支持复杂的参数调用
|
||||
- 通过`URL`传参,适用于简单传参的调用,不需要转成JSON格式,例:`lxmusic://music/search/xxxx`,但仍然需要对数据进行URL编码,只适应于简单参数调用(v1.18.0新增)
|
||||
|
||||
### `data`方式传参
|
||||
|
||||
以经过URL编码的JSON数据传参,例:`lxmusic://music/play?data=xxxx`,其中`xxxx`为经过URL编码后的JSON数据,JSON数据内容取决于下表的参数部分
|
||||
|
||||
| 描述 | URL | 参数
|
||||
| --- | --- | ---
|
||||
| 打开歌单 | `songlist/open` | `source<String>`(源,必须)<br>`id<String/Number>`(歌单ID,可选)<br>`url<String>`(歌单URL,可选)其中ID与URL必需传一个
|
||||
| 播放歌单 | `songlist/play` | `source<String>`(源,必须)<br>`id<String/Number>`(歌单ID,可选)<br>`url<String>`(歌单URL,可选)其中`id`与`url`必需传一个<br>`index<Number>`(播放第几首歌,可选,从0开始)
|
||||
| 搜索歌曲 | `music/search` | `keywords<String/Number>`(要搜索的内容,必须)<br>`source<String>`(源,可选)
|
||||
| 播放歌曲 | `music/play` | `name<String>`(歌曲名,必传)<br>`singer<String>`(艺术家名,必传)<br>`source<String>`(源,必传)<br>`songmid<String/Number>`(歌曲ID,必传)<br>`img<String>`(歌曲图片链接,选传)<br>`albumId<String/Number>`(歌曲专辑ID,选传)<br>`interval<String>`(格式化后的歌曲时长,选传,例:`03:55`)<br>`albumName<String>`(歌曲专辑名称,选传)<br>`types<Object>`(歌曲可用音质数组,必传,<br>数组格式:`[{"type": "<音质>", size: "<格式化后的文件大小,选传>", hash: "<kg源必传>"}]`,<br>例:`[{"type": "128k", size: "3.56M"}, {"type": "320k", size: null}]`)<br><br>以下为平台特定参数:<br>`hash<String>`(歌曲hash,kg源必传)<br>`strMediaMid<String>`(歌曲strMediaMid,tx源必传)<br>`albumMid<String>`(歌曲albumMid,tx源专用,选传)<br>`copyrightId<String>`(歌曲copyrightId,mg源必传)<br>`lrcUrl<String>`(歌曲lrcUrl,mg源专用,选传)
|
||||
|
||||
### `URL`方式传参
|
||||
|
||||
由于URL传参只适用于简单传参场景,所以目前只支持以下功能的调用:
|
||||
|
||||
| 描述 | URL | 参数
|
||||
| --- | --- | ---
|
||||
| 搜索歌曲 | `music/search/{source}/{keywords}` | `source`(源,可选)<br>`keywords`(要搜索的内容,必须)<br>例:`music/search/kw/xxx`、`music/search/xxx`
|
||||
| 打开歌单 | `songlist/open/{source}/{id/url}` | `source`(源,必须)<br>`id/url`(歌单ID或歌单URL,必须)<br>例:`songlist/open/kw/123456`
|
||||
|
||||
## 自定义源脚本编写说明
|
||||
|
||||
文件请使用UTF-8编码格式编写,脚本所用编程语言为JavaScript,可以使用ES6+语法,脚本与应用的交互是使用类似事件收发的方式进行,这是一个基本的脚本例子:
|
||||
@@ -427,6 +491,7 @@ send(EVENT_NAMES.inited, {
|
||||
| --- | ---
|
||||
| `inited` | 脚本初始化完成后发送给应用的事件名,发送该事件时需要传入以下信息:`{status, sources, openDevTools}`<br>`status`:初始化结果(`true`成功,`false`失败)<br>`openDevTools`:是否打开DevTools,此选项可用于开发脚本时的调试<br>`sources`:支持的源信息对象,<br>`sources[kw/kg/tx/wy/mg].name`:源的名字(目前非必须)<br>`sources[kw/kg/tx/wy/mg].type`:源类型,目前固定值需为`music`<br>`sources[kw/kg/tx/wy/mg].actions`:支持的actions,由于目前只支持`musicUrl`,所以固定传`['musicUrl']`即可<br>`sources[kw/kg/tx/wy/mg].qualitys`:该源支持的音质列表,有效的值为`['128k', '320k', 'flac']`,该字段用于控制应用可用的音质类型
|
||||
| `request` | 应用API请求事件名,回调入参:`handler({ source, action, info})`,回调必须返回`Promise`对象<br>`source`:音乐源,可能的值取决于初始化时传入的`sources`对象的源key值<br>`info`:请求附加信息,内容根据`action`变化<br>`action`:请求操作类型,目前只有`musicUrl`,即获取音乐URL链接,需要在 Promise 返回歌曲 url,`info`的结构:`{type, musicInfo}`,`info.type`:音乐质量,可能的值有`128k` / `320k` / `flac`(取决于初始化时对应源传入的`qualitys`值中的一个),`info.musicInfo`:音乐信息对象,里面有音乐ID、名字等信息
|
||||
| `updateAlert` | 显示源更新弹窗,发送该事件时的参数:`{log, updateUrl}`<br>`log`:更新日志,必传,字符串类型,内容可以使用`\n`换行,最大长度1024,超过此长度后将被截取超出的部分<br>`updateUrl`:更新地址,用于引导用户去该地址更新源,选传,需为http协议的url地址,最大长度1024<br>此事件每次运行脚本只能调用一次(源版本v1.2.0新增)<br>例子:`lx.send(lx.EVENT_NAMES.updateAlert, { log: 'hello world', updateUrl: 'https://xxx.com' })`
|
||||
|
||||
|
||||
#### `window.lx.on`
|
||||
|
||||
15
README.md
15
README.md
@@ -36,7 +36,7 @@
|
||||
|
||||
所用技术栈:
|
||||
|
||||
- Electron 13
|
||||
- Electron 17
|
||||
- Vue 3
|
||||
|
||||
已支持的平台:
|
||||
@@ -48,13 +48,16 @@
|
||||
软件变化请查看:[更新日志](https://github.com/lyswhut/lx-music-desktop/blob/master/CHANGELOG.md)<br>
|
||||
软件下载请转到:[发布页面](https://github.com/lyswhut/lx-music-desktop/releases)<br>
|
||||
或者到网盘下载(网盘内有MAC、windows版):`https://www.lanzoui.com/b0bf2cfa/` 密码:`glqw`(若链接无法打开请百度:蓝奏云链接打不开)<br>
|
||||
使用常见问题请转至:[常见问题](https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md)
|
||||
使用常见问题请转至:[常见问题](https://lyswhut.github.io/lx-music-doc/desktop/faq)<br>
|
||||
移动版项目地址:<https://github.com/lyswhut/lx-music-mobile>
|
||||
|
||||
#### Scheme URL支持
|
||||
|
||||
从v1.17.0起支持 Scheme URL,可以使用此功能从浏览器等场景下调用LX Music,我们开发了一个[油猴脚本](https://github.com/lyswhut/lx-music-script#readme)配套使用,<br>
|
||||
脚本安装地址:<https://greasyfork.org/zh-CN/scripts/438148><br>
|
||||
|
||||
若你想自己调用LX Music,可以看[Scheme URL支持](https://lyswhut.github.io/lx-music-doc/desktop/scheme-url)
|
||||
|
||||
#### 启动参数
|
||||
|
||||
目前软件已支持的启动参数如下:
|
||||
@@ -67,7 +70,7 @@
|
||||
- `-dt` 以非透明模式启动(Disable Transparent)
|
||||
- `-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)
|
||||
|
||||
#### 数据存储路径
|
||||
|
||||
@@ -75,13 +78,13 @@
|
||||
|
||||
- Windows:`%APPDATA%/lx-music-desktop`
|
||||
- Linux:`$XDG_CONFIG_HOME/lx-music-desktop` 或 `~/.config/lx-music-desktop`
|
||||
- macOS:`~/Library/Application/lx-music-desktop`
|
||||
- macOS:`~/Library/Application Support/lx-music-desktop`
|
||||
|
||||
在Windows平台下,若程序目录下存在`portable`目录,则自动使用此目录作为数据存储目录(v1.17.0新增)。
|
||||
|
||||
### 源码使用方法
|
||||
|
||||
环境要求:Node.js 14+
|
||||
环境要求:Node.js 16+
|
||||
|
||||
```bash
|
||||
# 开发模式
|
||||
@@ -107,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>
|
||||
|
||||
### 项目协议
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
path: path.join(__dirname, '../../dist/electron'),
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
@@ -25,9 +25,6 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 300000,
|
||||
},
|
||||
plugins: [
|
||||
new ESLintPlugin(),
|
||||
],
|
||||
|
||||
@@ -19,4 +19,8 @@ module.exports = merge(baseConfig, {
|
||||
__userApi: `"${path.join(__dirname, '../../src/main/modules/userApi').replace(/\\/g, '\\\\')}"`,
|
||||
}),
|
||||
],
|
||||
performance: {
|
||||
maxEntrypointSize: 1024 * 1024 * 50,
|
||||
maxAssetSize: 1024 * 1024 * 30,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -26,11 +26,11 @@ module.exports = merge(baseConfig, {
|
||||
patterns: [
|
||||
{
|
||||
from: path.join(__dirname, '../../src/main/modules/userApi/renderer'),
|
||||
to: path.join(__dirname, '../../dist/electron/userApi/renderer'),
|
||||
to: path.join(__dirname, '../../dist/userApi/renderer'),
|
||||
},
|
||||
{
|
||||
from: path.join(__dirname, '../../src/main/modules/userApi/rendererEvent/name.js'),
|
||||
to: path.join(__dirname, '../../dist/electron/userApi/rendererEvent/name.js'),
|
||||
to: path.join(__dirname, '../../dist/userApi/rendererEvent/name.js'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
@@ -40,6 +40,10 @@ module.exports = merge(baseConfig, {
|
||||
},
|
||||
}),
|
||||
],
|
||||
performance: {
|
||||
maxEntrypointSize: 1024 * 1024 * 10,
|
||||
maxAssetSize: 1024 * 1024 * 20,
|
||||
},
|
||||
optimization: {
|
||||
minimize: false,
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ const okayLog = chalk.bgGreen.white(' OKAY ') + ' '
|
||||
|
||||
|
||||
function build() {
|
||||
del.sync(['dist/electron/**', 'build/**'])
|
||||
del.sync(['dist/**', 'build/**'])
|
||||
|
||||
const spinners = new Spinnies({ color: 'blue' })
|
||||
spinners.add('main', { text: 'main building' })
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = {
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
path: path.join(__dirname, '../../dist/electron'),
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
publicPath: 'auto',
|
||||
},
|
||||
resolve: {
|
||||
@@ -127,9 +127,6 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 300000,
|
||||
},
|
||||
plugins: [
|
||||
new HTMLPlugin({
|
||||
filename: 'lyric.html',
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
const path = require('path')
|
||||
// const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
|
||||
const TerserPlugin = require('terser-webpack-plugin')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const { merge } = require('webpack-merge')
|
||||
|
||||
const baseConfig = require('./webpack.config.base')
|
||||
@@ -20,14 +19,6 @@ module.exports = merge(baseConfig, {
|
||||
...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)),
|
||||
],
|
||||
plugins: [
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.join(__dirname, '../../src/static'),
|
||||
to: path.join(__dirname, '../../dist/electron/static'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"',
|
||||
@@ -44,6 +35,8 @@ module.exports = merge(baseConfig, {
|
||||
],
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 1024 * 1024 * 10,
|
||||
maxAssetSize: 1024 * 1024 * 20,
|
||||
hints: 'warning',
|
||||
},
|
||||
node: {
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = {
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
path: path.join(__dirname, '../../dist/electron'),
|
||||
path: path.join(__dirname, '../../dist'),
|
||||
publicPath: 'auto',
|
||||
},
|
||||
resolve: {
|
||||
@@ -127,9 +127,6 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 300000,
|
||||
},
|
||||
plugins: [
|
||||
new HTMLPlugin({
|
||||
filename: 'index.html',
|
||||
|
||||
@@ -14,6 +14,7 @@ module.exports = merge(baseConfig, {
|
||||
NODE_ENV: '"development"',
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
||||
},
|
||||
ENVIRONMENT: 'process.env',
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: 'false',
|
||||
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||
|
||||
@@ -23,7 +23,7 @@ module.exports = merge(baseConfig, {
|
||||
patterns: [
|
||||
{
|
||||
from: path.join(__dirname, '../../src/static'),
|
||||
to: path.join(__dirname, '../../dist/electron/static'),
|
||||
to: path.join(__dirname, '../../dist/static'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
@@ -31,6 +31,7 @@ module.exports = merge(baseConfig, {
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"',
|
||||
},
|
||||
ENVIRONMENT: 'process.env',
|
||||
__VUE_OPTIONS_API__: 'true',
|
||||
__VUE_PROD_DEVTOOLS__: 'false',
|
||||
}),
|
||||
@@ -43,6 +44,8 @@ module.exports = merge(baseConfig, {
|
||||
],
|
||||
},
|
||||
performance: {
|
||||
maxEntrypointSize: 1024 * 1024 * 10,
|
||||
maxAssetSize: 1024 * 1024 * 20,
|
||||
hints: 'warning',
|
||||
},
|
||||
node: {
|
||||
|
||||
@@ -151,7 +151,7 @@ function startElectron() {
|
||||
let args = [
|
||||
'--inspect=5858',
|
||||
// 'NODE_ENV=development',
|
||||
path.join(__dirname, '../dist/electron/main.js'),
|
||||
path.join(__dirname, '../dist/main.js'),
|
||||
]
|
||||
|
||||
// detect yarn or npm and process commandline args accordingly
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@main/*": ["src/main/*"],
|
||||
"@renderer/*": ["src/renderer/*"],
|
||||
"@lyric/*": ["src/renderer-lyric/*"],
|
||||
"@static/*": ["src/static/*"],
|
||||
"@common/*": ["src/common/*"],
|
||||
}
|
||||
},
|
||||
},
|
||||
"vueCompilerOptions": {
|
||||
"experimentalDisableTemplateSupport": true
|
||||
},
|
||||
"exclude": ["node_modules", "build", "dist"]
|
||||
}
|
||||
|
||||
25127
package-lock.json
generated
25127
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
133
package.json
133
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "lx-music-desktop",
|
||||
"version": "1.17.1",
|
||||
"version": "1.22.2",
|
||||
"description": "一个免费的音乐查找助手",
|
||||
"main": "./dist/electron/main.js",
|
||||
"main": "./dist/main.js",
|
||||
"productName": "lx-music-desktop",
|
||||
"scripts": {
|
||||
"pack": "node build-config/pack.js && npm run pack:win:setup:x64",
|
||||
@@ -57,7 +57,7 @@
|
||||
"publish:linux:rpm": "cross-env ARCH=x64 electron-builder -l=rpm --x64 -p onTagOrDraft",
|
||||
"publish:linux:pacman": "cross-env ARCH=x64 electron-builder -l=pacman --x64 -p onTagOrDraft",
|
||||
"dev": "node build-config/runner-dev.js",
|
||||
"clean:electron": "rimraf dist/electron",
|
||||
"clean:electron": "rimraf dist",
|
||||
"clean": "rimraf dist && rimraf build",
|
||||
"build:src": "node build-config/pack.js",
|
||||
"build:main": "cross-env NODE_ENV=production webpack --config build-config/main/webpack.config.prod.js --progress",
|
||||
@@ -70,10 +70,11 @@
|
||||
"up": "cross-env ELECTRON_GET_USE_PROXY=true GLOBAL_AGENT_HTTPS_PROXY=http://localhost:1081 npm i"
|
||||
},
|
||||
"browserslist": [
|
||||
"Electron 13.6.8"
|
||||
"Electron 15.5.7"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 16",
|
||||
"npm": ">=8.5.2"
|
||||
},
|
||||
"build": {
|
||||
"appId": "cn.toside.music.desktop",
|
||||
@@ -88,7 +89,7 @@
|
||||
"output": "./build"
|
||||
},
|
||||
"files": [
|
||||
"dist/electron/**/*"
|
||||
"dist/**/*"
|
||||
],
|
||||
"asar": {
|
||||
"smartUnpack": false
|
||||
@@ -103,7 +104,11 @@
|
||||
},
|
||||
"mac": {
|
||||
"icon": "./resources/icons/icon.icns",
|
||||
"category": "public.app-category.music"
|
||||
"category": "public.app-category.music",
|
||||
"extendInfo": {
|
||||
"CFBundleName": "lx-music-desktop",
|
||||
"CFBundleDisplayName": "LX Music"
|
||||
}
|
||||
},
|
||||
"linux": {
|
||||
"maintainer": "lyswhut <lyswhut@qq.com>",
|
||||
@@ -173,92 +178,96 @@
|
||||
},
|
||||
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.12",
|
||||
"@babel/eslint-parser": "^7.16.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
||||
"@babel/core": "^7.18.10",
|
||||
"@babel/eslint-parser": "^7.18.9",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-modules-umd": "^7.16.7",
|
||||
"@babel/plugin-transform-runtime": "^7.16.10",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"babel-loader": "^8.2.3",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"browserslist": "^4.19.1",
|
||||
"cfonts": "^2.10.0",
|
||||
"@babel/plugin-transform-modules-umd": "^7.18.6",
|
||||
"@babel/plugin-transform-runtime": "^7.18.10",
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-preset-minify": "^0.5.2",
|
||||
"browserslist": "^4.21.3",
|
||||
"chalk": "^4.1.2",
|
||||
"changelog-parser": "^2.8.0",
|
||||
"copy-webpack-plugin": "^10.2.1",
|
||||
"core-js": "^3.20.3",
|
||||
"changelog-parser": "^2.8.1",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"core-js": "^3.24.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
||||
"del": "^6.0.0",
|
||||
"electron": "^13.6.8",
|
||||
"electron-builder": "^22.11.7",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.0.0",
|
||||
"del": "^6.1.1",
|
||||
"electron": "^15.5.7",
|
||||
"electron-builder": "^23.3.3",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-to-chromium": "^1.4.56",
|
||||
"eslint": "^8.7.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-formatter-friendly": "^7.0.0",
|
||||
"eslint-plugin-html": "^6.2.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"electron-to-chromium": "^1.4.224",
|
||||
"electron-updater": "^5.2.1",
|
||||
"eslint": "^8.22.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-formatter-friendly": "git+https://github.com/lyswhut/eslint-friendly-formatter.git#2170d1320e2fad13615a9dcf229669f0bb473a53",
|
||||
"eslint-plugin-html": "^7.1.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"eslint-plugin-vue": "^8.4.0",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"eslint-webpack-plugin": "^3.2.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^10.2.0",
|
||||
"markdown-it": "^12.3.2",
|
||||
"mini-css-extract-plugin": "^2.5.3",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.0.0",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"node-loader": "^2.0.0",
|
||||
"postcss": "^8.4.5",
|
||||
"postcss-loader": "^6.2.1",
|
||||
"postcss": "^8.4.16",
|
||||
"postcss-loader": "^7.0.1",
|
||||
"postcss-pxtorem": "^6.0.0",
|
||||
"pug": "^3.0.2",
|
||||
"pug-loader": "^2.4.0",
|
||||
"pug-plain-loader": "^1.1.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"spinnies": "^0.5.1",
|
||||
"spinnies": "git+https://github.com/lyswhut/spinnies.git#233305c58694aa3b053e3ab9af9049993f918b9d",
|
||||
"svg-sprite-loader": "^6.0.11",
|
||||
"svg-transform-loader": "^2.0.13",
|
||||
"svgo-loader": "^3.0.0",
|
||||
"terser-webpack-plugin": "^5.3.0",
|
||||
"svgo-loader": "^3.0.1",
|
||||
"terser": "^5.14.2",
|
||||
"terser-webpack-plugin": "^5.3.5",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-loader": "^17.0.0",
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"webpack": "^5.67.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.7.3",
|
||||
"webpack-hot-middleware": "github:lyswhut/webpack-hot-middleware#329c4375134b89d39da23a56a94db651247c74a1",
|
||||
"vue-template-compiler": "^2.7.8",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-server": "^4.10.0",
|
||||
"webpack-hot-middleware": "git+https://github.com/lyswhut/webpack-hot-middleware.git#329c4375134b89d39da23a56a94db651247c74a1",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.6",
|
||||
"crypto-js": "^4.1.1",
|
||||
"electron-log": "^4.4.5",
|
||||
"electron-store": "^8.0.1",
|
||||
"electron-updater": "^4.6.1",
|
||||
"font-list": "github:lyswhut/node-font-list#4edbb1933b49a9bac1eedd63a31da16b487fe57d",
|
||||
"http-terminator": "^3.0.4",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-store": "^8.1.0",
|
||||
"font-list": "git+https://github.com/lyswhut/node-font-list.git#4edbb1933b49a9bac1eedd63a31da16b487fe57d",
|
||||
"http-terminator": "^3.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"image-size": "^1.0.1",
|
||||
"image-size": "^1.0.2",
|
||||
"koa": "^2.13.4",
|
||||
"long": "^5.2.0",
|
||||
"mitt": "^3.0.0",
|
||||
"needle": "^3.0.0",
|
||||
"needle": "^3.1.0",
|
||||
"node-id3": "^0.2.3",
|
||||
"request": "^2.88.2",
|
||||
"socket.io": "^4.4.1",
|
||||
"sortablejs": "^1.14.0",
|
||||
"utf-8-validate": "^5.0.8",
|
||||
"vue": "^3.2.29",
|
||||
"vue-i18n": "^9.2.0-beta.29",
|
||||
"vue-router": "^4.0.12",
|
||||
"socket.io": "^4.5.1",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tunnel": "^0.0.6",
|
||||
"utf-8-validate": "^5.0.9",
|
||||
"vue": "^3.2.37",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.1.3",
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"overrides": {
|
||||
"async": "^2.3.0",
|
||||
"got": "^11.8.5",
|
||||
"svg-sprite-loader": {
|
||||
"postcss": "8.2.13"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
### 优化
|
||||
|
||||
- 优化kw源英文与翻译歌词的匹配
|
||||
- 为tx、kw源添加 Flac 24bit 音质显示,注:由于之前没有记录此音质,所以之前收藏的歌曲信息中不包含它
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复快捷键与默认按键行为冲突的问题,现在若将某些有默认行为的按键(如在列表中上、下箭头、Home、End等键可以使列表滚动)设置为快捷键时,将禁用其默认行为
|
||||
- 修复列表的聚焦问题,现在在列表中使用上、下箭头、空格等键滚动列表时不会导致滚动到一定距离后丢失焦点的问题
|
||||
- 修复无法批量排序歌曲的问题
|
||||
- 修复某些缺失的繁体中文翻译
|
||||
- 修复企鹅音乐搜索失效的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新electron到v13.6.8
|
||||
- 降级electron到v15.5.7
|
||||
|
||||
@@ -9,12 +9,12 @@ const version_bak = JSON.stringify(version, null, 2)
|
||||
const parseChangelog = require('changelog-parser')
|
||||
const changelogPath = jp('../../CHANGELOG.md')
|
||||
|
||||
const md_renderer = markdownStr => new (require('markdown-it'))({
|
||||
html: true,
|
||||
linkify: true,
|
||||
typographer: true,
|
||||
breaks: true,
|
||||
}).render(markdownStr)
|
||||
// const md_renderer = markdownStr => new (require('markdown-it'))({
|
||||
// html: true,
|
||||
// linkify: true,
|
||||
// typographer: true,
|
||||
// breaks: true,
|
||||
// }).render(markdownStr)
|
||||
|
||||
const getPrevVer = () => parseChangelog(changelogPath).then(res => {
|
||||
if (!res.versions.length) throw new Error('CHANGELOG 无法解析到版本号')
|
||||
@@ -28,7 +28,7 @@ const updateChangeLog = async(newVerNum, newChangeLog) => {
|
||||
fs.writeFileSync(changelogPath, changeLog.replace(new RegExp('(## [?0.1.1]?)'), log + '\n$1'), 'utf-8')
|
||||
}
|
||||
|
||||
const renderChangeLog = md => md_renderer(md)
|
||||
// const renderChangeLog = md => md_renderer(md)
|
||||
|
||||
|
||||
module.exports = async newVerNum => {
|
||||
@@ -38,7 +38,7 @@ module.exports = async newVerNum => {
|
||||
newVerNum = verArr.join('.')
|
||||
}
|
||||
const newMDChangeLog = fs.readFileSync(jp('../changeLog.md'), 'utf-8')
|
||||
const newChangeLog = renderChangeLog(newMDChangeLog)
|
||||
// const newChangeLog = renderChangeLog(newMDChangeLog)
|
||||
version.history.unshift({
|
||||
version: version.version,
|
||||
desc: version.desc,
|
||||
@@ -58,7 +58,7 @@ module.exports = async newVerNum => {
|
||||
return {
|
||||
pkg_bak,
|
||||
version_bak,
|
||||
changeLog: newChangeLog,
|
||||
// changeLog: newChangeLog,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 27 KiB |
@@ -106,7 +106,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: '黑纸白字',
|
||||
name: '黑灯瞎火',
|
||||
className: 'black',
|
||||
},
|
||||
{
|
||||
@@ -125,4 +125,6 @@ module.exports = {
|
||||
className: 'happy_new_year',
|
||||
},
|
||||
],
|
||||
themeLights: [0, 1, 2, 3, 4, 10, 5, 6, 11, 12, 7, 8, 9],
|
||||
themeDarks: [13, 7],
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
const defaultSetting = {
|
||||
version: '1.0.48',
|
||||
version: '1.0.59',
|
||||
player: {
|
||||
togglePlayMethod: 'listLoop',
|
||||
highQuality: false,
|
||||
@@ -12,22 +12,36 @@ const defaultSetting = {
|
||||
mediaDeviceId: 'default',
|
||||
isMediaDeviceRemovedStopPlay: false,
|
||||
isShowLyricTranslation: false,
|
||||
isShowLyricRoma: false,
|
||||
isS2t: false, // 是否将歌词从简体转换为繁体
|
||||
isPlayLxlrc: true,
|
||||
isSavePlayTime: false,
|
||||
audioVisualization: false,
|
||||
waitPlayEndStop: true,
|
||||
waitPlayEndStopTime: '',
|
||||
autoSkipOnError: true,
|
||||
},
|
||||
playDetail: {
|
||||
isZoomActiveLrc: true,
|
||||
isShowLyricProgressSetting: false,
|
||||
style: {
|
||||
fontSize: 100,
|
||||
align: 'center',
|
||||
},
|
||||
},
|
||||
desktopLyric: {
|
||||
enable: false,
|
||||
isLock: false,
|
||||
isAlwaysOnTop: false,
|
||||
width: 380,
|
||||
height: 420,
|
||||
isAlwaysOnTopLoop: false,
|
||||
width: 450,
|
||||
height: 300,
|
||||
x: null,
|
||||
y: null,
|
||||
theme: 0,
|
||||
isLockScreen: true,
|
||||
isDelayScroll: true,
|
||||
isHoverHide: false,
|
||||
style: {
|
||||
font: '',
|
||||
fontSize: 120,
|
||||
@@ -36,6 +50,7 @@ const defaultSetting = {
|
||||
},
|
||||
},
|
||||
list: {
|
||||
isClickPlayList: false,
|
||||
isShowAlbumName: true,
|
||||
isShowSource: true,
|
||||
isSaveScrollLocation: true,
|
||||
@@ -94,11 +109,17 @@ const defaultSetting = {
|
||||
port: '23332',
|
||||
},
|
||||
windowSizeId: 2,
|
||||
themeId: 0,
|
||||
startInFullscreen: false,
|
||||
theme: {
|
||||
id: 0,
|
||||
lightId: 0,
|
||||
darkId: 13,
|
||||
},
|
||||
langId: null,
|
||||
sourceId: 'kw',
|
||||
apiSource: 'temp',
|
||||
sourceNameType: 'alias',
|
||||
font: '',
|
||||
isShowAnimation: true,
|
||||
randomAnimate: true,
|
||||
ignoreVersion: null,
|
||||
@@ -112,7 +133,7 @@ const overwriteSetting = {
|
||||
|
||||
// 使用新年皮肤
|
||||
if (new Date().getMonth() < 2) {
|
||||
defaultSetting.themeId = 9
|
||||
defaultSetting.theme.id = 9
|
||||
defaultSetting.desktopLyric.theme = 3
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ const hotKey = {
|
||||
}
|
||||
|
||||
const keyName = {
|
||||
common: names.mainWindow.name,
|
||||
player: names.mainWindow.name,
|
||||
desktop_lyric: names.winLyric.name,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ const names = {
|
||||
close: 'close',
|
||||
min: 'min',
|
||||
max: 'max',
|
||||
fullscreen: 'fullscreen',
|
||||
set_app_name: 'set_app_name',
|
||||
clear_cache: 'clear_cache',
|
||||
get_cache_size: 'get_cache_size',
|
||||
@@ -11,7 +12,11 @@ const names = {
|
||||
clear_env_params_deeplink: 'clear_env_params_deeplink',
|
||||
wait: 'wait',
|
||||
wait_cancel: 'wait_cancel',
|
||||
interval: 'interval',
|
||||
interval_callback: 'interval_callback',
|
||||
interval_cancel: 'interval_cancel',
|
||||
open_dev_tools: 'open_dev_tools',
|
||||
system_theme_change: 'system_theme_change',
|
||||
|
||||
set_music_meta: 'set_music_meta',
|
||||
progress: 'progress',
|
||||
@@ -66,10 +71,18 @@ const names = {
|
||||
request_user_api_cancel: 'request_user_api_cancel',
|
||||
get_user_api_status: 'get_user_api_status',
|
||||
user_api_status: 'user_api_status',
|
||||
user_api_show_update_alert: 'user_api_show_update_alert',
|
||||
user_api_set_allow_update_alert: 'user_api_set_allow_update_alert',
|
||||
|
||||
get_lyric: 'get_lyric',
|
||||
save_lyric: 'save_lyric',
|
||||
clear_lyric: 'clear_lyric',
|
||||
get_lyric_raw: 'get_lyric_raw',
|
||||
save_lyric_raw: 'save_lyric_raw',
|
||||
clear_lyric_raw: 'clear_lyric_raw',
|
||||
get_lyric_edited: 'get_lyric_edited',
|
||||
save_lyric_edited: 'save_lyric_edited',
|
||||
remove_lyric_edited: 'remove_lyric_edited',
|
||||
get_music_url: 'get_music_url',
|
||||
save_music_url: 'save_music_url',
|
||||
clear_music_url: 'clear_music_url',
|
||||
@@ -81,6 +94,9 @@ const names = {
|
||||
sync_action_list: 'sync_action_list',
|
||||
sync_list: 'sync_list',
|
||||
|
||||
taskbar_set_thumbar_buttons: 'taskbar_set_thumbar_buttons',
|
||||
taskbar_set_thumbnail_clip: 'taskbar_set_thumbnail_clip',
|
||||
taskbar_on_thumbar_button_click: 'taskbar_on_thumbar_button_click',
|
||||
},
|
||||
winLyric: {
|
||||
close: 'close',
|
||||
|
||||
@@ -157,11 +157,6 @@ exports.initSetting = isShowErrorAlert => {
|
||||
electronStore_config.set('setting.list.isSaveScrollLocation', scroll.enable)
|
||||
delete setting.list.scroll
|
||||
}
|
||||
|
||||
if (setting.player.isShowLyricTransition != null) { // 修正拼写问题 v1.8.2 及以前
|
||||
setting.player.isShowLyricTranslation = setting.player.isShowLyricTransition
|
||||
delete setting.player.isShowLyricTransition
|
||||
}
|
||||
}
|
||||
|
||||
// 从我的列表分离下载列表 v1.7.0 后
|
||||
@@ -173,6 +168,18 @@ exports.initSetting = isShowErrorAlert => {
|
||||
|
||||
const { version: settingVersion, setting: newSetting } = exports.mergeSetting(setting, electronStore_config.get('version'))
|
||||
|
||||
// 修正拼写问题 v1.8.2 及以前
|
||||
if (newSetting.player.isShowLyricTransition != null) {
|
||||
newSetting.player.isShowLyricTranslation = newSetting.player.isShowLyricTransition
|
||||
delete newSetting.player.isShowLyricTransition
|
||||
}
|
||||
|
||||
// 迁移v1.19.0之前的主题设置
|
||||
if (newSetting.themeId != null) {
|
||||
newSetting.theme.id = newSetting.themeId
|
||||
delete newSetting.themeId
|
||||
}
|
||||
|
||||
// 重置 ^0.18.2 排行榜ID
|
||||
if (!newSetting.leaderboard.tabId.includes('__')) newSetting.leaderboard.tabId = 'kw__16'
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"action": "Manage",
|
||||
"agree": "Accept",
|
||||
"alert_button_text": "All right",
|
||||
"audio_visualization": "Audio visualization (experimental)",
|
||||
"back": "Back",
|
||||
"cancel_button_text": "Cancel",
|
||||
@@ -52,6 +53,7 @@
|
||||
"download__runing": "Downloading",
|
||||
"download__status": "Status",
|
||||
"export": "Export",
|
||||
"fullscreen_exit": "Exit Full Screen",
|
||||
"history_clear": "Clear History",
|
||||
"history_remove": "Right click to remove this entry",
|
||||
"history_search": "History Searches",
|
||||
@@ -93,6 +95,11 @@
|
||||
"list_add__title_first_add": "Add",
|
||||
"list_add__title_first_move": "Move",
|
||||
"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_down": "Descending",
|
||||
"list_sort_modal_by_field": "Sort field",
|
||||
@@ -103,6 +110,10 @@
|
||||
"list_sort_modal_by_type": "Sort categories",
|
||||
"list_sort_modal_by_up": "Ascending",
|
||||
"list_sort_modal_tip_confirm": "Are you sure you want to do this?",
|
||||
"list_update_modal__auto_update": "auto update",
|
||||
"list_update_modal__tips": "💡 The list with \"Automatic Updates\" checked will be automatically updated each time the software is launched",
|
||||
"list_update_modal__title": "List update management",
|
||||
"list_update_modal__update": "Sync",
|
||||
"lists__duplicate": "Duplicate song",
|
||||
"lists__export": "Export",
|
||||
"lists__export_part_desc": "Choose where to save the list file",
|
||||
@@ -114,17 +125,33 @@
|
||||
"lists__new_list_btn": "Create list",
|
||||
"lists__new_list_input": "New list...",
|
||||
"lists__remove": "Remove",
|
||||
"lists__remove music_tip": "Do you really want to remove the selected {len} songs?",
|
||||
"lists__remove_tip": "Do you really want to remove {name}?",
|
||||
"lists__remove_tip_button": "Yes, that's right",
|
||||
"lists__rename": "Rename",
|
||||
"lists__sort_list": "Sort songs",
|
||||
"lists__source_detail": "Playlist Page",
|
||||
"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_title": "Error loading playlist data",
|
||||
"loding_list": "Loading...",
|
||||
"love_list": "Favorites",
|
||||
"lyric__load_error": "Failed to get lyrics",
|
||||
"lyric__select": "Lyric text selection",
|
||||
"lyric_menu__align": "Lyric Alignment",
|
||||
"lyric_menu__align_center": "Centered",
|
||||
"lyric_menu__align_left": "Left",
|
||||
"lyric_menu__lrc_size": "Font size [{size}]",
|
||||
"lyric_menu__offset": "Offset [ {offset}ms ]",
|
||||
"lyric_menu__offset_add_10": "10ms faster",
|
||||
"lyric_menu__offset_add_100": "100ms faster",
|
||||
"lyric_menu__offset_dec_10": "10ms slow down (right click slows down 5ms)",
|
||||
"lyric_menu__offset_dec_100": "slow down by 100ms",
|
||||
"lyric_menu__offset_reset": "Reset",
|
||||
"lyric_menu__size_add": "Increase font size (right click to fine-tune)",
|
||||
"lyric_menu__size_dec": "Decrease font (right click to fine tune)",
|
||||
"lyric_menu__size_reset": "Reset",
|
||||
"min": "Minimize",
|
||||
"music_album": "Album",
|
||||
"music_duplicate": "Duplicate song",
|
||||
@@ -139,9 +166,18 @@
|
||||
"my_list": "Your Library",
|
||||
"no_item": "Nothing's here...",
|
||||
"not_agree": "Not accept",
|
||||
"ok": "OK",
|
||||
"pagination__next": "Next page",
|
||||
"pagination__page": "Page {num}",
|
||||
"pagination__prev": "Previous page",
|
||||
"play_timeout": "Timed pause",
|
||||
"play_timeout_close": "Close",
|
||||
"play_timeout_confirm": "Confirm",
|
||||
"play_timeout_end": "Wait for the song to finish before pausing",
|
||||
"play_timeout_stop": "Cancel timer",
|
||||
"play_timeout_tip": "Pause after {time}",
|
||||
"play_timeout_unit": "minute",
|
||||
"play_timeout_update": "Update timing",
|
||||
"player__add_music_to": "Add the current song to...",
|
||||
"player__buffering": "Buffering...",
|
||||
"player__desktop_lyric_lock": "Right click to lock lyrics",
|
||||
@@ -158,7 +194,7 @@
|
||||
"player__music_singer": "Artist: ",
|
||||
"player__next": "Next",
|
||||
"player__pause": "Pause",
|
||||
"player__pic_tip": "Right click to locate the currently playing song in \"My List\"",
|
||||
"player__pic_tip": "Play details page (right-click to locate the currently playing song in \"My List\")",
|
||||
"player__play": "Play",
|
||||
"player__play_toggle_mode_list": "Play in order",
|
||||
"player__play_toggle_mode_list_loop": "List Loop",
|
||||
@@ -200,6 +236,7 @@
|
||||
"setting__basic_control_btn_position": "Control Button Position",
|
||||
"setting__basic_control_btn_position_left": "Left",
|
||||
"setting__basic_control_btn_position_right": "Right",
|
||||
"setting__basic_font": "Font",
|
||||
"setting__basic_lang": "Language",
|
||||
"setting__basic_lang_title": "The language displayed in the software",
|
||||
"setting__basic_show_animation": "Show switching animation",
|
||||
@@ -215,7 +252,9 @@
|
||||
"setting__basic_sourcename_alias": "Aliases",
|
||||
"setting__basic_sourcename_real": "Original",
|
||||
"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_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_window_size": "Window size",
|
||||
"setting__basic_window_size_big": "Large",
|
||||
@@ -230,10 +269,12 @@
|
||||
"setting__click_open": "Click to open",
|
||||
"setting__desktop_lyric": "Desktop Lyric Settings",
|
||||
"setting__desktop_lyric_always_on_top": "Make the lyrics always above other windows",
|
||||
"setting__desktop_lyric_always_on_top_loop": "Automatically refresh the top of the lyrics (try to enable this setting when the lyrics are still blocked by some programs)",
|
||||
"setting__desktop_lyric_delay_scroll": "Delayed lyrics scroll",
|
||||
"setting__desktop_lyric_enable": "Display lyrics",
|
||||
"setting__desktop_lyric_font": "Lyric font",
|
||||
"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_screen": "It is not allowed to drag the lyrics window out of the main screen",
|
||||
"setting__download": "Download",
|
||||
@@ -284,6 +325,7 @@
|
||||
"setting__list_add_music_location_type": "Position when adding a song to the list",
|
||||
"setting__list_add_music_location_type_bottom": "Bottom",
|
||||
"setting__list_add_music_location_type_top": "Top",
|
||||
"setting__list_click_action": "Automatically switch to the current list when double-clicking a song in the list (only valid for playlists and rankings)",
|
||||
"setting__list_scroll": "Remember the position of the scroll bar of the playlist (only valid for my music classification)",
|
||||
"setting__list_source": "Show song source (only valid for my music category)",
|
||||
"setting__network": "Network",
|
||||
@@ -311,15 +353,31 @@
|
||||
"setting__other_tray_theme_native": "White",
|
||||
"setting__other_tray_theme_origin": "Primary Color",
|
||||
"setting__play": "Play",
|
||||
"setting__play_lyric_lxlrc": "Use Karaoke-style lyrics playback (if supported)",
|
||||
"setting__play_auto_skip_on_error": "Automatically switch songs on playback error",
|
||||
"setting__play_detail": "Play details page settings",
|
||||
"setting__play_detail_align": "Lyric Alignment",
|
||||
"setting__play_detail_align_center": "Centered",
|
||||
"setting__play_detail_align_left": "Left",
|
||||
"setting__play_detail_align_right": "Right",
|
||||
"setting__play_detail_font_size": "Lyrics font size (you can use the keyboard + - adjust the font size on the playback details page)",
|
||||
"setting__play_detail_font_size_current": "Current font size: {size}",
|
||||
"setting__play_detail_font_size_reset": "Reset",
|
||||
"setting__play_detail_font_zoom": "Zoom the currently playing lyrics",
|
||||
"setting__play_detail_lyric_progress": "Allows to adjust playback progress by lyrics",
|
||||
"setting__play_lyric_lxlrc": "Play with karaoke-style lyrics (if available)",
|
||||
"setting__play_lyric_roma": "Show lyrics roman",
|
||||
"setting__play_lyric_s2t": "Convert the playing and downloading lyrics to Traditional Chinese",
|
||||
"setting__play_lyric_transition": "Show lyrics translation",
|
||||
"setting__play_mediaDevice": "Audio output",
|
||||
"setting__play_mediaDevice_remove_stop_play": "Pause the song when the current sound output device is changed",
|
||||
"setting__play_mediaDevice_title": "Select a media device for audio output",
|
||||
"setting__play_quality": "Play 320K quality songs first (if supported)",
|
||||
"setting__play_media_device_error_tip": "This function conflicts with the audio visualization function. You have enabled audio visualization when you started the software this time. This setting is temporarily unavailable. Please restart the software and then modify this setting.",
|
||||
"setting__play_media_device_tip": "This feature conflicts with Audio Visualization, both cannot be enabled at the same time, would you like to turn Audio Visualization off and apply the selected audio output settings?",
|
||||
"setting__play_quality": "Priority playback of 320K quality songs (if available)",
|
||||
"setting__play_save_play_time": "Remember playback progress",
|
||||
"setting__play_task_bar": "Show playing progress on the taskbar",
|
||||
"setting__play_timeout": "Timed pause",
|
||||
"setting__player_audio_visualization_tip": "The custom audio output device will conflict with the audio visualization function. After the audio visualization is enabled, the audio output device will be reset to the default output device. At present, this problem cannot be solved. Do you still want to enable it?",
|
||||
"setting__search": "Search",
|
||||
"setting__search_focus_search_box": "Automatically focus the search box on startup",
|
||||
"setting__search_history": "Search history",
|
||||
@@ -384,6 +442,9 @@
|
||||
"sync__title": "Choose how to synchronize the list with {name}",
|
||||
"tag__high_quality": "HQ",
|
||||
"tag__lossless": "SQ",
|
||||
"tag__lossless_24bit": "24bit",
|
||||
"theme_auto": "Auto",
|
||||
"theme_auto_tip": "Right-click to open the light and dark theme settings window",
|
||||
"theme_black": "Black",
|
||||
"theme_blue": "Blue",
|
||||
"theme_blue2": "Purple Blue",
|
||||
@@ -397,13 +458,21 @@
|
||||
"theme_pink": "Pink",
|
||||
"theme_purple": "Purple",
|
||||
"theme_red": "Red",
|
||||
"theme_selector_modal__dark_title": "dark theme",
|
||||
"theme_selector_modal__light_title": "Bright theme",
|
||||
"theme_selector_modal__title": "Follow system theme settings",
|
||||
"theme_selector_modal__title_tip": "Note: You can set a light theme and a dark theme in advance, and then it will automatically switch to the corresponding theme you set in advance according to the light and dark theme colors of the system.",
|
||||
"theme_yellow": "Yellow",
|
||||
"user_api__allow_show_update_alert": "Allow update popup to show",
|
||||
"user_api__btn_export": "Export",
|
||||
"user_api__btn_import": "Import",
|
||||
"user_api__btn_remove": "Remove",
|
||||
"user_api__import_file": "Select music API script file",
|
||||
"user_api__max_tip": "There can only be a maximum of 20 sources at the same time🤪\nIf you want to continue importing, please remove some old sources to make room",
|
||||
"user_api__noitem": "There is nothing here...😲",
|
||||
"user_api__note": "Tip: Although we have isolated the script's running environment as much as possible, importing scripts containing malicious behaviors may still affect your system. Please import them carefully.",
|
||||
"user_api__readme": "Source writing instructions: ",
|
||||
"user_api__title": "Custom Source Management"
|
||||
"user_api__title": "Custom Source Management",
|
||||
"user_api__update_alert": "Custom source [{name}] found new version:",
|
||||
"user_api__update_alert_open_url": "Open update address"
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ langs.forEach(item => {
|
||||
langList.push({
|
||||
name: item.name,
|
||||
locale: item.locale,
|
||||
alternate: item.alternate,
|
||||
})
|
||||
messages[item.locale] = item.message
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"action": "操作",
|
||||
"agree": "接受",
|
||||
"alert_button_text": "好吧",
|
||||
"audio_visualization": "音频可视化(实验性)",
|
||||
"back": "返回",
|
||||
"cancel_button_text": "我不",
|
||||
@@ -52,6 +53,7 @@
|
||||
"download__runing": "正在下载",
|
||||
"download__status": "状态",
|
||||
"export": "导出",
|
||||
"fullscreen_exit": "退出全屏",
|
||||
"history_clear": "清空搜索历史",
|
||||
"history_remove": "右击移除该历史",
|
||||
"history_search": "历史搜索",
|
||||
@@ -93,6 +95,11 @@
|
||||
"list_add__title_first_add": "添加",
|
||||
"list_add__title_first_move": "移动",
|
||||
"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_down": "降序",
|
||||
"list_sort_modal_by_field": "排序字段",
|
||||
@@ -103,6 +110,10 @@
|
||||
"list_sort_modal_by_type": "排序类别",
|
||||
"list_sort_modal_by_up": "升序",
|
||||
"list_sort_modal_tip_confirm": "你确定要这么做吗?",
|
||||
"list_update_modal__auto_update": "自动更新",
|
||||
"list_update_modal__tips": "💡 每次启动软件时将会自动更新已勾选“自动更新”的列表",
|
||||
"list_update_modal__title": "列表更新管理",
|
||||
"list_update_modal__update": "立即更新",
|
||||
"lists__duplicate": "重复歌曲",
|
||||
"lists__export": "导出",
|
||||
"lists__export_part_desc": "选择列表文件保存位置",
|
||||
@@ -114,17 +125,33 @@
|
||||
"lists__new_list_btn": "新建列表",
|
||||
"lists__new_list_input": "新列表...",
|
||||
"lists__remove": "删除",
|
||||
"lists__remove music_tip": "你真的要移除所选的 {len} 首歌曲吗?",
|
||||
"lists__remove_tip": "你真的想要移除 {name} 吗?",
|
||||
"lists__remove_tip_button": "是的 没错",
|
||||
"lists__rename": "重命名",
|
||||
"lists__sort_list": "排序歌曲",
|
||||
"lists__source_detail": "歌单详情页",
|
||||
"lists__sync": "更新",
|
||||
"lists__sync_confirm_tip": "这将会把 {name} 内的歌曲替换成在线列表的歌曲,你确认要更新吗?",
|
||||
"load_list_file_error_detail": "我们已经帮你把旧的列表文件备份到{path}\n它以 JSON 格式存储,你可以尝试手动修复并恢复它\n\n错误详情:{detail}",
|
||||
"load_list_file_error_title": "播放列表数据加载错误(建议到GitHub或加群反馈)",
|
||||
"loding": "加载中...",
|
||||
"love_list": "收藏",
|
||||
"lyric__load_error": "歌词获取失败",
|
||||
"lyric__select": "歌词文本选择",
|
||||
"lyric_menu__align": "歌词对齐方式",
|
||||
"lyric_menu__align_center": "居中",
|
||||
"lyric_menu__align_left": "居左",
|
||||
"lyric_menu__lrc_size": "字体大小 [ {size} ]",
|
||||
"lyric_menu__offset": "歌词偏移 [ {offset}ms ]",
|
||||
"lyric_menu__offset_add_10": "加快10毫秒",
|
||||
"lyric_menu__offset_add_100": "加快100毫秒",
|
||||
"lyric_menu__offset_dec_10": "减慢10毫秒",
|
||||
"lyric_menu__offset_dec_100": "减慢100毫秒",
|
||||
"lyric_menu__offset_reset": "重置",
|
||||
"lyric_menu__size_add": "加大字体(右击可微调)",
|
||||
"lyric_menu__size_dec": "减小字体(右击可微调)",
|
||||
"lyric_menu__size_reset": "重置",
|
||||
"min": "最小化",
|
||||
"music_album": "专辑名",
|
||||
"music_duplicate": "重复歌曲",
|
||||
@@ -139,9 +166,18 @@
|
||||
"my_list": "我的列表",
|
||||
"no_item": "列表竟然是空的...",
|
||||
"not_agree": "不接受",
|
||||
"ok": "我知道了",
|
||||
"pagination__next": "下一页",
|
||||
"pagination__page": "第 {num} 页",
|
||||
"pagination__prev": "上一页",
|
||||
"play_timeout": "定时暂停",
|
||||
"play_timeout_close": "关闭",
|
||||
"play_timeout_confirm": "确认",
|
||||
"play_timeout_end": "等待歌曲播放完毕再暂停",
|
||||
"play_timeout_stop": "取消定时",
|
||||
"play_timeout_tip": "{time} 后暂停播放",
|
||||
"play_timeout_unit": "分钟",
|
||||
"play_timeout_update": "更新定时",
|
||||
"player__add_music_to": "添加当前歌曲到...",
|
||||
"player__buffering": "缓冲中...",
|
||||
"player__desktop_lyric_lock": "右击锁定歌词",
|
||||
@@ -158,7 +194,7 @@
|
||||
"player__music_singer": "艺术家:",
|
||||
"player__next": "下一首",
|
||||
"player__pause": "暂停",
|
||||
"player__pic_tip": "右击在“我的列表”定位当前播放的歌曲",
|
||||
"player__pic_tip": "播放详情页(右击在“我的列表”定位当前播放的歌曲)",
|
||||
"player__play": "播放",
|
||||
"player__play_toggle_mode_list": "顺序播放",
|
||||
"player__play_toggle_mode_list_loop": "列表循环",
|
||||
@@ -200,6 +236,7 @@
|
||||
"setting__basic_control_btn_position": "控制按钮位置",
|
||||
"setting__basic_control_btn_position_left": "左边",
|
||||
"setting__basic_control_btn_position_right": "右边",
|
||||
"setting__basic_font": "字体",
|
||||
"setting__basic_lang": "语言",
|
||||
"setting__basic_lang_title": "软件显示的语言",
|
||||
"setting__basic_show_animation": "显示切换动画",
|
||||
@@ -215,7 +252,9 @@
|
||||
"setting__basic_sourcename_alias": "别名",
|
||||
"setting__basic_sourcename_real": "原名",
|
||||
"setting__basic_sourcename_title": "选择音源名字类型",
|
||||
"setting__basic_start_in_fullscreen": "以全屏模式启动",
|
||||
"setting__basic_theme": "主题颜色",
|
||||
"setting__basic_theme_auto_tip": "此乃动态主题,你可以预先设置一个亮色主题及暗色主题,此后将根据系统的亮、暗主题色自动切换为你预先设置的相应主题。\n注:鼠标 右击 此主题项即可打开亮、暗色主题设置窗口。",
|
||||
"setting__basic_to_tray": "关闭软件时不退出软件将其最小化到系统托盘",
|
||||
"setting__basic_window_size": "窗口尺寸",
|
||||
"setting__basic_window_size_big": "大",
|
||||
@@ -230,10 +269,12 @@
|
||||
"setting__click_open": "点击打开",
|
||||
"setting__desktop_lyric": "桌面歌词设置",
|
||||
"setting__desktop_lyric_always_on_top": "使歌词总是在其他窗口之上",
|
||||
"setting__desktop_lyric_always_on_top_loop": "自动刷新歌词置顶(当歌词置顶后仍被某些程序遮挡时可尝试启用此设置)",
|
||||
"setting__desktop_lyric_delay_scroll": "延迟歌词滚动",
|
||||
"setting__desktop_lyric_enable": "显示歌词",
|
||||
"setting__desktop_lyric_font": "歌词字体",
|
||||
"setting__desktop_lyric_font_default": "默认",
|
||||
"setting__desktop_lyric_hover_hide": "鼠标移入歌词区域时降低歌词透明度(此功能存在平台兼容性问题)",
|
||||
"setting__desktop_lyric_lock": "锁定歌词",
|
||||
"setting__desktop_lyric_lock_screen": "不允许歌词窗口拖出主屏幕之外",
|
||||
"setting__download": "下载设置",
|
||||
@@ -284,6 +325,7 @@
|
||||
"setting__list_add_music_location_type": "添加歌曲到列表时的位置",
|
||||
"setting__list_add_music_location_type_bottom": "底部",
|
||||
"setting__list_add_music_location_type_top": "顶部",
|
||||
"setting__list_click_action": "双击列表里的歌曲时自动切换到当前列表播放(仅对歌单、排行榜有效)",
|
||||
"setting__list_scroll": "记住播放列表滚动条位置(仅对我的音乐分类有效)",
|
||||
"setting__list_source": "显示歌曲源(仅对我的音乐分类有效)",
|
||||
"setting__network": "网络设置",
|
||||
@@ -311,15 +353,31 @@
|
||||
"setting__other_tray_theme_native": "白色",
|
||||
"setting__other_tray_theme_origin": "原色",
|
||||
"setting__play": "播放设置",
|
||||
"setting__play_lyric_lxlrc": "使用卡拉OK式歌词播放(如果支持)",
|
||||
"setting__play_auto_skip_on_error": "播放错误时自动切换歌曲",
|
||||
"setting__play_detail": "播放详情页设置",
|
||||
"setting__play_detail_align": "歌词对齐方式",
|
||||
"setting__play_detail_align_center": "居中",
|
||||
"setting__play_detail_align_left": "居左",
|
||||
"setting__play_detail_align_right": "居右",
|
||||
"setting__play_detail_font_size": "歌词字体大小(可以在播放详情页使用键盘的 + - 调整字体大小)",
|
||||
"setting__play_detail_font_size_current": "当前字体大小:{size}",
|
||||
"setting__play_detail_font_size_reset": "重置",
|
||||
"setting__play_detail_font_zoom": "缩放当前正在播放的歌词",
|
||||
"setting__play_detail_lyric_progress": "允许通过歌词调整播放进度",
|
||||
"setting__play_lyric_lxlrc": "使用卡拉OK式歌词播放(如果可用)",
|
||||
"setting__play_lyric_roma": "显示歌词罗马音(如果可用)",
|
||||
"setting__play_lyric_s2t": "将播放与下载的歌词转换为繁体中文",
|
||||
"setting__play_lyric_transition": "显示歌词翻译",
|
||||
"setting__play_lyric_transition": "显示歌词翻译(如果可用)",
|
||||
"setting__play_mediaDevice": "音频输出",
|
||||
"setting__play_mediaDevice_remove_stop_play": "当前的声音输出设备被改变时暂停播放歌曲",
|
||||
"setting__play_mediaDevice_title": "选择声音输出的媒体设备",
|
||||
"setting__play_quality": "优先播放320K品质的歌曲(如果支持)",
|
||||
"setting__play_media_device_error_tip": "此功能与音频可视化功能冲突,你本次启动软件时已启用过音频可视化,此设置暂不可用,请 重启 软件后,再来修改此设置。",
|
||||
"setting__play_media_device_tip": "此功能与音频可视化功能冲突,两者无法同时启用,是否将音频可视化关闭 并 应用所选音频输出设置?",
|
||||
"setting__play_quality": "优先播放320K品质的歌曲(如果可用)",
|
||||
"setting__play_save_play_time": "记住播放进度",
|
||||
"setting__play_task_bar": "在任务栏上显示当前歌曲播放进度",
|
||||
"setting__play_timeout": "定时暂停",
|
||||
"setting__player_audio_visualization_tip": "自定义音频输出设备与音频可视化功能会冲突,启用了音频可视化后音频输出设备将会被重置为默认的输出设备,目前此问题暂无法解决,是否仍要开启?",
|
||||
"setting__search": "搜索设置",
|
||||
"setting__search_focus_search_box": "启动时自动聚焦搜索框",
|
||||
"setting__search_history": "显示历史搜索记录",
|
||||
@@ -384,6 +442,9 @@
|
||||
"sync__title": "选择与 {name} 的列表同步方式",
|
||||
"tag__high_quality": "HQ",
|
||||
"tag__lossless": "SQ",
|
||||
"tag__lossless_24bit": "24bit",
|
||||
"theme_auto": "道法自然",
|
||||
"theme_auto_tip": "鼠标 右击 可打开亮、暗主题设置窗口",
|
||||
"theme_black": "黑灯瞎火",
|
||||
"theme_blue": "蓝田生玉",
|
||||
"theme_blue2": "清热版蓝",
|
||||
@@ -397,13 +458,21 @@
|
||||
"theme_pink": "粉装玉琢",
|
||||
"theme_purple": "重斤球紫",
|
||||
"theme_red": "热情似火",
|
||||
"theme_selector_modal__dark_title": "暗色主题",
|
||||
"theme_selector_modal__light_title": "亮色主题",
|
||||
"theme_selector_modal__title": "跟随系统主题设置",
|
||||
"theme_selector_modal__title_tip": "注:你可以预先设置一个亮色主题及暗色主题,此后将根据系统的亮、暗主题色自动切换为你预先设置的相应主题。",
|
||||
"theme_yellow": "信口雌黄",
|
||||
"user_api__allow_show_update_alert": "允许显示更新弹窗",
|
||||
"user_api__btn_export": "导出",
|
||||
"user_api__btn_import": "导入",
|
||||
"user_api__btn_remove": "移除",
|
||||
"user_api__import_file": "选择音乐API脚本文件",
|
||||
"user_api__max_tip": "最多只能同时存在20个源哦🤪\n想要继续导入的话,请先移除一些旧的源腾出位置吧",
|
||||
"user_api__noitem": "这里竟然是空的 😲",
|
||||
"user_api__note": "提示:虽然我们已经尽可能地隔离了脚本的运行环境,但导入包含恶意行为的脚本仍可能会影响你的系统,请谨慎导入。",
|
||||
"user_api__readme": "源编写说明:",
|
||||
"user_api__title": "自定义源管理"
|
||||
"user_api__title": "自定义源管理",
|
||||
"user_api__update_alert": "自定义源 [{name}] 发现新版本:",
|
||||
"user_api__update_alert_open_url": "打开更新地址"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"action": "操作",
|
||||
"agree": "接受",
|
||||
"alert_button_text": "好吧",
|
||||
"audio_visualization": "音頻可視化(實驗性)",
|
||||
"back": "返回",
|
||||
"cancel_button_text": "取消",
|
||||
@@ -36,7 +37,7 @@
|
||||
"desktop_lyric__unlock": "解鎖歌詞",
|
||||
"desktop_lyric__win_top_off": "取消置頂歌詞界面",
|
||||
"desktop_lyric__win_top_on": "置頂歌詞界面",
|
||||
"download": "下載管理",
|
||||
"download": "下載",
|
||||
"download__all": "全部任務",
|
||||
"download__error": "出錯",
|
||||
"download__finished": "下載完成",
|
||||
@@ -52,6 +53,7 @@
|
||||
"download__runing": "正在下載",
|
||||
"download__status": "狀態",
|
||||
"export": "導出",
|
||||
"fullscreen_exit": "退出全屏",
|
||||
"history_clear": "清空搜索歷史",
|
||||
"history_remove": "右擊移除該歷史",
|
||||
"history_search": "歷史搜索",
|
||||
@@ -89,10 +91,15 @@
|
||||
"list_add__btn_title": "把該歌曲添加到 {name}",
|
||||
"list_add__multiple_btn_title": "把這些歌曲添加到 {name}",
|
||||
"list_add__multiple_title_add": "添加已選的 {num} 首歌曲到...",
|
||||
"list_add__multiple_title_move": "添加移動已選的 {num} 首歌曲到...",
|
||||
"list_add__multiple_title_move": "移動已選的 {num} 首歌曲到...",
|
||||
"list_add__title_first_add": "添加",
|
||||
"list_add__title_first_move": "移動",
|
||||
"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_down": "降序",
|
||||
"list_sort_modal_by_field": "排序字段",
|
||||
@@ -103,6 +110,10 @@
|
||||
"list_sort_modal_by_type": "排序類別",
|
||||
"list_sort_modal_by_up": "升序",
|
||||
"list_sort_modal_tip_confirm": "你確定要這麼做嗎?",
|
||||
"list_update_modal__auto_update": "自動更新",
|
||||
"list_update_modal__tips": "💡 每次啟動軟件時將會自動更新已勾選“自動更新”的列表",
|
||||
"list_update_modal__title": "列表更新管理",
|
||||
"list_update_modal__update": "立即更新",
|
||||
"lists__duplicate": "重複歌曲",
|
||||
"lists__export": "導出",
|
||||
"lists__export_part_desc": "選擇列表文件保存位置",
|
||||
@@ -114,17 +125,33 @@
|
||||
"lists__new_list_btn": "新建列表",
|
||||
"lists__new_list_input": "新列表...",
|
||||
"lists__remove": "刪除",
|
||||
"lists__remove music_tip": "你真的要移除所選的 {len} 首歌曲嗎?",
|
||||
"lists__remove_tip": "你真的想要移除 {name} 嗎?",
|
||||
"lists__remove_tip_button": "是的 沒錯",
|
||||
"lists__rename": "重命名",
|
||||
"lists__sort_list": "排序歌曲",
|
||||
"lists__source_detail": "歌單詳情頁",
|
||||
"lists__sync": "更新",
|
||||
"lists__sync_confirm_tip": "這將會把 {name} 內的歌曲替換成在線列表的歌曲,你確認要更新嗎?",
|
||||
"load_list_file_error_detail": "我們已經幫你把舊的列表文件備份到{path}\n它以 JSON 格式存儲,你可以嘗試手動修復並恢復它\n\n錯誤詳情:{detail}",
|
||||
"load_list_file_error_title": "播放列表數據加載錯誤",
|
||||
"load_list_file_error_title": "播放列表數據加載錯誤(建議到GitHub或加群反饋)",
|
||||
"loding": "加載中...",
|
||||
"love_list": "收藏列表",
|
||||
"love_list": "收藏",
|
||||
"lyric__load_error": "歌詞獲取失敗",
|
||||
"lyric__select": "歌詞文本選擇",
|
||||
"lyric_menu__align": "歌詞對齊方式",
|
||||
"lyric_menu__align_center": "居中",
|
||||
"lyric_menu__align_left": "居左",
|
||||
"lyric_menu__lrc_size": "字體大小 [ {size} ]",
|
||||
"lyric_menu__offset": "歌詞偏移 [ {offset}ms ]",
|
||||
"lyric_menu__offset_add_10": "加快10毫秒",
|
||||
"lyric_menu__offset_add_100": "加快100毫秒",
|
||||
"lyric_menu__offset_dec_10": "減慢10毫秒",
|
||||
"lyric_menu__offset_dec_100": "減慢100毫秒",
|
||||
"lyric_menu__offset_reset": "重置",
|
||||
"lyric_menu__size_add": "加大字體(右擊可微調)",
|
||||
"lyric_menu__size_dec": "減小字體(右擊可微調)",
|
||||
"lyric_menu__size_reset": "重置",
|
||||
"min": "最小化",
|
||||
"music_album": "專輯名",
|
||||
"music_duplicate": "重複歌曲",
|
||||
@@ -139,11 +166,19 @@
|
||||
"my_list": "我的列表",
|
||||
"no_item": "列表竟然是空的...",
|
||||
"not_agree": "不接受",
|
||||
"ok": "我知道了",
|
||||
"pagination__next": "下一頁",
|
||||
"pagination__page": "第 {num} 頁",
|
||||
"pagination__prev": "上一頁",
|
||||
"play_timeout": "定時暫停",
|
||||
"play_timeout_close": "關閉",
|
||||
"play_timeout_confirm": "確認",
|
||||
"play_timeout_end": "等待歌曲播放完畢再暫停",
|
||||
"play_timeout_stop": "取消定時",
|
||||
"play_timeout_tip": "{time} 後暫停播放",
|
||||
"play_timeout_unit": "分鐘",
|
||||
"play_timeout_update": "更新定時",
|
||||
"player__add_music_to": "添加當前歌曲到...",
|
||||
"player__album": "專輯名:",
|
||||
"player__buffering": "緩衝中...",
|
||||
"player__desktop_lyric_lock": "右擊鎖定歌詞",
|
||||
"player__desktop_lyric_off": "關閉桌面歌詞",
|
||||
@@ -154,11 +189,12 @@
|
||||
"player__geting_url": "歌曲鏈接獲取中...",
|
||||
"player__hide_detail_tip": "隱藏詳情頁(界面內右鍵雙擊可快速隱藏詳情頁)",
|
||||
"player__loading": "音樂加載中...",
|
||||
"player__music_album": "專輯名:",
|
||||
"player__music_name": "歌曲名:",
|
||||
"player__music_singer": "藝術家:",
|
||||
"player__next": "下一首",
|
||||
"player__pause": "暫停",
|
||||
"player__pic_tip": "右擊在“我的列表”定位當前播放的歌曲",
|
||||
"player__pic_tip": "播放詳情頁(右擊在“我的列表”定位當前播放的歌曲)",
|
||||
"player__play": "播放",
|
||||
"player__play_toggle_mode_list": "順序播放",
|
||||
"player__play_toggle_mode_list_loop": "列表循環",
|
||||
@@ -200,6 +236,7 @@
|
||||
"setting__basic_control_btn_position": "控制按鈕位置",
|
||||
"setting__basic_control_btn_position_left": "左邊",
|
||||
"setting__basic_control_btn_position_right": "右邊",
|
||||
"setting__basic_font": "字體",
|
||||
"setting__basic_lang": "語言",
|
||||
"setting__basic_lang_title": "軟件顯示的語言",
|
||||
"setting__basic_show_animation": "顯示切換動畫",
|
||||
@@ -215,7 +252,9 @@
|
||||
"setting__basic_sourcename_alias": "別名",
|
||||
"setting__basic_sourcename_real": "原名",
|
||||
"setting__basic_sourcename_title": "選擇音源名字類型",
|
||||
"setting__basic_start_in_fullscreen": "以全屏模式啟動",
|
||||
"setting__basic_theme": "主題顏色",
|
||||
"setting__basic_theme_auto_tip": "此乃動態主題,你可以預先設置一個亮色主題及暗色主題,此後將根據系統的亮、暗主題色自動切換為你預先設置的相應主題。\n注:鼠標 右擊 此主題項即可打開亮、暗色主題設置窗口。",
|
||||
"setting__basic_to_tray": "關閉軟件時不退出軟件將其最小化到系統托盤",
|
||||
"setting__basic_window_size": "窗口尺寸",
|
||||
"setting__basic_window_size_big": "大",
|
||||
@@ -230,10 +269,12 @@
|
||||
"setting__click_open": "點擊打開",
|
||||
"setting__desktop_lyric": "桌面歌詞設置",
|
||||
"setting__desktop_lyric_always_on_top": "使歌詞總是在其他窗口之上",
|
||||
"setting__desktop_lyric_always_on_top_loop": "自動刷新歌詞置頂(當歌詞置頂後仍被某些程序遮擋時可嘗試啟用此設置)",
|
||||
"setting__desktop_lyric_delay_scroll": "延遲歌詞滾動",
|
||||
"setting__desktop_lyric_enable": "顯示歌詞",
|
||||
"setting__desktop_lyric_font": "歌詞字體",
|
||||
"setting__desktop_lyric_font_default": "默認",
|
||||
"setting__desktop_lyric_hover_hide": "鼠標移入歌詞區域時降低歌詞透明度(此功能存在平台兼容性問題)",
|
||||
"setting__desktop_lyric_lock": "鎖定歌詞",
|
||||
"setting__desktop_lyric_lock_screen": "不允許歌詞窗口拖出主屏幕之外",
|
||||
"setting__download": "下載設置",
|
||||
@@ -272,7 +313,7 @@
|
||||
"setting__hot_key_local_title": "軟件內快捷鍵",
|
||||
"setting__hot_key_player_next": "下一首歌曲",
|
||||
"setting__hot_key_player_prev": "上一首歌曲",
|
||||
"setting__hot_key_player_toggle_play": "播放/暫停控制",
|
||||
"setting__hot_key_player_toggle_play": "播放/暫停控制",
|
||||
"setting__hot_key_player_volume_down": "減少音量",
|
||||
"setting__hot_key_player_volume_mute": "靜音切換",
|
||||
"setting__hot_key_player_volume_up": "增加音量",
|
||||
@@ -284,6 +325,7 @@
|
||||
"setting__list_add_music_location_type": "添加歌曲到列表時的位置",
|
||||
"setting__list_add_music_location_type_bottom": "底部",
|
||||
"setting__list_add_music_location_type_top": "頂部",
|
||||
"setting__list_click_action": "雙擊列表裡的歌曲時自動切換到當前列表播放(僅對歌單、排行榜有效)",
|
||||
"setting__list_scroll": "記住播放列表滾動條位置(僅對我的音樂分類有效)",
|
||||
"setting__list_source": "顯示歌曲源(僅對我的音樂分類有效)",
|
||||
"setting__network": "網絡設置",
|
||||
@@ -311,15 +353,31 @@
|
||||
"setting__other_tray_theme_native": "白色",
|
||||
"setting__other_tray_theme_origin": "原色",
|
||||
"setting__play": "播放設置",
|
||||
"setting__play_lyric_lxlrc": "使用卡拉OK式歌詞播放(如果支持)",
|
||||
"setting__play_auto_skip_on_error": "播放錯誤時自動切換歌曲",
|
||||
"setting__play_detail": "播放詳情頁設置",
|
||||
"setting__play_detail_align": "歌詞對齊方式",
|
||||
"setting__play_detail_align_center": "居中",
|
||||
"setting__play_detail_align_left": "居左",
|
||||
"setting__play_detail_align_right": "居右",
|
||||
"setting__play_detail_font_size": "歌詞字體大小(可以在播放詳情頁使用鍵盤的 + - 調整字體大小)",
|
||||
"setting__play_detail_font_size_current": "當前字體大小:{size}",
|
||||
"setting__play_detail_font_size_reset": "重置",
|
||||
"setting__play_detail_font_zoom": "縮放當前正在播放的歌詞",
|
||||
"setting__play_detail_lyric_progress": "允許通過歌詞調整播放進度",
|
||||
"setting__play_lyric_lxlrc": "使用卡拉OK式歌詞播放(如果可用)",
|
||||
"setting__play_lyric_roma": "顯示歌詞羅馬音(如果可用)",
|
||||
"setting__play_lyric_s2t": "將播放與下載的歌詞轉換為繁體中文",
|
||||
"setting__play_lyric_transition": "顯示歌詞翻譯",
|
||||
"setting__play_lyric_transition": "顯示歌詞翻譯(如果可用)",
|
||||
"setting__play_mediaDevice": "音頻輸出",
|
||||
"setting__play_mediaDevice_remove_stop_play": "當前的聲音輸出設備被改變時暫停播放歌曲",
|
||||
"setting__play_mediaDevice_title": "選擇聲音輸出的媒體設備",
|
||||
"setting__play_quality": "優先播放320K品質的歌曲(如果支持)",
|
||||
"setting__play_media_device_error_tip": "此功能與音頻可視化功能衝突,你本次啟動軟件時已啟用過音頻可視化,此設置暫不可用,請 重啟 軟件後,再來修改此設置。",
|
||||
"setting__play_media_device_tip": "此功能與音頻可視化功能衝突,兩者無法同時啟用,是否將音頻可視化關閉 並 應用所選音頻輸出設置?",
|
||||
"setting__play_quality": "優先播放320K品質的歌曲(如果可用)",
|
||||
"setting__play_save_play_time": "記住播放進度",
|
||||
"setting__play_task_bar": "在任務欄上顯示當前歌曲播放進度",
|
||||
"setting__play_timeout": "定時暫停",
|
||||
"setting__player_audio_visualization_tip": "自定義音頻輸出設備與音頻可視化功能會衝突,啟用了音頻可視化後音頻輸出設備將會被重置為默認的輸出設備,目前此問題暫無法解決,是否仍要開啟?",
|
||||
"setting__search": "搜索設置",
|
||||
"setting__search_focus_search_box": "啟動時自動聚焦搜索框",
|
||||
"setting__search_history": "顯示歷史搜索記錄",
|
||||
@@ -384,6 +442,9 @@
|
||||
"sync__title": "選擇與 {name} 的列表同步方式",
|
||||
"tag__high_quality": "HQ",
|
||||
"tag__lossless": "SQ",
|
||||
"tag__lossless_24bit": "24bit",
|
||||
"theme_auto": "道法自然",
|
||||
"theme_auto_tip": "鼠標 右擊 可打開亮、暗主題設置窗口",
|
||||
"theme_black": "黑燈瞎火",
|
||||
"theme_blue": "藍田生玉",
|
||||
"theme_blue2": "清熱版藍",
|
||||
@@ -397,13 +458,21 @@
|
||||
"theme_pink": "粉裝玉琢",
|
||||
"theme_purple": "重斤球紫",
|
||||
"theme_red": "熱情似火",
|
||||
"theme_selector_modal__dark_title": "暗色主題",
|
||||
"theme_selector_modal__light_title": "亮色主題",
|
||||
"theme_selector_modal__title": "跟隨系統主題設置",
|
||||
"theme_selector_modal__title_tip": "注:你可以預先設置一個亮色主題及暗色主題,此後將根據系統的亮、暗主題色自動切換為你預先設置的相應主題。",
|
||||
"theme_yellow": "信口雌黃",
|
||||
"user_api__allow_show_update_alert": "允許顯示更新彈窗",
|
||||
"user_api__btn_export": "導出",
|
||||
"user_api__btn_import": "導入",
|
||||
"user_api__btn_remove": "移除",
|
||||
"user_api__import_file": "選擇音樂API腳本文件",
|
||||
"user_api__max_tip": "最多只能同時存在20個源哦🤪\n想要繼續導入的話,請先移除一些舊的源騰出位置吧",
|
||||
"user_api__noitem": "這裡竟然是空的 😲",
|
||||
"user_api__note": "提示:雖然我們已經盡可能地隔離了腳本的運行環境,但導入包含惡意行為的腳本仍可能會影響你的系統,請謹慎導入。",
|
||||
"user_api__readme": "源編寫說明:",
|
||||
"user_api__title": "自定義源管理"
|
||||
"user_api__title": "自定義源管理",
|
||||
"user_api__update_alert": "自定義源 [{name}] 發現新版本:",
|
||||
"user_api__update_alert_open_url": "打開更新地址"
|
||||
}
|
||||
|
||||
@@ -26,6 +26,14 @@ class MainWindow extends EventEmitter {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.show)
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.focus)
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.blur)
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.hide)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ exports.mainWindow = {
|
||||
ready_to_show: 'ready_to_show',
|
||||
show: 'show',
|
||||
hide: 'hide',
|
||||
focus: 'focus',
|
||||
blur: 'blur',
|
||||
}
|
||||
|
||||
exports.tray = {
|
||||
|
||||
@@ -6,6 +6,7 @@ const Tray = require('./Tray')
|
||||
const WinLyric = require('./WinLyric')
|
||||
const HotKey = require('./HotKey')
|
||||
|
||||
const { Event: TaskBar } = require('../modules/taskbar')
|
||||
const { Event: UserApi } = require('../modules/userApi')
|
||||
const { Event: Sync } = require('../modules/sync')
|
||||
|
||||
@@ -15,5 +16,6 @@ if (!global.lx_event.tray) global.lx_event.tray = new Tray()
|
||||
if (!global.lx_event.winLyric) global.lx_event.winLyric = new WinLyric()
|
||||
if (!global.lx_event.hotKey) global.lx_event.hotKey = new HotKey()
|
||||
|
||||
if (!global.lx_event.taskbar) global.lx_event.taskbar = new TaskBar()
|
||||
if (!global.lx_event.userApi) global.lx_event.userApi = new UserApi()
|
||||
if (!global.lx_event.sync) global.lx_event.sync = new Sync()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
const electron = require('electron')
|
||||
const electronDebug = require('electron-debug')
|
||||
const { default: installExtension, VUEJS3_DEVTOOLS } = require('electron-devtools-installer')
|
||||
const { default: installExtension, VUEJS_DEVTOOLS } = require('electron-devtools-installer')
|
||||
// Install `electron-debug` with `devtron`
|
||||
electronDebug({
|
||||
showDevTools: true,
|
||||
@@ -15,7 +15,7 @@ electronDebug({
|
||||
|
||||
// Install `vue-devtools`
|
||||
electron.app.on('ready', () => {
|
||||
installExtension(VUEJS3_DEVTOOLS)
|
||||
installExtension(VUEJS_DEVTOOLS)
|
||||
.then(name => console.log(`Added Extension: ${name}`))
|
||||
.catch(err => console.log('An error occurred: ', err))
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { app, BrowserWindow, shell } = require('electron')
|
||||
const { app, BrowserWindow, shell, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
const urlSchemeRxp = /^lxmusic:\/\//
|
||||
@@ -83,14 +83,13 @@ app.on('open-url', (event, url) => {
|
||||
init()
|
||||
}
|
||||
})
|
||||
if (isDev && process.platform === 'win32') {
|
||||
// Set the path of electron.exe and your app.
|
||||
// These two additional parameters are only available on windows.
|
||||
// console.log(process.execPath, process.argv)
|
||||
app.setAsDefaultProtocolClient('lxmusic', process.execPath, process.argv.slice(1))
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('lxmusic')
|
||||
}
|
||||
// if (isDev && process.platform === 'win32') {
|
||||
// // Set the path of electron.exe and your app.
|
||||
// // These two additional parameters are only available on windows.
|
||||
// // console.log(process.execPath, process.argv)
|
||||
// app.setAsDefaultProtocolClient('lxmusic', process.execPath, process.argv.slice(1))
|
||||
// }
|
||||
if (!isDev) app.setAsDefaultProtocolClient('lxmusic')
|
||||
|
||||
const { navigationUrlWhiteList, themes } = require('../common/config')
|
||||
const { getWindowSizeInfo, initSetting, updateSetting } = require('./utils')
|
||||
@@ -129,6 +128,10 @@ app.on('web-contents-created', (event, contents) => {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
// disable create dictionary
|
||||
// https://github.com/lyswhut/lx-music-desktop/issues/773
|
||||
contents.session.setSpellCheckerDictionaryDownloadURL('http://0.0.0.0')
|
||||
})
|
||||
|
||||
|
||||
@@ -156,7 +159,7 @@ function createWindow() {
|
||||
/**
|
||||
* Initial window options
|
||||
*/
|
||||
global.modules.mainWindow = new BrowserWindow({
|
||||
const options = {
|
||||
height: windowSizeInfo.height,
|
||||
useContentSize: true,
|
||||
width: windowSizeInfo.width,
|
||||
@@ -166,7 +169,7 @@ function createWindow() {
|
||||
// icon: path.join(global.__static, isWin ? 'icons/256x256.ico' : 'icons/512x512.png'),
|
||||
resizable: false,
|
||||
maximizable: false,
|
||||
fullscreenable: false,
|
||||
fullscreenable: true,
|
||||
show: false,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
@@ -174,11 +177,24 @@ function createWindow() {
|
||||
nodeIntegration: true,
|
||||
spellcheck: false, // 禁用拼写检查器
|
||||
},
|
||||
})
|
||||
}
|
||||
if (global.appSetting.startInFullscreen) {
|
||||
options.fullscreen = true
|
||||
if (isLinux) options.resizable = true
|
||||
}
|
||||
global.modules.mainWindow = new BrowserWindow(options)
|
||||
|
||||
global.modules.mainWindow.loadURL(winURL + `?dt=${!!global.envParams.cmdParams.dt}&theme=${themes.find(t => t.id == global.appSetting.themeId)?.className ?? themes[0].className}`)
|
||||
const shouldUseDarkColors = nativeTheme.shouldUseDarkColors
|
||||
const themeId = global.appSetting.theme.id == 'auto'
|
||||
? shouldUseDarkColors
|
||||
? global.appSetting.theme.darkId
|
||||
: global.appSetting.theme.lightId
|
||||
: global.appSetting.theme.id
|
||||
const themeClass = themes.find(t => t.id == themeId)?.className ?? themes[0].className
|
||||
global.modules.mainWindow.loadURL(winURL + `?dt=${!!global.envParams.cmdParams.dt}&dark=${shouldUseDarkColors}&theme=${themeClass}`)
|
||||
|
||||
winEvent(global.modules.mainWindow)
|
||||
if (global.envParams.cmdParams.odt) require('@main/utils').openDevTools(global.modules.mainWindow.webContents)
|
||||
// global.modules.mainWindow.webContents.openDevTools()
|
||||
|
||||
if (!isDev) autoUpdate()
|
||||
|
||||
@@ -2,4 +2,3 @@ require('./appMenu')
|
||||
require('./winLyric')
|
||||
require('./tray')
|
||||
require('./hotKey')
|
||||
require('./userApi')
|
||||
|
||||
@@ -3,8 +3,8 @@ const sio = require('socket.io')
|
||||
const { createHttpTerminator } = require('http-terminator')
|
||||
const modules = require('../modules')
|
||||
const { authCode, authConnect } = require('./auth')
|
||||
const { getAddress, getServerId, generateCode, getClientKeyInfo } = require('./utils')
|
||||
const syncList = require('./syncList')
|
||||
const { getAddress, getServerId, generateCode, getClientKeyInfo, setClientKeyInfo } = require('./utils')
|
||||
const { syncList, removeSnapshot } = require('./syncList')
|
||||
const { log } = require('@common/utils')
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ const handleStartServer = (port = 9527) => new Promise((resolve, reject) => {
|
||||
global.lx_event.sync.status(status)
|
||||
})
|
||||
const keyInfo = getClientKeyInfo(socket.handshake.query.i)
|
||||
keyInfo.connectionTime = Date.now()
|
||||
setClientKeyInfo(keyInfo)
|
||||
// socket.lx_keyInfo = keyInfo
|
||||
socket.data.keyInfo = keyInfo
|
||||
try {
|
||||
@@ -172,3 +174,5 @@ exports.generateCode = async() => {
|
||||
global.lx_event.sync.status(status)
|
||||
return status.code
|
||||
}
|
||||
|
||||
exports.removeSnapshot = removeSnapshot
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const fsPromises = fs.promises
|
||||
const { app } = require('electron')
|
||||
const { encryptMsg, decryptMsg } = require('./utils')
|
||||
const { encryptMsg, decryptMsg, getSnapshotFilePath } = require('./utils')
|
||||
const SYNC_EVENT_NAMES = require('../event/name')
|
||||
const { common: COMMON_EVENT_NAME } = require('@main/events/_name')
|
||||
const { throttle } = require('@common/utils')
|
||||
@@ -403,7 +401,7 @@ const registerUpdateSnapshotTask = (socket, snapshot) => {
|
||||
}
|
||||
|
||||
const syncList = async socket => {
|
||||
socket.data.snapshotFilePath = path.join(app.getPath('userData'), `snapshot-${Buffer.from(socket.data.keyInfo.clientId).toString('hex').substring(0, 10)}.json`)
|
||||
socket.data.snapshotFilePath = getSnapshotFilePath(socket.data.keyInfo)
|
||||
let fileData
|
||||
let isSyncRequired = false
|
||||
try {
|
||||
@@ -423,7 +421,7 @@ const checkSyncQueue = async() => {
|
||||
await wait()
|
||||
return checkSyncQueue()
|
||||
}
|
||||
module.exports = async(_io, socket) => {
|
||||
exports.syncList = async(_io, socket) => {
|
||||
io = _io
|
||||
await checkSyncQueue()
|
||||
syncingId = socket.data.keyInfo.clientId
|
||||
@@ -434,3 +432,7 @@ module.exports = async(_io, socket) => {
|
||||
syncingId = null
|
||||
})
|
||||
}
|
||||
exports.removeSnapshot = keyInfo => {
|
||||
const filePath = getSnapshotFilePath(keyInfo)
|
||||
return fsPromises.unlink(filePath)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const { app } = require('electron')
|
||||
const { networkInterfaces } = require('os')
|
||||
const { randomBytes, createCipheriv, createDecipheriv } = require('crypto')
|
||||
const path = require('path')
|
||||
const getStore = require('@common/store')
|
||||
const STORE_NAME = 'sync'
|
||||
|
||||
@@ -91,3 +93,7 @@ exports.decryptMsg = (keyInfo, enMsg) => {
|
||||
// }
|
||||
// return msg
|
||||
}
|
||||
|
||||
exports.getSnapshotFilePath = keyInfo => {
|
||||
return path.join(app.getPath('userData'), `snapshot-${Buffer.from(keyInfo.clientId).toString('hex').substring(0, 10)}.json`)
|
||||
}
|
||||
|
||||
11
src/main/modules/taskbar/event/event.js
Normal file
11
src/main/modules/taskbar/event/event.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const { EventEmitter } = require('events')
|
||||
const TASKBAR_EVENT_NAME = require('./name')
|
||||
|
||||
class TaskBar extends EventEmitter {
|
||||
thumbarButtonClick(type) {
|
||||
this.emit(TASKBAR_EVENT_NAME.thumbarButtonClick, type)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TaskBar
|
||||
|
||||
3
src/main/modules/taskbar/event/name.js
Normal file
3
src/main/modules/taskbar/event/name.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
thumbarButtonClick: 'thumbarButtonClick',
|
||||
}
|
||||
92
src/main/modules/taskbar/index.js
Normal file
92
src/main/modules/taskbar/index.js
Normal file
@@ -0,0 +1,92 @@
|
||||
const path = require('path')
|
||||
const Event = require('./event/event')
|
||||
const eventNames = require('./event/name')
|
||||
|
||||
exports.Event = Event
|
||||
exports.eventNames = eventNames
|
||||
|
||||
exports.setThumbnailClip = (region = { x: 0, y: 0, width: 0, height: 0 }) => {
|
||||
if (!global.modules.mainWindow) return
|
||||
return global.modules.mainWindow.setThumbnailClip(region)
|
||||
}
|
||||
|
||||
const getIconPath = name => {
|
||||
return path.join(global.__static, 'images/taskbar', name + '.png')
|
||||
}
|
||||
|
||||
const buttonsFlags = {
|
||||
empty: true,
|
||||
collect: false,
|
||||
play: false,
|
||||
next: true,
|
||||
prev: true,
|
||||
}
|
||||
const createButtons = ({ empty = false, collect = false, play = false, next = true, prev = true }) => {
|
||||
const buttons = [
|
||||
collect
|
||||
? {
|
||||
icon: getIconPath('collected'),
|
||||
click() {
|
||||
global.lx_event.taskbar.thumbarButtonClick('unCollect')
|
||||
},
|
||||
tooltip: '取消收藏',
|
||||
flags: ['nobackground'],
|
||||
}
|
||||
: {
|
||||
icon: getIconPath('collect'),
|
||||
click() {
|
||||
global.lx_event.taskbar.thumbarButtonClick('collect')
|
||||
},
|
||||
tooltip: '收藏',
|
||||
flags: ['nobackground'],
|
||||
},
|
||||
{
|
||||
icon: getIconPath('prev'),
|
||||
click() {
|
||||
global.lx_event.taskbar.thumbarButtonClick('prev')
|
||||
},
|
||||
tooltip: '上一曲',
|
||||
flags: prev ? ['nobackground'] : ['nobackground', 'disabled'],
|
||||
},
|
||||
play
|
||||
? {
|
||||
icon: getIconPath('pause'),
|
||||
click() {
|
||||
global.lx_event.taskbar.thumbarButtonClick('pause')
|
||||
},
|
||||
tooltip: '暂停',
|
||||
flags: ['nobackground'],
|
||||
}
|
||||
: {
|
||||
icon: getIconPath('play'),
|
||||
click() {
|
||||
global.lx_event.taskbar.thumbarButtonClick('play')
|
||||
},
|
||||
tooltip: '播放',
|
||||
flags: ['nobackground'],
|
||||
},
|
||||
{
|
||||
icon: getIconPath('next'),
|
||||
click() {
|
||||
global.lx_event.taskbar.thumbarButtonClick('next')
|
||||
},
|
||||
tooltip: '下一曲',
|
||||
flags: next ? ['nobackground'] : ['nobackground', 'disabled'],
|
||||
},
|
||||
]
|
||||
if (empty) {
|
||||
for (const button of buttons) {
|
||||
button.flags = ['nobackground', 'disabled']
|
||||
}
|
||||
}
|
||||
return buttons
|
||||
}
|
||||
exports.setThumbarButtons = ({ empty, collect, play, next, prev } = buttonsFlags) => {
|
||||
if (!global.modules.mainWindow) return
|
||||
buttonsFlags.empty = empty
|
||||
buttonsFlags.collect = collect
|
||||
buttonsFlags.play = play
|
||||
buttonsFlags.next = next
|
||||
buttonsFlags.prev = prev
|
||||
global.modules.mainWindow.setThumbarButtons(createButtons(buttonsFlags))
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const { app, Tray, Menu, nativeImage } = require('electron')
|
||||
// const { isWin } = require('../../common/utils')
|
||||
const { isWin } = require('@common/utils')
|
||||
const { tray: TRAY_EVENT_NAME, common: COMMON_EVENT_NAME, mainWindow: MAIN_WINDOW_NAME } = require('../events/_name')
|
||||
const path = require('path')
|
||||
let isEnableTray = null
|
||||
@@ -40,6 +40,14 @@ global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.ready_to_show, () => {
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.show, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
if (!isWin) {
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.focus, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.blur, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
}
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.hide, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
@@ -75,24 +83,27 @@ const destroyTray = () => {
|
||||
const createMenu = tray => {
|
||||
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()
|
||||
},
|
||||
})
|
||||
if (global.modules.mainWindow) {
|
||||
const isShow = global.modules.mainWindow.isVisible() && (isWin ? true : global.modules.mainWindow.isFocused())
|
||||
menu.push(isShow
|
||||
? {
|
||||
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: '关闭桌面歌词',
|
||||
|
||||
@@ -5,6 +5,10 @@ class UserApi extends EventEmitter {
|
||||
status(info) {
|
||||
this.emit(USER_API_EVENT_NAME.status, info)
|
||||
}
|
||||
|
||||
showUpdateAlert(info) {
|
||||
this.emit(USER_API_EVENT_NAME.showUpdateAlert, info)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserApi
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
module.exports = {
|
||||
status: 'status',
|
||||
showUpdateAlert: 'showUpdateAlert',
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const Event = require('./event/event')
|
||||
const eventNames = require('./event/name')
|
||||
const { closeWindow } = require('./main')
|
||||
const { getUserApis, importApi, removeApi } = require('./utils')
|
||||
const { request, cancelRequest, getStatus, loadApi } = require('./rendererEvent/rendererEvent')
|
||||
const { getUserApis, importApi, removeApi, setAllowShowUpdateAlert: saveAllowShowUpdateAlert } = require('./utils')
|
||||
const { request, cancelRequest, getStatus, loadApi, setAllowShowUpdateAlert } = require('./rendererEvent/rendererEvent')
|
||||
|
||||
// const { getApiList, importApi, removeApi, setApi, getStatus, request, eventNames }
|
||||
let userApiId
|
||||
@@ -41,4 +41,7 @@ exports.setApi = async id => {
|
||||
await loadApi(id)
|
||||
}
|
||||
|
||||
|
||||
exports.setAllowShowUpdateAlert = (id, enable) => {
|
||||
saveAllowShowUpdateAlert(id, enable)
|
||||
setAllowShowUpdateAlert(id, enable)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ fs.readFile(path.join(dir, 'renderer/user-api.html'), 'utf8', (err, data) => {
|
||||
})
|
||||
|
||||
const denyEvents = [
|
||||
'new-window',
|
||||
'will-navigate',
|
||||
'will-redirect',
|
||||
'will-attach-webview',
|
||||
@@ -49,11 +48,13 @@ exports.createWindow = async userApi => {
|
||||
contextIsolation: true,
|
||||
// worldSafeExecuteJavaScript: true,
|
||||
nodeIntegration: false,
|
||||
nodeIntegrationInWorker: false,
|
||||
|
||||
spellcheck: false,
|
||||
autoplayPolicy: 'document-user-activation-required',
|
||||
enableWebSQL: false,
|
||||
disableDialogs: true,
|
||||
nativeWindowOpen: false,
|
||||
webgl: false,
|
||||
images: false,
|
||||
|
||||
@@ -66,9 +67,13 @@ exports.createWindow = async userApi => {
|
||||
event.preventDefault()
|
||||
})
|
||||
}
|
||||
global.modules.userApiWindow.webContents.session.setPermissionRequestHandler((webContents, permission, callback) => {
|
||||
// eslint-disable-next-line node/no-callback-literal
|
||||
callback(false)
|
||||
global.modules.userApiWindow.webContents.session.setPermissionRequestHandler((webContents, permission, resolve) => {
|
||||
if (webContents === global.modules.mainWindow.webContents) return resolve(true)
|
||||
|
||||
resolve(false)
|
||||
})
|
||||
global.modules.userApiWindow.webContents.setWindowOpenHandler(() => {
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
winEvent(global.modules.userApiWindow)
|
||||
|
||||
@@ -3,14 +3,20 @@ const needle = require('needle')
|
||||
const { createCipheriv, publicEncrypt, constants, randomBytes, createHash } = require('crypto')
|
||||
const USER_API_RENDERER_EVENT_NAME = require('../rendererEvent/name')
|
||||
|
||||
const sendMessage = (action, status, data, message) => {
|
||||
ipcRenderer.send(action, { status, data, message })
|
||||
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) => {
|
||||
ipcRenderer.send(action, { data, status, message })
|
||||
}
|
||||
|
||||
let isInitedApi = false
|
||||
let isShowedUpdateAlert = false
|
||||
const EVENT_NAMES = {
|
||||
request: 'request',
|
||||
inited: 'inited',
|
||||
updateAlert: 'updateAlert',
|
||||
}
|
||||
const eventNames = Object.values(EVENT_NAMES)
|
||||
const events = {
|
||||
@@ -35,7 +41,7 @@ const supportActions = {
|
||||
|
||||
const handleRequest = (context, { requestKey, data }) => {
|
||||
// console.log(data)
|
||||
if (!events.request) return sendMessage(USER_API_RENDERER_EVENT_NAME.response, false, { requestKey }, 'Request event is not defined')
|
||||
if (!events.request) return sendMessage(USER_API_RENDERER_EVENT_NAME.response, { requestKey }, false, 'Request event is not defined')
|
||||
try {
|
||||
events.request.call(context, { source: data.source, action: data.action, info: data.info }).then(response => {
|
||||
let sendData = {
|
||||
@@ -53,12 +59,12 @@ const handleRequest = (context, { requestKey, data }) => {
|
||||
}
|
||||
break
|
||||
}
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.response, true, sendData)
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.response, sendData, true)
|
||||
}).catch(err => {
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.response, false, { requestKey }, err.message)
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.response, { requestKey }, false, err.message)
|
||||
})
|
||||
} catch (err) {
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.response, false, { requestKey }, err.message)
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.response, { requestKey }, false, err.message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +86,7 @@ const handleRequest = (context, { requestKey, data }) => {
|
||||
*/
|
||||
const handleInit = (context, info) => {
|
||||
if (!info) {
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, false, null, 'Init failed')
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, null, false, 'Init failed')
|
||||
// sendMessage(USER_API_RENDERER_EVENT_NAME.init, false, null, typeof info.message === 'string' ? info.message.substring(0, 100) : '')
|
||||
return
|
||||
}
|
||||
@@ -88,7 +94,7 @@ const handleInit = (context, info) => {
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.openDevTools)
|
||||
}
|
||||
if (!info.status) {
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, false, null, 'Init failed')
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, null, false, 'Init failed')
|
||||
// sendMessage(USER_API_RENDERER_EVENT_NAME.init, false, null, typeof info.message === 'string' ? info.message.substring(0, 100) : '')
|
||||
return
|
||||
}
|
||||
@@ -109,16 +115,28 @@ const handleInit = (context, info) => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, false, null, error.message)
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, null, false, error.message)
|
||||
return
|
||||
}
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, true, sourceInfo)
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.init, sourceInfo, true)
|
||||
|
||||
ipcRenderer.on(USER_API_RENDERER_EVENT_NAME.request, (event, data) => {
|
||||
handleRequest(context, data)
|
||||
})
|
||||
}
|
||||
|
||||
const handleShowUpdateAlert = (data, resolve, reject) => {
|
||||
if (!data || typeof data != 'object') return reject(new Error('parameter format error.'))
|
||||
if (!data.log || typeof data.log != 'string') return reject(new Error('log is required.'))
|
||||
if (data.updateUrl && !/^https?:\/\/[^\s$.?#].[^\s]*$/.test(data.updateUrl) && data.updateUrl.length > 1024) delete data.updateUrl
|
||||
if (data.log.length > 1024) data.log = data.log.substring(0, 1024) + '...'
|
||||
sendMessage(USER_API_RENDERER_EVENT_NAME.showUpdateAlert, {
|
||||
log: data.log,
|
||||
updateUrl: data.updateUrl,
|
||||
})
|
||||
resolve()
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('lx', {
|
||||
EVENT_NAMES,
|
||||
request(url, { method = 'get', timeout, headers, body, form, formData }, callback) {
|
||||
@@ -151,7 +169,7 @@ contextBridge.exposeInMainWorld('lx', {
|
||||
headers: resp.headers,
|
||||
bytes: resp.bytes,
|
||||
raw: resp.raw,
|
||||
body: body,
|
||||
body,
|
||||
}, body)
|
||||
}).request
|
||||
|
||||
@@ -165,12 +183,18 @@ contextBridge.exposeInMainWorld('lx', {
|
||||
if (!eventNames.includes(eventName)) return reject(new Error('The event is not supported: ' + eventName))
|
||||
switch (eventName) {
|
||||
case EVENT_NAMES.inited:
|
||||
if (isInitedApi) return
|
||||
if (isInitedApi) return reject(new Error('Script is inited'))
|
||||
isInitedApi = true
|
||||
handleInit(this, data)
|
||||
resolve()
|
||||
break
|
||||
case EVENT_NAMES.updateAlert:
|
||||
if (isShowedUpdateAlert) return reject(new Error('The update alert can only be called once.'))
|
||||
isShowedUpdateAlert = true
|
||||
handleShowUpdateAlert(data, resolve, reject)
|
||||
break
|
||||
default:
|
||||
resolve(new Error('Unknown event name: ' + eventName))
|
||||
reject(new Error('Unknown event name: ' + eventName))
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -180,7 +204,9 @@ contextBridge.exposeInMainWorld('lx', {
|
||||
case EVENT_NAMES.request:
|
||||
events.request = handler
|
||||
break
|
||||
default: return Promise.reject(new Error('The event is not supported: ' + eventName))
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
utils: {
|
||||
crypto: {
|
||||
@@ -190,7 +216,7 @@ contextBridge.exposeInMainWorld('lx', {
|
||||
},
|
||||
rsaEncrypt(buffer, key) {
|
||||
buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer])
|
||||
return publicEncrypt({ key: key, padding: constants.RSA_NO_PADDING }, buffer)
|
||||
return publicEncrypt({ key, padding: constants.RSA_NO_PADDING }, buffer)
|
||||
},
|
||||
randomBytes(size) {
|
||||
return randomBytes(size)
|
||||
@@ -208,7 +234,7 @@ contextBridge.exposeInMainWorld('lx', {
|
||||
},
|
||||
},
|
||||
},
|
||||
version: '1.1.0',
|
||||
version: '1.2.0',
|
||||
// removeEvent(eventName, handler) {
|
||||
// if (!eventNames.includes(eventName)) return Promise.reject(new Error('The event is not supported: ' + eventName))
|
||||
// let handlers
|
||||
|
||||
@@ -3,6 +3,7 @@ const names = {
|
||||
request: '',
|
||||
response: '',
|
||||
openDevTools: '',
|
||||
showUpdateAlert: '',
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ const { mainOn, mainSend } = require('@common/ipc')
|
||||
const USER_API_RENDERER_EVENT_NAME = require('../rendererEvent/name')
|
||||
const { createWindow } = require('../main')
|
||||
const { getUserApis } = require('../utils')
|
||||
const { openDevTools } = require('@main/utils')
|
||||
|
||||
let userApi
|
||||
let status = { status: true }
|
||||
@@ -32,14 +33,22 @@ const handleResponse = (event, { status, data: { requestKey, result }, message }
|
||||
}
|
||||
const handleOpenDevTools = () => {
|
||||
if (global.modules.userApiWindow) {
|
||||
global.modules.userApiWindow.webContents.openDevTools({
|
||||
mode: 'undocked',
|
||||
})
|
||||
openDevTools(global.modules.userApiWindow.webContents)
|
||||
}
|
||||
}
|
||||
const handleShowUpdateAlert = (event, { data }) => {
|
||||
if (!userApi.allowShowUpdateAlert) return
|
||||
global.lx_event.userApi.showUpdateAlert({
|
||||
name: userApi.name,
|
||||
description: userApi.description,
|
||||
log: data.log,
|
||||
updateUrl: data.updateUrl,
|
||||
})
|
||||
}
|
||||
mainOn(USER_API_RENDERER_EVENT_NAME.init, handleInit)
|
||||
mainOn(USER_API_RENDERER_EVENT_NAME.response, handleResponse)
|
||||
mainOn(USER_API_RENDERER_EVENT_NAME.openDevTools, handleOpenDevTools)
|
||||
mainOn(USER_API_RENDERER_EVENT_NAME.showUpdateAlert, handleShowUpdateAlert)
|
||||
|
||||
exports.loadApi = async apiId => {
|
||||
if (!apiId) return global.lx_event.userApi.status(status = { status: false, message: 'api id is null' })
|
||||
@@ -82,3 +91,8 @@ exports.request = ({ requestKey, data }) => new Promise((resolve, reject) => {
|
||||
})
|
||||
|
||||
exports.getStatus = () => status
|
||||
|
||||
exports.setAllowShowUpdateAlert = (id, enable) => {
|
||||
if (!userApi || userApi.id != id) return
|
||||
userApi.allowShowUpdateAlert = enable
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ exports.getUserApis = () => {
|
||||
userApis = defaultUserApis
|
||||
electronStore_userApi.set('userApis', userApis)
|
||||
}
|
||||
for (const api of userApis) {
|
||||
if (api.allowShowUpdateAlert == null) api.allowShowUpdateAlert = false
|
||||
}
|
||||
return userApis
|
||||
}
|
||||
|
||||
@@ -27,6 +30,7 @@ exports.importApi = script => {
|
||||
name,
|
||||
description,
|
||||
script,
|
||||
allowShowUpdateAlert: true,
|
||||
}
|
||||
userApis.push(apiInfo)
|
||||
getStore('userApi').set('userApis', userApis)
|
||||
@@ -42,3 +46,10 @@ exports.removeApi = ids => {
|
||||
}
|
||||
getStore('userApi').set('userApis', userApis)
|
||||
}
|
||||
|
||||
exports.setAllowShowUpdateAlert = (id, enable) => {
|
||||
const targetApi = userApis.find(api => api.id == id)
|
||||
if (!targetApi) return
|
||||
targetApi.allowShowUpdateAlert = enable
|
||||
getStore('userApi').set('userApis', userApis)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,40 @@ const { common: COMMON_EVENT_NAME, winLyric: WIN_LYRIC_EVENT_NAME, hotKey: HOT_K
|
||||
const { mainSend, NAMES: { winLyric: ipcWinLyricNames } } = require('../../../common/ipc')
|
||||
const { desktop_lyric } = require('../../../common/hotKey')
|
||||
const { getLyricWindowBounds } = require('./utils')
|
||||
const { isLinux } = require('@common/utils')
|
||||
|
||||
let isLock = null
|
||||
let isEnable = null
|
||||
let isAlwaysOnTop = null
|
||||
let isAlwaysOnTopLoop = null
|
||||
let isLockScreen = null
|
||||
let isHoverHide = null
|
||||
|
||||
const alwaysOnTopTools = {
|
||||
timeout: null,
|
||||
alwaysOnTop: false,
|
||||
setAlwaysOnTop(flag, isLoop) {
|
||||
this.alwaysOnTop = flag
|
||||
this.clearLoop()
|
||||
global.modules.lyricWindow.setAlwaysOnTop(flag, 'screen-saver')
|
||||
console.log(isLoop)
|
||||
if (flag && isLoop) this.startLoop()
|
||||
},
|
||||
startLoop() {
|
||||
if (!this.alwaysOnTop) return
|
||||
this.timeout = setInterval(() => {
|
||||
if (!global.modules.lyricWindow) return this.clearLoop()
|
||||
global.modules.lyricWindow.setAlwaysOnTop(true, 'screen-saver')
|
||||
}, 1000)
|
||||
},
|
||||
clearLoop() {
|
||||
if (!this.timeout) return
|
||||
clearInterval(this.timeout)
|
||||
this.timeout = null
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
const setLrcConfig = () => {
|
||||
let desktopLyric = global.appSetting.desktopLyric
|
||||
if (global.modules.lyricWindow) {
|
||||
@@ -14,19 +43,34 @@ const setLrcConfig = () => {
|
||||
config: desktopLyric,
|
||||
languageId: global.appSetting.langId,
|
||||
isShowLyricTranslation: global.appSetting.player.isShowLyricTranslation,
|
||||
isShowLyricRoma: global.appSetting.player.isShowLyricRoma,
|
||||
isPlayLxlrc: global.appSetting.player.isPlayLxlrc,
|
||||
})
|
||||
if (isLock != desktopLyric.isLock) {
|
||||
isLock = desktopLyric.isLock
|
||||
if (desktopLyric.isLock) {
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: false })
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: !isLinux && global.appSetting.desktopLyric.isHoverHide })
|
||||
} else {
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(false)
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(false, { forward: !isLinux && global.appSetting.desktopLyric.isHoverHide })
|
||||
}
|
||||
}
|
||||
if (isHoverHide != desktopLyric.isHoverHide) {
|
||||
isHoverHide = desktopLyric.isHoverHide
|
||||
if (!isLinux) {
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(desktopLyric.isLock, { forward: global.appSetting.desktopLyric.isHoverHide })
|
||||
}
|
||||
}
|
||||
if (isAlwaysOnTop != desktopLyric.isAlwaysOnTop) {
|
||||
isAlwaysOnTop = desktopLyric.isAlwaysOnTop
|
||||
global.modules.lyricWindow.setAlwaysOnTop(desktopLyric.isAlwaysOnTop, 'screen-saver')
|
||||
alwaysOnTopTools.setAlwaysOnTop(desktopLyric.isAlwaysOnTop, desktopLyric.isAlwaysOnTopLoop)
|
||||
}
|
||||
if (isAlwaysOnTopLoop != desktopLyric.isAlwaysOnTopLoop) {
|
||||
isAlwaysOnTopLoop = desktopLyric.isAlwaysOnTopLoop
|
||||
if (isAlwaysOnTopLoop) {
|
||||
alwaysOnTopTools.startLoop()
|
||||
} else {
|
||||
alwaysOnTopTools.clearLoop()
|
||||
}
|
||||
}
|
||||
if (isLockScreen != desktopLyric.isLockScreen) {
|
||||
isLockScreen = desktopLyric.isLockScreen
|
||||
@@ -45,6 +89,7 @@ const setLrcConfig = () => {
|
||||
if (desktopLyric.enable) {
|
||||
global.lx_event.winLyric.create()
|
||||
} else {
|
||||
alwaysOnTopTools.clearLoop()
|
||||
global.lx_event.winLyric.close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ const winEvent = lyricWindow => {
|
||||
lyricWindow.once('ready-to-show', () => {
|
||||
lyricWindow.show()
|
||||
if (global.appSetting.desktopLyric.isLock) {
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: false })
|
||||
global.modules.lyricWindow.setIgnoreMouseEvents(true, { forward: !isLinux && global.appSetting.desktopLyric.isHoverHide })
|
||||
}
|
||||
// linux下每次重开时貌似要重新设置置顶
|
||||
if (isLinux && global.appSetting.desktopLyric.isAlwaysOnTop) {
|
||||
|
||||
@@ -28,6 +28,7 @@ mainHandle(ipcWinLyricNames.get_lyric_config, async() => {
|
||||
config: global.appSetting.desktopLyric,
|
||||
languageId: global.appSetting.langId,
|
||||
isShowLyricTranslation: global.appSetting.player.isShowLyricTranslation,
|
||||
isShowLyricRoma: global.appSetting.player.isShowLyricRoma,
|
||||
isPlayLxlrc: global.appSetting.player.isPlayLxlrc,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
const { isWin } = require('@common/utils')
|
||||
// require('./request')
|
||||
// require('./appName')
|
||||
require('./progressBar')
|
||||
@@ -22,8 +22,11 @@ require('./musicUrl')
|
||||
require('./systemFonts')
|
||||
require('./wait')
|
||||
require('./openDevtools')
|
||||
require('./nativeTheme')
|
||||
|
||||
// require('./kw_decodeLyric')
|
||||
if (isWin) require('./taskbar')
|
||||
|
||||
require('./kw_decodeLyric')
|
||||
|
||||
require('./userApi')
|
||||
require('./sync')
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
const { mainOn, NAMES: { mainWindow: ipcMainWindowNames }, mainHandle } = require('../../common/ipc')
|
||||
const getStore = require('@common/store')
|
||||
|
||||
const LRC_RAW = 'lyrics'
|
||||
const LRC_EDITED = 'lyrics_edited'
|
||||
|
||||
mainHandle(ipcMainWindowNames.get_lyric, async(event, id) => getStore('lyrics', true, false).get(id) || {})
|
||||
mainHandle(ipcMainWindowNames.get_lyric, async(event, id) => {
|
||||
return getStore(LRC_EDITED, true, false).get(id) || getStore(LRC_RAW, true, false).get(id) || {}
|
||||
})
|
||||
|
||||
|
||||
mainOn(ipcMainWindowNames.save_lyric, (event, { id, lyrics }) => getStore('lyrics', true, false).set(id, lyrics))
|
||||
// 原始歌词
|
||||
mainHandle(ipcMainWindowNames.get_lyric_raw, async(event, id) => getStore(LRC_RAW, true, false).get(id) || {})
|
||||
mainOn(ipcMainWindowNames.save_lyric_raw, (event, { id, lyrics }) => getStore(LRC_RAW, true, false).set(id, lyrics))
|
||||
mainOn(ipcMainWindowNames.clear_lyric_raw, () => getStore(LRC_RAW, true, false).clear())
|
||||
|
||||
mainOn(ipcMainWindowNames.clear_lyric, () => getStore('lyrics', true, false).clear())
|
||||
// 已编辑的歌词
|
||||
mainHandle(ipcMainWindowNames.get_lyric_edited, async(event, id) => getStore(LRC_EDITED, true, false).get(id) || {})
|
||||
mainOn(ipcMainWindowNames.save_lyric_edited, (event, { id, lyrics }) => getStore(LRC_EDITED, true, false).set(id, lyrics))
|
||||
mainOn(ipcMainWindowNames.remove_lyric_edited, async(event, id) => getStore(LRC_EDITED, true, false).delete(id))
|
||||
|
||||
11
src/main/rendererEvents/nativeTheme.js
Normal file
11
src/main/rendererEvents/nativeTheme.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const { nativeTheme } = require('electron')
|
||||
|
||||
const { NAMES: { mainWindow: ipcMainWindowNames }, mainSend } = require('@common/ipc')
|
||||
|
||||
nativeTheme.addListener('updated', (event) => {
|
||||
// console.log(event.sender.shouldUseDarkColors)
|
||||
if (!global.modules.mainWindow) return
|
||||
mainSend(global.modules.mainWindow, ipcMainWindowNames.system_theme_change, event.sender.shouldUseDarkColors)
|
||||
// console.log(nativeTheme.themeSource)
|
||||
})
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
const { mainOn, NAMES: { mainWindow: ipcMainWindowNames } } = require('../../common/ipc')
|
||||
const { openDevTools } = require('@main/utils')
|
||||
|
||||
mainOn(ipcMainWindowNames.open_dev_tools, event => {
|
||||
if (global.modules.mainWindow) {
|
||||
if (global.modules.mainWindow.isDevToolsOpened()) {
|
||||
global.modules.mainWindow.webContents.closeDevTools()
|
||||
} else {
|
||||
global.modules.mainWindow.webContents.openDevTools({
|
||||
mode: 'undocked',
|
||||
})
|
||||
openDevTools(global.modules.mainWindow.webContents)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -23,6 +23,7 @@ const handleSaveList = ({ defaultList, loveList, userList, tempList }) => {
|
||||
getStore('playList').set(data)
|
||||
}
|
||||
mainOn(ipcMainWindowNames.save_playlist, (event, { type, data }) => {
|
||||
data = JSON.parse(data)
|
||||
switch (type) {
|
||||
case 'myList':
|
||||
handleSaveList(data)
|
||||
|
||||
18
src/main/rendererEvents/taskbar.js
Normal file
18
src/main/rendererEvents/taskbar.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const { mainSend, mainOn, NAMES: { mainWindow: ipcMainWindowNames }, mainHandle } = require('@common/ipc')
|
||||
const { setThumbnailClip, setThumbarButtons, eventNames } = require('../modules/taskbar')
|
||||
const { mainWindow: MAIN_WINDOW_EVENT_NAME } = require('@main/events/_name')
|
||||
|
||||
const handleThumbarButtonClick = action => {
|
||||
mainSend(global.modules.mainWindow, ipcMainWindowNames.taskbar_on_thumbar_button_click, action)
|
||||
}
|
||||
|
||||
global.lx_event.taskbar.on(eventNames.thumbarButtonClick, handleThumbarButtonClick)
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_EVENT_NAME.show, setThumbarButtons)
|
||||
|
||||
mainHandle(ipcMainWindowNames.taskbar_set_thumbnail_clip, (event, clip) => {
|
||||
return setThumbnailClip(clip)
|
||||
})
|
||||
|
||||
mainOn(ipcMainWindowNames.taskbar_set_thumbar_buttons, (event, buttons) => {
|
||||
setThumbarButtons(buttons)
|
||||
})
|
||||
@@ -1,5 +1,6 @@
|
||||
const { app } = require('electron')
|
||||
const { mainOn, NAMES: { mainWindow: ipcMainWindowNames } } = require('../../common/ipc')
|
||||
const { mainOn, mainHandle, NAMES: { mainWindow: ipcMainWindowNames } } = require('../../common/ipc')
|
||||
const { isLinux } = require('@common/utils')
|
||||
|
||||
mainOn(ipcMainWindowNames.min, event => {
|
||||
if (global.modules.mainWindow) {
|
||||
@@ -16,3 +17,18 @@ mainOn(ipcMainWindowNames.close, (event, isForce) => {
|
||||
global.isTrafficLightClose = true
|
||||
if (global.modules.mainWindow) global.modules.mainWindow.close()
|
||||
})
|
||||
mainHandle(ipcMainWindowNames.fullscreen, async(event, isFullscreen) => {
|
||||
if (!global.modules.mainWindow) return false
|
||||
if (isLinux) { // linux 需要先设置为可调整窗口大小才能全屏
|
||||
if (isFullscreen) {
|
||||
await global.modules.mainWindow.setResizable(isFullscreen)
|
||||
await global.modules.mainWindow.setFullScreen(isFullscreen)
|
||||
} else {
|
||||
await global.modules.mainWindow.setFullScreen(isFullscreen)
|
||||
await global.modules.mainWindow.setResizable(isFullscreen)
|
||||
}
|
||||
} else {
|
||||
await global.modules.mainWindow.setFullScreen(isFullscreen)
|
||||
}
|
||||
return isFullscreen
|
||||
})
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
const { mainSend, mainHandle, NAMES: { mainWindow: ipcMainWindowNames } } = require('@common/ipc')
|
||||
const { getApiList, importApi, removeApi, setApi, getStatus, request, cancelRequest, eventNames } = require('../modules/userApi')
|
||||
const { getApiList, importApi, removeApi, setApi, getStatus, request, cancelRequest, eventNames, setAllowShowUpdateAlert } = require('../modules/userApi')
|
||||
|
||||
const handleStatusChange = status => {
|
||||
mainSend(global.modules.mainWindow, ipcMainWindowNames.user_api_status, status)
|
||||
}
|
||||
const handleShowUpdateAlert = info => {
|
||||
mainSend(global.modules.mainWindow, ipcMainWindowNames.user_api_show_update_alert, info)
|
||||
}
|
||||
|
||||
global.lx_event.userApi.on(eventNames.status, handleStatusChange)
|
||||
global.lx_event.userApi.on(eventNames.showUpdateAlert, handleShowUpdateAlert)
|
||||
|
||||
mainHandle(ipcMainWindowNames.import_user_api, async(event, script) => {
|
||||
return importApi(script)
|
||||
@@ -27,6 +31,10 @@ mainHandle(ipcMainWindowNames.get_user_api_status, event => {
|
||||
return getStatus()
|
||||
})
|
||||
|
||||
mainHandle(ipcMainWindowNames.user_api_set_allow_update_alert, (event, { id, enable }) => {
|
||||
return setAllowShowUpdateAlert(id, enable)
|
||||
})
|
||||
|
||||
mainHandle(ipcMainWindowNames.request_user_api, (event, musicInfo) => {
|
||||
return request(musicInfo)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { mainOn, mainHandle, NAMES: { mainWindow: ipcMainWindowNames } } = require('@common/ipc')
|
||||
const { mainOn, mainHandle, mainSend, NAMES: { mainWindow: ipcMainWindowNames } } = require('@common/ipc')
|
||||
|
||||
const timeoutMap = new Map()
|
||||
|
||||
@@ -23,3 +23,24 @@ mainOn(ipcMainWindowNames.wait_cancel, (event, id) => {
|
||||
clearTimeout(timeout.timeout)
|
||||
timeout.reject('cancelled')
|
||||
})
|
||||
|
||||
mainOn(ipcMainWindowNames.interval, (event, { time, id }) => {
|
||||
if (timeoutMap.has(id)) return
|
||||
const timeout = setInterval(() => {
|
||||
if (global.modules.mainWindow) mainSend(global.modules.mainWindow, ipcMainWindowNames.interval_callback, id)
|
||||
}, time)
|
||||
|
||||
timeoutMap.set(id, {
|
||||
timeout,
|
||||
type: 'interval',
|
||||
time,
|
||||
})
|
||||
})
|
||||
|
||||
mainOn(ipcMainWindowNames.interval_cancel, (event, id) => {
|
||||
if (!timeoutMap.has(id)) return
|
||||
const timeout = timeoutMap.get(id)
|
||||
timeoutMap.delete(id)
|
||||
if (timeout.type != 'interval') return
|
||||
clearInterval(timeout.timeout)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { isWin } = require('../../common/utils')
|
||||
const { openDevTools } = require('@main/utils')
|
||||
const { mainSend, NAMES: { mainWindow: ipcMainWindowNames } } = require('../../common/ipc')
|
||||
global.isQuitting = false
|
||||
global.isTrafficLightClose = false // 是否点击软件上的关闭按钮关闭
|
||||
@@ -25,11 +26,17 @@ module.exports = mainWindow => {
|
||||
// })
|
||||
mainWindow.on('focus', () => {
|
||||
mainSend(mainWindow, ipcMainWindowNames.focus)
|
||||
global.lx_event.mainWindow.focus()
|
||||
})
|
||||
|
||||
mainWindow.on('blur', () => {
|
||||
global.lx_event.mainWindow.blur()
|
||||
})
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
global.lx_event.mainWindow.readyToShow()
|
||||
if (global.envParams.cmdParams.debug) openDevTools(global.modules.mainWindow.webContents)
|
||||
})
|
||||
|
||||
mainWindow.on('show', () => {
|
||||
|
||||
@@ -41,3 +41,9 @@ exports.initSetting = (isShowErrorAlert = true) => {
|
||||
global.appSetting = info.setting
|
||||
global.appSettingVersion = info.version
|
||||
}
|
||||
|
||||
exports.openDevTools = webContents => {
|
||||
webContents.openDevTools({
|
||||
mode: 'undocked',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template lang="pug">
|
||||
#container(:class="[theme, lrcConfig.isLock ? 'lock' : null]")
|
||||
#main
|
||||
#container(:class="[theme, { lock: lrcConfig.isLock }, { hide: isHoverHide && isMouseEnter }]")
|
||||
#main(@mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @mousemove="handleMouseMoveMain")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
.control-bar(v-show="!lrcConfig.isLock")
|
||||
core-control-bar(:lrcConfig="lrcConfig" :themes="themeList")
|
||||
core-lyric(:lrcConfig="lrcConfig" :isPlayLxlrc="isPlayLxlrc" :isShowLyricTranslation="isShowLyricTranslation")
|
||||
core-lyric(:lrcConfig="lrcConfig" :isPlayLxlrc="isPlayLxlrc" :isShowLyricTranslation="isShowLyricTranslation" :isShowLyricRoma="isShowLyricRoma")
|
||||
div.resize-left(@mousedown.self="handleMouseDown('left', $event)" @touchstart.self="handleTouchDown('left', $event)")
|
||||
div.resize-top(@mousedown.self="handleMouseDown('top', $event)" @touchstart.self="handleTouchDown('top', $event)")
|
||||
div.resize-right(@mousedown.self="handleMouseDown('right', $event)" @touchstart.self="handleTouchDown('right', $event)")
|
||||
@@ -21,6 +21,51 @@ import { rendererOn, rendererInvoke, rendererSend, NAMES } from '../common/ipc'
|
||||
|
||||
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 {
|
||||
data() {
|
||||
return {
|
||||
@@ -39,6 +84,7 @@ export default {
|
||||
x: -1,
|
||||
y: -1,
|
||||
theme: 0,
|
||||
isHoverHide: false,
|
||||
style: {
|
||||
font: '',
|
||||
fontSize: 125,
|
||||
@@ -46,7 +92,8 @@ export default {
|
||||
isZoomActiveLrc: true,
|
||||
},
|
||||
},
|
||||
isShowLyricTranslation: true,
|
||||
isShowLyricTranslation: false,
|
||||
isShowLyricRoma: false,
|
||||
isPlayLxlrc: true,
|
||||
themeList: [
|
||||
{
|
||||
@@ -90,6 +137,7 @@ export default {
|
||||
className: 'blue2',
|
||||
},
|
||||
],
|
||||
isMouseEnter: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -97,6 +145,9 @@ export default {
|
||||
let theme = this.themeList.find(t => t.id == this.lrcConfig.theme) || this.themeList[0]
|
||||
return theme.className
|
||||
},
|
||||
isHoverHide() {
|
||||
return this.lrcConfig.isLock && this.lrcConfig.isHoverHide
|
||||
},
|
||||
},
|
||||
created() {
|
||||
rendererOn(NAMES.winLyric.set_lyric_config, (event, config) => this.handleUpdateConfig(config))
|
||||
@@ -111,9 +162,10 @@ export default {
|
||||
document.removeEventListener('mouseup', this.handleMouseUp)
|
||||
},
|
||||
methods: {
|
||||
handleUpdateConfig({ config, languageId, isShowLyricTranslation, isPlayLxlrc }) {
|
||||
handleUpdateConfig({ config, languageId, isShowLyricTranslation, isShowLyricRoma, isPlayLxlrc }) {
|
||||
this.lrcConfig = config
|
||||
this.isShowLyricTranslation = isShowLyricTranslation
|
||||
this.isShowLyricRoma = isShowLyricRoma
|
||||
this.isPlayLxlrc = isPlayLxlrc
|
||||
if (this.$i18n.locale !== languageId && languageId != null) this.$i18n.locale = languageId
|
||||
},
|
||||
@@ -145,7 +197,7 @@ export default {
|
||||
}
|
||||
},
|
||||
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
|
||||
// console.log(event.target)
|
||||
let bounds = {
|
||||
@@ -209,6 +261,24 @@ export default {
|
||||
// handleMouseOver() {
|
||||
// // 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>
|
||||
@@ -238,11 +308,16 @@ body {
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
transition: opacity .3s ease;
|
||||
opacity: 1;
|
||||
&.lock {
|
||||
#main {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
&.hide {
|
||||
opacity: .05;
|
||||
}
|
||||
}
|
||||
|
||||
.resize-left {
|
||||
|
||||
@@ -23,6 +23,9 @@ article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
html {
|
||||
font-family: "Microsoft YaHei", "Microsoft Jhenghei", "PingFang SC", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Helvetica, Arial, "Hiragino Sans GB", "Source Han Sans", "Noto Sans CJK Sc", sans-serif;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
@@ -41,3 +44,6 @@ table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
button {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ div(:class="$style.container")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { rendererSend, rendererOn, NAMES } from '../../../common/ipc'
|
||||
import { rendererSend, NAMES } from '../../../common/ipc'
|
||||
import { toRaw } from 'vue'
|
||||
|
||||
export default {
|
||||
@@ -108,9 +108,6 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.config = JSON.parse(JSON.stringify(this.lrcConfig))
|
||||
rendererOn(NAMES.winLyric.key_down, (event, key) => {
|
||||
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
sendEvent() {
|
||||
|
||||
@@ -40,6 +40,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isShowLyricRoma: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -74,6 +78,7 @@ export default {
|
||||
lyrics: {
|
||||
lyric: '',
|
||||
tlyric: '',
|
||||
rlyric: '',
|
||||
lxlyric: '',
|
||||
},
|
||||
}
|
||||
@@ -143,6 +148,10 @@ export default {
|
||||
this.setLyric()
|
||||
rendererSend(NAMES.winLyric.get_lyric_info, 'status')
|
||||
},
|
||||
isShowLyricRoma() {
|
||||
this.setLyric()
|
||||
rendererSend(NAMES.winLyric.get_lyric_info, 'status')
|
||||
},
|
||||
isPlayLxlrc() {
|
||||
this.setLyric()
|
||||
rendererSend(NAMES.winLyric.get_lyric_info, 'status')
|
||||
@@ -172,7 +181,6 @@ export default {
|
||||
this.lyric.lines = lines
|
||||
this.lyric.line = 0
|
||||
},
|
||||
offset: 100,
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
@@ -196,6 +204,7 @@ export default {
|
||||
case 'lyric':
|
||||
this.lyrics.lyric = data.lrc
|
||||
this.lyrics.tlyric = data.tlrc
|
||||
this.lyrics.rlyric = data.rlrc
|
||||
this.lyrics.lxlyric = data.lxlrc
|
||||
this.setLyric()
|
||||
break
|
||||
@@ -207,15 +216,26 @@ export default {
|
||||
this.isPlay = false
|
||||
window.lrc.pause()
|
||||
break
|
||||
case 'stop':
|
||||
this.isPlay = false
|
||||
this.lyrics.lyric = ''
|
||||
this.lyrics.tlyric = ''
|
||||
this.lyrics.lxlyric = ''
|
||||
this.lyrics.rlyric = ''
|
||||
this.setLyric()
|
||||
break
|
||||
case 'info':
|
||||
// console.log('info', data)
|
||||
this.lyrics.lyric = data.lrc
|
||||
this.lyrics.tlyric = data.tlrc
|
||||
this.lyrics.rlyric = data.rlrc
|
||||
this.lyrics.lxlyric = data.lxlrc
|
||||
this.setLyric()
|
||||
this.$nextTick(() => {
|
||||
this.lyric.line = data.line
|
||||
rendererSend(NAMES.winLyric.get_lyric_info, 'status')
|
||||
setTimeout(() => {
|
||||
rendererSend(NAMES.winLyric.get_lyric_info, 'status')
|
||||
})
|
||||
})
|
||||
case 'music_info':
|
||||
this.musicInfo.name = data.name
|
||||
@@ -335,10 +355,12 @@ export default {
|
||||
rendererSend(NAMES.winLyric.close)
|
||||
},
|
||||
setLyric() {
|
||||
const extendedLyrics = []
|
||||
if (this.isShowLyricTranslation && this.lyrics.tlyric) extendedLyrics.push(this.lyrics.tlyric)
|
||||
if (this.isShowLyricRoma && this.lyrics.rlyric) extendedLyrics.push(this.lyrics.rlyric)
|
||||
window.lrc.setLyric(
|
||||
this.isPlayLxlrc && this.lyrics.lxlyric ? this.lyrics.lxlyric : this.lyrics.lyric,
|
||||
this.isShowLyricTranslation && this.lyrics.tlyric ? this.lyrics.tlyric : '',
|
||||
// (this.isShowLyricTranslation && this.lyrics.tlyric ? (this.lyrics.tlyric + '\n') : '') + (this.lyrics.lyric || ''),
|
||||
extendedLyrics,
|
||||
)
|
||||
},
|
||||
},
|
||||
@@ -367,11 +389,11 @@ export default {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.font, .translation {
|
||||
.font, .extended {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.translation {
|
||||
.extended {
|
||||
transition: @transition-theme !important;
|
||||
transition-property: font-size, color;
|
||||
font-size: 0.8em;
|
||||
@@ -388,7 +410,7 @@ export default {
|
||||
.line {
|
||||
color: @color-theme;
|
||||
}
|
||||
.translation {
|
||||
.extended {
|
||||
color: @color-theme;
|
||||
}
|
||||
// span {
|
||||
@@ -457,7 +479,7 @@ export default {
|
||||
.draging {
|
||||
:global {
|
||||
.lrc-content {
|
||||
.font, .translation {
|
||||
.font, .extended {
|
||||
cursor: grabbing;
|
||||
}
|
||||
}
|
||||
@@ -467,7 +489,7 @@ export default {
|
||||
:global {
|
||||
.lrc-content {
|
||||
&.active {
|
||||
.translation {
|
||||
.extended {
|
||||
font-size: .94em;
|
||||
}
|
||||
span {
|
||||
@@ -500,7 +522,7 @@ each(@themes, {
|
||||
:global {
|
||||
.lrc-content {
|
||||
&.active {
|
||||
.translation {
|
||||
.extended {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
.line {
|
||||
|
||||
@@ -14,20 +14,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useRefGetter, watch, onMounted } from '@renderer/utils/vueTools'
|
||||
import { onMounted } from '@renderer/utils/vueTools'
|
||||
import useApp from '@renderer/core/useApp'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const theme = useRefGetter('theme')
|
||||
|
||||
const dom_root = document.getElementById('root')
|
||||
|
||||
watch(theme, (val) => {
|
||||
dom_root.className = val
|
||||
})
|
||||
dom_root.className = theme.value
|
||||
|
||||
useApp()
|
||||
|
||||
onMounted(() => {
|
||||
@@ -78,13 +71,13 @@ body {
|
||||
|
||||
.transparent {
|
||||
padding: @shadow-app;
|
||||
#waiting-mask {
|
||||
border-radius: @radius-border;
|
||||
left: @shadow-app;
|
||||
right: @shadow-app;
|
||||
top: @shadow-app;
|
||||
bottom: @shadow-app;
|
||||
}
|
||||
// #waiting-mask {
|
||||
// border-radius: @radius-border;
|
||||
// left: @shadow-app;
|
||||
// right: @shadow-app;
|
||||
// top: @shadow-app;
|
||||
// bottom: @shadow-app;
|
||||
// }
|
||||
#root {
|
||||
box-shadow: 0 0 @shadow-app rgba(0, 0, 0, 0.5);
|
||||
border-radius: @radius-border;
|
||||
@@ -103,8 +96,16 @@ body {
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#view { // 偏移5px距离解决非透明模式下右侧滚动条无法拖动的问题
|
||||
margin-right: 5Px;
|
||||
// #view { // 偏移5px距离解决非透明模式下右侧滚动条无法拖动的问题
|
||||
// margin-right: 5Px;
|
||||
// }
|
||||
}
|
||||
.fullscreen {
|
||||
background-color: #fff;
|
||||
|
||||
#right {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ table {
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
// border-top: 1px solid rgba(0, 0, 0, 0.12);
|
||||
transition: background-color 0.2s ease;
|
||||
transition: 0.2s ease;
|
||||
transition-property: background-color, color;
|
||||
border-bottom: 1px solid @color-theme_2-line;
|
||||
box-sizing: border-box;
|
||||
&:hover {
|
||||
@@ -102,7 +103,7 @@ table {
|
||||
flex: none;
|
||||
padding: 0 6px;
|
||||
position: relative;
|
||||
transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
// transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
@@ -223,13 +224,13 @@ input, textarea {
|
||||
border-radius: 3px;
|
||||
background-color: @color-scrollbar-thumb;
|
||||
// background-color: rgba(0, 0, 0, 0.2);
|
||||
transition: all 0.4s ease;
|
||||
transition: background-color 0.4s ease;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
border-radius: 3px;
|
||||
background-color: @color-scrollbar-thumb-hover;
|
||||
// background-color: rgba(0, 0, 0, 0.4);
|
||||
transition: all 0.4s ease;
|
||||
transition: background-color 0.4s ease;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
html {
|
||||
font-family: "Microsoft YaHei", "Microsoft Jhenghei", "PingFang SC", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Helvetica, Arial, "Hiragino Sans GB", "Source Han Sans", "Noto Sans CJK Sc", sans-serif;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
@@ -41,3 +44,6 @@ table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
button {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
@color-player-pic-c2: darken(@color-theme_2, 30%);
|
||||
@color-player-progress: darken(@color-theme_2, 6%);
|
||||
@color-player-progress-bar1: darken(@color-theme_2, 12%);
|
||||
@color-player-progress-bar2: lighten(@color-theme, 12%);
|
||||
@color-player-progress-bar2: fadeout(lighten(@color-theme, 12%), 20%);
|
||||
@color-player-status-text: lighten(@color-theme_2-font, 32%);
|
||||
@color-player-detail-lyric: fadeout(@color-theme_2-font, 40%);
|
||||
@color-player-detail-lyric-active: darken(@color-theme, 2%);
|
||||
@@ -114,7 +114,7 @@
|
||||
@color-green-player-pic-c2: darken(@color-green-theme_2, 30%);
|
||||
@color-green-player-progress: darken(@color-green-theme_2, 6%);
|
||||
@color-green-player-progress-bar1: darken(@color-green-theme_2, 12%);
|
||||
@color-green-player-progress-bar2: lighten(@color-green-theme, 12%);
|
||||
@color-green-player-progress-bar2: fadeout(lighten(@color-green-theme, 12%), 20%);
|
||||
@color-green-player-status-text: lighten(@color-green-theme_2-font, 32%);
|
||||
@color-green-player-detail-lyric: fadeout(@color-green-theme_2-font, 40%);
|
||||
@color-green-player-detail-lyric-active: darken(@color-green-theme, 2%);
|
||||
@@ -174,7 +174,7 @@
|
||||
@color-yellow-player-pic-c2: darken(@color-yellow-theme_2, 30%);
|
||||
@color-yellow-player-progress: darken(@color-yellow-theme_2, 6%);
|
||||
@color-yellow-player-progress-bar1: darken(@color-yellow-theme_2, 12%);
|
||||
@color-yellow-player-progress-bar2: lighten(@color-yellow-theme, 2%);
|
||||
@color-yellow-player-progress-bar2: fadeout(lighten(@color-yellow-theme, 2%), 20%);
|
||||
@color-yellow-player-status-text: lighten(@color-yellow-theme_2-font, 32%);
|
||||
@color-yellow-player-detail-lyric: fadeout(@color-yellow-theme_2-font, 40%);
|
||||
@color-yellow-player-detail-lyric-active: darken(@color-yellow-theme, 7%);
|
||||
@@ -233,7 +233,7 @@
|
||||
@color-orange-player-pic-c2: darken(@color-orange-theme_2, 30%);
|
||||
@color-orange-player-progress: darken(@color-orange-theme_2, 6%);
|
||||
@color-orange-player-progress-bar1: darken(@color-orange-theme_2, 12%);
|
||||
@color-orange-player-progress-bar2: lighten(@color-orange-theme, 12%);
|
||||
@color-orange-player-progress-bar2: fadeout(lighten(@color-orange-theme, 12%), 20%);
|
||||
@color-orange-player-status-text: lighten(@color-orange-theme_2-font, 32%);
|
||||
@color-orange-player-detail-lyric: fadeout(@color-orange-theme_2-font, 40%);
|
||||
@color-orange-player-detail-lyric-active: darken(@color-orange-theme, 7%);
|
||||
@@ -292,7 +292,7 @@
|
||||
@color-blue-player-pic-c2: darken(@color-blue-theme_2, 30%);
|
||||
@color-blue-player-progress: darken(@color-blue-theme_2, 6%);
|
||||
@color-blue-player-progress-bar1: darken(@color-blue-theme_2, 12%);
|
||||
@color-blue-player-progress-bar2: lighten(@color-blue-theme, 12%);
|
||||
@color-blue-player-progress-bar2: fadeout(lighten(@color-blue-theme, 12%), 20%);
|
||||
@color-blue-player-status-text: lighten(@color-blue-theme_2-font, 32%);
|
||||
@color-blue-player-detail-lyric: fadeout(@color-blue-theme_2-font, 40%);
|
||||
@color-blue-player-detail-lyric-active: darken(@color-blue-theme, 2%);
|
||||
@@ -351,7 +351,7 @@
|
||||
@color-red-player-pic-c2: darken(@color-red-theme_2, 30%);
|
||||
@color-red-player-progress: darken(@color-red-theme_2, 6%);
|
||||
@color-red-player-progress-bar1: darken(@color-red-theme_2, 12%);
|
||||
@color-red-player-progress-bar2: lighten(@color-red-theme, 12%);
|
||||
@color-red-player-progress-bar2: fadeout(lighten(@color-red-theme, 12%), 20%);
|
||||
@color-red-player-status-text: lighten(@color-red-theme_2-font, 32%);
|
||||
@color-red-player-detail-lyric: fadeout(@color-red-theme_2-font, 40%);
|
||||
@color-red-player-detail-lyric-active: lighten(@color-red-theme, 2%);
|
||||
@@ -412,7 +412,7 @@
|
||||
@color-pink-player-pic-c2: darken(@color-pink-theme_2, 30%);
|
||||
@color-pink-player-progress: darken(@color-pink-theme_2, 6%);
|
||||
@color-pink-player-progress-bar1: darken(@color-pink-theme_2, 12%);
|
||||
@color-pink-player-progress-bar2: lighten(@color-pink-theme, 2%);
|
||||
@color-pink-player-progress-bar2: fadeout(lighten(@color-pink-theme, 2%), 20%);
|
||||
@color-pink-player-status-text: lighten(@color-pink-theme_2-font, 32%);
|
||||
@color-pink-player-detail-lyric: fadeout(@color-pink-theme_2-font, 40%);
|
||||
@color-pink-player-detail-lyric-active: darken(@color-pink-theme, 2%);
|
||||
@@ -471,7 +471,7 @@
|
||||
@color-purple-player-pic-c2: darken(@color-purple-theme_2, 30%);
|
||||
@color-purple-player-progress: darken(@color-purple-theme_2, 6%);
|
||||
@color-purple-player-progress-bar1: darken(@color-purple-theme_2, 12%);
|
||||
@color-purple-player-progress-bar2: lighten(@color-purple-theme, 12%);
|
||||
@color-purple-player-progress-bar2: fadeout(lighten(@color-purple-theme, 12%), 20%);
|
||||
@color-purple-player-status-text: lighten(@color-purple-theme_2-font, 32%);
|
||||
@color-purple-player-detail-lyric: fadeout(@color-purple-theme_2-font, 40%);
|
||||
@color-purple-player-detail-lyric-active: darken(@color-purple-theme, 2%);
|
||||
@@ -530,7 +530,7 @@
|
||||
@color-grey-player-pic-c2: darken(@color-grey-theme_2, 30%);
|
||||
@color-grey-player-progress: darken(@color-grey-theme_2, 6%);
|
||||
@color-grey-player-progress-bar1: darken(@color-grey-theme_2, 12%);
|
||||
@color-grey-player-progress-bar2: lighten(@color-grey-theme, 12%);
|
||||
@color-grey-player-progress-bar2: fadeout(lighten(@color-grey-theme, 12%), 20%);
|
||||
@color-grey-player-status-text: lighten(@color-grey-theme_2-font, 32%);
|
||||
@color-grey-player-detail-lyric: fadeout(@color-grey-theme_2-font, 55%);
|
||||
@color-grey-player-detail-lyric-active: darken(@color-grey-theme, 3%);
|
||||
@@ -590,7 +590,7 @@
|
||||
@color-ming-player-pic-c2: darken(@color-ming-theme_2, 30%);
|
||||
@color-ming-player-progress: darken(@color-ming-theme_2, 6%);
|
||||
@color-ming-player-progress-bar1: darken(@color-ming-theme_2, 12%);
|
||||
@color-ming-player-progress-bar2: lighten(@color-ming-theme, 12%);
|
||||
@color-ming-player-progress-bar2: fadeout(lighten(@color-ming-theme, 12%), 20%);
|
||||
@color-ming-player-status-text: lighten(@color-ming-theme_2-font, 32%);
|
||||
@color-ming-player-detail-lyric: fadeout(@color-ming-theme_2-font, 50%);
|
||||
@color-ming-player-detail-lyric-active: lighten(@color-ming-theme, 2%);
|
||||
@@ -652,7 +652,7 @@
|
||||
@color-blue2-player-pic-c2: darken(@color-blue2-theme_2, 30%);
|
||||
@color-blue2-player-progress: darken(@color-blue2-theme_2, 6%);
|
||||
@color-blue2-player-progress-bar1: darken(@color-blue2-theme_2, 12%);
|
||||
@color-blue2-player-progress-bar2: lighten(@color-blue2-theme, 12%);
|
||||
@color-blue2-player-progress-bar2: fadeout(lighten(@color-blue2-theme, 12%), 20%);
|
||||
@color-blue2-player-status-text: lighten(@color-blue2-theme_2-font, 32%);
|
||||
@color-blue2-player-detail-lyric: fadeout(@color-blue2-theme_2-font, 50%);
|
||||
@color-blue2-player-detail-lyric-active: darken(@color-blue2-theme, 2%);
|
||||
@@ -683,7 +683,7 @@
|
||||
@color-black-theme-active: fadeout(lighten(@color-black-theme, 8%), 30%);
|
||||
@color-black-theme-font: lighten(@color-black-theme, 55%);
|
||||
@color-black-theme-font-label: lighten(@color-black-theme, 35%);
|
||||
@color-black-theme_2: rgba(19, 19, 19, 0.82);
|
||||
@color-black-theme_2: rgba(19, 19, 19, 0.93);
|
||||
@color-black-theme_2-background_1: #080808;
|
||||
@color-black-theme_2-background_2: #1f1f1f;
|
||||
@color-black-theme_2-hover: fadeout(lighten(@color-black-theme, 10%), 80%);
|
||||
@@ -710,9 +710,9 @@
|
||||
@color-black-scrollbar-thumb-hover: fadeout(lighten(@color-black-theme, 10%), 35%);
|
||||
@color-black-player-pic-c1: fadeout(@color-black-theme_2, 50%);
|
||||
@color-black-player-pic-c2: lighten(@color-black-theme_2, 30%);
|
||||
@color-black-player-progress: lighten(@color-black-theme_2, 6%);
|
||||
@color-black-player-progress: fadeout(lighten(@color-black-theme, 20%), 80%);
|
||||
@color-black-player-progress-bar1: lighten(@color-black-theme_2, 12%);
|
||||
@color-black-player-progress-bar2: lighten(@color-black-theme, 12%);
|
||||
@color-black-player-progress-bar2: fadeout(lighten(@color-black-theme, 12%), 20%);
|
||||
@color-black-player-status-text: darken(@color-black-theme_2-font, 20%);
|
||||
@color-black-player-detail-lyric: fadeout(darken(@color-black-theme_2-font, 30%), 10%);
|
||||
@color-black-player-detail-lyric-active: lighten(@color-black-theme, 50%);
|
||||
@@ -770,9 +770,9 @@
|
||||
@color-mid_autumn-scrollbar-thumb-hover: fadeout(lighten(@color-mid_autumn-theme, 10%), 40%);
|
||||
@color-mid_autumn-player-pic-c1: fadeout(@color-mid_autumn-theme_2, 50%);
|
||||
@color-mid_autumn-player-pic-c2: darken(@color-mid_autumn-theme_2, 30%);
|
||||
@color-mid_autumn-player-progress: darken(@color-mid_autumn-theme_2, 10%);
|
||||
@color-mid_autumn-player-progress: fadeout(lighten(@color-mid_autumn-theme, 20%), 82%);
|
||||
@color-mid_autumn-player-progress-bar1: darken(@color-mid_autumn-theme_2, 12%);
|
||||
@color-mid_autumn-player-progress-bar2: lighten(@color-mid_autumn-theme, 12%);
|
||||
@color-mid_autumn-player-progress-bar2: fadeout(lighten(@color-mid_autumn-theme, 12%), 20%);
|
||||
@color-mid_autumn-player-status-text: lighten(@color-mid_autumn-theme_2-font, 32%);
|
||||
@color-mid_autumn-player-detail-lyric: fadeout(@color-mid_autumn-theme_2-font, 40%);
|
||||
@color-mid_autumn-player-detail-lyric-active: lighten(@color-mid_autumn-theme, 7%);
|
||||
@@ -832,7 +832,7 @@
|
||||
@color-mid_autumn-player-pic-c2: darken(@color-mid_autumn-theme_2, 30%);
|
||||
@color-mid_autumn-player-progress: darken(@color-mid_autumn-theme_2, 10%);
|
||||
@color-mid_autumn-player-progress-bar1: darken(@color-mid_autumn-theme_2, 12%);
|
||||
@color-mid_autumn-player-progress-bar2: lighten(@color-mid_autumn-theme, 12%);
|
||||
@color-mid_autumn-player-progress-bar2: fadeout(lighten(@color-mid_autumn-theme, 12%), 20%);
|
||||
@color-mid_autumn-player-status-text: lighten(@color-mid_autumn-theme_2-font, 32%);
|
||||
@color-mid_autumn-player-detail-lyric: lighten(@color-mid_autumn-theme, 7%);
|
||||
@color-mid_autumn-player-detail-lyric-active: lighten(@color-mid_autumn-theme, 7%);
|
||||
@@ -889,9 +889,9 @@
|
||||
@color-naruto-scrollbar-thumb-hover: fadeout(lighten(@color-naruto-theme, 10%), 35%);
|
||||
@color-naruto-player-pic-c1: fadeout(@color-naruto-theme_2, 50%);
|
||||
@color-naruto-player-pic-c2: darken(@color-naruto-theme_2, 30%);
|
||||
@color-naruto-player-progress: darken(@color-naruto-theme_2, 10%);
|
||||
@color-naruto-player-progress: fadeout(lighten(@color-naruto-theme, 20%), 70%);
|
||||
@color-naruto-player-progress-bar1: darken(@color-naruto-theme_2, 12%);
|
||||
@color-naruto-player-progress-bar2: lighten(@color-naruto-theme, 12%);
|
||||
@color-naruto-player-progress-bar2: fadeout(lighten(@color-naruto-theme, 12%), 20%);
|
||||
@color-naruto-player-status-text: lighten(@color-naruto-theme_2-font, 32%);
|
||||
@color-naruto-player-detail-lyric: fadeout(@color-naruto-theme_2-font, 36%);
|
||||
@color-naruto-player-detail-lyric-active: darken(@color-naruto-theme, 7%);
|
||||
@@ -948,9 +948,9 @@
|
||||
@color-happy_new_year-scrollbar-thumb-hover: fadeout(lighten(@color-happy_new_year-theme, 10%), 35%);
|
||||
@color-happy_new_year-player-pic-c1: fadeout(@color-happy_new_year-theme_2, 50%);
|
||||
@color-happy_new_year-player-pic-c2: darken(@color-happy_new_year-theme_2, 30%);
|
||||
@color-happy_new_year-player-progress: darken(@color-happy_new_year-theme_2, 10%);
|
||||
@color-happy_new_year-player-progress: fadeout(lighten(@color-happy_new_year-theme, 20%), 82%);
|
||||
@color-happy_new_year-player-progress-bar1: darken(@color-happy_new_year-theme_2, 5%);
|
||||
@color-happy_new_year-player-progress-bar2: lighten(@color-happy_new_year-theme, 5%);
|
||||
@color-happy_new_year-player-progress-bar2: fadeout(lighten(@color-happy_new_year-theme, 5%), 20%);
|
||||
@color-happy_new_year-player-status-text: lighten(@color-happy_new_year-theme_2-font, 32%);
|
||||
@color-happy_new_year-player-detail-lyric: fadeout(@color-happy_new_year-theme_2-font, 36%);
|
||||
@color-happy_new_year-player-detail-lyric-active: darken(@color-happy_new_year-theme, 7%);
|
||||
|
||||
3
src/renderer/assets/svgs/fullscreen-exit.svg
Normal file
3
src/renderer/assets/svgs/fullscreen-exit.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M14,14H19V16H16V19H14V14M5,14H10V19H8V16H5V14M8,5H10V10H5V8H8V5M19,8V10H14V5H16V8H19Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 187 B |
1
src/renderer/assets/svgs/headphones.svg
Normal file
1
src/renderer/assets/svgs/headphones.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H18A3,3 0 0,0 21,17V10C21,5 16.97,1 12,1Z" /></svg>
|
||||
|
After Width: | Height: | Size: 422 B |
1
src/renderer/assets/svgs/music.svg
Normal file
1
src/renderer/assets/svgs/music.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M21,3V15.5A3.5,3.5 0 0,1 17.5,19A3.5,3.5 0 0,1 14,15.5A3.5,3.5 0 0,1 17.5,12C18.04,12 18.55,12.12 19,12.34V6.47L9,8.6V17.5A3.5,3.5 0 0,1 5.5,21A3.5,3.5 0 0,1 2,17.5A3.5,3.5 0 0,1 5.5,14C6.04,14 6.55,14.12 7,14.34V6L21,3Z" /></svg>
|
||||
|
After Width: | Height: | Size: 515 B |
@@ -41,6 +41,7 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'change'],
|
||||
data() {
|
||||
return {
|
||||
bool: false,
|
||||
|
||||
@@ -24,7 +24,7 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<ul :class="$style.list" :style="listStyles" ref="dom_list">
|
||||
<ul :class="$style.list" :style="listStyles" ref="dom_list" role="toolbar" :aria-hidden="!show">
|
||||
<li v-for="item in menus"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
:aria-label="item[itemName]"
|
||||
ignore-tip
|
||||
:key="item.action"
|
||||
@click="handleClick(item)"
|
||||
v-show="!item.hide && (item.action == 'download' ? setting.download.enable : true)"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<ul class="selection-list scroll" :class="$style.list" :style="listStyles" ref="dom_list">
|
||||
<li v-for="(item, index) in list" :key="index" :class="(itemKey ? item[itemKey] : item) == modelValue ? $style.active : null"
|
||||
@click="handleClick(item)" :tips="itemName ? item[itemName] : item">{{itemName ? item[itemName] : item}}</li>
|
||||
@click="handleClick(item)" :aria-label="itemName ? item[itemName] : item">{{itemName ? item[itemName] : item}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -141,8 +141,8 @@ export default {
|
||||
const scrollContainerHeight = dom_scrollContainer.value.clientHeight
|
||||
const currentEndIndex = currentStartIndex + Math.ceil(scrollContainerHeight / itemHeight)
|
||||
const continuous = currentStartIndex <= endIndex && currentEndIndex >= startIndex
|
||||
const currentStartRenderIndex = Math.max(Math.floor(currentScrollTop / itemHeight) - props.outsideNum, 0)
|
||||
const currentEndRenderIndex = currentStartIndex + Math.ceil(scrollContainerHeight / itemHeight) + props.outsideNum
|
||||
const currentStartRenderIndex = Math.max(currentStartIndex - props.outsideNum, 0)
|
||||
const currentEndRenderIndex = currentEndIndex + props.outsideNum + 1
|
||||
// console.log(continuous)
|
||||
// debugger
|
||||
if (continuous) {
|
||||
@@ -161,7 +161,7 @@ export default {
|
||||
// // console.log('scroll up')
|
||||
// views.value = createList(currentStartRenderIndex, currentEndRenderIndex)
|
||||
// } else return
|
||||
if (currentScrollTop == scrollTop) return
|
||||
if (currentScrollTop == scrollTop && endIndex >= currentEndIndex) return
|
||||
views.value = createList(currentStartRenderIndex, currentEndRenderIndex)
|
||||
} else {
|
||||
views.value = createList(currentStartRenderIndex, currentEndRenderIndex)
|
||||
@@ -215,19 +215,28 @@ export default {
|
||||
return isScrolling ? scrollToValue : dom_scrollContainer.value.scrollTop
|
||||
}
|
||||
|
||||
const handleResize = () => {
|
||||
setTimeout(updateView)
|
||||
}
|
||||
|
||||
const contentStyle = computed(() => ({
|
||||
display: 'block',
|
||||
height: props.list.length * props.itemHeight + 'px',
|
||||
}))
|
||||
|
||||
watch(() => props.itemHeight, updateView)
|
||||
watch(() => props.list, (list) => {
|
||||
const handleReset = list => {
|
||||
cachedList = Array(list.length)
|
||||
startIndex = -1
|
||||
endIndex = -1
|
||||
nextTick(() => {
|
||||
updateView()
|
||||
})
|
||||
}
|
||||
watch(() => props.itemHeight, () => {
|
||||
handleReset(props.list)
|
||||
})
|
||||
watch(() => props.list, (list) => {
|
||||
handleReset(list)
|
||||
}, {
|
||||
deep: true,
|
||||
})
|
||||
@@ -238,9 +247,11 @@ export default {
|
||||
startIndex = -1
|
||||
endIndex = -1
|
||||
updateView()
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
dom_scrollContainer.value.removeEventListener('scroll', onScroll)
|
||||
window.removeEventListener('resize', handleResize)
|
||||
if (cancelScroll) cancelScroll()
|
||||
})
|
||||
|
||||
|
||||
@@ -23,19 +23,32 @@ const themes = {
|
||||
blue2: 'rgba(79,98,208,.14)',
|
||||
black: 'rgba(39,39,39,.4)',
|
||||
mid_autumn: 'rgba(74,55,82,.1)',
|
||||
naruto: 'rgba(87,144,167,.14)',
|
||||
naruto: 'rgba(87,144,167,.15)',
|
||||
happy_new_year: 'rgba(192,57,43,.1)',
|
||||
}
|
||||
|
||||
const getBarWidth = canvasWidth => {
|
||||
let barWidth = (canvasWidth / 128) * 2.5
|
||||
const width = canvasWidth / 86
|
||||
const diffWidth = barWidth - width
|
||||
// console.log(barWidth - width)
|
||||
// if (barWidth - width > 20) newBarWidth = 20
|
||||
// barWidth = newBarWidth
|
||||
return diffWidth > 32
|
||||
? canvasWidth / 128 // 4k屏、超宽屏直接显示所有频谱条
|
||||
: diffWidth > 12 ? width : barWidth
|
||||
}
|
||||
export default {
|
||||
setup() {
|
||||
const dom_canvas = ref(null)
|
||||
const analyser = getAnalyser()
|
||||
|
||||
let ctx
|
||||
let bufferLength
|
||||
let bufferLength = 0
|
||||
let dataArray
|
||||
let WIDTH
|
||||
let HEIGHT
|
||||
let MAX_HEIGHT
|
||||
let barWidth
|
||||
let barHeight
|
||||
let x = 0
|
||||
@@ -89,7 +102,7 @@ export default {
|
||||
// let b = 50
|
||||
|
||||
// ctx.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')'
|
||||
barHeight = barHeight * frequencyAvg + barHeight * 0.42
|
||||
barHeight = (barHeight * frequencyAvg + barHeight * 0.42) * MAX_HEIGHT
|
||||
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight)
|
||||
|
||||
x += barWidth
|
||||
@@ -101,7 +114,7 @@ export default {
|
||||
analyser.fftSize = 256
|
||||
bufferLength = analyser.frequencyBinCount
|
||||
// console.log(bufferLength)
|
||||
barWidth = (WIDTH / bufferLength) * 2.5
|
||||
barWidth = getBarWidth(WIDTH)
|
||||
dataArray = new Uint8Array(bufferLength)
|
||||
renderFrame()
|
||||
}
|
||||
@@ -110,14 +123,27 @@ export default {
|
||||
isPlaying = false
|
||||
}
|
||||
|
||||
const handleResize = () => {
|
||||
const canvas = dom_canvas.value
|
||||
canvas.width = canvas.clientWidth
|
||||
canvas.height = canvas.clientHeight
|
||||
WIDTH = canvas.width
|
||||
HEIGHT = canvas.height
|
||||
MAX_HEIGHT = Math.round(HEIGHT * 0.4 / 255 * 10000) / 10000
|
||||
// console.log(MAX_HEIGHT)
|
||||
barWidth = getBarWidth(WIDTH)
|
||||
}
|
||||
|
||||
window.eventHub.on(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.on(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.on(eventPlayerNames.error, handlePause)
|
||||
window.addEventListener('resize', handleResize)
|
||||
onBeforeUnmount(() => {
|
||||
handlePause()
|
||||
window.eventHub.off(eventPlayerNames.play, handlePlay)
|
||||
window.eventHub.off(eventPlayerNames.pause, handlePause)
|
||||
window.eventHub.off(eventPlayerNames.error, handlePause)
|
||||
window.removeEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
@@ -127,6 +153,8 @@ export default {
|
||||
canvas.height = canvas.clientHeight
|
||||
WIDTH = canvas.width
|
||||
HEIGHT = canvas.height
|
||||
MAX_HEIGHT = Math.round(HEIGHT * 0.4 / 255 * 10000) / 10000
|
||||
// console.log(MAX_HEIGHT)
|
||||
if (isPlay.value) handlePlay()
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<main :class="$style.main">
|
||||
<h2>{{ info.name }}<br/>{{ info.singer }}</h2>
|
||||
<base-btn :class="$style.btn" :key="type.type" @click="handleClick(type.type)" v-for="type in types"
|
||||
>{{getTypeName(type.type)}} {{ type.type.toUpperCase() }}{{ type.size && ` - ${type.size.toUpperCase()}` }}</base-btn>
|
||||
>{{getTypeName(type.type)}}{{ type.size && ` - ${type.size.toUpperCase()}` }}</base-btn>
|
||||
</main>
|
||||
</material-modal>
|
||||
</template>
|
||||
@@ -55,15 +55,17 @@ export default {
|
||||
},
|
||||
getTypeName(type) {
|
||||
switch (type) {
|
||||
case 'flac32bit':
|
||||
return this.$t('download__lossless') + ' FLAC Hires'
|
||||
case 'flac':
|
||||
case 'ape':
|
||||
case 'wav':
|
||||
return this.$t('download__lossless')
|
||||
return this.$t('download__lossless') + ' ' + type.toUpperCase()
|
||||
case '320k':
|
||||
return this.$t('download__high_quality')
|
||||
return this.$t('download__high_quality') + ' ' + type.toUpperCase()
|
||||
case '192k':
|
||||
case '128k':
|
||||
return this.$t('download__normal')
|
||||
return this.$t('download__normal') + ' ' + type.toUpperCase()
|
||||
}
|
||||
},
|
||||
checkSource(type) {
|
||||
@@ -79,7 +81,7 @@ export default {
|
||||
|
||||
.main {
|
||||
padding: 15px;
|
||||
max-width: 300px;
|
||||
max-width: 400px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<base-btn :class="$style.btn" @click="handleClick('128k')">{{$t('download__normal')}} - 128K</base-btn>
|
||||
<base-btn :class="$style.btn" @click="handleClick('320k')">{{$t('download__high_quality')}} - 320K</base-btn>
|
||||
<base-btn :class="$style.btn" @click="handleClick('flac')">{{$t('download__lossless')}} - FLAC</base-btn>
|
||||
<base-btn :class="$style.btn" @click="handleClick('flac32bit')">{{$t('download__lossless')}} - FLAC Hires</base-btn>
|
||||
</main>
|
||||
</material-modal>
|
||||
</template>
|
||||
@@ -51,7 +52,7 @@ export default {
|
||||
|
||||
.main {
|
||||
padding: 15px;
|
||||
max-width: 300px;
|
||||
max-width: 400px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose" :teleport="teleport">
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose" :teleport="teleport" max-width="70%">
|
||||
<main :class="$style.main">
|
||||
<h2>{{$t('list_add__' + (isMove ? 'title_first_move' : 'title_first_add'))}} <span :class="$style.name">{{this.musicInfo && `${musicInfo.name}`}}</span> {{$t('list_add__title_last')}}</h2>
|
||||
<div class="scroll" :class="$style.btnContent">
|
||||
<base-btn :class="$style.btn" :tips="$t('list_add__btn_title', { name: item.name })" :key="item.id" :disabled="item.isExist" @click="handleClick(index)" v-for="(item, index) in lists">{{item.name}}</base-btn>
|
||||
<base-btn :class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :tips="$t('lists__new_list_btn')">
|
||||
<base-btn :class="$style.btn" :aria-label="$t('list_add__btn_title', { name: item.name })" :key="item.id" :disabled="item.isExist" @click="handleClick(index)" v-for="(item, index) in lists">{{item.name}}</base-btn>
|
||||
<base-btn :class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :aria-label="$t('lists__new_list_btn')">
|
||||
<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>
|
||||
</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>
|
||||
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
||||
</div>
|
||||
@@ -21,6 +21,7 @@ import { mapMutations } from 'vuex'
|
||||
import { computed } from '@renderer/utils/vueTools'
|
||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
import useKeyDown from '@renderer/utils/compositions/useKeyDown'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -57,6 +58,8 @@ export default {
|
||||
},
|
||||
emits: ['update:show'],
|
||||
setup(props) {
|
||||
const keyModDown = useKeyDown('mod')
|
||||
|
||||
const lists = computed(() => {
|
||||
if (!props.musicInfo) return []
|
||||
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) }))
|
||||
})
|
||||
return {
|
||||
keyModDown,
|
||||
lists,
|
||||
}
|
||||
},
|
||||
@@ -74,19 +78,37 @@ export default {
|
||||
return {
|
||||
isEditing: false,
|
||||
newListName: '',
|
||||
rowNum: 3,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
spaceNum() {
|
||||
return this.lists.length < 2 ? 0 : (3 - this.lists.length % 3 - 1)
|
||||
return this.lists.length < 2 ? 0 : (this.rowNum - this.lists.length % this.rowNum - 1)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
this.handleResize()
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('list', ['listAdd', 'listMove', 'createUserList']),
|
||||
handleResize() {
|
||||
const width = window.innerWidth
|
||||
this.rowNum = width < 1920
|
||||
? 3
|
||||
: width < 2560
|
||||
? 4
|
||||
: width < 3840 ? 5 : 6
|
||||
},
|
||||
handleClick(index) {
|
||||
this.isMove
|
||||
? this.listMove({ fromId: this.fromListId, toId: 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.handleClose()
|
||||
})
|
||||
@@ -117,7 +139,7 @@ export default {
|
||||
|
||||
.main {
|
||||
// padding: 15px 0;
|
||||
max-width: 620px;
|
||||
// max-width: 70%;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
@@ -147,14 +169,17 @@ export default {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
@item-width: (100% / 3);
|
||||
.btn {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
margin-left: 15px;
|
||||
margin-bottom: 15px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px !important;
|
||||
width: 180px;
|
||||
width: calc(@item-width - 15px);
|
||||
min-width: 160px;
|
||||
.mixin-ellipsis-1;
|
||||
}
|
||||
|
||||
@@ -181,6 +206,9 @@ export default {
|
||||
}
|
||||
}
|
||||
.newListInput {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
border: none;
|
||||
@@ -191,9 +219,30 @@ export default {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
font-family: inherit;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@item-width2: (100% / 4);
|
||||
@media (min-width: 1920px){
|
||||
.btn {
|
||||
width: calc(@item-width2 - 15px);
|
||||
}
|
||||
}
|
||||
@item-width3: (100% / 5);
|
||||
@media (min-width: 2560px){
|
||||
.btn {
|
||||
width: calc(@item-width3 - 15px);
|
||||
}
|
||||
}
|
||||
@item-width4: (100% / 6);
|
||||
@media (min-width: 3840px){
|
||||
.btn {
|
||||
width: calc(@item-width4 - 15px);
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.main {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose">
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose" max-width="70%">
|
||||
<main :class="$style.main">
|
||||
<h2>{{$t('list_add__multiple_' + (isMove ? 'title_move' : 'title_add'), { num: musicList.length })}}</h2>
|
||||
<div class="scroll" :class="$style.btnContent">
|
||||
<base-btn :class="$style.btn" :tips="$t('list_add__multiple_btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists">{{item.name}}</base-btn>
|
||||
<base-btn :class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :tips="$t('lists__new_list_btn')">
|
||||
<base-btn :class="$style.btn" :aria-label="$t('list_add__multiple_btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists">{{item.name}}</base-btn>
|
||||
<base-btn :class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :aria-label="$t('lists__new_list_btn')">
|
||||
<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>
|
||||
</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>
|
||||
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
||||
</div>
|
||||
@@ -20,6 +20,7 @@
|
||||
import { mapMutations } from 'vuex'
|
||||
import { computed } from '@renderer/utils/vueTools'
|
||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
import useKeyDown from '@renderer/utils/compositions/useKeyDown'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -59,6 +60,8 @@ export default {
|
||||
},
|
||||
emits: ['update:show', 'confirm'],
|
||||
setup(props) {
|
||||
const keyModDown = useKeyDown('mod')
|
||||
|
||||
const lists = computed(() => {
|
||||
return [
|
||||
defaultList,
|
||||
@@ -67,6 +70,7 @@ export default {
|
||||
].filter(l => !props.excludeListId.includes(l.id))
|
||||
})
|
||||
return {
|
||||
keyModDown,
|
||||
lists,
|
||||
}
|
||||
},
|
||||
@@ -74,20 +78,38 @@ export default {
|
||||
return {
|
||||
isEditing: false,
|
||||
newListName: '',
|
||||
rowNum: 3,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
spaceNum() {
|
||||
return this.lists.length < 2 ? 0 : (3 - this.lists.length % 3 - 1)
|
||||
return this.lists.length < 2 ? 0 : (this.rowNum - this.lists.length % this.rowNum - 1)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
this.handleResize()
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('list', ['listAddMultiple', 'listMoveMultiple', 'createUserList']),
|
||||
handleResize() {
|
||||
const width = window.innerWidth
|
||||
this.rowNum = width < 1920
|
||||
? 3
|
||||
: width < 2560
|
||||
? 4
|
||||
: width < 3840 ? 5 : 6
|
||||
},
|
||||
handleClick(index) {
|
||||
this.isMove
|
||||
? this.listMoveMultiple({ fromId: this.fromListId, toId: 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.handleClose()
|
||||
this.$emit('confirm')
|
||||
@@ -119,7 +141,7 @@ export default {
|
||||
|
||||
.main {
|
||||
// padding: 15px 0;
|
||||
max-width: 620px;
|
||||
// max-width: 620px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
@@ -145,14 +167,17 @@ export default {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
@item-width: (100% / 3);
|
||||
.btn {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
margin-left: 15px;
|
||||
margin-bottom: 15px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px !important;
|
||||
width: 180px;
|
||||
width: calc(@item-width - 15px);
|
||||
min-width: 160px;
|
||||
.mixin-ellipsis-1;
|
||||
}
|
||||
|
||||
@@ -179,6 +204,9 @@ export default {
|
||||
}
|
||||
}
|
||||
.newListInput {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
border: none;
|
||||
@@ -189,9 +217,31 @@ export default {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
font-family: inherit;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@item-width2: (100% / 4);
|
||||
@media (min-width: 1920px){
|
||||
.btn {
|
||||
width: calc(@item-width2 - 15px);
|
||||
}
|
||||
}
|
||||
@item-width3: (100% / 5);
|
||||
@media (min-width: 2560px){
|
||||
.btn {
|
||||
width: calc(@item-width3 - 15px);
|
||||
}
|
||||
}
|
||||
@item-width4: (100% / 6);
|
||||
@media (min-width: 3840px){
|
||||
.btn {
|
||||
width: calc(@item-width4 - 15px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.main {
|
||||
|
||||
@@ -125,14 +125,13 @@ export default {
|
||||
|
||||
.progress-bar2 {
|
||||
background-color: @color-player-progress-bar2;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
|
||||
opacity: 0.8;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.progress-bar3 {
|
||||
background-color: @color-player-progress-bar2;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
|
||||
opacity: 0.3;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.bar-transition {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div :class="[$style.volume, {[$style.muted]: setting.player.isMute} ]">
|
||||
<div :class="$style.volumeBar" ref="dom_volumeBar" :style="{ transform: `scaleX(${volume || 0})` }"></div>
|
||||
</div>
|
||||
<div :class="$style.volumeMask" @mousedown="handleVolumeMsDown" :tips="`${$t('player__volume')}${parseInt(volume * 100)}%`"></div>
|
||||
<div :class="$style.volumeMask" @mousedown="handleVolumeMsDown" :aria-label="`${$t('player__volume')}${parseInt(volume * 100)}%`"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div :class="$style.controlBtn">
|
||||
<button type="button" :class="[$style.btn, $style.close]" :tips="$t('close')" @click="close">
|
||||
<div :class="$style.controlBtn" v-show="!isFullscreen">
|
||||
<button type="button" :class="[$style.btn, $style.close]" :aria-label="$t('close')" @click="close">
|
||||
<svg :class="$style.controlBtniIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve">
|
||||
<use xlink:href="#icon-window-close"></use>
|
||||
</svg>
|
||||
</button>
|
||||
<button type="button" :class="[$style.btn, $style.min]" :tips="$t('min')" @click="min">
|
||||
<button type="button" :class="[$style.btn, $style.min]" :aria-label="$t('min')" @click="min">
|
||||
<svg :class="$style.controlBtniIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve">
|
||||
<use xlink:href="#icon-window-minimize"></use>
|
||||
</svg>
|
||||
@@ -16,10 +16,12 @@
|
||||
<script>
|
||||
import { base as eventBaseName } from '@renderer/event/names'
|
||||
// import { getRandom } from '../../utils'
|
||||
import { isFullscreen } from '@renderer/core/share'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
return {
|
||||
isFullscreen,
|
||||
min() {
|
||||
window.eventHub.emit(eventBaseName.min)
|
||||
},
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div :class="$style.menu">
|
||||
<ul :class="$style.list">
|
||||
<li v-for="item in menus" :key="item.to">
|
||||
<router-link :class="$style.link" :active-class="$style.active" :to="item.to" :tips="item.tips">
|
||||
<ul :class="$style.list" role="toolbar">
|
||||
<li v-for="item in menus" :key="item.to" :class="$style.navItem" role="presentation">
|
||||
<router-link :class="$style.link" :active-class="$style.active" role="tab" :aria-selected="$route.name == item.to" :to="item.to" :aria-label="item.tips">
|
||||
<div :class="$style.icon">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" :viewBox="item.iconSize" space="preserve">
|
||||
<use :xlink:href="item.icon"></use>
|
||||
@@ -98,13 +98,26 @@ export default {
|
||||
// .mixin-ellipsis-1;
|
||||
// }
|
||||
}
|
||||
.navItem {
|
||||
position: relative;
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding-bottom: 84%;
|
||||
}
|
||||
}
|
||||
.link {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// display: block;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
|
||||
position: relative;
|
||||
padding: 18px 3px;
|
||||
// padding: 18px 3px;
|
||||
// margin: 5px 0;
|
||||
// border-left: 5px solid transparent;
|
||||
transition: @transition-theme;
|
||||
@@ -114,6 +127,9 @@ export default {
|
||||
font-size: 11.5px;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
transition: background-color 0.3s ease;
|
||||
// border-radius: @radius-border;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="$style.aside">
|
||||
<div :class="[$style.aside, { [$style.fullscreen]: isFullscreen }]">
|
||||
<ControlBtns v-if="setting.controlBtnPosition == 'left'" />
|
||||
<div :class="$style.logo" v-else>L X</div>
|
||||
<NavBar />
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { isFullscreen } from '@renderer/core/share'
|
||||
|
||||
import ControlBtns from './ControlBtns'
|
||||
import NavBar from './NavBar'
|
||||
@@ -15,6 +16,11 @@ import NavBar from './NavBar'
|
||||
export default {
|
||||
name: 'CoreAside',
|
||||
components: { ControlBtns, NavBar },
|
||||
setup() {
|
||||
return {
|
||||
isFullscreen,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['setting']),
|
||||
},
|
||||
@@ -36,6 +42,13 @@ export default {
|
||||
-webkit-user-select: none;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
|
||||
&.fullscreen {
|
||||
-webkit-app-region: no-drag;
|
||||
.logo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' style="display: none;")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' style="display: none;" aria-hidden="true")
|
||||
defs
|
||||
g#icon-search(fill='currentColor')
|
||||
// 30.239 30.239
|
||||
@@ -234,5 +234,13 @@ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/19
|
||||
// 0 0 24 24
|
||||
path(fill='currentColor', d='M22 12L20 13L19 14L18 13L17 16L16 13L15 21L14 13L13 15L12 13L11 17L10 13L9 22L8 13L7 19L6 13L5 14L4 13L2 12L4 11L5 10L6 11L7 5L8 11L9 2L10 11L11 7L12 11L13 9L14 11L15 3L16 11L17 8L18 11L19 10L20 11L22 12Z')
|
||||
|
||||
g#icon-font-decrease(fill='currentColor')
|
||||
// 0 0 24 24
|
||||
path(d='M5.12,14L7.5,7.67L9.87,14M6.5,5L1,19H3.25L4.37,16H10.62L11.75,19H14L8.5,5H6.5M18,17L23,11.93L21.59,10.5L19,13.1V7H17V13.1L14.41,10.5L13,11.93L18,17Z')
|
||||
|
||||
g#icon-font-increase(fill='currentColor')
|
||||
// 0 0 24 24
|
||||
path(d='M5.12,14L7.5,7.67L9.87,14M6.5,5L1,19H3.25L4.37,16H10.62L11.75,19H14L8.5,5H6.5M18,7L13,12.07L14.41,13.5L17,10.9V17H19V10.9L21.59,13.5L23,12.07L18,7Z')
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="$style.controlBtn">
|
||||
<common-volume-bar :setting="setting" />
|
||||
<div :class="$style.titleBtn" @click="toggleDesktopLyric" @contextmenu="toggleLockDesktopLyric" :tips="toggleDesktopLyricBtnTitle">
|
||||
<div :class="$style.titleBtn" @click="toggleDesktopLyric" @contextmenu="toggleLockDesktopLyric" :aria-label="toggleDesktopLyricBtnTitle">
|
||||
<svg v-show="setting.desktopLyric.enable" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 512 512" space="preserve">
|
||||
<use xlink:href="#icon-desktop-lyric-on"></use>
|
||||
</svg>
|
||||
@@ -9,7 +9,7 @@
|
||||
<use xlink:href="#icon-desktop-lyric-off"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div :class="$style.titleBtn" @click="toggleNextPlayMode" :tips="nextTogglePlayName">
|
||||
<div :class="$style.titleBtn" @click="toggleNextPlayMode" :aria-label="nextTogglePlayName">
|
||||
<svg v-show="setting.player.togglePlayMethod == 'listLoop'" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="80%" viewBox="0 0 24 24" space="preserve">
|
||||
<use xlink:href="#icon-list-loop"></use>
|
||||
</svg>
|
||||
@@ -26,7 +26,7 @@
|
||||
<use xlink:href="#icon-single"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div :class="$style.titleBtn" @click="addMusicTo" :tips="$t('player__add_music_to')">
|
||||
<div :class="$style.titleBtn" @click="addMusicTo" :aria-label="$t('player__add_music_to')">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="80%" viewBox="0 0 512 512" space="preserve">
|
||||
<use xlink:href="#icon-add-2"></use>
|
||||
</svg>
|
||||
@@ -68,7 +68,7 @@ export default {
|
||||
}
|
||||
|
||||
return {
|
||||
setting: setting,
|
||||
setting,
|
||||
isShowAddMusicTo,
|
||||
nextTogglePlayName,
|
||||
toggleNextPlayMode,
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
<template lang="pug">
|
||||
div(:class="$style.player")
|
||||
div(:class="$style.left" @contextmenu="handleToMusicLocation" @click="showPlayerDetail" :tips="$t('player__pic_tip')")
|
||||
div(:class="$style.left" @contextmenu="handleToMusicLocation" @click="showPlayerDetail" :aria-label="$t('player__pic_tip')")
|
||||
img(v-if="musicInfo.img" :src="musicInfo.img" @error="imgError")
|
||||
svg(v-else version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='102%' width='100%' viewBox='0 0 60 60' space='preserve')
|
||||
use(:xlink:href='`#${$style.iconPic}`')
|
||||
div(:class="$style.middle")
|
||||
div(:class="$style.column1")
|
||||
div(:class="$style.container")
|
||||
div(:class="$style.title" @click="handleCopy(title)" :tips="title + $t('copy_tip')") {{title}}
|
||||
div(:class="$style.title" @click="handleCopy(title)" :aria-label="title + $t('copy_tip')") {{title}}
|
||||
control-btns
|
||||
div(:class="$style.column2")
|
||||
common-progress-bar(:progress="progress" :handleTransitionEnd="handleTransitionEnd" :isActiveTransition="isActiveTransition")
|
||||
common-progress-bar(:progress="progress" :handleTransitionEnd="handleTransitionEnd" :isActiveTransition="isActiveTransition" v-if="!isShowPlayerDetail")
|
||||
div(:class="$style.column3")
|
||||
span(:class="$style.statusText") {{statusText}}
|
||||
span {{nowPlayTimeStr}}
|
||||
span(style="margin: 0 5px;") /
|
||||
span {{maxPlayTimeStr}}
|
||||
template(v-if="!isShowPlayerDetail")
|
||||
span(:class="$style.statusText") {{statusText}}
|
||||
span {{nowPlayTimeStr}}
|
||||
span(style="margin: 0 5px;") /
|
||||
span {{maxPlayTimeStr}}
|
||||
div(:class="$style.right")
|
||||
div(:class="$style.playBtn" @click='playPrev' :tips="$t('player__prev')" style="transform: rotate(180deg);")
|
||||
div(:class="$style.playBtn" @click='playPrev' :aria-label="$t('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('player__pause') : $t('player__play')" @click='togglePlay')
|
||||
div(:class="$style.playBtn" :aria-label="isPlay ? $t('player__pause') : $t('player__play')" @click='togglePlay')
|
||||
svg(v-if="isPlay" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 277.338 277.338' space='preserve')
|
||||
use(xlink:href='#icon-pause')
|
||||
svg(v-else version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 170 170' space='preserve')
|
||||
use(xlink:href='#icon-play')
|
||||
div(:class="$style.playBtn" @click='playNext' :tips="$t('player__next')")
|
||||
div(:class="$style.playBtn" @click='playNext' :aria-label="$t('player__next')")
|
||||
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')
|
||||
|
||||
@@ -48,7 +49,17 @@ import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import ControlBtns from './ControlBtns'
|
||||
import usePlayProgress from '@renderer/utils/compositions/usePlayProgress'
|
||||
// import { lyric } from '@renderer/core/share/lyric'
|
||||
import { statusText, musicInfo, setMusicInfo, setShowPlayerDetail, isPlay, musicInfoItem, playInfo, playMusicInfo } from '@renderer/core/share/player'
|
||||
import {
|
||||
statusText,
|
||||
musicInfo,
|
||||
setMusicInfo,
|
||||
isShowPlayerDetail,
|
||||
setShowPlayerDetail,
|
||||
isPlay,
|
||||
musicInfoItem,
|
||||
playInfo,
|
||||
playMusicInfo,
|
||||
} from '@renderer/core/share/player'
|
||||
|
||||
export default {
|
||||
name: 'CorePlayBar',
|
||||
@@ -138,6 +149,7 @@ export default {
|
||||
playNext,
|
||||
playPrev,
|
||||
handleToMusicLocation,
|
||||
isShowPlayerDetail,
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -264,6 +276,7 @@ export default {
|
||||
.column2 {
|
||||
flex: none;
|
||||
padding: 3px 0;
|
||||
height: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +1,157 @@
|
||||
<template>
|
||||
<div :class="['right', $style.right]">
|
||||
<div :class="['lyric', $style.lyric, { [$style.draging]: isMsDown }]" @wheel="handleWheel" @mousedown="handleLyricMouseDown" ref="dom_lyric">
|
||||
<div :class="$style.lyricSpace"></div>
|
||||
<div :class="[$style.lyricText]" ref="dom_lyric_text"></div>
|
||||
<div :class="$style.lyricSpace"></div>
|
||||
</div>
|
||||
<div :class="['right', $style.right]" :style="lrcFontSize">
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div :class="[$style.lyricSelectContent, 'select', 'scroll']" v-if="isShowLrcSelectContent" @contextmenu="handleCopySelectText">
|
||||
<div v-show="!isShowLrcSelectContent"
|
||||
:class="['lyric', $style.lyric, { [$style.draging]: isMsDown }, { [$style.lrcActiveZoom]: isZoomActiveLrc }]"
|
||||
:style="lrcStyles" @wheel="handleWheel"
|
||||
@mousedown="handleLyricMouseDown" ref="dom_lyric"
|
||||
@contextmenu.stop="handleShowLyricMenu"
|
||||
>
|
||||
<div :class="['pre', $style.lyricSpace]"></div>
|
||||
<div ref="dom_lyric_text"></div>
|
||||
<div :class="$style.lyricSpace"></div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div :class="$style.skip" v-if="isShowLyricProgressSetting" v-show="isStopScroll && !isShowLrcSelectContent">
|
||||
<div :class="$style.line" ref="dom_skip_line"></div>
|
||||
<span :class="$style.label">{{timeStr}}</span>
|
||||
<base-btn :class="$style.skipBtn" @mouseenter="handleSkipMouseEnter" @mouseleave="handleSkipMouseLeave" @click="handleSkipPlay">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="50%" viewBox="0 0 170 170" space="preserve">
|
||||
<use xlink:href="#icon-play"></use>
|
||||
</svg>
|
||||
</base-btn>
|
||||
</div>
|
||||
</transition>
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div :class="[$style.lyricSelectContent, 'select', 'scroll', 'lyricSelectContent']" v-if="isShowLrcSelectContent" @contextmenu="handleCopySelectText">
|
||||
<div v-for="(info, index) in lyric.lines" :key="index" :class="[$style.lyricSelectline, { [$style.lrcActive]: lyric.line == index }]">
|
||||
<span>{{info.text}}</span>
|
||||
<br v-if="info.translation"/>
|
||||
<span :class="$style.lyricSelectlineTransition">{{info.translation}}</span>
|
||||
<template v-for="(lrc, index) in info.extendedLyrics" :key="index">
|
||||
<br />
|
||||
<span :class="$style.lyricSelectlineExtended">{{lrc}}</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<LyricMenu v-model="lyricMenuVisible" :xy="lyricMenuXY" :lyricInfo="lyricInfo" @updateLyric="handleUpdateLyric" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { clipboardWriteText } from '@renderer/utils'
|
||||
import { lyric } from '@renderer/core/share/lyric'
|
||||
import { isPlay, isShowLrcSelectContent } from '@renderer/core/share/player'
|
||||
// import { ref } from '@renderer/utils/vueTools'
|
||||
import { isFullscreen } from '@renderer/core/share'
|
||||
import { isPlay, isShowLrcSelectContent, isShowPlayComment, musicInfo as playerMusicInfo, musicInfoItem, setMusicInfo } from '@renderer/core/share/player'
|
||||
import { onMounted, onBeforeUnmount, useRefGetter, computed, reactive, ref } from '@renderer/utils/vueTools'
|
||||
import useLyric from '@renderer/utils/compositions/useLyric'
|
||||
import LyricMenu from './components/LyricMenu'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LyricMenu,
|
||||
},
|
||||
setup() {
|
||||
const setting = useRefGetter('setting')
|
||||
const isZoomActiveLrc = computed(() => setting.value.playDetail.isZoomActiveLrc)
|
||||
const isShowLyricProgressSetting = computed(() => setting.value.playDetail.isShowLyricProgressSetting)
|
||||
|
||||
const {
|
||||
dom_lyric,
|
||||
dom_lyric_text,
|
||||
dom_skip_line,
|
||||
isMsDown,
|
||||
isStopScroll,
|
||||
timeStr,
|
||||
handleLyricMouseDown,
|
||||
handleWheel,
|
||||
} = useLyric({ isPlay, lyric })
|
||||
handleSkipPlay,
|
||||
handleSkipMouseEnter,
|
||||
handleSkipMouseLeave,
|
||||
} = useLyric({ isPlay, lyric, isShowLyricProgressSetting })
|
||||
|
||||
const lyricMenuVisible = ref(false)
|
||||
const lyricMenuXY = reactive({
|
||||
x: 0,
|
||||
y: 0,
|
||||
})
|
||||
const lyricInfo = reactive({
|
||||
lyric: '',
|
||||
tlyric: '',
|
||||
rlyric: '',
|
||||
lxlyric: '',
|
||||
rawlyric: '',
|
||||
musicInfo: null,
|
||||
})
|
||||
const updateMusicInfo = () => {
|
||||
lyricInfo.lyric = playerMusicInfo.lrc
|
||||
lyricInfo.tlyric = playerMusicInfo.tlrc
|
||||
lyricInfo.rlyric = playerMusicInfo.rlrc
|
||||
lyricInfo.lxlyric = playerMusicInfo.lxlrc
|
||||
lyricInfo.rawlyric = playerMusicInfo.rawlrc
|
||||
lyricInfo.musicInfo = musicInfoItem.value
|
||||
}
|
||||
const handleShowLyricMenu = event => {
|
||||
updateMusicInfo()
|
||||
lyricMenuXY.x = event.pageX
|
||||
lyricMenuXY.y = event.pageY
|
||||
lyricMenuVisible.value = true
|
||||
}
|
||||
const handleUpdateLyric = ({ lyric, tlyric, rlyric, lxlyric, offset }) => {
|
||||
setMusicInfo({
|
||||
lrc: lyric,
|
||||
tlrc: tlyric,
|
||||
rlrc: rlyric,
|
||||
lxlrc: lxlyric,
|
||||
})
|
||||
// console.log(offset)
|
||||
window.eventHub.emit(eventPlayerNames.updateLyricOffset, offset)
|
||||
}
|
||||
|
||||
const lrcStyles = computed(() => {
|
||||
return {
|
||||
textAlign: setting.value.playDetail.style.align,
|
||||
}
|
||||
})
|
||||
const lrcFontSize = computed(() => {
|
||||
let size = setting.value.playDetail.style.fontSize / 100
|
||||
if (isFullscreen.value) size = size *= 1.4
|
||||
return {
|
||||
'--playDetail-lrc-font-size': (isShowPlayComment.value ? size * 0.82 : size) + 'rem',
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
window.eventHub.on(eventPlayerNames.updateLyric, updateMusicInfo)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off(eventPlayerNames.updateLyric, updateMusicInfo)
|
||||
})
|
||||
|
||||
return {
|
||||
dom_lyric,
|
||||
dom_lyric_text,
|
||||
dom_skip_line,
|
||||
isMsDown,
|
||||
timeStr,
|
||||
handleLyricMouseDown,
|
||||
handleWheel,
|
||||
handleSkipPlay,
|
||||
handleSkipMouseEnter,
|
||||
handleSkipMouseLeave,
|
||||
lyric,
|
||||
lrcStyles,
|
||||
lrcFontSize,
|
||||
isShowLrcSelectContent,
|
||||
isShowLyricProgressSetting,
|
||||
isZoomActiveLrc,
|
||||
isStopScroll,
|
||||
lyricMenuVisible,
|
||||
lyricMenuXY,
|
||||
handleShowLyricMenu,
|
||||
handleUpdateLyric,
|
||||
lyricInfo,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -63,34 +174,13 @@ export default {
|
||||
// padding: 0 30px;
|
||||
position: relative;
|
||||
transition: flex-basis @transition-theme;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
content: ' ';
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background-image: linear-gradient(0deg,rgba(255,255,255,0) 0%,@color-theme_2-background_1 95%);
|
||||
pointer-events: none;
|
||||
}
|
||||
&:after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
content: ' ';
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background-image: linear-gradient(-180deg,rgba(255,255,255,0) 0%,@color-theme_2-background_1 95%);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
.lyric {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
font-size: var(--playDetail-lrc-font-size, 16px);
|
||||
-webkit-mask-image: linear-gradient(transparent 0%, #fff 20%, #fff 80%, transparent 100%);
|
||||
cursor: grab;
|
||||
&.draging {
|
||||
cursor: grabbing;
|
||||
@@ -98,11 +188,13 @@ export default {
|
||||
:global {
|
||||
.lrc-content {
|
||||
line-height: 1.2;
|
||||
margin: 16px 0;
|
||||
padding: calc(var(--playDetail-lrc-font-size, 16px) / 2) 1px;
|
||||
overflow-wrap: break-word;
|
||||
color: @color-player-detail-lyric;
|
||||
transition: @transition-theme;
|
||||
transition-property: padding;
|
||||
|
||||
.translation {
|
||||
.extended {
|
||||
transition: @transition-theme !important;
|
||||
transition-property: font-size, color;
|
||||
font-size: .9em;
|
||||
@@ -118,14 +210,13 @@ export default {
|
||||
.line {
|
||||
color: @color-theme;
|
||||
}
|
||||
.translation {
|
||||
font-size: .94em;
|
||||
.extended {
|
||||
color: @color-theme;
|
||||
}
|
||||
span {
|
||||
// color: @color-theme;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
// span {
|
||||
// // color: @color-theme;
|
||||
// font-size: 1.1em;
|
||||
// }
|
||||
}
|
||||
|
||||
span {
|
||||
@@ -153,6 +244,65 @@ export default {
|
||||
// font-size: 1.2em;
|
||||
// }
|
||||
}
|
||||
.lrcActiveZoom {
|
||||
:global {
|
||||
.lrc-content {
|
||||
&.active {
|
||||
.extended {
|
||||
font-size: .94em;
|
||||
}
|
||||
span {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skip {
|
||||
position: absolute;
|
||||
top: calc(38% + var(--playDetail-lrc-font-size, 16px) + 4px);
|
||||
left: 0;
|
||||
// height: 6px;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
// opacity: .5;
|
||||
.line {
|
||||
border-top: 2px dotted @color-player-detail-lyric-active;
|
||||
opacity: .15;
|
||||
margin-right: 30px;
|
||||
-webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 15%, #fff 100%);
|
||||
}
|
||||
.label {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: -14px;
|
||||
line-height: 1;
|
||||
font-size: 12px;
|
||||
color: @color-player-detail-lyric-active;
|
||||
opacity: .7;
|
||||
}
|
||||
.skipBtn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translateY(-50%);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: none !important;
|
||||
pointer-events: initial;
|
||||
transition: @transition-theme;
|
||||
transition-property: opacity;
|
||||
opacity: .8;
|
||||
&:hover {
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.lyricSelectContent {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
@@ -161,7 +311,6 @@ export default {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
background-color: @color-theme_2-background_1;
|
||||
z-index: 10;
|
||||
color: @color-player-detail-lyric;
|
||||
|
||||
@@ -172,7 +321,7 @@ export default {
|
||||
transition-property: color, font-size;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.lyricSelectlineTransition {
|
||||
.lyricSelectlineExtended {
|
||||
font-size: 14px;
|
||||
}
|
||||
.lrc-active {
|
||||
@@ -186,21 +335,13 @@ export default {
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.right {
|
||||
&:before {
|
||||
background-image: linear-gradient(0deg,rgba(255,255,255,0) 0%,~'@{color-@{value}-theme_2-background_1}' 95%);
|
||||
}
|
||||
&:after {
|
||||
background-image: linear-gradient(-180deg,rgba(255,255,255,0) 0%,~'@{color-@{value}-theme_2-background_1}' 95%);
|
||||
}
|
||||
}
|
||||
.lyric {
|
||||
:global {
|
||||
.lrc-content {
|
||||
color: ~'@{color-@{value}-player-detail-lyric}';
|
||||
|
||||
&.active {
|
||||
.translation {
|
||||
.extended {
|
||||
color: ~'@{color-@{value}-player-detail-lyric-active}';
|
||||
}
|
||||
.line {
|
||||
@@ -217,8 +358,15 @@ each(@themes, {
|
||||
// .lrc-active {
|
||||
// color: ~'@{color-@{value}-theme}';
|
||||
// }
|
||||
.skip {
|
||||
.line {
|
||||
border-top-color: ~'@{color-@{value}-player-detail-lyric-active}';
|
||||
}
|
||||
.label {
|
||||
color:~'@{color-@{value}-player-detail-lyric-active}';
|
||||
}
|
||||
}
|
||||
.lyricSelectContent {
|
||||
background-color: ~'@{color-@{value}-theme_2-background_1}';
|
||||
color: ~'@{color-@{value}-player-detail-lyric}';
|
||||
.lrc-active {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user