summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
@@ -380,3 +380,3 @@ void ChatControllerBase::handleMUCInvitation(Message::ref message) {
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 {
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
@@ -355,5 +355,7 @@ void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) {
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);
@@ -536,2 +538,8 @@ void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
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);
@@ -621,3 +629,3 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
// 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>()));
@@ -631,3 +639,3 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
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();
@@ -667,3 +675,3 @@ void ChatsManager::handleTransformChatToMUC(ChatController* chatController, Chat
// 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)));
@@ -841,16 +849,4 @@ void ChatsManager::rebindControllerJID(const JID& from, const JID& 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);
@@ -877,2 +873,6 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
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) {
@@ -908,2 +908,20 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
#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();
@@ -1017,3 +1035,3 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> incomingMessag
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;
@@ -1021,3 +1039,3 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> incomingMessag
} 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;
@@ -1093,3 +1111,3 @@ void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
/* 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));
}
@@ -1108,4 +1126,8 @@ void ChatsManager::handleChattableActivated(const JID& 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
@@ -96,3 +96,3 @@ namespace Swift {
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();
@@ -154,2 +154,5 @@ namespace Swift {
+ protected:
+ MUCBookmarkManager* mucBookmarkManager_;
+
private:
@@ -169,3 +172,2 @@ namespace Swift {
UIEventStream* uiEventStream_;
- MUCBookmarkManager* mucBookmarkManager_;
std::shared_ptr<DiscoInfo> serverDiscoInfo_;
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
@@ -38,2 +38,3 @@
#include <Swift/Controllers/Chat/ChatMessageParser.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Highlighting/Highlighter.h>
@@ -62,13 +63,2 @@ namespace Swift {
-class MUCBookmarkPredicate {
- public:
- MUCBookmarkPredicate(const JID& mucJID) : roomJID_(mucJID) { }
- bool operator()(const MUCBookmark& operand) {
- return operand.getRoom() == roomJID_;
- }
-
- private:
- JID roomJID_;
-};
-
/**
@@ -176,10 +166,3 @@ MUCController::MUCController (
- 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()));
}
@@ -500,2 +483,3 @@ void MUCController::setAvailableRoomActions(const MUCOccupant::Affiliation& affi
}
+ 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
@@ -40,2 +40,3 @@
#include <Swiften/MUC/UnitTest/MockMUC.h>
+#include <Swiften/MUC/MUCBookmarkManager.h>
#include <Swiften/Network/DummyTimerFactory.h>
@@ -60,2 +61,3 @@
#include <Swift/Controllers/Settings/DummySettingsProvider.h>
+#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIEvents/CreateImpromptuMUCUIEvent.h>
@@ -109,2 +111,12 @@ class DummyNotifier : public Notifier {
+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_;
+ }
+};
+
@@ -164,2 +176,5 @@ class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testReceivingBookmarksWithFullJID);
+ CPPUNIT_TEST(testAutoJoinBookmarksAndChattables);
+ CPPUNIT_TEST(testJoinNoAutojoinBookmark);
+ CPPUNIT_TEST(testJoinAndBookmarkMUC);
@@ -211,3 +226,3 @@ public:
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_);
@@ -1634,13 +1649,3 @@ public:
- 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);
@@ -1654,2 +1659,14 @@ public:
+ 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(
@@ -1658,3 +1675,3 @@ public:
bookmarkRequest->getID(),
- std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("montague.lit"))
+ std::make_shared<PrivateStorage>(createBookmarkStorageWithJID(bookmarkRequest, "montague.lit", true))
);
@@ -1665,13 +1682,35 @@ public:
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);
@@ -1681,18 +1720,46 @@ public:
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(
@@ -1701,5 +1768,31 @@ public:
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());
+ }
}
@@ -1730,3 +1823,3 @@ private:
std::unique_ptr<DummyNotifier> notifier_;
- ChatsManager* manager_;
+ ExtendedChatsManager* manager_;
DummyStanzaChannel* stanzaChannel_;
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
@@ -21,3 +21,3 @@ namespace Swift {
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_;}
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
@@ -143,3 +143,3 @@ namespace Swift {
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 {
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
@@ -88,3 +88,2 @@ 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()));
@@ -92,3 +91,2 @@ void QtChatListWindow::setupContextMenus() {
emptyMenu_ = new QMenu();
- onlineOnlyActions_ << emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
}
@@ -148,18 +146,2 @@ void QtChatListWindow::handleRemoveBookmark() {
-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() {
@@ -210,7 +192,4 @@ void QtChatListWindow::contextMenuEvent(QContextMenuEvent* event) {
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()));
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
@@ -37,6 +37,4 @@ namespace Swift {
void handleItemActivated(const QModelIndex&);
- void handleAddBookmark();
void handleEditBookmark();
void handleRemoveBookmark();
- void handleAddBookmarkFromRecents();
void handleClicked(const QModelIndex& index);
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
@@ -44,3 +44,3 @@ boost::optional<MUCBookmark> QtBookmarkDetailWindow::createBookmarkFromForm() {
std::string password(Q2PSTRING(password_->text()));
- bookmark.setAutojoin(autojoin_->isChecked());
+ bookmark.setAutojoin(true);
if (!nick.empty()) {
@@ -70,8 +70,2 @@ void QtBookmarkDetailWindow::createFormFromBookmark(const MUCBookmark& bookmark)
}
-
- 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
@@ -84,25 +84,2 @@
</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>
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
@@ -753,2 +753,3 @@ void QtChatWindow::handleActionButtonClicked() {
QAction* invite = nullptr;
+ QAction* leave = nullptr;
@@ -806,2 +807,6 @@ void QtChatWindow::handleActionButtonClicked() {
break;
+ case ChatWindow::Leave:
+ leave = contextMenu.addAction(tr("Leave room"));
+ leave->setEnabled(isOnline_);
+ break;
}
@@ -857,2 +862,5 @@ void QtChatWindow::handleActionButtonClicked() {
}
+ else if (result == leave) {
+ close();
+ }
else if (result == block) {
@@ -890,10 +898,12 @@ 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
}
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
@@ -14,3 +14,2 @@ QtEditBookmarkWindow::QtEditBookmarkWindow(UIEventStream* eventStream, const MUC
room_->setText(P2QSTRING(bookmark.getRoom().toString()));
- autojoin_->setChecked(bookmark.getAutojoin());
nick_->setText(bookmark.getNick() ? P2QSTRING(bookmark.getNick().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
@@ -51,3 +51,3 @@ void QtJoinMUCWindow::handleJoin() {
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
@@ -103,9 +103,2 @@
<item>
- <widget class="QCheckBox" name="joinAutomatically">
- <property name="text">
- <string>Enter automatically in future</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="QPushButton" name="joinButton">
@@ -126,3 +119,2 @@
<tabstop>instantRoom</tabstop>
- <tabstop>joinAutomatically</tabstop>
<tabstop>joinButton</tabstop>
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
@@ -329,3 +329,3 @@ void QtPlainChatView::acceptMUCInvite()
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
@@ -813,3 +813,3 @@ void QtWebKitChatView::handleHTMLButtonClicked(QString id, QString encodedArgume
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);
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
@@ -8,2 +8,3 @@
+#include <algorithm>
#include <memory>
@@ -32,2 +33,3 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
ready_ = true;
+ handlingReceivedBookmarks_ = true;
onBookmarksReady();
@@ -49,3 +51,3 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
}
-
+ std::vector<MUCBookmark> newAddedBookmarksToBeSignaled;
for (const auto& newBookmark : receivedBookmarks) {
@@ -53,3 +55,5 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
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);
}
@@ -57,2 +61,7 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
bookmarks_ = newBookmarks;
+ for (auto bookmark : newAddedBookmarksToBeSignaled) {
+ onBookmarkAdded(bookmark);
+ }
+
+ handlingReceivedBookmarks_ = false;
}
@@ -60,3 +69,3 @@ void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payloa
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();
}
@@ -78,4 +87,11 @@ 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();
@@ -98,2 +114,5 @@ void MUCBookmarkManager::removeBookmark(const MUCBookmark& bookmark) {
void MUCBookmarkManager::flush() {
+ if (handlingReceivedBookmarks_) {
+ return;
+ }
if (!storage) {
@@ -118,2 +137,10 @@ const std::vector<MUCBookmark>& MUCBookmarkManager::getBookmarks() const {
+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
@@ -29,4 +29,4 @@ namespace Swift {
void replaceBookmark(const MUCBookmark& oldBookmark, const MUCBookmark& newBookmark);
-
const std::vector<MUCBookmark>& getBookmarks() const;
+ boost::optional<MUCBookmark> lookupBookmark(const JID& bookmarkJID) const;
@@ -47,2 +47,3 @@ namespace Swift {
bool ready_;
+ bool handlingReceivedBookmarks_;
std::vector<MUCBookmark> bookmarks_;