From 0c6c79df29c58ff8790941ea40d40f84fae773c6 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Mon, 15 Nov 2010 13:15:15 +0000
Subject: Clean MUC joins slightly.

In an attempt to catch errors, this doesn't
Resolves: #691
but does add an assert that may help.
It also fixes an error with created rooms not receiving updates presences.
Release-Notes: Newly-created rooms will now receive your presence updates, consistent with existing rooms.

diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index e1a9adc..2fc5a43 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -39,16 +39,11 @@ ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRo
 	serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo());
 	presenceSender_ = presenceSender;
 	uiEventStream_ = uiEventStream;
-	mucBookmarkManager_ = new MUCBookmarkManager(iqRouter);
-	mucBookmarkManager_->onBookmarksReady.connect(boost::bind(&ChatsManager::handleBookmarksReady, this));
-	mucBookmarkManager_->onBookmarkAdded.connect(boost::bind(&ChatsManager::handleMUCBookmarkAdded, this, _1));
-	mucBookmarkManager_->onBookmarkRemoved.connect(boost::bind(&ChatsManager::handleMUCBookmarkRemoved, this, _1));
+	mucBookmarkManager_ = NULL;
 	presenceOracle_->onPresenceChange.connect(boost::bind(&ChatsManager::handlePresenceChange, this, _1));
 	uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1));
 	chatListWindow_ = chatListWindowFactory->createWindow(uiEventStream_);
