diff options
| -rw-r--r-- | Swiften/Chat/ChatStateActionProvider.h | 7 | ||||
| -rw-r--r-- | Swiften/Chat/ChatStateMessageSender.cpp | 5 | ||||
| -rw-r--r-- | Swiften/Chat/ChatStateMessageSender.h | 7 | ||||
| -rw-r--r-- | Swiften/Chat/ChatStateNotifier.cpp | 45 | ||||
| -rw-r--r-- | Swiften/Chat/ChatStateNotifier.h | 25 | ||||
| -rw-r--r-- | Swiften/Chat/ChatStateTracker.cpp | 5 | ||||
| -rw-r--r-- | Swiften/Chat/ChatStateTracker.h | 7 | ||||
| -rw-r--r-- | Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp | 132 | ||||
| -rw-r--r-- | Swiften/SConscript | 5 | 
9 files changed, 238 insertions, 0 deletions
| diff --git a/Swiften/Chat/ChatStateActionProvider.h b/Swiften/Chat/ChatStateActionProvider.h new file mode 100644 index 0000000..82bed3f --- /dev/null +++ b/Swiften/Chat/ChatStateActionProvider.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Swift { +	class ChatState { +		 +	}; +} diff --git a/Swiften/Chat/ChatStateMessageSender.cpp b/Swiften/Chat/ChatStateMessageSender.cpp new file mode 100644 index 0000000..d053cb5 --- /dev/null +++ b/Swiften/Chat/ChatStateMessageSender.cpp @@ -0,0 +1,5 @@ +#include "Swiften/Chat/ChatStateMessageSender.h" + +namespace Swift { + +} diff --git a/Swiften/Chat/ChatStateMessageSender.h b/Swiften/Chat/ChatStateMessageSender.h new file mode 100644 index 0000000..d27973d --- /dev/null +++ b/Swiften/Chat/ChatStateMessageSender.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Swift { +	class ChatStateMessageSender { +		 +	}; +} diff --git a/Swiften/Chat/ChatStateNotifier.cpp b/Swiften/Chat/ChatStateNotifier.cpp new file mode 100644 index 0000000..432f708 --- /dev/null +++ b/Swiften/Chat/ChatStateNotifier.cpp @@ -0,0 +1,45 @@ +#include "Swiften/Chat/ChatStateNotifier.h" + +namespace Swift { + +ChatStateNotifier::ChatStateNotifier() { +	contactHas85Caps_ = false; +	isInConversation_ = false; +	contactHasSentActive_ = false; +	userIsTyping_ = false; +} + +void ChatStateNotifier::setContactHas85Caps(bool hasCaps) { +	contactHas85Caps_ = hasCaps; +} + +void ChatStateNotifier::setUserIsTyping() { +	if (contactShouldReceiveStates() && !userIsTyping_) { +		userIsTyping_ = true; +		onChatStateChanged(Composing); +	} +} + +void ChatStateNotifier::userSentMessage() { +	userIsTyping_ = false; +} + +void ChatStateNotifier::userCancelledNewMessage() { +	if (userIsTyping_) { +		userIsTyping_ = false; +		onChatStateChanged(Active); +	} +} + +void ChatStateNotifier::receivedMessageFromContact(bool hasActiveElement) { +	isInConversation_ = true; +	contactHasSentActive_ = hasActiveElement; +} + +bool ChatStateNotifier::contactShouldReceiveStates() { +	/* So, yes, the XEP says to look at caps, but it also says that once you've +	   heard from the contact, the active state overrides this.*/ +	return contactHasSentActive_ || (contactHas85Caps_ && !isInConversation_);; +} + +} diff --git a/Swiften/Chat/ChatStateNotifier.h b/Swiften/Chat/ChatStateNotifier.h new file mode 100644 index 0000000..90228b7 --- /dev/null +++ b/Swiften/Chat/ChatStateNotifier.h @@ -0,0 +1,25 @@ +#pragma once + +#include <boost/signals.hpp> +#include <boost/shared_ptr.hpp> + +namespace Swift { +	class ChatStateNotifier { +		public: +			enum ChatState {Active, Composing, Paused, Inactive, Gone}; +			ChatStateNotifier(); +			void setContactHas85Caps(bool hasCaps); +			void setUserIsTyping(); +			void userSentMessage(); +			void userCancelledNewMessage(); +			void receivedMessageFromContact(bool hasActiveElement); +			bool contactShouldReceiveStates(); + +			boost::signal<void (ChatState)> onChatStateChanged; +		private: +			bool contactHas85Caps_; +			bool isInConversation_; +			bool contactHasSentActive_; +			bool userIsTyping_; +	}; +} diff --git a/Swiften/Chat/ChatStateTracker.cpp b/Swiften/Chat/ChatStateTracker.cpp new file mode 100644 index 0000000..553d2f4 --- /dev/null +++ b/Swiften/Chat/ChatStateTracker.cpp @@ -0,0 +1,5 @@ +#include "Swiften/Chat/ChatStateTracker.h" + +namespace Swift { + +} diff --git a/Swiften/Chat/ChatStateTracker.h b/Swiften/Chat/ChatStateTracker.h new file mode 100644 index 0000000..005c479 --- /dev/null +++ b/Swiften/Chat/ChatStateTracker.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Swift { +	class ChatStateTracker { +		 +	}; +} diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp new file mode 100644 index 0000000..bacfc3a --- /dev/null +++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp @@ -0,0 +1,132 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <boost/bind.hpp> + +#include "Swiften/Chat/ChatStateNotifier.h" + +using namespace Swift; + + +class ChatStateMonitor { +public: +	ChatStateMonitor(ChatStateNotifier* notifier) { +		notifier_ = notifier; +		composingCallCount = 0; +		activeCallCount = 0; +		notifier->onChatStateChanged.connect(boost::bind(&ChatStateMonitor::handleChatStateChanged, this, _1)); +	}; + +	int composingCallCount; +	int activeCallCount; +	ChatStateNotifier::ChatState currentState; + +private: +	void handleChatStateChanged(ChatStateNotifier::ChatState newState) { +		switch (newState) { +			case ChatStateNotifier::Composing: +				composingCallCount++; +				break; +			case ChatStateNotifier::Active: +				activeCallCount++; +				break; +			default: +				break; +			} +		currentState = newState; +	}; + +	ChatStateNotifier* notifier_; +}; + +class ChatStateNotifierTest : public CppUnit::TestFixture { +	CPPUNIT_TEST_SUITE(ChatStateNotifierTest); +	CPPUNIT_TEST(testStartTypingReply_CapsNotIncluded); +	CPPUNIT_TEST(testStartTypingReply_CapsIncluded); +	CPPUNIT_TEST(testCancelledNewMessage); +	CPPUNIT_TEST(testContinueTypingReply_CapsIncluded); +	CPPUNIT_TEST(testContactShouldReceiveStates_CapsOnly); +	CPPUNIT_TEST(testContactShouldReceiveStates_CapsNorActive); +	CPPUNIT_TEST(testContactShouldReceiveStates_ActiveOverrideOn);	 +	CPPUNIT_TEST(testContactShouldReceiveStates_ActiveOverrideOff); +	CPPUNIT_TEST_SUITE_END(); +	 +private: +	ChatStateNotifier* notifier_; +	ChatStateMonitor* monitor_; +	 +public: +	void setUp() { +		notifier_ = new ChatStateNotifier(); +		monitor_ = new ChatStateMonitor(notifier_); +	} +	 +	void tearDown() { +		delete notifier_; +		delete monitor_; +	} +	 +	void testStartTypingReply_CapsNotIncluded() { +		notifier_->setContactHas85Caps(false); +		notifier_->setUserIsTyping(); +		CPPUNIT_ASSERT_EQUAL(0, monitor_->composingCallCount); +	} + +	void testSendTwoMessages() { +		notifier_->setContactHas85Caps(true); +		notifier_->setUserIsTyping(); +		notifier_->userSentMessage(); +		notifier_->setUserIsTyping(); +		notifier_->userSentMessage(); +		CPPUNIT_ASSERT_EQUAL(2, monitor_->composingCallCount); +	} + +	void testCancelledNewMessage() { +		notifier_->setContactHas85Caps(true); +		notifier_->setUserIsTyping(); +		notifier_->userCancelledNewMessage(); +		CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); +		CPPUNIT_ASSERT_EQUAL(1, monitor_->activeCallCount); +		CPPUNIT_ASSERT_EQUAL(ChatStateNotifier::Active, monitor_->currentState); +	} + + +	void testContactShouldReceiveStates_CapsOnly() { +		notifier_->setContactHas85Caps(true); +		CPPUNIT_ASSERT_EQUAL(true, notifier_->contactShouldReceiveStates()); +	} + +	void testContactShouldReceiveStates_CapsNorActive() { +		CPPUNIT_ASSERT_EQUAL(false, notifier_->contactShouldReceiveStates()); +	} + +	void testContactShouldReceiveStates_ActiveOverrideOn() { +		notifier_->setContactHas85Caps(false); +		notifier_->receivedMessageFromContact(true); +		CPPUNIT_ASSERT_EQUAL(true, notifier_->contactShouldReceiveStates()); +	} + +	void testContactShouldReceiveStates_ActiveOverrideOff() { +		notifier_->setContactHas85Caps(true); +		notifier_->receivedMessageFromContact(false); +		CPPUNIT_ASSERT_EQUAL(false, notifier_->contactShouldReceiveStates()); +	} + + +	void testStartTypingReply_CapsIncluded() { +		notifier_->setContactHas85Caps(true); +		notifier_->setUserIsTyping(); +		CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); +	} + +	void testContinueTypingReply_CapsIncluded() { +		notifier_->setContactHas85Caps(true); +		notifier_->setUserIsTyping(); +		notifier_->setUserIsTyping(); +		notifier_->setUserIsTyping(); +		CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); +	} + +	 +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ChatStateNotifierTest); diff --git a/Swiften/SConscript b/Swiften/SConscript index f8e98de..e31818c 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -17,6 +17,9 @@ sources = [  		"Avatars/AvatarFileStorage.cpp",  		"Avatars/AvatarManager.cpp",  		"Avatars/AvatarStorage.cpp", +		"Chat/ChatStateTracker.cpp", +		"Chat/ChatStateNotifier.cpp", +		"Chat/ChatStateMessageSender.cpp",  		"Client/Client.cpp",  		"Client/ClientSession.cpp",  		"Compress/ZLibCodecompressor.cpp", @@ -119,6 +122,8 @@ env.Append(UNITTEST_SOURCES = [  		File("Base/UnitTest/IDGeneratorTest.cpp"),  		File("Base/UnitTest/StringTest.cpp"),  		File("Base/UnitTest/ByteArrayTest.cpp"), +		File("Chat/UnitTest/ChatStateNotifierTest.cpp"), +#		File("Chat/UnitTest/ChatStateTrackerTest.cpp"),  		File("Client/UnitTest/ClientSessionTest.cpp"),  		File("Compress/UnitTest/ZLibCompressorTest.cpp"),  		File("Compress/UnitTest/ZLibDecompressorTest.cpp"), | 
 Swift
 Swift