summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThanos Doukoudakis <thanos.doukoudakis@isode.com>2018-05-17 16:36:44 (GMT)
committerKevin Smith <kevin.smith@isode.com>2018-06-21 12:45:20 (GMT)
commit2bb40b14d3d7f5cebc56601dad066d5201040bd2 (patch)
tree5f208aa9a3b88c8fe0725aca1bd5d97451d45e2f
parent83434963a7b10b759ffe3fdc1312efdef282a450 (diff)
downloadswift-2bb40b14d3d7f5cebc56601dad066d5201040bd2.zip
swift-2bb40b14d3d7f5cebc56601dad066d5201040bd2.tar.bz2
Add a leave room option in MUC rooms
This patch will add a leave room option in the cog menu of a MUC room, allowing the user to leave the room and close the window. Additionally when joining or leaving a room the autojoin field will change to true or false respectively. This patch also fixes a minor issue with a gui option that was not identifying bookmarked rooms at the cog menu. The autojoin option on the Enter room, Bookmark room and Edit Bookmark menu has been removed, since the default behaviour will be to automatically bookmark every MUC room the user joins, setting autojoin to true. If the user chooses to leave the room, then the autojoin flag will be set to false and the bookmark will be updated. Test-Information: Tested the changes in the UI in Windows Qt 5.9. Updated the ChatsManagerTests unit tests to check the chattables and the behaviour of the bookmarks, when joining and leaving MUCs. Change-Id: Iad1f34480a1e0b9df25c73b49247acc7b7825e20
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp2
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp66
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h6
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp22
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp155
-rw-r--r--Swift/Controllers/UIEvents/JoinMUCUIEvent.h2
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h2
-rw-r--r--Swift/QtUI/ChatList/QtChatListWindow.cpp23
-rw-r--r--Swift/QtUI/ChatList/QtChatListWindow.h2
-rw-r--r--Swift/QtUI/QtBookmarkDetailWindow.cpp8
-rw-r--r--Swift/QtUI/QtBookmarkDetailWindow.ui23
-rw-r--r--Swift/QtUI/QtChatWindow.cpp16
-rw-r--r--Swift/QtUI/QtEditBookmarkWindow.cpp1
-rw-r--r--Swift/QtUI/QtJoinMUCWindow.cpp2
-rw-r--r--Swift/QtUI/QtJoinMUCWindow.ui8
-rw-r--r--Swift/QtUI/QtPlainChatView.cpp2
-rw-r--r--Swift/QtUI/QtWebKitChatView.cpp2
-rw-r--r--Swiften/MUC/MUCBookmarkManager.cpp37
-rw-r--r--Swiften/MUC/MUCBookmarkManager.h3
19 files changed, 230 insertions, 152 deletions
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 4d4ca86..8a26a56 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -378,7 +378,7 @@ 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);
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 63fd677..532b925 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -353,9 +353,11 @@ void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) {
if (bookmark.getRoom().isBare() && !bookmark.getRoom().getNode().empty()) {
std::map<JID, MUCController*>::iterator it = mucControllers_.find(bookmark.getRoom());
if (it == mucControllers_.end() && bookmark.getAutojoin()) {
- handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false, false );
+ handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false);
}
#ifndef NOT_YET
+ //Only one entry of the bookmark should exist
+ chatListWindow_->removeMUCBookmark(bookmark);
chatListWindow_->addMUCBookmark(bookmark);
#endif
chattables_.addJID(bookmark.getRoom(), Chattables::State::Type::Room);
@@ -534,6 +536,12 @@ void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
auto state = chattables_.getState(jid);
state.status = StatusShow::None;
chattables_.setState(jid, state);
+ //If user deletes bookmark from chatListWindow_ and then decides to leave the room, or if the server doesn't support bookmarks, the bookmark will not exist.
+ if (auto bookmarkFound = mucBookmarkManager_->lookupBookmark(jid)) {
+ MUCBookmark newBookmark(bookmarkFound.get());
+ newBookmark.setAutojoin(false);
+ mucBookmarkManager_->replaceBookmark(bookmarkFound.get(), newBookmark);
+ }
mucControllers_.erase(it);
delete mucController;
break;
@@ -619,7 +627,7 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
invitees_[roomJID].insert(jid);
}
// join muc
- MUC::ref muc = handleJoinMUCRequest(roomJID, boost::optional<std::string>(), nickResolver_->jidToNick(jid_), false, true, true);
+ MUC::ref muc = handleJoinMUCRequest(roomJID, boost::optional<std::string>(), nickResolver_->jidToNick(jid_), true, true);
mucControllers_[roomJID]->onImpromptuConfigCompleted.connect(boost::bind(&ChatsManager::finalizeImpromptuJoin, this, muc, createImpromptuMUCEvent->getJIDs(), createImpromptuMUCEvent->getReason(), boost::optional<JID>()));
mucControllers_[roomJID]->activateChatWindow();
}
@@ -629,7 +637,7 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
mucBookmarkManager_->replaceBookmark(editMUCBookmarkEvent->getOldBookmark(), editMUCBookmarkEvent->getNewBookmark());
}
else if (JoinMUCUIEvent::ref joinEvent = std::dynamic_pointer_cast<JoinMUCUIEvent>(event)) {
- handleJoinMUCRequest(joinEvent->getJID(), joinEvent->getPassword(), joinEvent->getNick(), joinEvent->getShouldJoinAutomatically(), joinEvent->getCreateAsReservedRoomIfNew(), joinEvent->isImpromptu());
+ handleJoinMUCRequest(joinEvent->getJID(), joinEvent->getPassword(), joinEvent->getNick(), joinEvent->getCreateAsReservedRoomIfNew(), joinEvent->isImpromptu());
mucControllers_[joinEvent->getJID()]->activateChatWindow();
}
else if (std::shared_ptr<RequestJoinMUCUIEvent> joinEvent = std::dynamic_pointer_cast<RequestJoinMUCUIEvent>(event)) {
@@ -665,7 +673,7 @@ void ChatsManager::handleTransformChatToMUC(ChatController* chatController, Chat
JID roomJID = JID(idGenerator_.generateID(), localMUCServiceJID_);
// join muc
- MUC::ref muc = handleJoinMUCRequest(roomJID, boost::optional<std::string>(), nickResolver_->jidToNick(jid_), false, true, true, chatWindow);
+ MUC::ref muc = handleJoinMUCRequest(roomJID, boost::optional<std::string>(), nickResolver_->jidToNick(jid_), true, true, chatWindow);
mucControllers_[roomJID]->onImpromptuConfigCompleted.connect(boost::bind(&ChatsManager::finalizeImpromptuJoin, this, muc, jidsToInvite, reason, boost::optional<JID>(reuseChatInvite)));
}
@@ -839,20 +847,8 @@ void ChatsManager::rebindControllerJID(const JID& from, const JID& to) {
chatControllers_[to]->setToJID(to);
}
-MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional<std::string>& password, const boost::optional<std::string>& nickMaybe, bool addAutoJoin, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow) {
+MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional<std::string>& password, const boost::optional<std::string>& nickMaybe, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow) {
MUC::ref muc;
- if (addAutoJoin) {
- MUCBookmark bookmark(mucJID, mucJID.getNode());
- bookmark.setAutojoin(true);
- if (nickMaybe) {
- bookmark.setNick(*nickMaybe);
- }
- if (password) {
- bookmark.setPassword(*password);
- }
- mucBookmarkManager_->addBookmark(bookmark);
- }
-
std::map<JID, MUCController*>::iterator it = mucControllers_.find(mucJID);
if (it != mucControllers_.end()) {
if (stanzaChannel_->isAvailable()) {
@@ -875,6 +871,10 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
}
std::shared_ptr<ChatMessageParser> chatMessageParser = std::make_shared<ChatMessageParser>(emoticons_, highlightManager_->getConfiguration(), ChatMessageParser::Mode::GroupChat); /* a message parser that knows this is a room/MUC (not a chat) */
controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, reuseChatwindow ? chatWindowFactoryAdapter : chatWindowFactory_, nickResolver_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, isImpromptu, autoAcceptMUCInviteDecider_, vcardManager_, mucBookmarkManager_, settings_, chattables_);
+ chattables_.addJID(muc->getJID(), Chattables::State::Type::Room);
+ auto state = chattables_.getState(muc->getJID());
+ state.status = StatusShow::Online;
+ chattables_.setState(muc->getJID(), state);
if (chatWindowFactoryAdapter) {
/* The adapters are only passed to chat windows, which are deleted in their
* controllers' dtor, which are deleted in ChatManager's dtor. The adapters
@@ -906,6 +906,24 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
mucControllers_[mucJID]->setChatWindowTitle(chatListWindowIter->getTitle());
}
#endif
+ if (auto existingBookmark = mucBookmarkManager_->lookupBookmark(mucJID)) {
+ if (!existingBookmark->getAutojoin()) {
+ MUCBookmark newbookmark(existingBookmark.get());
+ newbookmark.setAutojoin(true);
+ mucBookmarkManager_->replaceBookmark(*existingBookmark, newbookmark);
+ }
+ }
+ else {
+ MUCBookmark bookmark(mucJID, mucJID.getNode());
+ bookmark.setAutojoin(true);
+ if (nickMaybe) {
+ bookmark.setNick(*nickMaybe);
+ }
+ if (password) {
+ bookmark.setPassword(*password);
+ }
+ mucBookmarkManager_->addBookmark(bookmark);
+ }
mucControllers_[mucJID]->showChatWindow();
return muc;
}
@@ -1015,11 +1033,11 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> incomingMessag
ChatWindow* window = controller->detachChatWindow();
chatControllers_.erase(fromJID);
delete controller;
- handleJoinMUCRequest(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, false, true, window);
+ handleJoinMUCRequest(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, true, window);
return;
}
} else {
- handleJoinMUCRequest(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, false, true);
+ handleJoinMUCRequest(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, true);
return;
}
}
@@ -1091,7 +1109,7 @@ void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
else if (chat.isMUC) {
bool isImpromptu = (!chat.inviteesNames.empty() || !chat.impromptuJIDs.empty());
/* FIXME: This means that recents requiring passwords will just flat-out not work */
- uiEventStream_->send(std::make_shared<JoinMUCUIEvent>(chat.jid, boost::optional<std::string>(), chat.nick, false, false, isImpromptu));
+ uiEventStream_->send(std::make_shared<JoinMUCUIEvent>(chat.jid, boost::optional<std::string>(), chat.nick, false, isImpromptu));
}
else {
uiEventStream_->send(std::make_shared<RequestChatUIEvent>(chat.jid));
@@ -1106,8 +1124,12 @@ void ChatsManager::handleChattableActivated(const JID& jid) {
uiEventStream_->send(std::make_shared<RequestChatUIEvent>(jid));
}
else if (state.type == Chattables::State::Type::Room) {
- //FIXME: Find bookmarks and do handleMUCBookmarkActivated things
- uiEventStream_->send(std::make_shared<JoinMUCUIEvent>(jid, boost::optional<std::string>(), boost::optional<std::string>())); // Just a quick hack to reuse already open MUCs
+ if (auto foundBookmark = mucBookmarkManager_->lookupBookmark(jid)) {
+ handleMUCBookmarkActivated(foundBookmark.get());
+ }
+ else {
+ uiEventStream_->send(std::make_shared<JoinMUCUIEvent>(jid, boost::optional<std::string>(), boost::optional<std::string>())); // Just a quick hack to reuse already open MUCs
+ }
}
}
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 0b85840..e120831 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -94,7 +94,7 @@ namespace Swift {
#endif
void handleChatRequest(const std::string& contact);
void finalizeImpromptuJoin(MUC::ref muc, const std::vector<JID>& jidsToInvite, const std::string& reason, const boost::optional<JID>& reuseChatJID = boost::optional<JID>());
- MUC::ref handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& password, const boost::optional<std::string>& nick, bool addAutoJoin, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow = nullptr);
+ MUC::ref handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& password, const boost::optional<std::string>& nick, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow = nullptr);
void handleSearchMUCRequest();
void handleMUCSelectedAfterSearch(const JID&);
void rebindControllerJID(const JID& from, const JID& to);
@@ -152,6 +152,9 @@ namespace Swift {
ChatController* getChatControllerOrCreate(const JID &contact);
ChatController* getChatControllerIfExists(const JID &contact, bool rebindIfNeeded = true);
+ protected:
+ MUCBookmarkManager* mucBookmarkManager_;
+
private:
std::map<JID, MUCController*> mucControllers_;
std::map<JID, ChatController*> chatControllers_;
@@ -167,7 +170,6 @@ namespace Swift {
AvatarManager* avatarManager_;
PresenceSender* presenceSender_;
UIEventStream* uiEventStream_;
- MUCBookmarkManager* mucBookmarkManager_;
std::shared_ptr<DiscoInfo> serverDiscoInfo_;
#ifndef NOT_YET
ChatListWindow* chatListWindow_;
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 071b919..30d4933 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -36,6 +36,7 @@
#include <SwifTools/TabComplete.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Highlighting/Highlighter.h>
#include <Swift/Controllers/Intl.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
@@ -60,17 +61,6 @@
namespace Swift {
-class MUCBookmarkPredicate {
- public:
- MUCBookmarkPredicate(const JID& mucJID) : roomJID_(mucJID) { }
- bool operator()(const MUCBookmark& operand) {
- return operand.getRoom() == roomJID_;
- }
-
- private:
- JID roomJID_;
-};
-
/**
* The controller does not gain ownership of the stanzaChannel, nor the factory.
*/
@@ -174,14 +164,7 @@ MUCController::MUCController (
mucBookmarkManagerBookmarkAddedConnection_ = (mucBookmarkManager_->onBookmarkAdded.connect(boost::bind(&MUCController::handleMUCBookmarkAdded, this, _1)));
mucBookmarkManagerBookmarkRemovedConnection_ = (mucBookmarkManager_->onBookmarkRemoved.connect(boost::bind(&MUCController::handleMUCBookmarkRemoved, this, _1)));
- std::vector<MUCBookmark> mucBookmarks = mucBookmarkManager_->getBookmarks();
- std::vector<MUCBookmark>::iterator bookmarkIterator = std::find_if(mucBookmarks.begin(), mucBookmarks.end(), MUCBookmarkPredicate(muc->getJID()));
- if (bookmarkIterator != mucBookmarks.end()) {
- updateChatWindowBookmarkStatus(*bookmarkIterator);
- }
- else {
- updateChatWindowBookmarkStatus(boost::optional<MUCBookmark>());
- }
+ updateChatWindowBookmarkStatus(mucBookmarkManager_->lookupBookmark(muc->getJID()));
}
MUCController::~MUCController() {
@@ -498,6 +481,7 @@ void MUCController::setAvailableRoomActions(const MUCOccupant::Affiliation& affi
if (role <= MUCOccupant::Visitor) {
actions.push_back(ChatWindow::Invite);
}
+ actions.push_back(ChatWindow::Leave);
chatWindow_->setAvailableRoomActions(actions);
}
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index e0a7fe3..7469d64 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -38,6 +38,7 @@
#include <Swiften/Jingle/JingleSessionManager.h>
#include <Swiften/MUC/MUCManager.h>
#include <Swiften/MUC/UnitTest/MockMUC.h>
+#include <Swiften/MUC/MUCBookmarkManager.h>
#include <Swiften/Network/DummyTimerFactory.h>
#include <Swiften/Presence/DirectedPresenceSender.h>
#include <Swiften/Presence/PresenceOracle.h>
@@ -58,6 +59,7 @@
#include <Swift/Controllers/ProfileSettingsProvider.h>
#include <Swift/Controllers/SettingConstants.h>
#include <Swift/Controllers/Settings/DummySettingsProvider.h>
+#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIEvents/CreateImpromptuMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
@@ -107,6 +109,16 @@ class DummyNotifier : public Notifier {
std::vector<Notification> notifications;
};
+class ExtendedChatsManager : public ChatsManager {
+public:
+ ExtendedChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, const std::map<std::string, std::string>& emoticons, VCardManager* vcardManager, Chattables& chattables) :
+ ChatsManager(jid, stanzaChannel, iqRouter, eventController, chatWindowFactory, joinMUCWindowFactory, nickResolver, presenceOracle, presenceSender, uiEventStream, chatListWindowFactory, useDelayForLatency, timerFactory, mucRegistry, entityCapsProvider, mucManager, mucSearchWindowFactory, profileSettings, ftOverview, roster, eagleMode, settings, historyController_, whiteboardManager, highlightManager, clientBlockListManager, emoticons, vcardManager, chattables) {
+ }
+ MUCBookmarkManager* getBookmarkManager() {
+ return mucBookmarkManager_;
+ }
+};
+
class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ChatsManagerTest);
@@ -162,6 +174,9 @@ class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testReceivingBookmarksWithDomainJID);
CPPUNIT_TEST(testReceivingBookmarksWithBareJID);
CPPUNIT_TEST(testReceivingBookmarksWithFullJID);
+ CPPUNIT_TEST(testAutoJoinBookmarksAndChattables);
+ CPPUNIT_TEST(testJoinNoAutojoinBookmark);
+ CPPUNIT_TEST(testJoinAndBookmarkMUC);
CPPUNIT_TEST_SUITE_END();
@@ -209,7 +224,7 @@ public:
clientBlockListManager_ = new ClientBlockListManager(iqRouter_);
timerFactory_ = new DummyTimerFactory();
chattables_ = std::make_unique<Chattables>();
- manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, timerFactory_, mucRegistry_, entityCapsProvider_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, nullptr, wbManager_, highlightManager_, clientBlockListManager_, emoticons_, vcardManager_, *chattables_);
+ manager_ = new ExtendedChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, timerFactory_, mucRegistry_, entityCapsProvider_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, nullptr, wbManager_, highlightManager_, clientBlockListManager_, emoticons_, vcardManager_, *chattables_);
manager_->setAvatarManager(avatarManager_);
}
@@ -1632,17 +1647,7 @@ public:
CPPUNIT_ASSERT_EQUAL(std::string("mucroom"), window->name_);
}
- static std::shared_ptr<Storage> createBookmarkStorageWithJID(const JID& jid) {
- auto storage = std::make_shared<Storage>();
- auto room = Storage::Room();
- room.jid = jid;
- room.autoJoin = true;
- storage->addRoom(room);
- return storage;
- }
-
- void testReceivingBookmarksWithDomainJID() {
- auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
+ std::shared_ptr<Storage> createBookmarkStorageWithJID(std::shared_ptr<IQ> bookmarkRequest, const JID& jid, const bool autojoin) {
CPPUNIT_ASSERT(bookmarkRequest);
CPPUNIT_ASSERT_EQUAL(IQ::Get, bookmarkRequest->getType());
@@ -1652,56 +1657,144 @@ public:
auto storage = std::dynamic_pointer_cast<Storage>(privateStorage->getPayload());
CPPUNIT_ASSERT(storage);
+ auto roomsStorage = std::make_shared<Storage>();
+ if (jid.isValid()) {
+ auto room = Storage::Room();
+ room.jid = jid;
+ room.autoJoin = autojoin;
+ roomsStorage->addRoom(room);
+ }
+ return roomsStorage;
+ }
+
+ void testReceivingBookmarksWithDomainJID() {
+ auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
auto response = IQ::createResult(
bookmarkRequest->getFrom(),
bookmarkRequest->getTo(),
bookmarkRequest->getID(),
- std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("montague.lit"))
+ std::make_shared<PrivateStorage>(createBookmarkStorageWithJID(bookmarkRequest, "montague.lit", true))
);
stanzaChannel_->onIQReceived(response);
}
void testReceivingBookmarksWithBareJID() {
auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
- CPPUNIT_ASSERT(bookmarkRequest);
- CPPUNIT_ASSERT_EQUAL(IQ::Get, bookmarkRequest->getType());
+ MockChatWindow* window = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID("example@montague.lit"), uiEventStream_).Return(window);
+ auto response = IQ::createResult(
+ bookmarkRequest->getFrom(),
+ bookmarkRequest->getTo(),
+ bookmarkRequest->getID(),
+ std::make_shared<PrivateStorage>(createBookmarkStorageWithJID(bookmarkRequest, "example@montague.lit", true))
+ );
+ stanzaChannel_->onIQReceived(response);
+ }
- auto privateStorage = bookmarkRequest->getPayload<PrivateStorage>();
- CPPUNIT_ASSERT(privateStorage);
+ void testReceivingBookmarksWithFullJID() {
+ auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
+ auto response = IQ::createResult(
+ bookmarkRequest->getFrom(),
+ bookmarkRequest->getTo(),
+ bookmarkRequest->getID(),
+ std::make_shared<PrivateStorage>(createBookmarkStorageWithJID(bookmarkRequest, "example@montague.lit/someresource", true))
+ );
+ stanzaChannel_->onIQReceived(response);
+ }
- auto storage = std::dynamic_pointer_cast<Storage>(privateStorage->getPayload());
- CPPUNIT_ASSERT(storage);
+ void testAutoJoinBookmarksAndChattables() {
- MockChatWindow* window = new MockChatWindow();
- mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID("example@montague.lit"), uiEventStream_).Return(window);
+ auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
+ auto roomsStorage = createBookmarkStorageWithJID(bookmarkRequest, "autojoin@bookmark.lit", true);
+ auto room = Storage::Room();
+ room.jid = "noAutojoin@bookmark.lit";
+ roomsStorage->addRoom(room);
+
+ //Only autojoin@bookmark.lit window should open.
+ MockChatWindow* autojoinBookmarkWindow = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID("autojoin@bookmark.lit"), uiEventStream_).Return(autojoinBookmarkWindow);
auto response = IQ::createResult(
bookmarkRequest->getFrom(),
bookmarkRequest->getTo(),
bookmarkRequest->getID(),
- std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("example@montague.lit"))
+ std::make_shared<PrivateStorage>(roomsStorage)
);
stanzaChannel_->onIQReceived(response);
+ //Both bookmarks should be added to the chattables.
+ CPPUNIT_ASSERT_EQUAL(size_t(2), chattables_->get().size());
+ auto autoJoinState = chattables_->getState("autojoin@bookmark.lit");
+ CPPUNIT_ASSERT(autoJoinState.type == Chattables::State::Type::Room);
+ CPPUNIT_ASSERT_EQUAL(autoJoinState.status, StatusShow::Online);
+ auto noAutoJoinState = chattables_->getState("noAutojoin@bookmark.lit");
+ CPPUNIT_ASSERT(noAutoJoinState.type == Chattables::State::Type::Room);
+ CPPUNIT_ASSERT_EQUAL(noAutoJoinState.status, StatusShow::None);
}
- void testReceivingBookmarksWithFullJID() {
+ void testJoinNoAutojoinBookmark() {
+
auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
- CPPUNIT_ASSERT(bookmarkRequest);
- CPPUNIT_ASSERT_EQUAL(IQ::Get, bookmarkRequest->getType());
+ auto roomsStorage = createBookmarkStorageWithJID(bookmarkRequest, "example@montague.lit", false);
- auto privateStorage = bookmarkRequest->getPayload<PrivateStorage>();
- CPPUNIT_ASSERT(privateStorage);
+ auto response = IQ::createResult(
+ bookmarkRequest->getFrom(),
+ bookmarkRequest->getTo(),
+ bookmarkRequest->getID(),
+ std::make_shared<PrivateStorage>(roomsStorage)
+ );
+ stanzaChannel_->onIQReceived(response);
- auto storage = std::dynamic_pointer_cast<Storage>(privateStorage->getPayload());
- CPPUNIT_ASSERT(storage);
+ //Join previous bookmarked room, expecting no increase in chattables and change of autojoin in bookmark to true
+ MockChatWindow* newExampleChatWindow = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID("example@montague.lit"), uiEventStream_).Return(newExampleChatWindow);
+ uiEventStream_->send(std::make_shared<JoinMUCUIEvent>("example@montague.lit", boost::optional<std::string>(), boost::optional<std::string>()));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), chattables_->get().size());
+ auto state = chattables_->getState("example@montague.lit");
+ CPPUNIT_ASSERT(state.type == Chattables::State::Type::Room);
+ CPPUNIT_ASSERT_EQUAL(state.status, StatusShow::Online);
+
+ auto bookmarks = manager_->getBookmarkManager()->getBookmarks();
+ CPPUNIT_ASSERT_EQUAL(bookmarks.size(), size_t(1));
+ CPPUNIT_ASSERT(bookmarks[0].getRoom() == JID("example@montague.lit"));
+ CPPUNIT_ASSERT(bookmarks[0].getAutojoin());
+ }
+ void testJoinAndBookmarkMUC() {
+ auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]);
+ auto roomsStorage = createBookmarkStorageWithJID(bookmarkRequest, "", true);
auto response = IQ::createResult(
bookmarkRequest->getFrom(),
bookmarkRequest->getTo(),
bookmarkRequest->getID(),
- std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("example@montague.lit/someresource"))
+ std::make_shared<PrivateStorage>(roomsStorage)
);
stanzaChannel_->onIQReceived(response);
+
+ //Join non-bookmarked room expecting for the room to get bookmarked with autojoin to true
+ MockChatWindow* exampleChatWindow = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With("example@montague.lit", uiEventStream_).Return(exampleChatWindow);
+ uiEventStream_->send(std::make_shared<JoinMUCUIEvent>("example@montague.lit", boost::optional<std::string>(), boost::optional<std::string>()));
+ {
+ CPPUNIT_ASSERT_EQUAL(size_t(1), chattables_->get().size());
+ auto state = chattables_->getState("example@montague.lit");
+ CPPUNIT_ASSERT(state.type == Chattables::State::Type::Room);
+ CPPUNIT_ASSERT_EQUAL(state.status, StatusShow::Online);
+
+ auto bookmarks = manager_->getBookmarkManager()->getBookmarks();
+ CPPUNIT_ASSERT_EQUAL(bookmarks.size(), size_t(1));
+ CPPUNIT_ASSERT(bookmarks[0].getRoom() == JID("example@montague.lit"));
+ CPPUNIT_ASSERT(bookmarks[0].getAutojoin());
+
+ }
+ //Exiting room that is bookmarked, expecting chattable to stay but bookmark autojoin change to false.
+ exampleChatWindow->onClosed();
+ {
+ CPPUNIT_ASSERT_EQUAL(size_t(1), chattables_->get().size());
+ auto bookmarks = manager_->getBookmarkManager()->getBookmarks();
+ CPPUNIT_ASSERT_EQUAL(bookmarks.size(), size_t(1));
+ CPPUNIT_ASSERT(bookmarks[0].getRoom() == JID("example@montague.lit"));
+ CPPUNIT_ASSERT(!bookmarks[0].getAutojoin());
+ }
}
private:
@@ -1728,7 +1821,7 @@ private:
private:
JID jid_;
std::unique_ptr<DummyNotifier> notifier_;
- ChatsManager* manager_;
+ ExtendedChatsManager* manager_;
DummyStanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
EventController* eventController_;
diff --git a/Swift/Controllers/UIEvents/JoinMUCUIEvent.h b/Swift/Controllers/UIEvents/JoinMUCUIEvent.h
index 5d6df55..78103a8 100644
--- a/Swift/Controllers/UIEvents/JoinMUCUIEvent.h
+++ b/Swift/Controllers/UIEvents/JoinMUCUIEvent.h
@@ -19,7 +19,7 @@ namespace Swift {
class JoinMUCUIEvent : public UIEvent {
public:
typedef std::shared_ptr<JoinMUCUIEvent> ref;
- JoinMUCUIEvent(const JID& jid, const boost::optional<std::string>& password = boost::optional<std::string>(), const boost::optional<std::string>& nick = boost::optional<std::string>(), bool joinAutomaticallyInFuture = false, bool createAsReservedRoomIfNew = false, bool isImpromptu = false, bool isContinuation = false) : jid_(jid), nick_(nick), joinAutomatically_(joinAutomaticallyInFuture), createAsReservedRoomIfNew_(createAsReservedRoomIfNew), password_(password), isImpromptuMUC_(isImpromptu), isContinuation_(isContinuation) {}
+ JoinMUCUIEvent(const JID& jid, const boost::optional<std::string>& password = boost::optional<std::string>(), const boost::optional<std::string>& nick = boost::optional<std::string>(), bool createAsReservedRoomIfNew = false, bool isImpromptu = false, bool isContinuation = false) : jid_(jid), nick_(nick), createAsReservedRoomIfNew_(createAsReservedRoomIfNew), password_(password), isImpromptuMUC_(isImpromptu), isContinuation_(isContinuation) {}
const boost::optional<std::string>& getNick() const {return nick_;}
const JID& getJID() const {return jid_;}
bool getShouldJoinAutomatically() const {return joinAutomatically_;}
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 507269f..daece0e 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -141,7 +141,7 @@ namespace Swift {
enum AckState {Pending, Received, Failed};
enum ReceiptState {ReceiptRequested, ReceiptReceived, ReceiptFailed};
enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor, AddContact, ShowProfile};
- enum RoomAction {ChangeSubject, Configure, Affiliations, Destroy, Invite};
+ enum RoomAction {ChangeSubject, Configure, Affiliations, Destroy, Invite, Leave};
enum FileTransferState {
Initialisation, ///< Collecting information required for sending the request out.
WaitingForAccept, ///< The file transfer request was send out.
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp
index 3caed57..e92ba0d 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.cpp
+++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp
@@ -86,11 +86,9 @@ void QtChatListWindow::handleClicked(const QModelIndex& index) {
void QtChatListWindow::setupContextMenus() {
mucMenu_ = new QMenu();
- onlineOnlyActions_ << mucMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
onlineOnlyActions_ << mucMenu_->addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark()));
onlineOnlyActions_ << mucMenu_->addAction(tr("Remove Bookmark"), this, SLOT(handleRemoveBookmark()));
emptyMenu_ = new QMenu();
- onlineOnlyActions_ << emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
}
void QtChatListWindow::handleItemActivated(const QModelIndex& index) {
@@ -146,22 +144,6 @@ void QtChatListWindow::handleRemoveBookmark() {
eventStream_->send(std::make_shared<RemoveMUCBookmarkUIEvent>(mucItem->getBookmark()));
}
-void QtChatListWindow::handleAddBookmarkFromRecents() {
- const ChatListRecentItem* item = dynamic_cast<const ChatListRecentItem*>(contextMenuItem_);
- if (item) {
- const ChatListWindow::Chat& chat = item->getChat();
- MUCBookmark bookmark(chat.jid, chat.jid.toBare().toString());
- bookmark.setNick(chat.nick);
- bookmark.setPassword(chat.password);
- eventStream_->send(std::make_shared<AddMUCBookmarkUIEvent>(bookmark));
- }
-}
-
-void QtChatListWindow::handleAddBookmark() {
- (new QtAddBookmarkWindow(eventStream_))->show();
-}
-
-
void QtChatListWindow::handleEditBookmark() {
const ChatListMUCItem* mucItem = dynamic_cast<const ChatListMUCItem*>(contextMenuItem_);
if (!mucItem) return;
@@ -208,11 +190,8 @@ void QtChatListWindow::contextMenuEvent(QContextMenuEvent* event) {
if (mucItem) {
contextMenuItem_ = mucItem;
bookmarkAction = mucRecentsMenu.addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark()));
+ bookmarkAction->setEnabled(isOnline_);
}
- else {
- bookmarkAction = mucRecentsMenu.addAction(tr("Add to Bookmarks"), this, SLOT(handleAddBookmarkFromRecents()));
- }
- bookmarkAction->setEnabled(isOnline_);
mucRecentsMenu.addAction(tr("Clear recents"), this, SLOT(handleClearRecentsRequested()));
mucRecentsMenu.exec(QCursor::pos());
return;
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h
index 834e318..001650c 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.h
+++ b/Swift/QtUI/ChatList/QtChatListWindow.h
@@ -35,10 +35,8 @@ namespace Swift {
void onCountUpdated(int count);
private slots:
void handleItemActivated(const QModelIndex&);
- void handleAddBookmark();
void handleEditBookmark();
void handleRemoveBookmark();
- void handleAddBookmarkFromRecents();
void handleClicked(const QModelIndex& index);
void handleSettingChanged(const std::string& setting);
void handleClearRecentsRequested();
diff --git a/Swift/QtUI/QtBookmarkDetailWindow.cpp b/Swift/QtUI/QtBookmarkDetailWindow.cpp
index 920e94e..efa0e25 100644
--- a/Swift/QtUI/QtBookmarkDetailWindow.cpp
+++ b/Swift/QtUI/QtBookmarkDetailWindow.cpp
@@ -42,7 +42,7 @@ boost::optional<MUCBookmark> QtBookmarkDetailWindow::createBookmarkFromForm() {
MUCBookmark bookmark(room, name);
std::string nick(Q2PSTRING(nick_->text()));
std::string password(Q2PSTRING(password_->text()));
- bookmark.setAutojoin(autojoin_->isChecked());
+ bookmark.setAutojoin(true);
if (!nick.empty()) {
bookmark.setNick(nick);
}
@@ -68,12 +68,6 @@ void QtBookmarkDetailWindow::createFormFromBookmark(const MUCBookmark& bookmark)
if (bookmark.getPassword()) {
password_->setText(P2QSTRING((*bookmark.getPassword())));
}
-
- if (bookmark.getAutojoin()) {
- autojoin_->setCheckState(Qt::Checked);
- } else {
- autojoin_->setCheckState(Qt::Unchecked);
- }
}
}
diff --git a/Swift/QtUI/QtBookmarkDetailWindow.ui b/Swift/QtUI/QtBookmarkDetailWindow.ui
index be55686..affb7e4 100644
--- a/Swift/QtUI/QtBookmarkDetailWindow.ui
+++ b/Swift/QtUI/QtBookmarkDetailWindow.ui
@@ -82,29 +82,6 @@
<item row="3" column="1">
<widget class="QLineEdit" name="password_"/>
</item>
- <item row="4" column="0">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="4" column="1">
- <widget class="QCheckBox" name="autojoin_">
- <property name="text">
- <string>Enter automatically</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
</layout>
</item>
<item>
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 7c0a9d8..a413b4d 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -751,6 +751,7 @@ void QtChatWindow::handleActionButtonClicked() {
QAction* affiliations = nullptr;
QAction* destroy = nullptr;
QAction* invite = nullptr;
+ QAction* leave = nullptr;
QAction* block = nullptr;
QAction* unblock = nullptr;
@@ -804,6 +805,10 @@ void QtChatWindow::handleActionButtonClicked() {
invite = contextMenu.addAction(tr("Invite person to this room…"));
invite->setEnabled(isOnline_);
break;
+ case ChatWindow::Leave:
+ leave = contextMenu.addAction(tr("Leave room"));
+ leave->setEnabled(isOnline_);
+ break;
}
}
}
@@ -855,6 +860,9 @@ void QtChatWindow::handleActionButtonClicked() {
else if (result == invite) {
onInviteToChat(std::vector<JID>());
}
+ else if (result == leave) {
+ close();
+ }
else if (result == block) {
onBlockUserRequest();
}
@@ -888,14 +896,16 @@ void QtChatWindow::setCanInitiateImpromptuChats(bool supportsImpromptu) {
}
void QtChatWindow::showBookmarkWindow(const MUCBookmark& bookmark) {
- if (roomBookmarkState_ == RoomNotBookmarked) {
- QtAddBookmarkWindow* window = new QtAddBookmarkWindow(eventStream_, bookmark);
+ if (roomBookmarkState_ != RoomNotBookmarked) {
+ QtEditBookmarkWindow* window = new QtEditBookmarkWindow(eventStream_, bookmark);
window->show();
}
+#ifndef NOT_YET
else {
- QtEditBookmarkWindow* window = new QtEditBookmarkWindow(eventStream_, bookmark);
+ QtAddBookmarkWindow* window = new QtAddBookmarkWindow(eventStream_, bookmark);
window->show();
}
+#endif // ! NOT_YET
}
std::string QtChatWindow::getID() const {
diff --git a/Swift/QtUI/QtEditBookmarkWindow.cpp b/Swift/QtUI/QtEditBookmarkWindow.cpp
index 1d6b467..c724c97 100644
--- a/Swift/QtUI/QtEditBookmarkWindow.cpp
+++ b/Swift/QtUI/QtEditBookmarkWindow.cpp
@@ -12,7 +12,6 @@ namespace Swift {
QtEditBookmarkWindow::QtEditBookmarkWindow(UIEventStream* eventStream, const MUCBookmark& bookmark) : eventStream_(eventStream), bookmark_(bookmark) {
name_->setText(P2QSTRING(bookmark.getName()));
room_->setText(P2QSTRING(bookmark.getRoom().toString()));
- autojoin_->setChecked(bookmark.getAutojoin());
nick_->setText(bookmark.getNick() ? P2QSTRING(bookmark.getNick().get()) : "");
password_->setText(bookmark.getPassword() ? P2QSTRING(bookmark.getPassword().get()) : "");
}
diff --git a/Swift/QtUI/QtJoinMUCWindow.cpp b/Swift/QtUI/QtJoinMUCWindow.cpp
index 13de1c9..550ae4a 100644
--- a/Swift/QtUI/QtJoinMUCWindow.cpp
+++ b/Swift/QtUI/QtJoinMUCWindow.cpp
@@ -49,7 +49,7 @@ void QtJoinMUCWindow::handleJoin() {
lastSetNick = Q2PSTRING(ui.nickName->text());
std::string password = Q2PSTRING(ui.password->text());
JID room(Q2PSTRING(ui.room->text()));
- uiEventStream->send(std::make_shared<JoinMUCUIEvent>(room, password, lastSetNick, ui.joinAutomatically->isChecked(), !ui.instantRoom->isChecked()));
+ uiEventStream->send(std::make_shared<JoinMUCUIEvent>(room, password, lastSetNick, !ui.instantRoom->isChecked()));
hide();
}
diff --git a/Swift/QtUI/QtJoinMUCWindow.ui b/Swift/QtUI/QtJoinMUCWindow.ui
index 24d6ab8..96f1d17 100644
--- a/Swift/QtUI/QtJoinMUCWindow.ui
+++ b/Swift/QtUI/QtJoinMUCWindow.ui
@@ -101,13 +101,6 @@
</spacer>
</item>
<item>
- <widget class="QCheckBox" name="joinAutomatically">
- <property name="text">
- <string>Enter automatically in future</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="QPushButton" name="joinButton">
<property name="text">
<string>Enter Room</string>
@@ -124,7 +117,6 @@
<tabstop>nickName</tabstop>
<tabstop>password</tabstop>
<tabstop>instantRoom</tabstop>
- <tabstop>joinAutomatically</tabstop>
<tabstop>joinButton</tabstop>
</tabstops>
<resources/>
diff --git a/Swift/QtUI/QtPlainChatView.cpp b/Swift/QtUI/QtPlainChatView.cpp
index 5d23923..3d67091 100644
--- a/Swift/QtUI/QtPlainChatView.cpp
+++ b/Swift/QtUI/QtPlainChatView.cpp
@@ -327,7 +327,7 @@ void QtPlainChatView::acceptMUCInvite()
{
AcceptMUCInviteAction *action = dynamic_cast<AcceptMUCInviteAction*>(sender());
if (action) {
- eventStream_->send(std::make_shared<JoinMUCUIEvent>(action->jid_.toString(), action->password_, boost::optional<std::string>(), false, false, action->isImpromptu_, action->isContinuation_));
+ eventStream_->send(std::make_shared<JoinMUCUIEvent>(action->jid_.toString(), action->password_, boost::optional<std::string>(), false, action->isImpromptu_, action->isContinuation_));
delete action->parent_;
}
}
diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp
index 8ced8fc..f2effa8 100644
--- a/Swift/QtUI/QtWebKitChatView.cpp
+++ b/Swift/QtUI/QtWebKitChatView.cpp
@@ -811,7 +811,7 @@ void QtWebKitChatView::handleHTMLButtonClicked(QString id, QString encodedArgume
QString elementID = arg3;
QString isImpromptu = arg4;
QString isContinuation = arg5;
- eventStream_->send(std::make_shared<JoinMUCUIEvent>(Q2PSTRING(roomJID), Q2PSTRING(password), boost::optional<std::string>(), false, false, isImpromptu.contains("true"), isContinuation.contains("true")));
+ eventStream_->send(std::make_shared<JoinMUCUIEvent>(Q2PSTRING(roomJID), Q2PSTRING(password), boost::optional<std::string>(), false, isImpromptu.contains("true"), isContinuation.contains("true")));
setMUCInvitationJoined(elementID);
}
else if (id.startsWith(ButtonResendPopup)) {
diff --git a/Swiften/MUC/MUCBookmarkManager.cpp b/Swiften/MUC/MUCBookmarkManager.cpp
index 9f8ae77..e394217 100644
--- a/Swiften/MUC/MUCBookmarkManager.cpp
+++ b/Swiften/MUC/MUCBookmarkManager.cpp
@@ -6,6 +6,7 @@
#include <Swiften/MUC/MUCBookmarkManager.h>
+#include <algorithm>
#include <memory>
#include <boost/bind.hpp>
@@ -30,6 +31,7 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
}
ready_ = true;
+ handlingReceivedBookmarks_ = true;
onBookmarksReady();
storage = payload;
@@ -47,18 +49,25 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
onBookmarkRemoved(oldBookmark);
}
}
-
+ std::vector<MUCBookmark> newAddedBookmarksToBeSignaled;
for (const auto& newBookmark : receivedBookmarks) {
if (!containsEquivalent(bookmarks_, newBookmark)) {
newBookmarks.push_back(newBookmark);
- onBookmarkAdded(newBookmark);
+ //If the bookmark does not exist in bookmark manager, after emmiting the signal, chatsmanager will try to join the room, if the bookmark has autojoin to true.
+ //The bookmark is not yet available in bookmark manager, therefore a new bookmark will be created which will be lost when newBookmarks replace bookmarks.
+ newAddedBookmarksToBeSignaled.push_back(newBookmark);
}
}
bookmarks_ = newBookmarks;
+ for (auto bookmark : newAddedBookmarksToBeSignaled) {
+ onBookmarkAdded(bookmark);
+ }
+
+ handlingReceivedBookmarks_ = false;
}
bool MUCBookmarkManager::containsEquivalent(const std::vector<MUCBookmark>& list, const MUCBookmark& bookmark) {
- return std::find(list.begin(), list.end(), bookmark) != list.end();
+ return std::find_if(list.begin(), list.end(), [&](const MUCBookmark& val) { return bookmark.getRoom() == val.getRoom(); }) != list.end();
}
void MUCBookmarkManager::replaceBookmark(const MUCBookmark& oldBookmark, const MUCBookmark& newBookmark) {
@@ -76,8 +85,15 @@ void MUCBookmarkManager::replaceBookmark(const MUCBookmark& oldBookmark, const M
void MUCBookmarkManager::addBookmark(const MUCBookmark& bookmark) {
if (!ready_) return;
- bookmarks_.push_back(bookmark);
- onBookmarkAdded(bookmark);
+ if (auto found = lookupBookmark(bookmark.getRoom())) {
+ if (found != bookmark) {
+ replaceBookmark(found.get(), bookmark);
+ }
+ }
+ else {
+ bookmarks_.push_back(bookmark);
+ onBookmarkAdded(bookmark);
+ }
flush();
}
@@ -96,6 +112,9 @@ void MUCBookmarkManager::removeBookmark(const MUCBookmark& bookmark) {
}
void MUCBookmarkManager::flush() {
+ if (handlingReceivedBookmarks_) {
+ return;
+ }
if (!storage) {
storage = std::make_shared<Storage>();
}
@@ -116,4 +135,12 @@ const std::vector<MUCBookmark>& MUCBookmarkManager::getBookmarks() const {
return bookmarks_;
}
+boost::optional<MUCBookmark> MUCBookmarkManager::lookupBookmark(const JID& bookmarkJID) const {
+ auto bookmarkIterator = std::find_if(bookmarks_.begin(), bookmarks_.end(), [&](const MUCBookmark& val) { return bookmarkJID == val.getRoom(); });
+ if (bookmarkIterator != bookmarks_.end()) {
+ return *bookmarkIterator;
+ }
+ return boost::none;
+}
+
}
diff --git a/Swiften/MUC/MUCBookmarkManager.h b/Swiften/MUC/MUCBookmarkManager.h
index 78fbbb0..7f262da 100644
--- a/Swiften/MUC/MUCBookmarkManager.h
+++ b/Swiften/MUC/MUCBookmarkManager.h
@@ -27,8 +27,8 @@ namespace Swift {
void addBookmark(const MUCBookmark& bookmark);
void removeBookmark(const MUCBookmark& bookmark);
void replaceBookmark(const MUCBookmark& oldBookmark, const MUCBookmark& newBookmark);
-
const std::vector<MUCBookmark>& getBookmarks() const;
+ boost::optional<MUCBookmark> lookupBookmark(const JID& bookmarkJID) const;
public:
boost::signals2::signal<void (const MUCBookmark&)> onBookmarkAdded;
@@ -45,6 +45,7 @@ namespace Swift {
private:
bool ready_;
+ bool handlingReceivedBookmarks_;
std::vector<MUCBookmark> bookmarks_;
IQRouter* iqRouter_;
std::shared_ptr<Storage> storage;