aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/Body.hpp1
-rw-r--r--plugins/Matrix.hpp5
-rw-r--r--src/Body.cpp4
-rw-r--r--src/QuickMedia.cpp5
-rw-r--r--src/plugins/Matrix.cpp65
5 files changed, 65 insertions, 15 deletions
diff --git a/include/Body.hpp b/include/Body.hpp
index 676eef8..1664696 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -186,6 +186,7 @@ namespace QuickMedia {
// Select next item, ignoring invisible items. Returns true if the item was changed or if the item scrolled. This can be used to check if the bottom was hit when wrap_around is set to false
bool select_next_item(bool scroll_page_if_large_item = true);
void set_selected_item(int item, bool reset_prev_selected_item = true);
+ void reset_prev_selected_item();
// Returns -1 if item can't be found
int get_index_by_body_item(BodyItem *body_item);
diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp
index 09500a6..08be8e1 100644
--- a/plugins/Matrix.hpp
+++ b/plugins/Matrix.hpp
@@ -150,6 +150,7 @@ namespace QuickMedia {
std::atomic_int64_t last_message_timestamp = 0;
std::atomic_int unread_notification_count = 0;
+ std::atomic_int64_t read_marker_event_timestamp = 0;
size_t index = 0;
private:
@@ -473,7 +474,7 @@ namespace QuickMedia {
PluginResult on_start_typing(RoomData *room);
PluginResult on_stop_typing(RoomData *room);
- PluginResult set_read_marker(RoomData *room, const std::string &event_id);
+ PluginResult set_read_marker(RoomData *room, const std::string &event_id, int64_t event_timestamp);
PluginResult join_room(const std::string &room_id);
PluginResult leave_room(const std::string &room_id);
@@ -497,6 +498,8 @@ namespace QuickMedia {
bool use_tor = false;
private:
+ PluginResult set_qm_last_read_message_timestamp(RoomData *room, int64_t timestamp);
+
PluginResult parse_sync_response(const rapidjson::Document &root, bool is_additional_messages_sync, bool initial_sync);
PluginResult parse_notifications(const rapidjson::Value &notifications_json);
PluginResult parse_sync_account_data(const rapidjson::Value &account_data_json, std::optional<std::set<std::string>> &dm_rooms);
diff --git a/src/Body.cpp b/src/Body.cpp
index 88bada4..44d1a2d 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -228,6 +228,10 @@ namespace QuickMedia {
//page_scroll = 0.0f;
}
+ void Body::reset_prev_selected_item() {
+ prev_selected_item = selected_item;
+ }
+
int Body::get_index_by_body_item(BodyItem *body_item) {
for(int i = 0; i < (int)items.size(); ++i) {
if(items[i].get() == body_item)
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 6970920..4e84cda 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -3754,8 +3754,9 @@ namespace QuickMedia {
setting_read_marker = true;
RoomData *room = current_room;
std::string event_id = message->event_id;
- set_read_marker_future = [this, room, event_id]() mutable {
- if(matrix->set_read_marker(room, event_id) != PluginResult::OK) {
+ int64_t event_timestamp = message->timestamp;
+ set_read_marker_future = [this, room, event_id, event_timestamp]() mutable {
+ if(matrix->set_read_marker(room, event_id, event_timestamp) != PluginResult::OK) {
fprintf(stderr, "Warning: failed to set read marker to %s\n", event_id.c_str());
}
};
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 66a942b..50a2cd4 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -23,9 +23,9 @@
static const char* SERVICE_NAME = "matrix";
static const char* OTHERS_ROOM_TAG = "tld.name.others";
// Filter without account data
-static const char* INITIAL_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"types\":[\"m.room.message\"],\"limit\":1,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":1,\"types\":[\"m.fully_read\",\"m.tag\"],\"lazy_load_members\":true}}}";
+static const char* INITIAL_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"types\":[\"m.room.message\"],\"limit\":1,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":1,\"types\":[\"m.fully_read\",\"m.tag\",\"qm.last_read_message_timestamp\"],\"lazy_load_members\":true}}}";
static const char* ADDITIONAL_MESSAGES_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"limit\":20,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true}}}";
-static const char* CONTINUE_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"types\":[\"m.fully_read\",\"m.tag\"],\"lazy_load_members\":true}}}";
+static const char* CONTINUE_FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"types\":[\"m.fully_read\",\"m.tag\",\"qm.last_read_message_timestamp\"],\"lazy_load_members\":true}}}";
static std::string capitalize(const std::string &str) {
if(str.size() >= 1)
@@ -437,6 +437,7 @@ namespace QuickMedia {
for(size_t i = 0; i < body->items.size(); ++i) {
if(body->items[i]->url == selected_item->url) {
body->set_selected_item(i);
+ body->reset_prev_selected_item();
return;
}
}
@@ -509,6 +510,9 @@ namespace QuickMedia {
read_marker_message_timestamp = read_marker_message->timestamp;
}
+ if(read_marker_message_timestamp == 0)
+ read_marker_message_timestamp = room->last_read_message_timestamp;
+
std::shared_ptr<Message> last_new_message = get_last_message_by_timestamp(new_messages);
if(!last_new_message)
return;
@@ -532,6 +536,9 @@ namespace QuickMedia {
else if(read_marker_message_timestamp == 0 && !my_user_read_marker.empty() && last_new_message->event_id.find(':') != std::string::npos && last_new_message->event_id > my_user_read_marker)
last_unread_message = last_new_message.get();
+ if(!last_unread_message && read_marker_message_timestamp == 0)
+ last_unread_message = last_new_message.get();
+
//assert(room_body_item);
if(!room->body_item)
return;
@@ -1603,18 +1610,30 @@ namespace QuickMedia {
continue;
const rapidjson::Value &type_json = GetMember(event_json, "type");
- if(!type_json.IsString() || strcmp(type_json.GetString(), "m.fully_read") != 0)
+ if(!type_json.IsString())
continue;
- const rapidjson::Value &content_json = GetMember(event_json, "content");
- if(!content_json.IsObject())
- continue;
+ if(strcmp(type_json.GetString(), "m.fully_read") == 0) {
+ const rapidjson::Value &content_json = GetMember(event_json, "content");
+ if(!content_json.IsObject())
+ continue;
- const rapidjson::Value &event_id_json = GetMember(content_json, "event_id");
- if(!event_id_json.IsString())
- continue;
+ const rapidjson::Value &event_id_json = GetMember(content_json, "event_id");
+ if(!event_id_json.IsString())
+ continue;
+
+ room_data->set_user_read_marker(me, std::string(event_id_json.GetString(), event_id_json.GetStringLength()));
+ } else if(strcmp(type_json.GetString(), "qm.last_read_message_timestamp") == 0) {
+ const rapidjson::Value &content_json = GetMember(event_json, "content");
+ if(!content_json.IsObject())
+ continue;
- room_data->set_user_read_marker(me, std::string(event_id_json.GetString(), event_id_json.GetStringLength()));
+ const rapidjson::Value &timestamp_json = GetMember(content_json, "timestamp");
+ if(!timestamp_json.IsInt64())
+ continue;
+
+ room_data->last_read_message_timestamp = timestamp_json.GetInt64();
+ }
}
}
@@ -3360,7 +3379,7 @@ namespace QuickMedia {
return download_result_to_plugin_result(download_result);
}
- PluginResult Matrix::set_read_marker(RoomData *room, const std::string &event_id) {
+ PluginResult Matrix::set_read_marker(RoomData *room, const std::string &event_id, int64_t event_timestamp) {
rapidjson::Document request_data(rapidjson::kObjectType);
request_data.AddMember("m.fully_read", rapidjson::StringRef(event_id.c_str()), request_data.GetAllocator());
request_data.AddMember("m.read", rapidjson::StringRef(event_id.c_str()), request_data.GetAllocator());
@@ -3385,7 +3404,29 @@ namespace QuickMedia {
if(me)
room->set_user_read_marker(me, event_id);
- return PluginResult::OK;
+ return set_qm_last_read_message_timestamp(room, event_timestamp);
+ }
+
+ PluginResult Matrix::set_qm_last_read_message_timestamp(RoomData *room, int64_t timestamp) {
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("timestamp", timestamp, request_data.GetAllocator());
+
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
+
+ std::vector<CommandArg> additional_args = {
+ { "-X", "PUT" },
+ { "-H", "content-type: application/json" },
+ { "-H", "Authorization: Bearer " + access_token },
+ { "--data-binary", buffer.GetString() }
+ };
+
+ room->last_read_message_timestamp = timestamp;
+
+ std::string server_response;
+ DownloadResult download_result = download_to_string(homeserver + "/_matrix/client/r0/user/" + my_user_id + "/rooms/" + room->id + "/account_data/qm.last_read_message_timestamp", server_response, std::move(additional_args), use_tor, true);
+ return download_result_to_plugin_result(download_result);
}
PluginResult Matrix::join_room(const std::string &room_id) {