Merge branch 'dev'

pull/392/head v1.5.0
lyswhut 2020-12-13 11:48:17 +08:00
commit 0709aa56a4
29 changed files with 771 additions and 459 deletions

View File

@ -13,10 +13,13 @@ assignees: ''
- [ ] 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>)
**描述您想要的解决方案**
简洁明了地描述您要发生的事情。
<!-- 简洁明了地描述您要发生的事情。 -->
**描述您考虑过的替代方案**
对您考虑过的所有替代解决方案或功能的简洁明了的描述。
<!-- 对您考虑过的所有替代解决方案或功能的简洁明了的描述。 -->
**其他内容**
在此处添加有关功能请求的任何其他上下文或屏幕截图(直接把图片拖到编辑框即可添加图片)。
<!-- 在此处添加有关功能请求的任何其他上下文或屏幕截图(直接把图片拖到编辑框即可添加图片)。 -->

View File

@ -13,7 +13,8 @@ assignees: ''
- [ ] 我已搜索issue列表(<https://github.com/lyswhut/lx-music-desktop/issues?utf8=✓&q=>)
**描述错误**
清楚简洁地说明错误是什么。
<!-- 清楚简洁地说明错误是什么。 -->
**重现**
重现行为的步骤:
@ -22,15 +23,20 @@ assignees: ''
3.向下滚动到“ ....”
4.看到错误
**预期行为**
对您期望发生的事情的简洁明了的描述。
<!-- 对您期望发生的事情的简洁明了的描述。 -->
**截图**
如果适用,请添加屏幕截图以帮助解释您的问题(直接把图片拖到编辑框即可添加图片)。
<!-- 如果适用,请添加屏幕截图以帮助解释您的问题(直接把图片拖到编辑框即可添加图片)。 -->
**环境:**
  -操作系统及版本:[例如Windows 10 64位 18362.156]
  -软件安装包及版本:[例如Windows 64位绿色版 1.0.0]
**其他内容**
在此处添加有关该问题的任何其他上下文。
<!-- 在此处添加有关该问题的任何其他上下文。 -->

View File

@ -6,6 +6,23 @@ 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.5.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.4.1...v1.5.0) - 2020-12-13
### 新增
- 直接从歌单详情收藏的列表新增同步功能。注意:这将会覆盖本地的目标列表,歌曲将被替换成最新的在线列表
### 优化
- 优化软件启动时恢复上一次播放的歌曲进度功能
### 修复
- 修复MAC平台上下载歌曲封面嵌入无法显示的问题
- 修复MAC平台首次运行软件最小化、关闭控制按钮默认在右边的问题
- 修复酷狗源的某些歌曲没有专辑字段导致的列表加载失败问题
- 修复某些酷狗源歌单链接无法打开的问题
## [1.4.1](https://github.com/lyswhut/lx-music-desktop/compare/v1.4.0...v1.4.1) - 2020-11-25

View File

@ -9,9 +9,10 @@ module.exports = {
},
resolve: {
alias: {
'@': path.join(__dirname, '../../src/main'),
events: path.join(__dirname, '../../src/main/events'),
common: path.join(__dirname, '../../src/common'),
'@main': path.join(__dirname, '../../src/main'),
'@renderer': path.join(__dirname, '../../src/renderer'),
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
'@common': path.join(__dirname, '../../src/common'),
},
extensions: ['*', '.js', '.json', '.node'],
},

View File

@ -21,8 +21,11 @@ module.exports = {
},
resolve: {
alias: {
'@': path.join(__dirname, '../../src/renderer'),
common: path.join(__dirname, '../../src/common'),
'@main': path.join(__dirname, '../../src/main'),
'@renderer': path.join(__dirname, '../../src/renderer'),
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
'@static': path.join(__dirname, '../../src/static'),
'@common': path.join(__dirname, '../../src/common'),
},
extensions: ['*', '.js', '.json', '.vue', '.node'],
},

View File

@ -21,8 +21,11 @@ module.exports = {
},
resolve: {
alias: {
'@': path.join(__dirname, '../../src/renderer'),
common: path.join(__dirname, '../../src/common'),
'@main': path.join(__dirname, '../../src/main'),
'@renderer': path.join(__dirname, '../../src/renderer'),
'@lyric': path.join(__dirname, '../../src/renderer-lyric'),
'@static': path.join(__dirname, '../../src/static'),
'@common': path.join(__dirname, '../../src/common'),
},
extensions: ['*', '.js', '.json', '.vue', '.node'],
},

