From 58f8ddf56649a3342b500b8526f1cee2593b4562 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 21 May 2021 21:59:07 +0200 Subject: Fix mangadex navigate to previous/next page using same images as the previous chapter --- plugins/Mangadex.hpp | 15 +++++++-- src/QuickMedia.cpp | 4 ++- src/plugins/Mangadex.cpp | 83 ++++++++++++++++++++++++++++-------------------- 3 files changed, 63 insertions(+), 39 deletions(-) diff --git a/plugins/Mangadex.hpp b/plugins/Mangadex.hpp index 1bed70c..bd4385b 100644 --- a/plugins/Mangadex.hpp +++ b/plugins/Mangadex.hpp @@ -6,6 +6,8 @@ namespace QuickMedia { PluginResult legacy_mangadex_id_to_new_manga_id(Page *page, const std::vector &manga_ids, std::vector> &new_manga_ids); + using ChapterImageUrls = std::unordered_map>; + class MangadexSearchPage : public Page { public: MangadexSearchPage(Program *program) : Page(program) {} @@ -15,6 +17,8 @@ namespace QuickMedia { PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override; PluginResult submit(const std::string &title, const std::string &url, std::vector &result_tabs) override; sf::Vector2i get_thumbnail_max_size() override { return sf::Vector2i(101, 141); }; + + ChapterImageUrls chapter_image_urls; private: SearchResult search(const std::string &str, int page, BodyItems &result_items); bool get_rememberme_token(std::string &rememberme_token); @@ -23,22 +27,27 @@ namespace QuickMedia { class MangadexChaptersPage : public MangaChaptersPage { public: - MangadexChaptersPage(Program *program, std::string manga_name, std::string manga_url) : MangaChaptersPage(program, std::move(manga_name), std::move(manga_url)) {} + MangadexChaptersPage(Program *program, MangadexSearchPage *search_page, std::string manga_name, std::string manga_url) : MangaChaptersPage(program, std::move(manga_name), std::move(manga_url)), search_page(search_page) {} PluginResult submit(const std::string &title, const std::string &url, std::vector &result_tabs) override; PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override; protected: bool extract_id_from_url(const std::string &url, std::string &manga_id) const override; const char* get_service_name() const override { return "mangadex"; } + private: + MangadexSearchPage *search_page; }; class MangadexImagesPage : public MangaImagesPage { public: - MangadexImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url, std::vector image_urls) : MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url)), image_urls(std::move(image_urls)) {} + MangadexImagesPage(Program *program, MangadexSearchPage *search_page, std::string manga_name, std::string chapter_id, std::string chapter_name) : + MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(chapter_id)), search_page(search_page) {} ImageResult get_number_of_images(int &num_images) override; ImageResult for_each_page_in_chapter(PageCallback callback) override; const char* get_service_name() const override { return "mangadex"; } const char* get_website_url() const override { return "https://mangadex.org/"; } private: - std::vector image_urls; + ImageResult get_image_urls_for_chapter(const std::string &url); + private: + MangadexSearchPage *search_page; }; } \ No newline at end of file diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index bb9844f..4d20b24 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -2893,7 +2893,7 @@ namespace QuickMedia { if(current_page != PageType::IMAGES || !window.isOpen()) return 0; - image_index = std::min(image_index, num_manga_pages); + image_index = std::max(0, std::min(image_index, num_manga_pages)); if(image_index < num_manga_pages) { sf::String error_msg; @@ -3086,6 +3086,8 @@ namespace QuickMedia { if(current_page != PageType::IMAGES_CONTINUOUS || !window.isOpen()) return; + image_index = std::max(0, std::min(image_index, num_manga_pages)); + Json::Value &json_chapters = content_storage_json["chapters"]; Json::Value json_chapter; int latest_read = 1 + image_index; diff --git a/src/plugins/Mangadex.cpp b/src/plugins/Mangadex.cpp index 48ab23f..3f42297 100644 --- a/src/plugins/Mangadex.cpp +++ b/src/plugins/Mangadex.cpp @@ -58,11 +58,6 @@ namespace QuickMedia { return PluginResult::OK; } - class MangadexChapterImagesList : public BodyItemExtra { - public: - std::vector image_urls; - }; - SearchResult MangadexSearchPage::search(const std::string &str, int page, BodyItems &result_items) { std::string url = "https://api.mangadex.org/manga?title=" + url_param_encode(str) + "&limit=100&offset=" + std::to_string(page * 100); @@ -124,7 +119,7 @@ namespace QuickMedia { return search_result_to_plugin_result(search(str, page, result_items)); } - static PluginResult get_chapters_for_manga(Page *page, const std::string &manga_id, int page_num, BodyItems &result_items) { + static PluginResult get_chapters_for_manga(Page *page, const std::string &manga_id, int page_num, BodyItems &result_items, ChapterImageUrls &chapter_image_urls) { std::string request_url = "https://api.mangadex.org/manga/" + manga_id + "/feed?order[chapter]=desc&limit=100&locales[]=en&offset=" + std::to_string(page_num * 100); Json::Value json_root; @@ -186,15 +181,16 @@ namespace QuickMedia { auto body_item = BodyItem::create(std::move(title)); body_item->url = id_json.asString(); - auto images_list = std::make_shared(); + std::vector image_urls; + image_urls.reserve(attributes_data_json.size()); for(const Json::Value &data_item_json : attributes_data_json) { if(!data_item_json.isString()) continue; std::string url = hash_json.asString() + "/" + data_item_json.asString(); - images_list->image_urls.push_back(std::move(url)); + image_urls.push_back(std::move(url)); } - body_item->extra = std::move(images_list); + chapter_image_urls[body_item->url] = std::move(image_urls); result_items.push_back(std::move(body_item)); } @@ -202,39 +198,20 @@ namespace QuickMedia { } PluginResult MangadexSearchPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { + chapter_image_urls.clear(); auto body = create_body(); - get_chapters_for_manga(this, url, 0, body->items); - result_tabs.push_back(Tab{std::move(body), std::make_unique(program, title, url), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); + get_chapters_for_manga(this, url, 0, body->items, chapter_image_urls); + result_tabs.push_back(Tab{std::move(body), std::make_unique(program, this, title, url), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); return PluginResult::OK; } PluginResult MangadexChaptersPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { - Json::Value json_root; - if(download_json(json_root, "https://api.mangadex.org/at-home/server/" + url, {}, true) != DownloadResult::OK) - return PluginResult::NET_ERR; - - if(!json_root.isObject()) - return PluginResult::ERR; - - const Json::Value &base_url_json = json_root["baseUrl"]; - if(!base_url_json.isString()) - return PluginResult::ERR; - - std::string base_url = base_url_json.asString(); - if(!base_url.empty() && base_url.back() != '/') - base_url += '/'; - - auto image_urls = static_cast(submit_body_item->extra.get())->image_urls; - for(auto &image_url : image_urls) { - image_url = base_url + "data/" + image_url; - } - - result_tabs.push_back(Tab{nullptr, std::make_unique(program, content_title, title, content_url, image_urls), nullptr}); + result_tabs.push_back(Tab{nullptr, std::make_unique(program, search_page, content_title, url, title), nullptr}); return PluginResult::OK; } PluginResult MangadexChaptersPage::get_page(const std::string&, int page, BodyItems &result_items) { - return get_chapters_for_manga(this, content_url, page, result_items); + return get_chapters_for_manga(this, content_url, page, result_items, search_page->chapter_image_urls); } bool MangadexChaptersPage::extract_id_from_url(const std::string &url, std::string &manga_id) const { @@ -256,15 +233,51 @@ namespace QuickMedia { } ImageResult MangadexImagesPage::get_number_of_images(int &num_images) { - num_images = image_urls.size(); + num_images = 0; + ImageResult image_result = get_image_urls_for_chapter(url); + if(image_result != ImageResult::OK) return image_result; + num_images = chapter_image_urls.size(); return ImageResult::OK; } ImageResult MangadexImagesPage::for_each_page_in_chapter(PageCallback callback) { - for(const std::string &url : image_urls) { + ImageResult image_result = get_image_urls_for_chapter(url); + if(image_result != ImageResult::OK) return image_result; + for(const std::string &url : chapter_image_urls) { if(!callback(url)) break; } return ImageResult::OK; } + + ImageResult MangadexImagesPage::get_image_urls_for_chapter(const std::string &url) { + if(!chapter_image_urls.empty()) + return ImageResult::OK; + + Json::Value json_root; + if(download_json(json_root, "https://api.mangadex.org/at-home/server/" + url, {}, true) != DownloadResult::OK) + return ImageResult::NET_ERR; + + if(!json_root.isObject()) + return ImageResult::ERR; + + const Json::Value &base_url_json = json_root["baseUrl"]; + if(!base_url_json.isString()) + return ImageResult::ERR; + + std::string base_url = base_url_json.asString(); + if(!base_url.empty() && base_url.back() != '/') + base_url += '/'; + + auto it = search_page->chapter_image_urls.find(url); + if(it == search_page->chapter_image_urls.end()) + return ImageResult::ERR; + + chapter_image_urls.resize(it->second.size()); + for(size_t i = 0; i < it->second.size(); ++i) { + chapter_image_urls[i] = base_url + "data/" + it->second[i]; + } + + return ImageResult::OK; + } } -- cgit v1.2.3