diff options
author | dec05eba <dec05eba@protonmail.com> | 2020-10-21 04:57:21 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-10-21 04:57:21 +0200 |
commit | f8b54139f89ef21eb025defd17a5655e41fb9c03 (patch) | |
tree | a29540ddb94df59ede1700549d536536188ff2bf /src/plugins | |
parent | ea6f1b425a6aa9b7145a00d81473ef9508279eec (diff) |
Matrix: sort rooms by mention/unread messages
fix multiple messages being marker as mentioning us if the latest
mention is close to another mention that we have already read.
Do not go to bottom when sending a message or uploading media.
Do not scroll to bottom unless we have the last message selected, the
tab is the messages tab and the window is focused.
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/Matrix.cpp | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index ff0d498..7de8af9 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -55,7 +55,7 @@ namespace QuickMedia { return user->read_marker_event_id; } - void RoomData::prepend_messages_reverse(std::vector<std::shared_ptr<Message>> new_messages) { + void RoomData::prepend_messages_reverse(const std::vector<std::shared_ptr<Message>> &new_messages) { std::lock_guard<std::mutex> lock(room_mutex); for(auto it = new_messages.begin(); it != new_messages.end(); ++it) { if(message_by_event_id.find((*it)->event_id) == message_by_event_id.end()) { @@ -65,7 +65,7 @@ namespace QuickMedia { } } - void RoomData::append_messages(std::vector<std::shared_ptr<Message>> new_messages) { + void RoomData::append_messages(const std::vector<std::shared_ptr<Message>> &new_messages) { std::lock_guard<std::mutex> lock(room_mutex); for(auto it = new_messages.begin(); it != new_messages.end(); ++it) { if(message_by_event_id.find((*it)->event_id) == message_by_event_id.end()) { @@ -208,6 +208,8 @@ namespace QuickMedia { events_set_room_name(events_json, room); } + const rapidjson::Value &ephemeral_json = GetMember(it.value, "ephemeral"); + const rapidjson::Value &timeline_json = GetMember(it.value, "timeline"); if(timeline_json.IsObject()) { if(room->prev_batch.empty()) { @@ -217,7 +219,7 @@ namespace QuickMedia { room->prev_batch = prev_batch_json.GetString(); } - // TODO: Is there no better way to check for notifications? this is not robust... + // TODO: Use /_matrix/client/r0/notifications ? or remove this and always look for displayname/user_id in messages bool has_unread_notifications = false; const rapidjson::Value &unread_notification_json = GetMember(it.value, "unread_notifications"); if(unread_notification_json.IsObject()) { @@ -228,14 +230,18 @@ namespace QuickMedia { const rapidjson::Value &events_json = GetMember(timeline_json, "events"); events_add_user_info(events_json, room); - events_add_messages(events_json, room, MessageDirection::AFTER, &room_messages, has_unread_notifications); events_set_room_name(events_json, room); - } - - const rapidjson::Value &ephemeral_json = GetMember(it.value, "ephemeral"); - if(ephemeral_json.IsObject()) { - const rapidjson::Value &events_json = GetMember(ephemeral_json, "events"); - events_add_user_read_markers(events_json, room); + // We want to do this before adding messages to know if a message that mentions us is a new mention + if(ephemeral_json.IsObject()) { + const rapidjson::Value &events_json = GetMember(ephemeral_json, "events"); + events_add_user_read_markers(events_json, room); + } + events_add_messages(events_json, room, MessageDirection::AFTER, &room_messages, has_unread_notifications); + } else { + if(ephemeral_json.IsObject()) { + const rapidjson::Value &events_json = GetMember(ephemeral_json, "events"); + events_add_user_read_markers(events_json, room); + } } } @@ -457,25 +463,33 @@ namespace QuickMedia { for(const rapidjson::Value &event_item_json : events_json.GetArray()) { std::shared_ptr<Message> new_message = parse_message_event(event_item_json, room_data); - if(!new_message) - continue; - - // TODO: Is @room ok? shouldn't we also check if the user has permission to do @room? (only when notifications are limited to @mentions) - if(has_unread_notifications && me) - new_message->mentions_me = message_contains_user_mention(new_message->body, me->display_name) || message_contains_user_mention(new_message->body, me->user_id) || message_contains_user_mention(new_message->body, "@room"); - - new_messages.push_back(std::move(new_message)); + if(new_message) + new_messages.push_back(std::move(new_message)); } + if(new_messages.empty()) + return; + // TODO: Add directly to this instead when set? otherwise add to new_messages if(room_messages) (*room_messages)[room_data] = new_messages; // TODO: Loop and std::move instead? doesn't insert create copies? if(message_dir == MessageDirection::BEFORE) { - room_data->prepend_messages_reverse(std::move(new_messages)); + room_data->prepend_messages_reverse(new_messages); } else if(message_dir == MessageDirection::AFTER) { - room_data->append_messages(std::move(new_messages)); + room_data->append_messages(new_messages); + } + + std::shared_ptr<Message> read_marker_message; + if(me) + read_marker_message = room_data->get_message_by_id(room_data->get_user_read_marker(me)); + + for(auto &message : new_messages) { + // TODO: Is @room ok? shouldn't we also check if the user has permission to do @room? (only when notifications are limited to @mentions) + // TODO: Is comparing against read marker timestamp ok enough? + if(has_unread_notifications && me && (!read_marker_message || read_marker_message->timestamp < message->timestamp)) + message->mentions_me = message_contains_user_mention(message->body, me->display_name) || message_contains_user_mention(message->body, me->user_id) || message_contains_user_mention(message->body, "@room"); } } |