19
jsconfig.json Normal file
View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
// This is the line you want to add
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {
"@main": ["src/main"],
"@renderer": ["src/renderer"],
"@lyric": ["src/renderer-lyric"],
"@static": ["src/static"],
"@common": ["src/common"],
}
},
"include": ["src/**/*"],
"exclude": ["node_modules/**/*"]
}

906
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
"version": "1.4.1",
"version": "1.5.0",
"description": "一个免费的音乐下载助手",
"main": "./dist/electron/main.js",
"productName": "lx-music-desktop",
@ -34,16 +34,18 @@
"publish:gh:linux": "node build-config/pack.js && npm run publish:linux",
"publish:linux": "npm run publish:linux:deb && npm run publish:linux:appImage && npm run publish:linux:rpm && npm run publish:linux:pacman",
"publish:linux:appImage": "cross-env ARCH=x64 electron-builder -l=AppImage -p onTagOrDraft",
"publish:linux:deb": "npm run publish:linux:deb:x64 && npm run publish:linux:deb:x86",
"publish:linux:deb": "npm run publish:linux:deb:x64 && npm run publish:linux:deb:x86 && npm run publish:linux:deb:arm64",
"publish:linux:deb:x64": "cross-env ARCH=x64 electron-builder -l=deb --x64 -p onTagOrDraft",
"publish:linux:deb:x86": "cross-env ARCH=x86 electron-builder -l=deb --ia32 -p onTagOrDraft",
"publish:linux:deb:arm64": "cross-env ARCH=arm64 electron-builder -l=deb --arm64 -p onTagOrDraft",
"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",
"pack:linux": "node build-config/pack.js && npm run pack:linux:deb && npm run pack:linux:appImage && npm run pack:linux:rpm && npm run pack:linux:pacman",
"pack:linux:appImage": "cross-env ARCH=x64 electron-builder -l=AppImage",
"pack:linux:deb": "npm run pack:linux:deb:x64 && npm run pack:linux:deb:x86",
"pack:linux:deb": "npm run pack:linux:deb:x64 && npm run pack:linux:deb:x86 && npm run pack:linux:deb:arm64",
"pack:linux:deb:x64": "cross-env ARCH=x64 electron-builder -l=deb --x64",
"pack:linux:deb:x86": "cross-env ARCH=x86 electron-builder -l=deb --ia32",
"pack:linux:deb:arm64": "cross-env ARCH=arm64 electron-builder -l=deb --arm64",
"pack:linux:rpm": "cross-env ARCH=x64 electron-builder -l=rpm --x64",
"pack:linux:pacman": "cross-env ARCH=x64 electron-builder -l=pacman --x64",
"pack:mac": "node build-config/pack.js && electron-builder -m=dmg",
@ -158,29 +160,29 @@
},
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/core": "^7.12.10",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-modules-umd": "^7.12.1",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@babel/preset-env": "^7.12.10",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.1",
"babel-loader": "^8.2.2",
"babel-minify-webpack-plugin": "^0.3.1",
"babel-preset-minify": "^0.5.1",
"cfonts": "^2.8.6",
"cfonts": "^2.9.0",
"chalk": "^4.1.0",
"changelog-parser": "^2.8.0",
"copy-webpack-plugin": "^6.3.1",
"core-js": "^3.7.0",
"cross-env": "^7.0.2",
"copy-webpack-plugin": "^6.4.0",
"core-js": "^3.8.1",
"cross-env": "^7.0.3",
"css-loader": "^4.3.0",
"del": "^6.0.0",
"electron": "^9.3.3",
"electron-builder": "^22.9.1",
"electron-debug": "^3.1.0",
"electron-devtools-installer": "^3.1.1",
"eslint": "^7.13.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^14.1.1",
"eslint-formatter-friendly": "^7.0.0",
"eslint-loader": "^4.0.2",
@ -194,19 +196,19 @@
"html-webpack-plugin": "^4.5.0",
"less": "^3.12.2",
"less-loader": "^7.1.0",
"markdown-it": "^12.0.2",
"markdown-it": "^12.0.3",
"mini-css-extract-plugin": "^0.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-loader": "^4.0.4",
"postcss-loader": "^4.1.0",
"postcss-pxtorem": "^5.1.1",
"pug": "^3.0.0",
"pug-loader": "^2.4.0",
"pug-plain-loader": "^1.0.0",
"pug-plain-loader": "^1.1.0",
"raw-loader": "^4.0.2",
"rimraf": "^3.0.2",
"spinnies": "^0.5.1",
"stylus": "^0.54.8",
"stylus-loader": "^4.3.0",
"stylus-loader": "^4.3.1",
"terser-webpack-plugin": "^4.2.3",
"url-loader": "^4.1.1",
"vue-loader": "^15.9.5",
@ -215,7 +217,7 @@
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-hot-middleware": "^2.25.0",
"webpack-merge": "^5.4.0"
"webpack-merge": "^5.6.1"
},
"dependencies": {
"crypto-js": "^4.0.0",
@ -228,12 +230,12 @@
"js-htmlencode": "^0.3.0",
"lrc-file-parser": "^1.0.5",
"needle": "^2.5.2",
"node-id3": "^0.1.21",
"node-id3": "^0.1.19",
"request": "^2.88.2",
"vue": "^2.6.12",
"vue-i18n": "^8.22.1",
"vue-i18n": "^8.22.2",
"vue-router": "^3.4.9",
"vuex": "^3.5.1",
"vuex": "^3.6.0",
"vuex-router-sync": "^5.0.0"
}
}

