summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2010-02-16 09:05:37 (GMT)
committerKevin Smith <git@kismith.co.uk>2010-02-17 08:05:08 (GMT)
commit5a334fd9b676564a8915baad312d92bd86358eec (patch)
treeaaecbbccd9cddcb843c126b8c022f1d1e667efde /Swift/Controllers
parent231c2cb6d00061e70860626467107f4c63f359a0 (diff)
downloadswift-5a334fd9b676564a8915baad312d92bd86358eec.zip
swift-5a334fd9b676564a8915baad312d92bd86358eec.tar.bz2
Preliminary Chat State Notifications support.
Only covers Active and Composing (Which is very possibly all we care about).
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp24
-rw-r--r--Swift/Controllers/Chat/ChatController.h8
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp7
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h2
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp6
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h4
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h1
7 files changed, 47 insertions, 5 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index e4031f2..8d63d99 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -3,6 +3,9 @@
#include <boost/bind.hpp>
#include "Swiften/Avatars/AvatarManager.h"
+#include "Swiften/Chat/ChatStateNotifier.h"
+#include "Swiften/Chat/ChatStateMessageSender.h"
+#include "Swiften/Chat/ChatStateTracker.h"
#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
#include "Swift/Controllers/NickResolver.h"
@@ -14,9 +17,20 @@ namespace Swift {
*/
ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager)
: ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager) {
+ chatStateNotifier_ = new ChatStateNotifier();
+ chatStateMessageSender_ = new ChatStateMessageSender(chatStateNotifier_, stanzaChannel, contact);
+ chatStateTracker_ = new ChatStateTracker();
nickResolver_ = nickResolver;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatController::handlePresenceChange, this, _1, _2));
+ chatStateTracker_->onChatStateChange.connect(boost::bind(&ChatWindow::setContactChatState, chatWindow_, _1));
chatWindow_->setName(nickResolver_->jidToNick(toJID_));
+ chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_));
+ chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_));
+}
+
+void ChatController::setToJID(const JID& jid) {
+ chatStateMessageSender_->setContact(jid);
+ ChatControllerBase::setToJID(jid);
}
bool ChatController::isIncomingMessageFromMe(boost::shared_ptr<Message>) {
@@ -30,10 +44,19 @@ void ChatController::preHandleIncomingMessage(boost::shared_ptr<Message> message
toJID_ = from;
}
}
+ chatStateNotifier_->receivedMessageFromContact(message->getPayload<ChatState>());
+ chatStateTracker_->handleMessageReceived(message);
+}
+
+void ChatController::preSendMessageRequest(boost::shared_ptr<Message> message) {
+ if (chatStateNotifier_->contactShouldReceiveStates()) {
+ message->addPayload(boost::shared_ptr<Payload>(new ChatState(ChatState::Active)));
+ }
}
void ChatController::postSendMessage(const String& body) {
addMessage(body, "me", true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel() : boost::optional<SecurityLabel>(), String(avatarManager_->getAvatarPath(selfJID_).string()));
+ chatStateNotifier_->userSentMessage();
}
String ChatController::senderDisplayNameFromMessage(const JID& from) {
@@ -62,6 +85,7 @@ void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresenc
if (!(toJID_.isBare() && newPresence->getFrom().equals(toJID_, JID::WithoutResource)) && newPresence->getFrom() != toJID_) {
return;
}
+ chatStateTracker_->handlePresenceChange(newPresence, previousPresence);
String newStatusChangeString = getStatusChangeString(newPresence);
if (!previousPresence || newStatusChangeString != getStatusChangeString(previousPresence)) {
chatWindow_->addSystemMessage(newStatusChangeString);
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 58ea797..f2963fd 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -5,10 +5,14 @@
namespace Swift {
class AvatarManager;
+ class ChatStateNotifier;
+ class ChatStateMessageSender;
+ class ChatStateTracker;
class NickResolver;
class ChatController : public ChatControllerBase {
public:
ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager*);
+ virtual void setToJID(const JID& jid);
private:
void handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> previousPresence);
@@ -16,11 +20,15 @@ namespace Swift {
bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
void postSendMessage(const String &body);
void preHandleIncomingMessage(boost::shared_ptr<Message> message);
+ void preSendMessageRequest(boost::shared_ptr<Message>);
String senderDisplayNameFromMessage(const JID& from);
private:
NickResolver* nickResolver_;
JID contact_;
+ ChatStateNotifier* chatStateNotifier_;
+ ChatStateMessageSender* chatStateMessageSender_;
+ ChatStateTracker* chatStateTracker_;
};
}
#endif
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 5f78795..6fe50d3 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -98,7 +98,9 @@ void ChatControllerBase::addMessage(const String& message, const String& senderN
}
void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
- unreadMessages_.push_back(messageEvent);
+ if (messageEvent->isReadable()) {
+ unreadMessages_.push_back(messageEvent);
+ }
chatWindow_->setUnreadMessageCount(unreadMessages_.size());
boost::shared_ptr<Message> message = messageEvent->getStanza();
@@ -109,6 +111,9 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
chatWindow_->addErrorMessage(errorMessage);
}
else {
+ if (!messageEvent->isReadable()) {
+ return;
+ }
showChatWindow();
boost::shared_ptr<SecurityLabel> label = message->getPayload<SecurityLabel>();
boost::optional<SecurityLabel> maybeLabel = label ? boost::optional<SecurityLabel>(*label) : boost::optional<SecurityLabel>();
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index abf0116..e0d6ac5 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -32,7 +32,7 @@ namespace Swift {
void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);
void addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath);
void setEnabled(bool enabled);
- void setToJID(const JID& jid) {toJID_ = jid;};
+ virtual void setToJID(const JID& jid) {toJID_ = jid;};
protected:
ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager);
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 0efd3e1..9a72f1f 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -133,9 +133,9 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const String &nick) {
void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) {
JID jid = message->getFrom();
boost::shared_ptr<MessageEvent> event(new MessageEvent(message));
- if (!event->isReadable()) {
- return;
- }
+ //if (!event->isReadable()) {
+ // return;
+ //}
// Try to deliver it to a MUC
if (message->getType() == Message::Groupchat || message->getType() == Message::Error) {
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 59c3152..5b38ba2 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -8,6 +8,7 @@
#include "Swiften/Base/String.h"
#include "Swiften/Elements/SecurityLabel.h"
+#include "Swiften/Elements/ChatState.h"
namespace Swift {
class AvatarManager;
@@ -23,6 +24,7 @@ namespace Swift {
virtual void addSystemMessage(const String& message) = 0;
virtual void addErrorMessage(const String& message) = 0;
+ virtual void setContactChatState(ChatState::ChatStateType state) = 0;
virtual void setName(const String& name) = 0;
virtual void show() = 0;
virtual void activate() = 0;
@@ -38,6 +40,8 @@ namespace Swift {
boost::signal<void ()> onClosed;
boost::signal<void ()> onAllMessagesRead;
boost::signal<void (const String&)> onSendMessageRequest;
+ boost::signal<void ()> onUserTyping;
+ boost::signal<void ()> onUserCancelsTyping;
};
}
#endif
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index dc744cd..b487f50 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -13,6 +13,7 @@ namespace Swift {
virtual void addSystemMessage(const String& /*message*/) {};
virtual void addErrorMessage(const String& /*message*/) {};
+ virtual void setContactChatState(ChatState::ChatStateType /*state*/) {};
virtual void setName(const String& name) {name_ = name;};
virtual void show() {};
virtual void activate() {};