From f330b16a2c36585be8ce8102cfb11e4914ed9a69 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 1 Dec 2019 23:35:01 +0100 Subject: Add image preview to image board thread --- README.md | 3 +- images/4chan_logo.png | Bin 8301 -> 9112 bytes include/Body.hpp | 1 + src/Body.cpp | 6 ++++ src/QuickMedia.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++-- src/plugins/Fourchan.cpp | 4 ++- 6 files changed, 81 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cd52125..e17d1da 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ Press `Ctrl + T` when hovering over a manga chapter to start tracking manga afte accessible in PATH environment variable.\ Press `Backspace` to return to the preview item when reading replies in image board threads.\ Press `Ctrl + R` to post a reply to a thread (TODO: This should be the keybinding for replying to one comment, not the thread).\ -Press `1 to 9` or `Numpad 1 to 9` to select google captcha image when posting a comment on 4chan. +Press `1 to 9` or `Numpad 1 to 9` to select google captcha image when posting a comment on 4chan.\ +Press `P` to preview the attached item of the selected row in full screen view. Only works for image boards when browsing a thread. ## Video controls Press `space` to pause/unpause video. `Double-click` video to fullscreen or leave fullscreen. # Dependencies diff --git a/images/4chan_logo.png b/images/4chan_logo.png index 6ba927a..0c51610 100644 Binary files a/images/4chan_logo.png and b/images/4chan_logo.png differ diff --git a/include/Body.hpp b/include/Body.hpp index 36ced92..e727244 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -29,6 +29,7 @@ namespace QuickMedia { std::string title; std::string url; std::string thumbnail_url; + std::string fullsize_image_url; std::string author; bool visible; // Used by image boards for example. The elements are indices to other body items diff --git a/src/Body.cpp b/src/Body.cpp index 8412c6c..01f0292 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -60,6 +60,12 @@ namespace QuickMedia { } void Body::reset_selected() { + for(size_t i = 0; i < items.size(); ++i) { + if(items[i]->visible) { + selected_item = i; + return; + } + } selected_item = 0; } diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index f11127d..f3b4b7b 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -1448,17 +1448,23 @@ namespace QuickMedia { REPLYING, SOLVING_POST_CAPTCHA, POSTING_SOLUTION, - POSTING_COMMENT + POSTING_COMMENT, + VIEWING_ATTACHED_IMAGE }; NavigationStage navigation_stage = NavigationStage::VIEWING_COMMENTS; std::future captcha_request_future; std::future captcha_post_solution_future; std::future post_comment_future; + std::future load_image_future; sf::Texture captcha_texture; sf::Sprite captcha_sprite; std::mutex captcha_image_mutex; + auto attached_image_texture = std::make_unique(); + sf::Sprite attached_image_sprite; + std::mutex attachment_load_mutex; + GoogleCaptchaChallengeInfo challenge_info; sf::Text challenge_description_text("", font, 24); challenge_description_text.setFillColor(sf::Color::White); @@ -1599,6 +1605,32 @@ namespace QuickMedia { body->clear_items(); body->reset_selected(); search_bar->clear(); + } else if(event.key.code == sf::Keyboard::P) { + // TODO: Make this work when thumbnail is preview for a video/gif instead of a static image + BodyItem *selected_item = body->get_selected(); + if(selected_item && !selected_item->fullsize_image_url.empty()) { + navigation_stage = NavigationStage::VIEWING_ATTACHED_IMAGE; + load_image_future = std::async(std::launch::async, [this, &image_board, &attached_image_texture, &attached_image_sprite, &attachment_load_mutex]() -> bool { + BodyItem *selected_item = body->get_selected(); + if(!selected_item || selected_item->fullsize_image_url.empty()) { + return false; + } + std::string image_data; + if(download_to_string(selected_item->fullsize_image_url, image_data, {}, image_board->use_tor) != DownloadResult::OK) { + show_notification(image_board->name, "Failed to download image: " + selected_item->fullsize_image_url, Urgency::CRITICAL); + return false; + } + + std::lock_guard lock(attachment_load_mutex); + if(!attached_image_texture->loadFromMemory(image_data.data(), image_data.size())) { + show_notification(image_board->name, "Failed to load image downloaded from url: " + selected_item->fullsize_image_url, Urgency::CRITICAL); + return false; + } + attached_image_texture->setSmooth(true); + attached_image_sprite.setTexture(*attached_image_texture, true); + return true; + }); + } } BodyItem *selected_item = body->get_selected(); @@ -1694,6 +1726,13 @@ namespace QuickMedia { navigation_stage = NavigationStage::VIEWING_COMMENTS; } } + + if(event.type == sf::Event::KeyPressed && navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { + if(event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::BackSpace) { + navigation_stage = NavigationStage::VIEWING_COMMENTS; + attached_image_texture.reset(new sf::Texture()); + } + } } // TODO: This code is duplicated in many places. Handle it in one place. @@ -1752,9 +1791,35 @@ namespace QuickMedia { // TODO: Show "Posting..." when posting solution } else if(navigation_stage == NavigationStage::POSTING_COMMENT) { // TODO: Show "Posting..." when posting comment - } else { + } else if(navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { + // TODO: Show a white image with the text "Downloading..." while the image is downloading and loading + std::lock_guard lock(attachment_load_mutex); + if(attached_image_texture->getNativeHandle() != 0) { + auto content_size = window_size; + sf::Vector2u texture_size = attached_image_texture->getSize(); + sf::Vector2f texture_size_f(texture_size.x, texture_size.y); + auto image_scale = get_ratio(texture_size_f, clamp_to_size(texture_size_f, content_size)); + attached_image_sprite.setScale(image_scale); + + auto image_size = texture_size_f; + image_size.x *= image_scale.x; + image_size.y *= image_scale.y; + attached_image_sprite.setPosition(std::floor(content_size.x * 0.5f - image_size.x * 0.5f), std::floor(content_size.y * 0.5f - image_size.y * 0.5f)); + window.draw(attached_image_sprite); + } else { + sf::RectangleShape rect(sf::Vector2f(640.0f, 480.0f)); + rect.setFillColor(sf::Color::White); + auto content_size = window_size; + auto rect_size = clamp_to_size(rect.getSize(), content_size); + rect.setSize(rect_size); + rect.setPosition(std::floor(content_size.x * 0.5f - rect_size.x * 0.5f), std::floor(content_size.y * 0.5f - rect_size.y * 0.5f)); + window.draw(rect); + } + } else if(navigation_stage == NavigationStage::REPLYING) { body->draw(window, body_pos, body_size); search_bar->draw(window); + } else if(navigation_stage == NavigationStage::VIEWING_COMMENTS) { + body->draw(window, body_pos, body_size); } window.display(); } @@ -1766,5 +1831,7 @@ namespace QuickMedia { captcha_post_solution_future.get(); if(post_comment_future.valid()) post_comment_future.get(); + if(load_image_future.valid()) + load_image_future.get(); } } \ No newline at end of file diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp index cd3f7e7..17fefdc 100644 --- a/src/plugins/Fourchan.cpp +++ b/src/plugins/Fourchan.cpp @@ -353,7 +353,9 @@ namespace QuickMedia { } // "s" means small, that's the url 4chan uses for thumbnails. // thumbnails always has .jpg extension even if they are gifs or webm. - body_item->thumbnail_url = fourchan_image_url + list_url + "/" + std::to_string(tim.asInt64()) + "s.jpg"; + std::string tim_str = std::to_string(tim.asInt64()); + body_item->thumbnail_url = fourchan_image_url + list_url + "/" + tim_str + "s.jpg"; + body_item->fullsize_image_url = fourchan_image_url + list_url + "/" + tim_str + ext_str; } ++body_item_index; -- cgit v1.2.3