aboutsummaryrefslogtreecommitdiff
path: root/src/QuickMedia.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-11-13 02:05:27 +0100
committerdec05eba <dec05eba@protonmail.com>2022-11-13 02:05:27 +0100
commitaea90e2c43d6dbf8b8276e1209f4d4abe1cea128 (patch)
treea21cd16b95e027d7e277e25089b63b45e2bdb735 /src/QuickMedia.cpp
parent01f23292bf2451a0c7b9ada88c6314dcb09509b1 (diff)
Matrix: fix message edits not being applied correctly
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r--src/QuickMedia.cpp190
1 files changed, 92 insertions, 98 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index e8c76d7..74cd4a1 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -5261,37 +5261,45 @@ namespace QuickMedia {
static const mgl::vec2i CHAT_MESSAGE_THUMBNAIL_MAX_SIZE(600, 337);
- // TODO: Optimize
+ static Message* get_original_message(Message *message) {
+ while(message) {
+ if(!message->replaces)
+ break;
+ message = message->replaces;
+ }
+ return message;
+ }
+
+ // TODO: Optimize.
+ // Note: finds the original message if it's an edit
static std::shared_ptr<BodyItem> find_body_item_by_event_id(const std::shared_ptr<BodyItem> *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) {
if(event_id.empty())
return nullptr;
for(size_t i = 0; i < num_body_items; ++i) {
auto &body_item = body_items[i];
- if(body_item->userdata && static_cast<Message*>(body_item->userdata)->event_id == event_id) {
- if(index_result)
- *index_result = i;
- return body_item;
+ Message *message = static_cast<Message*>(body_item->userdata);
+ if(message && message->event_id == event_id) {
+ const Message *original_message = get_original_message(message);
+ if(original_message == message) {
+ if(index_result)
+ *index_result = i;
+ return body_item;
+ } else {
+ return find_body_item_by_event_id(body_items, num_body_items, original_message->event_id, index_result);
+ }
}
}
return nullptr;
}
- // TODO: Optimize
static std::shared_ptr<BodyItem> find_body_item_by_event_id(BodyItemList body_items, const std::string &event_id, int *index_result) {
- if(event_id.empty())
- return nullptr;
-
- for(int i = 0; i < (int)body_items.size(); ++i) {
- auto &body_item = body_items[i];
- if(body_item->userdata && static_cast<Message*>(body_item->userdata)->event_id == event_id) {
- if(index_result)
- *index_result = i;
- return body_item;
- }
- }
- return nullptr;
+ size_t index_result_z = 0;
+ auto result = find_body_item_by_event_id(body_items.data(), body_items.size(), event_id, &index_result_z);
+ if(index_result)
+ *index_result = index_result_z;
+ return result;
}
// Returns true if cached and loaded
@@ -5319,9 +5327,10 @@ namespace QuickMedia {
}
static std::shared_ptr<BodyItem> message_to_body_item(Matrix *matrix, RoomData *room, Message *message, const std::string &my_display_name, const std::string &my_user_id) {
+ Message *latest_message = get_latest_message_in_edit_chain(message);
auto body_item = BodyItem::create("");
body_item->set_author(extract_first_line_remove_newline_elipses(room->get_user_display_name(message->user), AUTHOR_MAX_LENGTH));
- body_item->set_description(strip(message_to_qm_text(matrix, message)));
+ body_item->set_description(strip(message_to_qm_text(matrix, latest_message)));
body_item->set_timestamp(message->timestamp);
if(!message->thumbnail_url.empty()) {
body_item->thumbnail_url = message->thumbnail_url;
@@ -5422,19 +5431,6 @@ namespace QuickMedia {
user_update_display_info(body_item->embedded_item.get(), room, (Message*)body_item->embedded_item->userdata);
}
- static Message* get_original_message(Message *message) {
- if(!message)
- return nullptr;
-
- Message *replaces = message->replaces;
- while(replaces) {
- if(!replaces->replaces)
- return replaces;
- replaces = replaces->replaces;
- }
- return message;
- }
-
bool Program::chat_page(MatrixChatPage *matrix_chat_page, RoomData *current_room) {
assert(current_room);
assert(strcmp(plugin_name, "matrix") == 0);
@@ -5445,6 +5441,8 @@ namespace QuickMedia {
window.set_title(("QuickMedia - matrix - " + current_room->get_name()).c_str());
bool move_room = false;
+ // Year 2500.. The year that humanity is wiped out. Also we want our local message to appear at the bottom even if time is not synced with ntp, until it's replaced by the server
+ constexpr int64_t timestamp_provisional_event = 16755030000LL * 1000LL;
const float room_name_text_height = std::floor(18.0f * get_config().scale * get_config().font_scale);
mgl::Text room_name_text("", *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD, room_name_text_height));
@@ -5843,7 +5841,7 @@ namespace QuickMedia {
std::string event_id;
};
- std::unordered_map<std::string, std::shared_ptr<Message>> pending_sent_replies;
+ std::unordered_map<std::string, ProvisionalMessage> pending_sent_events;
// This is needed to keep the message shared ptr alive. TODO: Remove this shit, maybe even use raw pointers.
std::unordered_map<std::string, ProvisionalMessage> sent_messages; // |event_id| is always empty in this. Use |message->event_id| instead
@@ -5860,38 +5858,6 @@ namespace QuickMedia {
};
std::thread post_thread(post_thread_handler);
- 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->get_items().data(), tabs[MESSAGES_TAB_INDEX].body->get_items().size(), message->related_event_id);
- if(body_item) {
- Message *reply_to_message = static_cast<Message*>(body_item->userdata);
- if(!reply_to_message) {
- show_notification("QuickMedia", "Unexpected error, failed to set replaced by message", Urgency::CRITICAL);
- return;
- }
- message->replaces = reply_to_message;
- reply_to_message->replaced_by = message;
- }
- } else if(message->related_event_type == RelatedEventType::REPLY) {
- auto pending_sent_reply_it = pending_sent_replies.find(message->transaction_id);
- if(pending_sent_reply_it != pending_sent_replies.end()) {
- pending_sent_reply_it->second->replaced_by = message;
- pending_sent_replies.erase(pending_sent_reply_it);
- }
- }
- };
-
- auto filter_sent_messages = [&sent_messages, &message_set_replaced_by](Messages &messages) {
- for(auto it = messages.begin(); it != messages.end();) {
- if(!(*it)->event_id.empty() && sent_messages.find((*it)->event_id) != sent_messages.end()) {
- message_set_replaced_by(*it);
- it = messages.erase(it);
- } else {
- ++it;
- }
- }
- };
-
auto upload_file = [this, &current_room, &tabs, &ui_tabs, &chat_state](const std::string &filepath, const std::string &filename) {
const int selected_tab = ui_tabs.get_selected();
std::shared_ptr<BodyItem> selected = tabs[selected_tab].body->get_selected_shared();
@@ -6064,7 +6030,7 @@ namespace QuickMedia {
"/me [text]: Send a message of type \"m.emote\".\n"
"/react [text]: React to the selected message (also works if you are replying to a message).\n"
"/id: Show the room id.";
- message->timestamp = time(nullptr) * 1000;
+ message->timestamp = time(nullptr) * 1000; // TODO: What if the user has broken local time?
matrix->append_system_message(current_room, std::move(message));
chat_input.set_editable(false);
@@ -6075,7 +6041,7 @@ namespace QuickMedia {
message->type = MessageType::SYSTEM;
message->user = me;
message->body = current_room->id;
- message->timestamp = time(nullptr) * 1000;
+ message->timestamp = time(nullptr) * 1000; // TODO: What if the user has broken local time?
matrix->append_system_message(current_room, std::move(message));
chat_input.set_editable(false);
@@ -6110,7 +6076,9 @@ namespace QuickMedia {
message->body = matrix->body_to_formatted_body(current_room, text);
}
message->type = MessageType::TEXT;
- message->timestamp = time(NULL) * 1000;
+ message->timestamp = timestamp_provisional_event;
+ const std::string transaction_id = create_transaction_id();
+ message->transaction_id = transaction_id;
if(chat_state == ChatState::TYPING_MESSAGE || (chat_state == ChatState::REPLYING && msgtype == "m.reaction")) {
BodyItem *selected_item = tabs[MESSAGES_TAB_INDEX].body->get_selected();
@@ -6125,15 +6093,21 @@ namespace QuickMedia {
message->related_event_id = static_cast<Message*>(related_to_message)->event_id;
auto body_item = message_to_body_item(matrix, current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
- tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
+ tabs[MESSAGES_TAB_INDEX].body->append_item(body_item);
+
+ ProvisionalMessage provisional_message;
+ provisional_message.body_item = body_item;
+ provisional_message.message = message;
+ pending_sent_events[message->transaction_id] = std::move(provisional_message);
+
Messages messages;
messages.push_back(message);
process_reactions(messages);
- post_task_queue.push([this, &current_room, text, body_item, message, related_to_message]() {
+ post_task_queue.push([this, &current_room, text, body_item, message, related_to_message, transaction_id]() {
ProvisionalMessage provisional_message;
provisional_message.body_item = body_item;
provisional_message.message = message;
- if(matrix->post_reaction(current_room, text, related_to_message, provisional_message.event_id) != PluginResult::OK)
+ if(matrix->post_reaction(current_room, text, related_to_message, provisional_message.event_id, transaction_id) != PluginResult::OK)
fprintf(stderr, "Failed to post matrix reaction\n");
return provisional_message;
});
@@ -6141,12 +6115,18 @@ namespace QuickMedia {
auto body_item = message_to_body_item(matrix, current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
body_item->set_description_color(get_theme().provisional_message_color);
load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
- tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
- post_task_queue.push([this, &current_room, text, msgtype, body_item, message]() {
+ tabs[MESSAGES_TAB_INDEX].body->append_item(body_item);
+
+ ProvisionalMessage provisional_message;
+ provisional_message.body_item = body_item;
+ provisional_message.message = message;
+ pending_sent_events[message->transaction_id] = std::move(provisional_message);
+
+ post_task_queue.push([this, &current_room, text, msgtype, body_item, message, transaction_id]() {
ProvisionalMessage provisional_message;
provisional_message.body_item = body_item;
provisional_message.message = message;
- if(matrix->post_message(current_room, text, provisional_message.event_id, std::nullopt, std::nullopt, msgtype) != PluginResult::OK)
+ if(matrix->post_message(current_room, text, provisional_message.event_id, std::nullopt, std::nullopt, msgtype, transaction_id) != PluginResult::OK)
fprintf(stderr, "Failed to post matrix message\n");
return provisional_message;
});
@@ -6157,16 +6137,19 @@ namespace QuickMedia {
tabs[MESSAGES_TAB_INDEX].body->select_last_item();
return true;
} else if(chat_state == ChatState::REPLYING) {
- std::string transaction_id = create_transaction_id();
- pending_sent_replies[transaction_id] = message;
-
void *related_to_message = currently_operating_on_item->userdata;
message->related_event_type = RelatedEventType::REPLY;
message->related_event_id = static_cast<Message*>(related_to_message)->event_id;
auto body_item = message_to_body_item(matrix, current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
body_item->set_description_color(get_theme().provisional_message_color);
load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
- tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
+ tabs[MESSAGES_TAB_INDEX].body->append_item(body_item);
+
+ ProvisionalMessage provisional_message;
+ provisional_message.body_item = body_item;
+ provisional_message.message = message;
+ pending_sent_events[message->transaction_id] = std::move(provisional_message);
+
post_task_queue.push([this, &current_room, text, related_to_message, body_item, message, transaction_id]() {
ProvisionalMessage provisional_message;
provisional_message.body_item = body_item;
@@ -6185,9 +6168,10 @@ namespace QuickMedia {
Message *related_to_message = (Message*)currently_operating_on_item->userdata;
message->related_event_type = RelatedEventType::EDIT;
message->related_event_id = related_to_message->event_id;
- // TODO:
- //related_to_message->replaced_by = message;
- //message->replaces = related_to_message;
+
+ //Message *latest_message_related_to = get_latest_message_in_edit_chain(related_to_message);
+ //latest_message_related_to->replaced_by = message;
+ //message->replaces = latest_message_related_to;
size_t body_item_index = 0;
auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->get_items().data(), tabs[MESSAGES_TAB_INDEX].body->get_items().size(), message->related_event_id, &body_item_index);
if(body_item) {
@@ -6198,17 +6182,17 @@ namespace QuickMedia {
body_item_shared_ptr->set_description(std::move(qm_formatted_text));
body_item_shared_ptr->set_description_color(get_theme().provisional_message_color);
- auto edit_body_item = message_to_body_item(matrix, current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
- edit_body_item->visible = false;
- load_cached_related_embedded_item(edit_body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
- tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({edit_body_item});
+ //auto edit_body_item = message_to_body_item(matrix, current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
+ //edit_body_item->visible = false;
+ //load_cached_related_embedded_item(edit_body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
+ //tabs[MESSAGES_TAB_INDEX].body->append_item(edit_body_item);
//unreferenced_events.push_back(message);
- post_task_queue.push([this, &current_room, text, related_to_message, message, body_item_shared_ptr]() {
+ post_task_queue.push([this, &current_room, text, related_to_message, message, body_item_shared_ptr, transaction_id]() {
ProvisionalMessage provisional_message;
provisional_message.message = message;
provisional_message.body_item = body_item_shared_ptr;
- if(matrix->post_edit(current_room, text, related_to_message, provisional_message.event_id) != PluginResult::OK)
+ if(matrix->post_edit(current_room, text, related_to_message, provisional_message.event_id, transaction_id) != PluginResult::OK)
fprintf(stderr, "Failed to post matrix edit\n");
return provisional_message;
});
@@ -6505,14 +6489,24 @@ namespace QuickMedia {
}
};
- auto filter_provisional_messages = [&message_set_replaced_by](Messages &messages) {
- for(auto it = messages.begin(); it != messages.end();) {
- if(!(*it)->transaction_id.empty()) {
- message_set_replaced_by(*it);
- it = messages.erase(it);
- } else {
- ++it;
+ auto filter_provisional_messages = [&](Messages &messages) {
+ auto &messages_body = tabs[MESSAGES_TAB_INDEX].body;
+ for(auto message_it = messages.begin(); message_it != messages.end();) {
+ auto &message = *message_it;
+ auto it = pending_sent_events.find(message->transaction_id);
+ if(it != pending_sent_events.end()) {
+ if(message->type == MessageType::REACTION) {
+ message_it = messages.erase(message_it);
+ pending_sent_events.erase(it);
+ continue;
+ }
+
+ messages_body->erase_item([&](auto &body_item) {
+ return body_item == it->second.body_item;
+ });
+ pending_sent_events.erase(it);
}
+ ++message_it;
}
};
@@ -6706,7 +6700,7 @@ namespace QuickMedia {
provisional_message_queue.clear();
fetched_messages_set.clear();
sent_messages.clear();
- pending_sent_replies.clear();
+ pending_sent_events.clear();
//unreferenced_event_by_room.clear();
@@ -7436,7 +7430,7 @@ namespace QuickMedia {
if(new_messages_result.message_dir == MessageDirection::AFTER)
fetched_enough_messages_bottom = new_messages_result.reached_end;
- filter_sent_messages(new_messages_result.messages);
+ filter_provisional_messages(new_messages_result.messages);
filter_existing_messages(new_messages_result.messages);
size_t num_new_messages = new_messages_result.messages.size();
if(num_new_messages > 0) {
@@ -7595,7 +7589,7 @@ namespace QuickMedia {
for(; last_timeline_message >= 0; --last_timeline_message) {
BodyItem *item = body_items[last_timeline_message].get();
Message *message = static_cast<Message*>(item->userdata);
- if(item->visible && message && message_is_timeline(message))
+ if(message && message_is_timeline(message) && !message->event_id.empty())
break;
}
@@ -7744,7 +7738,7 @@ namespace QuickMedia {
}
all_messages.insert(all_messages.end(), all_messages_new.begin(), all_messages_new.end());
//me = matrix->get_me(current_room);
- filter_sent_messages(all_messages_new);
+ filter_provisional_messages(all_messages_new);
add_new_messages_to_current_room(all_messages_new);
modify_related_messages_in_current_room(all_messages_new);
unresolved_reactions.clear();