diff --git a/publish/changeLog.md b/publish/changeLog.md
index fb316e41..46750c97 100644
--- a/publish/changeLog.md
+++ b/publish/changeLog.md
@@ -2,6 +2,13 @@
- 新增`rpm`、`pacman`包的打包
- 新增当前音频输出设备改变时是否暂停播放的设置,默认关闭
+- 新增自定义列表,编辑列表名字时,按`ESC`键可取消编辑,按回车键或使输入框失去焦点即可保存列表名字
+
+### 优化
+
+- 优化浮动按钮与布局颜色
+- 改进歌曲切换时的歌词滚动效果
+- 极大优化批量添加、删除播放列表的歌曲操作流畅度
### 修复
diff --git a/src/common/config.js b/src/common/config.js
index a04e49b6..451cc76e 100644
--- a/src/common/config.js
+++ b/src/common/config.js
@@ -33,7 +33,7 @@ module.exports = {
name: 'larger',
width: 1198,
height: 766,
- fontSize: '18px',
+ fontSize: '17px',
},
{
id: 5,
diff --git a/src/renderer/App.vue b/src/renderer/App.vue
index ea1117a2..5c5fc516 100644
--- a/src/renderer/App.vue
+++ b/src/renderer/App.vue
@@ -58,7 +58,7 @@ export default {
computed: {
...mapGetters('player', ['isShowPlayerDetail']),
...mapGetters(['setting', 'theme', 'version', 'windowSizeActive']),
- ...mapGetters('list', ['defaultList', 'loveList']),
+ ...mapGetters('list', ['defaultList', 'loveList', 'userList']),
...mapGetters('download', {
downloadList: 'list',
downloadStatus: 'downloadStatus',
@@ -81,6 +81,9 @@ export default {
this.saveLoveList = throttle(n => {
window.electronStore_list.set('loveList', n)
}, 500)
+ this.saveUserList = throttle(n => {
+ window.electronStore_list.set('userList', n)
+ }, 500)
this.saveDownloadList = throttle(n => {
window.electronStore_list.set('downloadList', n)
}, 1000)
@@ -112,6 +115,12 @@ export default {
},
deep: true,
},
+ userList: {
+ handler(n) {
+ this.saveUserList(n)
+ },
+ deep: true,
+ },
downloadList: {
handler(n) {
this.saveDownloadList(n)
@@ -196,6 +205,7 @@ export default {
})
}, 60 * 30 * 1000)
+ this.listenEvent()
this.initData()
this.globalObj.apiSource = this.setting.apiSource
this.globalObj.qualityList = music.supportQuality[this.setting.apiSource]
@@ -221,9 +231,10 @@ export default {
this.initDownloadList() // 初始化下载列表
},
initPlayList() {
- let defaultList = window.electronStore_list.get('defaultList')
- let loveList = window.electronStore_list.get('loveList')
- this.initList({ defaultList, loveList })
+ let defaultList = window.electronStore_list.get('defaultList') || this.defaultList
+ let loveList = window.electronStore_list.get('loveList') || this.loveList
+ let userList = window.electronStore_list.get('userList') || this.userList
+ this.initList({ defaultList, loveList, userList })
},
initDownloadList() {
let downloadList = window.electronStore_list.get('downloadList')
@@ -303,9 +314,22 @@ export default {
handleXMVerifyModalClose() {
music.xm.closeVerifyModal()
},
+ listenEvent() {
+ window.eventHub.$on('key_escape_down', this.handle_key_esc_down)
+ },
+ unlistenEvent() {
+ window.eventHub.$off('key_escape_down', this.handle_key_esc_down)
+ },
+ handle_key_esc_down({ event }) {
+ if (event.repeat) return
+ if (event.target.tagName != 'INPUT' || event.target.classList.contains('ignore-esc')) return
+ event.target.value = ''
+ event.target.blur()
+ },
},
beforeDestroy() {
this.clearUpdateTimeout()
+ this.unlistenEvent()
if (this.isProd) {
document.body.removeEventListener('mouseenter', this.dieableIgnoreMouseEvents)
document.body.removeEventListener('mouseleave', this.enableIgnoreMouseEvents)
@@ -330,7 +354,7 @@ body {
padding: @shadow-app;
#container {
box-shadow: 0 0 @shadow-app rgba(0, 0, 0, 0.5);
- border-radius: 4px;
+ border-radius: @radius-border;
background-color: transparent;
}
}
@@ -359,6 +383,10 @@ body {
flex-flow: column nowrap;
transition: background-color @transition-theme;
background-color: @color-theme_2;
+
+ border-top-left-radius: @radius-border;
+ border-bottom-left-radius: @radius-border;
+ overflow: hidden;
}
#toolbar, #player {
flex: none;
diff --git a/src/renderer/assets/styles/index.less b/src/renderer/assets/styles/index.less
index 3d50608a..acde4152 100644
--- a/src/renderer/assets/styles/index.less
+++ b/src/renderer/assets/styles/index.less
@@ -40,25 +40,23 @@ table {
th {
font-size: 12px;
text-align: left;
- height: 28px;
- line-height: 28px;
- padding: 5px;
+ line-height: 38px;
+ padding: 0 6px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
tbody {
tr {
- border-top: 1px solid @color-theme_2-line;
// border-top: 1px solid rgba(0, 0, 0, 0.12);
transition: background-color 0.2s ease;
+ + tr {
+ border-top: 1px solid @color-theme_2-line;
+ }
&:hover {
background-color: @color-theme_2-hover;
}
&.active {
background-color: @color-theme_2-active;
}
- &:first-child {
- border-top: none;
- }
td {
padding: 6px;
position: relative;
diff --git a/src/renderer/assets/styles/variables.less b/src/renderer/assets/styles/variables.less
index 1bc71284..6d4a8ae7 100644
--- a/src/renderer/assets/styles/variables.less
+++ b/src/renderer/assets/styles/variables.less
@@ -35,9 +35,9 @@
// @color-search-list-background: fadeout(lighten(@color-theme, 35%), 10%);
@color-search-list-hover: fadeout(darken(@color-theme, 10%), 70%);
-@color-scrollbar-track: fadeout(@color-theme, 80%);
-@color-scrollbar-thumb: fadeout(@color-theme, 60%);
-@color-scrollbar-thumb-hover: fadeout(@color-theme, 40%);
+@color-scrollbar-track: fadeout(lighten(@color-theme, 10%), 65%);
+@color-scrollbar-thumb: fadeout(lighten(@color-theme, 10%), 45%);
+@color-scrollbar-thumb-hover: fadeout(lighten(@color-theme, 10%), 25%);
@color-player-pic-c1: fadeout(@color-theme_2, 50%);
@@ -95,9 +95,9 @@
@color-green-pagination-select: fadeout(lighten(@color-green-theme, 10%), 50%);
@color-green-search-form-background: fadeout(lighten(@color-green-theme, 35%), 10%);
@color-green-search-list-hover: fadeout(darken(@color-green-theme, 10%), 70%);
-@color-green-scrollbar-track: fadeout(@color-green-theme, 80%);
-@color-green-scrollbar-thumb: fadeout(@color-green-theme, 60%);
-@color-green-scrollbar-thumb-hover: fadeout(@color-green-theme, 40%);
+@color-green-scrollbar-track: fadeout(lighten(@color-green-theme, 10%), 75%);
+@color-green-scrollbar-thumb: fadeout(lighten(@color-green-theme, 10%), 50%);
+@color-green-scrollbar-thumb-hover: fadeout(lighten(@color-green-theme, 10%), 30%);
@color-green-player-pic-c1: fadeout(@color-green-theme_2, 50%);
@color-green-player-pic-c2: darken(@color-green-theme_2, 30%);
@color-green-player-progress: darken(@color-green-theme_2, 6%);
@@ -148,9 +148,9 @@
@color-yellow-pagination-select: fadeout(lighten(@color-yellow-theme, 5%), 50%);
@color-yellow-search-form-background: fadeout(lighten(@color-yellow-theme, 25%), 10%);
@color-yellow-search-list-hover: fadeout(darken(@color-yellow-theme, 10%), 60%);
-@color-yellow-scrollbar-track: fadeout(@color-yellow-theme, 60%);
-@color-yellow-scrollbar-thumb: fadeout(@color-yellow-theme, 45%);
-@color-yellow-scrollbar-thumb-hover: fadeout(@color-yellow-theme, 30%);
+@color-yellow-scrollbar-track: fadeout(lighten(@color-yellow-theme, 5%), 65%);
+@color-yellow-scrollbar-thumb: fadeout(lighten(@color-yellow-theme, 5%), 30%);
+@color-yellow-scrollbar-thumb-hover: fadeout(lighten(@color-yellow-theme, 5%), 15%);
@color-yellow-player-pic-c1: fadeout(@color-yellow-theme_2, 50%);
@color-yellow-player-pic-c2: darken(@color-yellow-theme_2, 30%);
@color-yellow-player-progress: darken(@color-yellow-theme_2, 6%);
@@ -200,9 +200,9 @@
@color-orange-pagination-select: fadeout(lighten(@color-orange-theme, 10%), 50%);
@color-orange-search-form-background: fadeout(lighten(@color-orange-theme, 30%), 10%);
@color-orange-search-list-hover: fadeout(darken(@color-orange-theme, 10%), 70%);
-@color-orange-scrollbar-track: fadeout(@color-orange-theme, 80%);
-@color-orange-scrollbar-thumb: fadeout(@color-orange-theme, 60%);
-@color-orange-scrollbar-thumb-hover: fadeout(@color-orange-theme, 40%);
+@color-orange-scrollbar-track: fadeout(lighten(@color-orange-theme, 10%), 75%);
+@color-orange-scrollbar-thumb: fadeout(lighten(@color-orange-theme, 10%), 45%);
+@color-orange-scrollbar-thumb-hover: fadeout(lighten(@color-orange-theme, 10%), 25%);
@color-orange-player-pic-c1: fadeout(@color-orange-theme_2, 50%);
@color-orange-player-pic-c2: darken(@color-orange-theme_2, 30%);
@color-orange-player-progress: darken(@color-orange-theme_2, 6%);
@@ -252,9 +252,9 @@
@color-blue-pagination-select: fadeout(lighten(@color-blue-theme, 15%), 50%);
@color-blue-search-form-background: fadeout(lighten(@color-blue-theme, 35%), 10%);
@color-blue-search-list-hover: fadeout(darken(@color-blue-theme, 10%), 70%);
-@color-blue-scrollbar-track: fadeout(@color-blue-theme, 80%);
-@color-blue-scrollbar-thumb: fadeout(@color-blue-theme, 60%);
-@color-blue-scrollbar-thumb-hover: fadeout(@color-blue-theme, 40%);
+@color-blue-scrollbar-track: fadeout(lighten(@color-blue-theme, 10%), 75%);
+@color-blue-scrollbar-thumb: fadeout(lighten(@color-blue-theme, 10%), 50%);
+@color-blue-scrollbar-thumb-hover: fadeout(lighten(@color-blue-theme, 10%), 35%);
@color-blue-player-pic-c1: fadeout(@color-blue-theme_2, 50%);
@color-blue-player-pic-c2: darken(@color-blue-theme_2, 30%);
@color-blue-player-progress: darken(@color-blue-theme_2, 6%);
@@ -304,9 +304,9 @@
@color-red-pagination-select: fadeout(lighten(@color-red-theme, 15%), 50%);
@color-red-search-form-background: fadeout(lighten(@color-red-theme, 35%), 10%);
@color-red-search-list-hover: fadeout(darken(@color-red-theme, 10%), 70%);
-@color-red-scrollbar-track: fadeout(@color-red-theme, 80%);
-@color-red-scrollbar-thumb: fadeout(@color-red-theme, 60%);
-@color-red-scrollbar-thumb-hover: fadeout(@color-red-theme, 40%);
+@color-red-scrollbar-track: fadeout(lighten(@color-red-theme, 10%), 75%);
+@color-red-scrollbar-thumb: fadeout(lighten(@color-red-theme, 10%), 45%);
+@color-red-scrollbar-thumb-hover: fadeout(lighten(@color-red-theme, 10%), 25%);
@color-red-player-pic-c1: fadeout(@color-red-theme_2, 50%);
@color-red-player-pic-c2: darken(@color-red-theme_2, 30%);
@color-red-player-progress: darken(@color-red-theme_2, 6%);
@@ -358,9 +358,9 @@
@color-pink-pagination-select: fadeout(lighten(@color-pink-theme, 5%), 50%);
@color-pink-search-form-background: fadeout(lighten(@color-pink-theme, 20%), 10%);
@color-pink-search-list-hover: fadeout(darken(@color-pink-theme, 10%), 60%);
-@color-pink-scrollbar-track: fadeout(@color-pink-theme, 60%);
-@color-pink-scrollbar-thumb: fadeout(@color-pink-theme, 45%);
-@color-pink-scrollbar-thumb-hover: fadeout(@color-pink-theme, 30%);
+@color-pink-scrollbar-track: fadeout(lighten(@color-pink-theme, 6%), 75%);
+@color-pink-scrollbar-thumb: fadeout(lighten(@color-pink-theme, 6%), 35%);
+@color-pink-scrollbar-thumb-hover: fadeout(lighten(@color-pink-theme, 6%), 20%);
@color-pink-player-pic-c1: fadeout(@color-pink-theme_2, 50%);
@color-pink-player-pic-c2: darken(@color-pink-theme_2, 30%);
@color-pink-player-progress: darken(@color-pink-theme_2, 6%);
@@ -410,9 +410,9 @@
@color-purple-pagination-select: fadeout(lighten(@color-purple-theme, 15%), 50%);
@color-purple-search-form-background: fadeout(lighten(@color-purple-theme, 35%), 10%);
@color-purple-search-list-hover: fadeout(darken(@color-purple-theme, 10%), 70%);
-@color-purple-scrollbar-track: fadeout(@color-purple-theme, 80%);
-@color-purple-scrollbar-thumb: fadeout(@color-purple-theme, 60%);
-@color-purple-scrollbar-thumb-hover: fadeout(@color-purple-theme, 40%);
+@color-purple-scrollbar-track: fadeout(lighten(@color-purple-theme, 10%), 77%);
+@color-purple-scrollbar-thumb: fadeout(lighten(@color-purple-theme, 10%), 50%);
+@color-purple-scrollbar-thumb-hover: fadeout(lighten(@color-purple-theme, 10%), 35%);
@color-purple-player-pic-c1: fadeout(@color-purple-theme_2, 50%);
@color-purple-player-pic-c2: darken(@color-purple-theme_2, 30%);
@color-purple-player-progress: darken(@color-purple-theme_2, 6%);
@@ -462,9 +462,9 @@
@color-grey-pagination-select: fadeout(lighten(@color-grey-theme, 10%), 50%);
@color-grey-search-form-background: fadeout(lighten(@color-grey-theme, 35%), 10%);
@color-grey-search-list-hover: fadeout(darken(@color-grey-theme, 10%), 70%);
-@color-grey-scrollbar-track: fadeout(@color-grey-theme, 80%);
-@color-grey-scrollbar-thumb: fadeout(@color-grey-theme, 60%);
-@color-grey-scrollbar-thumb-hover: fadeout(@color-grey-theme, 40%);
+@color-grey-scrollbar-track: fadeout(lighten(@color-grey-theme, 10%), 75%);
+@color-grey-scrollbar-thumb: fadeout(lighten(@color-grey-theme, 10%), 50%);
+@color-grey-scrollbar-thumb-hover: fadeout(lighten(@color-grey-theme, 10%), 35%);
@color-grey-player-pic-c1: fadeout(@color-grey-theme_2, 50%);
@color-grey-player-pic-c2: darken(@color-grey-theme_2, 30%);
@color-grey-player-progress: darken(@color-grey-theme_2, 6%);
@@ -515,9 +515,9 @@
@color-ming-pagination-select: fadeout(lighten(@color-ming-theme, 15%), 50%);
@color-ming-search-form-background: fadeout(lighten(@color-ming-theme, 45%), 15%);
@color-ming-search-list-hover: fadeout(darken(@color-ming-theme, 10%), 70%);
-@color-ming-scrollbar-track: fadeout(@color-ming-theme, 80%);
-@color-ming-scrollbar-thumb: fadeout(@color-ming-theme, 60%);
-@color-ming-scrollbar-thumb-hover: fadeout(@color-ming-theme, 40%);
+@color-ming-scrollbar-track: fadeout(lighten(@color-ming-theme, 10%), 75%);
+@color-ming-scrollbar-thumb: fadeout(lighten(@color-ming-theme, 10%), 50%);
+@color-ming-scrollbar-thumb-hover: fadeout(lighten(@color-ming-theme, 10%), 35%);
@color-ming-player-pic-c1: fadeout(@color-ming-theme_2, 50%);
@color-ming-player-pic-c2: darken(@color-ming-theme_2, 30%);
@color-ming-player-progress: darken(@color-ming-theme_2, 6%);
@@ -569,9 +569,9 @@
@color-mid_autumn-pagination-select: fadeout(lighten(@color-mid_autumn-theme, 10%), 55%);
@color-mid_autumn-search-form-background: fadeout(lighten(@color-mid_autumn-theme, 50%), 10%);
@color-mid_autumn-search-list-hover: fadeout(darken(@color-mid_autumn-theme, 10%), 70%);
-@color-mid_autumn-scrollbar-track: fadeout(@color-mid_autumn-theme, 80%);
-@color-mid_autumn-scrollbar-thumb: fadeout(@color-mid_autumn-theme, 60%);
-@color-mid_autumn-scrollbar-thumb-hover: fadeout(@color-mid_autumn-theme, 40%);
+@color-mid_autumn-scrollbar-track: fadeout(lighten(@color-mid_autumn-theme, 10%), 80%);
+@color-mid_autumn-scrollbar-thumb: fadeout(lighten(@color-mid_autumn-theme, 10%), 60%);
+@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%);
@@ -621,9 +621,9 @@
@color-naruto-pagination-select: fadeout(lighten(@color-naruto-theme, 10%), 50%);
@color-naruto-search-form-background: fadeout(lighten(@color-naruto-theme, 30%), 20%);
@color-naruto-search-list-hover: fadeout(darken(@color-naruto-theme, 10%), 50%);
-@color-naruto-scrollbar-track: fadeout(@color-naruto-theme, 80%);
-@color-naruto-scrollbar-thumb: fadeout(@color-naruto-theme, 60%);
-@color-naruto-scrollbar-thumb-hover: fadeout(@color-naruto-theme, 40%);
+@color-naruto-scrollbar-track: fadeout(lighten(@color-naruto-theme, 10%), 75%);
+@color-naruto-scrollbar-thumb: fadeout(lighten(@color-naruto-theme, 10%), 50%);
+@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%);
@@ -673,9 +673,9 @@
@color-happy_new_year-pagination-select: fadeout(lighten(@color-happy_new_year-theme, 10%), 55%);
@color-happy_new_year-search-form-background: fadeout(lighten(@color-happy_new_year-theme, 15%), 20%);
@color-happy_new_year-search-list-hover: fadeout(darken(@color-happy_new_year-theme, 10%), 50%);
-@color-happy_new_year-scrollbar-track: fadeout(@color-happy_new_year-theme, 80%);
-@color-happy_new_year-scrollbar-thumb: fadeout(@color-happy_new_year-theme, 60%);
-@color-happy_new_year-scrollbar-thumb-hover: fadeout(@color-happy_new_year-theme, 40%);
+@color-happy_new_year-scrollbar-track: fadeout(lighten(@color-happy_new_year-theme, 6%), 75%);
+@color-happy_new_year-scrollbar-thumb: fadeout(lighten(@color-happy_new_year-theme, 6%), 50%);
+@color-happy_new_year-scrollbar-thumb-hover: fadeout(lighten(@color-happy_new_year-theme, 6%), 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%);
@@ -703,11 +703,11 @@
// Width
-@width-app-left: 20%;
+@width-app-left: 6.5%;
// Height
-@height-toolbar: 50px;
-@height-player: 55px;
+@height-toolbar: 54px;
+@height-player: 60px;
// Shadow
@@ -716,6 +716,7 @@
// Radius
@radius-progress-border: 5px;
+@radius-border: 4px;
@transition-theme: .4s ease;
diff --git a/src/renderer/components/core/Aside.vue b/src/renderer/components/core/Aside.vue
index d3a84350..56132281 100644
--- a/src/renderer/components/core/Aside.vue
+++ b/src/renderer/components/core/Aside.vue
@@ -1,44 +1,56 @@
div(:class="$style.aside")
- div(:class="['animated', logoAnimate, $style.logo]")
- svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='100%' height='100%' viewBox='0 0 127 61' space='preserve')
+ div(:class="['animated', logoAnimate, $style.logo]") L X
+ //- svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='100%' height='100%' viewBox='0 0 127 61' space='preserve')
use(xlink:href='#icon-logo')
div(:class="$style.menu")
dl
- dt {{$t('core.aside.online_music')}}
+ //- dt {{$t('core.aside.online_music')}}
dd
- router-link(:active-class="$style.active" to="search") {{$t('core.aside.search')}}
+ router-link(:active-class="$style.active" to="search" :title="$t('core.aside.search')")
+ div(:class="$style.icon")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 801.99 811.98' space='preserve')
+ use(xlink:href='#icon-search-2')
dd
- router-link(:active-class="$style.active" to="songList") {{$t('core.aside.song_list')}}
+ router-link(:active-class="$style.active" to="songList" :title="$t('core.aside.song_list')")
+ div(:class="$style.icon")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 739.96 763.59' space='preserve')
+ use(xlink:href='#icon-album')
+ //- span {{$t('core.aside.song_list')}}
dd
- router-link(:active-class="$style.active" to="leaderboard") {{$t('core.aside.leaderboard')}}
+ router-link(:active-class="$style.active" to="leaderboard" :title="$t('core.aside.leaderboard')")
+ div(:class="$style.icon")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 819.1 819.38' space='preserve')
+ use(xlink:href='#icon-leaderboard')
+ //- span {{$t('core.aside.leaderboard')}}
dl
- dt {{$t('core.aside.my_music')}}
+ //- dt {{$t('core.aside.my_music')}}
dd
- router-link(:active-class="($route.query.id === defaultList.id || $route.query.id == '') ? $style.active : ''" :to="`list?id=${defaultList.id || ''}`") {{$t('core.aside.default_list')}}
- router-link(:active-class="$route.query.id === loveList.id ? $style.active : ''" :to="`list?id=${loveList.id}`") {{$t('core.aside.love_list')}}
- router-link(:active-class="$route.query.id === item.id ? $style.active : ''" v-for="item in userList" :to="`list?id=${item._id}`" :key="item._id") {{item.name}}
+ router-link(:active-class="$style.active" :title="$t('core.aside.my_list')" :to="`list?id=${setting.list.prevSelectListId || defaultList.id}`")
+ div(:class="$style.icon")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 830.33 740.22' space='preserve')
+ use(xlink:href='#icon-love')
dl
- dt {{$t('core.aside.other')}}
+ //- dt {{$t('core.aside.other')}}
dd
- router-link(:active-class="$style.active" to="download") {{$t('core.aside.download')}}
+ router-link(:active-class="$style.active" to="download" :title="$t('core.aside.download')")
+ div(:class="$style.icon")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 798.85 718.96' space='preserve')
+ use(xlink:href='#icon-download-2')
+ //- span {{$t('core.aside.download')}}
dd
- router-link(:active-class="$style.active" to="setting") {{$t('core.aside.setting')}}
+ router-link(:active-class="$style.active" to="setting" :title="$t('core.aside.setting')")
+ div(:class="$style.icon")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 854.85 775.41' space='preserve')
+ use(xlink:href='#icon-setting')
+ //- span {{$t('core.aside.setting')}}
+
+
+
diff --git a/src/renderer/components/material/DownloadModal.vue b/src/renderer/components/material/DownloadModal.vue
index efe021d6..f47f3b2b 100644
--- a/src/renderer/components/material/DownloadModal.vue
+++ b/src/renderer/components/material/DownloadModal.vue
@@ -30,7 +30,7 @@ export default {
return this.musicInfo || {}
},
qualityList() {
- return window.globalObj.qualityList[this.musicInfo.source]
+ return window.globalObj.qualityList[this.musicInfo.source] || []
},
},
methods: {
diff --git a/src/renderer/components/material/FlowBtn.vue b/src/renderer/components/material/FlowBtn.vue
index be316b65..15647151 100644
--- a/src/renderer/components/material/FlowBtn.vue
+++ b/src/renderer/components/material/FlowBtn.vue
@@ -71,10 +71,11 @@ export default {
position: fixed;
bottom: 80px;
right: 30px;
- background-color: @color-search-form-background;
+ // transform: translateX(-25%);
+ background-color: @color-theme_2-background_2;
border-radius: 5px;
// padding: 3px 5px;
- box-shadow: 0 1px 5px 0 rgba(0,0,0,.2);
+ box-shadow: 0 1px 8px 0 rgba(0,0,0,.2);
button {
background-color: transparent;
border: none;
@@ -106,7 +107,7 @@ export default {
each(@themes, {
:global(#container.@{value}) {
.btns {
- background-color: ~'@{color-@{value}-search-form-background}';
+ background-color: ~'@{color-@{value}-theme_2-background_2}';
button {
color: ~'@{color-@{value}-btn}';
&:hover {
diff --git a/src/renderer/components/material/Input.vue b/src/renderer/components/material/Input.vue
index 478e12e2..5aab07f5 100644
--- a/src/renderer/components/material/Input.vue
+++ b/src/renderer/components/material/Input.vue
@@ -55,6 +55,7 @@ export default {
outline: none;
transition: background-color 0.2s ease;
background-color: @color-btn-background;
+ font-size: 13.3px;
&[disabled] {
opacity: .4;
}
diff --git a/src/renderer/components/material/Menu.vue b/src/renderer/components/material/Menu.vue
new file mode 100644
index 00000000..aacaec91
--- /dev/null
+++ b/src/renderer/components/material/Menu.vue
@@ -0,0 +1,172 @@
+
+ul(:class="$style.list" :style="listStyles" ref="dom_list")
+ li(v-for="item in menus" @click="handleClick(item)" :disabled="item.disabled") {{item[itemName]}}
+
+
+
+
+
+
diff --git a/src/renderer/components/material/Pagination.vue b/src/renderer/components/material/Pagination.vue
index 82c51726..53ca3bf3 100644
--- a/src/renderer/components/material/Pagination.vue
+++ b/src/renderer/components/material/Pagination.vue
@@ -118,7 +118,7 @@ export default {
display: inline-block;
background-color: @color-pagination-background;
// border-top-left-radius: 8px;
- border-radius: 4px;
+ border-radius: @radius-border;
ul {
display: flex;
flex-flow: row nowrap;
@@ -170,15 +170,15 @@ export default {
}
&:first-child {
span, button {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
+ border-top-left-radius: @radius-border;
+ border-bottom-left-radius: @radius-border;
}
// border-right: .0625rem solid @theme_line;
}
&:last-child {
span, button {
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
+ border-top-right-radius: @radius-border;
+ border-bottom-right-radius: @radius-border;
}
// border-right: .0625rem solid @theme_line;
}
diff --git a/src/renderer/components/material/SearchInput.vue b/src/renderer/components/material/SearchInput.vue
index 0d060e1b..ac599f5e 100644
--- a/src/renderer/components/material/SearchInput.vue
+++ b/src/renderer/components/material/SearchInput.vue
@@ -140,7 +140,7 @@ export default {
transition: box-shadow .4s ease, background-color @transition-theme;
display: flex;
flex-flow: column nowrap;
- width: 240px;
+ width: 35%;
background-color: @color-search-form-background;
&.active {
@@ -148,6 +148,7 @@ export default {
.form {
input {
border-bottom-left-radius: 0;
+
}
button {
border-bottom-right-radius: 0;
@@ -156,7 +157,7 @@ export default {
}
.form {
display: flex;
- height: @height-toolbar / 2;
+ height: @height-toolbar * 0.52;
position: relative;
input {
flex: auto;
@@ -172,6 +173,8 @@ export default {
// height: @height-toolbar * .7;
padding: 0 5px;
overflow: hidden;
+ font-size: 13.5px;
+ line-height: @height-toolbar * 0.52 + 5px;
&::placeholder {
color: @color-btn;
}
@@ -186,7 +189,7 @@ export default {
border-bottom-right-radius: 3px;
cursor: pointer;
height: 100%;
- padding: 5px 7px;
+ padding: 6px 7px;
color: @color-btn;
transition: background-color .2s ease;
@@ -226,7 +229,8 @@ export default {
}
.big {
- width: 500px;
+ min-width: 500px;
+ width: 100%;
// input {
// line-height: 30px;
// }
diff --git a/src/renderer/components/material/Select.vue b/src/renderer/components/material/Select.vue
index ffccc0d7..37cf2cda 100644
--- a/src/renderer/components/material/Select.vue
+++ b/src/renderer/components/material/Select.vue
@@ -80,7 +80,7 @@ export default {
border-left: 2px solid @color-tab-border-bottom;
box-sizing: border-box;
text-align: center;
- border-top-left-radius: 4px;
+ border-top-left-radius: @radius-border;
color: @color-btn;
cursor: pointer;
.mixin-ellipsis-1;
@@ -100,7 +100,7 @@ export default {
left: 0;
border-bottom: 2px solid @color-tab-border-bottom;
border-left: 2px solid @color-tab-border-bottom;
- border-bottom-left-radius: 4px;
+ border-bottom-left-radius: @radius-border;
background-color: @color-theme_2-background_2;
opacity: 0;
transform: scaleY(0);
diff --git a/src/renderer/components/material/SongList.vue b/src/renderer/components/material/SongList.vue
index 0214552a..6343670c 100644
--- a/src/renderer/components/material/SongList.vue
+++ b/src/renderer/components/material/SongList.vue
@@ -10,8 +10,8 @@ div(:class="$style.songList")
th.nobreak(style="width: 25%;") {{$t('material.song_list.name')}}
th.nobreak(style="width: 20%;") {{$t('material.song_list.singer')}}
th.nobreak(style="width: 20%;") {{$t('material.song_list.album')}}
- th.nobreak(style="width: 20%;") {{$t('material.song_list.action')}}
th.nobreak(style="width: 10%;") {{$t('material.song_list.time')}}
+ th.nobreak(style="width: 20%;") {{$t('material.song_list.action')}}
div.scroll(:class="$style.tbody" ref="dom_scrollContent")
table
tbody(@contextmenu="handleContextMenu" ref="dom_tbody")
@@ -25,8 +25,10 @@ div(:class="$style.songList")
span.select {{item.singer}}
td.break(style="width: 20%;")
span.select {{item.albumName}}
+ td(style="width: 10%;")
+ span(:class="[$style.time, $style.noSelect]") {{item.interval || '--/--'}}
td(style="width: 20%; padding-left: 0; padding-right: 0;")
- material-list-buttons(:index="index" :search-btn="true"
+ material-list-buttons(:index="index" :search-btn="true" :class="$style.btns"
:remove-btn="false" @btn-click="handleListBtnClick"
:listAdd-btn="assertApiSupport(item.source)"
:play-btn="assertApiSupport(item.source)"
@@ -34,8 +36,6 @@ div(:class="$style.songList")
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
- td(style="width: 10%;")
- span(:class="[$style.time, $style.noSelect]") {{item.interval || '--/--'}}
div(:class="$style.pagination")
material-pagination(:count="total" :limit="limit" :page="page" @btn-click="handleTogglePage")
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
@@ -158,6 +158,8 @@ export default {
if (this.keyEvent.isModDown) this.keyEvent.isModDown = false
},
handle_key_mod_a_down({ event }) {
+ if (event.target.tagName == 'INPUT') return
+ event.preventDefault()
if (event.repeat) return
this.keyEvent.isModDown = false
this.handleSelectAllData()
diff --git a/src/renderer/components/material/Tab.vue b/src/renderer/components/material/Tab.vue
index f17267c2..d0f1115b 100644
--- a/src/renderer/components/material/Tab.vue
+++ b/src/renderer/components/material/Tab.vue
@@ -98,15 +98,15 @@ export default {
margin-left: 0;
button {
border-top-left-radius: 3px;
- // border-bottom-left-radius: 4px;
+ // border-bottom-left-radius: @radius-border;
}
}
&:last-child {
border-right: 2px solid @color-tab-border-top;
- border-top-right-radius: 4px;
+ border-top-right-radius: @radius-border;
button {
border-top-right-radius: 3px;
- // border-bottom-right-radius: 4px;
+ // border-bottom-right-radius: @radius-border;
}
}
button {
diff --git a/src/renderer/components/material/listAddModal.vue b/src/renderer/components/material/listAddModal.vue
index 9a61f670..cc1fef04 100644
--- a/src/renderer/components/material/listAddModal.vue
+++ b/src/renderer/components/material/listAddModal.vue
@@ -5,7 +5,13 @@ material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
| {{$t('material.list_add_modal.title_first')}}
span(:class="$style.name") {{this.musicInfo && `${musicInfo.name}`}}
| {{$t('material.list_add_modal.title_last')}}
- material-btn(:class="$style.btn" :title="$t('material.list_add_modal.btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists") {{item.name}}
+ div.scroll(:class="$style.btnContent")
+ material-btn(:class="$style.btn" :title="$t('material.list_add_modal.btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists") {{item.name}}
+ material-btn(:class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :title="$t('view.list.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')
+ input.key-bind(:class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('view.list.lists_new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)")
+ span(:class="$style.btn" v-for="i in spaceNum")
@@ -60,18 +92,21 @@ export default {
@import '../../assets/styles/layout.less';
.main {
- padding: 15px;
- max-width: 300px;
+ // padding: 15px 0;
+ max-width: 530px;
min-width: 200px;
display: flex;
flex-flow: column nowrap;
justify-content: center;
+ min-height: 0;
+ // max-height: 100%;
+ // overflow: hidden;
h2 {
font-size: 13px;
color: @color-theme_2-font;
line-height: 1.3;
text-align: center;
- margin-bottom: 15px;
+ padding: 15px;
}
}
@@ -79,12 +114,60 @@ export default {
color: @color-theme;
}
+.btn-content {
+ flex: auto;
+ max-height: 100%;
+ padding-right: 15px;
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-evenly;
+}
+
.btn {
- display: block;
+ box-sizing: border-box;
+ margin-left: 15px;
margin-bottom: 15px;
- &:last-child {
- margin-bottom: 0;
+ height: 36px;
+ line-height: 36px;
+ padding: 0 10px;
+ width: 150px;
+ .mixin-ellipsis-1;
+}
+
+.newList {
+ border: 1px dashed @color-theme-hover;
+ background-color: @color-theme_2-background_2;
+ color: @color-theme-hover;
+ opacity: .7;
+
+ svg {
+ height: 18px;
+ margin-top: 9px;
}
+
+ &.editing {
+ opacity: 1;
+
+ svg {
+ display: none;
+ }
+ .newListInput {
+ display: block;
+ }
+ }
+}
+.newListInput {
+ width: 100%;
+ height: 34px;
+ border: none;
+ padding: 0;
+ line-height: 34px;
+ background: none;
+ outline: none;
+ font-size: 14px;
+ text-align: center;
+ font-family: inherit;
+ display: none;
}
each(@themes, {
@@ -97,6 +180,11 @@ each(@themes, {
.name {
color: ~'@{color-@{value}-theme}';
}
+ .newList {
+ border-color: ~'@{color-@{value}-theme-hover}';
+ color: ~'@{color-@{value}-theme-hover}';
+ background-color: ~'@{color-@{value}-theme_2-background_2}';
+ }
}
})
diff --git a/src/renderer/components/material/listAddMultipleModal.vue b/src/renderer/components/material/listAddMultipleModal.vue
index e1408330..7ab72f7b 100644
--- a/src/renderer/components/material/listAddMultipleModal.vue
+++ b/src/renderer/components/material/listAddMultipleModal.vue
@@ -2,7 +2,13 @@
material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
main(:class="$style.main")
h2 {{$t('material.list_add_multiple_modal.title', { num: musicList.length })}}
- material-btn(:class="$style.btn" :title="$t('material.list_add_multiple_modal.btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists") {{item.name}}
+ div.scroll(:class="$style.btnContent")
+ material-btn(:class="$style.btn" :title="$t('material.list_add_multiple_modal.btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists") {{item.name}}
+ material-btn(:class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :title="$t('view.list.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')
+ input.key-bind(:class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('view.list.lists_new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)")
+ span(:class="$style.btn" v-for="i in spaceNum")
@@ -61,27 +93,78 @@ export default {
@import '../../assets/styles/layout.less';
.main {
- padding: 15px;
- max-width: 300px;
+ // padding: 15px 0;
+ max-width: 530px;
min-width: 200px;
display: flex;
flex-flow: column nowrap;
justify-content: center;
+ min-height: 0;
+ // max-height: 100%;
+ // overflow: hidden;
h2 {
font-size: 13px;
color: @color-theme_2-font;
line-height: 1.3;
text-align: center;
- margin-bottom: 15px;
+ padding: 15px;
}
}
+.btn-content {
+ flex: auto;
+ max-height: 100%;
+ padding-right: 15px;
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-evenly;
+}
+
.btn {
- display: block;
+ box-sizing: border-box;
+ margin-left: 15px;
margin-bottom: 15px;
- &:last-child {
- margin-bottom: 0;
+ height: 36px;
+ line-height: 36px;
+ padding: 0 10px;
+ width: 150px;
+ .mixin-ellipsis-1;
+}
+
+.newList {
+ border: 1px dashed @color-theme-hover;
+ background-color: @color-theme_2-background_2;
+ color: @color-theme-hover;
+ opacity: .7;
+
+ svg {
+ height: 18px;
+ margin-top: 9px;
}
+
+ &.editing {
+ opacity: 1;
+
+ svg {
+ display: none;
+ }
+ .newListInput {
+ display: block;
+ }
+ }
+}
+.newListInput {
+ width: 100%;
+ height: 34px;
+ border: none;
+ padding: 0;
+ line-height: 34px;
+ background: none;
+ outline: none;
+ font-size: 14px;
+ text-align: center;
+ font-family: inherit;
+ display: none;
}
each(@themes, {
@@ -91,6 +174,11 @@ each(@themes, {
color: ~'@{color-@{value}-theme_2-font}';
}
}
+ .newList {
+ border-color: ~'@{color-@{value}-theme-hover}';
+ color: ~'@{color-@{value}-theme-hover}';
+ background-color: ~'@{color-@{value}-theme_2-background_2}';
+ }
}
})
diff --git a/src/renderer/config/index.js b/src/renderer/config/index.js
index 543e37db..a614fe06 100644
--- a/src/renderer/config/index.js
+++ b/src/renderer/config/index.js
@@ -2,7 +2,7 @@ import path from 'path'
import os from 'os'
const defaultSetting = {
- version: '1.0.24',
+ version: '1.0.26',
player: {
togglePlayMethod: 'listLoop',
highQuality: false,
@@ -14,10 +14,8 @@ const defaultSetting = {
list: {
isShowAlbumName: true,
isShowSource: true,
- scroll: {
- enable: true,
- locations: {},
- },
+ prevSelectListId: 'default',
+ isSaveScrollLocation: true,
},
download: {
savePath: path.join(os.homedir(), 'Desktop'),
diff --git a/src/renderer/lang/cns/core/aside.json b/src/renderer/lang/cns/core/aside.json
index 73b67a75..32b709b7 100644
--- a/src/renderer/lang/cns/core/aside.json
+++ b/src/renderer/lang/cns/core/aside.json
@@ -1,12 +1,8 @@
{
- "online_music": "在线音乐",
"search": "搜索",
"song_list": "歌单",
"leaderboard": "排行榜",
- "my_music": "我的音乐",
- "default_list": "试听列表",
- "love_list": "收藏列表",
- "other": "其他",
- "download": "下载管理",
+ "my_list": "我的列表",
+ "download": "下载",
"setting": "设置"
}
diff --git a/src/renderer/lang/cns/material/list_add_multiple_modal.json b/src/renderer/lang/cns/material/list_add_multiple_modal.json
index a85a7544..97130881 100644
--- a/src/renderer/lang/cns/material/list_add_multiple_modal.json
+++ b/src/renderer/lang/cns/material/list_add_multiple_modal.json
@@ -1,4 +1,4 @@
{
"title": "添加已选的 {num} 首歌曲到...",
- "btn_title": "把该歌曲添加到 {name}"
+ "btn_title": "把这些歌曲添加到 {name}"
}
diff --git a/src/renderer/lang/cns/view/list.json b/src/renderer/lang/cns/view/list.json
index 0738c013..72671d86 100644
--- a/src/renderer/lang/cns/view/list.json
+++ b/src/renderer/lang/cns/view/list.json
@@ -1,6 +1,12 @@
{
- "select_all": "全选",
- "unselect_all": "全不选",
+ "lists_new_list_btn": "新建列表",
+ "lists_new_list_input": "新列表...",
+ "lists_rename": "重命名",
+ "lists_moveup": "上移",
+ "lists_movedown": "下移",
+ "lists_remove": "删除",
+ "default_list": "试听列表",
+ "love_list": "收藏",
"name": "歌曲名",
"singer": "歌手",
"album": "专辑",
diff --git a/src/renderer/lang/cnt/core/aside.json b/src/renderer/lang/cnt/core/aside.json
index 8d3981e8..23f3fce6 100644
--- a/src/renderer/lang/cnt/core/aside.json
+++ b/src/renderer/lang/cnt/core/aside.json
@@ -1,12 +1,8 @@
{
- "online_music": "在線音樂",
"search": "搜索",
"song_list": "歌單",
"leaderboard": "排行榜",
- "my_music": "我的音樂",
- "default_list": "試聽列表",
- "love_list": "收藏列表",
- "other": "其他",
+ "my_list": "我的列表",
"download": "下載管理",
"setting": "設置"
}
diff --git a/src/renderer/lang/cnt/material/list_add_multiple_modal.json b/src/renderer/lang/cnt/material/list_add_multiple_modal.json
index 2e3bf68e..a69200f2 100644
--- a/src/renderer/lang/cnt/material/list_add_multiple_modal.json
+++ b/src/renderer/lang/cnt/material/list_add_multiple_modal.json
@@ -1,4 +1,4 @@
{
"title": "添加已選的 {num} 首歌曲到...",
- "btn_title": "把該歌曲添加到 {name}"
+ "btn_title": "把這些歌曲添加到 {name}"
}
diff --git a/src/renderer/lang/cnt/view/list.json b/src/renderer/lang/cnt/view/list.json
index 8e76c91c..7fca1675 100644
--- a/src/renderer/lang/cnt/view/list.json
+++ b/src/renderer/lang/cnt/view/list.json
@@ -1,6 +1,12 @@
{
- "select_all": "全選",
- "unselect_all": "全不選",
+ "lists_new_list_btn": "新建列表",
+ "lists_new_list_input": "新列表...",
+ "lists_rename": "重命名",
+ "lists_moveup": "上移",
+ "lists_movedown": "下移",
+ "lists_remove": "刪除",
+ "default_list": "試聽列表",
+ "love_list": "收藏列表",
"name": "歌曲名",
"singer": "歌手",
"album": "專輯",
diff --git a/src/renderer/lang/en/core/aside.json b/src/renderer/lang/en/core/aside.json
index 311828d6..30d86e45 100644
--- a/src/renderer/lang/en/core/aside.json
+++ b/src/renderer/lang/en/core/aside.json
@@ -1,12 +1,8 @@
{
- "online_music": "Online music",
"search": "Search",
"song_list": "Playlists",
"leaderboard": "Charts",
- "my_music": "Your Library",
- "default_list": "Recently Played",
- "love_list": "Favorites",
- "other": "Extras",
+ "my_list": "Your Library",
"download": "Downloads",
"setting": "Settings"
}
diff --git a/src/renderer/lang/en/material/list_add_multiple_modal.json b/src/renderer/lang/en/material/list_add_multiple_modal.json
index b440e03d..a83dad04 100644
--- a/src/renderer/lang/en/material/list_add_multiple_modal.json
+++ b/src/renderer/lang/en/material/list_add_multiple_modal.json
@@ -1,4 +1,4 @@
{
"title": "Add the selected {num} song(s) to ...",
- "btn_title": "Add the song(s) to {name}"
+ "btn_title": "Add these song(s) to {name}"
}
diff --git a/src/renderer/lang/en/view/list.json b/src/renderer/lang/en/view/list.json
index baa08b6b..c6e2fab3 100644
--- a/src/renderer/lang/en/view/list.json
+++ b/src/renderer/lang/en/view/list.json
@@ -1,6 +1,12 @@
{
- "select_all": "Select all",
- "unselect_all": "Unselect all",
+ "lists_new_list_btn": "Create list",
+ "lists_new_list_input": "New list...",
+ "lists_rename": "Rename",
+ "lists_moveup": "Move Up",
+ "lists_movedown": "Move Down",
+ "lists_remove": "Remove",
+ "default_list": "Recently Played",
+ "love_list": "Favorites",
"name": "Name",
"singer": "Artist",
"album": "Album",
diff --git a/src/renderer/store/modules/list.js b/src/renderer/store/modules/list.js
index e22c0d63..4cda1b3e 100644
--- a/src/renderer/store/modules/list.js
+++ b/src/renderer/store/modules/list.js
@@ -1,23 +1,43 @@
+let allList = {}
+window.allList = allList
+
+const allListInit = (defaultList, loveList, userList) => {
+ allList[defaultList.id] = defaultList
+ allList[loveList.id] = loveList
+ for (const list of userList) allList[list.id] = list
+}
+const allListUpdate = list => {
+ allList[list.id] = list
+}
+const allListRemove = list => {
+ delete allList[list.id]
+}
+
// state
const state = {
+ isInitedList: false,
defaultList: {
id: 'default',
name: '试听列表',
list: [],
+ location: 0,
},
loveList: {
id: 'love',
name: '我的收藏',
list: [],
+ location: 0,
},
userList: [],
}
// getters
const getters = {
+ isInitedList: state => state.isInitedList,
defaultList: state => state.defaultList || {},
loveList: state => state.loveList || {},
userList: state => state.userList,
+ allList: () => allList,
}
// actions
@@ -25,73 +45,118 @@ const actions = {
}
-const getList = (state, id) => {
- let targetList
- switch (id) {
- case 'default':
- targetList = state.defaultList
- break
- case 'love':
- targetList = state.loveList
- break
- default:
- targetList = state.userList.find(l => l.id === id)
- break
- }
- return targetList
-}
-
// mitations
const mutations = {
- initList(state, { defaultList, loveList }) {
- if (defaultList !== undefined) state.defaultList.list = defaultList.list
- if (loveList !== undefined) state.loveList.list = loveList.list
+ initList(state, { defaultList, loveList, userList }) {
+ if (defaultList != null) state.defaultList.list = defaultList.list
+ if (loveList != null) state.loveList.list = loveList.list
+ if (userList != null) state.userList = userList
+ allListInit(state.defaultList, state.loveList, state.userList)
+ state.isInitedList = true
},
- setList(state, { id, list }) {
- const targetList = getList(state, id)
- if (!targetList) return
- targetList.list = list
+ setList(state, { id, list, name, location }) {
+ const targetList = allList[id]
+ if (targetList) {
+ if (name && targetList.name === name) {
+ targetList.list.splice(0, targetList.list.length, ...list)
+ targetList.location = location
+ return
+ }
+
+ id += '_' + Math.random()
+ }
+ let newList = {
+ name,
+ id,
+ list,
+ location,
+ }
+ state.userList.push(newList)
+ allListUpdate(newList)
},
listAdd(state, { id, musicInfo }) {
- const targetList = getList(state, id)
+ const targetList = allList[id]
if (!targetList) return
if (targetList.list.some(s => s.songmid === musicInfo.songmid)) return
targetList.list.push(musicInfo)
},
listAddMultiple(state, { id, list }) {
- let targetList = getList(state, id)
+ let targetList = allList[id]
if (!targetList) return
- targetList = targetList.list
- list.forEach(musicInfo => {
- if (targetList.some(s => s.songmid === musicInfo.songmid)) return
- targetList.push(musicInfo)
- })
+ let newList = [...targetList.list, ...list]
+ let map = {}
+ let ids = []
+ for (const item of newList) {
+ if (map[item.songmid]) continue
+ ids.push(item.songmid)
+ map[item.songmid] = item
+ }
+ targetList.list.splice(0, targetList.list.length, ...ids.map(id => map[id]))
},
listRemove(state, { id, index }) {
- let targetList = getList(state, id)
+ let targetList = allList[id]
if (!targetList) return
targetList.list.splice(index, 1)
},
listRemoveMultiple(state, { id, list }) {
- let targetList = getList(state, id)
+ let targetList = allList[id]
if (!targetList) return
- targetList = targetList.list
- list.forEach(musicInfo => {
- let index = targetList.indexOf(musicInfo)
- if (index < 0) return
- targetList.splice(index, 1)
- })
+ let map = {}
+ let ids = []
+ for (const item of targetList.list) {
+ ids.push(item.songmid)
+ map[item.songmid] = item
+ }
+ for (const item of list) {
+ if (map[item.songmid]) delete map[item.songmid]
+ }
+ let newList = []
+ for (const id of ids) if (map[id]) newList.push(map[id])
+
+ targetList.list.splice(0, targetList.list.length, ...newList)
},
listClear(state, id) {
- let targetList = getList(state, id)
+ let targetList = allList[id]
if (!targetList) return
- targetList.list.length = []
+ targetList.list.splice(0, targetList.list.length)
},
updateMusicInfo(state, { id, index, data }) {
- let targetList = getList(state, id)
+ let targetList = allList[id]
if (!targetList) return
Object.assign(targetList.list[index], data)
},
+ createUserList(state, name) {
+ let newList = {
+ name,
+ id: `userlist_${Date.now()}`,
+ list: [],
+ location: 0,
+ }
+ state.userList.push(newList)
+ allListUpdate(newList)
+ },
+ removeUserList(state, index) {
+ let list = state.userList.splice(index, 1)[0]
+ allListRemove(list)
+ },
+ setUserListName(state, { index, name }) {
+ let list = state.userList[index]
+ if (!list) return
+ list.name = name
+ },
+ moveupUserList(state, index) {
+ let targetList = state.userList[index]
+ state.userList.splice(index, 1)
+ state.userList.splice(index - 1, 0, targetList)
+ },
+ movedownUserList(state, index) {
+ let targetList = state.userList[index]
+ state.userList.splice(index, 1)
+ state.userList.splice(index + 1, 0, targetList)
+ },
+ setListScroll(state, { id, location }) {
+ if (allList[id]) allList[id].location = location
+ },
}
export default {
diff --git a/src/renderer/store/modules/player.js b/src/renderer/store/modules/player.js
index 37d8616e..e61ee64f 100644
--- a/src/renderer/store/modules/player.js
+++ b/src/renderer/store/modules/player.js
@@ -2,8 +2,10 @@ import music from '../../utils/music'
// state
const state = {
- list: [],
- listId: null,
+ listInfo: {
+ list: [],
+ id: null,
+ },
playIndex: -1,
changePlay: false,
isShowPlayerDetail: false,
@@ -15,8 +17,8 @@ let lrcRequest
// getters
const getters = {
- list: state => state.list || [],
- listId: state => state.listId,
+ list: state => state.listInfo.list,
+ listId: state => state.listInfo.id,
changePlay: satte => satte.changePlay,
playIndex: state => state.playIndex,
isShowPlayerDetail: state => state.isShowPlayerDetail,
@@ -78,9 +80,8 @@ const mutations = {
setLrc(state, datas) {
datas.musicInfo.lrc = datas.lrc
},
- setList(state, { list, listId, index }) {
- state.list = list
- state.listId = listId
+ setList(state, { list, index }) {
+ state.listInfo = list
state.playIndex = index
state.changePlay = true
},
diff --git a/src/renderer/store/mutations.js b/src/renderer/store/mutations.js
index 8aade6cc..43e2064a 100644
--- a/src/renderer/store/mutations.js
+++ b/src/renderer/store/mutations.js
@@ -24,9 +24,6 @@ export default {
if (sortId != null) state.setting.songList.sortId = sortId
if (source != null) state.setting.songList.source = source
},
- setListScroll(state, { id, location }) {
- state.setting.list.scroll.locations[id] = location
- },
setNewVersion(state, val) {
state.version.newVersion = val
},
@@ -51,4 +48,7 @@ export default {
setMediaDeviceId(state, val) {
state.setting.player.mediaDeviceId = val
},
+ setPrevSelectListId(state, val) {
+ state.setting.list.prevSelectListId = val
+ },
}
diff --git a/src/renderer/store/state.js b/src/renderer/store/state.js
index 8c1cffae..f7ef094e 100644
--- a/src/renderer/store/state.js
+++ b/src/renderer/store/state.js
@@ -10,7 +10,8 @@ const electronStore_list = window.electronStore_list = new Store({
const electronStore_config = window.electronStore_config = new Store({
name: 'config',
})
-if (!electronStore_config.get('version') && electronStore_config.get('setting')) { // 迁移配置
+let setting = electronStore_config.get('setting')
+if (!electronStore_config.get('version') && setting) { // 迁移配置
electronStore_config.set('version', electronStore_config.get('setting.version'))
electronStore_config.delete('setting.version')
const list = electronStore_config.get('list')
@@ -25,7 +26,20 @@ if (!electronStore_config.get('version') && electronStore_config.get('setting'))
electronStore_config.delete('download')
}
}
-const { version: settingVersion, setting } = updateSetting(electronStore_config.get('setting'), electronStore_config.get('version'))
+
+// 迁移列表滚动位置设置 ^0.18.3
+if (setting && setting.list.scroll) {
+ let scroll = setting.list.scroll
+ const electronStore_list = window.electronStore_list = new Store({
+ name: 'playList',
+ })
+ electronStore_list.set('defaultList.location', scroll.locations.defaultList || 0)
+ electronStore_list.set('loveList.location', scroll.locations.loveList || 0)
+ electronStore_config.delete('setting.list.scroll')
+ electronStore_config.set('setting.list.isSaveScrollLocation', scroll.enable)
+}
+
+const { version: settingVersion, setting: newSetting } = updateSetting(setting, electronStore_config.get('version'))
electronStore_config.set('version', settingVersion)
electronStore_config.set('setting', setting)
process.versions.app = version
@@ -108,7 +122,7 @@ export default {
downloadProgress: null,
},
userInfo: null,
- setting,
+ setting: newSetting,
settingVersion,
windowSizeList,
diff --git a/src/renderer/utils/index.js b/src/renderer/utils/index.js
index 4ce5d718..4ce549bf 100644
--- a/src/renderer/utils/index.js
+++ b/src/renderer/utils/index.js
@@ -55,15 +55,8 @@ const easeInOutQuad = (t, b, c, d) => {
t--
return (-c / 2) * (t * (t - 2) - 1) + b
}
-/**
- * 设置滚动条位置
- * @param {*} element 要设置滚动的容器 dom
- * @param {*} to 滚动的目标位置
- * @param {*} duration 滚动完成时间 ms
- * @param {*} fn 滚动完成后的回调
- */
-export const scrollTo = (element, to, duration = 300, fn = () => {}) => {
- if (!element) return
+const handleScroll = (element, to, duration = 300, fn = () => {}) => {
+ if (!element) return fn()
const start = element.scrollTop || element.scrollY || 0
let cancel = false
if (to > start) {
@@ -99,6 +92,31 @@ export const scrollTo = (element, to, duration = 300, fn = () => {}) => {
cancel = true
}
}
+/**
+ * 设置滚动条位置
+ * @param {*} element 要设置滚动的容器 dom
+ * @param {*} to 滚动的目标位置
+ * @param {*} duration 滚动完成时间 ms
+ * @param {*} fn 滚动完成后的回调
+ * @param {*} delay 延迟执行时间
+ */
+export const scrollTo = (element, to, duration = 300, fn = () => {}, delay) => {
+ let cancelFn
+ let timeout
+ if (delay) {
+ let scrollCancelFn
+ cancelFn = () => {
+ timeout == null ? scrollCancelFn && scrollCancelFn() : clearTimeout(timeout)
+ }
+ timeout = setTimeout(() => {
+ timeout = null
+ scrollCancelFn = handleScroll(element, to, duration, fn, delay)
+ }, delay)
+ } else {
+ cancelFn = handleScroll(element, to, duration, fn, delay)
+ }
+ return cancelFn
+}
/**
* 检查路径是否存在
diff --git a/src/renderer/utils/keyBind.js b/src/renderer/utils/keyBind.js
index 6b6156e8..9b33b112 100644
--- a/src/renderer/utils/keyBind.js
+++ b/src/renderer/utils/keyBind.js
@@ -52,7 +52,7 @@ const assertStopCallback = element => {
const handleKeyDown = event => {
if (assertStopCallback(event.target)) return
- event.preventDefault()
+ // event.preventDefault()
let keys = eventModifiers(event)
switch (event.key) {
case 'Control':
@@ -61,7 +61,7 @@ const handleKeyDown = event => {
case 'Shift':
break
default:
- keys.push(event.key)
+ keys.push(event.key.toLowerCase())
break
}
handleEvent('down', event, keys)
diff --git a/src/renderer/utils/request.js b/src/renderer/utils/request.js
index b0bb47db..1a402690 100644
--- a/src/renderer/utils/request.js
+++ b/src/renderer/utils/request.js
@@ -109,7 +109,8 @@ export const httpFetch = (url, options = { method: 'get' }) => {
export const cancelHttp = requestObj => {
// console.log(requestObj)
if (!requestObj) return
- console.log('cancel:', requestObj.href)
+ console.log('cancel:', requestObj)
+ if (!requestObj.abort) return
requestObj.abort()
}
diff --git a/src/renderer/views/Download.vue b/src/renderer/views/Download.vue
index a6723d36..c741c5dc 100644
--- a/src/renderer/views/Download.vue
+++ b/src/renderer/views/Download.vue
@@ -154,6 +154,8 @@ export default {
if (this.keyEvent.isModDown) this.keyEvent.isModDown = false
},
handle_key_mod_a_down({ event }) {
+ if (event.target.tagName == 'INPUT') return
+ event.preventDefault()
if (event.repeat) return
this.keyEvent.isModDown = false
this.handleSelectAllData()
@@ -236,7 +238,7 @@ export default {
async handlePlay(index) {
const targetSong = this.list[index]
if (!await checkPath(path.join(this.setting.download.savePath, targetSong.fileName))) return
- this.setList({ list: this.list, listId: 'download', index: this.list.findIndex(i => i.key === targetSong.key) })
+ this.setList({ list: { list: this.list, id: 'download' }, index: this.list.findIndex(i => i.key === targetSong.key) })
},
handleListBtnClick(info) {
let item = this.showList[info.index]
@@ -364,7 +366,7 @@ export default {
}
tr {
&.active {
- color: @color-theme;
+ color: @color-btn;
}
}
}
@@ -374,7 +376,7 @@ each(@themes, {
.tbody {
tr {
&.active {
- color: ~'@{color-@{value}-theme}';
+ color: ~'@{color-@{value}-btn}';
}
}
td {
diff --git a/src/renderer/views/Leaderboard.vue b/src/renderer/views/Leaderboard.vue
index 3185f3dd..fe0a75af 100644
--- a/src/renderer/views/Leaderboard.vue
+++ b/src/renderer/views/Leaderboard.vue
@@ -96,8 +96,7 @@ export default {
)
if (targetIndex > -1) {
this.setList({
- list: this.defaultList.list,
- listId: this.defaultList.id,
+ list: this.defaultList,
index: targetIndex,
})
}
diff --git a/src/renderer/views/List.vue b/src/renderer/views/List.vue
index c7d2aede..96e44118 100644
--- a/src/renderer/views/List.vue
+++ b/src/renderer/views/List.vue
@@ -1,7 +1,24 @@
- div(:class="$style.list")
- //- transition
- div(v-if="delayShow && list.length" :class="$style.content")
+ div(:class="$style.container" @click="handleContainerClick($event)")
+ div(:class="$style.lists" ref="dom_lists")
+ div(:class="$style.listHeader")
+ h2(:class="$style.listsTitle") {{$t('core.aside.my_list')}}
+ button(:class="$style.listsAdd" @click="handleShowNewList" :title="$t('view.list.lists_new_list_btn')")
+ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='70%' viewBox='0 0 24 24' space='preserve')
+ use(xlink:href='#icon-list-add')
+ ul.scroll(:class="$style.listsContent" ref="dom_lists_list")
+ li(:class="[$style.listsItem, defaultList.id == listId ? $style.active : null]" :title="defaultList.name" @click="handleListToggle(defaultList.id)")
+ span(:class="$style.listsLabel") {{defaultList.name}}
+ li(:class="[$style.listsItem, loveList.id == listId ? $style.active : null]" :title="loveList.name" @click="handleListToggle(loveList.id)")
+ span(:class="$style.listsLabel") {{loveList.name}}
+ li.user-list(:class="[$style.listsItem, item.id == listId ? $style.active : null, listsData.rightClickItemIndex == index ? $style.clicked : null]" @contextmenu="handleListsItemRigthClick($event, index)" :title="item.name" v-for="(item, index) in userList" :key="item.id")
+ span(:class="$style.listsLabel" @click="handleListToggle(item.id, index + 2)") {{item.name}}
+ input.key-bind(:class="$style.listsInput" type="text" @keyup.enter="handleListsSave(index, $event)" @blur="handleListsSave(index, $event)" :value="item.name" :placeholder="item.name")
+ transition(enter-active-class="animated-fast slideInLeft" leave-active-class="animated-fast fadeOut" @after-leave="handleListsNewAfterLeave")
+ li(:class="[$style.listsItem, $style.listsNew, listsData.isNewLeave ? $style.newLeave : null]" v-if="listsData.isShowNewList")
+ input.key-bind(:class="$style.listsInput" ref="dom_listsNewInput" type="text" @keyup.enter="handleListsCreate($event)" @blur="handleListsCreate($event)" :placeholder="$t('view.list.lists_new_list_input')")
+ div(:class="$style.list")
+ //- transition
div(:class="$style.thead")
table
thead
@@ -10,41 +27,43 @@
th.nobreak(style="width: 25%;") {{$t('view.list.name')}}
th.nobreak(style="width: 20%;") {{$t('view.list.singer')}}
th.nobreak(style="width: 20%;") {{$t('view.list.album')}}
- th.nobreak(style="width: 20%;") {{$t('view.list.action')}}
- th.nobreak(style="width: 10%;") {{$t('view.list.time')}}
- div.scroll(:class="$style.tbody" @scroll="handleScroll" ref="dom_scrollContent")
- table
- tbody(@contextmenu="handleContextMenu" ref="dom_tbody")
- tr(v-for='(item, index) in list' :key='item.songmid' :id="'mid_' + item.songmid"
- @click="handleDoubleClick($event, index)" :class="[isPlayList && playIndex === index ? $style.active : '', assertApiSupport(item.source) ? null : $style.disabled]")
- td.nobreak.center(style="width: 37px;" :class="$style.noSelect" @click.stop) {{index + 1}}
- td.break(style="width: 25%;")
- span.select {{item.name}}
- span(:class="[$style.labelSource, $style.noSelect]" v-if="isShowSource") {{item.source}}
- //- span.badge.badge-light(v-if="item._types['128k']") 128K
- //- span.badge.badge-light(v-if="item._types['192k']") 192K
- //- span.badge.badge-secondary(v-if="item._types['320k']") 320K
- //- span.badge.badge-theme-info(v-if="item._types.ape") APE
- //- span.badge.badge-theme-success(v-if="item._types.flac") FLAC
- td.break(style="width: 20%;")
- span.select {{item.singer}}
- td.break(style="width: 20%;")
- span.select {{item.albumName}}
- td(style="width: 20%; padding-left: 0; padding-right: 0;")
- material-list-buttons(:index="index" @btn-click="handleListBtnClick")
- //- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
- //- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
- //- button.btn-secondary(type='button' @click.stop='handleRemove(index)') 删除
- //- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
- td(style="width: 10%;")
- span(:class="[$style.time, $style.noSelect]") {{item.interval || '--/--'}}
- div(:class="$style.noItem" v-else)
- p(v-text="list.length ? $t('view.list.loding_list') : $t('view.list.no_item')")
+ th.nobreak(style="width: 9%;") {{$t('view.list.time')}}
+ th.nobreak(style="width: 21%;") {{$t('view.list.action')}}
+ div(v-if="delayShow && list.length" :class="$style.content")
+ div.scroll(:class="$style.tbody" @scroll="handleScroll" ref="dom_scrollContent")
+ table
+ tbody(@contextmenu="handleContextMenu" ref="dom_tbody")
+ tr(v-for='(item, index) in list' :key='item.songmid' :id="'mid_' + item.songmid"
+ @click="handleDoubleClick($event, index)" :class="[isPlayList && playIndex === index ? $style.active : '', assertApiSupport(item.source) ? null : $style.disabled]")
+ td.nobreak.center(style="width: 37px;" :class="$style.noSelect" @click.stop) {{index + 1}}
+ td.break(style="width: 25%;")
+ span.select {{item.name}}
+ span(:class="[$style.labelSource, $style.noSelect]" v-if="isShowSource") {{item.source}}
+ //- span.badge.badge-light(v-if="item._types['128k']") 128K
+ //- span.badge.badge-light(v-if="item._types['192k']") 192K
+ //- span.badge.badge-secondary(v-if="item._types['320k']") 320K
+ //- span.badge.badge-theme-info(v-if="item._types.ape") APE
+ //- span.badge.badge-theme-success(v-if="item._types.flac") FLAC
+ td.break(style="width: 20%;")
+ span.select {{item.singer}}
+ td.break(style="width: 20%;")
+ span.select {{item.albumName}}
+ td(style="width: 9%;")
+ span(:class="[$style.time, $style.noSelect]") {{item.interval || '--/--'}}
+ td(style="width: 21%; padding-left: 0; padding-right: 0;")
+ material-list-buttons(:index="index" @btn-click="handleListBtnClick")
+ //- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
+ //- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
+ //- button.btn-secondary(type='button' @click.stop='handleRemove(index)') 删除
+ //- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
+ div(:class="$style.noItem" v-else)
+ p(v-text="list.length ? $t('view.list.loding_list') : $t('view.list.no_item')")
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
- material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
+ material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdListDetailData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
material-flow-btn(:show="isShowEditBtn" :play-btn="false" @btn-click="handleFlowBtnClick")
material-list-add-modal(:show="isShowListAdd" :musicInfo="musicInfo" :exclude-list-id="excludeListId" @close="isShowListAdd = false")
- material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectdData" :exclude-list-id="excludeListId" @close="handleListAddModalClose")
+ material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectdListDetailData" :exclude-list-id="excludeListId" @close="handleListAddModalClose")
+ material-menu(:menus="listsItemMenu" :location="listsData.menuLocation" item-name="name" :isShow="listsData.isShowItemMenu" @menu-click="handleListsItemMenuClick")
@@ -420,15 +626,135 @@ export default {