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"), |