Skip to content

Commit a8ac2c3

Browse files
committed
download progress bar on taskbar
+ Get the best possible artwork
1 parent 2168cbc commit a8ac2c3

File tree

6 files changed

+62
-19
lines changed

6 files changed

+62
-19
lines changed

plugins/downloader/actions.js

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const CHANNEL = "downloader";
22
const ACTIONS = {
33
ERROR: "error",
44
METADATA: "metadata",
5+
PROGRESS: "progress",
56
};
67

78
module.exports = {

plugins/downloader/back.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@ const { dialog, ipcMain } = require("electron");
66

77
const getSongInfo = require("../../providers/song-info");
88
const { injectCSS, listenAction } = require("../utils");
9+
const { cropMaxWidth } = require("./utils");
910
const { ACTIONS, CHANNEL } = require("./actions.js");
1011
const { getImage } = require("../../providers/song-info");
1112

12-
const sendError = (win, err) => {
13+
const sendError = (err) => {
1314
const dialogOpts = {
1415
type: "info",
1516
buttons: ["OK"],
1617
title: "Error in download!",
1718
message: "Argh! Apologies, download failed…",
1819
detail: err.toString(),
1920
};
21+
win.setProgressBar(-1); // close progress bar
2022
dialog.showMessageBox(dialogOpts);
2123
};
2224

@@ -29,14 +31,17 @@ function handle(win) {
2931
metadata = info;
3032
});
3133

32-
listenAction(CHANNEL, (event, action, error) => {
34+
listenAction(CHANNEL, (event, action, arg) => {
3335
switch (action) {
34-
case ACTIONS.ERROR:
35-
sendError(win, error);
36+
case ACTIONS.ERROR: //arg = error
37+
sendError(arg);
3638
break;
3739
case ACTIONS.METADATA:
3840
event.returnValue = JSON.stringify(metadata);
3941
break;
42+
case ACTIONS.PROGRESS: //arg = progress
43+
win.setProgressBar(arg);
44+
break;
4045
default:
4146
console.log("Unknown action: " + action);
4247
}
@@ -46,7 +51,7 @@ function handle(win) {
4651
let fileBuffer = songBuffer;
4752

4853
if (currentMetadata.imageSrc) {
49-
currentMetadata.image = await getImage(currentMetadata.imageSrc);
54+
currentMetadata.image = cropMaxWidth(await getImage(currentMetadata.imageSrc));
5055
}
5156

5257
const songMetadata = { ...metadata, ...currentMetadata };
@@ -69,7 +74,7 @@ function handle(win) {
6974
writer.addTag();
7075
fileBuffer = Buffer.from(writer.arrayBuffer);
7176
} catch (error) {
72-
sendError(win, error);
77+
sendError(error);
7378
}
7479

7580
writeFileSync(filePath, fileBuffer);

plugins/downloader/front.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const observer = new MutationObserver((mutations, observer) => {
2525
});
2626

2727
const reinit = () => {
28+
triggerAction(CHANNEL, ACTIONS.PROGRESS, -1); // closes progress bar
2829
if (!progress) {
2930
console.warn("Cannot update progress");
3031
} else {
@@ -38,6 +39,7 @@ const baseUrl = defaultConfig.url;
3839
// contextBridge.exposeInMainWorld("downloader", {
3940
// download: () => {
4041
global.download = () => {
42+
triggerAction(CHANNEL, ACTIONS.PROGRESS, 2); // starts with indefinite progress bar
4143
let metadata;
4244
let videoUrl = getSongMenu()
4345
?.querySelector('ytmusic-menu-navigation-item-renderer.iron-selected[tabindex="0"]')
@@ -53,12 +55,15 @@ global.download = () => {
5355

5456
downloadVideoToMP3(
5557
videoUrl,
56-
(feedback) => {
58+
(feedback, ratio = undefined) => {
5759
if (!progress) {
5860
console.warn("Cannot update progress");
5961
} else {
6062
progress.innerHTML = feedback;
6163
}
64+
if (ratio) {
65+
triggerAction(CHANNEL, ACTIONS.PROGRESS, ratio);
66+
}
6267
},
6368
(error) => {
6469
triggerAction(CHANNEL, ACTIONS.ERROR, error);

plugins/downloader/menu.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module.exports = (win, options) => {
3232
const currentURL = metadataURL || win.webContents.getURL();
3333
const playlistID = new URL(currentURL).searchParams.get("list");
3434
if (!playlistID) {
35-
sendError(win, new Error("No playlist ID found"));
35+
sendError(new Error("No playlist ID found"));
3636
return;
3737
}
3838

@@ -46,7 +46,6 @@ module.exports = (win, options) => {
4646
const playlistFolder = join(folder, playlistTitle);
4747
if (existsSync(playlistFolder)) {
4848
sendError(
49-
win,
5049
new Error(`The folder ${playlistFolder} already exists`)
5150
);
5251
return;

plugins/downloader/utils.js

+30
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,33 @@ const electron = require("electron");
33
module.exports.getFolder = (customFolder) =>
44
customFolder || (electron.app || electron.remote.app).getPath("downloads");
55
module.exports.defaultMenuDownloadLabel = "Download playlist";
6+
7+
module.exports.UrlToJPG = (imgUrl, videoId) => {
8+
if (!imgUrl || imgUrl.includes(".jpg")) return imgUrl;
9+
if (imgUrl.includes("maxresdefault")) {
10+
return "https://img.youtube.com/vi/"+videoId+"/maxresdefault.jpg";
11+
}
12+
if (imgUrl.includes("hqdefault")) {
13+
return "https://img.youtube.com/vi/"+videoId+"/hqdefault.jpg";
14+
} //it will almost never get further than hq
15+
if (imgUrl.includes("mqdefault")) {
16+
return "https://img.youtube.com/vi/"+videoId+"/mqdefault.jpg";
17+
}
18+
if (imgUrl.includes("sdddefault")) {
19+
return "https://img.youtube.com/vi/"+videoId+"/sdddefault.jpg";
20+
}
21+
return "https://img.youtube.com/vi/"+videoId+"/default.jpg";
22+
}
23+
24+
module.exports.cropMaxWidth = (image) => {
25+
const imageSize = image.getSize();
26+
if (imageSize.width === 1280 && imageSize.height === 720) {
27+
return image.crop({
28+
x: 280,
29+
y: 0,
30+
width: 720,
31+
height: 720
32+
});
33+
}
34+
return image;
35+
}

plugins/downloader/youtube-dl.js

+13-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const ytdl = require("ytdl-core");
1414

1515
const { triggerAction, triggerActionSync } = require("../utils");
1616
const { ACTIONS, CHANNEL } = require("./actions.js");
17-
const { getFolder } = require("./utils");
17+
const { getFolder, UrlToJPG } = require("./utils");
1818
const { cleanupArtistName } = require("../../providers/song-info");
1919

2020
const { createFFmpeg } = FFmpeg;
@@ -37,12 +37,14 @@ const downloadVideoToMP3 = async (
3737
sendFeedback("Downloading…");
3838

3939
if (metadata === null) {
40-
const info = await ytdl.getInfo(videoUrl);
41-
const thumbnails = info.videoDetails?.author?.thumbnails;
40+
const { videoDetails } = await ytdl.getInfo(videoUrl);
41+
const thumbnails = videoDetails?.thumbnails;
4242
metadata = {
43-
artist: info.videoDetails?.media?.artist || cleanupArtistName(info.videoDetails?.author?.name) || "",
44-
title: info.videoDetails?.media?.song || info.videoDetails?.title || "",
45-
imageSrc: thumbnails ? thumbnails[thumbnails.length - 1].url : ""
43+
artist: videoDetails?.media?.artist || cleanupArtistName(videoDetails?.author?.name) || "",
44+
title: videoDetails?.media?.song || videoDetails?.title || "",
45+
imageSrc: thumbnails ?
46+
UrlToJPG(thumbnails[thumbnails.length - 1].url, videoDetails?.videoId)
47+
: ""
4648
}
4749
}
4850

@@ -65,9 +67,10 @@ const downloadVideoToMP3 = async (
6567
.on("data", (chunk) => {
6668
chunks.push(chunk);
6769
})
68-
.on("progress", (chunkLength, downloaded, total) => {
69-
const progress = Math.floor((downloaded / total) * 100);
70-
sendFeedback("Download: " + progress + "%");
70+
.on("progress", (_chunkLength, downloaded, total) => {
71+
const ratio = downloaded / total;
72+
const progress = Math.floor(ratio * 100);
73+
sendFeedback("Download: " + progress + "%", ratio);
7174
})
7275
.on("info", (info, format) => {
7376
videoName = info.videoDetails.title.replace("|", "").toString("ascii");
@@ -112,7 +115,7 @@ const toMP3 = async (
112115

113116
try {
114117
if (!ffmpeg.isLoaded()) {
115-
sendFeedback("Loading…");
118+
sendFeedback("Loading…", 2); // indefinite progress bar after download
116119
await ffmpeg.load();
117120
}
118121

0 commit comments

Comments
 (0)