better progress bars

This commit is contained in:
Daniel Bulant 2021-05-30 22:01:53 +02:00
parent cc857ef855
commit aad5a393cc
5 changed files with 88 additions and 16 deletions

View file

@ -59,10 +59,11 @@
if(chapter === -1 || link === -1) return; if(chapter === -1 || link === -1) return;
var cs = await chapters; var cs = await chapters;
var related = cs.results.filter(t => processing.opts.chapters.find(c => t.data.id === c.id)); var related = cs.results.filter(t => processing.opts.chapters.find(c => t.data.id === c.id));
var done = processing.opts.chapters.filter(t => t.number < chapter); var done = processing.opts.chapters.filter(t => parseFloat(t.number) < parseFloat(processing.opts.chapters[chapter].number));
var linkCount = related.map(t => t.data.attributes[quality].length).reduce((a, b) => a + b); var linkCount = related.map(t => t.data.attributes[quality].length).reduce((a, b) => a + b);
console.log(related, done, done.reduce((a, b) => (a.links || []).length + (b.links || []).length, 0), link + 1, linkCount);
progress = (done.reduce((a, b) => (a.links || []).length + (b.links || []).length, 0) + link + 1) / linkCount; progress = (done.reduce((a, b) => (a.links || []).length + (b.links || []).length, 0) + link + 1) / linkCount;
progressMap.set(processing.opts.chapters[chapter].number, link + 1); progressMap.set(processing.opts.chapters[chapter].id, link + 1);
progressMap = progressMap; progressMap = progressMap;
}; };
await processing.generate(); await processing.generate();
@ -220,7 +221,7 @@
<table> <table>
<tbody> <tbody>
{#each chapters.results as chapter, i} {#each chapters.results as chapter, i}
<Chapter progress={(progressMap.get(chapter.data.attributes.chapter) || 0) / chapter.data.attributes[quality].length} {chapter} disabledDownload={!!progress} selected={selected.includes(chapter)} on:select={() => select(chapter)} on:download={() => downloadSingle(chapter)} /> <Chapter progress={(progressMap.get(chapter.data.id) || 0) / chapter.data.attributes[quality].length} {chapter} disabledDownload={!!progress} selected={selected.includes(chapter)} on:select={() => select(chapter)} on:download={() => downloadSingle(chapter)} />
{/each} {/each}
</tbody> </tbody>
</table> </table>

View file

@ -6,10 +6,13 @@
* @property {number?} volume * @property {number?} volume
* @property {string[]} links * @property {string[]} links
* @property {string} hash * @property {string} hash
* @property {string} baseUrl
*/ */
import request, { proxy } from "./request"; import request, { proxy } from "./request";
const RETRY_LIMIT = 10;
/** /**
* Base generator, to be extended * Base generator, to be extended
*/ */
@ -17,7 +20,6 @@ export class BaseGenerator {
/** /**
* *
* @param {object} opts * @param {object} opts
* @param {string} opts.baseUrl
* @param {string} opts.quality * @param {string} opts.quality
* @param {WritableStream} opts.file * @param {WritableStream} opts.file
* @param {string} opts.title * @param {string} opts.title
@ -47,15 +49,24 @@ export class BaseGenerator {
/** /**
* @param {string} url * @param {string} url
* @param {Chapter} chapter
* @returns {Promise<Response>} * @returns {Promise<Response>}
*/ */
async fetchImage(url) { async fetchImage(url, chapter) {
var res; var res;
try { try {
res = await fetch(url); res = await fetch(chapter.baseUrl + "/" + url);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
res = await fetch(proxy + url); res = await fetch(proxy + chapter.baseUrl + "/" + url);
}
if(Math.floor(res.status / 100) !== 2) {
for(var i = 0; i < RETRY_LIMIT; i++) {
chapter.baseUrl = await this.getBaseURL(chapter);
res = await fetch(chapter.baseUrl + "/" + url);
if(Math.floor(res.status / 100) === 2) return res;
}
throw new Error("Retry limit reached");
} }
return res; return res;
} }

60
src/util/bookName.test.js Normal file
View file

@ -0,0 +1,60 @@
import { bookName } from "./bookName";
function assert(isTrue, success, failure = "Failed") {
if(isTrue) {
console.log("✅ " + success);
} else {
console.log("❌ " + failure + " (" + success + ")");
}
return isTrue;
}
assert(
bookName([1, 2, 3]) === "Chapters 1 - 3",
"Basic chapter shortening"
);
assert(
bookName([1, 2, 3, 4, 5], [{ vol: 1, chapters: 5}]) === "Vol 1",
"Basic shortening to volumes"
);
assert(
bookName([1,2,3,4,5], [{vol: 1, chapters: 3}]) === "Vol 1, Chapters 4, 5",
"Mixed volume and chapter shortening"
);
assert(
bookName([1, 2], [{vol: 1, chapters: 3}, {vol: 2, chapters: 5}]) === "Chapters 1, 2",
"List of chapters without shortening with volume definitions"
);
assert(
bookName([1,2,3,5,6]) === "Chapters 1 - 3, 5, 6",
"Mixed shortening and list of chapters"
);
assert(
bookName([1,2,3,4,5], [{vol: "First", chapters: 5}]) === "Vol First",
"String volume"
);
assert(
bookName([1,2,3.5,3]) === "Chapters 1 - 3, 3.5",
"Float chapters"
);
assert(
bookName([1,2,"3.5.1", 3]) === "Chapters 1 - 3, 3.5.1",
"String chapters"
);
assert(
bookName([1,3,5,2,4]) === "Chapters 1 - 5",
"Out of order input"
);
assert(
bookName([1,2,3,4,5,"5.1"], [{ vol: 1, chapters: 5 }]) === "Vol 1, Chapters 5.1",
"String/float chapters and volume definitions"
)

View file

@ -25,16 +25,16 @@ export class CBZGenerator extends BaseGenerator {
const chapterCountLength = this.opts.chapters.reduce((a, b) => Math.max(a.number, b.number), 0).toString().length; const chapterCountLength = this.opts.chapters.reduce((a, b) => Math.max(a.number, b.number), 0).toString().length;
for(const chapterI in this.opts.chapters) { for(const chapterI in this.opts.chapters) {
const chapter = this.opts.chapters[chapterI]; const chapter = this.opts.chapters[chapterI];
const baseUrl = await this.getBaseURL(chapter.id); if(!chapter.baseUrl) chapter.baseUrl = await this.getBaseURL(chapter.id);
const imageCountLength = chapter.links.length.toString().length; const imageCountLength = chapter.links.length.toString().length;
for(const i in chapter.links) { for(const i in chapter.links) {
this.callback(chapterI, i, false); this.callback(chapterI, i, false);
const hash = chapter.links[i]; const hash = chapter.links[i];
const URL = `${baseUrl}/${this.opts.quality}/${chapter.hash}/${hash}`; const URL = `${this.opts.quality}/${chapter.hash}/${hash}`;
const start = performance.now(); const start = performance.now();
const res = await this.fetchImage(URL); const res = await this.fetchImage(URL, chapter);
const chapterText = chapter.number.toString().padStart(chapterCountLength, "0"); const chapterText = chapter.number.toString().padStart(chapterCountLength, "0");
const image = new ZipPassThrough(`${this.opts.title} ${chapterText}/${chapterText} page ${i.toString().padStart(imageCountLength, "0")}.${hash.substr(hash.lastIndexOf(".") + 1)}`); const image = new ZipPassThrough(`${this.opts.title} ${chapterText}/${this.opts.title} ${chapterText} page ${i.toString().padStart(imageCountLength, "0")}.${hash.substr(hash.lastIndexOf(".") + 1)}`);
this.zip.add(image); this.zip.add(image);
const data = new Uint8Array(await res.arrayBuffer()); const data = new Uint8Array(await res.arrayBuffer());
const end = performance.now() - start; const end = performance.now() - start;
@ -43,7 +43,7 @@ export class CBZGenerator extends BaseGenerator {
cached: res.headers.get("X-Cache") === "HIT", cached: res.headers.get("X-Cache") === "HIT",
duration: end, duration: end,
success: Math.floor(res.status / 100) === 2, success: Math.floor(res.status / 100) === 2,
url: URL url: `${chapter.baseUrl}/${URL}`
}); });
image.push(data, true); image.push(data, true);
this.callback(chapterI, i, true); this.callback(chapterI, i, true);

View file

@ -36,13 +36,13 @@ export class EpubGenerator extends BaseGenerator {
for(const chapterI in this.opts.chapters) { for(const chapterI in this.opts.chapters) {
const chapter = this.opts.chapters[chapterI]; const chapter = this.opts.chapters[chapterI];
const baseUrl = await this.getBaseURL(chapter.id); if(!chapter.baseUrl) chapter.baseUrl = await this.getBaseURL(chapter.id);
for(const i in chapter.links) { for(const i in chapter.links) {
this.callback(chapterI, i, false); this.callback(chapterI, i, false);
const hash = chapter.links[i]; const hash = chapter.links[i];
const URL = `${baseUrl}/${this.opts.quality}/${chapter.hash}/${hash}`; const URL = `${this.opts.quality}/${chapter.hash}/${hash}`;
const start = performance.now(); const start = performance.now();
const res = await this.fetchImage(URL); const res = await this.fetchImage(URL, chapter);
const image = new ZipPassThrough("OEBPS/" + hash); const image = new ZipPassThrough("OEBPS/" + hash);
this.zip.add(image); this.zip.add(image);
const data = new Uint8Array(await res.arrayBuffer()); const data = new Uint8Array(await res.arrayBuffer());
@ -52,7 +52,7 @@ export class EpubGenerator extends BaseGenerator {
cached: res.headers.get("X-Cache") === "HIT", cached: res.headers.get("X-Cache") === "HIT",
duration: end, duration: end,
success: Math.floor(res.status / 100) === 2, success: Math.floor(res.status / 100) === 2,
url: URL url: `${chapter.baseUrl}/${URL}`
}); });
image.push(data, true); image.push(data, true);
const textContent = new ZipPassThrough("OEBPS/" + i + ".xhtml"); const textContent = new ZipPassThrough("OEBPS/" + i + ".xhtml");