From 8dae4c265e75e93ce3691ea1143e314f2fa84d93 Mon Sep 17 00:00:00 2001
From: Alexei Arabadji <aarabadji@productengine.com>
Date: Thu, 29 Apr 2010 15:35:44 +0300
Subject: [PATCH] fixed EXT-6736 Notecard floater missing Keep/Discard Buttons
 (vwr 2.0) Added functionality to close hidden IM toasts when IM floater
 opens.

reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/321/

--HG--
branch : product-engine
---
 indra/newview/llchannelmanager.cpp | 16 ++++++++++++++++
 indra/newview/llchannelmanager.h   |  5 +++++
 indra/newview/llimfloater.cpp      | 23 +++++++++++++++++++++++
 indra/newview/llimfloater.h        |  2 ++
 indra/newview/llscreenchannel.cpp  | 25 +++++++++++++++++++++++++
 indra/newview/llscreenchannel.h    |  6 ++++++
 6 files changed, 77 insertions(+)

diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index 4f9434030f0..fafa315a59d 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -243,3 +243,19 @@ void LLChannelManager::killToastsFromChannel(const LLUUID& channel_id, const LLS
 	}
 }
 
+// static
+LLNotificationsUI::LLScreenChannel* LLChannelManager::getNotificationScreenChannel()
+{
+	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
+	(LLNotificationsUI::LLChannelManager::getInstance()->
+										findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+
+	if (channel == NULL)
+	{
+		llwarns << "Can't find screen channel by NotificationChannelUUID" << llendl;
+		llassert(!"Can't find screen channel by NotificationChannelUUID");
+	}
+
+	return channel;
+}
+
diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h
index c2be39122f4..8c725f26609 100644
--- a/indra/newview/llchannelmanager.h
+++ b/indra/newview/llchannelmanager.h
@@ -114,6 +114,11 @@ class LLChannelManager : public LLSingleton<LLChannelManager>
 	 */
 	void killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher);
 
+	/**
+	 * Returns notification screen channel.
+	 */
+	static LLNotificationsUI::LLScreenChannel* getNotificationScreenChannel();
+
 private:
 
 	LLScreenChannel* createChannel(LLChannelManager::Params& p);
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 19dbc564d17..c0cc3f19859 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -53,6 +53,7 @@
 #include "llsyswellwindow.h"
 #include "lltrans.h"
 #include "llchathistory.h"
+#include "llnotifications.h"
 #include "llviewerwindow.h"
 #include "llvoicechannel.h"
 #include "lltransientfloatermgr.h"
@@ -371,6 +372,8 @@ void LLIMFloater::onSlide()
 //static
 LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
 {
+	closeHiddenIMToasts();
+
 	if (!gIMMgr->hasSession(session_id)) return NULL;
 
 	if(!isChatMultiTab())
@@ -1083,6 +1086,26 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
 	}
 }
 
+// static
+void LLIMFloater::closeHiddenIMToasts()
+{
+	class IMToastMatcher: public LLNotificationsUI::LLScreenChannel::Matcher
+	{
+	public:
+		bool matches(const LLNotificationPtr notification) const
+		{
+			// "notifytoast" type of notifications is reserved for IM notifications
+			return "notifytoast" == notification->getType();
+		}
+	};
+
+	LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();
+	if (channel != NULL)
+	{
+		channel->closeHiddenToasts(IMToastMatcher());
+	}
+}
+
 // static
 bool LLIMFloater::isChatMultiTab()
 {
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 763dd5655ba..f9dd8b9b852 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -148,6 +148,8 @@ class LLIMFloater : public LLTransientDockableFloater
 	// Remove the "User is typing..." indicator.
 	void removeTypingIndicator(const LLIMInfo* im_info = NULL);
 
+	static void closeHiddenIMToasts();
+
 	LLPanelChatControlPanel* mControlPanel;
 	LLUUID mSessionID;
 	S32 mLastMessageIndex;
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index af440a36891..de1da248c12 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -706,6 +706,31 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id)
 	}
 }
 
+void LLScreenChannel::closeHiddenToasts(const Matcher& matcher)
+{
+	// since we can't guarantee that close toast operation doesn't change mToastList
+	// we collect matched toasts that should be closed into separate list
+	std::list<ToastElem> toasts;
+	for (std::vector<ToastElem>::iterator it = mToastList.begin(); it
+			!= mToastList.end(); it++)
+	{
+		LLToast * toast = it->toast;
+		// add to list valid toast that match to provided matcher criteria
+		if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL
+				&& !toast->getVisible() && matcher.matches(toast->getNotification()))
+		{
+			toasts.push_back(*it);
+		}
+	}
+
+	// close collected toasts
+	for (std::list<ToastElem>::iterator it = toasts.begin(); it
+			!= toasts.end(); it++)
+	{
+		it->toast->closeFloater();
+	}
+}
+
 //--------------------------------------------------------------------------
 void LLScreenChannel::removeToastsFromChannel()
 {
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index 88053d87d9d..46c5fed7b69 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -173,6 +173,12 @@ class LLScreenChannel : public LLScreenChannelBase
 	void		hideToastsFromScreen();
 	// hide toast by notification id
 	void		hideToast(const LLUUID& notification_id);
+
+	/**
+	 * Closes hidden matched toasts from channel.
+	 */
+	void closeHiddenToasts(const Matcher& matcher);
+
 	// removes all toasts from a channel
 	void		removeToastsFromChannel();
 	// show all toasts in a channel
-- 
GitLab