From fdeb82815db468ac7e99e9646f57bed2bf1832de Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 22 Sep 2021 20:10:48 +0200 Subject: Sort anilist recommendations by best match, show episode duration, show titles differently --- include/Body.hpp | 3 +-- include/BodyItem.hpp | 8 ++++++-- src/Body.cpp | 41 +++++++++++++++++++++-------------------- src/BodyItem.cpp | 13 ++++++++++--- src/QuickMedia.cpp | 2 +- src/plugins/AniList.cpp | 25 ++++++++++++++++++------- src/plugins/Manga.cpp | 2 +- src/plugins/MangaCombined.cpp | 12 ++++++------ src/plugins/MyAnimeList.cpp | 8 ++++---- 9 files changed, 68 insertions(+), 46 deletions(-) diff --git a/include/Body.hpp b/include/Body.hpp index 91913b5..4126697 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -117,8 +117,6 @@ namespace QuickMedia { // TODO: Highlight the part of the text that matches the search. void filter_search_fuzzy(const std::string &text); - bool no_items_visible() const; - int get_selected_item() const { return selected_item; } bool is_selected_item_last_visible_item() const; @@ -162,6 +160,7 @@ namespace QuickMedia { void update_dirty_state(BodyItem *body_item, float width); void clear_body_item_cache(BodyItem *body_item); sf::Vector2i get_item_thumbnail_size(BodyItem *item) const; + // Returns -1 if not found int get_previous_visible_item(int start_index); // Returns -1 if not found diff --git a/include/BodyItem.hpp b/include/BodyItem.hpp index e2f4918..5889d58 100644 --- a/include/BodyItem.hpp +++ b/include/BodyItem.hpp @@ -43,11 +43,10 @@ namespace QuickMedia { class BodyItem { public: - BodyItem(std::string _title); BodyItem(const BodyItem&) = delete; BodyItem& operator=(const BodyItem &other); - static std::shared_ptr create(std::string title) { return std::make_shared(std::move(title)); } + static std::shared_ptr create(std::string title, bool selectable = true); void set_title(std::string new_title) { if(title == new_title) @@ -122,6 +121,8 @@ namespace QuickMedia { sf::Color get_description_color() const { return description_color; } sf::Color get_author_color() const { return author_color; } + bool is_selectable() const { return selectable; } + void draw_list(Body *body, sf::RenderTarget &render_target); // TODO: Use a list of strings instead, not all plugins need all of these fields @@ -161,6 +162,8 @@ namespace QuickMedia { // Internal use only int keep_alive_frames = 0; + private: + BodyItem(std::string _title, bool selectable); private: // TODO: Clean up these strings when set in text, and get_title for example should return |title_text.getString()| // TODO: Use sf::String instead, removes the need to convert to utf32 every time the text is dirty (for example when resizing window) @@ -171,6 +174,7 @@ namespace QuickMedia { sf::Color title_color; sf::Color author_color; sf::Color description_color; + bool selectable; }; using BodyItems = std::vector>; diff --git a/src/Body.cpp b/src/Body.cpp index 5509938..d5395fd 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -441,13 +441,13 @@ namespace QuickMedia { } BodyItem* Body::get_selected() const { - if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible) + if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible || !items[selected_item]->is_selectable()) return nullptr; return items[selected_item].get(); } std::shared_ptr Body::get_selected_shared() { - if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible) + if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible || !items[selected_item]->is_selectable()) return nullptr; return items[selected_item]; } @@ -694,11 +694,13 @@ namespace QuickMedia { if(mouse_scroll_accel.y > 0.1f && prev_first_visible_item != -1) { selected_item = prev_first_visible_item; // TODO: Cache this + // TODO: Selectable item if(on_top_reached && get_previous_visible_item(selected_item) == -1) on_top_reached(); } else if(mouse_scroll_accel.y < -0.1f && prev_last_visible_item != -1) { selected_item = prev_last_visible_item; // TODO: Cache this + // TODO: Selectable item if(on_bottom_reached && get_next_visible_item(selected_item) == -1) on_bottom_reached(); } @@ -1094,7 +1096,7 @@ namespace QuickMedia { item_pos.x = std::floor(pos.x); item_pos.y = std::floor(pos.y); - if(body_theme == BODY_THEME_MODERN_SPACIOUS) { + if(body_theme == BODY_THEME_MODERN_SPACIOUS && item->is_selectable()) { item_background.set_position(item_pos); item_background.set_size(sf::Vector2f(size.x, item->loaded_height)); item_background.set_color(get_theme().shade_color); @@ -1273,10 +1275,12 @@ namespace QuickMedia { new_view.setViewport(sf::FloatRect(0.0f, scissor_y / (float)window_size.y, 1.0f, size.y / (float)window_size.y)); window.setView(new_view); - item_background.set_position(round(pos + pos_offset)); - item_background.set_size(round(sf::Vector2f(card_width, item_height))); - item_background.set_color(get_theme().card_item_background_color); - item_background.draw(window); + if(item->is_selectable()) { + item_background.set_position(round(pos + pos_offset)); + item_background.set_size(round(sf::Vector2f(card_width, item_height))); + item_background.set_color(get_theme().card_item_background_color); + item_background.draw(window); + } handle_item_render(pos + pos_offset, card_width, item_height, item_index); @@ -1759,11 +1763,15 @@ namespace QuickMedia { void Body::filter_search_fuzzy_item(const std::string &text, BodyItem *body_item) { const bool prev_visible = body_item->visible; - body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_title(), text); - if(!body_item->visible && !body_item->get_description().empty()) - body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_description(), text); - if(!body_item->visible && !body_item->get_author().empty()) - body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_author(), text); + if(!body_item->is_selectable()) { + body_item->visible = true; + } else { + body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_title(), text); + if(!body_item->visible && !body_item->get_description().empty()) + body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_description(), text); + if(!body_item->visible && !body_item->get_author().empty()) + body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_author(), text); + } if(prev_visible && !body_item->visible) { clear_body_item_cache(body_item); @@ -1773,14 +1781,7 @@ namespace QuickMedia { } } - bool Body::no_items_visible() const { - for(auto &item : items) { - if(item->visible) - return false; - } - return true; - } - + // TODO: Selectable bool Body::is_selected_item_last_visible_item() const { if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible) return false; diff --git a/src/BodyItem.cpp b/src/BodyItem.cpp index 0b41893..6523738 100644 --- a/src/BodyItem.cpp +++ b/src/BodyItem.cpp @@ -4,7 +4,12 @@ #include namespace QuickMedia { - BodyItem::BodyItem(std::string _title) : + // static + std::shared_ptr BodyItem::create(std::string title, bool selectable) { + return std::shared_ptr(new BodyItem(std::move(title), selectable)); + } + + BodyItem::BodyItem(std::string _title, bool selectable) : visible(true), dirty(false), dirty_description(false), @@ -15,7 +20,8 @@ namespace QuickMedia { timestamp(0), title_color(get_theme().text_color), author_color(get_theme().text_color), - description_color(get_theme().text_color) + description_color(get_theme().text_color), + selectable(selectable) { if(!_title.empty()) set_title(std::move(_title)); @@ -43,7 +49,7 @@ namespace QuickMedia { loaded_content_height = 0.0f; embedded_item_status = other.embedded_item_status; if(other.embedded_item) { - embedded_item.reset(new BodyItem("")); + embedded_item.reset(new BodyItem("", true)); *embedded_item = *other.embedded_item; } else { embedded_item.reset(); @@ -66,6 +72,7 @@ namespace QuickMedia { description_color = other.description_color; extra = other.extra; keep_alive_frames = other.keep_alive_frames; + selectable = other.selectable; return *this; } diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 9b31580..bb71c73 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -4704,7 +4704,7 @@ namespace QuickMedia { if(!related_body_item) return false; - body_item->embedded_item = std::make_shared(""); + body_item->embedded_item = BodyItem::create(""); *body_item->embedded_item = *related_body_item; body_item->embedded_item->embedded_item = nullptr; body_item->embedded_item->reactions.clear(); diff --git a/src/plugins/AniList.cpp b/src/plugins/AniList.cpp index 0c7229f..5043eb7 100644 --- a/src/plugins/AniList.cpp +++ b/src/plugins/AniList.cpp @@ -28,6 +28,7 @@ query ($page: Int, $perPage: Int, $search: String) { averageScore episodes chapters + duration genres coverImage { medium @@ -62,6 +63,7 @@ query ($id: Int) { averageScore episodes chapters + duration genres description (asHtml: false) coverImage { @@ -99,6 +101,7 @@ query ($id: Int) { averageScore episodes chapters + duration genres coverImage { medium @@ -117,7 +120,7 @@ query ($id: Int) { static const std::string recommendations_query_graphql = R"END( query ($id: Int, $page: Int, $perPage: Int) { Media (id: $id) { - recommendations (page: $page, perPage: $perPage) { + recommendations (page: $page, perPage: $perPage, sort: RATING_DESC) { nodes { mediaRecommendation { id @@ -137,6 +140,7 @@ query ($id: Int, $page: Int, $perPage: Int) { averageScore episodes chapters + duration genres coverImage { medium @@ -288,6 +292,7 @@ query ($id: Int, $page: Int, $perPage: Int) { const Json::Value &status_json = media_json["status"]; const Json::Value &episodes_json = media_json["episodes"]; const Json::Value &chapters_json = media_json["chapters"]; + const Json::Value &duration_json = media_json["duration"]; const Json::Value &genres_json = media_json["genres"]; const Json::Value &description_json = media_json["description"]; @@ -356,6 +361,12 @@ query ($id: Int, $page: Int, $perPage: Int) { description += "Chapters: " + std::to_string(chapters_json.asInt()); } + if(duration_json.isInt()) { + if(!description.empty()) + description += '\n'; + description += "Episode duration: " + std::to_string(duration_json.asInt()) + " minute" + (duration_json.asInt() == 1 ? "" : "s"); + } + if(status_json.isString()) { if(!description.empty()) description += '\n'; @@ -598,8 +609,8 @@ query ($id: Int, $page: Int, $perPage: Int) { if(it.second.empty()) continue; - auto anime_title_item = BodyItem::create(""); - anime_title_item->set_author("------------------------ " + it.first + " ------------------------"); + auto anime_title_item = BodyItem::create("", false); + anime_title_item->set_author(it.first); result_items.push_back(std::move(anime_title_item)); result_items.insert(result_items.end(), std::move_iterator(it.second.begin()), std::move_iterator(it.second.end())); } @@ -754,15 +765,15 @@ query ($id: Int, $page: Int, $perPage: Int) { } if(!anime_items.empty()) { - auto anime_title_item = BodyItem::create(""); - anime_title_item->set_author("------------------------ Anime ------------------------"); + auto anime_title_item = BodyItem::create("", false); + anime_title_item->set_author("Anime"); result_items.push_back(std::move(anime_title_item)); result_items.insert(result_items.end(), std::move_iterator(anime_items.begin()), std::move_iterator(anime_items.end())); } if(!manga_items.empty()) { - auto manga_title_item = BodyItem::create(""); - manga_title_item->set_author("------------------------ Manga ------------------------"); + auto manga_title_item = BodyItem::create("", false); + manga_title_item->set_author("Manga"); result_items.push_back(std::move(manga_title_item)); result_items.insert(result_items.end(), std::move_iterator(manga_items.begin()), std::move_iterator(manga_items.end())); } diff --git a/src/plugins/Manga.cpp b/src/plugins/Manga.cpp index 1d44bee..5f0aae7 100644 --- a/src/plugins/Manga.cpp +++ b/src/plugins/Manga.cpp @@ -22,7 +22,7 @@ namespace QuickMedia { } std::shared_ptr MangaChaptersPage::get_bookmark_body_item() { - auto body_item = std::make_shared(content_title); + auto body_item = BodyItem::create(content_title); body_item->url = content_url; return body_item; } diff --git a/src/plugins/MangaCombined.cpp b/src/plugins/MangaCombined.cpp index 5440871..c7fdd13 100644 --- a/src/plugins/MangaCombined.cpp +++ b/src/plugins/MangaCombined.cpp @@ -56,8 +56,8 @@ namespace QuickMedia { if(num_finished_plugins == search_threads.size()) { for(auto &f : plugin_finished_state) { if(f.second && !f.second->empty()) { - auto title_item = BodyItem::create(""); - title_item->set_author("------------------------ " + f.first->title + " ------------------------"); + auto title_item = BodyItem::create("", false); + title_item->set_author(f.first->title); result_items.push_back(std::move(title_item)); result_items.insert(result_items.end(), std::move_iterator(f.second->begin()), std::move_iterator(f.second->end())); } @@ -72,14 +72,14 @@ namespace QuickMedia { for(auto &f : plugin_finished_state) { if(f.second) { if(!f.second->empty()) { - auto title_item = BodyItem::create(""); - title_item->set_author("------------------------ " + f.first->title + " ------------------------"); + auto title_item = BodyItem::create("", false); + title_item->set_author(f.first->title); result_items.push_back(std::move(title_item)); result_items.insert(result_items.end(), std::move_iterator(f.second->begin()), std::move_iterator(f.second->end())); } } else { - auto title_item = BodyItem::create(""); - title_item->set_author("------------------------ " + f.first->title + " timed out ------------------------"); + auto title_item = BodyItem::create("", false); + title_item->set_author(f.first->title + " timed out "); result_items.push_back(std::move(title_item)); } } diff --git a/src/plugins/MyAnimeList.cpp b/src/plugins/MyAnimeList.cpp index ceba73a..a4d1d30 100644 --- a/src/plugins/MyAnimeList.cpp +++ b/src/plugins/MyAnimeList.cpp @@ -134,15 +134,15 @@ namespace QuickMedia { } if(!anime_items.empty()) { - auto anime_title_item = BodyItem::create(""); - anime_title_item->set_author("------------------------ Anime ------------------------"); + auto anime_title_item = BodyItem::create("", false); + anime_title_item->set_author("Anime"); result_items.push_back(std::move(anime_title_item)); result_items.insert(result_items.end(), std::move_iterator(anime_items.begin()), std::move_iterator(anime_items.end())); } if(!manga_items.empty()) { - auto manga_title_item = BodyItem::create(""); - manga_title_item->set_author("------------------------ Manga ------------------------"); + auto manga_title_item = BodyItem::create("", false); + manga_title_item->set_author("Manga"); result_items.push_back(std::move(manga_title_item)); result_items.insert(result_items.end(), std::move_iterator(manga_items.begin()), std::move_iterator(manga_items.end())); } -- cgit v1.2.3