diff options
author | Joanna Hulboj <joanna.hulboj@isode.com> | 2017-03-13 21:51:04 (GMT) |
---|---|---|
committer | Kevin Smith <kevin.smith@isode.com> | 2017-05-04 10:34:00 (GMT) |
commit | cfea60eda7f3ce5fa10ed92c50c19fc1ee264eb1 (patch) | |
tree | fb2564927189eb1cc8e28ac82fd96f6161b54d31 | |
parent | dc70dbb6af039fba8f7a1cece8db4bb119deaabd (diff) | |
download | swift-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
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 21 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.h | 3 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp | 73 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/ChatListWindow.h | 36 | ||||
-rw-r--r-- | Swift/QtUI/ChatList/ChatListRecentItem.cpp | 2 | ||||
-rw-r--r-- | Swiften/Base/Algorithm.h | 8 | ||||
-rw-r--r-- | Swiften/Client/DummyStanzaChannel.h | 14 |
7 files changed, 140 insertions, 17 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 @@ -69,3 +69,3 @@ -BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 1) +BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 2) @@ -98,2 +98,5 @@ namespace serialization { } + if (version > 1) { + ar & chat.inviteesNames; + } } @@ -404,2 +407,8 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const 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; @@ -490,3 +499,4 @@ void ChatsManager::appendRecent(const ChatListWindow::Chat& 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()); @@ -499,3 +509,4 @@ void ChatsManager::prependRecent(const ChatListWindow::Chat& 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()); @@ -592,2 +603,6 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) { + std::vector<JID> missingJIDsToInvite = createImpromptuMUCEvent->getJIDs(); + for (const JID& jid : missingJIDsToInvite) { + invitees_[roomJID].insert(jid); + } // join muc 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 @@ -11,2 +11,3 @@ #include <string> +#include <set> @@ -183,2 +184,4 @@ namespace Swift { 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 @@ -18,2 +18,4 @@ #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Base/LogSerializers.h> #include <Swiften/Client/Client.h> @@ -54,2 +56,3 @@ #include <Swift/Controllers/Settings/DummySettingsProvider.h> +#include <Swift/Controllers/UIEvents/CreateImpromptuMUCUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> @@ -69,2 +72,5 @@ +#include <Swift/QtUI/QtSwiftUtil.h> +#include <Swiften/MUC/UnitTest/MockMUC.h> + using namespace Swift; @@ -139,3 +145,2 @@ class ChatsManagerTest : public CppUnit::TestFixture { - // Message correction tests @@ -147,2 +152,5 @@ class ChatsManagerTest : public CppUnit::TestFixture { + //Imptomptu test + CPPUNIT_TEST(testImpromptuChatTitle); + CPPUNIT_TEST_SUITE_END(); @@ -1505,2 +1513,65 @@ public: + 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()); + } + 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 @@ -13,2 +13,4 @@ + +#include <boost/algorithm/string/join.hpp> #include <boost/filesystem/path.hpp> @@ -16,2 +18,3 @@ +#include <Swiften/Base/Algorithm.h> #include <Swiften/Elements/StatusShow.h> @@ -33,2 +36,5 @@ namespace Swift { } + if (chatName == other.chatName) { + return true; + } else { /* compare the chat occupant lists */ @@ -46,3 +52,3 @@ namespace Swift { } - return true; + return key_compare(inviteesNames, other.inviteesNames); } @@ -59,11 +65,24 @@ namespace Swift { 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; } @@ -79,2 +98,3 @@ namespace Swift { std::map<std::string, JID> impromptuJIDs; + std::map<JID, std::string> inviteesNames; bool isPrivateMessage; diff --git a/Swift/QtUI/ChatList/ChatListRecentItem.cpp b/Swift/QtUI/ChatList/ChatListRecentItem.cpp index faac937..9e55e1b 100644 --- a/Swift/QtUI/ChatList/ChatListRecentItem.cpp +++ b/Swift/QtUI/ChatList/ChatListRecentItem.cpp @@ -24,3 +24,3 @@ QVariant ChatListRecentItem::data(int role) const { switch (role) { - case Qt::DisplayRole: return chat_.impromptuJIDs.empty() ? P2QSTRING(chat_.chatName) : P2QSTRING(chat_.getImpromptuTitle()); + case Qt::DisplayRole: return P2QSTRING(chat_.getTitle()); case DetailTextRole: return P2QSTRING(chat_.activity); diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h index c481aa8..108dbe3 100644 --- a/Swiften/Base/Algorithm.h +++ b/Swiften/Base/Algorithm.h @@ -154,2 +154,10 @@ namespace Swift { }; + + template <typename Map> + bool key_compare(Map const& lhs, Map const& rhs) { + + auto pred = [](decltype(*lhs.begin()) a, decltype(a) b) { return a.first == b.first; }; + + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred); + } } diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h index fc2f05b..4cc0f7e 100644 --- a/Swiften/Client/DummyStanzaChannel.h +++ b/Swiften/Client/DummyStanzaChannel.h @@ -1,3 +1,3 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. @@ -15,3 +15,3 @@ namespace Swift { public: - DummyStanzaChannel() : available_(true) {} + DummyStanzaChannel() {} @@ -39,3 +39,7 @@ namespace Swift { virtual std::string getNewIQID() { - return "test-id"; + std::string id = "test-id"; + if (uniqueIDs_) { + id += "-" + std::to_string(idCounter_++); + } + return id; } @@ -96,3 +100,5 @@ namespace Swift { std::vector<std::shared_ptr<Stanza> > sentStanzas; - bool available_; + bool available_ = true; + bool uniqueIDs_ = false; + unsigned int idCounter_ = 0; }; |