From 1de087eac79c2e38442a4db6093c31c3b5f48db9 Mon Sep 17 00:00:00 2001 From: lyswhut Date: Sat, 30 Dec 2023 12:31:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E7=8A=B6=E6=80=81=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- publish/changeLog.md | 1 + src/common/types/download_list.d.ts | 2 + src/common/utils/download/Downloader.ts | 38 ++++++++++++++++--- src/common/utils/download/index.ts | 1 + src/lang/en-us.json | 1 + src/lang/zh-cn.json | 1 + src/lang/zh-tw.json | 1 + .../dbService/modules/download/index.ts | 1 + src/renderer/store/download/action.ts | 12 +++++- src/renderer/worker/download/download.ts | 1 + src/renderer/worker/download/utils.ts | 1 + 11 files changed, 52 insertions(+), 8 deletions(-) diff --git a/publish/changeLog.md b/publish/changeLog.md index e238edab96..758e4b33d5 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -21,6 +21,7 @@ - 优化搜索框交互逻辑,防止鼠标操作时意外搜索候选列表的内容 - 添加对wy源某些歌曲有问题的歌词进行修复 - 改进本地音乐在线信息的匹配机制 +- 优化任务下载状态显示,现在下载时若数据传输完成但数据写入未完成时会显示相应的状态 ### 修复 diff --git a/src/common/types/download_list.d.ts b/src/common/types/download_list.d.ts index 270f8e19ab..94b1cf70c9 100644 --- a/src/common/types/download_list.d.ts +++ b/src/common/types/download_list.d.ts @@ -21,6 +21,7 @@ declare global { speed: string downloaded: number total: number + writeQueue: number } interface DownloadTaskActionBase { @@ -50,6 +51,7 @@ declare global { total: number progress: number speed: string + writeQueue: number metadata: { musicInfo: LX.Music.MusicInfoOnline url: string | null diff --git a/src/common/utils/download/Downloader.ts b/src/common/utils/download/Downloader.ts index 3957c9b092..975a0f5061 100644 --- a/src/common/utils/download/Downloader.ts +++ b/src/common/utils/download/Downloader.ts @@ -8,6 +8,7 @@ import { request, type Options as RequestOptions } from './request' export interface Options { forceResume: boolean + timeout: number requestOptions: RequestOptions } @@ -23,6 +24,7 @@ const defaultRequestOptions: Options['requestOptions'] = { } const defaultOptions: Options = { forceResume: true, + timeout: 20_000, requestOptions: { ...defaultRequestOptions }, } @@ -41,6 +43,7 @@ class Task extends EventEmitter { private redirectNum = 0 private dataWriteQueueLength = 0 private closeWaiting = false + private timeout: null | NodeJS.Timeout = null constructor(url: string, savePath: string, filename: string, options: Partial = {}) { @@ -69,6 +72,8 @@ class Task extends EventEmitter { this.progress.speed = 0 this.dataWriteQueueLength = 0 this.closeWaiting = false + this.__clearTimeout() + this.__startTimeout() if (startByte) this.requestOptions.headers!.range = `bytes=${startByte}-${endByte}` if (!path) return @@ -144,6 +149,7 @@ class Task extends EventEmitter { } this.status = STATUS.failed this.emit('fail', response) + this.__clearTimeout() this.__closeRequest() void this.__closeWriteStream() return @@ -156,6 +162,7 @@ class Task extends EventEmitter { return } this.status = STATUS.running + this.__startTimeout() response .on('data', this.__handleWriteData.bind(this)) .on('error', err => { this.__handleError(err) }) @@ -222,6 +229,7 @@ class Task extends EventEmitter { __handleComplete() { if (this.status == STATUS.error) return + this.__clearTimeout() void this.__closeWriteStream().then(() => { if (this.progress.downloaded == this.progress.total) { this.status = STATUS.completed @@ -237,6 +245,7 @@ class Task extends EventEmitter { __handleError(error: Error) { if (this.status == STATUS.error) return this.status = STATUS.error + this.__clearTimeout() this.__closeRequest() void this.__closeWriteStream() if (error.message == 'aborted') return @@ -304,9 +313,11 @@ class Task extends EventEmitter { return } this.dataWriteQueueLength++ + this.__startTimeout() this.__calculateProgress(chunk.length) this.ws.write(chunk, err => { this.dataWriteQueueLength-- + if (this.status == STATUS.running) this.__calculateProgress(0) if (err) { console.log(err) this.__handleError(err) @@ -322,24 +333,38 @@ class Task extends EventEmitter { let chunkLen = chunk.length let isOk if (chunkLen >= resumeLastChunkLen) { - isOk = chunk.slice(0, resumeLastChunkLen).toString('hex') === this.resumeLastChunk!.toString('hex') + isOk = chunk.subarray(0, resumeLastChunkLen).toString('hex') === this.resumeLastChunk!.toString('hex') if (!isOk) return null this.resumeLastChunk = null - return chunk.slice(resumeLastChunkLen) + return chunk.subarray(resumeLastChunkLen) } else { - isOk = chunk.slice(0, chunkLen).toString('hex') === this.resumeLastChunk!.slice(0, chunkLen).toString('hex') + isOk = chunk.subarray(0, chunkLen).toString('hex') === this.resumeLastChunk!.subarray(0, chunkLen).toString('hex') if (!isOk) return null - this.resumeLastChunk = this.resumeLastChunk!.slice(chunkLen) - return chunk.slice(chunkLen) + this.resumeLastChunk = this.resumeLastChunk!.subarray(chunkLen) + return chunk.subarray(chunkLen) } } async __handleStop() { + this.__clearTimeout() this.__closeRequest() return this.__closeWriteStream() } + private __clearTimeout() { + if (!this.timeout) return + clearTimeout(this.timeout) + this.timeout = null + } + + private __startTimeout() { + this.__clearTimeout() + this.timeout = setTimeout(() => { + this.__handleError(new Error('download timeout')) + }, this.options.timeout) + } + __calculateProgress(receivedBytes: number) { const currentTime = performance.now() const elaspsedTime = currentTime - this.statsEstimate.time @@ -350,7 +375,7 @@ class Task extends EventEmitter { // emit the progress every second or if finished - if (progress.downloaded === progress.total || elaspsedTime > 1000) { + if ((progress.downloaded === progress.total && this.dataWriteQueueLength == 0) || elaspsedTime > 1000) { this.statsEstimate.time = currentTime this.statsEstimate.bytes = progress.downloaded - this.statsEstimate.prevBytes this.statsEstimate.prevBytes = progress.downloaded @@ -359,6 +384,7 @@ class Task extends EventEmitter { downloaded: progress.downloaded, progress: progress.progress, speed: this.statsEstimate.bytes, + writeQueue: this.dataWriteQueueLength, }) } } diff --git a/src/common/utils/download/index.ts b/src/common/utils/download/index.ts index 85e6b4cc29..d6eba61d69 100644 --- a/src/common/utils/download/index.ts +++ b/src/common/utils/download/index.ts @@ -74,6 +74,7 @@ export const createDownload = ({ speed, downloaded: stats.downloaded, total: stats.total, + writeQueue: stats.writeQueue, }) // if (debugDownload) { // const downloaded = sizeFormate(stats.downloaded) diff --git a/src/lang/en-us.json b/src/lang/en-us.json index 32b740fd95..b3dfb928ac 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -71,6 +71,7 @@ "download_status_error_write": "The song save location is occupied or does not have write permission, please try to change the song save directory or restart the software or restart the computer, the error details:", "download_status_start": "start download", "download_status_url_geting": "Getting music link...", + "download_status_write_queue": "Data is being written ({num})", "duplicate_list_tip": "You have favorited this list [{name}] before, do you need to update the songs in it?", "export": "Export", "fullscreen_exit": "Exit Full Screen", diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index 2ff664d44b..bd78a1041a 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -71,6 +71,7 @@ "download_status_error_write": "歌曲保存位置被占用或没有写入权限,请尝试更改歌曲保存目录或重启软件或重启电脑,错误详情:", "download_status_start": "开始下载", "download_status_url_geting": "音乐链接获取中...", + "download_status_write_queue": "数据写入中({num})", "duplicate_list_tip": "你之前已收藏过该列表 [{name}],是否需要更新里面的歌曲?", "export": "导出", "fullscreen_exit": "退出全屏", diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 8b186ac769..96bdac0bf9 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -71,6 +71,7 @@ "download_status_error_write": "歌曲儲存位置被佔用或沒有寫入權限,請嘗試變更歌曲儲存目錄或重新啟動軟體或重新啟動電腦,錯誤詳情:", "download_status_start": "開始下載", "download_status_url_geting": "音樂連結獲取中...", + "download_status_write_queue": "資料寫入中({num})", "duplicate_list_tip": "你之前已收藏過該清單 [{name}],是否需要更新裡面的歌曲?", "export": "匯出", "fullscreen_exit": "退出全螢幕", diff --git a/src/main/worker/dbService/modules/download/index.ts b/src/main/worker/dbService/modules/download/index.ts index 4a93de4047..43388557dc 100644 --- a/src/main/worker/dbService/modules/download/index.ts +++ b/src/main/worker/dbService/modules/download/index.ts @@ -41,6 +41,7 @@ const initDownloadList = () => { total: item.progress_total, progress: item.progress_total ? parseInt((item.progress_downloaded / item.progress_total).toFixed(2)) * 100 : 0, speed: '', + writeQueue: 0, metadata: { musicInfo, url: item.url, diff --git a/src/renderer/store/download/action.ts b/src/renderer/store/download/action.ts index 02db7e0943..60ee04318a 100644 --- a/src/renderer/store/download/action.ts +++ b/src/renderer/store/download/action.ts @@ -82,10 +82,17 @@ const updateFilePath = (downloadInfo: LX.Download.ListItem, filePath: string) => } const setProgress = (downloadInfo: LX.Download.ListItem, progress: LX.Download.ProgressInfo) => { - downloadInfo.progress = progress.progress downloadInfo.total = progress.total downloadInfo.downloaded = progress.downloaded - downloadInfo.speed = progress.speed + downloadInfo.writeQueue = progress.writeQueue + if (progress.progress == 100) { + downloadInfo.speed = '' + downloadInfo.progress = 99.99 + setStatusText(downloadInfo, window.i18n.t('download_status_write_queue', { num: progress.writeQueue })) + } else { + downloadInfo.speed = progress.speed + downloadInfo.progress = progress.progress + } throttleUpdateTask([downloadInfo]) } @@ -248,6 +255,7 @@ const handleStartTask = async(downloadInfo: LX.Download.ListItem) => { setStatus(downloadInfo, DOWNLOAD_STATUS.RUN) break case 'complete': + downloadInfo.progress = 100 saveMeta(downloadInfo) downloadLyric(downloadInfo) void window.lx.worker.download.removeTask(downloadInfo.id) diff --git a/src/renderer/worker/download/download.ts b/src/renderer/worker/download/download.ts index 175df9bbb8..ec1c451f80 100644 --- a/src/renderer/worker/download/download.ts +++ b/src/renderer/worker/download/download.ts @@ -205,6 +205,7 @@ const createTask = async(downloadInfo: LX.Download.ListItem, savePath: string, s downloadInfo.downloaded = status.downloaded downloadInfo.progress = status.progress downloadInfo.speed = status.speed + downloadInfo.writeQueue = status.writeQueue sendAction(downloadInfo.id, { action: 'progress', data: status }) // console.log(status) }, diff --git a/src/renderer/worker/download/utils.ts b/src/renderer/worker/download/utils.ts index 97434e55ba..b47de065a6 100644 --- a/src/renderer/worker/download/utils.ts +++ b/src/renderer/worker/download/utils.ts @@ -80,6 +80,7 @@ export const createDownloadInfo = (musicInfo: LX.Music.MusicInfoOnline, type: LX total: 0, progress: 0, speed: '', + writeQueue: 0, metadata: { musicInfo, url: null,