-	if (chatListWindow_) {
-		chatListWindow_->setBookmarksEnabled(false);
-	}
+	setupBookmarks();
 }
 
 ChatsManager::~ChatsManager() {
@@ -61,6 +56,20 @@ ChatsManager::~ChatsManager() {
 	delete mucBookmarkManager_;
 }
 
+void ChatsManager::setupBookmarks() {
+	if (!mucBookmarkManager_) {
+		mucBookmarkManager_ = new MUCBookmarkManager(iqRouter_);
+		mucBookmarkManager_->onBookmarksReady.connect(boost::bind(&ChatsManager::handleBookmarksReady, this));
+		mucBookmarkManager_->onBookmarkAdded.connect(boost::bind(&ChatsManager::handleMUCBookmarkAdded, this, _1));
+		mucBookmarkManager_->onBookmarkRemoved.connect(boost::bind(&ChatsManager::handleMUCBookmarkRemoved, this, _1));
+
+		if (chatListWindow_) {
+			chatListWindow_->setBookmarksEnabled(false);
+			chatListWindow_->clear();
+		}
+	}
+}
+
 void ChatsManager::handleBookmarksReady() {
 	if (chatListWindow_) {
 		chatListWindow_->setBookmarksEnabled(true);
@@ -161,7 +170,14 @@ void ChatsManager::setOnline(bool enabled) {
 			controllerPair.second->rejoin();
 		}
 	}
-	chatListWindow_->setBookmarksEnabled(enabled);
+	if (!enabled) {
+		delete mucBookmarkManager_;
+		mucBookmarkManager_ = NULL;
+		chatListWindow_->setBookmarksEnabled(false);
+	} else {
+		setupBookmarks();
+	}
+
 }
 
 void ChatsManager::handleChatRequest(const String &contact) {
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 6dab532..2b771eb 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -56,6 +56,7 @@ namespace Swift {
 			void handleMUCBookmarkRemoved(const MUCBookmark& bookmark);
 			void handleUserLeftMUC(MUCController* mucController);
 			void handleBookmarksReady();
+			void setupBookmarks();
 			ChatController* getChatControllerOrFindAnother(const JID &contact);
 			ChatController* createNewChatController(const JID &contact);
 			ChatController* getChatControllerOrCreate(const JID &contact);
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 6ac6a0c..975a2d2 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -284,6 +284,7 @@ String MUCController::roleToGroupName(MUCOccupant::Role role) {
 void MUCController::setOnline(bool online) {
 	ChatControllerBase::setOnline(online);
 	if (!online) {
+		muc_->part();
 		parting_ = true;
 		processUserPart();
 	} else {
diff --git a/Swift/Controllers/UIInterfaces/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h
index 3a7c30e..a2a0874 100644
--- a/Swift/Controllers/UIInterfaces/ChatListWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h
@@ -18,5 +18,6 @@ namespace Swift {
 			virtual void setBookmarksEnabled(bool enabled) = 0;
 			virtual void addMUCBookmark(const MUCBookmark& bookmark) = 0;
 			virtual void removeMUCBookmark(const MUCBookmark& bookmark) = 0;
+			virtual void clear() = 0;
 	};
 }
diff --git a/Swift/QtUI/ChatList/ChatListGroupItem.h b/Swift/QtUI/ChatList/ChatListGroupItem.h
index 389410a..cc4d4af 100644
--- a/Swift/QtUI/ChatList/ChatListGroupItem.h
+++ b/Swift/QtUI/ChatList/ChatListGroupItem.h
@@ -20,6 +20,7 @@ namespace Swift {
 			ChatListItem* item(int i) {return items_[i];};
 			int row(ChatListItem* item) {return items_.indexOf(item);};
 			QVariant data(int role) const {return (role == Qt::DisplayRole) ? name_ : QVariant();};
+			void clear() {items_.clear();};
 		private:
 			static bool pointerItemLessThan(const ChatListItem* first, const ChatListItem* second) {
 				QString myName = first->data(Qt::DisplayRole).toString().toLower();
diff --git a/Swift/QtUI/ChatList/ChatListModel.cpp b/Swift/QtUI/ChatList/ChatListModel.cpp
index 50a6ad3..39b6a3c 100644
--- a/Swift/QtUI/ChatList/ChatListModel.cpp
+++ b/Swift/QtUI/ChatList/ChatListModel.cpp
@@ -16,6 +16,12 @@ ChatListModel::ChatListModel() {
 	root_->addItem(mucBookmarks_);
 }
 
+void ChatListModel::clear() {
+	emit layoutAboutToBeChanged();
+	mucBookmarks_->clear();
+	emit layoutChanged();
+}
+
 void ChatListModel::addMUCBookmark(const Swift::MUCBookmark& bookmark) {
 	emit layoutAboutToBeChanged();
 	mucBookmarks_->addItem(new ChatListMUCItem(bookmark, mucBookmarks_));
diff --git a/Swift/QtUI/ChatList/ChatListModel.h b/Swift/QtUI/ChatList/ChatListModel.h
index 05fa60b..adde148 100644
--- a/Swift/QtUI/ChatList/ChatListModel.h
+++ b/Swift/QtUI/ChatList/ChatListModel.h
@@ -28,6 +28,7 @@ namespace Swift {
 			QModelIndex parent(const QModelIndex& index) const;
 			int rowCount(const QModelIndex& parent = QModelIndex()) const;
 			ChatListItem* getItemForIndex(const QModelIndex& index) const;
+			void clear();
 		private:
 			ChatListGroupItem* mucBookmarks_;
 			ChatListGroupItem* root_;
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp
index 887d9a4..48ccf7f 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.cpp
+++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp
@@ -79,6 +79,10 @@ void QtChatListWindow::handleItemActivated(const QModelIndex& index) {
 	}
 }
 
+void QtChatListWindow::clear() {
+	model_->clear();
+}
+
 void QtChatListWindow::addMUCBookmark(const MUCBookmark& bookmark) {
 	model_->addMUCBookmark(bookmark);
 }
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h
index 2c13300..b389474 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.h
+++ b/Swift/QtUI/ChatList/QtChatListWindow.h
@@ -24,6 +24,7 @@ namespace Swift {
 			void addMUCBookmark(const MUCBookmark& bookmark);
 			void removeMUCBookmark(const MUCBookmark& bookmark);
 			void setBookmarksEnabled(bool enabled);
+			void clear();
 		private slots:
 			void handleItemActivated(const QModelIndex&);
 			void handleAddBookmark();
diff --git a/Swiften/Elements/ErrorPayload.h b/Swiften/Elements/ErrorPayload.h
index 8c74f0c..fab398e 100644
--- a/Swiften/Elements/ErrorPayload.h
+++ b/Swiften/Elements/ErrorPayload.h
@@ -41,6 +41,10 @@ namespace Swift {
 
 			ErrorPayload(Condition condition = UndefinedCondition, Type type = Cancel, const String& text = String()) : type_(type), condition_(condition), text_(text) { }
 
+			ErrorPayload(const ErrorPayload& other) : type_(other.getType()), condition_(other.getCondition()), text_(other.getText()) {
+
+			}
+
 			Type getType() const {
 				return type_; 
 			}
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index b0365d4..86c8ca9 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -15,9 +15,9 @@
 #include "Swiften/Elements/Form.h"
 #include "Swiften/Elements/IQ.h"
 #include "Swiften/Elements/MUCUserPayload.h"
-#include "Swiften/Elements/MUCOwnerPayload.h"
 #include "Swiften/Elements/MUCPayload.h"
 #include "Swiften/MUC/MUCRegistry.h"
+#include "Swiften/Queries/GenericRequest.h"
 
 namespace Swift {
 
@@ -44,6 +44,7 @@ void MUC::internalJoin(const String &nick) {
 	joinComplete_ = false;
 	ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick);
 	boost::shared_ptr<Presence> joinPresence(presenceSender->getLastSentUndirectedPresence());
+	assert(joinPresence->getType() == Presence::Available);
 	joinPresence->setTo(ownMUCJID);
 	boost::shared_ptr<MUCPayload> mucPayload(new MUCPayload());
 	if (joinSince_ != boost::posix_time::not_a_date_time) {
@@ -162,16 +163,28 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
 			if (status.code == 201) {
 				/* Room is created and locked */
 				/* Currently deal with this by making an instant room */
+				ownMUCJID = presence->getFrom();
 				boost::shared_ptr<MUCOwnerPayload> mucPayload(new MUCOwnerPayload());
 				mucPayload->setPayload(boost::shared_ptr<Payload>(new Form(Form::SubmitType)));
-				boost::shared_ptr<IQ> iq(IQ::createRequest(IQ::Set, getJID(), iqRouter_->getNewIQID(), mucPayload));
-				iqRouter_->sendIQ(iq);
+				GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_);
+				request->onResponse.connect(boost::bind(&MUC::handleCreationConfigResponse, this, _1, _2));
+				request->send();
 			}
 		}
 	}
 
 }
 
+void MUC::handleCreationConfigResponse(boost::shared_ptr<MUCOwnerPayload> /*unused*/, const boost::optional<ErrorPayload>& error) {
+	if (error) {
+		boost::shared_ptr<ErrorPayload> errorCopy(new ErrorPayload(*error));
+		onJoinFailed(errorCopy);
+	} else {
+		/* onJoinComplete(getOwnNick()); isn't needed here, the presence will cause an emit elsewhere. */
+		presenceSender->addDirectedPresenceReceiver(ownMUCJID);
+	}
+}
+
 //FIXME: Recognise Topic changes
 
 //TODO: Invites(direct/mediated)
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 672cdf2..3539e49 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -12,6 +12,7 @@
 #include "Swiften/Elements/Presence.h"
 #include "Swiften/MUC/MUCOccupant.h"
 #include "Swiften/MUC/MUCRegistry.h"
+#include "Swiften/Elements/MUCOwnerPayload.h"
 
 #include <boost/shared_ptr.hpp>
 #include "Swiften/Base/boost_bsignals.h"
@@ -75,6 +76,7 @@ namespace Swift {
 		private:
 			void handleIncomingPresence(boost::shared_ptr<Presence> presence);
 			void internalJoin(const String& nick);
+			void handleCreationConfigResponse(boost::shared_ptr<MUCOwnerPayload>, const boost::optional<ErrorPayload>&);
 
 		private:
 			JID ownMUCJID;
-- 
cgit v0.10.2-6-g49f6