Compare commits

...

298 Commits

Author SHA1 Message Date
lyswhut
41f4130e5d Merge branch 'dev' 2022-08-18 17:15:24 +08:00
lyswhut
8e19f3fc0b 发布v1.22.2 2022-08-18 17:15:00 +08:00
lyswhut
c4b8ac8b0b 修复hires类型显示 2022-08-11 17:20:07 +08:00
lyswhut
0ac2df1297 更新版本号 2022-08-11 17:01:18 +08:00
lyswhut
251450fd50 修复企鹅音乐搜索失效的问题 2022-08-11 15:44:37 +08:00
lyswhut
85c5595f43 更新依赖 2022-08-06 18:26:10 +08:00
lyswhut
ca3188c930 优化列表保存性能 2022-08-06 18:20:58 +08:00
lyswhut
2f47f82b0f 修复某些缺失的繁体中文翻译 2022-08-06 17:33:23 +08:00
lyswhut
0e09598b10 降级electron到v15.5.7 2022-08-05 10:45:17 +08:00
lyswhut
a705420528 修复依赖安全警告 2022-08-04 09:31:39 +08:00
lyswhut
4089887514 升级electron到v18.3.7 2022-08-04 09:18:53 +08:00
lyswhut
a3d02e5f39 修复列表移动的更新问题 2022-08-04 08:38:30 +08:00
lyswhut
6e09363832 修复无法批量排序歌曲的问题 2022-08-04 08:37:57 +08:00
lyswhut
1c58a64847 修复wy源音质获取问题 2022-07-22 14:29:57 +08:00
lyswhut
2a716e4d5a 更新依赖 2022-07-17 12:40:21 +08:00
lyswhut
a2c613d380 修复默认设置的语言显示问题 2022-07-10 16:06:07 +08:00
lyswhut
aa4b09436c Merge branch 'dev' 2022-07-09 12:03:42 +08:00
lyswhut
9521bba4ba 发布v1.22.1 2022-07-09 12:03:16 +08:00
lyswhut
55d10021f8 更新依赖 2022-07-08 19:03:36 +08:00
lyswhut
7fe35748d0 更新依赖 2022-07-08 16:43:28 +08:00
lyswhut
ff9efbd4ea 歌单列表添加歌单内歌曲数量显示 2022-07-08 16:39:56 +08:00
lyswhut
23b8c325f4 修复tx源搜索失效的问题 2022-07-08 09:12:45 +08:00
lyswhut
ecfccb4c40 修复临时列表meta信息丢失的问题 2022-07-03 22:55:33 +08:00
lyswhut
2472574cde 更新依赖 2022-07-03 22:16:06 +08:00
lyswhut
bf81c8facc 更新版本号 2022-06-25 13:23:30 +08:00
lyswhut
9bf0d69ab6 更新依赖 2022-06-25 10:29:55 +08:00
lyswhut
cf9d98d434 修复若桌面歌词窗口与主窗口重叠时,鼠标划过重叠区域鼠标会闪烁的问题 2022-06-20 12:02:55 +08:00
lyswhut
da8e67d4e5 修复处于不支持的源时,歌单、排行榜的右键下载菜单没有禁用的问题 2022-06-19 14:36:04 +08:00
lyswhut
d695cdef08 Merge branch 'dev' 2022-06-19 12:34:09 +08:00
lyswhut
d7a7701c09 发布v1.22.0 2022-06-19 11:59:11 +08:00
lyswhut
a31180260b 屏蔽设置 2022-06-18 11:50:54 +08:00
lyswhut
f33947287c 更新版本号 2022-06-17 20:26:08 +08:00
lyswhut
c054ceeab5 修复 2022-06-17 20:17:42 +08:00
lyswhut
c8dce1bcb6 更新更新 Electron 到 v17.4.7 2022-06-17 20:16:07 +08:00
lyswhut
6195c10646 更新常见问题地址 2022-06-17 19:20:08 +08:00
lyswhut
535cbbbd16 修复ctrl跳转播放失效的问题 2022-06-17 14:44:28 +08:00
lyswhut
fa99f35bc0 修复歌词显示问题 2022-06-15 11:08:00 +08:00
lyswhut
5800f0e354 添加导入文件错误时的指引提示 2022-06-15 09:30:58 +08:00
lyswhut
aa5e621184 新增设置-桌面歌词设置-鼠标移入歌词区域时降低歌词透明度(#883) 2022-06-14 11:43:18 +08:00
lyswhut
283bdd6246 添加歌曲列表更新操作的二次确认 2022-06-13 12:57:25 +08:00
lyswhut
2884e67109 修复esc键冲突问题 2022-06-12 18:01:26 +08:00
lyswhut
4542f9b2e3 更新依赖 2022-06-12 14:46:34 +08:00
lyswhut
9d08f91079 修复在新建歌单输入框、歌单内歌曲搜索输入框会意外触发设置的全局快捷键的问题(#879) 2022-06-12 14:39:58 +08:00
lyswhut
0704a4ad12 修复设置快捷键时的处理逻辑问题 2022-06-11 18:52:52 +08:00
lyswhut
bb8509a21c 支持mg源逐字歌词的播放 2022-06-09 13:03:46 +08:00
lyswhut
f2e3d4a53d 更新版本号 2022-06-07 19:49:01 +08:00
lyswhut
b8a221e67e 更新t文档 2022-06-07 08:52:19 +08:00
lyswhut
f4147cce37 添加其他开发者工具打开方式 2022-06-07 08:51:41 +08:00
lyswhut
01f9fd502f 还原文档 2022-06-06 10:00:12 +08:00
lyswhut
5d20adc81e 更新依赖 2022-06-05 14:51:58 +08:00
lyswhut
6a78f659e3 移除http_proxy环境变量 2022-06-05 14:51:46 +08:00
lyswhut
211f584bf8 更新文档说明 2022-06-04 13:03:20 +08:00
lyswhut
fcfba8b12c 新增添加歌曲到“我的列表”时,若按住ctrl键,则不会自动关闭添加窗口 2022-06-04 12:48:26 +08:00
lyswhut
85e4c7555a 修复多选后切换列表后不会清空多选内容的问题 2022-06-04 12:43:15 +08:00
lyswhut
19dccffdde 优化换源匹配 2022-05-31 09:13:59 +08:00
lyswhut
359514a83c 修复变量移除问题 2022-05-29 10:58:04 +08:00
lyswhut
90ea0dc857 修复环境变量被替换的问题 2022-05-29 10:48:05 +08:00
lyswhut
ae18db45a4 修复若配置了http_proxy环境变量时,会意外使用此代理配置的问题 2022-05-29 10:39:14 +08:00
lyswhut
4783c9be8d 更新依赖 2022-05-26 13:02:52 +08:00
lyswhut
ff41fa9829 修复kuwo歌词解析 2022-05-26 12:03:40 +08:00
lyswhut
aa56dafd5f 新增设置-以全屏模式启动设置 2022-05-24 08:57:04 +08:00
lyswhut
f2f2008d5d Merge branch 'dev' 2022-05-22 11:17:47 +08:00
lyswhut
15d2589db8 发布v1.21.0 2022-05-22 11:17:13 +08:00
lyswhut
47a8da49ca 修改包大小提示 2022-05-22 01:50:34 +08:00
lyswhut
2250cac7f9 不处理可能存在翻译的歌词 2022-05-22 01:50:02 +08:00
lyswhut
94e3063307 添加flac 24bit显示 2022-05-20 19:32:31 +08:00
lyswhut
88691b3f18 更新依赖 2022-05-19 17:33:12 +08:00
lyswhut
3851880007 添加稍后播放说明 2022-05-19 15:19:37 +08:00
lyswhut
e5d2e089f4 在全屏状态下使用Esc键可以退出全屏 2022-05-19 14:57:42 +08:00
lyswhut
bfe7f24a4b 删除未下载完成的任务时,只同时尝试删除已有下载进度的本地文件(#849) 2022-05-17 10:07:34 +08:00
lyswhut
0d1e2c3349 更新链接 2022-05-17 09:22:43 +08:00
lyswhut
bc6272a0ed 更新依赖 2022-05-17 09:11:52 +08:00
lyswhut
56a752dc26 更新依赖 2022-05-13 10:48:32 +08:00
lyswhut
0fe443c92a 修复潜在歌单更新失败的问题 2022-05-12 12:03:45 +08:00
lyswhut
74afdb2a46 更新依赖 2022-05-11 15:52:04 +08:00
lyswhut
ebd6ff36ed 合并打包的页面文件 2022-05-11 15:37:06 +08:00
lyswhut
a5ec36bf89 新增设置-播放设置-显示歌词罗马音 2022-05-10 11:12:14 +08:00
lyswhut
c65802c1c3 修复长度大于一行的歌词在使用歌词调整播放进度时的时间不准问题 2022-05-10 09:36:12 +08:00
lyswhut
784515e411 修复原始歌词存在偏移时,歌词偏移设置的重置未按预期工作的问题 2022-05-09 14:07:31 +08:00
lyswhut
e859d39b2b 更新依赖 2022-05-08 13:34:59 +08:00
lyswhut
62c4bfb9eb 修复评论换行处理问题 2022-05-07 12:56:46 +08:00
lyswhut
8ab1bdf30a 修复关闭“显示切换动画”设置后,在应用启动时该设置没有被应用的问题 2022-05-05 16:02:09 +08:00
lyswhut
c758066e25 禁用透明窗口时右侧不再偏移5px距离 2022-05-05 14:57:04 +08:00
lyswhut
06b7f69b3c 同时删除一首歌以上时将需要二次确认删除 2022-05-04 10:06:02 +08:00
lyswhut
c3c43a2645 修复某些情况下歌曲播放出错时不会自动切歌的问题 2022-05-03 19:53:13 +08:00
lyswhut
343395a5de 更新依赖 2022-05-03 18:55:39 +08:00
lyswhut
3c9bb74b61 lint fix 2022-04-26 13:04:28 +08:00
lyswhut
c9cf30692f 更新依赖 2022-04-26 13:04:19 +08:00
lyswhut
c979339c4e Merge branch 'dev' 2022-04-17 10:06:33 +08:00
lyswhut
9393906eb9 修复构建 2022-04-17 10:06:13 +08:00
lyswhut
1b4c910264 Merge branch 'dev' 2022-04-17 09:08:06 +08:00
lyswhut
4db5d26b1e 发布v1.20.0 2022-04-17 09:07:44 +08:00
lyswhut
c09a4131db 修复歌词菜单弹出位置问题 2022-04-16 14:41:58 +08:00
lyswhut
ce6f3f23c6 修复歌曲匹配 2022-04-16 14:19:19 +08:00
lyswhut
7b898c2d91 更新依赖 2022-04-16 13:49:29 +08:00
lyswhut
3da797a0ad 修复linux构建 2022-04-13 20:04:25 +08:00
lyswhut
517899cd03 优化逻辑 2022-04-13 11:52:01 +08:00
lyswhut
1d6a14685e 更新依赖 2022-04-13 11:09:30 +08:00
lyswhut
737d00f550 修复正在下载的歌曲暂停任务后,再开始会导致程序卡死的问题 2022-04-13 11:08:29 +08:00
lyswhut
68798a9627 优化歌词选择UI问题 2022-04-11 11:56:22 +08:00
lyswhut
5b1dfee05c 修复歌曲信息更新时的保存问题 2022-04-10 22:40:28 +08:00
lyswhut
e75863e99d 跳过空白歌词 2022-04-10 22:25:25 +08:00
lyswhut
1c542a9b17 跳过空白歌词 2022-04-10 22:11:42 +08:00
lyswhut
729ac5a0d7 修复全屏切换的事件清理问题 2022-04-10 21:37:25 +08:00
lyswhut
ff8195df46 添加列表元数据清理 2022-04-10 21:03:40 +08:00
lyswhut
692ab6dacb 更新依赖 2022-04-10 20:28:29 +08:00
lyswhut
128039d678 修复歌词偏移处理问题 2022-04-09 13:42:12 +08:00
lyswhut
bb5de056d4 更新依赖 2022-04-09 10:40:45 +08:00
lyswhut
d927ac90e7 修复按键监听问题 2022-04-08 14:04:50 +08:00
lyswhut
f61099ecad 修改按键绑定 2022-04-08 11:43:43 +08:00
lyswhut
f96b663bbe 更新版本号 2022-04-07 19:29:18 +08:00
lyswhut
f65213f8aa 修复启用代理时,https请求可能被挂起或被转为http的问题 2022-04-07 14:41:09 +08:00
lyswhut
2e5adeb50c 优化滚动 2022-04-07 09:54:06 +08:00
lyswhut
6de84d3b9b 修复歌词调整时间显示问题 2022-04-07 09:24:09 +08:00
lyswhut
65ae08add6 修复网易歌单详情无法打开的问题 2022-04-07 08:28:02 +08:00
lyswhut
3c970c24c1 修复换源失败时的处理问题 2022-04-05 22:08:35 +08:00
lyswhut
93f3507dc8 添加说明 2022-04-05 17:15:29 +08:00
lyswhut
e92e291409 修复鼠标自动隐藏问题 2022-04-05 16:47:37 +08:00
lyswhut
4b4de8937e 更新windows下的图标 2022-04-05 14:34:56 +08:00
lyswhut
27a036bc00 优化布局 2022-04-04 20:56:40 +08:00
lyswhut
1eb2540c67 更新依赖 2022-04-04 20:11:30 +08:00
lyswhut
3a5bd6029f 更新版本号 2022-04-03 14:00:20 +08:00
lyswhut
249ff7f2d2 尝试修改应用名称 2022-04-03 13:56:39 +08:00
lyswhut
9afa965d5d 修复使用Scheme URL搜索歌曲时,不会自动关闭播放详情页(若处于打开状态)的问题 2022-04-03 00:37:38 +08:00
lyswhut
28b7b5581d 添加提示 2022-04-02 22:14:47 +08:00
lyswhut
26aab15e50 修复wy源搜索某些歌曲时第一页之后的歌曲无法加载的问题 2022-04-02 21:16:41 +08:00
lyswhut
92351049f1 修复潜在更新问题 2022-04-02 14:26:31 +08:00
lyswhut
47d3c50863 新增列表更新管理 2022-04-02 14:13:58 +08:00
lyswhut
36ac3532e6 修复歌词菜单的弹出问题 2022-04-01 14:29:07 +08:00
lyswhut
dee16f6943 修复播放详情页的鼠标隐藏问题 2022-04-01 14:28:22 +08:00
lyswhut
3541b568c9 更新版本号 2022-03-31 17:54:35 +08:00
lyswhut
4dfa4d9525 新增设置-桌面歌词设置-自动刷新歌词置顶 2022-03-31 17:54:22 +08:00
lyswhut
5938f4e591 修复窗口尺寸设置对应的字体大小在启动后不生效的问题 2022-03-31 13:19:50 +08:00
lyswhut
9ac26be65d 记录连接时间 2022-03-30 16:22:13 +08:00
lyswhut
5099ba9c96 添加源有效性校验 2022-03-30 13:14:23 +08:00
lyswhut
bca5b13516 修复鼠标不会隐藏的问题 2022-03-28 20:28:33 +08:00
lyswhut
6ceb984393 更新版本号 2022-03-28 19:04:40 +08:00
lyswhut
17b29f376a 更新说明文档 2022-03-28 18:46:13 +08:00
lyswhut
36bef673d3 在全屏状态下鼠标在空白处静止不动3秒后自动将其隐藏 2022-03-28 18:05:58 +08:00
lyswhut
c2fa4e5220 修复不启用热门搜索时,搜索历史不显示的问题 2022-03-28 14:11:03 +08:00
lyswhut
ddf06d20c2 移除右击调整 2022-03-28 13:04:43 +08:00
lyswhut
e51f640371 在全屏状态下的播放详情页仍会显示退出播放详情页按钮 2022-03-28 09:41:30 +08:00
lyswhut
e302f53d5c Update 2022-03-27 12:23:48 +08:00
lyswhut
b2058b9581 调整颜色 2022-03-26 14:59:13 +08:00
lyswhut
35501d328b 加深颜色 2022-03-26 13:15:39 +08:00
lyswhut
cb746c64db 更新版本号 2022-03-26 13:06:34 +08:00
lyswhut
e2f6d117bc 优化播放详情页背景显示 2022-03-26 13:06:07 +08:00
lyswhut
9fd9449eca 新增播放错误时自动切换歌曲设置 2022-03-25 15:52:33 +08:00
lyswhut
1f97af6ff1 修复歌词解析问题 2022-03-25 15:52:19 +08:00
lyswhut
f1a7862a9c 更新node版本 2022-03-25 14:34:12 +08:00
lyswhut
8aeac3ed2e 更新依赖 2022-03-25 10:24:47 +08:00
lyswhut
469832a598 通过歌词调整进度时添加对偏移时间的计算 2022-03-23 17:49:34 +08:00
lyswhut
e0e65e4374 更新版本号 2022-03-22 20:21:01 +08:00
lyswhut
66f78d6979 修复偏移标签的匹配问题 2022-03-22 20:19:16 +08:00
lyswhut
efc58f7dd1 更新版本号 2022-03-22 17:49:18 +08:00
lyswhut
bc301c27c2 新增播放详情页歌词右键菜单,新增歌词偏移设置 2022-03-22 16:55:44 +08:00
lyswhut
82ea1935de 修复任务栏收藏按钮的下载列表歌曲收藏问题 2022-03-21 10:03:35 +08:00
lyswhut
226fb05337 修复Linux无法全屏的问题 2022-03-20 20:16:01 +08:00
lyswhut
be219f03d5 typo 2022-03-20 14:28:59 +08:00
lyswhut
f10c1e923e Merge branch 'dev' 2022-03-20 13:52:15 +08:00
lyswhut
66121e5ff3 发布v1.19.0 2022-03-20 13:50:32 +08:00
lyswhut
478b71172d 添加切歌逻辑注释 2022-03-20 12:53:48 +08:00
lyswhut
e7370f12ae 切换devtools版本 2022-03-20 12:26:03 +08:00
lyswhut
b844a577c7 迁移提示文本字段 2022-03-20 12:04:01 +08:00
lyswhut
9bf33fdb25 优化播放下载列表时的切歌性能 2022-03-20 01:47:09 +08:00
lyswhut
8b988b227b 修复下载列表播放歌曲序号更新问题 2022-03-20 00:43:16 +08:00
lyswhut
8b2be019c6 移除偏移 2022-03-19 19:46:13 +08:00
lyswhut
4d7d92759f 过滤id重复的歌曲 2022-03-19 16:25:28 +08:00
lyswhut
798b840472 fix syntax 2022-03-19 13:07:43 +08:00
lyswhut
48db75a995 更新依赖 2022-03-19 13:05:49 +08:00
lyswhut
7072541ba7 Generate file MD5 2022-03-19 13:03:10 +08:00
lyswhut
7119c915ec 修复依赖漏洞警告问题 2022-03-18 20:30:58 +08:00
lyswhut
5e3035cc15 更新依赖 2022-03-18 19:32:00 +08:00
lyswhut
7cf2e4c4ed 修复歌单详情获取流程问题 2022-03-18 14:56:29 +08:00
lyswhut
674a3a0a3f 优化歌词解析 2022-03-18 14:36:00 +08:00
lyswhut
7486a99494 修改延迟 2022-03-18 13:15:52 +08:00
lyswhut
783d96bd7d 更新文档 2022-03-18 11:38:08 +08:00
lyswhut
64eea42092 优化歌词播放机制 2022-03-18 11:27:31 +08:00
lyswhut
8453ad0fb4 修复歌词播放问题 2022-03-18 11:26:52 +08:00
lyswhut
0acfeff006 优化托盘菜单操作#686 2022-03-18 10:56:28 +08:00
lyswhut
a338b7ef39 取消默认偏移 2022-03-15 15:29:53 +08:00
lyswhut
e821660124 添加动画 2022-03-15 11:23:58 +08:00
lyswhut
bad6045164 修复歌词解析问题 2022-03-15 10:54:51 +08:00
lyswhut
6779fd7ae5 优化歌词偏移时间计算 2022-03-15 10:23:47 +08:00
lyswhut
04858cc42c 修复歌词解析问题 2022-03-14 19:38:48 +08:00
lyswhut
916975b0a9 更新版本号 2022-03-14 17:59:38 +08:00
lyswhut
644db88e58 添加对歌词offset字段的支持 2022-03-14 17:37:27 +08:00
lyswhut
b025af45fa 优化歌词播放器 2022-03-14 17:06:50 +08:00
lyswhut
0f11731c01 修复歌词解析问题 2022-03-14 15:37:44 +08:00
lyswhut
ea1d21a3ef 修复歌词解析问题 2022-03-14 10:24:30 +08:00
lyswhut
545ba6521b 新增对kw源卡拉OK歌词的支持 2022-03-14 10:02:31 +08:00
lyswhut
1fd3e6c9fa 更换kw歌词获取方式 2022-03-13 15:00:43 +08:00
lyswhut
2913c0c7de 优化音频可视化与音频设备输出设置冲突的提示机制 2022-03-13 11:32:40 +08:00
lyswhut
a4c851899f 修复依赖漏洞警告 2022-03-12 21:32:51 +08:00
lyswhut
df1c58e79b 修复依赖安全警告 2022-03-12 20:53:59 +08:00
lyswhut
67edeab09b 更新版本号 2022-03-11 21:44:46 +08:00
lyswhut
fe07ac025a 修复设置的迁移问题 2022-03-11 21:44:38 +08:00
lyswhut
fc72d99ab3 优化大屏的UI布局 2022-03-11 21:36:33 +08:00
lyswhut
377f665361 修复UI问题 2022-03-11 20:44:40 +08:00
lyswhut
4e458ec4cb 修复计算问题 2022-03-11 20:08:41 +08:00
lyswhut
6f4500f31a 修复与优化列表渲染 2022-03-11 15:10:29 +08:00
lyswhut
a363c5525b 修复使用链接导入的歌单无法在我的列表打开原歌单详情页的问题 2022-03-11 12:02:59 +08:00
lyswhut
65027fceba 修复设置迁移问题 2022-03-11 11:30:47 +08:00
lyswhut
2b0c75a649 添加提示 2022-03-11 11:29:30 +08:00
lyswhut
bcc79541c1 优化大屏下的UI展示 2022-03-11 10:52:13 +08:00
lyswhut
081d6dc91e 修复评论列表显示问题 2022-03-11 10:10:01 +08:00
lyswhut
09a5111e36 修复列表渲染问题 2022-03-10 19:52:03 +08:00
lyswhut
253746843c 更新描述 2022-03-10 19:02:09 +08:00
lyswhut
5d2fac9247 更新版本号 2022-03-10 17:47:05 +08:00
lyswhut
3c2a1093a0 更新依赖 2022-03-10 17:46:41 +08:00
lyswhut
88b3d8ee4a 新增动态主题“道法自然” 2022-03-10 16:07:51 +08:00
lyswhut
d35a6f504f 优化下载、歌曲添加弹窗在大屏幕下的排版 2022-03-09 15:03:35 +08:00
lyswhut
4965dad6a2 修复评论宽度计算问题 2022-03-09 15:02:49 +08:00
lyswhut
3ad4584159 修复设置意外被更改的问题 2022-03-08 18:20:09 +08:00
lyswhut
5e291255bb 修复切换全屏问题 2022-03-08 18:02:45 +08:00
lyswhut
205c99372e 修复标签列表宽度问题 2022-03-08 17:42:42 +08:00
lyswhut
a05f3a969b 更新版本号 2022-03-08 17:19:57 +08:00
lyswhut
3acc0931d8 新增全屏状态 2022-03-08 17:19:34 +08:00
lyswhut
05f6a953ea 添加音频可视化与音频输出设备冲突的提示 2022-03-08 14:51:29 +08:00
lyswhut
6253368f05 更新版本号 2022-03-08 08:32:00 +08:00
lyswhut
9483f2f178 修复依赖 2022-03-07 19:10:15 +08:00
lyswhut
8df6e7ef90 修复展开评论时的歌词大小问题 2022-03-07 17:23:33 +08:00
lyswhut
b09dba0a95 添加通过歌词调整播放进度开关设置 2022-03-07 16:10:18 +08:00
lyswhut
cfee4a0b24 新增通过播放详情页歌词调整播放进度 2022-03-07 15:33:04 +08:00
lyswhut
34febf4949 确保音频输出改变时能暂停播放 2022-03-06 21:57:32 +08:00
lyswhut
6aed9dfb9f 修复Windows任务栏缩略图工具栏控制按钮的歌曲收藏按钮状态更新问题 2022-03-06 21:38:45 +08:00
lyswhut
c7360993c9 更新说明 2022-03-06 14:29:44 +08:00
lyswhut
34a072bada 修复展开评论时的歌词间隔问题 2022-03-06 13:43:58 +08:00
lyswhut
dda0d54f20 添加歌词间隔跟随字体大小改变 2022-03-06 13:33:13 +08:00
lyswhut
d710c31d48 修复翻译依赖导致的错误 2022-03-06 13:11:03 +08:00
lyswhut
02c74f7d96 修复AppImage包无法运行的问题 2022-03-06 10:27:37 +08:00
lyswhut
5bdccba29e 修复高度塌陷的问题 2022-03-05 16:11:25 +08:00
lyswhut
cdc819fbe8 新增对播放详情页歌词大小、是否缩放、对齐方式的设置 2022-03-05 16:06:45 +08:00
lyswhut
4629d4cd3e 修复桌面歌词没有处理停止播放状态的问题 2022-03-03 17:39:33 +08:00
lyswhut
ba3a70c524 更新快捷操作说明 2022-03-03 13:15:56 +08:00
lyswhut
52b985dd8e 更新依赖 2022-03-02 18:41:29 +08:00
lyswhut
b51c8e1552 修复“当前的声音输出设备被改变时暂停播放歌曲”设置无效的问题 2022-02-28 12:00:54 +08:00
lyswhut
86f9c03707 添加LX中定义的快捷操作汇总说明 2022-02-27 12:25:53 +08:00
lyswhut
e61c84ee08 优化Windows任务栏缩略图工具栏控制按钮在浅色任务栏下的显示效果 2022-02-27 11:36:18 +08:00
lyswhut
2f39808275 Merge branch 'dev' 2022-02-26 13:39:58 +08:00
lyswhut
f5aee4cbd0 修复依赖 2022-02-26 13:39:37 +08:00
lyswhut
9fd9bb4eef Merge branch 'dev' 2022-02-26 13:31:14 +08:00
lyswhut
685cae8993 更新依赖 2022-02-26 13:30:54 +08:00
lyswhut
ec14aadec6 Merge branch 'dev' 2022-02-26 13:14:33 +08:00
lyswhut
b934770e1e 更新依赖 2022-02-26 13:14:19 +08:00
lyswhut
2f76433f34 Merge branch 'dev' 2022-02-26 12:58:31 +08:00
lyswhut
535c63be2b 修改构建顺序 2022-02-26 12:57:58 +08:00
lyswhut
53d4f08ee7 Merge branch 'dev' 2022-02-26 12:22:00 +08:00
lyswhut
81b72fe72b 发布v1.18.0 2022-02-26 12:21:40 +08:00
lyswhut
e496794052 更新依赖 2022-02-26 12:19:48 +08:00
lyswhut
442b4fb30f 分离方法 2022-02-25 10:26:59 +08:00
lyswhut
9528b10d01 添加debug启动参数 2022-02-25 10:18:57 +08:00
lyswhut
a9f9c887b5 更新版本号 2022-02-24 17:25:03 +08:00
lyswhut
6105a331aa 修复播放器的停止逻辑问题 2022-02-24 17:23:33 +08:00
lyswhut
0f0be95c12 修复任务栏按钮的控制问题 2022-02-24 17:21:36 +08:00
lyswhut
d6ca9e4539 修复windows平台下软件目录存在portable文件夹时,仍会在默认目录创建文件的问题 2022-02-24 13:09:13 +08:00
lyswhut
d3b5171237 优化滚动 2022-02-22 17:05:18 +08:00
lyswhut
cf501ac19e 修复字体设置不生效的问题 2022-02-22 08:56:10 +08:00
lyswhut
4fd4746ddf 更新版本号 2022-02-21 17:41:56 +08:00
lyswhut
61c1476823 新增任务栏缩略图工具栏控制按钮 2022-02-21 16:05:41 +08:00
lyswhut
e28b8bb6e8 修改默认字体 2022-02-21 10:28:09 +08:00
lyswhut
5eb9107adf 新增设置-基本设置-软件字体设置 2022-02-20 17:22:58 +08:00
lyswhut
83ddf74890 修复歌单详情的播放按钮无效的问题 2022-02-18 17:21:11 +08:00
lyswhut
6aa7f2a0ee 移除多余样式 2022-02-18 16:34:35 +08:00
lyswhut
d801d55c3c 修复进度条动画问题 2022-02-18 16:21:03 +08:00
lyswhut
491e644c3c 修改进度条高度 2022-02-18 16:15:08 +08:00
lyswhut
5844232a00 添加源数量限制 2022-02-18 15:50:51 +08:00
lyswhut
abbf067625 修复歌单无法从用data传参调用的问题 2022-02-18 14:48:15 +08:00
lyswhut
806c882965 更新说明 2022-02-18 11:26:17 +08:00
lyswhut
3fe5a85ffe 更新依赖 2022-02-18 10:33:56 +08:00
lyswhut
95dae62bb3 更新说明 2022-02-17 16:29:42 +08:00
lyswhut
f7edd54ea7 修复宽度计算问题 2022-02-17 15:48:55 +08:00
lyswhut
78ae89199e 更新说明 2022-02-17 14:53:51 +08:00
lyswhut
fc12a235f2 自定义源添加更新地址参数 2022-02-17 10:13:45 +08:00
lyswhut
48fc96226c 更新版本号 2022-02-16 18:38:11 +08:00
lyswhut
3534dd27dc 自定义源新增更新弹窗方法 2022-02-16 18:32:55 +08:00
lyswhut
a7e3c1a0c4 优化进度条动画 2022-02-16 11:30:35 +08:00
lyswhut
43c5051158 打开播放详情页时隐藏外部进度条 2022-02-16 10:33:52 +08:00
lyswhut
2f56a7090a 新增Scheme URL对音乐搜索的调用支持;新增Scheme URL以url传参的方式调用 2022-02-15 18:49:02 +08:00
lyswhut
13ffcfbbcd 更新调用错误信息弹窗按钮文案 2022-02-15 15:29:13 +08:00
lyswhut
1aeb8e29e2 更新依赖 2022-02-15 15:13:25 +08:00
lyswhut
a3b844d2e3 添加缺失的翻译 2022-02-14 15:55:12 +08:00
lyswhut
5aa027f1a9 修复问题 2022-02-14 15:48:43 +08:00
lyswhut
c12be6a1c8 新增定时暂停播放功能 2022-02-14 15:38:27 +08:00
lyswhut
c891ed81e1 修复某些歌曲无法下载的问题 2022-02-13 14:17:38 +08:00
lyswhut
c48921990d 修复下载功能的歌词换源时会进入死循环的问题 2022-02-13 14:16:45 +08:00
lyswhut
54bfd945e5 修复wy源某些歌曲获取歌词翻译的问题处理 2022-02-13 14:14:23 +08:00
lyswhut
1d8c4db5eb 更新版本号 2022-02-12 18:25:39 +08:00
lyswhut
055ab98d4c 把歌曲的热门评论与最新评论拆分成两个列表显示 2022-02-11 19:38:51 +08:00
lyswhut
777551cb43 新增打开收藏的在线列表的对应平台详情页功能 2022-02-11 16:51:39 +08:00
lyswhut
68827f7697 修复修改列表名时无法使用Ctrl键的问题 2022-02-11 16:06:07 +08:00
lyswhut
8e5b144f00 新增“双击列表里的歌曲时自动切换到当前列表播放”设置 2022-02-10 12:48:01 +08:00
lyswhut
748a420b64 修复排行榜名字右击菜单的播放功能在播放非激活的列表时的列表获取问题 2022-02-09 21:02:43 +08:00
lyswhut
80fc43a075 更新依赖 2022-02-09 19:53:26 +08:00
lyswhut
0588f2846b 添加链接 2022-02-08 17:34:58 +08:00
lyswhut
8e4e7d9efa 更新依赖 2022-02-07 13:02:46 +08:00
lyswhut
6df01edc7a 更新electron到v13.6.9 2022-02-04 18:30:06 +08:00
lyswhut
996396c943 过滤tx源某些不支持播放的歌曲,解决播放此类内容会导致意外的问题 2022-02-04 18:29:48 +08:00
240 changed files with 26743 additions and 7146 deletions

View File

@@ -30,5 +30,5 @@
"settings": {
"html/html-extensions": [".html", ".vue"]
},
"ignorePatterns": ["vendors", "*.min.js"]
"ignorePatterns": ["vendors", "*.min.js", "dist", "node_modules"]
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -2,11 +2,13 @@ module.exports = {
upgrade: true,
reject: [
'electron',
'electron-builder',
'chalk',
'del',
],
// target: 'newest',
// filter: [
// /^vue/,
// 'electron-builder',
// 'electron-updater',
// ],
}

View File

@@ -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
View File

@@ -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>`歌曲hashkg源必传<br>`strMediaMid<String>`歌曲strMediaMidtx源必传<br>`albumMid<String>`歌曲albumMidtx源专用选传<br>`copyrightId<String>`歌曲copyrightIdmg源必传<br>`lrcUrl<String>`歌曲lrcUrlmg源专用选传
### `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`

View File

@@ -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>
### 项目协议

View File

@@ -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(),
],

View File

@@ -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,
},
})

View File

@@ -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,
},

View File

@@ -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' })

View File

@@ -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',

View File

@@ -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: {

View File

@@ -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',

View File

@@ -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, '\\\\')}"`,

View File

@@ -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: {

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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"
}
}
}

View File

@@ -1,12 +1,13 @@
### 优化
- 优化kw源英文与翻译歌词的匹配
- 为tx、kw源添加 Flac 24bit 音质显示,注:由于之前没有记录此音质,所以之前收藏的歌曲信息中不包含它
### 修复
- 修复快捷键与默认按键行为冲突的问题现在若将某些有默认行为的按键如在列表中上、下箭头、Home、End等键可以使列表滚动设置为快捷键时将禁用其默认行为
- 修复列表的聚焦问题,现在在列表中使用上、下箭头、空格等键滚动列表时不会导致滚动到一定距离后丢失焦点的问题
- 修复无法批量排序歌曲的问题
- 修复某些缺失的繁体中文翻译
- 修复企鹅音乐搜索失效的问题
### 其他
- 更新electron到v13.6.8
- 降级electron到v15.5.7

View File

@@ -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

View File

@@ -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],
}

