aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--TODO8
-rw-r--r--include/Body.hpp1
-rw-r--r--include/QuickMedia.hpp34
-rw-r--r--src/Body.cpp4
-rw-r--r--src/QuickMedia.cpp286
-rw-r--r--src/SearchBar.cpp2
7 files changed, 194 insertions, 144 deletions
diff --git a/README.md b/README.md
index 4c495d1..a075a10 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,8 @@ Press `R` to reply to a message on matrix, press `ESC` to cancel.\
Press `E` to edit a message on matrix, press `ESC` to cancel. Currently only works for your own messages.\
Press `Ctrl + D` to delete a message on matrix. Currently deleting a message only deletes the event, so if you delete an edit then the original message wont be deleted.\
Press `Ctrl + C` to copy the message of the selected item in matrix to the clipboard.\
-Press `Ctrl + V` to upload media to room in matrix if the clipboard contains a valid absolute filepath.
+Press `Ctrl + V` to upload media to room in matrix if the clipboard contains a valid absolute filepath.\
+Press `Ctrl+Alt+Arrow up` / `Ctrl+Alt+Arrow down` or `Ctrl+Alt+K` / `Ctrl+Alt+J` to select another room in matrix when you are in a room. Press `Ctrl+Alt+Enter` to go to the selected room.
In matrix you can select a message with enter to open the url in the message (or if there are multiple urls then a menu will appear for selecting which to open).
## Matrix commands
diff --git a/TODO b/TODO
index c53a2c9..c8dcbff 100644
--- a/TODO
+++ b/TODO
@@ -29,11 +29,8 @@ Show filename at the bottom when viewing an image/video on 4chan.
Add ctrl+c keybinding to copy the url of the previewing image.
Add ctrl+c keybiding to copy the url to the currently selected post on 4chan.
Add ctrl+s to save the previewing image/video (for images that would be a copy, since its already stored in cache and for videos youtube-dl would be used).
-Show some kind of indication that there are new messages in a room in matrix room view, and also show another indication if somebody mentioned us (and how many times).
-Show the rooms menu on the left side when the window is large in matrix.
Use https://github.com/simdjson/simdjson as a json library in other parts than matrix.
Sanitize check: do not allow pasting more than 2gb of text.
-Add search bar for matrix rooms.
Only add related videos to recommendations if its the first time we watch the video. This is to prevent rewatching a video multiple times from messing up recommendations.
Implement mentions in matrix with an autofill list, like on element. Also do the same with / commands.
Add option to disable autosearch and search when pressing enter instead or something? this would be needed for mobile phones where typing is slow.
@@ -42,7 +39,7 @@ Provide a way to specify when notifications should be received (using matrix api
Use quickmedia to show image in matrix rooms, instead of mpv.
Respect ~/.Xresources dpi (read the file, loop lines and look for Xft.dpi). Fallback to 96 dpi.
Merge body items in matrix if they are posted by the same author (there is a git stash for this).
-Add joining/leaving room in matrix, and also show invites and add command to ban users.
+Add command to ban users.
Support peertube (works with mpv, but need to implement search and related videos).
Scroll to bottom when receiving a new message even if the selected message is not the last one. It should instead scroll if the last message is visible on the screen.
Also add a tab for common directories and recently accessed files/directories (the directories would be the directory of used files).
@@ -82,7 +79,6 @@ Show redacted messages even when part of the initial sync in matrix. Right now t
Fix inconsistent behavior when editing a message that is replied to in matrix. Right now if the replied to message already exits in the body then its used directly and when editing that message the reply message shows the edit embedded, but not if the edit is of an body item that is created because we dont already have it,
to fix this we could perhaps replace the newly created body items for replies when loading old messages and one of the old messages is also one of the embedded messages (by event id).
Add button to skip to next video. MPV has this feature when setting "next" video (can be done over IPC).
-Handle room leave in matrix and remove rooms from the list.
Use a custom allocator that replaces malloc/realloc/free/new/delete to release memory properly, using munmap in free/delete. The C allocator doesn't do that! memory usage remains high after one large allocation. The C allocator only marks it as free.
Ignore timestamp ordering for messages in matrix? element seems to do that (or only for new messages???), and also we need the latest message to be last I guess to set read markers properly?
Merge |Page::search| and |Page::get_page|. get_page with page 0 should be the same as search.
@@ -98,7 +94,6 @@ Remove reply formatting for NOTICE in matrix as well.
Scroll body when adding new items and the selected item fits after the scroll (needed for matrix where we want to see new messages when the last item is not selected). Or show the last item when its not visible in matrix (at the bottom, just like when replying/editing).
Implement our own encryption for matrix. This is also needed to make forwarded message work. Pantalaimon ignores them!
Modify matrix sync to download and parse json but not handle it, and then add a function to handle the json. This would allow us to remove all the mutex code if we would call that new method from the main thread (similar to chromium multithreading).
-Room list in matrix ignores edited messages, which it should for unread messages but it should show the edited message if the edited message is the last message in the room.
Fetch replies/pinned message using multiple threads.
Show in room tags list when there is a message in any of the rooms in the tag.
Cancel video download when pressing escape or closing window (important in matrix).
@@ -158,7 +153,6 @@ Add arguments to pipe plugin to pass input and output fifo for sending commands
Update thumbnails in file-manager if an image is replaced, by including the modify date of the image in the thumbnail cache as well.
Create a workaround for dwm terminal swallow patch stealing mpv when moving QuickMedia to another monitor sometimes. Maybe check for structure notify events on mpv and reparent and select input on the mpv window again?
Resize video thumbnail when extracted with ffmpeg to 480x360, clamped from its original size.
-Remove reply formatting from edited text in room description in room list.
Add option to decline and mute user in invites. This is to combat invite spam, where muted users cant invite you.
Searching in channel page should search in the channel instead of filter, because with filtering we only filter the videos we have loaded in the channel page and the channel page uses pagination; so we may have only loaded 20 videos while the channel may actually have 2000 videos.
Allow hiding videos so they dont show up in recommendations and related videos.
diff --git a/include/Body.hpp b/include/Body.hpp
index 676eef8..ee83dae 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -252,6 +252,7 @@ namespace QuickMedia {
BodyItemRenderCallback body_item_render_callback;
sf::Shader *thumbnail_mask_shader;
AttachSide attach_side = AttachSide::TOP;
+ bool render_selection = true;
private:
void draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item = true);
void update_dirty_state(BodyItem *body_item, float width);
diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp
index 90e24bc..665c7e9 100644
--- a/include/QuickMedia.hpp
+++ b/include/QuickMedia.hpp
@@ -16,6 +16,7 @@
#include <future>
#include <thread>
#include <stack>
+#include "../plugins/Plugin.hpp"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
@@ -43,6 +44,30 @@ namespace QuickMedia {
FALSE,
CANCEL
};
+
+ enum class FetchType {
+ SEARCH,
+ LAZY
+ };
+
+ struct FetchResult {
+ BodyItems body_items;
+ PluginResult result;
+ };
+
+ struct TabAssociatedData {
+ std::string update_search_text;
+ bool search_text_updated = false;
+ FetchStatus fetch_status = FetchStatus::NONE;
+ bool lazy_fetch_finished = false;
+ FetchType fetch_type;
+ bool typing = false;
+ bool fetching_next_page_running = false;
+ int fetched_page = 0;
+ sf::Text search_result_text;
+ std::future<FetchResult> fetch_future;
+ std::future<BodyItems> next_page_future;
+ };
class Program {
public:
@@ -70,6 +95,7 @@ namespace QuickMedia {
void youtube_get_watch_history(BodyItems &history_items);
private:
void base_event_handler(sf::Event &event, PageType previous_page, Body *body, SearchBar *search_bar, bool handle_key_press = true, bool handle_searchbar = true);
+ void page_loop_render(sf::RenderWindow &window, std::vector<Tab> &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters);
void page_loop(std::vector<Tab> &tabs, int start_tab_index = 0, std::function<void()> after_submit_handler = nullptr);
void video_content_page(VideoPage *video_page, std::string video_url, std::string video_title, bool download_if_streaming_fails);
// Returns -1 to go to previous chapter, 0 to stay on same chapter and 1 to go to next chapter
@@ -77,7 +103,7 @@ namespace QuickMedia {
void image_continuous_page(MangaImagesPage *images_page);
void image_board_thread_page(ImageBoardThreadPage *thread_page, Body *thread_body);
void chat_login_page();
- void chat_page(MatrixChatPage *matrix_chat_page, RoomData *current_room);
+ bool chat_page(MatrixChatPage *matrix_chat_page, RoomData *current_room, std::vector<Tab> &room_tabs, int room_selected_tab, TabAssociatedData &room_tab_associated_data);
void after_matrix_login_page();
enum class LoadImageResult {
@@ -144,6 +170,12 @@ namespace QuickMedia {
bool fit_image_to_window = false;
RoomData *current_chat_room = nullptr;
bool go_to_previous_page = false;
+ sf::RoundedRectangleShape tab_background;
+ sf::RectangleShape tab_shade;
+ sf::Text tab_text;
+ sf::Vertex gradient_points[4];
+ sf::Vector2f body_pos;
+ sf::Vector2f body_size;
std::thread::id main_thread_id;
};
} \ No newline at end of file
diff --git a/src/Body.cpp b/src/Body.cpp
index 8eeee49..8abd2b3 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -706,7 +706,7 @@ namespace QuickMedia {
item_separator.setPosition(item_pos + sf::Vector2f(10.0f, std::floor(item_height + spacing_y * 0.5f)));
window.draw(item_separator);
- if(item_index == selected_item) {
+ if(item_index == selected_item && render_selection) {
item_background.setPosition(item_pos);
item_background.setSize(sf::Vector2f(size.x, item_height));
window.draw(item_background);
@@ -837,7 +837,7 @@ namespace QuickMedia {
if(!item->reactions.empty() && include_embedded_item) {
sf::RoundedRectangleShape reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10);
- reaction_background.setFillColor(sf::Color(33, 38, 44));
+ reaction_background.setFillColor(sf::Color(31, 35, 41));
float reaction_offset_x = 0.0f;
item_pos.y += reaction_padding_y;
float reaction_max_height = 0.0f;
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 76bd084..7e487d1 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -346,7 +346,8 @@ namespace QuickMedia {
window(sf::VideoMode(1280, 720, 24), "QuickMedia", sf::Style::Default),
window_size(1280, 720),
current_page(PageType::EXIT),
- image_index(0)
+ image_index(0),
+ tab_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10)
{
disp = XOpenDisplay(NULL);
if (!disp)
@@ -919,12 +920,63 @@ namespace QuickMedia {
go_to_previous_page = true;
}
- static void select_body_item_by_room(Body *body, RoomData *room) {
- for(size_t i = 0; i < body->items.size(); ++i) {
- auto &body_item = body->items[i];
- if(body_item->userdata == room) {
- body->set_selected_item(i, false);
- return;
+ void Program::page_loop_render(sf::RenderWindow &window, std::vector<Tab> &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters) {
+ 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 = 10.0f;
+
+ 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 + 5.0f) * 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 + 10.0f));
+ 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), tab_y);
+ window.draw(tab_text);
+ ++i;
+ }
+ }
+
+ if(tab_associated_data.fetching_next_page_running)
+ window.draw(gradient_points, 4, sf::Quads); // Note: sf::Quads doesn't work with egl
+
+ if(!tab_associated_data.search_result_text.getString().isEmpty()) {
+ auto search_result_text_bounds = tab_associated_data.search_result_text.getLocalBounds();
+ tab_associated_data.search_result_text.setPosition(
+ std::floor(body_pos.x + body_size.x * 0.5f - search_result_text_bounds.width * 0.5f),
+ std::floor(body_pos.y + body_size.y * 0.5f - search_result_text_bounds.height * 0.5f));
+ window.draw(tab_associated_data.search_result_text);
+ }
+
+ if(matrix && !matrix->is_initial_sync_finished()) {
+ // if(is_login_sync) {
+ load_sprite.setPosition(body_pos.x + body_size.x * 0.5f, body_pos.y + body_size.y * 0.5f);
+ load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0);
+ window.draw(load_sprite);
+ // }
+ std::string err_msg;
+ if(matrix->did_initial_sync_fail(err_msg)) {
+ show_notification("QuickMedia", "Initial matrix sync failed, error: " + err_msg, Urgency::CRITICAL);
+ window.close();
+ exit(0);
}
}
}
@@ -947,30 +999,6 @@ namespace QuickMedia {
json_chapters = &chapters_json;
}
- enum class FetchType {
- SEARCH,
- LAZY
- };
-
- struct FetchResult {
- BodyItems body_items;
- PluginResult result;
- };
-
- struct TabAssociatedData {
- std::string update_search_text;
- bool search_text_updated = false;
- FetchStatus fetch_status = FetchStatus::NONE;
- bool lazy_fetch_finished = false;
- FetchType fetch_type;
- bool typing = false;
- bool fetching_next_page_running = false;
- int fetched_page = 0;
- sf::Text search_result_text;
- std::future<FetchResult> fetch_future;
- std::future<BodyItems> next_page_future;
- };
-
std::vector<TabAssociatedData> tab_associated_data;
for(size_t i = 0; i < tabs.size(); ++i) {
TabAssociatedData data;
@@ -983,9 +1011,8 @@ namespace QuickMedia {
double gradient_inc = 0.0;
const float gradient_height = 5.0f;
- sf::Vertex gradient_points[4];
- sf::Text tab_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size);
+ 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;
@@ -995,7 +1022,7 @@ namespace QuickMedia {
window_size.x = window_size_u.x;
window_size.y = window_size_u.y;
- auto submit_handler = [this, &after_submit_handler, &json_chapters, &tabs, &selected_tab, &loop_running, &redraw]() {
+ auto submit_handler = [this, &after_submit_handler, &json_chapters, &tabs, &tab_associated_data, &selected_tab, &loop_running, &redraw]() {
BodyItem *selected_item = tabs[selected_tab].body->get_selected();
if(!selected_item)
return;
@@ -1082,7 +1109,16 @@ namespace QuickMedia {
} else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::CHAT) {
current_page = PageType::CHAT;
current_chat_room = matrix->get_room_by_id(selected_item->url);
- chat_page(static_cast<MatrixChatPage*>(new_tabs[0].page.get()), current_chat_room);
+ while(window.isOpen()) {
+ bool move_room = chat_page(static_cast<MatrixChatPage*>(new_tabs[0].page.get()), current_chat_room, tabs, selected_tab, tab_associated_data[selected_tab]);
+ if(!move_room)
+ break;
+ BodyItem *selected_item = tabs[selected_tab].body->get_selected();
+ if(!selected_item)
+ break;
+ current_chat_room = matrix->get_room_by_id(selected_item->url);
+ }
+ tabs[selected_tab].body->render_selection = true;
//select_body_item_by_room(tabs[selected_tab].body.get(), current_chat_room);
current_chat_room = nullptr;
} else {
@@ -1129,16 +1165,9 @@ namespace QuickMedia {
};
}
- sf::Vector2f body_pos;
- sf::Vector2f body_size;
sf::Event event;
-
- const float tab_spacer_height = 0.0f;
- sf::RectangleShape tab_shade;
- tab_shade.setFillColor(sf::Color(33, 38, 44));
-
- sf::RoundedRectangleShape tab_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10);
+ tab_shade.setFillColor(sf::Color(31, 35, 41));
tab_background.setFillColor(tab_selected_color);
sf::Clock frame_timer;
@@ -1259,6 +1288,17 @@ namespace QuickMedia {
gradient_points[3].position.y = window_size.y;
}
+ if(tab_associated_data[selected_tab].fetching_next_page_running) {
+ double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5;
+ gradient_inc += (frame_time_ms * 0.5);
+ sf::Color bottom_color = interpolate_colors(back_color, sf::Color(175, 180, 188), progress);
+
+ gradient_points[0].color = back_color;
+ gradient_points[1].color = back_color;
+ gradient_points[2].color = bottom_color;
+ gradient_points[3].color = bottom_color;
+ }
+
if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->update();
if(tabs[selected_tab].page->is_lazy_fetch_page() && tab_associated_data[selected_tab].fetch_status == FetchStatus::NONE && !tab_associated_data[selected_tab].lazy_fetch_finished) {
@@ -1337,74 +1377,7 @@ namespace QuickMedia {
}
window.clear(back_color);
- 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 = 10.0f;
-
- 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 = tab_spacer_height + std::floor(tab_vertical_offset + tab_height * 0.5f - (tab_text_size + 5.0f) * 0.5f) + shade_extra_height;
-
- tab_shade.setPosition(0.0f, tab_spacer_height + std::floor(tab_vertical_offset));
- tab_shade.setSize(sf::Vector2f(window_size.x, shade_extra_height + tab_height + 10.0f));
- 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), tab_spacer_height + 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), tab_y);
- window.draw(tab_text);
- ++i;
- }
- }
-
- if(tab_associated_data[selected_tab].fetching_next_page_running) {
- double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5;
- gradient_inc += (frame_time_ms * 0.5);
- sf::Color bottom_color = interpolate_colors(back_color, sf::Color(175, 180, 188), progress);
-
- gradient_points[0].color = back_color;
- gradient_points[1].color = back_color;
- gradient_points[2].color = bottom_color;
- gradient_points[3].color = bottom_color;
- window.draw(gradient_points, 4, sf::Quads); // Note: sf::Quads doesn't work with egl
- }
-
- if(!tab_associated_data[selected_tab].search_result_text.getString().isEmpty()) {
- auto search_result_text_bounds = tab_associated_data[selected_tab].search_result_text.getLocalBounds();
- tab_associated_data[selected_tab].search_result_text.setPosition(
- std::floor(body_pos.x + body_size.x * 0.5f - search_result_text_bounds.width * 0.5f),
- std::floor(body_pos.y + body_size.y * 0.5f - search_result_text_bounds.height * 0.5f));
- window.draw(tab_associated_data[selected_tab].search_result_text);
- }
-
- if(matrix && !matrix->is_initial_sync_finished()) {
- // if(is_login_sync) {
- load_sprite.setPosition(body_pos.x + body_size.x * 0.5f, body_pos.y + body_size.y * 0.5f);
- load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0);
- window.draw(load_sprite);
- // }
- std::string err_msg;
- if(matrix->did_initial_sync_fail(err_msg)) {
- show_notification("QuickMedia", "Initial matrix sync failed, error: " + err_msg, Urgency::CRITICAL);
- window.close();
- goto page_end;
- }
- }
-
+ page_loop_render(window, tabs, selected_tab, tab_associated_data[selected_tab], json_chapters);
window.display();
if(go_to_previous_page) {
@@ -2642,7 +2615,7 @@ namespace QuickMedia {
};
sf::RectangleShape comment_input_shade;
- comment_input_shade.setFillColor(sf::Color(33, 38, 44));
+ comment_input_shade.setFillColor(sf::Color(31, 35, 41));
sf::Sprite logo_sprite(plugin_logo);
logo_sprite.setScale(0.8f, 0.8f);
@@ -3138,11 +3111,17 @@ namespace QuickMedia {
Message *message = nullptr;
};
- void Program::chat_page(MatrixChatPage *matrix_chat_page, RoomData *current_room) {
+ bool Program::chat_page(MatrixChatPage *matrix_chat_page, RoomData *current_room, std::vector<Tab> &room_tabs, int room_selected_tab, TabAssociatedData &room_tab_associated_data) {
+ assert(current_room);
assert(strcmp(plugin_name, "matrix") == 0);
+ if(!current_room) {
+ show_notification("QuickMedia", "Bug: current room empty", Urgency::CRITICAL);
+ abort();
+ }
window.setTitle("QuickMedia - matrix - " + current_room->get_name());
auto video_page = std::make_unique<MatrixVideoPage>(this);
+ bool move_room = false;
std::vector<ChatTab> tabs;
@@ -3215,6 +3194,7 @@ namespace QuickMedia {
bool setting_read_marker = false;
bool redraw = true;
+ bool draw_room_list = true;
// TODO: Optimize with hash map?
auto find_body_item_by_event_id = [](std::shared_ptr<BodyItem> *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) -> std::shared_ptr<BodyItem> {
@@ -3815,7 +3795,7 @@ namespace QuickMedia {
sf::Event event;
sf::RectangleShape tab_shade;
- tab_shade.setFillColor(sf::Color(33, 38, 44));
+ tab_shade.setFillColor(sf::Color(31, 35, 41));
sf::RoundedRectangleShape tab_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10);
tab_background.setFillColor(tab_selected_color);
@@ -3854,7 +3834,7 @@ namespace QuickMedia {
more_messages_below_rect.setFillColor(sf::Color(128, 50, 50));
sf::RectangleShape chat_input_shade;
- chat_input_shade.setFillColor(sf::Color(33, 38, 44));
+ chat_input_shade.setFillColor(sf::Color(31, 35, 41));
sf::Clock start_typing_timer;
const double typing_timeout_seconds = 3.0;
@@ -4134,6 +4114,29 @@ namespace QuickMedia {
while (window.pollEvent(event)) {
base_event_handler(event, PageType::EXIT, tabs[selected_tab].body.get(), nullptr, false, false);
+ if(event.type == sf::Event::KeyPressed && event.key.control && event.key.alt && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION)) {
+ if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) {
+ room_tabs[room_selected_tab].body->select_previous_item();
+ } else if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) {
+ room_tabs[room_selected_tab].body->select_next_item();
+ } else if(event.key.code == sf::Keyboard::PageUp) {
+ room_tabs[room_selected_tab].body->select_previous_page();
+ } else if(event.key.code == sf::Keyboard::PageDown) {
+ room_tabs[room_selected_tab].body->select_next_page();
+ } else if(event.key.code == sf::Keyboard::Home) {
+ room_tabs[room_selected_tab].body->select_first_item();
+ } else if(event.key.code == sf::Keyboard::End) {
+ room_tabs[room_selected_tab].body->select_last_item();
+ } else if(event.key.code == sf::Keyboard::Escape) {
+ move_room = false;
+ goto chat_page_end;
+ } else if(event.key.code == sf::Keyboard::Enter) {
+ move_room = true;
+ goto chat_page_end;
+ }
+ continue;
+ }
+
if(event.type == sf::Event::GainedFocus) {
is_window_focused = true;
redraw = true;
@@ -4142,20 +4145,20 @@ namespace QuickMedia {
} else if(event.type == sf::Event::Resized || event.type == sf::Event::GainedFocus) {
redraw = true;
} else if(event.type == sf::Event::KeyPressed && chat_state == ChatState::NAVIGATING) {
- if(event.key.code == sf::Keyboard::Up || event.key.code == sf::Keyboard::PageUp || event.key.code == sf::Keyboard::Home || (event.key.control && event.key.code == sf::Keyboard::K)){
+ if(event.key.code == sf::Keyboard::Up || event.key.code == sf::Keyboard::PageUp || event.key.code == sf::Keyboard::Home || (event.key.control && event.key.code == sf::Keyboard::K)) {
bool hit_top = false;
switch(event.key.code) {
case sf::Keyboard::Up:
- hit_top = !tabs[selected_tab].body->select_previous_item();
+ hit_top = !tabs[selected_tab].body.get()->select_previous_item();
break;
case sf::Keyboard::K:
- hit_top = !tabs[selected_tab].body->select_previous_item();
+ hit_top = !tabs[selected_tab].body.get()->select_previous_item();
break;
case sf::Keyboard::PageUp:
- hit_top = !tabs[selected_tab].body->select_previous_page();
+ hit_top = !tabs[selected_tab].body.get()->select_previous_page();
break;
case sf::Keyboard::Home:
- tabs[selected_tab].body->select_first_item();
+ tabs[selected_tab].body.get()->select_first_item();
hit_top = true;
break;
default:
@@ -4172,11 +4175,11 @@ namespace QuickMedia {
};
}
} else if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) {
- tabs[selected_tab].body->select_next_item();
+ tabs[selected_tab].body.get()->select_next_item();
} else if(event.key.code == sf::Keyboard::PageDown) {
- tabs[selected_tab].body->select_next_page();
+ tabs[selected_tab].body.get()->select_next_page();
} else if(event.key.code == sf::Keyboard::End) {
- tabs[selected_tab].body->select_last_item();
+ 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;
@@ -4476,9 +4479,6 @@ namespace QuickMedia {
tab_shade_height = tab_spacer_height + std::floor(tab_vertical_offset) + tab_height + room_name_padding_y + padding_bottom;
- chat_input.set_max_width(window_size.x - (logo_padding_x + logo_size.x + chat_input_padding_x + logo_padding_x));
- chat_input.set_position(sf::Vector2f(std::floor(logo_padding_x + logo_size.x + chat_input_padding_x), window_size.y - chat_height - chat_input_padding_y));
-
float body_padding_horizontal = 25.0f;
float body_padding_vertical = 5.0f;
float body_width = window_size.x - body_padding_horizontal * 2.0f;
@@ -4487,16 +4487,28 @@ namespace QuickMedia {
body_padding_horizontal = 0.0f;
}
- chat_input_shade.setSize(sf::Vector2f(window_size.x, chat_input_height_full));
- chat_input_shade.setPosition(0.0f, window_size.y - chat_input_shade.getSize().y);
+ this->body_pos = sf::Vector2f(0.0f, body_padding_vertical + tab_shade_height);
+ if(body_width > 640.0f) {
+ this->body_size = sf::Vector2f(250.0f, window_size.y - body_padding_vertical - tab_shade_height);
+ draw_room_list = true;
+ } else {
+ this->body_size = sf::Vector2f(0.0f, 0.0f);
+ draw_room_list = false;
+ }
+
+ body_pos = sf::Vector2f(this->body_pos.x + this->body_size.x + body_padding_horizontal, body_padding_vertical + tab_shade_height);
+ body_size = sf::Vector2f(body_width - this->body_pos.x - this->body_size.x, window_size.y - chat_input_height_full - body_padding_vertical - tab_shade_height);
- body_pos = sf::Vector2f(body_padding_horizontal, body_padding_vertical + tab_shade_height);
- body_size = sf::Vector2f(body_width, window_size.y - chat_input_shade.getSize().y - body_padding_vertical - tab_shade_height);
+ chat_input_shade.setSize(sf::Vector2f(window_size.x - (body_pos.x - body_padding_horizontal), chat_input_height_full));
+ chat_input_shade.setPosition(body_pos.x - body_padding_horizontal, window_size.y - chat_input_shade.getSize().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 - body_padding_horizontal));
+ chat_input.set_position(sf::Vector2f(std::floor(body_pos.x - body_padding_horizontal + logo_padding_x + logo_size.x + chat_input_padding_x), window_size.y - chat_height - chat_input_padding_y));
more_messages_below_rect.setSize(sf::Vector2f(window_size.x, gradient_height));
- more_messages_below_rect.setPosition(0.0f, std::floor(window_size.y - chat_input_shade.getSize().y - gradient_height));
+ more_messages_below_rect.setPosition(0.0f, std::floor(window_size.y - chat_input_height_full - gradient_height));
- logo_sprite.setPosition(logo_padding_x, std::floor(window_size.y - chat_input_shade.getSize().y * 0.5f - logo_size.y * 0.5f));
+ logo_sprite.setPosition(body_pos.x - body_padding_horizontal + logo_padding_x, std::floor(window_size.y - chat_input_height_full * 0.5f - logo_size.y * 0.5f));
}
while((provisional_message = provisional_message_queue.pop_if_available()) != std::nullopt) {
@@ -4598,6 +4610,15 @@ namespace QuickMedia {
window.clear(back_color);
+ room_tabs[room_selected_tab].body->render_selection = sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt) && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION);
+ if(draw_room_list) {
+ sf::RectangleShape room_list_background(this->body_size);
+ room_list_background.setPosition(this->body_pos);
+ room_list_background.setFillColor(sf::Color(31, 35, 41));
+ window.draw(room_list_background);
+ page_loop_render(window, room_tabs, room_selected_tab, room_tab_associated_data, &Json::Value::nullSingleton());
+ }
+
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));
@@ -4802,6 +4823,7 @@ namespace QuickMedia {
previous_messages_future.cancel();
cleanup_tasks();
window.setTitle("QuickMedia - matrix");
+ return move_room;
}
void Program::after_matrix_login_page() {
diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp
index 739a0b6..5c5b860 100644
--- a/src/SearchBar.cpp
+++ b/src/SearchBar.cpp
@@ -46,7 +46,7 @@ namespace QuickMedia {
//background.setCornersRadius(5);
background_shadow.setFillColor(sf::Color(23, 25, 27));
//background_shadow.setPosition(background.getPosition() + sf::Vector2f(5.0f, 5.0f));
- shade.setFillColor(sf::Color(33, 38, 44));
+ shade.setFillColor(sf::Color(31, 35, 41));
//background.setOutlineThickness(1.0f);
//background.setOutlineColor(sf::Color(13, 15, 17));
if(plugin_logo && plugin_logo->getNativeHandle() != 0)