From 5e29715201f3b67648728a0cd048fd1b3e1dbcf7 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 8 Dec 2019 02:25:03 +0100 Subject: Add replying to posts (image boards), changed keybinding of writing a post (image boards) --- README.md | 4 ++-- include/Body.hpp | 4 ++-- include/SearchBar.hpp | 3 +++ src/Body.cpp | 10 ++++------ src/QuickMedia.cpp | 26 ++++++++++++++++--------- src/SearchBar.cpp | 49 +++++++++++++++++++++++++++++++++++++++--------- src/plugins/Fourchan.cpp | 4 ++++ 7 files changed, 72 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index abeaf90..35b57c5 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ Press `ESC` to go back to the previous menu.\ Press `Ctrl + T` when hovering over a manga chapter to start tracking manga after that chapter. This only works if AutoMedia is installed and 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 `R` to paste the post number of the selected post into the post field (image boards). +Press `Ctrl + C` to begin writing a post to a thread (image boards).\ 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 @@ -59,7 +60,6 @@ then start downloading from the current page instead of page 1.\ Show progress of manga in the history tab (current chapter out of total chapters).\ Animate page navigation.\ Properly format text in items. For example for 4chan. The size of the item should also change.\ -Show list of replies to a comment (for image boards).\ Wrap text that is too long.\ Add greentext support for quotes.\ Add support for special formatting for posts by admins on imageboards.\ diff --git a/include/Body.hpp b/include/Body.hpp index 35928cb..b90f64a 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -12,14 +12,14 @@ namespace QuickMedia { class BodyItem { public: - BodyItem(std::string _title): visible(true), num_lines(0) { + BodyItem(std::string _title): visible(true), num_lines(1) { set_title(std::move(_title)); } void set_title(std::string new_title) { title = std::move(new_title); // TODO: Optimize this - num_lines = 0; + num_lines = 1; for(char c : title) { if(c == '\n') ++num_lines; diff --git a/include/SearchBar.hpp b/include/SearchBar.hpp index 88eed19..e986368 100644 --- a/include/SearchBar.hpp +++ b/include/SearchBar.hpp @@ -20,6 +20,8 @@ namespace QuickMedia { void onWindowResize(const sf::Vector2f &window_size); void onTextEntered(sf::Uint32 codepoint); void clear(); + void append_text(const std::string &text_to_add); + bool is_cursor_at_start_of_line() const; float getBottom() const; float getBottomWithoutShadow() const; @@ -36,6 +38,7 @@ namespace QuickMedia { bool show_placeholder; bool updated_search; bool draw_logo; + bool needs_update; sf::Clock time_since_search_update; }; } \ No newline at end of file diff --git a/src/Body.cpp b/src/Body.cpp index 54eba54..50d46ce 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -133,7 +133,7 @@ namespace QuickMedia { // TODO: Load thumbnails with more than one thread. // TODO: Show chapters (rows) that have been read differently to make it easier to see what hasn't been read yet. void Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const Json::Value &content_progress) { - const float font_height = title_text.getCharacterSize() + 4.0f; + const float font_height = title_text.getCharacterSize() + title_text.getLineSpacing() + 4.0f; const float image_max_height = 100.0f; const float spacing_y = 15.0f; const float padding_x = 10.0f; @@ -178,7 +178,7 @@ namespace QuickMedia { for(; first_visible_item >= 0; --first_visible_item) { auto &item = items[first_visible_item]; if(item->visible) { - float item_height = font_height * std::max(1, item->num_lines); + float item_height = font_height * item->num_lines; if(!item->author.empty()) { item_height += author_text.getCharacterSize() + 2.0f; } @@ -212,7 +212,7 @@ namespace QuickMedia { if(!item->visible) continue; - float item_height = font_height * std::max(1, item->num_lines); + float item_height = font_height * item->num_lines; if(!item->author.empty()) { item_height += author_text.getCharacterSize() + 2.0f; } @@ -318,10 +318,8 @@ namespace QuickMedia { } for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) { - if(!it->second.referenced) { - fprintf(stderr, "Remove no longer referenced thumbnail: %p\n", it->second.texture.get()); + if(!it->second.referenced) it = item_thumbnail_textures.erase(it); - } else ++it; } diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index a9e5a89..059cecf 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -23,8 +23,9 @@ #include #include -const sf::Color back_color(30, 32, 34); -const int DOUBLE_CLICK_TIME = 500; +static const sf::Color back_color(30, 32, 34); +static const int DOUBLE_CLICK_TIME = 500; +static const std::string fourchan_google_captcha_api_key = "6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc"; // Prevent writing to broken pipe from exiting the program static void sigpipe_handler(int unused) { @@ -1460,8 +1461,6 @@ namespace QuickMedia { const std::string &board = image_board_thread_list_url; const std::string &thread = content_url; - fprintf(stderr, "boards: %s, thread: %s\n", board.c_str(), thread.c_str()); - // TODO: Instead of using stage here, use different pages for each stage enum class NavigationStage { VIEWING_COMMENTS, @@ -1533,7 +1532,6 @@ namespace QuickMedia { for(size_t i = 0; i < selected_captcha_images.size(); ++i) { selected_captcha_images[i] = false; } - const std::string fourchan_google_captcha_api_key = "6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc"; const std::string referer = "https://boards.4chan.org/"; captcha_request_future = google_captcha_request_challenge(fourchan_google_captcha_api_key, referer, [&navigation_stage, &request_google_captcha_image, &challenge_info](std::optional new_challenge_info) { @@ -1694,9 +1692,13 @@ namespace QuickMedia { body->items[reply_index]->visible = true; } } - } else if(event.key.code == sf::Keyboard::R && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) && selected_item) { + } else if(event.key.code == sf::Keyboard::C && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) && selected_item) { navigation_stage = NavigationStage::REPLYING; - fprintf(stderr, "Replying!\n"); + } else if(event.key.code == sf::Keyboard::R && selected_item) { + std::string text_to_add = ">>" + selected_item->post_number; + if(search_bar->is_cursor_at_start_of_line()) + text_to_add += '\n'; + search_bar->append_text(text_to_add); } } else if(event.type == sf::Event::TextEntered && navigation_stage == NavigationStage::REPLYING) { search_bar->onTextEntered(event.text.unicode); @@ -1704,7 +1706,7 @@ namespace QuickMedia { if(event.type == sf::Event::KeyPressed && navigation_stage == NavigationStage::REPLYING) { if(event.key.code == sf::Keyboard::Escape) { - search_bar->clear(); + //search_bar->clear(); navigation_stage = NavigationStage::VIEWING_COMMENTS; } } @@ -1727,7 +1729,6 @@ namespace QuickMedia { navigation_stage = NavigationStage::VIEWING_COMMENTS; } else if(event.key.code == sf::Keyboard::Enter) { navigation_stage = NavigationStage::POSTING_SOLUTION; - const std::string fourchan_google_captcha_api_key = "6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc"; captcha_post_solution_future = google_captcha_post_solution(fourchan_google_captcha_api_key, challenge_info.id, selected_captcha_images, [&navigation_stage, &captcha_post_id, &captcha_solved_time, &selected_captcha_images, &challenge_info, &request_google_captcha_image, &post_comment](std::optional new_captcha_post_id, std::optional new_challenge_info) { if(navigation_stage != NavigationStage::POSTING_SOLUTION) @@ -1849,6 +1850,7 @@ namespace QuickMedia { search_bar->draw(window); } else if(navigation_stage == NavigationStage::VIEWING_COMMENTS) { body->draw(window, body_pos, body_size); + search_bar->draw(window); } window.display(); } @@ -1862,5 +1864,11 @@ namespace QuickMedia { post_comment_future.get(); if(load_image_future.valid()) load_image_future.get(); + + // Clear post that is still being written. + // TODO: A multiline text edit widget should be cleared instead of the search bar. + // TODO: This post should be saved for the thread. Each thread should have its own text edit widget, + // so you dont have to retype a post that was in the middle of being posted when returning. + search_bar->clear(); } } \ No newline at end of file diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp index 78cacb9..985f931 100644 --- a/src/SearchBar.cpp +++ b/src/SearchBar.cpp @@ -1,6 +1,7 @@ #include "../include/SearchBar.hpp" #include "../include/Scale.hpp" #include +#include const sf::Color text_placeholder_color(255, 255, 255, 100); const sf::Color front_color(43, 45, 47); @@ -17,7 +18,8 @@ namespace QuickMedia { text("Search...", font, 18), show_placeholder(true), updated_search(false), - draw_logo(false) + draw_logo(false), + needs_update(false) { text.setFillColor(text_placeholder_color); background.setFillColor(front_color); @@ -31,6 +33,11 @@ namespace QuickMedia { } void SearchBar::draw(sf::RenderWindow &window, bool draw_shadow) { + if(needs_update) { + needs_update = false; + sf::Vector2u window_size = window.getSize(); + onWindowResize(sf::Vector2f(window_size.x, window_size.y)); + } if(draw_shadow) window.draw(background_shadow); window.draw(shade); @@ -60,14 +67,14 @@ namespace QuickMedia { draw_logo = false; } - float font_height = text.getCharacterSize() + 8.0f; + float font_height = text.getLocalBounds().height + 8.0f; float rect_height = std::floor(font_height + background_margin_vertical * 2.0f); float offset_x = padding_horizontal; if(draw_logo) { auto texture_size = plugin_logo_sprite.getTexture()->getSize(); sf::Vector2f texture_size_f(texture_size.x, texture_size.y); - sf::Vector2f new_size = wrap_to_size(texture_size_f, sf::Vector2f(200.0f, rect_height)); + sf::Vector2f new_size = wrap_to_size(texture_size_f, sf::Vector2f(200.0f, text.getCharacterSize() + 8.0f)); plugin_logo_sprite.setScale(get_ratio(texture_size_f, new_size)); plugin_logo_sprite.setPosition(25.0f, padding_vertical); offset_x = 25.0f + new_size.x + 25.0f; @@ -87,6 +94,9 @@ namespace QuickMedia { if(codepoint == 8 && !show_placeholder) { // Backspace sf::String str = text.getString(); if(str.getSize() > 0) { + // TODO: When it's possible to move the cursor, then check at cursor position instead of end of the string + if(str[str.getSize() - 1] == '\n') + needs_update = true; str.erase(str.getSize() - 1, 1); text.setString(str); if(str.getSize() == 0) { @@ -102,11 +112,8 @@ namespace QuickMedia { if(onTextSubmitCallback) clear_search = onTextSubmitCallback(text.getString()); - if(clear_search && !show_placeholder) { - show_placeholder = true; - text.setString("Search..."); - text.setFillColor(text_placeholder_color); - } + if(clear_search) + clear(); } else if(codepoint > 31) { // Non-control character if(show_placeholder) { show_placeholder = false; @@ -118,13 +125,37 @@ namespace QuickMedia { text.setString(str); updated_search = true; time_since_search_update.restart(); - } + } else if(codepoint == '\n') + needs_update = true; } void SearchBar::clear() { + if(show_placeholder) + return; show_placeholder = true; text.setString("Search..."); text.setFillColor(text_placeholder_color); + needs_update = true; + } + + void SearchBar::append_text(const std::string &text_to_add) { + if(show_placeholder) { + show_placeholder = false; + text.setString(""); + text.setFillColor(sf::Color::White); + } + sf::String str = text.getString(); + str += text_to_add; + text.setString(str); + updated_search = true; + time_since_search_update.restart(); + needs_update = true; + } + + bool SearchBar::is_cursor_at_start_of_line() const { + // TODO: When it's possible to move the cursor, then check at the cursor position instead of end of the string + const sf::String &str = text.getString(); + return show_placeholder || str.getSize() == 0 || str[str.getSize() - 1] == '\n'; } float SearchBar::getBottom() const { diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp index f19d3aa..88bcafa 100644 --- a/src/plugins/Fourchan.cpp +++ b/src/plugins/Fourchan.cpp @@ -212,6 +212,8 @@ namespace QuickMedia { } } ); + if(!comment_text.empty() && comment_text.back() == '\n') + comment_text.back() = ' '; html_unescape_sequences(comment_text); // TODO: Do the same when wrapping is implemented int num_lines = 0; @@ -333,6 +335,8 @@ namespace QuickMedia { } } ); + if(!comment_text.empty() && comment_text.back() == '\n') + comment_text.back() = ' '; html_unescape_sequences(comment_text); BodyItem *body_item = result_items[body_item_index].get(); body_item->set_title(std::move(comment_text)); -- cgit v1.2.3