summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoanna Hulboj <joanna.hulboj@isode.com>2017-03-13 21:51:04 (GMT)
committerKevin Smith <kevin.smith@isode.com>2017-05-04 10:34:00 (GMT)
commitcfea60eda7f3ce5fa10ed92c50c19fc1ee264eb1 (patch)
treefb2564927189eb1cc8e28ac82fd96f6161b54d31 /Swift/Controllers
parentdc70dbb6af039fba8f7a1cece8db4bb119deaabd (diff)
downloadswift-cfea60eda7f3ce5fa10ed92c50c19fc1ee264eb1.zip
swift-cfea60eda7f3ce5fa10ed92c50c19fc1ee264eb1.tar.bz2
Fix recent chat entries being incorrectly displayed
Recent chat entries were displayed as a randomly generated numbers instead of impromptus (if invitees were offline). Title displayed in the Recent Chat List for MUC is now based on both the occupants and invitees. To do that a collection with all the invitees is being stored (new) along the occupants (existing). Test-Information: From Swift menu choose Actions, Start Chat... Add some offline contacts to the List of Participants and press Finish. Recent chat entry will have correct name (combined of contact names). Change-Id: Ie076165e8dbb493aa261cc49ca3ab1e0c1c542a8
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp21
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h3
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp73
-rw-r--r--Swift/Controllers/UIInterfaces/ChatListWindow.h36
4 files changed, 121 insertions, 12 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index db3b3b7..9db343f 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -67,7 +67,7 @@
#include <Swift/Controllers/WhiteboardManager.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
-BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 1)
+BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 2)
namespace boost {
namespace serialization {
@@ -96,6 +96,9 @@ namespace serialization {
if (version > 0) {
ar & chat.password;
}
+ if (version > 1) {
+ ar & chat.inviteesNames;
+ }
}
}
}
@@ -402,6 +405,12 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const
ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, privateMessage, nick, password);
std::map<std::string, JID> participants = controller->getParticipantJIDs();
chat.impromptuJIDs = participants;
+
+ std::map<JID, std::string> participantsNames;
+ for (auto& i : invitees_[jid]) {
+ participantsNames.emplace(i, roster_->getNameForJID(i));
+ }
+ chat.inviteesNames = participantsNames;
return chat;
}
}
@@ -488,7 +497,8 @@ void ChatsManager::cleanupPrivateMessageRecents() {
void ChatsManager::appendRecent(const ChatListWindow::Chat& chat) {
boost::optional<ChatListWindow::Chat> oldChat = removeExistingChat(chat);
ChatListWindow::Chat mergedChat = chat;
- if (oldChat && !oldChat->impromptuJIDs.empty()) {
+ if (oldChat) {
+ mergedChat.inviteesNames.insert(oldChat->inviteesNames.begin(), oldChat->inviteesNames.end());
mergedChat.impromptuJIDs.insert(oldChat->impromptuJIDs.begin(), oldChat->impromptuJIDs.end());
}
recentChats_.push_front(mergedChat);
@@ -497,7 +507,8 @@ void ChatsManager::appendRecent(const ChatListWindow::Chat& chat) {
void ChatsManager::prependRecent(const ChatListWindow::Chat& chat) {
boost::optional<ChatListWindow::Chat> oldChat = removeExistingChat(chat);
ChatListWindow::Chat mergedChat = chat;
- if (oldChat && !oldChat->impromptuJIDs.empty()) {
+ if (oldChat) {
+ mergedChat.inviteesNames.insert(oldChat->inviteesNames.begin(), oldChat->inviteesNames.end());
mergedChat.impromptuJIDs.insert(oldChat->impromptuJIDs.begin(), oldChat->impromptuJIDs.end());
}
recentChats_.push_back(mergedChat);
@@ -590,6 +601,10 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
// The room JID is random for new impromptu rooms, or a predefined JID for impromptu rooms resumed from the 'Recent chats' list.
JID roomJID = createImpromptuMUCEvent->getRoomJID().toString().empty() ? JID(idGenerator_.generateID(), localMUCServiceJID_) : createImpromptuMUCEvent->getRoomJID();
+ std::vector<JID> missingJIDsToInvite = createImpromptuMUCEvent->getJIDs();
+ for (const JID& jid : missingJIDsToInvite) {
+ invitees_[roomJID].insert(jid);
+ }
// join muc
MUC::ref muc = handleJoinMUCRequest(roomJID, boost::optional<std::string>(), nickResolver_->jidToNick(jid_), false, true, true);
mucControllers_[roomJID]->onImpromptuConfigCompleted.connect(boost::bind(&ChatsManager::finalizeImpromptuJoin, this, muc, createImpromptuMUCEvent->getJIDs(), createImpromptuMUCEvent->getReason(), boost::optional<JID>()));
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 593624d..6004347 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <string>
+#include <set>
#include <Swiften/Base/IDGenerator.h>
#include <Swiften/Elements/DiscoInfo.h>
@@ -181,5 +182,7 @@ namespace Swift {
AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider_;
IDGenerator idGenerator_;
VCardManager* vcardManager_;
+
+ std::map<JID, std::set<JID>> invitees_;
};
}
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index bf645d0..52537a9 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -16,6 +16,8 @@
#include <Swiften/Avatars/AvatarMemoryStorage.h>
#include <Swiften/Avatars/NullAvatarManager.h>
#include <Swiften/Base/Algorithm.h>
+#include <Swiften/Base/Log.h>
+#include <Swiften/Base/LogSerializers.h>
#include <Swiften/Client/Client.h>
#include <Swiften/Client/ClientBlockListManager.h>
#include <Swiften/Client/DummyStanzaChannel.h>
@@ -52,6 +54,7 @@
#include <Swift/Controllers/ProfileSettingsProvider.h>
#include <Swift/Controllers/SettingConstants.h>
#include <Swift/Controllers/Settings/DummySettingsProvider.h>
+#include <Swift/Controllers/UIEvents/CreateImpromptuMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
@@ -67,6 +70,9 @@
#include <SwifTools/Notifier/Notifier.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swiften/MUC/UnitTest/MockMUC.h>
+
using namespace Swift;
class DummyNotifier : public Notifier {
@@ -137,7 +143,6 @@ class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testCarbonsForwardedOutgoingMessageFromSecondResource);
CPPUNIT_TEST(testCarbonsForwardedIncomingDuplicates);
-
// Message correction tests
CPPUNIT_TEST(testChatControllerMessageCorrectionCorrectReplaceID);
CPPUNIT_TEST(testChatControllerMessageCorrectionIncorrectReplaceID);
@@ -145,6 +150,9 @@ class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testChatControllerMessageCorrectionReplaceByOtherResource);
CPPUNIT_TEST(testMUCControllerMessageCorrectionNoIDMatchRequired);
+ //Imptomptu test
+ CPPUNIT_TEST(testImpromptuChatTitle);
+
CPPUNIT_TEST_SUITE_END();
public:
@@ -1503,6 +1511,69 @@ public:
CPPUNIT_ASSERT_EQUAL(std::string("Some correctly spelled message."), window->bodyFromMessage(window->lastReplacedMessage_));
}
+ void testImpromptuChatTitle() {
+ stanzaChannel_->uniqueIDs_ = true;
+ JID mucJID("795B7BBE-9099-4A0D-81BA-C816F78E275C@test.com");
+ manager_->setOnline(true);
+
+ // Open chat window to a sender.
+ MockChatWindow* window = new MockChatWindow();
+ std::shared_ptr<IQ> infoRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[1]);
+ CPPUNIT_ASSERT(infoRequest);
+
+ std::shared_ptr<IQ> infoResponse = IQ::createResult(infoRequest->getFrom(), infoRequest->getTo(), infoRequest->getID());
+
+ DiscoInfo info;
+ info.addIdentity(DiscoInfo::Identity("Shakespearean Chat Service", "conference", "text"));
+ info.addFeature("http://jabber.org/protocol/muc");
+ infoResponse->addPayload(std::make_shared<DiscoInfo>(info));
+ stanzaChannel_->onIQReceived(infoResponse);
+
+ std::vector<JID> jids;
+ jids.emplace_back("foo@test.com");
+ jids.emplace_back("bar@test.com");
+
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(mucJID, uiEventStream_).Return(window);
+ uiEventStream_->send(std::make_shared<CreateImpromptuMUCUIEvent>(jids, mucJID, ""));
+ CPPUNIT_ASSERT_EQUAL(std::string("bar@test.com, foo@test.com"), manager_->getRecentChats()[0].getTitle());
+
+ auto mucJoinPresence = std::dynamic_pointer_cast<Presence>(stanzaChannel_->sentStanzas[2]);
+ CPPUNIT_ASSERT(mucJoinPresence);
+
+ // MUC presence reply
+ auto mucResponse = Presence::create();
+ mucResponse->setTo(jid_);
+ mucResponse->setFrom(mucJoinPresence->getTo());
+ mucResponse->addPayload([]() {
+ auto mucUser = std::make_shared<MUCUserPayload>();
+ mucUser->addItem(MUCItem(MUCOccupant::Member, MUCOccupant::Participant));
+ mucUser->addStatusCode(MUCUserPayload::StatusCode(110));
+ mucUser->addStatusCode(MUCUserPayload::StatusCode(210));
+ return mucUser;
+ }());
+ stanzaChannel_->onPresenceReceived(mucResponse);
+
+ // Before people join the impromptu room, the title is based on names coming from Roster
+ CPPUNIT_ASSERT_EQUAL(std::string("bar@test.com, foo@test.com"), manager_->getRecentChats()[0].getTitle());
+
+ auto mucParticipantJoined = [&](const JID& jid) {
+ auto participantJoinedPresence = Presence::create();
+ participantJoinedPresence->setTo(jid_);
+ participantJoinedPresence->setFrom(mucJID.withResource(jid.toString()));
+ auto mucUser = std::make_shared<MUCUserPayload>();
+ mucUser->addItem(MUCItem(MUCOccupant::Member, MUCOccupant::Participant));
+ participantJoinedPresence->addPayload(mucUser);
+ return participantJoinedPresence;
+ };
+
+ for (const auto& participantJID : jids) {
+ stanzaChannel_->onPresenceReceived(mucParticipantJoined(participantJID));
+ }
+
+ // After people joined, the title is the list of participant nicknames or names coming from Roster (if nicknames are unavailable)
+ CPPUNIT_ASSERT_EQUAL(std::string("bar@test.com, foo@test.com"), manager_->getRecentChats()[0].getTitle());
+ }
+
private:
std::shared_ptr<Message> makeDeliveryReceiptTestMessage(const JID& from, const std::string& id) {
diff --git a/Swift/Controllers/UIInterfaces/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h
index dde596e..29097e9 100644
--- a/Swift/Controllers/UIInterfaces/ChatListWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h
@@ -11,9 +11,12 @@
#include <memory>
#include <set>
+
+#include <boost/algorithm/string/join.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/signals2.hpp>
+#include <Swiften/Base/Algorithm.h>
#include <Swiften/Elements/StatusShow.h>
#include <Swiften/MUC/MUCBookmark.h>
@@ -31,6 +34,9 @@ namespace Swift {
return jid.toBare() == other.jid.toBare()
&& isMUC == other.isMUC;
}
+ if (chatName == other.chatName) {
+ return true;
+ }
else { /* compare the chat occupant lists */
for (const auto& jid : impromptuJIDs) {
bool found = false;
@@ -44,7 +50,7 @@ namespace Swift {
return false;
}
}
- return true;
+ return key_compare(inviteesNames, other.inviteesNames);
}
}
void setUnreadCount(int unread) {
@@ -57,15 +63,28 @@ namespace Swift {
avatarPath = path;
}
std::string getImpromptuTitle() const {
- std::string title;
- for (auto& pair : impromptuJIDs) {
- if (title.empty()) {
- title += pair.first;
- } else {
- title += ", " + pair.first;
+ std::set<std::string> participants;
+ std::map<JID, std::string> participantsMap;
+
+ for (auto& pair : inviteesNames) {
+ if (!pair.second.empty()) {
+ participantsMap[pair.first] = pair.second;
}
+ else {
+ participantsMap[pair.first] = pair.first.toString();
+ }
+ }
+ for (auto& pair : impromptuJIDs) {
+ participantsMap[pair.second] = pair.first;
}
- return title;
+ for (auto& participant : participantsMap) {
+ participants.insert(participant.second);
+ }
+ return boost::algorithm::join(participants, ", ");
+ }
+ std::string getTitle() const {
+ std::string title = getImpromptuTitle();
+ return title.empty() ? chatName : title;
}
JID jid;
std::string chatName;
@@ -77,6 +96,7 @@ namespace Swift {
int unreadCount;
boost::filesystem::path avatarPath;
std::map<std::string, JID> impromptuJIDs;
+ std::map<JID, std::string> inviteesNames;
bool isPrivateMessage;
};
virtual ~ChatListWindow();