aboutsummaryrefslogtreecommitdiff
path: root/src/QuickMedia.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-10-01 22:21:14 +0200
committerdec05eba <dec05eba@protonmail.com>2020-10-01 22:21:14 +0200
commitef1dd33682ae26b4af1343aaecf443e7cd883674 (patch)
treecf3c959f1cf9f8b6b401d384537685191ae3e4ba /src/QuickMedia.cpp
parent30dbaeb2b175c1e67f57aba748ced1a2280fb56d (diff)
Matrix: implement mention/reply notifications
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r--src/QuickMedia.cpp150
1 files changed, 106 insertions, 44 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 909bdd7..da5453e 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -3331,50 +3331,58 @@ namespace QuickMedia {
*/
// This is needed to get initial data, with joined rooms etc. TODO: Remove this once its cached
// and allow asynchronous update of rooms
- RoomSyncMessages room_sync_messages;
- if(matrix->sync(room_sync_messages) != PluginResult::OK) {
- show_notification("QuickMedia", "Intial matrix sync failed", Urgency::CRITICAL);
- current_page = Page::EXIT;
- return;
- }
-
- if(matrix->get_joined_rooms(tabs[ROOMS_TAB_INDEX].body->items) != PluginResult::OK) {
- show_notification("QuickMedia", "Failed to get a list of joined rooms", Urgency::CRITICAL);
- current_page = Page::EXIT;
- return;
- }
+ bool synced = false;
struct RoomBodyData {
std::shared_ptr<BodyItem> body_item;
bool last_message_read;
+ time_t last_read_message_timestamp;
};
std::unordered_map<std::string, RoomBodyData> body_items_by_room_id;
- for(auto body_item : tabs[ROOMS_TAB_INDEX].body->items) {
- // TODO: Set |last_message_read| depending on read markers (either remote matrix read markers or locally saved ones)
- body_items_by_room_id[body_item->url] = { body_item, true };
- }
- for(auto &[room, messages] : room_sync_messages) {
- auto room_body_item_it = body_items_by_room_id.find(room->id);
- if(room_body_item_it != body_items_by_room_id.end() && !messages.empty()) {
- room_body_item_it->second.body_item->set_description(matrix->message_get_author_displayname(room, messages.back().get()) + ": " + extract_first_line(messages.back()->body));
+ auto process_new_room_messages = [matrix, &body_items_by_room_id](RoomSyncMessages &room_sync_messages, bool only_show_mentions) mutable {
+ for(auto &[room, messages] : room_sync_messages) {
+ bool was_mentioned = false;
+ for(auto &message : messages) {
+ if(message->mentions_me) {
+ was_mentioned = true;
+ message->mentions_me = false;
+ // TODO: What if the message or username begins with "-"? also make the notification image be the avatar of the user
+ std::string desc = "QuickMedia Matrix\n\n" + message->body;
+ show_notification(matrix->message_get_author_displayname(room, message.get()), desc.c_str());
+ }
+ }
+
+ auto room_body_item_it = body_items_by_room_id.find(room->id);
+ if(room_body_item_it == body_items_by_room_id.end())
+ continue;
+
+ if(only_show_mentions) {
+ std::string room_desc;
+ if(!messages.empty())
+ room_desc = matrix->message_get_author_displayname(room, messages.back().get()) + ": " + extract_first_line(messages.back()->body);
+ if(was_mentioned) {
+ room_desc += "\n** You were mentioned **"; // TODO: Better notification?
+ room_body_item_it->second.body_item->title_color = sf::Color(255, 100, 100);
+ room_body_item_it->second.last_message_read = false;
+ }
+ room_body_item_it->second.body_item->set_description(std::move(room_desc));
+ } else if(!messages.empty()) {
+ std::string room_desc = "Unread: " + matrix->message_get_author_displayname(room, messages.back().get()) + ": " + extract_first_line(messages.back()->body);
+ if(was_mentioned)
+ room_desc += "\n** You were mentioned **"; // TODO: Better notification?
+ room_body_item_it->second.body_item->set_description(std::move(room_desc));
+ room_body_item_it->second.body_item->title_color = sf::Color(255, 100, 100);
+ room_body_item_it->second.last_message_read = false;
+ }
}
- }
+ };
// TODO: the initial room to view should be the last viewed room when closing QuickMedia.
// The room id should be saved in a file when changing viewed room.
std::string current_room_id;
- if(!tabs[ROOMS_TAB_INDEX].body->items.empty())
- current_room_id = tabs[ROOMS_TAB_INDEX].body->items[0]->url;
-
- // TODO: Allow empty initial room (if the user hasn't joined any room yet).
- assert(!current_room_id.empty());
-
RoomBodyData *current_room_body_data = nullptr;
- auto room_body_item_it = body_items_by_room_id.find(current_room_id);
- if(room_body_item_it != body_items_by_room_id.end())
- current_room_body_data = &room_body_item_it->second;
// get_all_room_messages is not needed here because its done in the loop, where the initial timeout is 0ms
@@ -3461,6 +3469,7 @@ namespace QuickMedia {
struct SyncFutureResult {
BodyItems body_items;
+ BodyItems rooms_body_items;
RoomSyncMessages room_sync_messages;
};
@@ -3503,9 +3512,7 @@ namespace QuickMedia {
const float tab_vertical_offset = 10.0f;
sf::Text room_name_text("", *font, 18);
- if(current_room_body_data)
- room_name_text.setString(current_room_body_data->body_item->get_title());
- const float room_name_text_height = std::floor(room_name_text.getLocalBounds().height);
+ const float room_name_text_height = 20.0f;
const float room_name_text_padding_y = 10.0f;
const float room_name_total_height = room_name_text_height + room_name_text_padding_y * 2.0f;
const float room_avatar_height = 32.0f;
@@ -3534,6 +3541,9 @@ namespace QuickMedia {
Body url_selection_body(this, font.get(), bold_font.get(), cjk_font.get());
+ sf::Clock read_marker_timer;
+ const sf::Int32 read_marker_timeout_ms = 3000;
+
auto launch_url = [this, &redraw](const std::string &url) mutable {
if(url.empty())
return;
@@ -3608,6 +3618,7 @@ namespace QuickMedia {
} else if(event.key.code == sf::Keyboard::Left) {
tabs[selected_tab].body->clear_thumbnails();
selected_tab = std::max(0, selected_tab - 1);
+ read_marker_timer.restart();
if(typing) {
fprintf(stderr, "Stopped typing\n");
typing = false;
@@ -3616,6 +3627,7 @@ namespace QuickMedia {
} else if(event.key.code == sf::Keyboard::Right) {
tabs[selected_tab].body->clear_thumbnails();
selected_tab = std::min((int)tabs.size() - 1, selected_tab + 1);
+ read_marker_timer.restart();
if(typing) {
fprintf(stderr, "Stopped typing\n");
typing = false;
@@ -3907,6 +3919,8 @@ namespace QuickMedia {
}
chat_input_height_full = chat_input.get_height() + chat_input_padding_y * 2.0f;
+ if(selected_tab != MESSAGES_TAB_INDEX)
+ chat_input_height_full = 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);
@@ -3927,12 +3941,21 @@ namespace QuickMedia {
sync_running = true;
sync_timer.restart();
sync_future_room_id = current_room_id;
- sync_future = std::async(std::launch::async, [this, &sync_future_room_id]() {
+ sync_future = std::async(std::launch::async, [this, &sync_future_room_id, synced]() {
Matrix *matrix = static_cast<Matrix*>(current_plugin);
SyncFutureResult result;
if(matrix->sync(result.room_sync_messages) == PluginResult::OK) {
fprintf(stderr, "Synced matrix\n");
+
+ if(!synced) {
+ if(matrix->get_joined_rooms(result.rooms_body_items) != PluginResult::OK) {
+ show_notification("QuickMedia", "Failed to get a list of joined rooms", Urgency::CRITICAL);
+ current_page = Page::EXIT;
+ return result;
+ }
+ }
+
if(matrix->get_new_room_messages(sync_future_room_id, result.body_items) != PluginResult::OK) {
fprintf(stderr, "Failed to get new matrix messages in room: %s\n", sync_future_room_id.c_str());
}
@@ -3954,23 +3977,39 @@ namespace QuickMedia {
if(scroll_to_end)
tabs[MESSAGES_TAB_INDEX].body->select_last_item();
}
- for(auto &[room, messages] : sync_result.room_sync_messages) {
- auto room_body_item_it = body_items_by_room_id.find(room->id);
- if(room_body_item_it != body_items_by_room_id.end() && !messages.empty()) {
- room_body_item_it->second.body_item->set_description("Unread: " + matrix->message_get_author_displayname(room, messages.back().get()) + ": " + extract_first_line(messages.back()->body));
- room_body_item_it->second.body_item->title_color = sf::Color(255, 100, 100);
- room_body_item_it->second.last_message_read = false;
+
+ if(!synced) {
+ tabs[ROOMS_TAB_INDEX].body->items = std::move(sync_result.rooms_body_items);
+
+ for(auto body_item : tabs[ROOMS_TAB_INDEX].body->items) {
+ // TODO: Set |last_message_read| depending on read markers (either remote matrix read markers or locally saved ones)
+ body_items_by_room_id[body_item->url] = { body_item, true, 0 };
}
+
+ // TODO: the initial room to view should be the last viewed room when closing QuickMedia.
+ // The room id should be saved in a file when changing viewed room.
+ if(!tabs[ROOMS_TAB_INDEX].body->items.empty())
+ current_room_id = tabs[ROOMS_TAB_INDEX].body->items[0]->url;
+
+ auto room_body_item_it = body_items_by_room_id.find(current_room_id);
+ if(room_body_item_it != body_items_by_room_id.end()) {
+ current_room_body_data = &room_body_item_it->second;
+ room_name_text.setString(current_room_body_data->body_item->get_title());
+ }
+ redraw = true;
}
+
+ process_new_room_messages(sync_result.room_sync_messages, !synced);
sync_running = false;
+ synced = true;
}
if(fetching_previous_messages_running && previous_messages_future.valid() && previous_messages_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
BodyItems new_body_items = previous_messages_future.get();
fprintf(stderr, "Finished fetching older messages, num new messages: %zu\n", new_body_items.size());
// Ignore finished fetch of messages if it happened in another room. When we navigate back to the room we will get the messages again
- if(previous_messages_future_room_id == current_room_id) {
- size_t num_new_messages = new_body_items.size();
+ size_t num_new_messages = new_body_items.size();
+ if(previous_messages_future_room_id == current_room_id && num_new_messages > 0) {
int selected_item_index = tabs[MESSAGES_TAB_INDEX].body->get_selected_item();
tabs[MESSAGES_TAB_INDEX].body->prepend_items(std::move(new_body_items));
tabs[MESSAGES_TAB_INDEX].body->set_selected_item(selected_item_index + num_new_messages);
@@ -4073,8 +4112,12 @@ namespace QuickMedia {
if(tabs[selected_tab].type == ChatTabType::MESSAGES) {
if(tabs[selected_tab].body->is_last_item_fully_visible()) {
if(current_room_body_data && !current_room_body_data->last_message_read) {
- if(strncmp(current_room_body_data->body_item->get_description().c_str(), "Unread: ", 8) == 0)
- current_room_body_data->body_item->set_description(current_room_body_data->body_item->get_description().c_str() + 8);
+ std::string room_desc = current_room_body_data->body_item->get_description();
+ if(strncmp(room_desc.c_str(), "Unread: ", 8) == 0)
+ room_desc = room_desc.substr(8);
+ if(room_desc.size() >= 26 && strncmp(room_desc.c_str() + room_desc.size() - 26, "\n** You were mentioned **", 26) == 0)
+ room_desc = room_desc.substr(0, room_desc.size() - 26);
+ current_room_body_data->body_item->set_description(std::move(room_desc));
// TODO: Show a line like nheko instead for unread messages, or something else
current_room_body_data->body_item->title_color = sf::Color::White;
current_room_body_data->last_message_read = true;
@@ -4084,7 +4127,26 @@ namespace QuickMedia {
}
}
+ // TODO: Cache /sync, then we wont only see loading text
+ if(!synced) {
+ sf::Text loading_text("Loading...", *font, 24);
+ loading_text.setPosition(body_pos.x + body_size.x * 0.5f - loading_text.getLocalBounds().width * 0.5f, body_pos.y + body_size.y * 0.5f - loading_text.getLocalBounds().height * 0.5f);
+ window.draw(loading_text);
+ }
+
if(tabs[selected_tab].type == ChatTabType::MESSAGES) {
+ BodyItem *last_visible_item = tabs[selected_tab].body->get_last_fully_visible_item();
+ if(chat_state != ChatState::URL_SELECTION && current_room_body_data && last_visible_item && read_marker_timer.getElapsedTime().asMilliseconds() >= read_marker_timeout_ms) {
+ Message *message = (Message*)last_visible_item->userdata;
+ if(message->timestamp > current_room_body_data->last_read_message_timestamp) {
+ current_room_body_data->last_read_message_timestamp = message->timestamp;
+ read_marker_timer.restart();
+ if(matrix->set_read_marker(current_room_id, message) != PluginResult::OK) {
+ fprintf(stderr, "Warning: failed to set read marker to %s\n", message->event_id.c_str());
+ }
+ }
+ }
+
window.draw(chat_input_shade);
chat_input.draw(window); //chat_input.draw(window, false);
window.draw(logo_sprite);