View File

@ -1,6 +1,14 @@
### 新增
- 直接从歌单详情收藏的列表新增同步功能。注意:这将会覆盖本地的目标列表,歌曲将被替换成最新的在线列表
### 优化
- 优化软件启动时恢复上一次播放的歌曲进度功能
### 修复
- 修复有歌词翻译与无歌词的音乐间切换会导致歌词翻译残留显示的问题
- 修复歌曲URL过期时等待刷新URL的自动切换歌曲时间间隔太短的问题
- 修复某些电脑上的某些歌曲没有声音的问题升级Electron9.3.4导致的现降级到9.3.3
- 修复MAC平台上下载歌曲封面嵌入无法显示的问题
- 修复MAC平台首次运行软件最小化、关闭控制按钮默认在右边的问题
- 修复酷狗源的某些歌曲没有专辑字段导致的列表加载失败问题
- 修复某些酷狗源歌单链接无法打开的问题

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,5 @@
const path = require('path')
const os = require('os')
const { isMac } = require('./utils')
const defaultSetting = {
version: '1.0.38',
@ -92,7 +91,7 @@ const defaultSetting = {
randomAnimate: true,
ignoreVersion: null,
isAgreePact: false,
controlBtnPosition: isMac ? 'left' : 'right',
controlBtnPosition: process.platform === 'darwin' ? 'left' : 'right',
}
const overwriteSetting = {

View File

@ -1,4 +1,4 @@
const names = require('../main/events/_name')
const names = require('@main/events/_name')
const hotKey = {
common: {
min: {

View File

@ -273,7 +273,21 @@ export default {
getPlayList().then(({ defaultList, loveList, userList, downloadList }) => {
if (!defaultList) defaultList = this.defaultList
if (!loveList) loveList = this.loveList
if (!userList) userList = this.userList
if (userList) {
let needSave = false
const getListId = id => id.includes('.') ? getListId(id.substring(0, id.lastIndexOf('_'))) : id
userList.forEach(l => {
if (!l.id.includes('__') || l.source) return
let [source, id] = l.id.split('__')
id = getListId(id)
l.source = source
l.sourceListId = id
if (!needSave) needSave = true
})
if (needSave) this.saveUserList(userList)
} else {
userList = this.userList
}
if (!defaultList.list) defaultList.list = []
if (!loveList.list) loveList.list = []
@ -306,7 +320,9 @@ export default {
initPlayInfo() {
rendererInvoke(NAMES.mainWindow.get_data, 'playInfo').then(info => {
// console.log(info, window.allList)
window.restorePlayInfo = null
if (!info) return
if (info.index < 0) return
if (info.listId) {
const list = window.allList[info.listId]
// console.log(list)

View File

@ -244,9 +244,31 @@ export default {
watch: {
changePlay(n) {
if (!n) return
this.resetChangePlay()
if (window.restorePlayInfo) {
let musicInfo = this.targetSong = this.list[window.restorePlayInfo.index]
this.musicInfo.songmid = musicInfo.songmid
this.musicInfo.singer = musicInfo.singer
this.musicInfo.name = musicInfo.name
this.musicInfo.album = musicInfo.albumName
this.setImg(musicInfo)
this.setLrc(musicInfo)
this.nowPlayTime = this.restorePlayTime = window.restorePlayInfo.time
this.maxPlayTime = window.restorePlayInfo.maxTime || 0
this.handleUpdateWinLyricInfo('music_info', {
songmid: this.musicInfo.songmid,
singer: this.musicInfo.singer,
name: this.musicInfo.name,
album: this.musicInfo.album,
})
this.$nextTick(() => {
this.sendProgressEvent(this.progress, 'paused')
})
window.restorePlayInfo = null
return
}
// console.log('changePlay')
this.handleRemoveMusic()
this.resetChangePlay()
if (this.playIndex < 0) return
this.stopPlay()
this.play()
@ -295,6 +317,7 @@ export default {
if (Math.abs(n - o) > 2) this.isActiveTransition = true
this.savePlayInfo({
time: n,
maxTime: this.maxPlayTime,
listId: this.listId,
list: this.listId == null ? this.list : null,
index: this.playIndex,
@ -377,12 +400,7 @@ export default {
this.clearLoadingTimeout()
this.status = this.statusText = this.$t('core.player.loading')
this.maxPlayTime = audio.duration
if (window.restorePlayInfo) {
audio.currentTime = window.restorePlayInfo.time
window.restorePlayInfo = null
audio.pause()
this.stopPlay()
} else if (this.restorePlayTime) {
if (this.restorePlayTime) {
audio.currentTime = this.restorePlayTime
this.restorePlayTime = 0
}
@ -651,7 +669,13 @@ export default {
)
},
togglePlay() {
if (!audio.src) return
if (!audio.src) {
if (this.restorePlayTime != null) {
if (!this.assertApiSupport(this.targetSong.source)) return this.handleNext()
this.setUrl(this.targetSong)
}
return
}
if (this.isPlay) {
audio.pause()
this.clearBufferTimeout()
@ -801,7 +825,7 @@ export default {
// console.log('start load timeout')
this.loadingTimeout = setTimeout(() => {
this.handleNext()
}, 10000)
}, 20000)
},
clearLoadingTimeout() {
if (!this.loadingTimeout) return
@ -810,7 +834,7 @@ export default {
this.loadingTimeout = null
},
startBuffering() {
console.error('start t')
console.log('start t')
if (this.mediaBuffer.timeout) return
this.mediaBuffer.timeout = setTimeout(() => {
this.mediaBuffer.timeout = null

View File

@ -4,6 +4,7 @@
"lists_rename": "Rename",
"lists_moveup": "Move Up",
"lists_movedown": "Move Down",
"lists_sync": "Sync",
"lists_remove": "Remove",
"list_play": "Play",
"list_copy_name": "Copy name",

View File

@ -1,7 +1,7 @@
// http://kazupon.github.io/vue-i18n/en/messages.html
const requireLang = require.context(
'@/lang',
'@renderer/lang',
true,
/\.json$/,
)

View File

@ -4,6 +4,7 @@
"lists_rename": "重命名",
"lists_moveup": "上移",
"lists_movedown": "下移",
"lists_sync": "同步",
"lists_remove": "删除",
"list_play": "播放",
"list_copy_name": "复制歌曲名",

View File

@ -4,6 +4,7 @@
"lists_rename": "重命名",
"lists_moveup": "上移",
"lists_movedown": "下移",
"lists_sync": "同步",
"lists_remove": "刪除",
"list_play": "播放",
"list_copy_name": "複製歌曲名",

View File

@ -17,7 +17,7 @@ import store from './store'
import '../common/error'
import { getSetting } from './utils'
import languageList from '@/lang/languages.json'
import languageList from '@renderer/lang/languages.json'
import { rendererSend, NAMES } from '../common/ipc'
sync(store, router)

View File

@ -9,7 +9,7 @@
// Lib imports
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from '@/lang'
import messages from '@renderer/lang'
Vue.use(VueI18n)

View File

@ -60,7 +60,7 @@ const mutations = {
allListInit(state.defaultList, state.loveList, state.userList)
state.isInitedList = true
},
setList(state, { id, list, name, location }) {
setList(state, { id, list, name, location, source, sourceListId }) {
const targetList = allList[id]
if (targetList) {
if (name && targetList.name === name) {
@ -76,6 +76,8 @@ const mutations = {
id,
list,
location,
source,
sourceListId,
}
state.userList.push(newList)
allListUpdate(newList)
@ -145,7 +147,7 @@ const mutations = {
if (!targetList) return
Object.assign(targetList.list[index], data)
},
createUserList(state, { name, id = `userlist_${Date.now()}`, list = [] }) {
createUserList(state, { name, id = `userlist_${Date.now()}`, list = [], source, sourceListId }) {
let newList = state.userList.find(item => item.id === id)
if (!newList) {
newList = {
@ -153,6 +155,8 @@ const mutations = {
id,
list: [],
location: 0,
source,
sourceListId,
}
state.userList.push(newList)
allListUpdate(newList)

View File

@ -9,6 +9,15 @@ for (const source of music.sources) {
sources.push(source)
}
const filterList = list => {
const keys = new Set()
return list.filter(item => {
if (keys.has(item.songmid)) return false
keys.add(item.songmid)
return true
})
}
// state
const state = {
tags: {},
@ -78,11 +87,11 @@ const actions = {
return (
cache.has(key)
? Promise.resolve(cache.get(key))
: music[source].songList.getListDetail(id, page)
: music[source].songList.getListDetail(id, page).then(result => ({ ...result, list: filterList(result.list) }))
).then(result => commit('setListDetail', { result, key, source, id, page }))
},
getListDetailAll({ state, rootState }, id) {
let source = rootState.setting.songList.source
getListDetailAll({ state, rootState }, { source, id }) {
// console.log(source, id)
const loadData = (id, page) => {
let key = `sdetail__${source}__${id}__${page}`
return cache.has(key)
@ -93,7 +102,7 @@ const actions = {
})
}
return loadData(id, 1).then(result => {
if (result.total <= result.limit) return result.list
if (result.total <= result.limit) return filterList(result.list)
let maxPage = Math.ceil(result.total / result.limit)
const loadDetail = (loadPage = 1) => {
@ -101,7 +110,7 @@ const actions = {
? loadData(id, ++loadPage).then(result => result.list)
: loadData(id, ++loadPage).then(result1 => loadDetail(loadPage).then(result2 => [...result1.list, ...result2]))
}
return loadDetail().then(result2 => [...result.list, ...result2])
return loadDetail().then(result2 => [...result.list, ...result2]).then(list => filterList(list))
})
},
}

View File

@ -80,7 +80,7 @@ const encodeNames = {
'&apos;': "'",
'&#039;': "'",
}
export const decodeName = str => str.replace(/(?:&amp;|&lt;|&gt;|&quot;|&apos;|&#039;)/gm, s => encodeNames[s])
export const decodeName = (str = '') => str.replace(/(?:&amp;|&lt;|&gt;|&quot;|&apos;|&#039;)/gm, s => encodeNames[s])
const easeInOutQuad = (t, b, c, d) => {
t /= d / 2

View File

@ -378,7 +378,7 @@ export default {
id = id.toString()
if (id.includes('special/single/')) {
id = id.replace(this.regExps.listDetailLink, '$1')
} else if (/http(?:s):/.test(id)) {
} else if (/https?:/.test(id)) {
return this.getUserListDetail(id.replace(/^.*http/, 'http'), page)
} else if (/^\d+$/.test(id)) {
return this.getUserListDetailByCode(id)

View File

@ -31,7 +31,7 @@ export default {
},
})
const { body, statusCode } = await _requestObj.promise
console.log(body)
// console.log(body)
if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取评论失败')
return { source: 'mg', comments: this.filterComment(body.data.items), total: body.data.itemTotal, page, limit, maxPage: Math.ceil(body.data.itemTotal / limit) || 1 }
},

View File

@ -11,7 +11,10 @@
span(:class="$style.listsLabel") {{defaultList.name}}
li(:class="[$style.listsItem, loveList.id == listId ? $style.active : null]" :tips="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)" :tips="item.name" v-for="(item, index) in userList" :key="item.id")
li.user-list(
:class="[$style.listsItem, item.id == listId ? $style.active : null, listsData.rightClickItemIndex == index ? $style.clicked : null, fetchingListStatus[item.id] ? $style.fetching : null]"
@contextmenu="handleListsItemRigthClick($event, index)"
:tips="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" @contextmenu.stop 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")
@ -100,6 +103,7 @@ export default {
isShowItemMenu: false,
itemMenuControl: {
rename: true,
sync: false,
moveup: true,
movedown: true,
remove: true,
@ -131,6 +135,7 @@ export default {
isMove: false,
isMoveMultiple: false,
isVisibleMusicSearch: false,
fetchingListStatus: {},
}
},
computed: {
@ -180,6 +185,11 @@ export default {
action: 'rename',
disabled: !this.listsData.itemMenuControl.rename,
},
{
name: this.$t('view.list.lists_sync'),
action: 'sync',
disabled: !this.listsData.itemMenuControl.sync,
},
{
name: this.$t('view.list.lists_moveup'),
action: 'moveup',
@ -309,7 +319,18 @@ export default {
},
methods: {
...mapMutations(['setPrevSelectListId']),
...mapMutations('list', ['listRemove', 'listRemoveMultiple', 'setUserListName', 'createUserList', 'moveupUserList', 'movedownUserList', 'removeUserList', 'setListScroll']),
...mapMutations('list', [
'listRemove',
'listRemoveMultiple',
'setUserListName',
'createUserList',
'moveupUserList',
'movedownUserList',
'removeUserList',
'setListScroll',
'setList',
]),
...mapActions('songList', ['getListDetailAll']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('player', {
setPlayList: 'setList',
@ -668,6 +689,8 @@ export default {
}).catch(_ => _)
},
handleListsItemRigthClick(event, index) {
const source = this.userList[index].source
this.listsData.itemMenuControl.sync = !!source && !!musicSdk[source].songList
this.listsData.itemMenuControl.moveup = index > 0
this.listsData.itemMenuControl.movedown = index < this.userList.length - 1
this.listsData.rightClickItemIndex = index
@ -714,6 +737,9 @@ export default {
dom.querySelector('input').focus()
})
break
case 'sync':
this.handleSyncSourceList(index)
break
case 'moveup':
this.moveupUserList(index)
break
@ -814,6 +840,27 @@ export default {
break
}
},
fetchList(id, source, sourceListId) {
if (this.fetchingListStatus[id] == null) {
this.$set(this.fetchingListStatus, id, true)
} else {
this.fetchingListStatus[id] = true
}
return this.getListDetailAll({ source, id: sourceListId }).catch(err => {
return Promise.reject(err)
}).finally(() => {
this.fetchingListStatus[id] = false
})
},
async handleSyncSourceList(index) {
const targetList = this.userList[index]
const list = await this.fetchList(targetList.id, targetList.source, targetList.sourceListId)
// console.log(targetList.list.length, list.length)
this.setList({
...targetList,
list,
})
},
},
}
</script>
@ -880,7 +927,7 @@ export default {
.listsItem {
position: relative;
transition: .3s ease;
transition-property: color, background-color;
transition-property: color, background-color, opacity;
background-color: transparent;
&:hover:not(.active) {
background-color: @color-theme_2-hover;
@ -896,6 +943,9 @@ export default {
&.clicked {
background-color: @color-theme_2-hover;
}
&.fetching {
opacity: .5;
}
&.editing {
padding: 0 10px;
background-color: @color-theme_2-hover;

View File

@ -296,11 +296,11 @@ import {
sizeFormate,
setWindowSize,
} from '../utils'
import { rendererSend, rendererInvoke, NAMES } from '../../common/ipc'
import { rendererSend, rendererInvoke, NAMES } from '@common/ipc'
import { mergeSetting, isMac } from '../../common/utils'
import apiSourceInfo from '../utils/music/api-source-info'
import fs from 'fs'
import languageList from '@/lang/languages.json'
import languageList from '@renderer/lang/languages.json'
import { base as eventBaseName } from '../event/names'
import * as hotKeys from '../../common/hotKey'
import { mainWindow as eventsNameMainWindow, winLyric as eventsNameWinLyric } from '../../main/events/_name'

View File

@ -373,6 +373,7 @@ export default {
}
},
handleGetSongListDetail() {
if (!this.importSongListText.length) return
this.setSelectListInfo({
play_count: null,
id: this.importSongListText,
@ -404,14 +405,22 @@ export default {
},
async fetchList() {
this.detailLoading = true
const list = await this.getListDetailAll(this.selectListInfo.id)
this.detailLoading = false
return list
return this.getListDetailAll({ source: this.source, id: this.selectListInfo.id }).catch(err => {
return Promise.reject(err)
}).finally(() => {
this.detailLoading = false
})
},
async addSongListDetail() {
if (!this.listDetail.info.name) return
const list = await this.fetchList()
this.createUserList({ name: this.listDetail.info.name, id: `${this.listDetail.source}__${this.listDetail.id}`, list })
this.createUserList({
name: this.listDetail.info.name,
id: `${this.listDetail.source}__${this.listDetail.id}`,
list,
source: this.listDetail.source,
sourceListId: this.listDetail.id,
})
},
async playSongListDetail() {
if (!this.listDetail.info.name) return