From dd6fe37580c5a0d9426312287cb4ed31116d8c4c Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Sat, 9 Jul 2011 14:45:46 +0100
Subject: Keep MUCs in the recent chats list.

Populate them with Available StatusShow::Type when they're joined, and None when they're not.

Resolves: #907

diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 0efbdfd..5173a6f 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -10,24 +10,25 @@
 #include <boost/algorithm/string.hpp>
 
 #include <Swiften/Base/foreach.h>
-#include "Swift/Controllers/Chat/ChatController.h"
-#include "Swift/Controllers/Chat/MUCSearchController.h"
-#include "Swift/Controllers/XMPPEvents/EventController.h"
-#include "Swift/Controllers/Chat/MUCController.h"
-#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
-#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
-#include "Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h"
-#include "Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h"
-#include "Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h"
-#include "Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h"
-#include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h"
-#include "Swift/Controllers/UIInterfaces/JoinMUCWindow.h"
-#include "Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h"
-#include "Swiften/Presence/PresenceSender.h"
-#include "Swiften/Client/NickResolver.h"
-#include "Swiften/MUC/MUCManager.h"
-#include "Swiften/Elements/ChatState.h"
-#include "Swiften/MUC/MUCBookmarkManager.h"
+#include <Swift/Controllers/Chat/ChatController.h>
+#include <Swift/Controllers/Chat/ChatControllerBase.h>
+#include <Swift/Controllers/Chat/MUCSearchController.h>
+#include <Swift/Controllers/XMPPEvents/EventController.h>
+#include <Swift/Controllers/Chat/MUCController.h>
+#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
+#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
+#include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h>
+#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h>
+#include <Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h>
+#include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h>
+#include <Swift/Controllers/UIInterfaces/ChatListWindowFactory.h>
+#include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h>
+#include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h>
+#include <Swiften/Presence/PresenceSender.h>
+#include <Swiften/Client/NickResolver.h>
+#include <Swiften/MUC/MUCManager.h>
+#include <Swiften/Elements/ChatState.h>
+#include <Swiften/MUC/MUCBookmarkManager.h>
 #include <Swift/Controllers/ProfileSettingsProvider.h>
 
 namespace Swift {
@@ -132,8 +133,16 @@ void ChatsManager::loadRecents() {
 		std::string activity(recent[1]);
 		bool isMUC = recent[2] == "true";
 		std::string nick(recent[3]);
-		Presence::ref presence = presenceOracle_->getHighestPriorityPresence(jid.toBare());
-		StatusShow::Type type = presence ? presence->getShow() : StatusShow::None;
+		StatusShow::Type type = StatusShow::None;
+		if (isMUC) {
+			if (mucControllers_.find(jid.toBare()) != mucControllers_.end()) {
+				type = StatusShow::Online;
+			}
+		} else {
+			Presence::ref presence = presenceOracle_->getHighestPriorityPresence(jid.toBare());
+			type = presence ? presence->getShow() : StatusShow::None;
+		}
+
 		ChatListWindow::Chat chat(jid, nickResolver_->jidToNick(jid), activity, 0, type, isMUC, nick);
 		prependRecent(chat);
 	}
@@ -175,30 +184,58 @@ void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) {
 
 ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity) {
 	int unreadCount = 0;
-	ChatController* controller = getChatControllerIfExists(jid, false);
-	if (controller) {
-		unreadCount = controller->getUnreadCount();
-	}
+	if (mucRegistry_->isMUC(jid)) {
+		MUCController* controller = mucControllers_[jid.toBare()];
+		StatusShow::Type type = StatusShow::None;
+		std::string nick = "";
+		if (controller) {
+			unreadCount = controller->getUnreadCount();
+			if (controller->isJoined()) {
+				type = StatusShow::Online;
+			}
+			nick = controller->getNick();
+		}
+		return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, true, nick);
+
+	} else {
+		ChatController* controller = getChatControllerIfExists(jid, false);
+		if (controller) {
+			unreadCount = controller->getUnreadCount();
+		}
 
-	Presence::ref presence = presenceOracle_->getHighestPriorityPresence(jid.toBare());
-	StatusShow::Type type = presence ? presence->getShow() : StatusShow::None;
-	return ChatListWindow::Chat(jid, nickResolver_->jidToNick(jid), activity, unreadCount, type, false);
+		Presence::ref presence = presenceOracle_->getHighestPriorityPresence(jid.toBare());
+		StatusShow::Type type = presence ? presence->getShow() : StatusShow::None;
+		return ChatListWindow::Chat(jid, nickResolver_->jidToNick(jid), activity, unreadCount, type, false);
+	}
 }
 
