From 5b22db817bfc84db5ce1956ec1cb4a6d9f98e35b Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 22 Oct 2010 11:53:01 +0100
Subject: Don't send composing events to offline users.

Resolves: #637

diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 0247c0e..10a0336 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -54,6 +54,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
 	if (theirPresence && !theirPresence->getStatus().isEmpty()) {
 		startMessage += " (" + theirPresence->getStatus() + ")";
 	}
+	chatStateNotifier_->setContactIsOnline(theirPresence && theirPresence->getType() == Presence::Available);
 	startMessage += ".";
 	chatWindow_->addSystemMessage(startMessage);
 	chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_));
@@ -80,6 +81,13 @@ void ChatController::setToJID(const JID& jid) {
 	chatStateMessageSender_->setContact(jid);
 	ChatControllerBase::setToJID(jid);
 	handleCapsChanged(jid);
+	Presence::ref presence;
+	if (isInMUC_) {
+		presence = presenceOracle_->getLastPresence(jid);
+	} else {
+		presence = jid.isBare() ? presenceOracle_->getHighestPriorityPresence(jid.toBare()) : presenceOracle_->getLastPresence(jid);
+	}
+	chatStateNotifier_->setContactIsOnline(presence && presence->getType() == Presence::Available);
 }
 
 bool ChatController::isIncomingMessageFromMe(boost::shared_ptr<Message>) {
@@ -174,6 +182,7 @@ void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresenc
 	}
 
 	chatStateTracker_->handlePresenceChange(newPresence);
+	chatStateNotifier_->setContactIsOnline(newPresence->getType() == Presence::Available);
 	String newStatusChangeString = getStatusChangeString(newPresence);
 	if (newStatusChangeString != lastStatusChangeString_) {
 		if (lastWasPresence_) {
diff --git a/Swiften/Chat/ChatStateNotifier.cpp b/Swiften/Chat/ChatStateNotifier.cpp
index 667c244..1aee9cf 100644
--- a/Swiften/Chat/ChatStateNotifier.cpp
+++ b/Swiften/Chat/ChatStateNotifier.cpp
@@ -16,10 +16,15 @@ void ChatStateNotifier::setContactHas85Caps(bool hasCaps) {
 	contactHas85Caps_ = hasCaps;
 }
 
+void ChatStateNotifier::setContactIsOnline(bool online) {
+	contactIsOnline_ = online;
+}
+
 void ChatStateNotifier::contactJIDHasChanged() {
 	contactHasSentActive_ = false;
 	contactHas85Caps_ = false;
 	userIsTyping_ = false;
+	contactIsOnline_ = false;
 }
 
 void ChatStateNotifier::setUserIsTyping() {
@@ -50,7 +55,7 @@ bool ChatStateNotifier::contactShouldReceiveStates() {
 	   heard from the contact, the active state overrides this.
 	   *HOWEVER* it says that the MUST NOT send csn if you haven't received
 	   active is OPTIONAL behaviour for if you haven't got caps.*/
-	return contactHasSentActive_ || contactHas85Caps_ ;
+	return contactIsOnline_ && (contactHasSentActive_ || contactHas85Caps_);
 }
 
 }
diff --git a/Swiften/Chat/ChatStateNotifier.h b/Swiften/Chat/ChatStateNotifier.h
index 8dcd5cd..3889b9c 100644
--- a/Swiften/Chat/ChatStateNotifier.h
+++ b/Swiften/Chat/ChatStateNotifier.h
@@ -17,6 +17,7 @@ namespace Swift {
 			ChatStateNotifier();
 			void setContactHas85Caps(bool hasCaps);
 			void setUserIsTyping();
+			void setContactIsOnline(bool online);
 			void userSentMessage();
 			void userCancelledNewMessage();
 			void receivedMessageFromContact(bool hasActiveElement);
@@ -28,5 +29,6 @@ namespace Swift {
 			bool contactHas85Caps_;
 			bool contactHasSentActive_;
 			bool userIsTyping_;
+			bool contactIsOnline_;
 	};
 }
diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
index 2fa4c26..045a245 100644
--- a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
+++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
@@ -50,6 +50,7 @@ class ChatStateNotifierTest : public CppUnit::TestFixture {
 	CPPUNIT_TEST(testStartTypingReply_CapsIncluded);
 	CPPUNIT_TEST(testCancelledNewMessage);
 	CPPUNIT_TEST(testContinueTypingReply_CapsIncluded);
+	CPPUNIT_TEST(testTypeReplies_WentOffline);
 	CPPUNIT_TEST(testContactShouldReceiveStates_CapsOnly);
 	CPPUNIT_TEST(testContactShouldReceiveStates_CapsNorActive);
 	CPPUNIT_TEST(testContactShouldReceiveStates_ActiveOverrideOn);	
@@ -63,6 +64,7 @@ private:
 public:
 	void setUp() {
 		notifier_ = new ChatStateNotifier();
+		notifier_->setContactIsOnline(true);
 		monitor_ = new ChatStateMonitor(notifier_);
 	}
 	
@@ -134,8 +136,21 @@ public:
 		notifier_->setUserIsTyping();
 		notifier_->setUserIsTyping();
 		CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount);
+		notifier_->userSentMessage();
+		notifier_->setUserIsTyping();
+		CPPUNIT_ASSERT_EQUAL(2, monitor_->composingCallCount);
+
 	}
 
+	void testTypeReplies_WentOffline() {
+			notifier_->setContactHas85Caps(true);
+			notifier_->setUserIsTyping();
+			CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount);
+			notifier_->setContactIsOnline(false);
+			notifier_->userSentMessage();
+			notifier_->setUserIsTyping();
+			CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount);
+		}
 	
 };
 
-- 
cgit v0.10.2-6-g49f6