aboutsummaryrefslogtreecommitdiff
path: root/src/QuickMedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r--src/QuickMedia.cpp312
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, &current_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, &current_room, &set_body_as_deleted, &unreferenced_events, &tabs](Messages &messages) {
+ auto modify_related_messages_in_current_room = [this, &current_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, &current_room](Messages &messages) {
+ auto process_reactions = [&tabs, &unresolved_reactions, &current_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, &current_room](const std::string &filepath) {
+ auto upload_file = [this, &tabs, &current_room, MESSAGES_TAB_INDEX](const std::string &filepath) {
TaskResult post_file_result = run_task_with_loading_screen([this, &current_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, &current_room, &new_page, &chat_state, &pending_sent_replies, &currently_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, &current_room, &new_page, &chat_state, &pending_sent_replies, &currently_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, &current_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, &current_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, &current_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, &current_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, &current_room, &fetched_enough_messages, &previous_messages_future]() {
+ auto fetch_more_previous_messages_if_needed = [this, &tabs, &current_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, &current_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, &current_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, &current_room](Messages &messages) {
+ auto add_new_messages_to_current_room = [&me, &tabs, &ui_tabs, &current_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, &current_room](const std::shared_ptr<UserInfo> &user) {
+ auto update_pinned_messages_author = [&tabs, &current_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, &current_room](const std::shared_ptr<UserInfo> &user) {
+ auto update_messages_author = [&tabs, &current_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, &current_room]() {
+ auto update_pinned_messages_authors = [&tabs, &current_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, &current_room]() {
+ auto update_messages_authors = [&tabs, &current_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) {