From 3dce4e2b9200a1cd4eca50147203cb34a31e0ef3 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 5 Jun 2021 12:13:08 +0200 Subject: Add covers to mangadex, remove arrow left/right, require alt --- README.md | 6 ++-- plugins/Mangadex.hpp | 1 + src/Body.cpp | 4 +-- src/QuickMedia.cpp | 2 +- src/SearchBar.cpp | 6 ++-- src/Tabs.cpp | 16 +++++---- src/plugins/Mangadex.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++- src/plugins/Matrix.cpp | 11 ------- 8 files changed, 103 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 5c7996b..49a6ec2 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ EXAMPLES: If you are running arch linux then you can install QuickMedia from aur (https://aur.archlinux.org/packages/quickmedia-git/), otherwise you will need to first install [sibs](https://git.dec05eba.com/sibs/) and then run `./install.sh` as root. ## Controls Press `Arrow up` / `Arrow down` or `Ctrl+K` / `Ctrl+J` to navigate the menu and also to scroll to the previous/next image when viewing manga in scroll mode. Alternatively you can use the mouse scroll to scroll to the previous/next manga in scroll mode.\ -Press `Arrow left` / `Arrow right` or `Ctrl+H` / `Ctrl+L` or `Tab` / `Shift+Tab` to switch tab. The alt key can also be used in grid mode to move tabs instead of moving selection left/right.\ -Press `Ctrl+1-9` to move to the numbered tab.\ +Press `Alt+Arrow left` / `Alt+Arrow right` or `Ctrl+Alt+H` / `Ctrl+Alt+L` or `Tab` / `Shift+Tab` to switch tab.\ +Press `Alt+1-9` to switch to the specified tab.\ Press `Page up` to scroll up and entire page or `Page down` to scroll down an entire page.\ Press `Home` to scroll to the top or `End` to scroll to the bottom.\ Press `Enter` (aka `Return`) to select the item.\ @@ -60,7 +60,7 @@ Press `U` in matrix or in a 4chan thread to bring up the file manager to choose Press `Ctrl + V` to upload media to room in matrix if the clipboard contains a valid absolute filepath.\ Press `Ctrl + D` to remove the file that was previously selected with `U` in a 4chan thread.\ Press `Ctrl + I` to reverse image search the selected image on 4chan or matrix, or to select the url in the text to open in a browser.\ -Press `Ctrl+Alt+Arrow up` / `Ctrl+Alt+Arrow down` or `Ctrl+Alt+K` / `Ctrl+Alt+J` to view the room above/below the selected room in matrix.\ +Press `Alt+Arrow up` / `Alt+Arrow down` or `Ctrl+Alt+K` / `Ctrl+Alt+J` to view the room above/below the selected room in matrix.\ Press `Ctrl + S` to save the selected/displaying image/video/audio (does currently not work for manga pages).\ Press `Ctrl + Enter` to submit text, ignoring the selected item (when saving a file or selecting a server for matrix room directory).\ Press `Ctrl + Enter` to save the file to the selected directory with the selected name, when downloading a file. diff --git a/plugins/Mangadex.hpp b/plugins/Mangadex.hpp index bd4385b..7497b06 100644 --- a/plugins/Mangadex.hpp +++ b/plugins/Mangadex.hpp @@ -20,6 +20,7 @@ namespace QuickMedia { ChapterImageUrls chapter_image_urls; private: + PluginResult get_cover_urls(BodyItems &body_items); SearchResult search(const std::string &str, int page, BodyItems &result_items); bool get_rememberme_token(std::string &rememberme_token); std::optional rememberme_token; diff --git a/src/Body.cpp b/src/Body.cpp index 9843492..ce7f4f3 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -520,7 +520,7 @@ namespace QuickMedia { if(!show_drop_shadow) return; - const sf::Color color(21, 25, 30); + const sf::Color color(0, 0, 0, 50); const float height = 5.0f; sf::Vertex gradient_points[4]; @@ -1201,7 +1201,7 @@ namespace QuickMedia { const float text_height = (card_height - card_padding_y * 2.0f) - image_height - text_padding; const float underflow_text = text_pos.y - scissor_y; - const float underflow_height = underflow_text < 0.0f ? text_height + underflow_text : text_height; + const float underflow_height = underflow_text < 0.0f ? std::max(0.0f, text_height + underflow_text) : text_height; sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, underflow_height)); new_view.setViewport(sf::FloatRect(0.0f, std::max(text_pos.y, scissor_y) / (float)window_size.y, 1.0f, underflow_height / (float)window_size.y)); window.setView(new_view); diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 0709a12..c4a5d72 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -5251,7 +5251,7 @@ namespace QuickMedia { idle_active_handler(); } - if(event.type == sf::Event::KeyPressed && event.key.control && event.key.alt && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION)) { + if(event.type == sf::Event::KeyPressed && event.key.alt && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION)) { if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) { matrix_chat_page->rooms_page->body->select_previous_item(true); move_room = true; diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp index 91ad2e8..bf58c34 100644 --- a/src/SearchBar.cpp +++ b/src/SearchBar.cpp @@ -106,9 +106,6 @@ namespace QuickMedia { if(!editable) return; - if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) - return; - if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace) backspace_pressed = true; else if(event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Backspace) @@ -125,6 +122,9 @@ namespace QuickMedia { time_since_search_update.restart(); } + if(sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt) || sf::Keyboard::isKeyPressed(sf::Keyboard::RAlt)) + return; + if(event.type == sf::Event::TextEntered && event.text.unicode != 8 && event.text.unicode != 127) // 8 = backspace, 127 = del onTextEntered(event.text.unicode); else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace) diff --git a/src/Tabs.cpp b/src/Tabs.cpp index e1a0d86..390b088 100644 --- a/src/Tabs.cpp +++ b/src/Tabs.cpp @@ -62,17 +62,19 @@ namespace QuickMedia { void Tabs::on_event(sf::Event &event) { if(event.type == sf::Event::KeyPressed && !tabs.empty()) { - if(((!tabs[selected_tab].body->can_move_left() || event.key.alt) && (event.key.code == sf::Keyboard::Left || (event.key.control && event.key.code == sf::Keyboard::H))) - || (event.key.code == sf::Keyboard::Tab && event.key.shift)) - { + bool move_left = event.key.alt && (event.key.code == sf::Keyboard::Left || (event.key.control && event.key.code == sf::Keyboard::H)); + move_left |= (event.key.code == sf::Keyboard::Tab && event.key.shift); + + bool move_right = event.key.alt && (event.key.code == sf::Keyboard::Right || (event.key.control && event.key.code == sf::Keyboard::L)); + move_right |= (event.key.code == sf::Keyboard::Tab && !event.key.shift); + + if(move_left) { if(selected_tab > 0) move_selected_tab(selected_tab - 1); - } else if(((!tabs[selected_tab].body->can_move_right() || event.key.alt) && (event.key.code == sf::Keyboard::Right || (event.key.control && event.key.code == sf::Keyboard::L))) - || (event.key.code == sf::Keyboard::Tab && !event.key.shift)) - { + } else if(move_right) { if(selected_tab < (int)tabs.size() - 1) move_selected_tab(selected_tab + 1); - } else if(event.key.control && event.key.code >= sf::Keyboard::Num1 && event.key.code <= sf::Keyboard::Num9) { + } else if(event.key.alt && event.key.code >= sf::Keyboard::Num1 && event.key.code <= sf::Keyboard::Num9) { const int tab_target = event.key.code - sf::Keyboard::Num1; if(tab_target < (int)tabs.size()) move_selected_tab(tab_target); diff --git a/src/plugins/Mangadex.cpp b/src/plugins/Mangadex.cpp index 0143d7f..4a10455 100644 --- a/src/plugins/Mangadex.cpp +++ b/src/plugins/Mangadex.cpp @@ -58,8 +58,88 @@ namespace QuickMedia { return PluginResult::OK; } + static std::shared_ptr relationship_get_body_item(const Json::Value &json, BodyItems &body_items) { + for(const Json::Value &item_json : json) { + if(!item_json.isObject()) + continue; + + const Json::Value &type_json = item_json["type"]; + if(!type_json.isString() || strcmp(type_json.asCString(), "manga") != 0) + continue; + + const Json::Value &id_json = item_json["id"]; + if(!id_json.isString()) + continue; + + std::string id_str = id_json.asString(); + auto it = std::find_if(body_items.begin(), body_items.end(), [&id_str](const std::shared_ptr &body_item) { + return body_item->url == id_str; + }); + + if(it == body_items.end()) + continue; + + return *it; + } + return nullptr; + } + + PluginResult MangadexSearchPage::get_cover_urls(BodyItems &body_items) { + std::string url = "https://api.mangadex.org/cover?"; + for(size_t i = 0; i < body_items.size(); ++i) { + if(i > 0) + url += "&"; + url += "manga[]=" + body_items[i]->url; + } + + Json::Value json_root; + if(download_json(json_root, url, {}, true) != DownloadResult::OK) + return PluginResult::NET_ERR; + + if(!json_root.isObject()) + return PluginResult::OK; + + const Json::Value &results_json = json_root["results"]; + if(!results_json.isArray()) + return PluginResult::OK; + + std::shared_ptr body_item; + for(const Json::Value &result_item_json : results_json) { + if(!result_item_json.isObject()) + continue; + + const Json::Value &result_json = result_item_json["result"]; + if(!result_json.isString() || strcmp(result_json.asCString(), "ok") != 0) + continue; + + const Json::Value &relationships_json = result_item_json["relationships"]; + if(!relationships_json.isArray()) + continue; + + body_item = relationship_get_body_item(relationships_json, body_items); + if(!body_item) + continue; + + const Json::Value &data_json = result_item_json["data"]; + if(!data_json.isObject()) + continue; + + const Json::Value &attributes_json = data_json["attributes"]; + if(!attributes_json.isObject()) + continue; + + const Json::Value &filename_json = attributes_json["fileName"]; + if(!filename_json.isString()) + continue; + + body_item->thumbnail_url = "https://uploads.mangadex.org/covers/" + body_item->url + "/" + filename_json.asString() + ".256.jpg"; + } + + return PluginResult::OK; + } + 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); + std::string url = "https://api.mangadex.org/manga?title=" + url_param_encode(str) + "&limit=20&offset=" + std::to_string(page * 20); Json::Value json_root; if(download_json(json_root, url, {}, true) != DownloadResult::OK) @@ -108,6 +188,9 @@ namespace QuickMedia { result_items.push_back(std::move(body_item)); } + // Intentionally ignore errors. This api shouldn't fail if we fail to get covers + get_cover_urls(result_items); + return SearchResult::OK; } diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 1e69bd7..6c7e4bd 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -2462,17 +2462,6 @@ namespace QuickMedia { if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0) continue; - room_data->set_avatar_url(get_thumbnail_url(homeserver, thumbnail_url_extract_media_id(url_json.GetString()))); - room_data->avatar_is_fallback = false; - } else if(strcmp(type_json.GetString(), "m.room.avatar") == 0) { - const rapidjson::Value &content_json = GetMember(event_item_json, "content"); - if(!content_json.IsObject()) - continue; - - const rapidjson::Value &url_json = GetMember(content_json, "url"); - if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0) - continue; - room_data->set_avatar_url(get_thumbnail_url(homeserver, thumbnail_url_extract_media_id(url_json.GetString()))); room_data->avatar_is_fallback = false; } else if(strcmp(type_json.GetString(), "m.room.topic") == 0) { -- cgit v1.2.3