summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2016-12-08 08:55:19 (GMT)
committerEdwin Mons <edwin.mons@isode.com>2016-12-09 08:15:44 (GMT)
commitda7162b6e80ed6ce802bece3891fe85f30770c56 (patch)
tree11cffaa17e475a0854b0726bdb4d4f126632dbe9 /Swift/Controllers
parentc65a90e2a73814d09ad8c60adc4a259e90006db7 (diff)
downloadswift-da7162b6e80ed6ce802bece3891fe85f30770c56.zip
swift-da7162b6e80ed6ce802bece3891fe85f30770c56.tar.bz2
Fix issue with invites to MUC if a MUC PM for that room is open
Previously if you wanted to invite people to a MUC and had a PM window for a MUC occupant open at the same time, the InviteToMUCUIEvent would be handled by the PM window, by the ChatController of the PM window and not the MUCController of the MUC window. Test-Information: Verified that some scenarios work correctly: - Tested a drop to a MUC window while a MUC PM window is open to an occupant in the MUC. Previously this crashed due to ChatsManager::localMUCServiceJID_ being empty. - Test that impromptu MUC creation to a normal chat works. - Test that impromptu MUC creation to a MUC PM chat works. All unit and integration tests pass on macOS 10.12.1. Change-Id: Ib20de7e925e3503308211936ee47d4ba829d0394
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp4
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp6
-rw-r--r--Swift/Controllers/Chat/UserSearchController.cpp7
-rw-r--r--Swift/Controllers/UIEvents/InviteToMUCUIEvent.h8
-rw-r--r--Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h18
-rw-r--r--Swift/Controllers/UIInterfaces/UserSearchWindow.h1
6 files changed, 28 insertions, 16 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 41a34b9..cd8fa0c 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -270,71 +270,71 @@ void ChatController::handleBlockingStateChanged() {
} else {
if (blockedContactAlert_) {
chatWindow_->removeAlert(*blockedContactAlert_);
blockedContactAlert_.reset();
}
chatWindow_->setBlockingState(ChatWindow::IsUnblocked);
chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_));
chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_));
}
}
}
void ChatController::handleBlockUserRequest() {
if (isInMUC_) {
eventStream_->send(std::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Blocked, toJID_));
} else {
eventStream_->send(std::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Blocked, toJID_.toBare()));
}
}
void ChatController::handleUnblockUserRequest() {
if (isInMUC_) {
eventStream_->send(std::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Unblocked, toJID_));
} else {
eventStream_->send(std::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Unblocked, toJID_.toBare()));
}
}
void ChatController::handleInviteToChat(const std::vector<JID>& droppedJIDs) {
- std::shared_ptr<UIEvent> event(new RequestInviteToMUCUIEvent(toJID_.toBare(), droppedJIDs, RequestInviteToMUCUIEvent::Impromptu));
+ std::shared_ptr<UIEvent> event(new RequestInviteToMUCUIEvent(getToJID(), droppedJIDs, RequestInviteToMUCUIEvent::Impromptu));
eventStream_->send(event);
}
void ChatController::handleWindowClosed() {
onWindowClosed();
}
void ChatController::handleUIEvent(std::shared_ptr<UIEvent> event) {
std::shared_ptr<InviteToMUCUIEvent> inviteEvent = std::dynamic_pointer_cast<InviteToMUCUIEvent>(event);
- if (inviteEvent && inviteEvent->getRoom() == toJID_.toBare()) {
+ if (inviteEvent && inviteEvent->getOriginator() == getToJID()) {
onConvertToMUC(detachChatWindow(), inviteEvent->getInvites(), inviteEvent->getReason());
}
}
void ChatController::handleIncomingOwnMessage(std::shared_ptr<Message> message) {
if (!message->getBody().get_value_or("").empty()) {
postSendMessage(message->getBody().get_value_or(""), message);
handleStanzaAcked(message);
}
}
void ChatController::postSendMessage(const std::string& body, std::shared_ptr<Stanza> sentStanza) {
std::shared_ptr<Replace> replace = sentStanza->getPayload<Replace>();
if (replace) {
eraseIf(unackedStanzas_, PairSecondEquals<std::shared_ptr<Stanza>, std::string>(myLastMessageUIID_));
replaceMessage(chatMessageParser_->parseMessageBody(body, "", true), myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());
} else {
myLastMessageUIID_ = addMessage(chatMessageParser_->parseMessageBody(body, "", true), QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : std::shared_ptr<SecurityLabel>(), avatarManager_->getAvatarPath(selfJID_), boost::posix_time::microsec_clock::universal_time());
}
if (stanzaChannel_->getStreamManagementEnabled() && !myLastMessageUIID_.empty() ) {
chatWindow_->setAckState(myLastMessageUIID_, ChatWindow::Pending);
unackedStanzas_[sentStanza] = myLastMessageUIID_;
}
if (sentStanza->getPayload<DeliveryReceiptRequest>()) {
requestedReceipts_[sentStanza->getID()] = myLastMessageUIID_;
chatWindow_->setMessageReceiptState(myLastMessageUIID_, ChatWindow::ReceiptRequested);
}
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 349bf8a..ceed776 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -1,39 +1,40 @@
/*
* Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swift/Controllers/Chat/MUCController.h>
#include <algorithm>
+#include <memory>
#include <boost/bind.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swiften/Base/Log.h>
#include <Swiften/Base/format.h>
#include <Swiften/Base/Tristate.h>
#include <Swiften/Client/BlockList.h>
#include <Swiften/Client/ClientBlockListManager.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Disco/EntityCapsProvider.h>
#include <Swiften/Elements/Delay.h>
#include <Swiften/Elements/Thread.h>
#include <Swiften/MUC/MUC.h>
#include <Swiften/MUC/MUCBookmark.h>
#include <Swiften/MUC/MUCBookmarkManager.h>
#include <Swiften/Network/Timer.h>
#include <Swiften/Network/TimerFactory.h>
#include <Swiften/Roster/XMPPRoster.h>
#include <SwifTools/TabComplete.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
#include <Swift/Controllers/Highlighter.h>
#include <Swift/Controllers/Intl.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
@@ -966,67 +967,66 @@ void MUCController::handleOccupantRoleChangeFailed(ErrorPayload::ref error, cons
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Occupant role change failed: %1%.")) % errorMessage);
chatWindow_->addErrorMessage(chatMessageParser_->parseMessageBody(errorMessage));
}
void MUCController::configureAsImpromptuRoom(Form::ref form) {
muc_->configureRoom(buildImpromptuRoomConfiguration(form));
isImpromptuAlreadyConfigured_ = true;
onImpromptuConfigCompleted();
}
void MUCController::handleConfigurationFormReceived(Form::ref form) {
if (isImpromptu_) {
if (!isImpromptuAlreadyConfigured_) {
configureAsImpromptuRoom(form);
}
} else {
chatWindow_->showRoomConfigurationForm(form);
}
}
void MUCController::handleConfigurationCancelled() {
muc_->cancelConfigureRoom();
}
void MUCController::handleDestroyRoomRequest() {
muc_->destroyRoom();
}
void MUCController::handleInvitePersonToThisMUCRequest(const std::vector<JID>& jidsToInvite) {
RequestInviteToMUCUIEvent::ImpromptuMode mode = isImpromptu_ ? RequestInviteToMUCUIEvent::Impromptu : RequestInviteToMUCUIEvent::NotImpromptu;
- std::shared_ptr<UIEvent> event(new RequestInviteToMUCUIEvent(muc_->getJID(), jidsToInvite, mode));
- eventStream_->send(event);
+ eventStream_->send(std::make_shared<RequestInviteToMUCUIEvent>(getToJID(), jidsToInvite, mode));
}
void MUCController::handleUIEvent(std::shared_ptr<UIEvent> event) {
std::shared_ptr<InviteToMUCUIEvent> inviteEvent = std::dynamic_pointer_cast<InviteToMUCUIEvent>(event);
- if (inviteEvent && inviteEvent->getRoom() == muc_->getJID()) {
+ if (inviteEvent && inviteEvent->getOriginator() == muc_->getJID()) {
for (const auto& jid : inviteEvent->getInvites()) {
muc_->invitePerson(jid, inviteEvent->getReason(), isImpromptu_);
}
}
}
void MUCController::handleGetAffiliationsRequest() {
muc_->requestAffiliationList(MUCOccupant::Owner);
muc_->requestAffiliationList(MUCOccupant::Admin);
muc_->requestAffiliationList(MUCOccupant::Member);
muc_->requestAffiliationList(MUCOccupant::Outcast);
}
void MUCController::handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes) {
std::set<JID> addedJIDs;
for (const auto& change : changes) {
if (change.first != MUCOccupant::NoAffiliation) {
addedJIDs.insert(change.second);
}
}
for (const auto& change : changes) {
if (change.first != MUCOccupant::NoAffiliation || addedJIDs.find(change.second) == addedJIDs.end()) {
muc_->changeAffiliation(change.second, change.first);
}
}
}
void MUCController::handleUnblockUserRequest() {
eventStream_->send(std::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Unblocked, muc_->getJID()));
}
diff --git a/Swift/Controllers/Chat/UserSearchController.cpp b/Swift/Controllers/Chat/UserSearchController.cpp
index 91e0dea..91de670 100644
--- a/Swift/Controllers/Chat/UserSearchController.cpp
+++ b/Swift/Controllers/Chat/UserSearchController.cpp
@@ -54,92 +54,93 @@ UserSearchController::~UserSearchController() {
window_->onContactSuggestionsRequested.disconnect(boost::bind(&UserSearchController::handleContactSuggestionsRequested, this, _1));
window_->onJIDUpdateRequested.disconnect(boost::bind(&UserSearchController::handleJIDUpdateRequested, this, _1));
window_->onJIDAddRequested.disconnect(boost::bind(&UserSearchController::handleJIDAddRequested, this, _1));
window_->onJIDEditFieldChanged.disconnect(boost::bind(&UserSearchController::handleJIDEditingFinished, this, _1));
delete window_;
}
presenceOracle_->onPresenceChange.disconnect(boost::bind(&UserSearchController::handlePresenceChanged, this, _1));
avatarManager_->onAvatarChanged.disconnect(boost::bind(&UserSearchController::handleAvatarChanged, this, _1));
vcardManager_->onVCardChanged.disconnect(boost::bind(&UserSearchController::handleVCardChanged, this, _1, _2));
uiEventStream_->onUIEvent.disconnect(boost::bind(&UserSearchController::handleUIEvent, this, _1));
}
UserSearchWindow* UserSearchController::getUserSearchWindow() {
initializeUserWindow();
assert(window_);
return window_;
}
void UserSearchController::setCanInitiateImpromptuMUC(bool supportsImpromptu) {
if (!window_) {
initializeUserWindow();
}
if (window_) {
window_->setCanStartImpromptuChats(supportsImpromptu);
} // Else doesn't support search
}
void UserSearchController::handleUIEvent(std::shared_ptr<UIEvent> event) {
bool handle = false;
std::shared_ptr<RequestAddUserDialogUIEvent> addUserRequest = std::shared_ptr<RequestAddUserDialogUIEvent>();
- RequestInviteToMUCUIEvent::ref inviteToMUCRequest = RequestInviteToMUCUIEvent::ref();
+ auto inviteToMUCRequest = RequestInviteToMUCUIEvent::ref();
switch (type_) {
case AddContact:
if ((addUserRequest = std::dynamic_pointer_cast<RequestAddUserDialogUIEvent>(event))) {
handle = true;
}
break;
case StartChat:
if (std::dynamic_pointer_cast<RequestChatWithUserDialogUIEvent>(event)) {
handle = true;
}
break;
case InviteToChat:
if ((inviteToMUCRequest = std::dynamic_pointer_cast<RequestInviteToMUCUIEvent>(event))) {
handle = true;
}
break;
}
if (handle) {
initializeUserWindow();
window_->show();
window_->addSavedServices(savedDirectories_);
if (addUserRequest) {
const std::string& name = addUserRequest->getPredefinedName();
const JID& jid = addUserRequest->getPredefinedJID();
if (!name.empty() && jid.isValid()) {
window_->prepopulateJIDAndName(jid, name);
}
- } else if (inviteToMUCRequest) {
+ }
+ else if (inviteToMUCRequest) {
window_->setCanSupplyDescription(!inviteToMUCRequest->isImpromptu());
window_->setJIDs(inviteToMUCRequest->getInvites());
- window_->setRoomJID(inviteToMUCRequest->getRoom());
+ window_->setOriginator(inviteToMUCRequest->getOriginator());
}
return;
}
}
void UserSearchController::handleFormRequested(const JID& service) {
window_->setSearchError(false);
window_->setServerSupportsSearch(true);
//Abort a previous search if is active
endDiscoWalker();
delete discoWalker_;
discoWalker_ = new DiscoServiceWalker(service, iqRouter_);
discoWalker_->onServiceFound.connect(boost::bind(&UserSearchController::handleDiscoServiceFound, this, _1, _2));
discoWalker_->onWalkComplete.connect(boost::bind(&UserSearchController::handleDiscoWalkFinished, this));
discoWalker_->beginWalk();
}
void UserSearchController::endDiscoWalker() {
if (discoWalker_) {
discoWalker_->endWalk();
discoWalker_->onServiceFound.disconnect(boost::bind(&UserSearchController::handleDiscoServiceFound, this, _1, _2));
discoWalker_->onWalkComplete.disconnect(boost::bind(&UserSearchController::handleDiscoWalkFinished, this));
}
}
void UserSearchController::handleDiscoServiceFound(const JID& jid, std::shared_ptr<DiscoInfo> info) {
//bool isUserDirectory = false;
bool supports55 = false;
// TODO: Cleanup code
diff --git a/Swift/Controllers/UIEvents/InviteToMUCUIEvent.h b/Swift/Controllers/UIEvents/InviteToMUCUIEvent.h
index 414582d..e38eab8 100644
--- a/Swift/Controllers/UIEvents/InviteToMUCUIEvent.h
+++ b/Swift/Controllers/UIEvents/InviteToMUCUIEvent.h
@@ -1,47 +1,47 @@
/*
* Copyright (c) 2013 Tobias Markmann
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
/*
* Copyright (c) 2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#pragma once
#include <memory>
#include <vector>
#include <Swiften/JID/JID.h>
#include <Swift/Controllers/UIEvents/UIEvent.h>
namespace Swift {
class InviteToMUCUIEvent : public UIEvent {
public:
typedef std::shared_ptr<InviteToMUCUIEvent> ref;
- InviteToMUCUIEvent(const JID& room, const std::vector<JID>& JIDsToInvite, const std::string& reason) : room_(room), invite_(JIDsToInvite), reason_(reason) {
+ InviteToMUCUIEvent(const JID& originator, const std::vector<JID>& JIDsToInvite, const std::string& reason) : originator_(originator), invite_(JIDsToInvite), reason_(reason) {
}
- const JID& getRoom() const {
- return room_;
+ const JID& getOriginator() const {
+ return originator_;
}
const std::vector<JID> getInvites() const {
return invite_;
}
const std::string getReason() const {
return reason_;
}
private:
- JID room_;
+ JID originator_;
std::vector<JID> invite_;
std::string reason_;
};
}
diff --git a/Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h b/Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h
index dac499f..a8e4bb7 100644
--- a/Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h
+++ b/Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h
@@ -2,52 +2,62 @@
* Copyright (c) 2013 Tobias Markmann
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
/*
* Copyright (c) 2014-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#pragma once
#include <memory>
#include <vector>
#include <Swiften/JID/JID.h>
#include <Swift/Controllers/UIEvents/UIEvent.h>
namespace Swift {
class RequestInviteToMUCUIEvent : public UIEvent {
public:
typedef std::shared_ptr<RequestInviteToMUCUIEvent> ref;
enum ImpromptuMode {
Impromptu,
NotImpromptu
};
- RequestInviteToMUCUIEvent(const JID& room, const std::vector<JID>& JIDsToInvite, ImpromptuMode impromptu) : room_(room), invite_(JIDsToInvite) {
+ /**
+ * @brief RequestInviteToMUCUIEvent
+ * @param originator This can be a MUC JID if the user wants to invite
+ * people to an existing MUC, or a contact JID if this is the
+ * start of an impromptu group chat.
+ * @param JIDsToInvite This is a std::vector of JIDs which are prefilled
+ * in the invite dialog.
+ * @param impromptu This flag indicates whether it is a normal MUC invite
+ * or an impromptu MUC invite.
+ */
+ RequestInviteToMUCUIEvent(const JID& originator, const std::vector<JID>& JIDsToInvite, ImpromptuMode impromptu) : originator_(originator), invite_(JIDsToInvite) {
isImpromptu_ = impromptu == Impromptu;
}
- const JID& getRoom() const {
- return room_;
+ const JID& getOriginator() const {
+ return originator_;
}
const std::vector<JID> getInvites() const {
return invite_;
}
bool isImpromptu() const {
return isImpromptu_;
}
private:
- JID room_;
+ JID originator_;
std::vector<JID> invite_;
bool isImpromptu_;
};
}
diff --git a/Swift/Controllers/UIInterfaces/UserSearchWindow.h b/Swift/Controllers/UIInterfaces/UserSearchWindow.h
index be17dc0..279f4f3 100644
--- a/Swift/Controllers/UIInterfaces/UserSearchWindow.h
+++ b/Swift/Controllers/UIInterfaces/UserSearchWindow.h
@@ -8,50 +8,51 @@
#include <string>
#include <vector>
#include <boost/signals2.hpp>
#include <Swiften/JID/JID.h>
#include <Swift/Controllers/Chat/UserSearchController.h>
#include <Swift/Controllers/Contact.h>
namespace Swift {
class UserSearchWindow {
public:
enum Type {AddContact, ChatToContact, InviteToChat};
virtual ~UserSearchWindow() {}
virtual void clear() = 0;
virtual void setResults(const std::vector<UserSearchResult>& results) = 0;
virtual void setResultsForm(const Form::ref results) = 0;
virtual void addSavedServices(const std::vector<JID>& services) = 0;
virtual void setSelectedService(const JID& service) = 0;
virtual void setServerSupportsSearch(bool support) = 0;
virtual void setSearchError(bool support) = 0;
virtual void setSearchFields(std::shared_ptr<SearchPayload> fields) = 0;
virtual void setNameSuggestions(const std::vector<std::string>& suggestions) = 0;
virtual void prepopulateJIDAndName(const JID& jid, const std::string& name) = 0;
virtual void setContactSuggestions(const std::vector<Contact::ref>& suggestions) = 0;
virtual void setJIDs(const std::vector<JID>&) = 0;
+ virtual void setOriginator(const JID& originator) = 0;
virtual void setRoomJID(const JID& roomJID) = 0;
virtual std::string getReason() const = 0;
virtual std::vector<JID> getJIDs() const = 0;
virtual void setCanStartImpromptuChats(bool supportsImpromptu) = 0;
virtual void updateContacts(const std::vector<Contact::ref>& contacts) = 0;
virtual void addContacts(const std::vector<Contact::ref>& contacts) = 0;
virtual void setCanSupplyDescription(bool allowed) = 0;
virtual void setWarning(const boost::optional<std::string>& message) = 0;
virtual void show() = 0;
boost::signals2::signal<void (const JID&)> onFormRequested;
boost::signals2::signal<void (std::shared_ptr<SearchPayload>, const JID&)> onSearchRequested;
boost::signals2::signal<void (const JID&)> onNameSuggestionRequested;
boost::signals2::signal<void (const std::string&)> onContactSuggestionsRequested;
boost::signals2::signal<void (const std::vector<JID>&)> onJIDUpdateRequested;
boost::signals2::signal<void (const std::vector<JID>&)> onJIDAddRequested;
boost::signals2::signal<void (const JID&)> onJIDEditFieldChanged;
};
}