summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers/Chat/ChatControllerBase.cpp')
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp69
1 files changed, 61 insertions, 8 deletions
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 19bbf8d..3805084 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2010-2017 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <map>
#include <memory>
#include <sstream>
@@ -14,59 +14,64 @@
#include <boost/bind.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swiften/Base/Path.h>
#include <Swiften/Base/format.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Disco/EntityCapsProvider.h>
#include <Swiften/Elements/Delay.h>
+#include <Swiften/Elements/DeliveryReceipt.h>
+#include <Swiften/Elements/DeliveryReceiptRequest.h>
#include <Swiften/Elements/MUCInvitationPayload.h>
#include <Swiften/Elements/MUCUserPayload.h>
#include <Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h>
#include <Swift/Controllers/Chat/AutoAcceptMUCInviteDecider.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
#include <Swift/Controllers/Highlighting/HighlightManager.h>
#include <Swift/Controllers/Highlighting/Highlighter.h>
#include <Swift/Controllers/Intl.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
#include <Swift/Controllers/XMPPEvents/MUCInviteEvent.h>
namespace Swift {
-ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry), chatMessageParser_(chatMessageParser), autoAcceptMUCInviteDecider_(autoAcceptMUCInviteDecider), eventStream_(eventStream) {
+ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings, Chattables& chattables) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry), chatMessageParser_(chatMessageParser), autoAcceptMUCInviteDecider_(autoAcceptMUCInviteDecider), eventStream_(eventStream), roomSecurityMarking_(""), previousMessageSecurityMarking_(""), settings_(settings), chattables_(chattables) {
chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);
chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2));
chatWindow_->onContinuationsBroken.connect(boost::bind(&ChatControllerBase::handleContinuationsBroken, this));
+ scopedConnectionResendMessage_ = chatWindow_->onResendMessageRequest.connect(boost::bind(&ChatControllerBase::handleResendMessageRequest, this, _1));
entityCapsProvider_->onCapsChanged.connect(boost::bind(&ChatControllerBase::handleCapsChanged, this, _1));
highlighter_ = highlightManager->createHighlighter(nickResolver);
ChatControllerBase::setOnline(stanzaChannel->isAvailable() && iqRouter->isAvailable());
}
ChatControllerBase::~ChatControllerBase() {
delete highlighter_;
delete chatWindow_;
}
void ChatControllerBase::handleContinuationsBroken() {
cancelReplaces();
}
ChatWindow* ChatControllerBase::detachChatWindow() {
chatWindow_->onContinuationsBroken.disconnect(boost::bind(&ChatControllerBase::handleContinuationsBroken, this));
chatWindow_->onSendMessageRequest.disconnect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2));
chatWindow_->onAllMessagesRead.disconnect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
+ scopedConnectionResendMessage_.disconnect();
ChatWindow* chatWindow = chatWindow_;
chatWindow_ = nullptr;
return chatWindow;
}
void ChatControllerBase::handleCapsChanged(const JID& jid) {
if (jid.compare(toJID_, JID::WithoutResource) == 0) {
handleBareJIDCapsChanged(jid);
}
@@ -107,20 +112,20 @@ void ChatControllerBase::handleAllMessagesRead() {
targetedUnreadMessages_.clear();
for (std::shared_ptr<StanzaEvent> stanzaEvent : unreadMessages_) {
stanzaEvent->conclude();
}
unreadMessages_.clear();
updateMessageCount();
}
}
-int ChatControllerBase::getUnreadCount() {
- return boost::numeric_cast<int>(targetedUnreadMessages_.size());
+size_t ChatControllerBase::getUnreadCount() {
+ return targetedUnreadMessages_.size();
}
void ChatControllerBase::handleSendMessageRequest(const std::string &body, bool isCorrectionMessage) {
if (!stanzaChannel_->isAvailable() || body.empty()) {
return;
}
std::shared_ptr<Message> message(new Message());
message->setTo(toJID_);
message->setType(Swift::Message::Chat);
@@ -182,28 +187,56 @@ bool ChatControllerBase::hasOpenWindow() const {
}
ChatWindow::ChatMessage ChatControllerBase::buildChatWindowChatMessage(const std::string& message, const std::string& senderName, bool senderIsSelf) {
ChatWindow::ChatMessage chatMessage;
chatMessage = chatMessageParser_->parseMessageBody(message, senderName, senderIsSelf);
return chatMessage;
}
void ChatControllerBase::updateMessageCount() {
- chatWindow_->setUnreadMessageCount(boost::numeric_cast<int>(unreadMessages_.size()));
+ auto baseJID = getBaseJID();
+ auto state = chattables_.getState(baseJID);
+ state.unreadCount = unreadMessages_.size();
+ chatWindow_->setUnreadMessageCount(state.unreadCount);
+ chattables_.setState(baseJID, state);
+#ifndef NOT_YET
onUnreadCountChanged();
+#endif
}
std::string ChatControllerBase::addMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& senderName, bool senderIsSelf, const std::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time) {
+ auto displayedLabel = label;
+
+ if (settings_->getSetting(SettingConstants::MUC_MARKING_ELISION)) {
+ if (roomSecurityMarking_ != "") {
+
+ if (label && label->getDisplayMarking() == roomSecurityMarking_) {
+ if (label->getDisplayMarking() == previousMessageSecurityMarking_) {
+ displayedLabel = std::make_shared<SecurityLabel>();
+ }
+ previousMessageSecurityMarking_ = label->getDisplayMarking();
+ }
+ else if (!label || label->getDisplayMarking().empty()) {
+ displayedLabel = std::make_shared<SecurityLabel>();
+ displayedLabel->setDisplayMarking("Unmarked");
+ previousMessageSecurityMarking_ = "Unmarked";
+ }
+ else {
+ previousMessageSecurityMarking_ = displayedLabel->getDisplayMarking();
+ }
+ }
+ }
+
if (chatMessage.isMeCommand()) {
- return chatWindow_->addAction(chatMessage, senderName, senderIsSelf, label, pathToString(avatarPath), time);
+ return chatWindow_->addAction(chatMessage, senderName, senderIsSelf, displayedLabel, pathToString(avatarPath), time);
}
else {
- return chatWindow_->addMessage(chatMessage, senderName, senderIsSelf, label, pathToString(avatarPath), time);
+ return chatWindow_->addMessage(chatMessage, senderName, senderIsSelf, displayedLabel, pathToString(avatarPath), time);
}
}
void ChatControllerBase::replaceMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& id, const boost::posix_time::ptime& time) {
if (chatMessage.isMeCommand()) {
chatWindow_->replaceWithAction(chatMessage, id, time);
}
else {
chatWindow_->replaceMessage(chatMessage, id, time);
@@ -281,19 +314,21 @@ void ChatControllerBase::handleIncomingMessage(std::shared_ptr<MessageEvent> mes
bool senderIsSelf = isIncomingMessageFromMe(message);
chatMessage = buildChatWindowChatMessage(body, senderHighlightNameFromMessage(from), senderIsSelf);
if (replace) {
handleIncomingReplaceMessage(from, chatMessage, message->getID(), replace->getID(), senderIsSelf, label, timeStamp);
}
else {
addMessageHandleIncomingMessage(from, chatMessage, message->getID(), senderIsSelf, label, timeStamp);
}
+#ifdef SWIFT_EXPERIMENTAL_HISTORY
logMessage(body, from, selfJID_, timeStamp, true);
+#endif
}
chatWindow_->show();
updateMessageCount();
postHandleIncomingMessage(messageEvent, chatMessage);
}
std::string ChatControllerBase::getErrorMessage(std::shared_ptr<ErrorPayload> error) {
std::string defaultMessage = QT_TRANSLATE_NOOP("", "Error sending message");
if (!error->getText().empty()) {
@@ -336,19 +371,19 @@ void ChatControllerBase::handleGeneralMUCInvitation(MUCInviteEvent::ref event) {
chatWindow_->addMUCInvitation(senderDisplayNameFromMessage(event->getInviter()), event->getRoomJID(), event->getReason(), event->getPassword(), event->getDirect(), event->getImpromptu());
eventController_->handleIncomingEvent(event);
lastWasPresence_ = false;
}
void ChatControllerBase::handleMUCInvitation(Message::ref message) {
MUCInvitationPayload::ref invite = message->getPayload<MUCInvitationPayload>();
if (autoAcceptMUCInviteDecider_->isAutoAcceptedInvite(message->getFrom(), invite)) {
- eventStream_->send(std::make_shared<JoinMUCUIEvent>(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, false, true));
+ eventStream_->send(std::make_shared<JoinMUCUIEvent>(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, true));
} else {
MUCInviteEvent::ref inviteEvent = std::make_shared<MUCInviteEvent>(toJID_, invite->getJID(), invite->getReason(), invite->getPassword(), true, invite->getIsImpromptu());
handleGeneralMUCInvitation(inviteEvent);
}
}
void ChatControllerBase::handleMediatedMUCInvitation(Message::ref message) {
MUCUserPayload::Invite invite = *message->getPayload<MUCUserPayload>()->getInvite();
JID from = message->getFrom();
@@ -359,10 +394,28 @@ void ChatControllerBase::handleMediatedMUCInvitation(Message::ref message) {
std::string password;
if (message->getPayload<MUCUserPayload>()->getPassword()) {
password = *message->getPayload<MUCUserPayload>()->getPassword();
}
MUCInviteEvent::ref inviteEvent = std::make_shared<MUCInviteEvent>(invite.from, from, reason, password, false, false);
handleGeneralMUCInvitation(inviteEvent);
}
+void ChatControllerBase::handleResendMessageRequest(const std::string& id) {
+ if (failedStanzas_.find(id) != failedStanzas_.end()) {
+ if (auto resendMsg = std::dynamic_pointer_cast<Message>(failedStanzas_[id])) {
+ stanzaChannel_->sendMessage(resendMsg);
+ if (stanzaChannel_->getStreamManagementEnabled()) {
+ chatWindow_->setAckState(id, ChatWindow::Pending);
+ unackedStanzas_[failedStanzas_[id]] = id;
+ }
+ if (resendMsg->getPayload<DeliveryReceiptRequest>()) {
+ requestedReceipts_[resendMsg->getID()] = id;
+ chatWindow_->setMessageReceiptState(id, ChatWindow::ReceiptRequested);
+ }
+ lastWasPresence_ = false;
+ failedStanzas_.erase(id);
+ }
+ }
+}
+
}