comic-book-dl
Version:
124 lines (123 loc) • 4.26 kB
JavaScript
import fs from 'node:fs/promises';
import cliProgress from 'cli-progress';
import { rimraf } from 'rimraf';
export default class ProgressBar {
constructor(bookPath, total, ignoreConsole = false) {
this.bookPath = '';
this.progressFilePath = '';
this.progressInfo = [];
this.curr = 0;
this.total = 0;
this.isDownloadInterrupted = false;
this.multiBar = null;
this.bar = null;
this.completePromise = null;
this.ignoreConsole = false;
this.bookPath = bookPath;
this.progressFilePath = `${bookPath}/progress.json`;
this.total = total;
this.ignoreConsole = ignoreConsole;
}
async init() {
this.progressInfo = await this.getProgress();
this.curr = this.progressInfo.length;
if (this.curr === this.total)
return;
this.isDownloadInterrupted = this.curr > 0 && this.curr !== this.total;
if (this.ignoreConsole)
return;
this.multiBar = new cliProgress.MultiBar({
format: ' {bar} | {file} | {value}/{total}',
hideCursor: true,
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
clearOnComplete: true,
stopOnComplete: true,
noTTYOutput: true
});
this.bar = this.multiBar.create(this.total, this.curr, {}, {
...cliProgress.Presets.legacy,
format: 'Download [{bar}] {percentage}% | {value}/{total}',
});
}
async getProgress() {
let progressInfo = [];
try {
const progressInfoStr = await fs.readFile(this.progressFilePath, { encoding: 'utf8' });
progressInfo = JSON.parse(progressInfoStr);
}
catch (err) {
if (err && err.code === 'ENOENT') {
await fs.writeFile(this.progressFilePath, JSON.stringify(progressInfo), { encoding: 'utf8' });
}
}
return progressInfo;
}
async updateProgress(progressItem, isSuccess) {
this.curr = this.curr + 1;
if (isSuccess) {
this.progressInfo.push(progressItem);
await fs.writeFile(this.progressFilePath, JSON.stringify(this.progressInfo, null, 2), { encoding: 'utf8' });
}
if (this.bar) {
this.bar.update(this.curr > this.total ? this.total : this.curr);
if (this.curr >= this.total) {
this.clearLine(1);
this.bar.render();
this.bar.stop();
console.log('');
}
}
}
async resetProgressInfo(updateProgressInfo) {
if (updateProgressInfo.length < this.progressInfo.length) {
const needDeleteList = this.progressInfo.filter((oldData) => {
return !updateProgressInfo.some(item => {
return item.href == oldData.href &&
item.name === oldData.name &&
item.rawName === oldData.rawName;
});
});
this.progressInfo = updateProgressInfo;
if (this.bar)
this.bar.update(updateProgressInfo.length);
this.curr = updateProgressInfo.length;
const promiseList = needDeleteList.map(needDel => {
return rimraf(needDel.path, { preserveRoot: true });
});
await Promise.all(promiseList);
}
}
multiBarCreate(params) {
if (this.ignoreConsole)
return;
return this.multiBar?.create(params.total, 0, {
file: params.file
});
}
multiBarUpdate(curBar) {
if (curBar)
curBar.increment();
}
multiBarRemove(curBar) {
if (curBar)
this.multiBar?.remove(curBar);
}
pause() {
if (this.bar)
this.bar.stop();
}
continue(line) {
this.clearLine(line);
this.bar?.start(this.total, this.curr);
}
clearLine(line) {
if (line <= 0)
return;
process.stderr.cursorTo(0);
for (let i = 0; i < line; i++) {
process.stderr.moveCursor(0, -1);
process.stderr.clearLine(1);
}
}
}