summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Maudsley <richard.maudsley@isode.com>2014-07-11 14:03:57 (GMT)
committerSwift Review <review@swift.im>2014-07-27 14:09:54 (GMT)
commitfde89fee2175e7cbeda9262e7517f153de76e1b8 (patch)
tree9834c5d04a66c84fe50b1719e16c3749123fa8ff /Swift/Controllers
parent9353d3c692e1cd37bdd15b8dbe75b92be5eaa1c0 (diff)
downloadswift-fde89fee2175e7cbeda9262e7517f153de76e1b8.zip
swift-fde89fee2175e7cbeda9262e7517f153de76e1b8.tar.bz2
Fix recent chat items not being shown for private MUC messages.
Test-Information: Send private message and verify that the private message item in the recents list is erased when the user leaves the MUC and the chat window is closed. Check that other recent items are not removed. Check that private message recent items are not saved and loaded when the application is restarted. Change-Id: I62b9d324143d2e77ed98592cf37fb681165285c2
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp5
-rw-r--r--Swift/Controllers/Chat/ChatController.h4
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp4
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h2
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp56
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h4
-rw-r--r--Swift/Controllers/UIInterfaces/ChatListWindow.h7
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h1
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h1
9 files changed, 65 insertions, 19 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 9df7708..9b65c9f 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -95,6 +95,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
chatWindow_->onBlockUserRequest.connect(boost::bind(&ChatController::handleBlockUserRequest, this));
chatWindow_->onUnblockUserRequest.connect(boost::bind(&ChatController::handleUnblockUserRequest, this));
chatWindow_->onInviteToChat.connect(boost::bind(&ChatController::handleInviteToChat, this, _1));
+ chatWindow_->onClosed.connect(boost::bind(&ChatController::handleWindowClosed, this));
handleBareJIDCapsChanged(toJID_);
settings_->onSettingChanged.connect(boost::bind(&ChatController::handleSettingChanged, this, _1));
@@ -306,6 +307,10 @@ void ChatController::handleInviteToChat(const std::vector<JID>& droppedJIDs) {
eventStream_->send(event);
}
+void ChatController::handleWindowClosed() {
+ onWindowClosed();
+}
+
void ChatController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
boost::shared_ptr<InviteToMUCUIEvent> inviteEvent = boost::dynamic_pointer_cast<InviteToMUCUIEvent>(event);
if (inviteEvent && inviteEvent->getRoom() == toJID_.toBare()) {
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 8b1bb9a..2e92be7 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -79,8 +79,8 @@ namespace Swift {
void handleUnblockUserRequest();
void handleInviteToChat(const std::vector<JID>& droppedJIDs);
- void handleInviteToMUCWindowDismissed();
- void handleInviteToMUCWindowCompleted();
+
+ void handleWindowClosed();
void handleUIEvent(boost::shared_ptr<UIEvent> event);
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 5363e0c..24341e6 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -197,6 +197,10 @@ void ChatControllerBase::activateChatWindow() {
chatWindow_->activate();
}
+bool ChatControllerBase::hasOpenWindow() const {
+ return chatWindow_ && chatWindow_->isVisible();
+}
+
std::string ChatControllerBase::addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) {
if (boost::starts_with(message, "/me ")) {
return chatWindow_->addAction(chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index cf0a4d2..a0b848b 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -52,6 +52,7 @@ namespace Swift {
virtual ~ChatControllerBase();
void showChatWindow();
void activateChatWindow();
+ bool hasOpenWindow() const;
virtual void setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info);
void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);
std::string addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight);
@@ -62,6 +63,7 @@ namespace Swift {
/** Used for determining when something is recent.*/
boost::signal<void (const std::string& /*activity*/)> onActivity;
boost::signal<void ()> onUnreadCountChanged;
+ boost::signal<void ()> onWindowClosed;
int getUnreadCount();
const JID& getToJID() {return toJID_;}
void handleCapsChanged(const JID& jid);
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 8a077d1..3db1327 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -224,6 +224,15 @@ void ChatsManager::saveRecents() {
}
}
+ class RemoveRecent {
+ public:
+ static bool ifPrivateMessage(const ChatListWindow::Chat& chat) {
+ return chat.isPrivateMessage;
+ }
+ };
+
+ recentsLimited.erase(std::remove_if(recentsLimited.begin(), recentsLimited.end(), RemoveRecent::ifPrivateMessage), recentsLimited.end());
+
oa << recentsLimited;
std::string serializedStr = Base64::encode(createByteArray(serializeStream.str()));
profileSettings_->storeString(RECENT_CHATS, serializedStr);
@@ -310,7 +319,7 @@ void ChatsManager::loadRecents() {
StatusShow::Type type = StatusShow::None;
boost::filesystem::path path;
- ChatListWindow::Chat chat(jid, nickResolver_->jidToNick(jid), activity, 0, type, path, isMUC, nick);
+ ChatListWindow::Chat chat(jid, nickResolver_->jidToNick(jid), activity, 0, type, path, isMUC, false, nick);
chat = updateChatStatusAndAvatarHelper(chat);
prependRecent(chat);
}
@@ -368,7 +377,7 @@ void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) {
chatListWindow_->removeMUCBookmark(bookmark);
}
-ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity) {
+ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage) {
int unreadCount = 0;
if (mucRegistry_->isMUC(jid)) {
MUCController* controller = mucControllers_[jid.toBare()];
@@ -387,14 +396,14 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const
}
if (controller->isImpromptu()) {
- ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick, password);
+ ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, privateMessage, nick, password);
typedef std::pair<std::string, JID> StringJIDPair;
std::map<std::string, JID> participants = controller->getParticipantJIDs();
chat.impromptuJIDs = participants;
return chat;
}
}
- return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick, password);
+ return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, privateMessage, nick, password);
} else {
ChatController* controller = getChatControllerIfExists(jid, false);
if (controller) {
@@ -404,22 +413,24 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const
Presence::ref presence = presenceOracle_->getHighestPriorityPresence(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);
+ return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false, privateMessage);
}
}
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);
+ const bool privateMessage = mucRegistry_->isMUC(jid.toBare()) && !isMUC;
+ ChatListWindow::Chat chat = createChatListChatItem(jid, activity, privateMessage);
/* FIXME: handle nick changes */
appendRecent(chat);
handleUnreadCountChanged(NULL);
saveRecents();
}
+void ChatsManager::handleChatClosed(const JID& /*jid*/) {
+ cleanupPrivateMessageRecents();
+ chatListWindow_->setRecents(recentChats_);
+}
+
void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) {
int unreadTotal = 0;
bool controllerIsMUC = dynamic_cast<MUCController*>(controller);
@@ -454,6 +465,24 @@ boost::optional<ChatListWindow::Chat> ChatsManager::removeExistingChat(const Cha
}
}
+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_;
+ foreach (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);
+ if (!chatController || !chatController->hasOpenWindow()) {
+ removeExistingChat(chat);
+ break;
+ }
+ }
+ }
+ }
+}
+
void ChatsManager::appendRecent(const ChatListWindow::Chat& chat) {
boost::optional<ChatListWindow::Chat> oldChat = removeExistingChat(chat);
ChatListWindow::Chat mergedChat = chat;
@@ -479,15 +508,15 @@ void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
foreach (ChatListWindow::Chat& chat, recentChats_) {
if (chat.isMUC && chat.jid == (*it).first) {
chat.statusType = StatusShow::None;
- chatListWindow_->setRecents(recentChats_);
- break;
}
}
mucControllers_.erase(it);
delete mucController;
- return;
+ break;
}
}
+ cleanupPrivateMessageRecents();
+ chatListWindow_->setRecents(recentChats_);
}
void ChatsManager::handleSettingChanged(const std::string& settingPath) {
@@ -701,6 +730,7 @@ ChatController* ChatsManager::createNewChatController(const JID& contact) {
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));
controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
controller->onConvertToMUC.connect(boost::bind(&ChatsManager::handleTransformChatToMUC, this, controller, _1, _2, _3));
updatePresenceReceivingStateOnChatController(contact);
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 41435d9..179f536 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -89,7 +89,7 @@ namespace Swift {
};
private:
- ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity);
+ ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage);
void handleChatRequest(const std::string& contact);
void finalizeImpromptuJoin(MUC::ref muc, const std::vector<JID>& jidsToInvite, const std::string& reason, const boost::optional<JID>& reuseChatJID = boost::optional<JID>());
MUC::ref handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& password, const boost::optional<std::string>& nick, bool addAutoJoin, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow = 0);
@@ -103,10 +103,12 @@ namespace Swift {
void handleUserLeftMUC(MUCController* mucController);
void handleBookmarksReady();
void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC);
+ void handleChatClosed(const JID& jid);
void handleNewFileTransferController(FileTransferController*);
void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf);
void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state);
boost::optional<ChatListWindow::Chat> removeExistingChat(const ChatListWindow::Chat& chat);
+ void cleanupPrivateMessageRecents();
void appendRecent(const ChatListWindow::Chat& chat);
void prependRecent(const ChatListWindow::Chat& chat);
void setupBookmarks();
diff --git a/Swift/Controllers/UIInterfaces/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h
index 38d8c3e..f7eb151 100644
--- a/Swift/Controllers/UIInterfaces/ChatListWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h
@@ -21,9 +21,9 @@ namespace Swift {
public:
class Chat {
public:
- Chat() : statusType(StatusShow::None), isMUC(false), unreadCount(0) {}
- Chat(const JID& jid, const std::string& chatName, const std::string& activity, int unreadCount, StatusShow::Type statusType, const boost::filesystem::path& avatarPath, bool isMUC, const std::string& nick = "", const boost::optional<std::string> password = boost::optional<std::string>())
- : jid(jid), chatName(chatName), activity(activity), statusType(statusType), isMUC(isMUC), nick(nick), password(password), unreadCount(unreadCount), avatarPath(avatarPath) {}
+ Chat() : statusType(StatusShow::None), isMUC(false), unreadCount(0), isPrivateMessage(false) {}
+ Chat(const JID& jid, const std::string& chatName, const std::string& activity, int unreadCount, StatusShow::Type statusType, const boost::filesystem::path& avatarPath, bool isMUC, bool isPrivateMessage = false, const std::string& nick = "", const boost::optional<std::string> password = boost::optional<std::string>())
+ : jid(jid), chatName(chatName), activity(activity), statusType(statusType), isMUC(isMUC), nick(nick), password(password), unreadCount(unreadCount), avatarPath(avatarPath), isPrivateMessage(isPrivateMessage) {}
/** Assume that nicks and other transient features aren't important for equality */
bool operator==(const Chat& other) const {
if (impromptuJIDs.empty()) {
@@ -77,6 +77,7 @@ namespace Swift {
int unreadCount;
boost::filesystem::path avatarPath;
std::map<std::string, JID> impromptuJIDs;
+ bool isPrivateMessage;
};
virtual ~ChatListWindow();
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index bf4744b..81d26c8 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -130,6 +130,7 @@ namespace Swift {
virtual void setContactChatState(ChatState::ChatStateType state) = 0;
virtual void setName(const std::string& name) = 0;
virtual void show() = 0;
+ virtual bool isVisible() const = 0;
virtual void activate() = 0;
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;
virtual void setSecurityLabelsEnabled(bool enabled) = 0;
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 823ea3a..5e6606b 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -41,6 +41,7 @@ namespace Swift {
virtual void setContactChatState(ChatState::ChatStateType /*state*/) {}
virtual void setName(const std::string& name) {name_ = name;}
virtual void show() {}
+ virtual bool isVisible() const { return true; }
virtual void activate() {}
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) {labels_ = labels;}
virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;}