完成同步功能

This commit is contained in:
lyswhut
2021-08-01 12:57:13 +08:00
parent 33ec3de1b4
commit bcf3dde60d
38 changed files with 1975 additions and 120 deletions
+115 -3
View File
@@ -8,6 +8,7 @@
core-icons
material-version-modal(v-show="version.showModal")
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
material-sync-mode-modal(v-show="globalObj.sync.isShowSyncMode")
#container(v-else :class="theme")
core-aside#left
#right
@@ -17,6 +18,7 @@
core-icons
material-version-modal(v-show="version.showModal")
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
material-sync-mode-modal(v-show="globalObj.sync.isShowSyncMode")
</template>
<script>
@@ -25,7 +27,7 @@ import { rendererOn, rendererSend, rendererInvoke, NAMES } from '../common/ipc'
import { isLinux } from '../common/utils'
import music from './utils/music'
import { throttle, openUrl, compareVer, getPlayList, parseUrlParams, saveSetting } from './utils'
import { base as eventBaseName } from './event/names'
import { base as eventBaseName, sync as eventSyncName } from './event/names'
import apiSourceInfo from './utils/music/api-source-info'
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
@@ -61,6 +63,11 @@ export default {
message: 'initing',
apis: {},
},
sync: {
enable: false,
isShowSyncMode: false,
deviceName: '',
},
},
updateTimeout: null,
envParams: {
@@ -103,6 +110,14 @@ export default {
document.body.classList.add(this.isDT ? 'disableTransparent' : 'transparent')
window.eventHub.$emit(eventBaseName.bindKey)
this.init()
window.eventHub.$on(eventSyncName.handle_action_list, this.handleSyncAction)
window.eventHub.$on(eventSyncName.handle_sync_list, this.handleSyncList)
if (this.setting.sync.enable && this.setting.sync.port) {
rendererInvoke(NAMES.mainWindow.sync_enable, {
enable: this.setting.sync.enable,
port: this.setting.sync.port,
})
}
},
watch: {
setting: {
@@ -193,7 +208,25 @@ export default {
methods: {
...mapActions(['getVersionInfo']),
...mapMutations(['setNewVersion', 'setVersionModalVisible', 'setDownloadProgress', 'setSetting', 'setDesktopLyricConfig']),
...mapMutations('list', ['initList']),
...mapMutations('list', {
list_initList: 'initList',
list_setList: 'setList',
list_listAdd: 'listAdd',
list_listMove: 'listMove',
list_listAddMultiple: 'listAddMultiple',
list_listMoveMultiple: 'listMoveMultiple',
list_listRemove: 'listRemove',
list_listRemoveMultiple: 'listRemoveMultiple',
list_listClear: 'listClear',
list_updateMusicInfo: 'updateMusicInfo',
list_createUserList: 'createUserList',
list_removeUserList: 'removeUserList',
list_setUserListName: 'setUserListName',
list_moveupUserList: 'moveupUserList',
list_movedownUserList: 'movedownUserList',
list_setMusicPosition: 'setMusicPosition',
list_setSyncListData: 'setSyncListData',
}),
...mapMutations('download', ['updateDownloadList']),
...mapMutations('search', {
setSearchHistoryList: 'setHistory',
@@ -272,6 +305,7 @@ export default {
this.listenEvent()
asyncTask.push(this.initData())
asyncTask.push(this.initUserApi())
this.globalObj.sync.enable = this.setting.sync.enable
this.globalObj.apiSource = this.setting.apiSource
if (/^user_api/.test(this.setting.apiSource)) {
rendererInvoke(NAMES.mainWindow.set_user_api, this.setting.apiSource)
@@ -328,7 +362,7 @@ export default {
if (!defaultList.list) defaultList.list = []
if (!loveList.list) loveList.list = []
this.initList({ defaultList, loveList, userList })
this.list_initList({ defaultList, loveList, userList })
this.initDownloadList(downloadList) // 初始化下载列表
this.initPlayInfo()
})
@@ -590,6 +624,84 @@ export default {
event.target.value = ''
event.target.blur()
},
handleSyncAction({ action, data }) {
if (typeof data == 'object') data.isSync = true
// console.log(action, data)
switch (action) {
case 'set_list':
this.list_setList(data)
break
case 'list_add':
this.list_listAdd(data)
break
case 'list_move':
this.list_listMove(data)
break
case 'list_add_multiple':
this.list_listAddMultiple(data)
break
case 'list_move_multiple':
this.list_listMoveMultiple(data)
break
case 'list_remove':
this.list_listRemove(data)
break
case 'list_remove_multiple':
this.list_listRemoveMultiple(data)
break
case 'list_clear':
this.list_listClear(data)
break
case 'update_music_info':
this.list_updateMusicInfo(data)
break
case 'create_user_list':
this.list_createUserList(data)
break
case 'remove_user_list':
this.list_removeUserList(data)
break
case 'set_user_list_name':
this.list_setUserListName(data)
break
case 'moveup_user_list':
this.list_moveupUserList(data)
break
case 'movedown_user_list':
this.list_movedownUserList(data)
break
case 'set_music_position':
this.list_setMusicPosition(data)
break
default:
break
}
},
handleSyncList({ action, data }) {
switch (action) {
case 'getData':
global.eventHub.$emit(eventSyncName.send_sync_list, {
action: 'getData',
data: {
defaultList: this.defaultList,
loveList: this.loveList,
userList: this.userList,
},
})
break
case 'setData':
this.list_setSyncListData(data)
break
case 'selectMode':
this.globalObj.sync.deviceName = data.deviceName
this.globalObj.sync.isShowSyncMode = true
break
case 'closeSelectMode':
this.globalObj.sync.isShowSyncMode = false
break
}
},
},
beforeDestroy() {
this.clearUpdateTimeout()
+6
View File
@@ -123,6 +123,9 @@ small {
.small {
font-size: .9em;
}
.tip {
color: @color-theme_2-font-label;
}
strong {
font-weight: bold;
}
@@ -192,6 +195,9 @@ each(@themes, {
button, input, textarea, a {
color: ~'@{color-@{value}-theme_2-font}';
}
.tip {
color: ~'@{color-@{value}-theme_2-font-label}';
}
.hover, a {
&:hover {
+1 -1
View File
@@ -411,7 +411,7 @@ export default {
this.restorePlayTime = 0
}
if (!this.targetSong.interval && this.listId != 'download') {
this.updateMusicInfo({ id: this.listId, index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) }, musicInfo: this.targetSong })
this.updateMusicInfo({ listId: this.listId, id: this.targetSong.songmid, musicInfo: this.targetSong, data: { interval: formatPlayTime2(this.maxPlayTime) } })
}
})
audio.addEventListener('loadstart', () => {
+1 -1
View File
@@ -140,7 +140,7 @@ export default {
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
overflow: hidden;
max-height: 80%;
max-width: 70%;
max-width: 76%;
position: relative;
display: flex;
flex-flow: column nowrap;
@@ -0,0 +1,164 @@
<template lang="pug">
material-modal(:show="globalObj.sync.isShowSyncMode" @close="handleClose(false)" :bgClose="false" :close-btn="false")
main(:class="$style.main")
h2 {{$t('material.sync_mode_modal.title', { name: globalObj.sync.deviceName })}}
div.scroll(:class="$style.content")
dl(:class="$style.btnGroup")
dt(:class="$style.label") {{$t('material.sync_mode_modal.merge_label')}}
dd(:class="$style.btns")
material-btn(:class="$style.btn" @click="handleSelectMode('merge_local_remote')") {{$t('material.sync_mode_modal.merge_btn_local_remote')}}
material-btn(:class="$style.btn" @click="handleSelectMode('merge_remote_local')") {{$t('material.sync_mode_modal.merge_btn_remote_local')}}
dl(:class="$style.btnGroup")
dt(:class="$style.label") {{$t('material.sync_mode_modal.overwrite_label')}}
dd(:class="$style.btns")
material-btn(:class="$style.btn" @click="handleSelectMode('overwrite_local_remote')") {{$t('material.sync_mode_modal.overwrite_btn_local_remote')}}
material-btn(:class="$style.btn" @click="handleSelectMode('overwrite_remote_local')") {{$t('material.sync_mode_modal.overwrite_btn_remote_local')}}
dd(style="font-size: 14px; margin-top: 5px;")
material-checkbox(id="sync_mode_modal_isOverwrite" v-model="isOverwrite" :label="$t('material.sync_mode_modal.overwrite')")
dl(:class="$style.btnGroup")
dt(:class="$style.label") {{$t('material.sync_mode_modal.other_label')}}
dd(:class="$style.btns")
material-btn(:class="$style.btn" @click="handleSelectMode('none')") {{$t('material.sync_mode_modal.overwrite_btn_none')}}
material-btn(:class="$style.btn" @click="handleSelectMode('cancel')") {{$t('material.sync_mode_modal.overwrite_btn_cancel')}}
dl(:class="$style.btnGroup")
dd
section(:class="$style.tipGroup")
h3(:class="$style.title") {{$t('material.sync_mode_modal.merge_tip')}}
p(:class="$style.tip") {{$t('material.sync_mode_modal.merge_tip_desc')}}
section(:class="$style.tipGroup")
h3(:class="$style.title") {{$t('material.sync_mode_modal.overwrite_tip')}}
p(:class="$style.tip") {{$t('material.sync_mode_modal.overwrite_tip_desc')}}
section(:class="$style.tipGroup")
h3(:class="$style.title") {{$t('material.sync_mode_modal.other_tip')}}
p(:class="$style.tip") {{$t('material.sync_mode_modal.other_tip_desc')}}
</template>
<script>
import { sync as eventSyncName } from '@renderer/event/names'
export default {
data() {
return {
isOverwrite: false,
globalObj: {
sync: {
isShowSyncMode: false,
deviceName: '',
},
},
}
},
computed: {
},
mounted() {
this.$nextTick(() => {
this.globalObj = window.globalObj
})
},
methods: {
handleSelectMode(mode) {
if (mode.startsWith('overwrite') && this.isOverwrite) mode += '_full'
window.eventHub.$emit(eventSyncName.send_sync_list, {
action: 'selectMode',
data: mode,
})
this.handleClose()
},
handleClose() {
this.globalObj.sync.isShowSyncMode = false
},
},
}
</script>
<style lang="less" module>
@import '../../assets/styles/layout.less';
.main {
padding: 15px;
max-width: 700px;
min-width: 200px;
min-height: 0;
display: flex;
flex-flow: column nowrap;
justify-content: center;
h2 {
font-size: 16px;
color: @color-theme_2-font;
line-height: 1.3;
text-align: center;
}
}
.content {
flex: auto;
padding: 15px 0 5px;
padding-right: 5px;
.btnGroup + .btnGroup {
margin-top: 10px;
}
.label {
color: @color-theme_2-font-label;
font-size: 14px;
line-height: 2;
}
.desc {
line-height: 1.5;
font-size: 14px;
text-align: justify;
}
.tipGroup {
display: flex;
flex-direction: row;
font-size: 12px;
+ .tipGroup {
margin-top: 5px;
}
.title {
white-space: nowrap;
font-weight: bold;
margin-right: 5px;
}
.tip {
line-height: 1.3;
}
}
}
.btns {
display: flex;
align-items: center;
}
.btn {
display: block;
white-space: nowrap;
+.btn {
margin-left: 15px;
}
&:last-child {
margin-bottom: 0;
}
}
each(@themes, {
:global(#container.@{value}) {
.main {
h2 {
color: ~'@{color-@{value}-theme_2-font}';
}
}
.name {
color: ~'@{color-@{value}-theme}';
}
}
})
</style>
+16 -1
View File
@@ -1,7 +1,7 @@
import Vue from 'vue'
import keyBind from '../utils/keyBind'
import { rendererOn, rendererSend, NAMES, rendererInvoke } from '../../common/ipc'
import { base as baseName } from './names'
import { base as baseName, sync as syncName } from './names'
import { common as hotKeyNamesCommon } from '../../common/hotKey'
const eventHub = window.eventHub = new Vue()
@@ -77,3 +77,18 @@ rendererOn(NAMES.mainWindow.set_hot_key_config, (event, config) => {
}
window.eventHub.$emit(baseName.set_hot_key_config, config)
})
rendererOn(NAMES.mainWindow.sync_action_list, (event, { action, data }) => {
window.eventHub.$emit(syncName.handle_action_list, { action, data })
})
eventHub.$on(syncName.send_action_list, ({ action, data }) => {
if (!window.globalObj.sync.enable) return
rendererSend(NAMES.mainWindow.sync_action_list, { action, data })
})
rendererOn(NAMES.mainWindow.sync_list, (event, { action, data }) => {
window.eventHub.$emit(syncName.handle_sync_list, { action, data })
})
eventHub.$on(syncName.send_sync_list, ({ action, data }) => {
if (!window.globalObj.sync.enable) return
rendererSend(NAMES.mainWindow.sync_list, { action, data })
})
+7
View File
@@ -10,6 +10,12 @@ const names = {
set_config: 'set_config',
set_hot_key_config: 'set_hot_key_config',
},
sync: {
send_action_list: 'send_action_list',
handle_action_list: 'handle_action_list',
send_sync_list: 'send_sync_list',
handle_sync_list: 'handle_sync_list',
},
}
for (const item of Object.keys(names)) {
@@ -20,3 +26,4 @@ for (const item of Object.keys(names)) {
}
export const base = names.base
export const sync = names.sync
@@ -0,0 +1,19 @@
{
"merge_btn_local_remote": "Local list merge remote list",
"merge_btn_remote_local": "Remote list merge local list",
"merge_label": "Merge",
"merge_tip": "Merge:",
"merge_tip_desc": "Merge the two lists together, the same song will be removed (the song of the merged person is removed), and different songs will be added.",
"other_label": "Other",
"other_tip": "Other: ",
"other_tip_desc": "\"Only use real-time synchronization function\" will not modify the lists of both parties, only real-time synchronization operations; \"Cancel synchronization\" will directly disconnect the two parties.",
"overwrite": "Full coverage",
"overwrite_btn_cancel": "Cancel sync",
"overwrite_btn_local_remote": "Local list Overwrite remote list",
"overwrite_btn_none": "Only use real-time synchronization",
"overwrite_btn_remote_local": "Remote list Overwrite local list",
"overwrite_label": "Cover",
"overwrite_tip": "Cover: ",
"overwrite_tip_desc": "The list with the same ID of the covered person and the covered list will be deleted and replaced with the list of the covered person (lists with different list IDs will be merged together). If you check Complete coverage, all lists of the covered person will be moved. \nDivide, and then replace with a list of overriders.",
"title": "Choose how to synchronize the list with {name}"
}
@@ -130,6 +130,14 @@
"search_focus_search_box": "Automatically focus the search box on startup",
"search_history": "Search history",
"search_hot": "Top Searches",
"sync": "Data synchronization [This is a test function, it is recommended to back up the playlist before using it for the first time]",
"sync_address": "Synchronization service address: {address}",
"sync_auth_code": "Connection code: {code}",
"sync_device": "Connected devices: {devices}",
"sync_enable": "Enable synchronization",
"sync_port": "Sync port settings",
"sync_port_tip": "Please enter the synchronization service port number",
"sync_refresh_code": "Refresh the connection code",
"update": "Update",
"update_checking": "Checking for updates...",
"update_current_label": "Current version: ",
@@ -0,0 +1,19 @@
{
"merge_btn_local_remote": "本机列表 合并 远程列表",
"merge_btn_remote_local": "远程列表 合并 本机列表",
"merge_label": "合并",
"merge_tip": "合并:",
"merge_tip_desc": "将两边的列表合并到一起,相同的歌曲将被去掉(去掉的是被合并者的歌曲),不同的歌曲将被添加。",
"other_label": "其他",
"other_tip": "其他:",
"other_tip_desc": "“仅使用实时同步功能”将不修改双方的列表,仅实时同步操作;“取消同步”将直接断开双方的连接。",
"overwrite": "完全覆盖",
"overwrite_btn_cancel": "取消同步",
"overwrite_btn_local_remote": "本机列表 覆盖 远程列表",
"overwrite_btn_none": "仅使用实时同步功能",
"overwrite_btn_remote_local": "远程列表 覆盖 本机列表",
"overwrite_label": "覆盖",
"overwrite_tip": "覆盖:",
"overwrite_tip_desc": "被覆盖者与覆盖者列表ID相同的列表将被删除后替换成覆盖者的列表(列表ID不同的列表将被合并到一起),若勾选完全覆盖,则被覆盖者的所有列表将被移除,然后替换成覆盖者的列表。",
"title": "选择与 {name} 的列表同步方式"
}
@@ -130,6 +130,14 @@
"search_focus_search_box": "启动时自动聚焦搜索框",
"search_history": "显示历史搜索记录",
"search_hot": "显示热门搜索",
"sync": "数据同步 [此为测试功能,首次使用前建议先备份一次歌单]",
"sync_address": "同步服务地址:{address}",
"sync_auth_code": "连接码:{code}",
"sync_device": "已连接的设备:{devices}",
"sync_enable": "启用同步功能",
"sync_port": "同步端口设置",
"sync_port_tip": "请输入同步服务端口号",
"sync_refresh_code": "刷新连接码",
"update": "软件更新",
"update_checking": "检查更新中...",
"update_current_label": "当前版本:",
@@ -0,0 +1,19 @@
{
"merge_btn_local_remote": "本機列表 合併 遠程列表",
"merge_btn_remote_local": "遠程列表 合併 本機列表",
"merge_label": "合併",
"merge_tip": "合併:",
"merge_tip_desc": "將兩邊的列表合併到一起,相同的歌曲將被去掉(去掉的是被合併者的歌曲),不同的歌曲將被添加。",
"other_label": "其他",
"other_tip": "其他:",
"other_tip_desc": "“僅使用實時同步功能”將不修改雙方的列表,僅實時同步操作;“取消同步”將直接斷開雙方的連接。",
"overwrite": "完全覆蓋",
"overwrite_btn_cancel": "取消同步",
"overwrite_btn_local_remote": "本機列表 覆蓋 遠程列表",
"overwrite_btn_none": "僅使用實時同步功能",
"overwrite_btn_remote_local": "遠程列表 覆蓋 本機列表",
"overwrite_label": "覆蓋",
"overwrite_tip": "覆蓋:",
"overwrite_tip_desc": "被覆蓋者與覆蓋者列表ID相同的列表將被刪除後替換成覆蓋者的列表(列表ID不同的列表將被合併到一起),若勾選完全覆蓋,則被覆蓋者的所有列表將被移除,然後替換成覆蓋者的列表。",
"title": "選擇與 {name} 的列表同步方式"
}
@@ -130,6 +130,14 @@
"search_focus_search_box": "啟動時自動聚焦搜索框",
"search_history": "顯示歷史搜索記錄",
"search_hot": "顯示熱門搜索",
"sync": "數據同步 [此為測試功能,首次使用前建議先備份一次歌單]",
"sync_address": "同步服務地址:{address}",
"sync_auth_code": "連接碼:{code}",
"sync_device": "已連接的設備:{devices}",
"sync_enable": "啟用同步功能",
"sync_port": "同步端口設置",
"sync_port_tip": "請輸入同步服務端口號",
"sync_refresh_code": "刷新連接碼",
"update": "軟件更新",
"update_checking": "檢查更新中...",
"update_current_label": "當前版本:",
+184 -41
View File
@@ -1,10 +1,14 @@
import musicSdk from '../../utils/music'
import { clearLyric, clearMusicUrl } from '../../utils'
import { sync as eventSyncName } from '@renderer/event/names'
let allList = {}
window.allList = allList
const allListInit = (defaultList, loveList, userList) => {
for (const id of Object.keys(allList)) {
delete allList[id]
}
allList[defaultList.id] = defaultList
allList[loveList.id] = loveList
for (const list of userList) allList[list.id] = list
@@ -67,8 +71,28 @@ const mutations = {
if (userList != null) state.userList = userList
allListInit(state.defaultList, state.loveList, state.userList)
state.isInitedList = true
// if (!isSync) {
// window.eventHub.$emit(eventSyncName.send_action_list, {
// action: 'init_list',
// data: { defaultList, loveList, userList },
// })
// }
},
setList(state, { id, list, name, location, source, sourceListId }) {
setSyncListData(state, { defaultList, loveList, userList }) {
state.defaultList.list.splice(0, state.defaultList.list.length, ...defaultList.list)
state.loveList.list.splice(0, state.loveList.list.length, ...loveList.list)
state.userList = userList
allListInit(state.defaultList, state.loveList, state.userList)
},
setList(state, { id, list, name, location, source, sourceListId, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'set_list',
data: { id, list, name, location, source, sourceListId },
})
}
const targetList = allList[id]
if (targetList) {
if (name && targetList.name === name) {
@@ -90,11 +114,20 @@ const mutations = {
state.userList.push(newList)
allListUpdate(newList)
},
listAdd(state, { id, musicInfo }) {
listAdd(state, { id, musicInfo, addMusicLocationType, isSync }) {
if (!addMusicLocationType) addMusicLocationType = this.state.setting.list.addMusicLocationType
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_add',
data: { id, musicInfo, addMusicLocationType },
})
}
const targetList = allList[id]
if (!targetList) return
if (targetList.list.some(s => s.songmid === musicInfo.songmid)) return
switch (this.state.setting.list.addMusicLocationType) {
switch (addMusicLocationType) {
case 'top':
targetList.list.unshift(musicInfo)
break
@@ -104,11 +137,18 @@ const mutations = {
break
}
},
listMove(state, { fromId, musicInfo, toId }) {
listMove(state, { fromId, musicInfo, toId, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_move',
data: { fromId, musicInfo, toId },
})
}
const fromList = allList[fromId]
const toList = allList[toId]
if (!fromList || !toList) return
fromList.list.splice(fromList.list.indexOf(musicInfo), 1)
fromList.list.splice(fromList.list.findIndex(s => s.songmid === musicInfo.songmid), 1)
let index = toList.list.findIndex(s => s.songmid === musicInfo.songmid)
if (index < 0) {
switch (this.state.setting.list.addMusicLocationType) {
@@ -122,41 +162,79 @@ const mutations = {
}
}
},
listAddMultiple(state, { id, list }) {
listAddMultiple(state, { id, list, addMusicLocationType, isSync }) {
if (!addMusicLocationType) addMusicLocationType = this.state.setting.list.addMusicLocationType
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_add_multiple',
data: { id, list, addMusicLocationType },
})
}
let targetList = allList[id]
if (!targetList) return
let newList
switch (this.state.setting.list.addMusicLocationType) {
const map = {}
const ids = []
switch (addMusicLocationType) {
case 'top':
newList = [...list, ...targetList.list]
for (let i = newList.length - 1; i > -1; i--) {
const item = newList[i]
if (map[item.songmid]) continue
ids.unshift(item.songmid)
map[item.songmid] = item
}
break
case 'bottom':
default:
newList = [...targetList.list, ...list]
for (const item of newList) {
if (map[item.songmid]) continue
ids.push(item.songmid)
map[item.songmid] = item
}
break
}
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]))
},
// { fromId, toId, list }
listMoveMultiple(state, { fromId, toId, list }) {
listMoveMultiple(state, { fromId, toId, list, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_move_multiple',
data: { fromId, toId, list },
})
}
// console.log(state.commit)
this.commit('list/listRemoveMultiple', { id: fromId, list })
this.commit('list/listAddMultiple', { id: toId, list })
this.commit('list/listRemoveMultiple', { listId: fromId, ids: list.map(s => s.songmid), isSync: true })
this.commit('list/listAddMultiple', { id: toId, list, isSync: true })
},
listRemove(state, { id, index }) {
let targetList = allList[id]
listRemove(state, { listId, id, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_remove',
data: { listId, id },
})
}
let targetList = allList[listId]
if (!targetList) return
const index = targetList.list.findIndex(item => item.songmid == id)
if (index < 0) return
targetList.list.splice(index, 1)
},
listRemoveMultiple(state, { id, list }) {
let targetList = allList[id]
listRemoveMultiple(state, { listId, ids: musicIds, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_remove_multiple',
data: { listId, ids: musicIds },
})
}
let targetList = allList[listId]
if (!targetList) return
let map = {}
let ids = []
@@ -164,25 +242,50 @@ const mutations = {
ids.push(item.songmid)
map[item.songmid] = item
}
for (const item of list) {
if (map[item.songmid]) delete map[item.songmid]
for (const songmid of musicIds) {
if (map[songmid]) delete map[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) {
listClear(state, { id, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'list_clear',
data: { id },
})
}
let targetList = allList[id]
if (!targetList) return
targetList.list.splice(0, targetList.list.length)
},
updateMusicInfo(state, { id, index, data, musicInfo = {} }) {
let targetList = allList[id]
if (!targetList) return Object.assign(musicInfo, data)
Object.assign(targetList.list[index], data)
updateMusicInfo(state, { listId, id, data, musicInfo, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'update_music_info',
data: { listId, id, data, musicInfo },
})
}
let targetList = allList[listId]
if (!targetList) {
if (musicInfo) Object.assign(musicInfo, data)
return
}
const targetMusicInfo = targetList.list.find(item => item.songmid == id)
if (targetMusicInfo) Object.assign(targetMusicInfo, data)
},
createUserList(state, { name, id = `userlist_${Date.now()}`, list = [], source, sourceListId }) {
createUserList(state, { name, id = `userlist_${Date.now()}`, list = [], source, sourceListId, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'create_user_list',
data: { name, id, list, source, sourceListId },
})
}
let newList = state.userList.find(item => item.id === id)
if (!newList) {
newList = {
@@ -196,35 +299,75 @@ const mutations = {
state.userList.push(newList)
allListUpdate(newList)
}
this.commit('list/listAddMultiple', { id, list })
this.commit('list/listAddMultiple', { id, list, isSync: true })
},
removeUserList(state, index) {
removeUserList(state, { id, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'remove_user_list',
data: { id },
})
}
const index = state.userList.findIndex(l => l.id === id)
if (index < 0) return
let list = state.userList.splice(index, 1)[0]
allListRemove(list)
},
setUserListName(state, { index, name }) {
let list = state.userList[index]
setUserListName(state, { id, name, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'set_user_list_name',
data: { id, name },
})
}
let list = allList[id]
if (!list) return
list.name = name
},
moveupUserList(state, index) {
let targetList = state.userList[index]
moveupUserList(state, { id, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'moveup_user_list',
data: { id },
})
}
const index = state.userList.findIndex(l => l.id == id)
if (index < 0) return
let targetList = allList[id]
state.userList.splice(index, 1)
state.userList.splice(index - 1, 0, targetList)
},
movedownUserList(state, index) {
let targetList = state.userList[index]
movedownUserList(state, { id, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'movedown_user_list',
data: { id },
})
}
const index = state.userList.findIndex(l => l.id == id)
if (index < 0) return
let targetList = allList[id]
state.userList.splice(index, 1)
state.userList.splice(index + 1, 0, targetList)
},
setListScroll(state, { id, location }) {
if (allList[id]) allList[id].location = location
},
sortList(state, { id, sortNum, musicInfos }) {
let targetList = allList[id]
this.commit('list/listRemoveMultiple', { id, list: musicInfos })
setMusicPosition(state, { id, position, list, isSync }) {
if (!isSync) {
window.eventHub.$emit(eventSyncName.send_action_list, {
action: 'set_music_position',
data: { id, position, list },
})
}
targetList.list.splice(sortNum - 1, 0, ...musicInfos)
let targetList = allList[id]
this.commit('list/listRemoveMultiple', { listId: id, ids: list.map(m => m.songmid), isSync: true })
targetList.list.splice(position - 1, 0, ...list)
},
clearCache() {
const lists = Object.values(allList)
+7 -5
View File
@@ -156,11 +156,11 @@ const getters = {
if (listId != '__temp__') {
if (isPlayList) {
playIndex = state.listInfo.list.indexOf(state.playMusicInfo.musicInfo)
playIndex = state.listInfo.list.findIndex(m => m.songmid == state.playMusicInfo.musicInfo.songmid)
if (!isTempPlay) listPlayIndex = playIndex
} else {
let list = window.allList[listId]
if (list) playIndex = list.list.indexOf(state.playMusicInfo.musicInfo)
if (list) playIndex = list.list.findIndex(m => m.songmid == state.playMusicInfo.musicInfo.songmid)
}
}
// console.log({
@@ -273,7 +273,8 @@ const actions = {
})
if (!filteredList.length) return commit('setPlayMusicInfo', null)
const playInfo = getters.playInfo
let currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex])
const currentMusic = currentList[playInfo.listPlayIndex]
let currentIndex = filteredList.findIndex(m => m.songmid == currentMusic.songmid)
if (currentIndex == -1) currentIndex = 0
let nextIndex = currentIndex
if (!playInfo.isTempPlay) {
@@ -334,7 +335,8 @@ const actions = {
if (!filteredList.length) return commit('setPlayMusicInfo', null)
const playInfo = getters.playInfo
const currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex])
const currentMusic = currentList[playInfo.listPlayIndex]
let currentIndex = filteredList.findIndex(m => m.songmid == currentMusic.songmid)
let nextIndex = currentIndex
switch (rootState.setting.player.togglePlayMethod) {
case 'listLoop':
@@ -433,7 +435,7 @@ const mutations = {
playIndex = -1
} else {
let listId = playMusicInfo.listId
if (listId != '__temp__' && !playMusicInfo.isTempPlay && listId === state.listInfo.id) playIndex = state.listInfo.list.indexOf(playMusicInfo.musicInfo)
if (listId != '__temp__' && !playMusicInfo.isTempPlay && listId === state.listInfo.id) playIndex = state.listInfo.list.findIndex(m => m.songmid == playMusicInfo.musicInfo.songmid)
}
state.playMusicInfo = playMusicInfo
+12 -11
View File
@@ -355,7 +355,7 @@ export default {
'removeUserList',
'setListScroll',
'setList',
'sortList',
'setMusicPosition',
]),
...mapActions('songList', ['getListDetailAll']),
...mapActions('leaderboard', {
@@ -576,7 +576,7 @@ export default {
this.setPlayList({ list: this.listData, index })
},
handleRemove(index) {
this.listRemove({ id: this.listId, index })
this.listRemove({ listId: this.listId, id: this.list[index].songmid })
},
handleListBtnClick(info) {
switch (info.action) {
@@ -677,8 +677,9 @@ export default {
let dom_target = this.$refs.dom_lists_list.querySelector('.' + this.$style.editing)
if (dom_target) dom_target.classList.remove(this.$style.editing)
let name = event.target.value.trim()
if (name.length) return this.setUserListName({ index, name })
event.target.value = this.userList[index].name
const targetList = this.userList[index]
if (name.length) return this.setUserListName({ id: targetList.id, name })
event.target.value = targetList.name
},
handleListsCreate(event) {
if (event.target.readonly) return
@@ -774,13 +775,13 @@ export default {
this.handleSyncSourceList(index)
break
case 'moveup':
this.moveupUserList(index)
this.moveupUserList({ id: this.userList[index].id })
break
case 'movedown':
this.movedownUserList(index)
this.movedownUserList({ id: this.userList[index].id })
break
case 'remove':
this.removeUserList(index)
this.removeUserList({ id: this.userList[index].id })
break
}
},
@@ -870,7 +871,7 @@ export default {
break
case 'remove':
if (this.selectdListDetailData.length) {
this.listRemoveMultiple({ id: this.listId, list: this.selectdListDetailData })
this.listRemoveMultiple({ listId: this.listId, ids: this.selectdListDetailData.map(m => m.songmid) })
this.removeAllSelectListDetail()
} else {
this.handleRemove(index)
@@ -929,10 +930,10 @@ export default {
},
handleSortMusicInfo(num) {
num = Math.min(num, this.list.length)
this.sortList({
this.setMusicPosition({
id: this.listId,
sortNum: num,
musicInfos: this.selectdListDetailData.length ? [...this.selectdListDetailData] : [this.musicInfo],
position: num,
list: this.selectdListDetailData.length ? [...this.selectdListDetailData] : [this.musicInfo],
})
this.removeAllSelectListDetail()
this.isShowListSortModal = false
+82 -1
View File
@@ -150,6 +150,21 @@ div(:class="$style.main")
div
material-checkbox(id="setting_download_isDownloadLrc" v-model="current_setting.download.isDownloadLrc" :label="$t('view.setting.is_enable')")
dt#sync {{$t('view.setting.sync')}}
dd
material-checkbox(id="setting_sync_enable" v-model="current_setting.sync.enable" @change="handleSyncChange('enable')" :label="syncEnableTitle")
div
p.small {{$t('view.setting.sync_auth_code', { code: sync.status.code || '' })}}
p.small {{$t('view.setting.sync_address', { address: sync.status.address.join(', ') || '' })}}
p.small {{$t('view.setting.sync_device', { devices: syncDevices })}}
p
material-btn(:class="$style.btn" min :disabled="!current_setting.sync.enable" @click="handleRefreshSyncCode") {{$t('view.setting.sync_refresh_code')}}
dd
h3#sync_port {{$t('view.setting.sync_port')}}
div
p
material-input(:class="$style.gapLeft" v-model.trim="current_setting.sync.port" @change="handleSyncChange('port')" :placeholder="$t('view.setting.sync_port_tip')")
dt#hot_key {{$t('view.setting.hot_key')}}
dd
h3#hot_key_local_title {{$t('view.setting.hot_key_local_title')}}
@@ -295,7 +310,7 @@ import {
getSetting,
saveSetting,
} from '../utils'
import { rendererSend, rendererInvoke, NAMES } from '@common/ipc'
import { rendererSend, rendererInvoke, rendererOn, NAMES, rendererOff } from '@common/ipc'
import { mergeSetting, isMac } from '../../common/utils'
import apiSourceInfo from '../utils/music/api-source-info'
import fs from 'fs'
@@ -410,6 +425,21 @@ export default {
},
]
},
syncEnableTitle() {
let title = this.$t('view.setting.sync_enable')
if (this.sync.status.message) {
title += ` [${this.sync.status.message}]`
}
// else if (this.sync.status.address.length) {
// // title += ` [${this.sync.status.address.join(', ')}]`
// }
return title
},
syncDevices() {
return this.sync.status.devices.length
? this.sync.status.devices.map(d => `${d.deviceName} (${d.clientId.substring(0, 5)})`).join(', ')
: ''
},
},
data() {
return {
@@ -474,6 +504,10 @@ export default {
isToTray: false,
themeId: 0,
},
sync: {
enable: false,
port: '23332',
},
windowSizeId: 1,
langId: 'cns',
themeId: 0,
@@ -608,6 +642,15 @@ export default {
},
isDisabledResourceCacheClear: false,
isDisabledListCacheClear: false,
sync: {
status: {
status: false,
message: '',
address: [],
code: '',
devices: [],
},
},
}
},
watch: {
@@ -665,6 +708,7 @@ export default {
window.eventHub.$off(eventBaseName.set_config, this.handleUpdateSetting)
window.eventHub.$off(eventBaseName.key_down, this.handleKeyDown)
window.eventHub.$off(eventBaseName.set_hot_key_config, this.handleUpdateHotKeyConfig)
this.syncUnInit()
if (this.current_setting.network.proxy.enable && !this.current_setting.network.proxy.host) window.globalObj.proxy.enable = false
},
@@ -684,6 +728,7 @@ export default {
this.current_hot_key = window.appHotKeyConfig
this.initHotKeyConfig()
this.getHotKeyStatus()
this.syncInit()
},
// initTOC() {
// const list = this.$refs.dom_setting_list.children
@@ -1151,6 +1196,42 @@ export default {
return status
},
setStatus(e, status) {
this.sync.status.status = status.status
this.sync.status.message = status.message
this.sync.status.address = status.address
this.sync.status.code = status.code
this.sync.status.devices = status.devices
},
syncInit() {
rendererInvoke(NAMES.mainWindow.sync_get_status).then(status => {
this.sync.status.status = status.status
this.sync.status.message = status.message
this.sync.status.address = status.address
this.sync.status.code = status.code
this.sync.status.devices = status.devices
})
rendererOn(NAMES.mainWindow.sync_status, this.setStatus)
},
syncUnInit() {
rendererOff(NAMES.mainWindow.sync_status, this.setStatus)
},
handleSyncChange(action) {
switch (action) {
case 'port':
if (!this.current_setting.sync.enable) return
case 'enable':
rendererInvoke(NAMES.mainWindow.sync_enable, {
enable: this.current_setting.sync.enable,
port: this.current_setting.sync.port,
})
window.globalObj.sync.enable = this.current_setting.sync.enable
break
}
},
handleRefreshSyncCode() {
rendererInvoke(NAMES.mainWindow.sync_generate_code)
},
},
}
</script>