From 86480c11a1f170e246689200b6616b833922d3d2 Mon Sep 17 00:00:00 2001 From: Inrixia Date: Wed, 26 Jun 2024 06:33:13 +1200 Subject: [PATCH] SongDownloader - Working native download progress --- plugins/SongDownloader/src/index.ts | 14 ++++++++--- plugins/_lib/nativeBridge/index.ts | 3 ++- .../native/downloadTrack.native.ts | 25 ++++++++++++++++--- .../native/request/helpers.native.ts | 3 ++- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/plugins/SongDownloader/src/index.ts b/plugins/SongDownloader/src/index.ts index 0894cc9..b9309cd 100644 --- a/plugins/SongDownloader/src/index.ts +++ b/plugins/SongDownloader/src/index.ts @@ -11,7 +11,7 @@ import safeUnload from "@inrixia/lib/safeUnload"; import { settings } from "./Settings"; import { ContextMenu } from "@inrixia/lib/ContextMenu"; import { PlaybackInfoCache } from "@inrixia/lib/Caches/PlaybackInfoCache"; -import { downloadTrackStream, openDialog, saveDialog } from "@inrixia/lib/nativeBridge"; +import { startTrackDownload, openDialog, saveDialog, getDownloadProgress } from "@inrixia/lib/nativeBridge"; export { Settings } from "./Settings"; type DownloadButtoms = Record; @@ -104,8 +104,14 @@ const downloadTrack = async (track: TrackItem, updateMethods: ButtonMethods, fil const dialogResult = await saveDialog({ defaultPath, filters: [{ name: "", extensions: [parseExtension(fileName) ?? "*"] }] }); filePath = dialogResult?.filePath; } - console.log(filePath); updateMethods.set("Downloading..."); - await downloadTrackStream(playbackInfo, filePath); - console.log("Done!"); + let downloadEnded = false; + const downloadComplete = startTrackDownload(playbackInfo, filePath).finally(() => (downloadEnded = true)); + const updateDownloadProgress = async () => { + const downloadProgress = await getDownloadProgress(filePath); + if (downloadProgress !== undefined) updateMethods.onProgress(downloadProgress); + if (!downloadEnded) setTimeout(updateDownloadProgress, 100); + }; + updateDownloadProgress(); + return downloadComplete; }; diff --git a/plugins/_lib/nativeBridge/index.ts b/plugins/_lib/nativeBridge/index.ts index cd462e9..97c7505 100644 --- a/plugins/_lib/nativeBridge/index.ts +++ b/plugins/_lib/nativeBridge/index.ts @@ -21,6 +21,7 @@ export const parseDasha = invoke("parseDasha"); export const requestJson = invoke("requestJson"); export const hash = invoke("hash"); export const voidTrack = invoke("voidTrack"); -export const downloadTrackStream = invoke("downloadTrackStream"); +export const startTrackDownload = invoke("startTrackDownload"); export const saveDialog = invoke("saveDialog"); export const openDialog = invoke("openDialog"); +export const getDownloadProgress = invoke("getDownloadProgress"); diff --git a/plugins/_lib/nativeBridge/native/downloadTrack.native.ts b/plugins/_lib/nativeBridge/native/downloadTrack.native.ts index 68e22ed..3a5dd6e 100644 --- a/plugins/_lib/nativeBridge/native/downloadTrack.native.ts +++ b/plugins/_lib/nativeBridge/native/downloadTrack.native.ts @@ -1,8 +1,25 @@ -import { requestTrackStream } from "./request/requestTrack.native"; import type { ExtendedPlayackInfo } from "../../Caches/PlaybackInfoTypes"; +import type { DownloadProgress } from "./request/helpers.native"; +import { requestTrackStream } from "./request/requestTrack.native"; import { createWriteStream } from "fs"; -export const downloadTrackStream = async (extPlaybackInfo: ExtendedPlayackInfo, filePath: string): Promise => { - const stream = await requestTrackStream(extPlaybackInfo); - return new Promise((res) => stream.pipe(createWriteStream(filePath)).on("finish", res)); +export type { DownloadProgress } from "./request/helpers.native"; + +const downloadStatus: Record = {}; + +export const startTrackDownload = async (extPlaybackInfo: ExtendedPlayackInfo, filePath: string): Promise => { + if (downloadStatus[filePath] !== undefined) throw new Error(`Something is already downloading to ${filePath}`); + try { + const stream = await requestTrackStream(extPlaybackInfo, { onProgress: (progress) => (downloadStatus[filePath] = progress) }); + return new Promise((res) => + stream.pipe(createWriteStream(filePath)).on("finish", () => { + delete downloadStatus[filePath]; + res(); + }) + ); + } catch (err) { + delete downloadStatus[filePath]; + throw err; + } }; +export const getDownloadProgress = (filePath: string) => downloadStatus[filePath]; diff --git a/plugins/_lib/nativeBridge/native/request/helpers.native.ts b/plugins/_lib/nativeBridge/native/request/helpers.native.ts index 796e83a..8340272 100644 --- a/plugins/_lib/nativeBridge/native/request/helpers.native.ts +++ b/plugins/_lib/nativeBridge/native/request/helpers.native.ts @@ -3,7 +3,8 @@ import type { Readable } from "stream"; import type { TidalManifest } from "../../../Caches/PlaybackInfoTypes"; import { ExtendedRequestOptions } from "./requestStream.native"; -export type OnProgress = (info: { total: number; downloaded: number; percent: number }) => void; +export type DownloadProgress = { total: number; downloaded: number; percent: number }; +type OnProgress = (progress: DownloadProgress) => void; export interface FetchyOptions { onProgress?: OnProgress; bytesWanted?: number;