View File

@@ -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
}

View File

@@ -65,6 +65,7 @@ const hotKey = {
}
const keyName = {
common: names.mainWindow.name,
player: names.mainWindow.name,
desktop_lyric: names.winLyric.name,
}

View File

@@ -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',

View File

@@ -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'

View File

@@ -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"
}

View File

@@ -32,6 +32,7 @@ langs.forEach(item => {
langList.push({
name: item.name,
locale: item.locale,
alternate: item.alternate,
})
messages[item.locale] = item.message
})

View File

@@ -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": "打开更新地址"
}

View File

@@ -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": "打開更新地址"
}

View File

@@ -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)
}

View File

@@ -14,6 +14,8 @@ exports.mainWindow = {
ready_to_show: 'ready_to_show',
show: 'show',
hide: 'hide',
focus: 'focus',
blur: 'blur',
}
exports.tray = {

View File

@@ -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()

View File

@@ -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))
})

View File

@@ -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()

View File

@@ -2,4 +2,3 @@ require('./appMenu')
require('./winLyric')
require('./tray')
require('./hotKey')
require('./userApi')

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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`)
}

View 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

View File

@@ -0,0 +1,3 @@
module.exports = {
thumbarButtonClick: 'thumbarButtonClick',
}

View 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))
}

View File

@@ -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: '关闭桌面歌词',

View File

@@ -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

View File

@@ -1,3 +1,4 @@
module.exports = {
status: 'status',
showUpdateAlert: 'showUpdateAlert',
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -3,6 +3,7 @@ const names = {
request: '',
response: '',
openDevTools: '',
showUpdateAlert: '',
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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()
}
}

View File

@@ -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) {

View File

@@ -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,
}
})

View File

@@ -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')

View File

@@ -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))

View 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)
})

View File

@@ -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)
}
}
})

View File

@@ -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)

View 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)
})

View File

@@ -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
})

View File

@@ -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)
})

View File

@@ -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)
})

View File

@@ -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', () => {

View File

@@ -41,3 +41,9 @@ exports.initSetting = (isShowErrorAlert = true) => {
global.appSetting = info.setting
global.appSettingVersion = info.version
}
exports.openDevTools = webContents => {
webContents.openDevTools({
mode: 'undocked',
})
}

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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 {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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%);

View 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

View 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

View 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

View File

@@ -41,6 +41,7 @@ export default {
default: false,
},
},
emits: ['update:modelValue', 'change'],
data() {
return {
bool: false,

View File

@@ -24,7 +24,7 @@ export default {
default: false,
},
modelValue: {
type: String,
type: [String, Number],
default: '',
},
type: {

View File

@@ -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)"

View File

@@ -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>

View File

@@ -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()
})

View File

@@ -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()
})

View File

@@ -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;

View File

@@ -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;

View File

@@ -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'))}}&nbsp;<span :class="$style.name">{{this.musicInfo && `${musicInfo.name}`}}</span>&nbsp;{{$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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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)
},

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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