From 1406ea55305666958d265855cf400e7fc1cdbbf7 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 7 Apr 2022 15:01:47 +0200 Subject: 4chan: move replies text to reactions, clear reactions when not visible on screen --- TODO | 1 - include/Body.hpp | 1 - include/BodyItem.hpp | 5 +++ src/Body.cpp | 83 +++++++++++++++++++++++++++++------------------- src/BodyItem.cpp | 17 ++++++---- src/QuickMedia.cpp | 2 +- src/plugins/Fourchan.cpp | 2 ++ 7 files changed, 70 insertions(+), 41 deletions(-) diff --git a/TODO b/TODO index 73eb504..4d83999 100644 --- a/TODO +++ b/TODO @@ -135,7 +135,6 @@ Support 4chan archive. Use old method of rendering body where rendering items is done up and down, starting from the selected item. This will make quickmedia run as fast when displaying 100 000 items as when displaying 10 items. Use correct spacing when in grid (card) mode. Should be row spacing instead of body spacing. Instead of selecting the first/last item when reaching the top/bottom, keep the selected column and instead scroll the body so the first/last item is visible. -Cleanup reactions when they are not visible on the screen. Kill async image downloader thread when the item with the image is no longer visible on the screen. Embedding elements in rich text: first byte should be an invalid utf8 character and the next 3 bytes should be an index into a vector with the element data. This forms 1 utf32 character. Do not set fps to monitor hz if no key is pressed and cursor is not moving (for example when the computer is sleeping). (Maybe just detect if any sfml event is received), but maybe that wouldn't work with accelerometer. diff --git a/include/Body.hpp b/include/Body.hpp index ec73a29..373c6b4 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -221,7 +221,6 @@ namespace QuickMedia { mgl::Sprite loading_icon; mgl::Text progress_text; - mgl::Text replies_text; mgl::Text embedded_item_load_text; bool body_size_changed = false; diff --git a/include/BodyItem.hpp b/include/BodyItem.hpp index 2e7dad4..510d0e9 100644 --- a/include/BodyItem.hpp +++ b/include/BodyItem.hpp @@ -52,8 +52,11 @@ namespace QuickMedia { }; struct Reaction { + std::string text_str; std::unique_ptr text; void *userdata = nullptr; + mgl::vec2f size; + mgl::Color text_color; }; class BodyItem { @@ -113,6 +116,7 @@ namespace QuickMedia { dirty_author = true; } + void add_reaction(std::string text, void *userdata, mgl::Color text_color); void add_reaction(std::string text, void *userdata); // Returns true if reaction is found @@ -148,6 +152,7 @@ namespace QuickMedia { bool dirty_description; bool dirty_author; bool dirty_timestamp; + bool dirty_reactions; // TODO: Remove this and instead if |thumbnail_url| starts with file://, then its a local file bool thumbnail_is_local; std::unique_ptr title_text; diff --git a/src/Body.cpp b/src/Body.cpp index 6bf816d..c79f836 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -100,7 +100,6 @@ namespace QuickMedia { prev_selected_item(0), loading_icon(&loading_icon_texture), progress_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, get_config().body.progress_font_size * get_config().scale * get_config().font_scale)), - replies_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, get_config().body.replies_font_size * get_config().scale * get_config().font_scale)), embedded_item_load_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, body_spacing[body_theme].embedded_item_font_size)), num_visible_items(0), top_cut_off(false), @@ -111,7 +110,6 @@ namespace QuickMedia { rounded_rectangle_mask_shader(rounded_rectangle_mask_shader) { progress_text.set_color(get_theme().text_color); - replies_text.set_color(get_theme().replies_text_color); thumbnail_max_size.x = 600; thumbnail_max_size.y = 337; mgl::vec2f loading_icon_size(loading_icon.get_texture()->get_size().x, loading_icon.get_texture()->get_size().y); @@ -925,6 +923,20 @@ namespace QuickMedia { body_item->timestamp_text->set_color(get_theme().timestamp_text_color); } } + + if((body_item->dirty_reactions && !body_item->reactions.empty()) || (body_size_changed && !body_item->reactions.empty() && body_item->reactions.front().text)) { + body_item->dirty_reactions = false; + for(auto &reaction : body_item->reactions) { + if(reaction.text) { + reaction.text->setString(reaction.text_str); + reaction.text->setMaxWidth(width); + } else { + reaction.text = std::make_unique(reaction.text_str, false, floor(get_config().body.reaction_font_size * get_config().scale * get_config().font_scale), width); + } + reaction.text->set_color(reaction.text_color); + reaction.size = { 0.0f, 0.0f }; + } + } } void Body::clear_body_item_cache(BodyItem *body_item) { @@ -944,6 +956,12 @@ namespace QuickMedia { body_item->timestamp_text.reset(); body_item->dirty_timestamp = true; } + if(!body_item->reactions.empty()) { + for(auto &reaction : body_item->reactions) { + reaction.text.reset(); + } + body_item->dirty_reactions = true; + } body_item->keep_alive_frames = 0; } @@ -1429,20 +1447,6 @@ namespace QuickMedia { if(item->author_text && !merge_with_previous) { item->author_text->set_position(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y)); item->author_text->draw(window); - - mgl::vec2f replies_text_pos = item->author_text->get_position(); - replies_text_pos.x += item->author_text->getWidth() + 5.0f; - replies_text.set_position(replies_text_pos); - - std::string replies_text_str; - for(size_t reply_index : item->replies) { - BodyItem *reply_item = items[reply_index].get(); - replies_text_str += " >>"; - replies_text_str += reply_item->post_number; - } - replies_text.set_string(std::move(replies_text_str)); - window.draw(replies_text); - item_pos.y += item->author_text->getHeight() - 2.0f + std::floor(3.0f * get_config().scale); } @@ -1483,21 +1487,27 @@ namespace QuickMedia { float reaction_offset_x = 0.0f; item_pos.y += body_spacing[body_theme].reaction_padding_y; float reaction_max_height = 0.0f; - // TODO: Fix first row wrap-around + int row = 0; for(int i = 0; i < (int)item->reactions.size(); ++i) { auto &reaction = item->reactions[i]; reaction.text->updateGeometry(); - reaction_max_height = std::max(reaction_max_height, reaction.text->getHeight()); - reaction.text->set_position(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x + body_spacing[body_theme].reaction_background_padding_x, item_pos.y + padding_y - 4.0f + body_spacing[body_theme].reaction_background_padding_y)); - reaction_background.set_position(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x, item_pos.y + padding_y)); - reaction_background.set_size(mgl::vec2f(reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f, reaction.text->getHeight() + body_spacing[body_theme].reaction_background_padding_y * 2.0f)); + reaction.size = { reaction.text->getWidth(), reaction.text->getHeight() }; + reaction_max_height = std::max(reaction_max_height, reaction.size.y); + reaction_background.set_size(mgl::vec2f(reaction.size.x + body_spacing[body_theme].reaction_background_padding_x * 2.0f, reaction.size.y + body_spacing[body_theme].reaction_background_padding_y * 2.0f)); reaction_background.draw(window); - reaction_offset_x += reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x; + + const float new_reaction_offset_x = reaction.size.x + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x; reaction.text->draw(window); - if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f > size.x && i < (int)item->reactions.size() - 1) { + if(text_offset_x + new_reaction_offset_x > size.x && row != 0) { reaction_offset_x = 0.0f; - item_pos.y += reaction.text->getHeight() + body_spacing[body_theme].reaction_padding_y + text_offset_y; - reaction_max_height = reaction.text->getHeight(); + item_pos.y += reaction_max_height + body_spacing[body_theme].reaction_padding_y + text_offset_y; + reaction_max_height = reaction.size.y; + row = 0; + } else { + reaction_background.set_position(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x, item_pos.y + padding_y)); + reaction.text->set_position(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x + body_spacing[body_theme].reaction_background_padding_x, item_pos.y + padding_y - 4.0f + body_spacing[body_theme].reaction_background_padding_y)); + reaction_offset_x = new_reaction_offset_x; + ++row; } } item_pos.y += reaction_max_height + body_spacing[body_theme].reaction_padding_y; @@ -1705,16 +1715,25 @@ namespace QuickMedia { float reaction_offset_x = 0.0f; item_height += body_spacing[body_theme].reaction_padding_y; float reaction_max_height = 0.0f; + int row = 0; for(int i = 0; i < (int)item->reactions.size(); ++i) { auto &reaction = item->reactions[i]; - reaction.text->setMaxWidth(text_max_width); - reaction.text->updateGeometry(); - reaction_max_height = std::max(reaction_max_height, reaction.text->getHeight()); - reaction_offset_x += reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x; - if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f > width && i < (int)item->reactions.size() - 1) { + if(reaction.size.x < 0.001f && reaction.text) { + reaction.text->setMaxWidth(text_max_width); + reaction.text->updateGeometry(); + reaction.size = { reaction.text->getWidth(), reaction.text->getHeight() }; + } + reaction_max_height = std::max(reaction_max_height, reaction.size.y); + + const float new_reaction_offset_x = reaction.size.x + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x; + if(text_offset_x + new_reaction_offset_x > width && row != 0) { reaction_offset_x = 0.0f; - item_height += reaction.text->getHeight() + body_spacing[body_theme].reaction_padding_y + std::floor(6.0f * get_config().scale); - reaction_max_height = reaction.text->getHeight(); + item_height += reaction_max_height + body_spacing[body_theme].reaction_padding_y + std::floor(6.0f * get_config().scale); + reaction_max_height = reaction.size.y; + row = 0; + } else { + reaction_offset_x = new_reaction_offset_x; + ++row; } } item_height += reaction_max_height + body_spacing[body_theme].reaction_padding_y; diff --git a/src/BodyItem.cpp b/src/BodyItem.cpp index 0c6e1ce..431616d 100644 --- a/src/BodyItem.cpp +++ b/src/BodyItem.cpp @@ -3,10 +3,6 @@ #include "../include/Config.hpp" namespace QuickMedia { - static float floor(float v) { - return (int)v; - } - // static std::shared_ptr BodyItem::create(std::string title, bool selectable) { return std::shared_ptr(new BodyItem(std::move(title), selectable)); @@ -18,6 +14,7 @@ namespace QuickMedia { dirty_description(false), dirty_author(false), dirty_timestamp(false), + dirty_reactions(false), thumbnail_is_local(false), userdata(nullptr), timestamp(0), @@ -38,6 +35,7 @@ namespace QuickMedia { dirty_description = !other.description.empty(); dirty_author = !other.author.empty(); dirty_timestamp = other.timestamp != 0; + dirty_reactions = !other.reactions.empty(); thumbnail_is_local = other.thumbnail_is_local; title_text.reset(); description_text.reset(); @@ -79,11 +77,18 @@ namespace QuickMedia { return *this; } - void BodyItem::add_reaction(std::string text, void *userdata) { + void BodyItem::add_reaction(std::string text, void *userdata, mgl::Color text_color) { Reaction reaction; - reaction.text = std::make_unique(std::move(text), false, floor(get_config().body.reaction_font_size * get_config().scale * get_config().font_scale), 0.0f); + reaction.text_str = std::move(text); + reaction.text = nullptr; reaction.userdata = userdata; + reaction.text_color = text_color; reactions.push_back(std::move(reaction)); + dirty_reactions = true; + } + + void BodyItem::add_reaction(std::string text, void *userdata) { + add_reaction(std::move(text), userdata, get_theme().text_color); } void BodyItem::draw_list(Body *body, mgl::Window &render_target) { diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 45c0bd1..b83f64a 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -7054,7 +7054,7 @@ namespace QuickMedia { chat_input_shade.set_position(mgl::vec2f(body_pos.x, window_size.y - chat_input_shade.get_size().y)); chat_input.set_max_width(window_size.x - (logo_padding_x + logo_size.x + chat_input_padding_x + logo_padding_x + body_pos.x)); - chat_input.set_position(vec2f_floor(body_pos.x + logo_padding_x + logo_size.x + chat_input_padding_x, window_size.y - chat_height - chat_input_padding_y - 5.0f * get_config().scale)); + chat_input.set_position(vec2f_floor(body_pos.x + logo_padding_x + logo_size.x + chat_input_padding_x, window_size.y - chat_height - chat_input_padding_y)); more_messages_below_rect.set_size(mgl::vec2f(chat_input_shade.get_size().x, gradient_height)); more_messages_below_rect.set_position(mgl::vec2f(chat_input_shade.get_position().x, std::floor(window_size.y - chat_input_height_full - gradient_height))); diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp index 51a3cc5..4522a56 100644 --- a/src/plugins/Fourchan.cpp +++ b/src/plugins/Fourchan.cpp @@ -4,6 +4,7 @@ #include "../../include/StringUtils.hpp" #include "../../include/NetUtils.hpp" #include "../../include/Notification.hpp" +#include "../../include/Theme.hpp" #include "../../external/cppcodec/base64_rfc4648.hpp" #include "../../include/QuickMedia.hpp" #include @@ -273,6 +274,7 @@ namespace QuickMedia { } else { result_items[body_item_index]->replies_to.push_back(it->second); result_items[it->second]->replies.push_back(body_item_index); + result_items[it->second]->add_reaction(">>" + result_items[body_item_index]->post_number, nullptr, get_theme().replies_text_color); } break; } -- cgit v1.2.3