diff options
Diffstat (limited to 'Swift/Controllers/Chat/ChatControllerBase.cpp')
-rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp new file mode 100644 index 0000000..5f78795 --- /dev/null +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -0,0 +1,154 @@ +#include "Swift/Controllers/Chat/ChatControllerBase.h" + +#include <boost/bind.hpp> +#include <boost/shared_ptr.hpp> + +#include "Swiften/Client/StanzaChannel.h" +#include "Swiften/Base/foreach.h" +#include "Swift/Controllers/UIInterfaces/ChatWindow.h" +#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" +#include "Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h" +#include "Swiften/Avatars/AvatarManager.h" + +namespace Swift { + +ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager) { + chatWindow_ = chatWindowFactory_->createChatWindow(toJID); + chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); + chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1)); + setEnabled(stanzaChannel->isAvailable() && iqRouter->isAvailable()); +} + +ChatControllerBase::~ChatControllerBase() { + delete chatWindow_; +} + +void ChatControllerBase::setEnabled(bool enabled) { + chatWindow_->setInputEnabled(enabled); +} + +void ChatControllerBase::setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info) { + if (iqRouter_->isAvailable() && info->hasFeature(DiscoInfo::SecurityLabels)) { + chatWindow_->setSecurityLabelsEnabled(true); + chatWindow_->setSecurityLabelsError(); + boost::shared_ptr<GetSecurityLabelsCatalogRequest> request(new GetSecurityLabelsCatalogRequest(JID(toJID_.toBare()), iqRouter_)); + request->onResponse.connect(boost::bind(&ChatControllerBase::handleSecurityLabelsCatalogResponse, this, _1, _2)); + request->send(); + labelsEnabled_ = true; + } else { + chatWindow_->setSecurityLabelsEnabled(false); + labelsEnabled_ = false; + } +} + +void ChatControllerBase::handleAllMessagesRead() { + foreach (boost::shared_ptr<MessageEvent> messageEvent, unreadMessages_) { + messageEvent->read(); + } + unreadMessages_.clear(); + chatWindow_->setUnreadMessageCount(0); +} + +void ChatControllerBase::handleSendMessageRequest(const String &body) { + if (!stanzaChannel_->isAvailable() || body.isEmpty()) { + return; + } + boost::shared_ptr<Message> message(new Message()); + message->setTo(toJID_); + message->setType(Swift::Message::Chat); + message->setBody(body); + boost::optional<SecurityLabel> label; + if (labelsEnabled_) { + message->addPayload(boost::shared_ptr<SecurityLabel>(new SecurityLabel(chatWindow_->getSelectedSecurityLabel()))); + label = boost::optional<SecurityLabel>(chatWindow_->getSelectedSecurityLabel()); + } + preSendMessageRequest(message); + stanzaChannel_->sendMessage(message); + postSendMessage(message->getBody()); +} + +void ChatControllerBase::handleSecurityLabelsCatalogResponse(boost::shared_ptr<SecurityLabelsCatalog> catalog, const boost::optional<ErrorPayload>& error) { + if (!error) { + if (catalog->getLabels().size() == 0) { + chatWindow_->setSecurityLabelsEnabled(false); + labelsEnabled_ = false; + } else { + chatWindow_->setAvailableSecurityLabels(catalog->getLabels()); + chatWindow_->setSecurityLabelsEnabled(true); + } + } else { + chatWindow_->setSecurityLabelsError(); + } +} + +void ChatControllerBase::showChatWindow() { + chatWindow_->show(); +} + +void ChatControllerBase::activateChatWindow() { + chatWindow_->activate(); +} + +void ChatControllerBase::addMessage(const String& message, const String& senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath) { + if (message.beginsWith("/me ")) { + chatWindow_->addMessage(message, senderName, senderIsSelf, label, avatarPath); + } else { + chatWindow_->addAction(message, senderName, senderIsSelf, label, avatarPath); + } +} + +void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) { + unreadMessages_.push_back(messageEvent); + chatWindow_->setUnreadMessageCount(unreadMessages_.size()); + + boost::shared_ptr<Message> message = messageEvent->getStanza(); + preHandleIncomingMessage(message); + String body = message->getBody(); + if (message->isError()) { + String errorMessage = getErrorMessage(message->getPayload<ErrorPayload>()); + chatWindow_->addErrorMessage(errorMessage); + } + else { + showChatWindow(); + boost::shared_ptr<SecurityLabel> label = message->getPayload<SecurityLabel>(); + boost::optional<SecurityLabel> maybeLabel = label ? boost::optional<SecurityLabel>(*label) : boost::optional<SecurityLabel>(); + JID from = message->getFrom(); + addMessage(body, senderDisplayNameFromMessage(from), isIncomingMessageFromMe(message), maybeLabel, String(avatarManager_->getAvatarPath(from).string())); + } +} + +String ChatControllerBase::getErrorMessage(boost::shared_ptr<ErrorPayload> error) { + String defaultMessage = "Error sending message"; + if (!error->getText().isEmpty()) { + return error->getText(); + } + else { + switch (error->getCondition()) { + case ErrorPayload::BadRequest: return defaultMessage; break; + case ErrorPayload::Conflict: return defaultMessage; break; + case ErrorPayload::FeatureNotImplemented: return defaultMessage; break; + case ErrorPayload::Forbidden: return defaultMessage; break; + case ErrorPayload::Gone: return "Recipient can no longer be contacted"; break; + case ErrorPayload::InternalServerError: return "Internal server error"; break; + case ErrorPayload::ItemNotFound: return defaultMessage; break; + case ErrorPayload::JIDMalformed: return defaultMessage; break; + case ErrorPayload::NotAcceptable: return "Message was rejected"; break; + case ErrorPayload::NotAllowed: return defaultMessage; break; + case ErrorPayload::NotAuthorized: return defaultMessage; break; + case ErrorPayload::PaymentRequired: return defaultMessage; break; + case ErrorPayload::RecipientUnavailable: return "Recipient is unavailable."; break; + case ErrorPayload::Redirect: return defaultMessage; break; + case ErrorPayload::RegistrationRequired: return defaultMessage; break; + case ErrorPayload::RemoteServerNotFound: return "Recipient's server not found."; break; + case ErrorPayload::RemoteServerTimeout: return defaultMessage; break; + case ErrorPayload::ResourceConstraint: return defaultMessage; break; + case ErrorPayload::ServiceUnavailable: return defaultMessage; break; + case ErrorPayload::SubscriptionRequired: return defaultMessage; break; + case ErrorPayload::UndefinedCondition: return defaultMessage; break; + case ErrorPayload::UnexpectedRequest: return defaultMessage; break; + } + } + return defaultMessage; +} + +} |