diff options
author | Kevin Smith <git@kismith.co.uk> | 2010-09-03 15:07:47 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2010-09-03 19:06:29 (GMT) |
commit | a0185934b0c929622c5526b84235b86cd44aad1d (patch) | |
tree | 2b377a5e8754c35e1a40fe7405dd75804e66fd73 /Swift/Controllers | |
parent | fde15d66a75334b23ca8bbd56b44e33893c813c4 (diff) | |
download | swift-a0185934b0c929622c5526b84235b86cd44aad1d.zip swift-a0185934b0c929622c5526b84235b86cd44aad1d.tar.bz2 |
XEP-0198 Ack support in the UI
Resolves: #7
Diffstat (limited to 'Swift/Controllers')
-rw-r--r-- | Swift/Controllers/Chat/ChatController.cpp | 30 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatController.h | 5 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 8 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.h | 8 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 2 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.h | 2 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/ChatWindow.h | 12 | ||||
-rw-r--r-- | Swift/Controllers/UnitTest/MockChatWindow.h | 5 |
8 files changed, 56 insertions, 16 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 52288c2..9154b9a 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -12,6 +12,7 @@ #include "Swiften/Chat/ChatStateNotifier.h" #include "Swiften/Chat/ChatStateMessageSender.h" #include "Swiften/Chat/ChatStateTracker.h" +#include "Swiften/Client/StanzaChannel.h" #include "Swift/Controllers/UIInterfaces/ChatWindow.h" #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" #include "Swift/Controllers/NickResolver.h" @@ -32,6 +33,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ nickResolver_ = nickResolver; presenceOracle_->onPresenceChange.connect(boost::bind(&ChatController::handlePresenceChange, this, _1, _2)); chatStateTracker_->onChatStateChange.connect(boost::bind(&ChatWindow::setContactChatState, chatWindow_, _1)); + stanzaChannel_->onStanzaAcked.connect(boost::bind(&ChatController::handleStanzaAcked, this, _1)); String nick = nickResolver_->jidToNick(toJID_); chatWindow_->setName(nick); String startMessage("Starting chat with " + nick); @@ -43,6 +45,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ chatWindow_->addSystemMessage(startMessage); chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_)); chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_)); + } ChatController::~ChatController() { @@ -80,12 +83,35 @@ void ChatController::preSendMessageRequest(boost::shared_ptr<Message> message) { } } -void ChatController::postSendMessage(const String& body) { - addMessage(body, "me", true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel() : boost::optional<SecurityLabel>(), String(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time()); +void ChatController::postSendMessage(const String& body, boost::shared_ptr<Stanza> sentStanza) { + String id = addMessage(body, "me", true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel() : boost::optional<SecurityLabel>(), String(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time()); + if (stanzaChannel_->getStreamManagementEnabled()) { + chatWindow_->setAckState(id, ChatWindow::Pending); + unackedStanzas_[sentStanza] = id; + } lastWasPresence_ = false; chatStateNotifier_->userSentMessage(); } +void ChatController::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { + String id = unackedStanzas_[stanza]; + if (id != "") { + chatWindow_->setAckState(id, ChatWindow::Received); + } + unackedStanzas_.erase(unackedStanzas_.find(stanza)); +} + +void ChatController::setEnabled(bool enabled) { + if (!enabled) { + std::map<boost::shared_ptr<Stanza>, String>::iterator it = unackedStanzas_.begin(); + for ( ; it != unackedStanzas_.end(); it++) { + chatWindow_->setAckState(it->second, ChatWindow::Failed); + } + unackedStanzas_.clear(); + } + ChatControllerBase::setEnabled(enabled); +} + String ChatController::senderDisplayNameFromMessage(const JID& from) { return nickResolver_->jidToNick(from); } diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index d833094..971fca9 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -20,16 +20,18 @@ namespace Swift { ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController); virtual ~ChatController(); virtual void setToJID(const JID& jid); + virtual void setEnabled(bool enabled); private: void handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> previousPresence); String getStatusChangeString(boost::shared_ptr<Presence> presence); bool isIncomingMessageFromMe(boost::shared_ptr<Message> message); - void postSendMessage(const String &body); + void postSendMessage(const String &body, boost::shared_ptr<Stanza> sentStanza); void preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent); void preSendMessageRequest(boost::shared_ptr<Message>); String senderDisplayNameFromMessage(const JID& from); virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const; + void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); private: NickResolver* nickResolver_; @@ -39,6 +41,7 @@ namespace Swift { ChatStateTracker* chatStateTracker_; bool isInMUC_; bool lastWasPresence_; + std::map<boost::shared_ptr<Stanza>, String> unackedStanzas_; }; } #endif diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index e38d12d..b7dd1c0 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -79,7 +79,7 @@ void ChatControllerBase::handleSendMessageRequest(const String &body) { message->addPayload(boost::shared_ptr<Delay>(new Delay(now, selfJID_))); } stanzaChannel_->sendMessage(message); - postSendMessage(message->getBody()); + postSendMessage(message->getBody(), boost::dynamic_pointer_cast<Stanza>(message)); } void ChatControllerBase::handleSecurityLabelsCatalogResponse(boost::shared_ptr<SecurityLabelsCatalog> catalog, const boost::optional<ErrorPayload>& error) { @@ -106,11 +106,11 @@ void ChatControllerBase::activateChatWindow() { chatWindow_->activate(); } -void ChatControllerBase::addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time) { +String ChatControllerBase::addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time) { if (message.beginsWith("/me ")) { - chatWindow_->addAction(message.getSplittedAtFirst(' ').second, senderName, senderIsSelf, label, avatarPath, time); + return chatWindow_->addAction(message.getSplittedAtFirst(' ').second, senderName, senderIsSelf, label, avatarPath, time); } else { - chatWindow_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time); + return chatWindow_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time); } } diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index 61d0ab7..2466690 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -15,6 +15,7 @@ #include <boost/optional.hpp> #include <boost/date_time/posix_time/posix_time.hpp> +#include "Swiften/Elements/Stanza.h" #include "Swiften/Base/String.h" #include "Swiften/Elements/DiscoInfo.h" #include "Swiften/Events/MessageEvent.h" @@ -40,13 +41,16 @@ namespace Swift { void activateChatWindow(); void setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info); 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, const boost::posix_time::ptime& time); + String addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time); virtual void setEnabled(bool enabled); 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, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController); - virtual void postSendMessage(const String&) {}; + /** + * Pass the Message appended, and the stanza used to send it. + */ + virtual void postSendMessage(const String&, boost::shared_ptr<Stanza>) {}; virtual String senderDisplayNameFromMessage(const JID& from) = 0; virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message>) = 0; virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {}; diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index dfe75d6..acc5e1d 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -8,8 +8,6 @@ #include <boost/bind.hpp> -#include "Swiften/Client/Client.h" - #include "Swift/Controllers/Chat/ChatController.h" #include "Swift/Controllers/EventController.h" #include "Swift/Controllers/Chat/MUCController.h" diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index d7a6275..3efd507 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -61,7 +61,7 @@ namespace Swift { EventController* eventController_; JID jid_; StanzaChannel* stanzaChannel_; - IQRouter* iqRouter_;; + IQRouter* iqRouter_; ChatWindowFactory* chatWindowFactory_; NickResolver* nickResolver_; PresenceOracle* presenceOracle_; diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 4d00dca..1ee632c 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -25,11 +25,18 @@ namespace Swift { class ChatWindow { public: + enum AckState {Pending, Received, Failed}; ChatWindow() {} virtual ~ChatWindow() {}; - virtual void addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time) = 0; - virtual void addAction(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time) = 0; + /** Add message to window. + * @return id of added message (for acks). + */ + virtual String addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time) = 0; + /** Adds action to window. + * @return id of added message (for acks); + */ + virtual String addAction(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time) = 0; virtual void addSystemMessage(const String& message) = 0; virtual void addPresenceMessage(const String& message) = 0; virtual void addErrorMessage(const String& message) = 0; @@ -49,6 +56,7 @@ namespace Swift { virtual void setRosterModel(Roster* model) = 0; virtual void setTabComplete(TabComplete* completer) = 0; virtual void replaceLastMessage(const String& message) = 0; + virtual void setAckState(const String& id, AckState state) = 0; boost::signal<void ()> onClosed; boost::signal<void ()> onAllMessagesRead; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index 822a128..4e7a117 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -14,8 +14,8 @@ namespace Swift { MockChatWindow() {}; virtual ~MockChatWindow(); - virtual void addMessage(const String& message, const String& /*senderName*/, bool /*senderIsSelf*/, const boost::optional<SecurityLabel>& /*label*/, const String& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message;}; - virtual void addAction(const String& message, const String& /*senderName*/, bool /*senderIsSelf*/, const boost::optional<SecurityLabel>& /*label*/, const String& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message;}; + virtual String addMessage(const String& message, const String& /*senderName*/, bool /*senderIsSelf*/, const boost::optional<SecurityLabel>& /*label*/, const String& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message; return "";}; + virtual String addAction(const String& message, const String& /*senderName*/, bool /*senderIsSelf*/, const boost::optional<SecurityLabel>& /*label*/, const String& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message; return "";}; virtual void addSystemMessage(const String& /*message*/) {}; virtual void addErrorMessage(const String& /*message*/) {}; virtual void addPresenceMessage(const String& /*message*/) {}; @@ -34,6 +34,7 @@ namespace Swift { virtual void setRosterModel(Roster* /*roster*/) {}; virtual void setTabComplete(TabComplete*) {}; virtual void replaceLastMessage(const Swift::String&) {}; + void setAckState(const String& /*id*/, AckState /*state*/) {}; boost::signal<void ()> onClosed; boost::signal<void ()> onAllMessagesRead; |