-void ChatsManager::handleChatActivity(const JID& jid, const std::string& activity) {
+void ChatsManager::handleChatActivity(const JID& jid, const std::string& activity, bool isMUC) {
+	if (mucRegistry_->isMUC(jid.toBare()) && !isMUC) {
+		/* Don't include PMs in MUC rooms.*/
+		return;
+	}
 	ChatListWindow::Chat chat = createChatListChatItem(jid, activity);
-	/* FIXME: MUC use requires changes here. */
-
 	/* FIXME: handle nick changes */
 	appendRecent(chat);
 	handleUnreadCountChanged(NULL);
 	saveRecents();
 }
 
-void ChatsManager::handleUnreadCountChanged(ChatController* controller) {
+void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) {
 	int unreadTotal = 0;
+	bool controllerIsMUC = dynamic_cast<MUCController*>(controller);
+	bool isPM = controller && !controllerIsMUC && mucRegistry_->isMUC(controller->getToJID().toBare());
 	foreach (ChatListWindow::Chat& chatItem, recentChats_) {
-		if (controller && chatItem.jid.toBare() == controller->getToJID().toBare()) {
+		bool match = false;
+		if (controller) {
+			/* Matching MUC item */
+			match |= chatItem.isMUC == controllerIsMUC && chatItem.jid.toBare() == controller->getToJID().toBare();
+			/* Matching PM */
+			match |= isPM &&  chatItem.jid == controller->getToJID();
+			/* Matching non-PM */
+			match |= !isPM && !controllerIsMUC && chatItem.jid.toBare() == controller->getToJID().toBare();
+		}
+		if (match) {
 			chatItem.setUnreadCount(controller->getUnreadCount());
 		}
 		unreadTotal += chatItem.unreadCount;
@@ -221,6 +258,11 @@ void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
 	std::map<JID, MUCController*>::iterator it;
 	for (it = mucControllers_.begin(); it != mucControllers_.end(); ++it) {
 		if ((*it).second == mucController) {
+			foreach (ChatListWindow::Chat& chat, recentChats_) {
+				if (chat.isMUC && chat.jid == (*it).first) {
+					chat.statusType = StatusShow::None;
+				}
+			}
 			mucControllers_.erase(it);
 			delete mucController;
 			return;
@@ -350,7 +392,7 @@ ChatController* ChatsManager::createNewChatController(const JID& contact) {
 	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_);
 	chatControllers_[contact] = controller;
 	controller->setAvailableServerFeatures(serverDiscoInfo_);
-	controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1));
+	controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false));
 	controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
 	return controller;
 }
@@ -413,10 +455,12 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional
 		mucControllers_[mucJID] = controller;
 		controller->setAvailableServerFeatures(serverDiscoInfo_);
 		controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
+		controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), _1, true));
+		controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+		handleChatActivity(mucJID.toBare(), "", true);
 	}
 
 	mucControllers_[mucJID]->showChatWindow();
-	/* FIXME: handleChatActivity connection for recents, and changes to that method.*/
 }
 
 void ChatsManager::handleSearchMUCRequest() {
@@ -458,7 +502,12 @@ void ChatsManager::handleMUCBookmarkActivated(const MUCBookmark& mucBookmark) {
 }
 
 void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
-	uiEventStream_->send(boost::make_shared<RequestChatUIEvent>(chat.jid));
+	if (chat.isMUC) {
+		uiEventStream_->send(boost::make_shared<JoinMUCUIEvent>(chat.jid, chat.nick));
+	}
+	else {
+		uiEventStream_->send(boost::make_shared<RequestChatUIEvent>(chat.jid));
+	}
 }
 
 
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index be6e575..a8dd599 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -23,6 +23,7 @@
 namespace Swift {
 	class EventController;
 	class ChatController;
+	class ChatControllerBase;
 	class MUCController;
 	class MUCManager;
 	class ChatWindowFactory;
@@ -51,9 +52,9 @@ namespace Swift {
 			void setOnline(bool enabled);
 			void setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info);
 			void handleIncomingMessage(boost::shared_ptr<Message> message);
-			ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity);
 
 		private:
+			ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity);
 			void handleChatRequest(const std::string& contact);
 			void handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& nick, bool addAutoJoin);
 			void handleSearchMUCRequest();
@@ -65,7 +66,7 @@ namespace Swift {
 			void handleMUCBookmarkRemoved(const MUCBookmark& bookmark);
 			void handleUserLeftMUC(MUCController* mucController);
 			void handleBookmarksReady();
-			void handleChatActivity(const JID& jid, const std::string& activity);
+			void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC);
 			void appendRecent(const ChatListWindow::Chat& chat);
 			void prependRecent(const ChatListWindow::Chat& chat);
 			void setupBookmarks();
@@ -74,7 +75,7 @@ namespace Swift {
 			void handleChatMadeRecent();
 			void handleMUCBookmarkActivated(const MUCBookmark&);
 			void handleRecentActivated(const ChatListWindow::Chat&);
-			void handleUnreadCountChanged(ChatController* controller);
+			void handleUnreadCountChanged(ChatControllerBase* controller);
 
 			ChatController* getChatControllerOrFindAnother(const JID &contact);
 			ChatController* createNewChatController(const JID &contact);
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index ac4689f..2ac6109 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -110,6 +110,14 @@ void MUCController::rejoin() {
 	}
 }
 
+bool MUCController::isJoined() {
+	return joined_;
+}
+
+const std::string& MUCController::getNick() {
+	return nick_;
+}
+
 void MUCController::handleJoinTimeoutTick() {
 	receivedActivity();
 	chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString()));
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 6b05a8e..b8972b1 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -49,6 +49,8 @@ namespace Swift {
 			static void appendToJoinParts(std::vector<NickJoinPart>& joinParts, const NickJoinPart& newEvent);
 			static std::string generateJoinPartString(const std::vector<NickJoinPart>& joinParts);
 			static std::string concatenateListOfNames(const std::vector<NickJoinPart>& joinParts);
+			bool isJoined();
+			const std::string& getNick();
 		
 		protected:
 			void preSendMessageRequest(boost::shared_ptr<Message> message);
-- 
cgit v0.10.2-6-g49f6