From 33993333609c81a18289259da57350f25eea17eb Mon Sep 17 00:00:00 2001 From: lyswhut Date: Wed, 1 Mar 2023 18:44:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lang/en-us.json | 4 +- src/lang/zh-cn.json | 2 +- src/lang/zh-tw.json | 2 +- src/main/modules/sync/client/client.ts | 52 ++++++++++++++----- src/main/modules/sync/client/index.ts | 15 +++--- src/main/modules/sync/data.ts | 14 +++-- src/main/modules/sync/server/modules/list.ts | 10 ++-- src/main/modules/sync/server/server.ts | 20 +++++-- src/main/modules/sync/server/utils.ts | 9 +--- src/main/utils/store.ts | 2 +- .../components/layout/SyncAuthCodeModal.vue | 1 + src/renderer/core/useApp/useSync.ts | 2 +- src/renderer/store/setting.ts | 2 +- src/renderer/views/List/MusicList/index.vue | 4 +- 14 files changed, 89 insertions(+), 50 deletions(-) diff --git a/src/lang/en-us.json b/src/lang/en-us.json index 9c76f6b7..6b2bea51 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -523,14 +523,14 @@ "sync__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.", "sync__other_label": "Other", "sync__other_tip": "Other: ", - "sync__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.", + "sync__other_tip_desc": "\"Cancel Sync\" will directly disconnect the two parties.", "sync__overwrite": "Full coverage", "sync__overwrite_btn_cancel": "Cancel sync", "sync__overwrite_btn_local_remote": "Local list Overwrite remote list", "sync__overwrite_btn_none": "Only use real-time synchronization", "sync__overwrite_btn_remote_local": "Remote list Overwrite local list", "sync__overwrite_label": "Cover", - "sync__overwrite_tip": "Cover: ", + "sync__overwrite_tip": "Over: ", "sync__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.", "sync__title": "Choose how to synchronize the list with {name}", "sync_status_disabled": "not connected", diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index f2a34789..f48ffa7e 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -526,7 +526,7 @@ "sync__merge_tip_desc": "将两边的列表合并到一起,相同的歌曲将被去掉(去掉的是被合并者的歌曲),不同的歌曲将被添加。", "sync__other_label": "其他", "sync__other_tip": "其他:", - "sync__other_tip_desc": "“仅使用实时同步功能”将不修改双方的列表,仅实时同步操作;“取消同步”将直接断开双方的连接。", + "sync__other_tip_desc": "“取消同步”将直接断开双方的连接。", "sync__overwrite": "完全覆盖", "sync__overwrite_btn_cancel": "取消同步", "sync__overwrite_btn_local_remote": "本机列表 覆盖 远程列表", diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 4d383aaa..1b29f243 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -523,7 +523,7 @@ "sync__merge_tip_desc": "將兩邊的列表合併到一起,相同的歌曲將被去掉(去掉的是被合併者的歌曲),不同的歌曲將被添加。", "sync__other_label": "其他", "sync__other_tip": "其他:", - "sync__other_tip_desc": "“僅使用實時同步功能”將不修改雙方的列表,僅實時同步操作;“取消同步”將直接斷開雙方的連接。", + "sync__other_tip_desc": "“取消同步”將直接斷開雙方的連接。", "sync__overwrite": "完全覆蓋", "sync__overwrite_btn_cancel": "取消同步", "sync__overwrite_btn_local_remote": "本機列表 覆蓋 遠程列表", diff --git a/src/main/modules/sync/client/client.ts b/src/main/modules/sync/client/client.ts index 0ef50392..ea0bff2a 100644 --- a/src/main/modules/sync/client/client.ts +++ b/src/main/modules/sync/client/client.ts @@ -38,6 +38,7 @@ const handleConnection = (socket: LX.Sync.Client.Socket) => { const heartbeatTools = { failedNum: 0, + maxTryNum: 3, pingTimeout: null as NodeJS.Timeout | null, delayRetryTimeout: null as NodeJS.Timeout | null, handleOpen() { @@ -64,16 +65,21 @@ const heartbeatTools = { // client = null if (!client) return - if (this.failedNum > 3) throw new Error('connect error') + if (++this.failedNum > this.maxTryNum) { + this.failedNum = 0 + throw new Error('connect error') + } this.delayRetryTimeout = setTimeout(() => { this.delayRetryTimeout = null if (!client) return console.log(dateFormat(new Date()), 'reconnnect...') + sendSyncStatus({ + status: false, + message: `Try reconnnect... (${this.failedNum}/${this.maxTryNum})`, + }) connect(client.data.urlInfo, client.data.keyInfo) }, 2000) - - this.failedNum++ }, clearTimeout() { if (this.delayRetryTimeout) { @@ -176,23 +182,40 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client message: '', }) }).catch(err => { - console.log(err) - log.r_error(err.stack) - sendSyncStatus({ - status: false, - message: err.message, - }) + if (err.message == 'closed') { + sendSyncStatus({ + status: false, + message: '', + }) + } else { + console.log(err) + log.r_error(err.stack) + sendSyncStatus({ + status: false, + message: err.message, + }) + } }) }) - client.addEventListener('close', () => { - sendSyncStatus({ - status: false, - message: '', - }) + client.addEventListener('close', ({ code }) => { const err = new Error('closed') for (const handler of closeEvents) void handler(err) closeEvents = [] events = {} + switch (code) { + case SYNC_CLOSE_CODE.normal: + // case SYNC_CLOSE_CODE.failed: + sendSyncStatus({ + status: false, + message: '', + }) + } + }) + client.addEventListener('error', ({ message }) => { + sendSyncStatus({ + status: false, + message, + }) }) } @@ -202,6 +225,7 @@ export const disconnect = async() => { client.close(SYNC_CLOSE_CODE.normal) client = null heartbeatTools.clearTimeout() + heartbeatTools.failedNum = 0 } export const getStatus = (): LX.Sync.ClientStatus => status diff --git a/src/main/modules/sync/client/index.ts b/src/main/modules/sync/client/index.ts index a12ee68a..2c0bcda6 100644 --- a/src/main/modules/sync/client/index.ts +++ b/src/main/modules/sync/client/index.ts @@ -5,13 +5,18 @@ import { SYNC_CODE } from '@common/constants' import log from '../log' import { parseUrl } from './utils' +let connectId = 0 + const handleConnect = async(host: string, authCode?: string) => { // const hostInfo = await getSyncHost() // console.log(hostInfo) // if (!hostInfo || !hostInfo.host || !hostInfo.port) throw new Error(SYNC_CODE.unknownServiceAddress) + const id = connectId const urlInfo = parseUrl(host) await disconnectServer(false) + if (id != connectId) return const keyInfo = await handleAuth(urlInfo, authCode) + if (id != connectId) return socketConnect(urlInfo, keyInfo) } const handleDisconnect = async() => { @@ -23,12 +28,9 @@ const connectServer = async(host: string, authCode?: string) => { status: false, message: SYNC_CODE.connecting, }) - return handleConnect(host, authCode).then(() => { - sendSyncStatus({ - status: true, - message: '', - }) - }).catch(async err => { + const id = connectId + return handleConnect(host, authCode).catch(async err => { + if (id != connectId) return sendSyncStatus({ status: false, message: err.message, @@ -49,6 +51,7 @@ const connectServer = async(host: string, authCode?: string) => { const disconnectServer = async(isResetStatus = true) => handleDisconnect().then(() => { log.info('disconnect...') if (isResetStatus) { + connectId++ sendSyncStatus({ status: false, message: '', diff --git a/src/main/modules/sync/data.ts b/src/main/modules/sync/data.ts index f7b83f73..4c082f1b 100644 --- a/src/main/modules/sync/data.ts +++ b/src/main/modules/sync/data.ts @@ -9,15 +9,15 @@ import log from './log' export const getSyncAuthKey = async(serverId: string) => { const store = getStore(STORE_NAMES.SYNC) - const keys = store.get('syncAuthKey') as Record | null + const keys = store.get('syncAuthKey_v3') as Record | null if (!keys) return null return keys[serverId] ?? null } export const setSyncAuthKey = async(serverId: string, info: LX.Sync.ClientKeyInfo) => { const store = getStore(STORE_NAMES.SYNC) - let keys: Record = (store.get('syncAuthKey') as Record | null) ?? {} + let keys: Record = (store.get('syncAuthKey_v3') as Record | null) ?? {} keys[serverId] = info - store.set('syncAuthKey', keys) + store.set('syncAuthKey_v3', keys) } let syncHost: string @@ -73,7 +73,7 @@ const devicesInfo: DevicesInfo = { serverId: '', clients: {}, snapshotInfo: { la let deviceKeys: string[] = [] const saveDevicesInfoThrottle = throttle(() => { const store = getStore(STORE_NAMES.SYNC) - store.set('keys', devicesInfo.clients) + store.set('clients', devicesInfo.clients) }) const initDeviceInfo = () => { @@ -82,7 +82,8 @@ const initDeviceInfo = () => { if (serverId) devicesInfo.serverId = serverId else { devicesInfo.serverId = randomBytes(4 * 4).toString('base64') - saveDevicesInfoThrottle() + const store = getStore(STORE_NAMES.SYNC) + store.set('serverId', devicesInfo.serverId) } const devices = store.get('clients') as DevicesInfo['clients'] | undefined if (devices) devicesInfo.clients = devices @@ -155,6 +156,7 @@ export const saveSnapshotInfo = (info: SnapshotInfo) => { } export const getSnapshot = async(name: string) => { + console.log('getSnapshot', name) const filePath = path.join(global.lxDataPath, `snapshot_${name}`) let listData: LX.Sync.ListData try { @@ -166,6 +168,7 @@ export const getSnapshot = async(name: string) => { return listData } export const saveSnapshot = async(name: string, data: string) => { + console.log('saveSnapshot', name) const filePath = path.join(global.lxDataPath, `snapshot_${name}`) return fs.promises.writeFile(filePath, data).catch((err) => { log.error(err) @@ -173,6 +176,7 @@ export const saveSnapshot = async(name: string, data: string) => { }) } export const removeSnapshot = async(name: string) => { + console.log('removeSnapshot', name) const filePath = path.join(global.lxDataPath, `snapshot_${name}`) return fs.promises.unlink(filePath).catch((err) => { log.error(err) diff --git a/src/main/modules/sync/server/modules/list.ts b/src/main/modules/sync/server/modules/list.ts index e84f9794..2a01925b 100644 --- a/src/main/modules/sync/server/modules/list.ts +++ b/src/main/modules/sync/server/modules/list.ts @@ -2,8 +2,8 @@ // import { sendSyncActionList } from '@main/modules/winMain' import { SYNC_CLOSE_CODE } from '@common/constants' import { updateDeviceSnapshotKey } from '../../data' -import { handleRemoteListAction } from '../../utils' -import { createSnapshot, encryptMsg } from '../utils' +import { handleRemoteListAction, registerListActionEvent } from '../../utils' +import { createSnapshot, encryptMsg, getCurrentListInfoKey } from '../utils' let wss: LX.Sync.Server.SocketServer | null let removeListener: (() => void) | null @@ -29,16 +29,16 @@ const broadcast = async(key: string, data: any, excludeIds: string[] = []) => { } } -export const sendListAction = async(action: LX.Sync.ActionList) => { +const sendListAction = async(action: LX.Sync.ActionList) => { console.log('sendListAction', action.action) // io.sockets - await broadcast('list:sync:action', action) + await broadcast(await getCurrentListInfoKey(), action) } export const registerListHandler = (_wss: LX.Sync.Server.SocketServer, socket: LX.Sync.Server.Socket) => { if (!wss) { wss = _wss - // removeListener = registerListActionEvent() + removeListener = registerListActionEvent(sendListAction) } socket.onRemoteEvent('list:sync:action', (action) => { diff --git a/src/main/modules/sync/server/server.ts b/src/main/modules/sync/server/server.ts index 03a0664a..3961417e 100644 --- a/src/main/modules/sync/server/server.ts +++ b/src/main/modules/sync/server/server.ts @@ -19,6 +19,7 @@ let status: LX.Sync.ServerStatus = { code: '', devices: [], } +let stopingServer = false const codeTools: { timeout: NodeJS.Timer | null @@ -148,6 +149,7 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis // const events = new Map void>>() // const events = new Map void>>() let events: Partial<{ [K in keyof LX.Sync.ActionSyncType]: Array<(data: LX.Sync.ActionSyncType[K]) => void> }> = {} + let closeEvents: Array<(err: Error) => (void | Promise)> = [] socket.addEventListener('message', ({ data }) => { if (typeof data === 'string') { let syncData: LX.Sync.ActionSync @@ -167,11 +169,9 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis }) socket.addEventListener('close', () => { const err = new Error('closed') - for (const handler of Object.values(events).flat()) { - // @ts-expect-error - handler(err, null) - } + for (const handler of closeEvents) void handler(err) events = {} + closeEvents = [] if (!status.devices.length) handleUnconnection() log.info('deconnection', socket.keyInfo.deviceName) }) @@ -186,6 +186,12 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis eventArr!.splice(eventArr!.indexOf(handler), 1) } } + socket.onClose = function(handler: typeof closeEvents[number]) { + closeEvents.push(handler) + return () => { + closeEvents.splice(closeEvents.indexOf(handler), 1) + } + } socket.sendData = function(eventName, data, callback) { socket.send(encryptMsg(socket.keyInfo, JSON.stringify({ action: eventName, data })), callback) } @@ -248,6 +254,7 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis const handleStopServer = async() => new Promise((resolve, reject) => { if (!wss) return + for (const client of wss.clients) client.close(SYNC_CLOSE_CODE.normal) wss.close() wss = null httpServer.close((err) => { @@ -271,6 +278,9 @@ export const stopServer = async() => { return } console.log('stoping sync server...') + status.message = 'stoping...' + sendServerStatus(status) + stopingServer = true await handleStopServer().then(() => { console.log('sync server stoped') status.status = false @@ -281,12 +291,14 @@ export const stopServer = async() => { console.log(err) status.message = err.message }).finally(() => { + stopingServer = false sendServerStatus(status) }) } export const startServer = async(port: number) => { console.log('status.status', status.status) + if (stopingServer) return if (status.status) await handleStopServer() log.info('starting sync server') diff --git a/src/main/modules/sync/server/utils.ts b/src/main/modules/sync/server/utils.ts index b57c1c53..364299b2 100644 --- a/src/main/modules/sync/server/utils.ts +++ b/src/main/modules/sync/server/utils.ts @@ -52,11 +52,6 @@ export const createSnapshot = async() => { export const getCurrentListInfoKey = async() => { - if (!snapshotInfo) snapshotInfo = getSnapshotInfo() - if (snapshotInfo.latest) { - return snapshotInfo.latest - } - snapshotInfo.latest = toMD5(JSON.stringify(await getLocalListData())) - saveSnapshotInfo(snapshotInfo) - return snapshotInfo.latest + // if (!snapshotInfo) snapshotInfo = getSnapshotInfo() + return createSnapshot() } diff --git a/src/main/utils/store.ts b/src/main/utils/store.ts index 7a128490..43bb6943 100644 --- a/src/main/utils/store.ts +++ b/src/main/utils/store.ts @@ -28,7 +28,7 @@ export default (name: string, isIgnoredError = true, isShowErrorAlert = true): S const backPath = join(global.lxDataPath, name + '.json.bak') - fs.copyFileSync(join(global.lxDataPath, name + '.json'), backPath) + fs.renameSync(join(global.lxDataPath, name + '.json'), backPath) if (isShowErrorAlert) { dialog.showMessageBoxSync({ type: 'error', diff --git a/src/renderer/components/layout/SyncAuthCodeModal.vue b/src/renderer/components/layout/SyncAuthCodeModal.vue index 4c4d754b..dd67dd35 100644 --- a/src/renderer/components/layout/SyncAuthCodeModal.vue +++ b/src/renderer/components/layout/SyncAuthCodeModal.vue @@ -35,6 +35,7 @@ export default { const handleSubmit = () => { let code = verify() if (code == '') return + authCode.value = '' handleClose() sendSyncAction({ action: 'enable_client', diff --git a/src/renderer/core/useApp/useSync.ts b/src/renderer/core/useApp/useSync.ts index 792b22f3..7fe8d8ed 100644 --- a/src/renderer/core/useApp/useSync.ts +++ b/src/renderer/core/useApp/useSync.ts @@ -6,7 +6,7 @@ import { SYNC_CODE } from '@common/constants' export default () => { const handleSyncList = (event: LX.Sync.SyncMainWindowActions) => { - console.log(event) + // console.log(event) switch (event.action) { case 'select_mode': sync.deviceName = event.data diff --git a/src/renderer/store/setting.ts b/src/renderer/store/setting.ts index 4269f2e8..57c63515 100644 --- a/src/renderer/store/setting.ts +++ b/src/renderer/store/setting.ts @@ -21,7 +21,7 @@ export const mergeSetting = (newSetting: Partial) => { } export const updateSetting = window.lxData.updateSetting = (setting: Partial) => { - console.warn(setting) + // console.warn(setting) void saveSetting(setting) } diff --git a/src/renderer/views/List/MusicList/index.vue b/src/renderer/views/List/MusicList/index.vue index fb96f935..72412821 100644 --- a/src/renderer/views/List/MusicList/index.vue +++ b/src/renderer/views/List/MusicList/index.vue @@ -140,10 +140,10 @@ export default { scrollIndex = _scrollIndex isAnimation = _isAnimation if (isAnimation) restoreScroll(scrollIndex, isAnimation) - console.log('handleRestoreScroll', scrollIndex, isAnimation) + // console.log('handleRestoreScroll', scrollIndex, isAnimation) } const onLoadedList = () => { - console.log('restoreScroll', scrollIndex, isAnimation) + // console.log('restoreScroll', scrollIndex, isAnimation) restoreScroll(scrollIndex, isAnimation) }