From 556d6a85c9d5f4e2d29b94526689568b4081c006 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Robert=20P=C3=B6sel?= <robyer@seznam.cz>
Date: Mon, 1 Dec 2014 22:24:48 +0000
Subject: Facebook: Optimize marking chat messages as read

Not mark as read every single message when loading history messages.

git-svn-id: http://svn.miranda-ng.org/main/trunk@11206 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 protocols/FacebookRM/src/client.h     |  2 +-
 protocols/FacebookRM/src/messages.cpp | 33 ++++++++++++++++++++++++---------
 protocols/FacebookRM/src/process.cpp  | 21 +++++++++++++--------
 protocols/FacebookRM/src/proto.cpp    | 19 +++++++++----------
 4 files changed, 47 insertions(+), 28 deletions(-)

(limited to 'protocols/FacebookRM')

diff --git a/protocols/FacebookRM/src/client.h b/protocols/FacebookRM/src/client.h
index d69c311363..e84aa3ad08 100644
--- a/protocols/FacebookRM/src/client.h
+++ b/protocols/FacebookRM/src/client.h
@@ -108,7 +108,7 @@ public:
 	std::string get_server_type();
 	std::string get_privacy_type();
 
-	std::map<MCONTACT, bool> ignore_read;
+	std::set<MCONTACT> ignore_read;
 	std::set<MCONTACT> typers;		// store info about typing contacts, because Facebook doesn't send "stopped typing" event when there is actual message being sent
 	std::map<MCONTACT, time_t> readers;
 
diff --git a/protocols/FacebookRM/src/messages.cpp b/protocols/FacebookRM/src/messages.cpp
index d25514fb4a..fb415825be 100644
--- a/protocols/FacebookRM/src/messages.cpp
+++ b/protocols/FacebookRM/src/messages.cpp
@@ -175,21 +175,36 @@ void FacebookProto::ReadMessageWorker(void *p)
 	if (p == NULL)
 		return;
 	
-	MCONTACT hContact = (MCONTACT)p;
-	
-	if (getBool(FACEBOOK_KEY_KEEP_UNREAD, 0) || getBool(hContact, FACEBOOK_KEY_KEEP_UNREAD, 0))
+	if (getBool(FACEBOOK_KEY_KEEP_UNREAD, 0))
 		return;
 
-	// mark message read (also send seen info)
-	const char *value = (isChatRoom(hContact) ? FACEBOOK_KEY_TID : FACEBOOK_KEY_ID);
-	ptrA id( getStringA(hContact, value));
-	if (id == NULL)
+	std::set<MCONTACT> *hContacts = (std::set<MCONTACT>*)p;
+
+	if (hContacts->empty()) {
+		delete hContacts;
 		return;
+	}
 
-	std::string data = "ids[" + utils::url::encode(std::string(id)) + "]=true";
-	data += "&fb_dtsg=" + facy.dtsg_;
+	std::string data = "fb_dtsg=" + facy.dtsg_;
 	data += "&__user=" + facy.self_.user_id;
 	data += "&__a=1&__dyn=&__req=&ttstamp=" + facy.ttstamp();
+	
+	for (std::set<MCONTACT>::iterator it = hContacts->begin(); it != hContacts->end(); ++it) {
+		MCONTACT hContact = *it;
+
+		if (getBool(hContact, FACEBOOK_KEY_KEEP_UNREAD, 0))
+			continue;
+
+		// mark message read (also send seen info)
+		const char *value = (isChatRoom(hContact) ? FACEBOOK_KEY_TID : FACEBOOK_KEY_ID);
+		ptrA id(getStringA(hContact, value));
+		if (id == NULL)
+			continue;
+		
+		data += "&ids[" + utils::url::encode(std::string(id)) + "]=true";
+	}
+	hContacts->clear();
+	delete hContacts;
 
 	facy.flap(REQUEST_MARK_READ, &data);
 }
