diff options
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r-- | src/QuickMedia.cpp | 312 |
1 files changed, 134 insertions, 178 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 0e8e197..37c5223 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -28,6 +28,7 @@ #include "../include/SfmlFixes.hpp" #include "../include/ResourceLoader.hpp" #include "../include/Utils.hpp" +#include "../include/Tabs.hpp" #include "../external/hash-library/sha256.h" #include <assert.h> @@ -50,10 +51,6 @@ static const sf::Color back_color(21, 25, 30); static const std::string fourchan_google_captcha_api_key = "6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc"; -static const float tab_text_size = std::floor(16.0f * QuickMedia::get_ui_scale()); -static const float tab_height = tab_text_size + std::floor(10.0f * QuickMedia::get_ui_scale()); -static const sf::Color tab_selected_color(55, 60, 68); -static const float tab_margin_x = std::floor(10.0f); static int FPS_IDLE = 2; static const double IDLE_TIMEOUT_SEC = 2.0; static const sf::Vector2i AVATAR_THUMBNAIL_SIZE(std::floor(32 * QuickMedia::get_ui_scale()), std::floor(32 * QuickMedia::get_ui_scale())); @@ -263,6 +260,7 @@ namespace QuickMedia { return search_page->submit(title, url, result_tabs); } void on_navigate_to_page(Body *body) override { + std::string selected_item_url = body->get_selected() ? body->get_selected()->url : ""; body->clear_items(); switch(history_type) { case HistoryType::YOUTUBE: @@ -273,6 +271,20 @@ namespace QuickMedia { break; } body->filter_search_fuzzy(search_bar->get_text()); + int item_to_revert_selection_to = get_body_item_by_url(body, selected_item_url); + if(item_to_revert_selection_to != -1) + body->set_selected_item(item_to_revert_selection_to, false); + } + + // Returns index to item or -1 if not found + int get_body_item_by_url(Body *body, const std::string &url) { + if(url.empty()) return -1; + for(size_t i = 0; i < body->items.size(); ++i) { + auto &body_item = body->items[i]; + if(body_item->url == url) + return i; + } + return -1; } private: Page *search_page; @@ -403,8 +415,7 @@ namespace QuickMedia { disp(nullptr), window_size(1280, 720), current_page(PageType::EXIT), - image_index(0), - tab_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10) + image_index(0) { } @@ -434,7 +445,7 @@ namespace QuickMedia { fprintf(stderr, " quickmedia launcher\n"); fprintf(stderr, " quickmedia --upscale-images-always manganelo\n"); fprintf(stderr, " echo -e \"hello\\nworld\" | quickmedia stdin\n"); - fprintf(stderr, " tabbed quickmedia launcher -e\n"); + fprintf(stderr, " tabbed -c -k quickmedia launcher -e\n"); } static bool is_manga_plugin(const char *plugin_name) { @@ -846,11 +857,11 @@ namespace QuickMedia { tabs.push_back(Tab{std::move(history_body), std::move(history_page), std::move(search_bar)}); } else if(strcmp(plugin_name, "manga") == 0) { auto manganelo = std::make_unique<ManganeloSearchPage>(this); - auto manganelos = std::make_unique<MangaGenericSearchPage>(this, plugin_name, nullptr); + auto manganelos = std::make_unique<MangaGenericSearchPage>(this, "manganelos", nullptr); add_manganelos_handlers(manganelos.get()); - auto mangatown = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "https://www.mangatown.com"); + auto mangatown = std::make_unique<MangaGenericSearchPage>(this, "mangatown", "https://www.mangatown.com"); add_mangatown_handlers(mangatown.get()); - auto mangakatana = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "https://mangakatana.com", false); + auto mangakatana = std::make_unique<MangaGenericSearchPage>(this, "mangakatana", "https://mangakatana.com", false); add_mangakatana_handlers(mangakatana.get()); std::vector<MangaPlugin> pages; @@ -1148,12 +1159,12 @@ namespace QuickMedia { float body_padding_horizontal = 10.0f; float body_padding_vertical = std::floor(10.0f); float body_width = window_size.x - body_padding_horizontal * 2.0f; - if(body_width <= 480.0f) { + /*if(body_width <= 480.0f) { body_width = window_size.x; - body_padding_horizontal = 0.0f; - } + body_padding_horizontal = 10.0f; + }*/ - float tab_h = tab_height + std::floor(10.0f * get_ui_scale()); + float tab_h = Tabs::get_shade_height(); if(!search_bar) tab_h += std::floor(10.0f * get_ui_scale()); @@ -1214,40 +1225,12 @@ namespace QuickMedia { pipe_selected_text = text; } - void Program::page_loop_render(sf::RenderWindow &window, std::vector<Tab> &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters) { + void Program::page_loop_render(sf::RenderWindow &window, std::vector<Tab> &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters, Tabs &ui_tabs) { if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->draw(window, false); - { - float shade_extra_height = 0.0f; - if(!tabs[selected_tab].search_bar) - shade_extra_height = std::floor(10.0f * get_ui_scale()); - - const float width_per_tab = window_size.x / tabs.size(); - tab_background.setSize(sf::Vector2f(std::floor(width_per_tab - tab_margin_x * 2.0f), tab_height)); - - float tab_vertical_offset = tabs[selected_tab].search_bar ? tabs[selected_tab].search_bar->getBottomWithoutShadow() : 0.0f; - tabs[selected_tab].body->draw(window, body_pos, body_size, *json_chapters); - const float tab_y = std::floor(tab_vertical_offset + tab_height * 0.5f - (tab_text_size + std::floor(5.0f * get_ui_scale())) * 0.5f) + shade_extra_height; - - tab_shade.setPosition(0.0f, std::floor(tab_vertical_offset)); - tab_shade.setSize(sf::Vector2f(window_size.x, shade_extra_height + tab_height + std::floor(10.0f * get_ui_scale()))); - window.draw(tab_shade); - - int i = 0; - // TODO: Dont show tabs if there is only one tab - for(Tab &tab : tabs) { - if(i == selected_tab) { - tab_background.setPosition(std::floor(i * width_per_tab + tab_margin_x), std::floor(tab_vertical_offset) + shade_extra_height); - window.draw(tab_background); - } - const float center = (i * width_per_tab) + (width_per_tab * 0.5f); - // TODO: Optimize. Only set once for each tab! - tab_text.setString(tab.page->get_title()); - tab_text.setPosition(std::floor(center - tab_text.getLocalBounds().width * 0.5f), std::floor(tab_y)); - window.draw(tab_text); - ++i; - } - } + float tab_vertical_offset = tabs[selected_tab].search_bar ? tabs[selected_tab].search_bar->getBottomWithoutShadow() : 0.0f; + ui_tabs.draw(window, sf::Vector2f(0.0f, tab_vertical_offset), window_size.x); + tabs[selected_tab].body->draw(window, body_pos, body_size, *json_chapters); if(tab_associated_data.fetching_next_page_running) window.draw(gradient_points, 4, sf::Quads); // Note: sf::Quads doesn't work with egl @@ -1285,11 +1268,25 @@ namespace QuickMedia { malloc_trim(0); idle = true; + bool loop_running = true; + bool redraw = true; + for(Tab &tab : tabs) { tab.body->thumbnail_max_size = tab.page->get_thumbnail_max_size(); tab.page->on_navigate_to_page(tab.body.get()); } + Tabs ui_tabs; + for(auto &tab : tabs) { + ui_tabs.add_tab(tab.page->get_title()); + } + ui_tabs.set_selected(start_tab_index); + + ui_tabs.on_change_tab = [&tabs, &redraw](int selected_tab) { + tabs[selected_tab].body->clear_cache(); + redraw = true; + }; + const Json::Value *json_chapters = &Json::Value::nullSingleton(); if(content_storage_json.isObject()) { const Json::Value &chapters_json = content_storage_json["chapters"]; @@ -1310,19 +1307,14 @@ namespace QuickMedia { double gradient_inc = 0.0; const float gradient_height = 5.0f; - tab_text = sf::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); - int selected_tab = std::min(std::max(0, start_tab_index), (int)tabs.size() - 1); - - bool loop_running = true; - bool redraw = true; - auto window_size_u = window.getSize(); window_size.x = window_size_u.x; window_size.y = window_size_u.y; std::function<void(const std::string&)> submit_handler; - submit_handler = [this, &submit_handler, &after_submit_handler, &json_chapters, &tabs, &tab_associated_data, &selected_tab, &loop_running, &redraw](const std::string &search_text) { + submit_handler = [this, &submit_handler, &after_submit_handler, &json_chapters, &tabs, &tab_associated_data, &ui_tabs, &loop_running, &redraw](const std::string &search_text) { + const int selected_tab = ui_tabs.get_selected(); auto selected_item = tabs[selected_tab].body->get_selected_shared(); if(!selected_item && !tabs[selected_tab].page->allow_submit_no_selection()) return; @@ -1499,15 +1491,13 @@ namespace QuickMedia { } sf::Event event; - - tab_shade.setFillColor(sf::Color(33, 37, 44)); - tab_background.setFillColor(tab_selected_color); - sf::Clock frame_timer; while (window.isOpen() && loop_running) { sf::Int32 frame_time_ms = frame_timer.restart().asMilliseconds(); while (window.pollEvent(event)) { + const int selected_tab = ui_tabs.get_selected(); + if(tabs[selected_tab].body->on_event(window, event)) idle_active_handler(); else @@ -1525,6 +1515,8 @@ namespace QuickMedia { tabs[selected_tab].search_bar->on_event(event); } + ui_tabs.on_event(event); + if(event.type == sf::Event::Resized || event.type == sf::Event::GainedFocus) redraw = true; else if(event.type == sf::Event::KeyPressed) { @@ -1574,18 +1566,6 @@ namespace QuickMedia { tabs[selected_tab].body->select_first_item(); } else if(event.key.code == sf::Keyboard::Escape) { goto page_end; - } else if(event.key.code == sf::Keyboard::Left || (event.key.control && event.key.code == sf::Keyboard::H)) { - if(selected_tab > 0) { - tabs[selected_tab].body->clear_cache(); - --selected_tab; - redraw = true; - } - } else if(event.key.code == sf::Keyboard::Right || (event.key.control && event.key.code == sf::Keyboard::L)) { - if(selected_tab < (int)tabs.size() - 1) { - tabs[selected_tab].body->clear_cache(); - ++selected_tab; - redraw = true; - } } else if(event.key.code == sf::Keyboard::Tab) { if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->set_to_autocomplete(); } else if(event.key.code == sf::Keyboard::Enter) { @@ -1614,6 +1594,8 @@ namespace QuickMedia { if(!loop_running || !window.isOpen()) break; + const int selected_tab = ui_tabs.get_selected(); + if(redraw) { redraw = false; if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->onWindowResize(window_size); @@ -1722,7 +1704,7 @@ namespace QuickMedia { } window.clear(back_color); - page_loop_render(window, tabs, selected_tab, tab_associated_data[selected_tab], json_chapters); + page_loop_render(window, tabs, selected_tab, tab_associated_data[selected_tab], json_chapters, ui_tabs); window.display(); if(go_to_previous_page) { @@ -3215,10 +3197,10 @@ namespace QuickMedia { float body_padding_horizontal = 10.0f; float body_padding_vertical = std::floor(10.0f); float body_width = window_size.x - body_padding_horizontal * 2.0f; - if(body_width <= 480.0f) { + /*if(body_width <= 480.0f) { body_width = window_size.x; body_padding_horizontal = 0.0f; - } + }*/ comment_input_shade.setSize(sf::Vector2f(window_size.x, chat_input_height_full)); comment_input_shade.setPosition(0.0f, 0.0f); @@ -3420,7 +3402,6 @@ namespace QuickMedia { struct ChatTab { std::unique_ptr<Body> body; AsyncTask<BodyItems> future; - sf::Text text; }; static const sf::Vector2i CHAT_MESSAGE_THUMBNAIL_MAX_SIZE(600, 337); @@ -3572,7 +3553,6 @@ namespace QuickMedia { pinned_tab.body->thumbnail_mask_shader = &circle_mask_shader; pinned_tab.body->attach_side = AttachSide::BOTTOM; pinned_tab.body->line_separator_color = sf::Color::Transparent; - pinned_tab.text = sf::Text("Pinned messages", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); tabs.push_back(std::move(pinned_tab)); ChatTab messages_tab; @@ -3581,7 +3561,6 @@ namespace QuickMedia { messages_tab.body->thumbnail_mask_shader = &circle_mask_shader; messages_tab.body->attach_side = AttachSide::BOTTOM; messages_tab.body->line_separator_color = sf::Color::Transparent; - messages_tab.text = sf::Text("Messages", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); tabs.push_back(std::move(messages_tab)); // ChatTab users_tab; @@ -3593,14 +3572,56 @@ namespace QuickMedia { // users_tab.text = sf::Text("Users", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); // tabs.push_back(std::move(users_tab)); - const int PINNED_TAB_INDEX = 0; - const int MESSAGES_TAB_INDEX = 1; - //const int USERS_TAB_INDEX = 2; + Tabs ui_tabs(back_color); + const int PINNED_TAB_INDEX = ui_tabs.add_tab("Pinned messages (0)"); + const int MESSAGES_TAB_INDEX = ui_tabs.add_tab("Messages"); + ui_tabs.set_selected(MESSAGES_TAB_INDEX); matrix_chat_page->chat_body = tabs[MESSAGES_TAB_INDEX].body.get(); matrix_chat_page->messages_tab_visible = true; - int selected_tab = MESSAGES_TAB_INDEX; + bool redraw = true; + + sf::Clock read_marker_timer; + const sf::Int32 read_marker_timeout_ms_default = 3000; + sf::Int32 read_marker_timeout_ms = 0; + + AsyncTask<void> set_read_marker_future; + bool setting_read_marker = false; + + sf::Clock start_typing_timer; + const double typing_timeout_seconds = 3.0; + bool typing = false; + + MessageQueue<bool> typing_state_queue; + auto typing_state_handler = [this, ¤t_room, &typing_state_queue]() { + while(true) { + std::optional<bool> state_opt = typing_state_queue.pop_wait(); + if(!state_opt) + break; + + bool state = state_opt.value(); + if(state) + matrix->on_start_typing(current_room); + else + matrix->on_stop_typing(current_room); + } + }; + std::thread typing_state_thread(typing_state_handler); + + ui_tabs.on_change_tab = [matrix_chat_page, &redraw, &typing, &typing_state_queue, &read_marker_timer, &tabs, MESSAGES_TAB_INDEX](int selected_tab) { + tabs[selected_tab].body->clear_cache(); + if(selected_tab == MESSAGES_TAB_INDEX) + matrix_chat_page->messages_tab_visible = true; + read_marker_timer.restart(); + redraw = true; + if(typing) { + fprintf(stderr, "Stopped typing\n"); + typing = false; + typing_state_queue.push(false); + } + }; + bool is_window_focused = window.hasFocus(); enum class ChatState { @@ -3633,14 +3654,6 @@ namespace QuickMedia { sf::Sprite room_avatar_sprite; auto room_avatar_thumbnail_data = std::make_shared<ThumbnailData>(); - sf::Clock read_marker_timer; - const sf::Int32 read_marker_timeout_ms_default = 3000; - sf::Int32 read_marker_timeout_ms = 0; - - AsyncTask<void> set_read_marker_future; - bool setting_read_marker = false; - - bool redraw = true; bool draw_room_list = show_room_side_panel; // TODO: What if these never end up referencing events? clean up automatically after a while? @@ -3700,7 +3713,7 @@ namespace QuickMedia { }; // TODO: Optimize find_body_item_by_event_id hash map? - auto modify_related_messages_in_current_room = [this, ¤t_room, &set_body_as_deleted, &unreferenced_events, &tabs](Messages &messages) { + auto modify_related_messages_in_current_room = [this, ¤t_room, &set_body_as_deleted, &unreferenced_events, &tabs, MESSAGES_TAB_INDEX](Messages &messages) { if(messages.empty()) return; @@ -3734,7 +3747,7 @@ namespace QuickMedia { std::vector<std::shared_ptr<Message>> unresolved_reactions; // TODO: Optimize find_body_item_by_event_id hash map? - auto process_reactions = [&tabs, &unresolved_reactions, ¤t_room](Messages &messages) { + auto process_reactions = [&tabs, &unresolved_reactions, ¤t_room, MESSAGES_TAB_INDEX](Messages &messages) { if(messages.empty()) return; @@ -3779,7 +3792,7 @@ namespace QuickMedia { } }; - auto pinned_body_items_contains_event = [&tabs](const std::string &event_id) { + auto pinned_body_items_contains_event = [&tabs, PINNED_TAB_INDEX](const std::string &event_id) { for(auto &body_item : tabs[PINNED_TAB_INDEX].body->items) { if(static_cast<PinnedEventData*>(body_item->userdata)->event_id == event_id) return true; @@ -3787,7 +3800,7 @@ namespace QuickMedia { return false; }; - auto process_pinned_events = [&tabs, &pinned_body_items_contains_event](const std::optional<std::vector<std::string>> &pinned_events) { + auto process_pinned_events = [&tabs, &ui_tabs, &pinned_body_items_contains_event, PINNED_TAB_INDEX](const std::optional<std::vector<std::string>> &pinned_events) { if(!pinned_events) return; @@ -3821,7 +3834,7 @@ namespace QuickMedia { else tabs[PINNED_TAB_INDEX].body->set_selected_item(selected_before); - tabs[PINNED_TAB_INDEX].text.setString("Pinned messages (" + std::to_string(tabs[PINNED_TAB_INDEX].body->items.size()) + ")"); + ui_tabs.set_text(PINNED_TAB_INDEX, "Pinned messages (" + std::to_string(tabs[PINNED_TAB_INDEX].body->items.size()) + ")"); }; Body url_selection_body(this, loading_icon); @@ -3891,7 +3904,7 @@ namespace QuickMedia { }; std::thread post_thread(post_thread_handler); - auto message_set_replaced_by = [&tabs, &pending_sent_replies](std::shared_ptr<Message> message) { + auto message_set_replaced_by = [&tabs, &pending_sent_replies, MESSAGES_TAB_INDEX](std::shared_ptr<Message> message) { if(message->related_event_type == RelatedEventType::EDIT) { auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), message->related_event_id); if(body_item) { @@ -3922,7 +3935,7 @@ namespace QuickMedia { } }; - auto upload_file = [this, &tabs, ¤t_room](const std::string &filepath) { + auto upload_file = [this, &tabs, ¤t_room, MESSAGES_TAB_INDEX](const std::string &filepath) { TaskResult post_file_result = run_task_with_loading_screen([this, ¤t_room, filepath]() { std::string event_id_response; std::string err_msg; @@ -3942,11 +3955,12 @@ namespace QuickMedia { bool frame_skip_text_entry = false; - chat_input.on_submit_callback = [this, &frame_skip_text_entry, &tabs, &me, &chat_input, &selected_tab, ¤t_room, &new_page, &chat_state, &pending_sent_replies, ¤tly_operating_on_item, &post_task_queue, &process_reactions](std::string text) mutable { + chat_input.on_submit_callback = [this, &frame_skip_text_entry, &tabs, &me, &chat_input, &ui_tabs, MESSAGES_TAB_INDEX, ¤t_room, &new_page, &chat_state, &pending_sent_replies, ¤tly_operating_on_item, &post_task_queue, &process_reactions](std::string text) mutable { if(!current_room) return false; frame_skip_text_entry = true; + const int selected_tab = ui_tabs.get_selected(); if(selected_tab == MESSAGES_TAB_INDEX) { if(text.empty()) @@ -4126,7 +4140,7 @@ namespace QuickMedia { int fetch_message_tab = -1; // TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads. - tabs[PINNED_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab](BodyItem *body_item) { + tabs[PINNED_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab, PINNED_TAB_INDEX, MESSAGES_TAB_INDEX](BodyItem *body_item) { if(fetch_message_future.valid()) return; @@ -4200,7 +4214,7 @@ namespace QuickMedia { bool remove_unread_marker = false; // TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads. - tabs[MESSAGES_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &remove_unread_marker, &fetch_message_future, &tabs, &is_window_focused, &chat_state, &setting_read_marker, &read_marker_timer, &read_marker_timeout_ms, &set_read_marker_future, &fetch_body_item, &fetch_message_tab](BodyItem *body_item) { + tabs[MESSAGES_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &remove_unread_marker, &fetch_message_future, &tabs, &is_window_focused, &chat_state, &setting_read_marker, &read_marker_timer, &read_marker_timeout_ms, &set_read_marker_future, &fetch_body_item, &fetch_message_tab, MESSAGES_TAB_INDEX](BodyItem *body_item) { Message *message = static_cast<Message*>(body_item->userdata); if(!message) return; @@ -4281,17 +4295,10 @@ namespace QuickMedia { return false; }; - const float tab_spacer_height = 0.0f; sf::Vector2f body_pos; sf::Vector2f body_size; sf::Event event; - sf::RectangleShape tab_shade; - tab_shade.setFillColor(sf::Color(33, 37, 44)); - - sf::RoundedRectangleShape tab_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10); - tab_background.setFillColor(tab_selected_color); - const float gradient_height = 5.0f; sf::Vertex gradient_points[4]; double gradient_inc = 0; @@ -4300,7 +4307,7 @@ namespace QuickMedia { bool fetched_enough_messages = false; - auto fetch_more_previous_messages_if_needed = [this, &tabs, ¤t_room, &fetched_enough_messages, &previous_messages_future]() { + auto fetch_more_previous_messages_if_needed = [this, &tabs, ¤t_room, &fetched_enough_messages, &previous_messages_future, MESSAGES_TAB_INDEX]() { if(!fetched_enough_messages && !previous_messages_future.valid()) { if(tabs[MESSAGES_TAB_INDEX].body->items.size() < 30) { previous_messages_future = AsyncTask<Messages>([this, ¤t_room]() { @@ -4328,28 +4335,8 @@ namespace QuickMedia { sf::RectangleShape chat_input_shade; chat_input_shade.setFillColor(sf::Color(33, 37, 44)); - sf::Clock start_typing_timer; - const double typing_timeout_seconds = 3.0; - bool typing = false; - float tab_vertical_offset = 0.0f; - MessageQueue<bool> typing_state_queue; - auto typing_state_handler = [this, ¤t_room, &typing_state_queue]() { - while(true) { - std::optional<bool> state_opt = typing_state_queue.pop_wait(); - if(!state_opt) - break; - - bool state = state_opt.value(); - if(state) - matrix->on_start_typing(current_room); - else - matrix->on_stop_typing(current_room); - } - }; - std::thread typing_state_thread(typing_state_handler); - sf::Clock frame_timer; float prev_chat_height = chat_input.get_height(); @@ -4400,10 +4387,11 @@ namespace QuickMedia { } }; - auto add_new_messages_to_current_room = [&me, &tabs, &selected_tab, ¤t_room](Messages &messages) { + auto add_new_messages_to_current_room = [&me, &tabs, &ui_tabs, ¤t_room, MESSAGES_TAB_INDEX](Messages &messages) { if(messages.empty()) return; + const int selected_tab = ui_tabs.get_selected(); int num_items = tabs[MESSAGES_TAB_INDEX].body->items.size(); bool scroll_to_end = num_items == 0; if(selected_tab == MESSAGES_TAB_INDEX && (tabs[MESSAGES_TAB_INDEX].body->is_selected_item_last_visible_item() || !tabs[MESSAGES_TAB_INDEX].body->get_selected())) @@ -4428,10 +4416,11 @@ namespace QuickMedia { } }; - auto display_url_or_image = [this, matrix_chat_page, &selected_tab, &redraw, &video_page, &launch_url, &chat_state, &url_selection_body](BodyItem *selected) { + auto display_url_or_image = [this, matrix_chat_page, &ui_tabs, &redraw, &video_page, &launch_url, &chat_state, &url_selection_body, PINNED_TAB_INDEX, MESSAGES_TAB_INDEX](BodyItem *selected) { if(!selected) return false; + const int selected_tab = ui_tabs.get_selected(); Message *selected_item_message = nullptr; if(selected_tab == MESSAGES_TAB_INDEX) { selected_item_message = static_cast<Message*>(selected->userdata); @@ -4480,7 +4469,7 @@ namespace QuickMedia { return false; }; - auto update_pinned_messages_author = [&tabs, ¤t_room](const std::shared_ptr<UserInfo> &user) { + auto update_pinned_messages_author = [&tabs, ¤t_room, PINNED_TAB_INDEX](const std::shared_ptr<UserInfo> &user) { fprintf(stderr, "updated pinned messages author for user: %s\n", user->user_id.c_str()); for(auto &pinned_body_item : tabs[PINNED_TAB_INDEX].body->items) { Message *message = static_cast<PinnedEventData*>(pinned_body_item->userdata)->message; @@ -4492,7 +4481,7 @@ namespace QuickMedia { } }; - auto update_messages_author = [&tabs, ¤t_room](const std::shared_ptr<UserInfo> &user) { + auto update_messages_author = [&tabs, ¤t_room, MESSAGES_TAB_INDEX](const std::shared_ptr<UserInfo> &user) { fprintf(stderr, "updated messages author for user: %s\n", user->user_id.c_str()); for(auto &message_body_items : tabs[MESSAGES_TAB_INDEX].body->items) { Message *message = static_cast<Message*>(message_body_items->userdata); @@ -4504,7 +4493,7 @@ namespace QuickMedia { }; // TODO: Optimize - auto update_pinned_messages_authors = [&tabs, ¤t_room]() { + auto update_pinned_messages_authors = [&tabs, ¤t_room, PINNED_TAB_INDEX]() { fprintf(stderr, "updated pinned messages author for all users in room: %s\n", current_room->id.c_str()); for(auto &pinned_body_item : tabs[PINNED_TAB_INDEX].body->items) { Message *message = static_cast<PinnedEventData*>(pinned_body_item->userdata)->message; @@ -4517,7 +4506,7 @@ namespace QuickMedia { }; // TODO: Optimize - auto update_messages_authors = [&tabs, ¤t_room]() { + auto update_messages_authors = [&tabs, ¤t_room, MESSAGES_TAB_INDEX]() { fprintf(stderr, "updated messages author for all users in room: %s\n", current_room->id.c_str()); for(auto &message_body_items : tabs[MESSAGES_TAB_INDEX].body->items) { Message *message = static_cast<Message*>(message_body_items->userdata); @@ -4528,7 +4517,7 @@ namespace QuickMedia { } }; - auto cleanup_tasks = [&set_read_marker_future, &fetch_message_future, &fetch_users_future, &typing_state_queue, &typing_state_thread, &post_task_queue, &provisional_message_queue, &fetched_messages_set, &sent_messages, &pending_sent_replies, &post_thread, &tabs]() { + auto cleanup_tasks = [&set_read_marker_future, &fetch_message_future, &fetch_users_future, &typing_state_queue, &typing_state_thread, &post_task_queue, &provisional_message_queue, &fetched_messages_set, &sent_messages, &pending_sent_replies, &post_thread, &tabs, PINNED_TAB_INDEX]() { set_read_marker_future.cancel(); fetch_message_future.cancel(); fetch_users_future.cancel(); @@ -4574,16 +4563,20 @@ namespace QuickMedia { } float tab_shade_height = 0.0f; + SyncData sync_data; room_tabs[room_selected_tab].body->body_item_select_callback = [&move_room](BodyItem *body_item) { move_room = true; }; - SyncData sync_data; - while (current_page == PageType::CHAT && window.isOpen() && !move_room) { sf::Int32 frame_time_ms = frame_timer.restart().asMilliseconds(); while (window.pollEvent(event)) { + const int selected_tab = ui_tabs.get_selected(); + + if(chat_state == ChatState::NAVIGATING) + ui_tabs.on_event(event); + if(chat_state == ChatState::URL_SELECTION) { if(url_selection_body.on_event(window, event)) idle_active_handler(); @@ -4680,30 +4673,6 @@ namespace QuickMedia { tabs[selected_tab].body.get()->select_next_page(); } else if(event.key.code == sf::Keyboard::End) { tabs[selected_tab].body.get()->select_last_item(); - } else if((event.key.code == sf::Keyboard::Left || (event.key.control && event.key.code == sf::Keyboard::H)) && selected_tab > 0) { - tabs[selected_tab].body->clear_cache(); - --selected_tab; - if(selected_tab == MESSAGES_TAB_INDEX) - matrix_chat_page->messages_tab_visible = true; - read_marker_timer.restart(); - redraw = true; - if(typing && current_room) { - fprintf(stderr, "Stopped typing\n"); - typing = false; - typing_state_queue.push(false); - } - } else if((event.key.code == sf::Keyboard::Right || (event.key.control && event.key.code == sf::Keyboard::L)) && selected_tab < (int)tabs.size() - 1) { - tabs[selected_tab].body->clear_cache(); - ++selected_tab; - if(selected_tab == MESSAGES_TAB_INDEX) - matrix_chat_page->messages_tab_visible = true; - read_marker_timer.restart(); - redraw = true; - if(typing && current_room) { - fprintf(stderr, "Stopped typing\n"); - typing = false; - typing_state_queue.push(false); - } } else if(event.key.code == sf::Keyboard::Escape) { goto chat_page_end; } @@ -4960,6 +4929,8 @@ namespace QuickMedia { } } + const int selected_tab = ui_tabs.get_selected(); + float room_name_padding_y = 0.0f; if(selected_tab == MESSAGES_TAB_INDEX || selected_tab == PINNED_TAB_INDEX) room_name_padding_y = room_name_total_height; @@ -4984,15 +4955,15 @@ namespace QuickMedia { tab_vertical_offset = std::floor(10.0f * get_ui_scale()); } - tab_shade_height = tab_spacer_height + std::floor(tab_vertical_offset) + tab_height + room_name_padding_y + padding_bottom; + tab_shade_height = std::floor(tab_vertical_offset) + Tabs::get_height() + room_name_padding_y + padding_bottom; float body_padding_horizontal = 10.0f; float body_padding_vertical = std::floor(10.0f); float body_width = window_size.x - body_padding_horizontal * 2.0f; - if(body_width <= 480.0f) { + /*if(body_width <= 480.0f) { body_width = window_size.x; body_padding_horizontal = 0.0f; - } + }*/ this->body_pos = sf::Vector2f(0.0f, tab_shade_height); if(window_size.x > 900.0f && show_room_side_panel) { @@ -5113,18 +5084,12 @@ namespace QuickMedia { fetch_message_tab = -1; } - //chat_input.update(); - window.clear(back_color); - - const float width_per_tab = body_size.x / tabs.size(); - tab_background.setSize(sf::Vector2f(std::floor(width_per_tab - tab_margin_x * 2.0f), tab_height)); if(chat_state == ChatState::URL_SELECTION) url_selection_body.draw(window, body_pos, body_size); else tabs[selected_tab].body->draw(window, body_pos, body_size); - const float tab_y = tab_spacer_height + std::floor(tab_vertical_offset + tab_height * 0.5f - (tab_text_size + 5.0f) * 0.5f) + room_name_padding_y; //tab_shade.setSize(sf::Vector2f(window_size.x, tab_shade_height)); //window.draw(tab_shade); @@ -5152,21 +5117,12 @@ namespace QuickMedia { window.draw(room_list_background); window.draw(room_label); const float padding_x = std::floor(10.0f * get_ui_scale()); + const float tab_y = std::floor(tab_vertical_offset) + room_name_padding_y; room_tabs[room_selected_tab].body->draw(window, sf::Vector2f(padding_x, tab_y), sf::Vector2f(this->body_size.x - padding_x * 2.0f, window_size.y - tab_y), Json::Value::nullSingleton()); glDisable(GL_SCISSOR_TEST); } - int i = 0; - for(ChatTab &tab : tabs) { - if(i == selected_tab) { - tab_background.setPosition(std::floor(body_pos.x + i * width_per_tab + tab_margin_x), tab_spacer_height + std::floor(tab_vertical_offset) + room_name_padding_y); - window.draw(tab_background); - } - const float center = body_pos.x + (i * width_per_tab) + (width_per_tab * 0.5f); - tab.text.setPosition(std::floor(center - tab.text.getLocalBounds().width * 0.5f), std::floor(tab_y)); - window.draw(tab.text); - ++i; - } + ui_tabs.draw(window, sf::Vector2f(body_pos.x, std::floor(tab_vertical_offset) + room_name_padding_y), body_size.x); // TODO: Have one for each room. Also add bottom one? for fetching new messages (currently not implemented, is it needed?) if(previous_messages_future.valid() && selected_tab == MESSAGES_TAB_INDEX) { |