From da7162b6e80ed6ce802bece3891fe85f30770c56 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Thu, 8 Dec 2016 09:55:19 +0100
Subject: 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

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
@@ -297,7 +297,7 @@ void ChatController::handleUnblockUserRequest() {
 }
 
 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);
 }
 
@@ -307,7 +307,7 @@ void ChatController::handleWindowClosed() {
 
 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());
     }
 }
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
@@ -7,6 +7,7 @@
 #include <Swift/Controllers/Chat/MUCController.h>
 
 #include <algorithm>
+#include <memory>
 
 #include <boost/bind.hpp>
 #include <boost/regex.hpp>
@@ -993,13 +994,12 @@ void MUCController::handleDestroyRoomRequest() {
 
 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_);
         }
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
@@ -81,7 +81,7 @@ void UserSearchController::setCanInitiateImpromptuMUC(bool supportsImpromptu) {
 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))) {
@@ -109,10 +109,11 @@ void UserSearchController::handleUIEvent(std::shared_ptr<UIEvent> event) {
             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;
     }
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
@@ -24,11 +24,11 @@ namespace Swift {
         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 {
@@ -40,7 +40,7 @@ namespace Swift {
             }
 
         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
@@ -29,12 +29,22 @@ namespace Swift {
                 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 {
@@ -46,7 +56,7 @@ namespace Swift {
             }
 
         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
@@ -35,6 +35,7 @@ namespace Swift {
             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;
diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp
index e00582c..cf62540 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp
+++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp
@@ -145,13 +145,13 @@ void QtUserSearchWindow::handleAccepted() {
                 jids.push_back(contact->jid);
             }
 
-            eventStream_->send(std::make_shared<CreateImpromptuMUCUIEvent>(jids, JID(), Q2PSTRING(firstMultiJIDPage_->reason_->text())));
+            eventStream_->send(std::make_shared<CreateImpromptuMUCUIEvent>(jids, Q2PSTRING(firstMultiJIDPage_->reason_->text())));
             break;
         case InviteToChat:
             for (Contact::ref contact : contactVector_) {
                 jids.push_back(contact->jid);
             }
-            eventStream_->send(std::make_shared<InviteToMUCUIEvent>(roomJID_, jids, Q2PSTRING(firstMultiJIDPage_->reason_->text())));
+            eventStream_->send(std::make_shared<InviteToMUCUIEvent>(originatorJID_, jids, Q2PSTRING(firstMultiJIDPage_->reason_->text())));
             break;
     }
 }
@@ -387,6 +387,10 @@ void QtUserSearchWindow::setJIDs(const std::vector<JID> &jids) {
     onJIDUpdateRequested(jids);
 }
 
+void QtUserSearchWindow::setOriginator(const JID& originator) {
+    originatorJID_ = originator;
+}
+
 void QtUserSearchWindow::setRoomJID(const JID& roomJID) {
     roomJID_ = roomJID;
 }
diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.h b/Swift/QtUI/UserSearch/QtUserSearchWindow.h
index 5d8b755..b9d4698 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchWindow.h
+++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.h
@@ -47,6 +47,7 @@ namespace Swift {
             virtual void prepopulateJIDAndName(const JID& jid, const std::string& name);
             virtual void setContactSuggestions(const std::vector<Contact::ref>& suggestions);
             virtual void setJIDs(const std::vector<JID> &jids);
+            virtual void setOriginator(const JID& originator);
             virtual void setRoomJID(const JID &roomJID);
             virtual std::string getReason() const;
             virtual std::vector<JID> getJIDs() const;
@@ -97,6 +98,7 @@ namespace Swift {
             QtUserSearchDetailsPage* detailsPage_;
             JID myServer_;
             JID roomJID_;
+            JID originatorJID_;
             int lastPage_;
             std::vector<Contact::ref> contactVector_;
             SettingsProvider* settings_;
-- 
cgit v0.10.2-6-g49f6