summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers/Chat/ChatsManager.cpp')
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp166
1 files changed, 130 insertions, 36 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 19400f9..6530a7e 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -28,18 +28,19 @@
#include <Swiften/Elements/MUCUserPayload.h>
#include <Swiften/MUC/MUCBookmarkManager.h>
#include <Swiften/MUC/MUCManager.h>
#include <Swiften/Presence/PresenceSender.h>
#include <Swiften/Roster/XMPPRoster.h>
#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/VCards/VCardManager.h>
#include <Swift/Controllers/Chat/AutoAcceptMUCInviteDecider.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/ChatController.h>
#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
#include <Swift/Controllers/Chat/MUCController.h>
#include <Swift/Controllers/Chat/MUCSearchController.h>
#include <Swift/Controllers/Chat/UserSearchController.h>
#include <Swift/Controllers/FileTransfer/FileTransferController.h>
#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
@@ -60,128 +61,139 @@
#include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h>
#include <Swift/Controllers/WhiteboardManager.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
namespace Swift {
typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
+#ifndef NOT_YET
#define RECENT_CHATS "recent_chats"
+#endif
ChatsManager::ChatsManager(
JID jid, StanzaChannel* stanzaChannel,
IQRouter* iqRouter,
EventController* eventController,
ChatWindowFactory* chatWindowFactory,
JoinMUCWindowFactory* joinMUCWindowFactory,
NickResolver* nickResolver,
PresenceOracle* presenceOracle,
PresenceSender* presenceSender,
UIEventStream* uiEventStream,
+#ifndef NOT_YET
ChatListWindowFactory* chatListWindowFactory,
+#endif
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) :
+ VCardManager* vcardManager,
+ Chattables& chattables) :
jid_(jid),
joinMUCWindowFactory_(joinMUCWindowFactory),
useDelayForLatency_(useDelayForLatency),
mucRegistry_(mucRegistry),
entityCapsProvider_(entityCapsProvider),
mucManager(mucManager),
ftOverview_(ftOverview),
roster_(roster),
eagleMode_(eagleMode),
settings_(settings),
historyController_(historyController),
whiteboardManager_(whiteboardManager),
highlightManager_(highlightManager),
emoticons_(emoticons),
clientBlockListManager_(clientBlockListManager),
- vcardManager_(vcardManager) {
+ vcardManager_(vcardManager),
+ chattables_(chattables) {
timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
iqRouter_ = iqRouter;
chatWindowFactory_ = chatWindowFactory;
nickResolver_ = nickResolver;
presenceOracle_ = presenceOracle;
avatarManager_ = nullptr;
serverDiscoInfo_ = std::make_shared<DiscoInfo>();
presenceSender_ = presenceSender;
uiEventStream_ = uiEventStream;
mucBookmarkManager_ = nullptr;
profileSettings_ = profileSettings;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatsManager::handlePresenceChange, this, _1));
uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1));
-
+#ifndef NOT_YET
chatListWindow_ = chatListWindowFactory->createChatListWindow(uiEventStream_);
chatListWindow_->onMUCBookmarkActivated.connect(boost::bind(&ChatsManager::handleMUCBookmarkActivated, this, _1));
chatListWindow_->onRecentActivated.connect(boost::bind(&ChatsManager::handleRecentActivated, this, _1));
chatListWindow_->onClearRecentsRequested.connect(boost::bind(&ChatsManager::handleClearRecentsRequested, this));
-
+#endif
joinMUCWindow_ = nullptr;
mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, profileSettings_);
mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));
ftOverview_->onNewFileTransferController.connect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1));
whiteboardManager_->onSessionRequest.connect(boost::bind(&ChatsManager::handleWhiteboardSessionRequest, this, _1, _2));
whiteboardManager_->onRequestAccepted.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardAccepted));
whiteboardManager_->onSessionTerminate.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardTerminated));
whiteboardManager_->onRequestRejected.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardRejected));
roster_->onJIDAdded.connect(boost::bind(&ChatsManager::handleJIDAddedToRoster, this, _1));
roster_->onJIDRemoved.connect(boost::bind(&ChatsManager::handleJIDRemovedFromRoster, this, _1));
roster_->onJIDUpdated.connect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
roster_->onRosterCleared.connect(boost::bind(&ChatsManager::handleRosterCleared, this));
+ chattables_.onActivated.connect(boost::bind(&ChatsManager::handleChattableActivated, this, _1));
+
settings_->onSettingChanged.connect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
userWantsReceipts_ = settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS);
setupBookmarks();
+#ifndef NOT_YET
loadRecents();
-
+#endif
autoAcceptMUCInviteDecider_ = new AutoAcceptMUCInviteDecider(jid.getDomain(), roster_, settings_);
}
ChatsManager::~ChatsManager() {
settings_->onSettingChanged.disconnect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
+ chattables_.onActivated.disconnect(boost::bind(&ChatsManager::handleChattableActivated, this, _1));
roster_->onJIDAdded.disconnect(boost::bind(&ChatsManager::handleJIDAddedToRoster, this, _1));
roster_->onJIDRemoved.disconnect(boost::bind(&ChatsManager::handleJIDRemovedFromRoster, this, _1));
roster_->onJIDUpdated.disconnect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
roster_->onRosterCleared.disconnect(boost::bind(&ChatsManager::handleRosterCleared, this));
ftOverview_->onNewFileTransferController.disconnect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1));
delete joinMUCWindow_;
SWIFT_LOG(debug) << "Destroying ChatsManager, containing " << chatControllers_.size() << " chats and " << mucControllers_.size() << " MUCs" << std::endl;
for (JIDChatControllerPair controllerPair : chatControllers_) {
delete controllerPair.second;
}
for (JIDMUCControllerPair controllerPair : mucControllers_) {
delete controllerPair.second;
}
delete mucBookmarkManager_;
delete mucSearchController_;
delete autoAcceptMUCInviteDecider_;
}
+#ifndef NOT_YET
void ChatsManager::saveRecents() {
std::stringstream serializeStream;
boost::archive::text_oarchive oa(serializeStream);
std::vector<ChatListWindow::Chat> recentsLimited = std::vector<ChatListWindow::Chat>(recentChats_.begin(), recentChats_.end());
if (recentsLimited.size() > 25) {
recentsLimited.erase(recentsLimited.begin() + 25, recentsLimited.end());
}
if (eagleMode_) {
for (ChatListWindow::Chat& chat : recentsLimited) {
@@ -202,18 +214,19 @@ void ChatsManager::saveRecents() {
std::string serializedStr = Base64::encode(createByteArray(serializeStream.str()));
profileSettings_->storeString(RECENT_CHATS, serializedStr);
}
void ChatsManager::handleClearRecentsRequested() {
recentChats_.clear();
saveRecents();
handleUnreadCountChanged(nullptr);
}
+#endif
void ChatsManager::handleJIDAddedToRoster(const JID &jid) {
updatePresenceReceivingStateOnChatController(jid);
}
void ChatsManager::handleJIDRemovedFromRoster(const JID &jid) {
updatePresenceReceivingStateOnChatController(jid);
}
@@ -236,18 +249,19 @@ void ChatsManager::updatePresenceReceivingStateOnChatController(const JID &jid)
if (!mucRegistry_->isMUC(jid.toBare())) {
RosterItemPayload::Subscription subscription = roster_->getSubscriptionStateForJID(jid);
controller->setContactIsReceivingPresence(subscription == RosterItemPayload::From || subscription == RosterItemPayload::Both);
} else {
controller->setContactIsReceivingPresence(true);
}
}
}
+#ifndef NOT_YET
ChatListWindow::Chat ChatsManager::updateChatStatusAndAvatarHelper(const ChatListWindow::Chat& chat) const {
ChatListWindow::Chat fixedChat = chat;
if (fixedChat.isMUC) {
if (mucControllers_.find(fixedChat.jid.toBare()) != mucControllers_.end()) {
fixedChat.statusType = StatusShow::Online;
}
} else {
if (avatarManager_) {
fixedChat.avatarPath = avatarManager_->getAvatarPath(fixedChat.jid);
@@ -303,55 +317,68 @@ void ChatsManager::loadRecents() {
recentChats.erase(std::remove(recentChats.begin(), recentChats.end(), ChatListWindow::Chat()), recentChats.end());
for (auto chat : recentChats) {
chat.statusType = StatusShow::None;
chat = updateChatStatusAndAvatarHelper(chat);
prependRecent(chat);
}
}
handleUnreadCountChanged(nullptr);
}
+#endif
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));
+#ifndef NOT_YET
if (chatListWindow_) {
chatListWindow_->setBookmarksEnabled(false);
chatListWindow_->clearBookmarks();
}
+#endif
}
}
void ChatsManager::handleBookmarksReady() {
+#ifndef NOT_YET
if (chatListWindow_) {
chatListWindow_->setBookmarksEnabled(true);
}
+#endif
}
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);
}
}
void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) {
+#ifndef NOT_YET
chatListWindow_->removeMUCBookmark(bookmark);
+#endif
}
+#ifndef NOT_YET
ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage) {
- int unreadCount = 0;
+ size_t unreadCount = 0;
if (mucRegistry_->isMUC(jid)) {
MUCController* controller = mucControllers_[jid.toBare()];
StatusShow::Type type = StatusShow::None;
std::string nick = "";
std::string password = "";
if (controller) {
unreadCount = controller->getUnreadCount();
if (controller->isJoined()) {
type = StatusShow::Online;
@@ -382,44 +409,51 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const
unreadCount = controller->getUnreadCount();
}
JID bareishJID = mucRegistry_->isMUC(jid.toBare()) ? jid : jid.toBare();
Presence::ref presence = presenceOracle_->getAccountPresence(bareishJID);
StatusShow::Type type = presence ? presence->getShow() : StatusShow::None;
boost::filesystem::path avatarPath = avatarManager_ ? avatarManager_->getAvatarPath(bareishJID) : boost::filesystem::path();
return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false, privateMessage);
}
}
+#endif
void ChatsManager::handleChatActivity(const JID& jid, const std::string& activity, bool isMUC) {
+#ifndef NOT_YET
const bool privateMessage = mucRegistry_->isMUC(jid.toBare()) && !isMUC;
ChatListWindow::Chat chat = createChatListChatItem(jid, activity, privateMessage);
/* FIXME: handle nick changes */
appendRecent(chat);
handleUnreadCountChanged(nullptr);
saveRecents();
// Look up potential MUC controller and update title accordingly as people
// join impromptu chats.
if (mucControllers_.find(jid) != mucControllers_.end()) {
auto chatListWindowIter = std::find_if(recentChats_.begin(), recentChats_.end(), [&](const ChatListWindow::Chat& chatListWindow) { return jid == (chatListWindow.jid); });
if (chatListWindowIter != recentChats_.end() && (mucControllers_[jid]->isImpromptu() || !chatListWindowIter->impromptuJIDs.empty())) {
mucControllers_[jid]->setChatWindowTitle(chatListWindowIter->getTitle());
}
}
+#endif
}
void ChatsManager::handleChatClosed(const JID& /*jid*/) {
cleanupPrivateMessageRecents();
+#ifndef NOT_YET
chatListWindow_->setRecents(recentChats_);
+#endif
}
+#ifndef NOT_YET
+
void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) {
- int unreadTotal = 0;
+ size_t unreadTotal = 0;
bool controllerIsMUC = dynamic_cast<MUCController*>(controller);
bool isPM = controller && !controllerIsMUC && mucRegistry_->isMUC(controller->getToJID().toBare());
for (ChatListWindow::Chat& chatItem : recentChats_) {
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();
@@ -439,19 +473,21 @@ boost::optional<ChatListWindow::Chat> ChatsManager::removeExistingChat(const Cha
std::list<ChatListWindow::Chat>::iterator result = std::find(recentChats_.begin(), recentChats_.end(), chat);
if (result != recentChats_.end()) {
ChatListWindow::Chat existingChat = *result;
recentChats_.erase(std::remove(recentChats_.begin(), recentChats_.end(), chat), recentChats_.end());
return boost::optional<ChatListWindow::Chat>(existingChat);
} else {
return boost::optional<ChatListWindow::Chat>();
}
}
+#endif
+#ifndef NOT_YET
void ChatsManager::cleanupPrivateMessageRecents() {
/* if we leave a MUC and close a PM, remove it's recent chat entry */
const std::list<ChatListWindow::Chat> chats = recentChats_;
for (const ChatListWindow::Chat& chat : chats) {
if (chat.isPrivateMessage) {
typedef std::map<JID, MUCController*> ControllerMap;
ControllerMap::iterator muc = mucControllers_.find(chat.jid.toBare());
if (muc == mucControllers_.end() || !muc->second->isJoined()) {
ChatController* chatController = getChatControllerIfExists(chat.jid);
@@ -477,35 +513,50 @@ void ChatsManager::appendRecent(const ChatListWindow::Chat& chat) {
void ChatsManager::prependRecent(const ChatListWindow::Chat& chat) {
boost::optional<ChatListWindow::Chat> oldChat = removeExistingChat(chat);
ChatListWindow::Chat mergedChat = chat;
if (oldChat) {
mergedChat.inviteesNames.insert(oldChat->inviteesNames.begin(), oldChat->inviteesNames.end());
mergedChat.impromptuJIDs.insert(oldChat->impromptuJIDs.begin(), oldChat->impromptuJIDs.end());
}
recentChats_.push_back(mergedChat);
}
+#endif
void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
std::map<JID, MUCController*>::iterator it;
for (it = mucControllers_.begin(); it != mucControllers_.end(); ++it) {
if ((*it).second == mucController) {
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (chat.isMUC && chat.jid == (*it).first) {
chat.statusType = StatusShow::None;
}
}
+#endif
+ const auto& jid = it->first;
+ 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;
}
}
cleanupPrivateMessageRecents();
+#ifndef NOT_YET
chatListWindow_->setRecents(recentChats_);
+#endif
}
void ChatsManager::handleSettingChanged(const std::string& settingPath) {
if (settingPath == SettingConstants::REQUEST_DELIVERYRECEIPTS.getKey()) {
userWantsReceipts_ = settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS);
return;
}
}
@@ -570,111 +621,118 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
assert(!localMUCServiceJID_.toString().empty());
// The room JID is random for new impromptu rooms, or a predefined JID for impromptu rooms resumed from the 'Recent chats' list.
JID roomJID = createImpromptuMUCEvent->getRoomJID().toString().empty() ? JID(idGenerator_.generateID(), localMUCServiceJID_) : createImpromptuMUCEvent->getRoomJID();
std::vector<JID> missingJIDsToInvite = createImpromptuMUCEvent->getJIDs();
for (const JID& jid : missingJIDsToInvite) {
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();
}
std::shared_ptr<EditMUCBookmarkUIEvent> editMUCBookmarkEvent = std::dynamic_pointer_cast<EditMUCBookmarkUIEvent>(event);
if (editMUCBookmarkEvent) {
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)) {
if (!joinMUCWindow_) {
joinMUCWindow_ = joinMUCWindowFactory_->createJoinMUCWindow(uiEventStream_);
joinMUCWindow_->onSearchMUC.connect(boost::bind(&ChatsManager::handleSearchMUCRequest, this));
}
joinMUCWindow_->setMUC(joinEvent->getRoom());
joinMUCWindow_->setNick(nickResolver_->jidToNick(jid_));
joinMUCWindow_->show();
}
}
+#ifndef NOT_YET
void ChatsManager::markAllRecentsOffline() {
for (ChatListWindow::Chat& chat : recentChats_) {
chat.setStatusType(StatusShow::None);
}
chatListWindow_->setRecents(recentChats_);
}
+#endif
void ChatsManager::handleTransformChatToMUC(ChatController* chatController, ChatWindow* chatWindow, const std::vector<JID>& jidsToInvite, const std::string& reason) {
JID reuseChatInvite = chatController->getToJID();
chatControllers_.erase(chatController->getToJID());
delete chatController;
// join new impromptu muc
assert(!localMUCServiceJID_.toString().empty());
// create new muc
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)));
}
/**
* If a resource goes offline, release bound chatdialog to that resource.
*/
void ChatsManager::handlePresenceChange(std::shared_ptr<Presence> newPresence) {
if (mucRegistry_->isMUC(newPresence->getFrom().toBare())) return;
-
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (newPresence->getFrom().toBare() == chat.jid.toBare() && !chat.isMUC) {
Presence::ref presence = presenceOracle_->getHighestPriorityPresence(chat.jid.toBare());
chat.setStatusType(presence ? presence->getShow() : StatusShow::None);
chatListWindow_->setRecents(recentChats_);
break;
}
}
-
+#endif
//if (newPresence->getType() != Presence::Unavailable) return;
+
JID fullJID(newPresence->getFrom());
std::map<JID, ChatController*>::iterator it = chatControllers_.find(fullJID);
if (it == chatControllers_.end()) return;
JID bareJID(fullJID.toBare());
//It doesn't make sense to have two unbound dialogs.
if (chatControllers_.find(bareJID) != chatControllers_.end()) return;
rebindControllerJID(fullJID, bareJID);
}
void ChatsManager::setAvatarManager(AvatarManager* avatarManager) {
if (avatarManager_) {
avatarManager_->onAvatarChanged.disconnect(boost::bind(&ChatsManager::handleAvatarChanged, this, _1));
}
avatarManager_ = avatarManager;
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (!chat.isMUC) {
chat.setAvatarPath(avatarManager_->getAvatarPath(chat.jid));
}
}
+#endif
avatarManager_->onAvatarChanged.connect(boost::bind(&ChatsManager::handleAvatarChanged, this, _1));
}
void ChatsManager::handleAvatarChanged(const JID& jid) {
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (!chat.isMUC && jid.toBare() == chat.jid.toBare()) {
chat.setAvatarPath(avatarManager_->getAvatarPath(jid));
break;
}
}
+#endif
}
void ChatsManager::setServerDiscoInfo(std::shared_ptr<DiscoInfo> info) {
serverDiscoInfo_ = info;
for (JIDChatControllerPair pair : chatControllers_) {
pair.second->setAvailableServerFeatures(info);
}
for (JIDMUCControllerPair pair : mucControllers_) {
pair.second->setAvailableServerFeatures(info);
@@ -699,22 +757,23 @@ void ChatsManager::setOnline(bool enabled) {
} else {
setupBookmarks();
localMUCServiceJID_ = JID();
localMUCServiceFinderWalker_ = std::make_shared<DiscoServiceWalker>(jid_.getDomain(), iqRouter_);
localMUCServiceFinderWalker_->onServiceFound.connect(boost::bind(&ChatsManager::handleLocalServiceFound, this, _1, _2));
localMUCServiceFinderWalker_->onWalkAborted.connect(boost::bind(&ChatsManager::handleLocalServiceWalkFinished, this));
localMUCServiceFinderWalker_->onWalkComplete.connect(boost::bind(&ChatsManager::handleLocalServiceWalkFinished, this));
localMUCServiceFinderWalker_->beginWalk();
}
-
+#ifndef NOT_YET
if (chatListWindow_) {
chatListWindow_->setBookmarksEnabled(enabled);
}
+#endif
}
void ChatsManager::handleChatRequest(const std::string &contact) {
ChatController* controller = getChatControllerOrFindAnother(JID(contact));
controller->activateChatWindow();
}
ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact) {
ChatController* controller = getChatControllerIfExists(contact);
@@ -726,24 +785,26 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact)
}
}
}
return controller ? controller : createNewChatController(contact);
}
ChatController* ChatsManager::createNewChatController(const JID& contact) {
assert(chatControllers_.find(contact) == chatControllers_.end());
std::shared_ptr<ChatMessageParser> chatMessageParser = std::make_shared<ChatMessageParser>(emoticons_, highlightManager_->getConfiguration(), ChatMessageParser::Mode::Chat); /* a message parser that knows this is a chat (not a room/MUC) */
- ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, timerFactory_, eventController_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, autoAcceptMUCInviteDecider_);
+ auto controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, timerFactory_, eventController_, entityCapsProvider_, userWantsReceipts_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, autoAcceptMUCInviteDecider_, settings_, chattables_);
chatControllers_[contact] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false));
controller->onWindowClosed.connect(boost::bind(&ChatsManager::handleChatClosed, this, contact));
+#ifndef NOT_YET
controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+#endif
controller->onConvertToMUC.connect(boost::bind(&ChatsManager::handleTransformChatToMUC, this, controller, _1, _2, _3));
updatePresenceReceivingStateOnChatController(contact);
controller->setCanStartImpromptuChats(!localMUCServiceJID_.toString().empty());
return controller;
}
ChatController* ChatsManager::getChatControllerOrCreate(const JID &contact) {
ChatController* controller = getChatControllerIfExists(contact);
return controller ? controller : createNewChatController(contact);
@@ -780,32 +841,20 @@ ChatController* ChatsManager::getChatControllerIfExists(const JID &contact, bool
return chatControllers_[contact];
}
void ChatsManager::rebindControllerJID(const JID& from, const JID& to) {
chatControllers_[to] = chatControllers_[from];
chatControllers_.erase(from);
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()) {
it->second->rejoin();
}
} else {
std::string nick = (nickMaybe && !(*nickMaybe).empty()) ? nickMaybe.get() : nickResolver_->jidToNick(jid_);
muc = mucManager->createMUC(mucJID);
if (createAsReservedIfNew) {
@@ -815,48 +864,72 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
muc->setCreateAsReservedIfNew();
}
MUCController* controller = nullptr;
SingleChatWindowFactoryAdapter* chatWindowFactoryAdapter = nullptr;
if (reuseChatwindow) {
chatWindowFactoryAdapter = new SingleChatWindowFactoryAdapter(reuseChatwindow);
}
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_);
+ 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
* are also deleted there.*/
chatWindowFactoryAdapters_[controller] = chatWindowFactoryAdapter;
}
mucControllers_[mucJID] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
controller->onUserJoined.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), "", true));
controller->onUserNicknameChanged.connect(boost::bind(&ChatsManager::handleUserNicknameChanged, this, controller, _1, _2));
controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), _1, true));
- controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+#ifndef NOT_YET
+ controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+#endif
if (!stanzaChannel_->isAvailable()) {
/* When online, the MUC is added to the registry in MUCImpl::internalJoin. This method is not
* called when Swift is offline, so we add it here as only MUCs in the registry are rejoined
* when going back online.
*/
mucRegistry_->addMUC(mucJID.toBare());
}
handleChatActivity(mucJID.toBare(), "", true);
}
-
+#ifndef NOT_YET
auto chatListWindowIter = std::find_if(recentChats_.begin(), recentChats_.end(), [&](const ChatListWindow::Chat& chatListWindow) { return mucJID == (chatListWindow.jid); });
if (chatListWindowIter != recentChats_.end() && (mucControllers_[mucJID]->isImpromptu() || !chatListWindowIter->impromptuJIDs.empty())) {
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;
}
void ChatsManager::handleSearchMUCRequest() {
mucSearchController_->openSearchWindow();
}
void ChatsManager::handleUserNicknameChanged(MUCController* mucController, const std::string& oldNickname, const std::string& newNickname) {
@@ -954,23 +1027,23 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> incomingMessag
MUCInvitationPayload::ref invite = message->getPayload<MUCInvitationPayload>();
if (invite && autoAcceptMUCInviteDecider_->isAutoAcceptedInvite(message->getFrom(), invite)) {
if (invite->getIsContinuation()) {
// check for existing chat controller for the from JID
ChatController* controller = getChatControllerIfExists(fromJID);
if (controller) {
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;
}
}
//if not a mucroom
if (!event->isReadable() && !isInvite && !isMediatedInvite) {
/* Only route such messages if a window exists, don't open new windows for them.*/
// Do not bind a controller to a full JID, for delivery receipts or chat state notifications.
@@ -1017,38 +1090,55 @@ void ChatsManager::handleWhiteboardStateChange(const JID& contact, const ChatWin
if (avatarManager_) {
path = avatarManager_->getAvatarPath(bareJID);
}
ChatListWindow::Chat chat(bareJID, nickResolver_->jidToNick(bareJID), "", 0, StatusShow::None, path, false);
chatListWindow_->addWhiteboardSession(chat);
} else {
chatListWindow_->removeWhiteboardSession(contact.toBare());
}
}
-
+#ifndef NOT_YET
void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
if (chat.isMUC && !chat.impromptuJIDs.empty()) {
typedef std::pair<std::string, JID> StringJIDPair;
std::vector<JID> inviteJIDs;
for (StringJIDPair pair : chat.impromptuJIDs) {
inviteJIDs.push_back(pair.second);
}
uiEventStream_->send(std::make_shared<CreateImpromptuMUCUIEvent>(inviteJIDs, chat.jid, ""));
}
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));
}
}
+#endif
+
+void ChatsManager::handleChattableActivated(const JID& jid) {
+ auto state = chattables_.getState(jid);
+ if (state.type == Chattables::State::Type::Person) {
+ uiEventStream_->send(std::make_shared<RequestChatUIEvent>(jid));
+ }
+ else if (state.type == Chattables::State::Type::Room) {
+ 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
+ }
+ }
+}
+
void ChatsManager::handleLocalServiceFound(const JID& service, std::shared_ptr<DiscoInfo> info) {
for (DiscoInfo::Identity identity : info->getIdentities()) {
if ((identity.getCategory() == "directory"
&& identity.getType() == "chatroom")
|| (identity.getCategory() == "conference"
&& identity.getType() == "text")) {
localMUCServiceJID_ = service;
localMUCServiceFinderWalker_->endWalk();
SWIFT_LOG(debug) << "Use following MUC service for impromptu chats: " << localMUCServiceJID_ << std::endl;
@@ -1062,29 +1152,33 @@ void ChatsManager::handleLocalServiceWalkFinished() {
for (JIDChatControllerPair controllerPair : chatControllers_) {
controllerPair.second->setCanStartImpromptuChats(impromptuMUCSupported);
}
for (JIDMUCControllerPair controllerPair : mucControllers_) {
controllerPair.second->setCanStartImpromptuChats(impromptuMUCSupported);
}
onImpromptuMUCServiceDiscovered(impromptuMUCSupported);
}
+#ifndef NOT_YET
std::vector<ChatListWindow::Chat> ChatsManager::getRecentChats() const {
return std::vector<ChatListWindow::Chat>(recentChats_.begin(), recentChats_.end());
}
+#endif
std::vector<Contact::ref> Swift::ChatsManager::getContacts(bool withMUCNicks) {
std::vector<Contact::ref> result;
+#ifndef NOT_YET
for (ChatListWindow::Chat chat : recentChats_) {
if (!chat.isMUC) {
result.push_back(std::make_shared<Contact>(chat.chatName.empty() ? chat.jid.toString() : chat.chatName, chat.jid, chat.statusType, chat.avatarPath));
}
}
+#endif
if (withMUCNicks) {
/* collect MUC nicks */
typedef std::map<JID, MUCController*>::value_type Item;
for (const Item& item : mucControllers_) {
JID mucJID = item.second->getToJID();
std::map<std::string, JID> participants = item.second->getParticipantJIDs();
typedef std::map<std::string, JID>::value_type ParticipantType;
for (const ParticipantType& participant : participants) {
const JID nickJID = JID(mucJID.getNode(), mucJID.getDomain(), participant.first);