From 0654ae807a9162cb3e090852ded09e72c46529ef Mon Sep 17 00:00:00 2001 From: Vahagn Khachatryan Date: Sat, 9 Feb 2019 10:59:51 +0000 Subject: [PATCH] Adding queue for download. --- src/sidebar.html | 39 ++---- src/sidebar.js | 357 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 269 insertions(+), 127 deletions(-) diff --git a/src/sidebar.html b/src/sidebar.html index e73d21e..1951210 100644 --- a/src/sidebar.html +++ b/src/sidebar.html @@ -22,30 +22,19 @@ - - -
-

- + + +
+
    +
-

- -

Book Name:

+

Progress:

@@ -54,26 +43,16 @@
- - -
- - -

-
- -
- - - - + + + \ No newline at end of file diff --git a/src/sidebar.js b/src/sidebar.js index d7c23d6..29c6e92 100644 --- a/src/sidebar.js +++ b/src/sidebar.js @@ -1,48 +1,12 @@ var concurrency = 5 var retry_delay = 15/* seconds */ +var book_delay = 300/* seconds */ +var download_list = [] function sleep(delay) { return new Promise((resolve) => setTimeout(resolve, delay*1000)); } -function getCurrentTab() { - console.debug("Querying active tab."); - var queryInfo = { - active: true, - currentWindow: true - }; - - return browser.tabs.query(queryInfo) - .then(function(tabs) { - if (tabs.length == 1){ - let url = tabs[0].url; - console.info(`Active URL: ${url}`); - return url; - } else { - console.error(`Expected 1 active tab, received: ${tabs}`); - throw 'Failed to get active tab.'; - } - }); -} - -function extractBookId(url){ - console.debug(`Extracting book id from ${url}`); - // match a url like: - // https://www.safaribooksonline.com/library/view/startup-opportunities-2nd/9781119378181/ - // https://www.safaribooksonline.com/library/view/startup-growth-engines/77961SEM00001/ - let match = url.match(/\/library\/view\/[^\/]+\/(\w+)\//); - let bookId = match && match[1]; - - if (bookId) { - console.debug(`Extracted book id: ${bookId}`); - return bookId; - }else{ - console.error('Could not extract book id from url, only ' - +'domain "www.safaribooksonline.com“ is supported.'); - throw 'Failed to extract book id.'; - } -} - class Book{ constructor(book_id, page) { @@ -57,6 +21,25 @@ class Book{ this.page = page } + addToLocalPlaylist(){ + let method = "https://learning.oreilly.com/api/v2/collections/92f0712e-eb58-4c6e-939e-d5c57a7e6d90/add-content/" + let request = { + content: [`/api/v1/book/${this.book_id}/`] + } + return fetch(method, { + method: "post", + body: JSON.stringify(request), + headers: new Headers({ + "Accept" : "application/json; version=v2", + "Content-Type": "application/json" + }), + credentials: 'include' + }) + .then((res)=>{ + console.warn(`Post ${method} - ${res.status} - ${res.statusText}`) + }) + } + downloadResource(url, retry=false){ if (retry){ console.warn(`Retry ${url}`) @@ -212,50 +195,120 @@ class Book{ } } +/*************************************************************************/ + class SidebarPage{ constructor() { - $('#loading').show(); - $('#error-message').hide(); - $('#book-info').hide(); - $("#book-file-list").empty(); + $('#book-info').hide() this.id = 1 } - renderInfo(book){ - $("#book-name").text(book.book_info.title); + getUniqueueId(){ + let id = `item_${this.id}` + this.id++ + return id + } + + loading_animatedDot(){ + return $('') + .addClass('loader__dot') + .text('.') + } + + loading_animation(){ + return $('') + .attr('id', 'dot_animation') + .append(this.loading_animatedDot()) + .append(this.loading_animatedDot()) + .append(this.loading_animatedDot()) + } + + remove_loading_animation(){ + $('#dot_animation').remove() + } + + /****************************************************/ + + renderBookItemId(book_id){ + let id = this.getUniqueueId() + + let link = $('') + .attr('href', `https://learning.oreilly.com/search/?query=${book_id}`) + .attr('id', `a_${id}`) + .text(`${book_id}`) + + var book_item = + $("
  • ") + .addClass("list-group-item") + .attr('id', id) + .append(link) + + $("#book-queue").prepend(book_item); + return id + } + + renderBookItemNameAndURL(id, name, url){ + $('#a_'+id) + .attr('href', url) + .text(name) + } + + renderBookItemAnimatedLoading(id){ + $('#'+id) + .append(this.loading_animation()) + } + + renderBookItemSuccess(id){ + this.remove_loading_animation() + $('#'+id) + .css( "color", "green" ) + .append(' - OK'); + } + + renderBookItemFail(id, err){ + this.remove_loading_animation() + $('#'+id) + .css( "color", "red" ) + .append(' - Fail: ') + .append(err) + } + + /****************************************************/ + + renderBookBeginLoading(id){ + $('#book-info').hide(); + $("#book-file-list").empty(); + this.renderBookItemAnimatedLoading(id) + } + + renderBookInfo(book, id){ $("#book-cover").attr("src", book.book_info.cover); + let link = $('
    ') + .attr('href', book.book_info.web_url) + .text(book.book_info.title) + $("#book-name").empty() + .append(link); + this.renderBookItemNameAndURL(id, + book.book_info.title, + book.book_info.web_url) + $('#book-info').show(); } - renderDoneWithBook(){ - $('#loading').hide(); + renderBookSuccess(id){ + this.renderBookItemSuccess(id) } - renderFailedTheBook(error) { - console.error(`Error: ${error}`); - $('#loading').hide(); - $('#error-message').text(`Error: ${error}`); - $('#error-message').show(); - // $('#book-info').hide(); + renderBookFail(id, err){ + this.renderBookItemFail(id, err) } - renderChapterList(book){ - // Add chapters to UI - for (let chapter_idx in book.chapter_list) { - let chapter = book.chapter_list[chapter_idx]; - var chapter_dom = $("
  • ") - .addClass("list-group-item") - .html(chapter.title) - .attr("chapterIndex", chapter_idx); - $("#book-chapter-list").append(chapter_dom); - } - $('#loading').hide(); - } + /****************************************************/ renderProgress(txt){ - let id = `item_${this.id}` - this.id++ + let id = this.getUniqueueId() + // Add chapters to UI var progress_dom = $("
  • ") .addClass("list-group-item") @@ -278,7 +331,9 @@ class SidebarPage{ .attr('title',reason.message); } } +var page = new SidebarPage() +/*********************************************************/ function fillMetadata(epub, book) { @@ -390,42 +445,152 @@ function createEpub(book, epub){ } } +/*********************************************************************/ + +function downloadBook(book_id, item_id){ + let epub = new EpubWriter(); + let book = new Book(book_id, page); + return book.downloadBookInfo() + .then(() => { page.renderBookInfo(book, item_id); }) + .then(() => { return book.downloadMetaContent(); }) + .then(() => { return book.downloadContent(); }) + .then(() => { return createEpubStructure(book, epub); }) + .then(() => { return createEpub(book, epub); }) + .then(() => { return epub.generateAsync(); }) + .then((file) => { + let title = book.book_info.title + let filename = "books/" + + title.replace(/[^a-z0-9]/gi, '_').toLowerCase() + + ".epub" + console.log(`Zip file name ${filename}`) + page.renderProgress(`Saved to ${filename}`) + let url = window.URL.createObjectURL(file) + return browser.downloads.download({ "filename" : filename, url : url}) + }) + .then(()=>{ + // Add to playlist "local" to indicate that this book + // is already downloaded. + return book.addToLocalPlaylist() + }) +} + + +/*********************************************************************/ + +var progress = false + +function downloadNextBook(){ + progress = true + + let download = download_list.pop() + item_id = download.page_id + book_id = download.book_id + + page.renderBookBeginLoading(item_id) + + downloadBook(book_id, item_id) + .then(() =>{ + page.renderBookSuccess(item_id); + }) + .catch((error)=>{ + page.renderBookFail(item_id, error); + }) + .then(()=>{ + if (download_list.length){ + return sleep(book_delay) + .then(()=>{ + return downloadNextBook() + }) + } + else{ + progress = false + } + }); +} + +/*********************************************************************/ + +function getCurrentTabUrl() { + console.debug("Querying active tab."); + var queryInfo = { + active: true, + currentWindow: true + }; + + return browser.tabs.query(queryInfo) + .then(function(tabs) { + if (tabs.length == 1){ + let url = tabs[0].url; + console.info(`Active URL: ${url}`); + return url; + } else { + console.error(`Expected 1 active tab, received: ${tabs}`); + throw 'Failed to get active tab.'; + } + }); +} + +function closeCurrentTab() { + console.debug("Querying active tab."); + var queryInfo = { + active: true, + currentWindow: true + }; + + return browser.tabs.query(queryInfo) + .then(function(tabs) { + if (tabs.length == 1){ + let tabId = tabs[0].id; + console.info(`Closing tab: ${tabId}`); + return browser.tabs.remove(tabId); + } else { + console.error(`Expected 1 active tab, received: ${tabs}`); + throw 'Failed to get active tab.'; + } + }); +} + +function extractBookId(url){ + console.debug(`Extracting book id from ${url}`); + // match a url like: + // https://www.safaribooksonline.com/library/view/startup-opportunities-2nd/9781119378181/ + // https://www.safaribooksonline.com/library/view/startup-growth-engines/77961SEM00001/ + let match = url.match(/\/library\/view\/[^\/]+\/(\w+)\//); + let bookId = match && match[1]; + + if (bookId) { + console.debug(`Extracted book id: ${bookId}`); + return bookId; + }else{ + console.error('Could not extract book id from url, only ' + +'domain "www.safaribooksonline.com“ is supported.'); + throw 'Failed to extract book id.'; + } +} function onDownloadBookClicked(){ console.info("Begin book download."); - page = new SidebarPage() - getCurrentTab() - .then(extractBookId) - .then((book_id) => { - epub = new EpubWriter(); - book = new Book(book_id, page); - return book.downloadBookInfo() - .then(() => { page.renderInfo(book); }) - // .then(() => { return book.downloadChapterList(); }) - // .then(() => { return page.renderChapterList(book); }) - .then(() => { return book.downloadMetaContent(); }) - .then(() => { return book.downloadContent(); }) - .then(() => { return createEpubStructure(book, epub); }) - .then(() => { return createEpub(book, epub); }) - .then(() => { return epub.generateAsync(); }) - .then((file) => { - let title = book.book_info.title - let filename = "books/" - + title.replace(/[^a-z0-9]/gi, '_').toLowerCase() - + ".epub" - console.log(`Zip file name ${filename}`) - page.renderProgress(`Saved to ${filename}`) - let url = window.URL.createObjectURL(file) - return browser.downloads.download({ "filename" : filename, url : url}) + getCurrentTabUrl() + .then((url)=>{ + return extractBookId(url) + }) + .then((book_id)=>{ + closeCurrentTab() + return book_id + }) + .then((book_id)=>{ + page_id = page.renderBookItemId(book_id) + download_list.push({ + book_id : book_id, + page_id : page_id }) }) - .then(() =>{ - page.renderDoneWithBook(); + .then(()=>{ + if (download_list.length && !progress){ + downloadNextBook() + } }) - .catch((error)=>{ - page.renderFailedTheBook(error); - }); } document.addEventListener('DOMContentLoaded', function() { @@ -438,8 +603,6 @@ document.addEventListener('DOMContentLoaded', function() { onDownloadBookClicked(); }); - - $('#deselect-all-button').show() $('#download-button').show() $('#download-section').hide();