From b23637e59839f5f28258f518ac234b2ff62b6da2 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Tue, 9 Nov 2010 21:06:28 +0000
Subject: Only request new MUC context when rejoining.

Resolves: #542
Release-Notes: On reconnects, existing MUC history now won't be replayed.

diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 259b715..6ac6a0c 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -96,10 +96,10 @@ void MUCController::rejoin() {
 		joined_ = false;
 		parting_ = false;
 		//FIXME: check for received activity
-		if (/*lastActivityDate_ == none*/true) {
+		if (lastActivity_ == boost::posix_time::not_a_date_time) {
 			muc_->joinAs(nick_);
 		} else {
-			muc_->joinWithContextSince(nick_);
+			muc_->joinWithContextSince(nick_, lastActivity_);
 		}
 	}
 }
@@ -230,6 +230,9 @@ bool MUCController::messageTargetsMe(boost::shared_ptr<Message> message) {
 }
 
 void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
+	if (messageEvent->getStanza()->getType() == Message::Groupchat) {
+		lastActivity_ = boost::posix_time::microsec_clock::universal_time();
+	}
 	clearPresenceQueue();
 	boost::shared_ptr<Message> message = messageEvent->getStanza();
 	if (joined_ && messageEvent->getStanza()->getFrom().getResource() != nick_ && messageTargetsMe(message) && !message->getPayload<Delay>()) {
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 1af9c58..20bf403 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -93,6 +93,7 @@ namespace Swift {
 			boost::shared_ptr<Timer> loginCheckTimer_;
 			std::set<String> currentOccupants_;
 			std::vector<NickJoinPart> joinParts_;
+			boost::posix_time::ptime lastActivity_;
 	};
 }
 
diff --git a/Swiften/Elements/MUCPayload.h b/Swiften/Elements/MUCPayload.h
index 4b48b45..5d7c4f5 100644
--- a/Swiften/Elements/MUCPayload.h
+++ b/Swiften/Elements/MUCPayload.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <boost/optional.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 #include "Swiften/JID/JID.h"
 #include "Swiften/Base/String.h"
@@ -14,6 +15,49 @@
 
 namespace Swift {
 	class MUCPayload : public Payload {
+		public:
+			MUCPayload() {
+				maxChars_ = -1;
+				maxStanzas_ = -1;
+				seconds_ = -1;
+			}
 
+			void setMaxChars(int maxChars) {
+				maxChars_ = maxChars;
+			}
+
+			void setMaxStanzas(int maxStanzas) {
+				maxStanzas_ = maxStanzas;
+			}
+
+			void setSeconds(int seconds) {
+				seconds_ = seconds;
+			}
+
+			void setSince(boost::posix_time::ptime since) {
+				since_ = since;
+			}
+
+			int getMaxChars() {
+				return maxChars_;
+			}
+
+			int getMaxStanzas() {
+				return maxStanzas_;
+			}
+
+			int getSeconds() {
+				return seconds_;
+			}
+
+			boost::posix_time::ptime getSince() {
+				return since_;
+			}
+
+		private:
+			int maxChars_;
+			int maxStanzas_;
+			int seconds_;
+			boost::posix_time::ptime since_;
 	};
 }
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 9f7c500..b0365d4 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -34,6 +34,7 @@ MUC::MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSende
  * Join the MUC with default context.
  */
 void MUC::joinAs(const String &nick) {
+	joinSince_ = boost::posix_time::not_a_date_time;
 	internalJoin(nick);
 }
 
@@ -43,17 +44,20 @@ void MUC::internalJoin(const String &nick) {
 	joinComplete_ = false;
 	ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick);
 	boost::shared_ptr<Presence> joinPresence(presenceSender->getLastSentUndirectedPresence());
-	//FIXME: use date
 	joinPresence->setTo(ownMUCJID);
-	joinPresence->addPayload(boost::shared_ptr<Payload>(new MUCPayload()));
+	boost::shared_ptr<MUCPayload> mucPayload(new MUCPayload());
+	if (joinSince_ != boost::posix_time::not_a_date_time) {
+		mucPayload->setSince(joinSince_);
+	}
+	joinPresence->addPayload(mucPayload);
 	presenceSender->sendPresence(joinPresence);
 }
 
 /**
  * Join the MUC with context since date.
  */
-void MUC::joinWithContextSince(const String &nick) {
-	//FIXME: add date
+void MUC::joinWithContextSince(const String &nick, const boost::posix_time::ptime& since) {
+	joinSince_ = since;
 	internalJoin(nick);
 }
 
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 29dbbe1..672cdf2 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -42,7 +42,7 @@ namespace Swift {
 			}
 
 			void joinAs(const String &nick);
-			void joinWithContextSince(const String &nick);
+			void joinWithContextSince(const String &nick, const boost::posix_time::ptime& since);
 			/*void queryRoomInfo(); */
 			/*void queryRoomItems(); */
 			String getCurrentNick();
@@ -85,5 +85,6 @@ namespace Swift {
 			std::map<String, MUCOccupant> occupants;
 			bool joinComplete_;
 			boost::bsignals::scoped_connection scopedConnection_;
+			boost::posix_time::ptime joinSince_;
 	};
 }
diff --git a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp
index 4586a74..087dece 100644
--- a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp
@@ -13,8 +13,32 @@ namespace Swift {
 MUCPayloadSerializer::MUCPayloadSerializer() : GenericPayloadSerializer<MUCPayload>() {
 }
 
-String MUCPayloadSerializer::serializePayload(boost::shared_ptr<MUCPayload>)  const {
+String MUCPayloadSerializer::serializePayload(boost::shared_ptr<MUCPayload> muc)  const {
 	XMLElement mucElement("x", "http://jabber.org/protocol/muc");
+	boost::shared_ptr<XMLElement> historyElement(new XMLElement("history"));
+	bool history = false;
+	if (muc->getMaxChars() >= 0) {
+		historyElement->setAttribute("maxchars", boost::lexical_cast<std::string>(muc->getMaxChars()));
+		history = true;
+	}
+	if (muc->getMaxStanzas() >= 0) {
+		historyElement->setAttribute("maxstanzas", boost::lexical_cast<std::string>(muc->getMaxStanzas()));
+		history = true;
+	}
+	if (muc->getSeconds() >= 0) {
+		historyElement->setAttribute("seconds", boost::lexical_cast<std::string>(muc->getSeconds()));
+		history = true;
+	}
+	if (muc->getSince() != boost::posix_time::not_a_date_time) {
+		String sinceString = String(boost::posix_time::to_iso_extended_string(muc->getSince()));
+		sinceString.replaceAll(',', ".");
+		sinceString += "Z";
+		historyElement->setAttribute("since", sinceString);
+		history = true;
+	}
+	if (history) {
+		mucElement.addNode(historyElement);
+	}
 	return mucElement.serialize();
 }
 
-- 
cgit v0.10.2-6-g49f6