diff --git a/protocols/FacebookRM/src/process.cpp b/protocols/FacebookRM/src/process.cpp
index b4e182842e..d7e676324b 100644
--- a/protocols/FacebookRM/src/process.cpp
+++ b/protocols/FacebookRM/src/process.cpp
@@ -492,9 +492,9 @@ void FacebookProto::LoadLastMessages(void *p)
 		facy.handle_error("LoadLastMessages");
 		return;
 	}
-
+	
 	// Temporarily disable marking messages as read for this contact
-	facy.ignore_read.insert(std::make_pair(hContact, true));
+	facy.ignore_read.insert(hContact);
 
 CODE_BLOCK_TRY
 
@@ -547,11 +547,8 @@ CODE_BLOCK_END
 	facy.handle_success("LoadLastMessages");
 
 	// Enable marking messages as read for this contact
-	std::map<MCONTACT, bool>::iterator it = facy.ignore_read.find(hContact);
-	if (it != facy.ignore_read.end()) {
-		it->second = false;
-	}
-	
+	facy.ignore_read.erase(hContact);
+
 	// And force mark read
 	OnDbEventRead(hContact, NULL);
 }
@@ -676,6 +673,8 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message*> messages, boo
 		}
 	}
 
+	std::set<MCONTACT> *hChatContacts = new std::set<MCONTACT>();
+
 	for(std::vector<facebook_message*>::size_type i = 0; i < messages.size(); i++) {
 		DWORD timestamp = local_timestamp || !messages[i]->time ? ::time(NULL) : messages[i]->time;
 
@@ -752,7 +751,7 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message*> messages, boo
 			UpdateChat(tthread_id.c_str(), messages[i]->user_id.c_str(), messages[i]->sender_name.c_str(), messages[i]->message_text.c_str(), timestamp);
 
 			// Automatically mark message as read because chatroom doesn't support onRead event (yet)
-			ForkThread(&FacebookProto::ReadMessageWorker, (void*)hChatContact);
+			hChatContacts->insert(hChatContact); // std::set checks duplicates at insert automatically
 		} else {
 			// Single-user message
 			debugLogA("      Got message: %s", messages[i]->message_text.c_str());
@@ -823,6 +822,12 @@ void FacebookProto::ReceiveMessages(std::vector<facebook_message*> messages, boo
 		delete messages[i];
 	}
 	messages.clear();
+
+	if (!hChatContacts->empty()) {
+		ForkThread(&FacebookProto::ReadMessageWorker, (void*)hChatContacts);
+	} else {
+		delete hChatContacts;
+	}
 }
 
 void FacebookProto::ProcessMessages(void* data)
diff --git a/protocols/FacebookRM/src/proto.cpp b/protocols/FacebookRM/src/proto.cpp
index b10a5821b5..a5443be932 100644
--- a/protocols/FacebookRM/src/proto.cpp
+++ b/protocols/FacebookRM/src/proto.cpp
@@ -538,17 +538,16 @@ INT_PTR FacebookProto::OnMind(WPARAM wParam, LPARAM lParam)
 
 int FacebookProto::OnDbEventRead(WPARAM contactID, LPARAM dbei)
 {
-	std::map<MCONTACT, bool>::iterator it = facy.ignore_read.find(contactID);
-	if (it != facy.ignore_read.end()) {
-		if (it->second) // it's TRUE, so we ignore this
-			return 0;
-		else // it's FALSE, so we just remove it from list
-			facy.ignore_read.erase(it);
-	}
+	if (isOffline() || !IsMyContact(contactID, false)) // ignore chats
+		return 0;
 
-	if ((IsMyContact(contactID, true)) && !isOffline()) {
-		ForkThread(&FacebookProto::ReadMessageWorker, (void*)contactID);
-	}
+	if (facy.ignore_read.find(contactID) != facy.ignore_read.end())
+		return 0; // it's there, so we ignore this
+
+	std::set<MCONTACT> *hContacts = new std::set<MCONTACT>();
+	hContacts->insert(contactID);
+
+	ForkThread(&FacebookProto::ReadMessageWorker, (void*)hContacts);
 
 	return 0;
 }
-- 
cgit v1.2.3