From c2afd200a0d55c5137de6f89200a8d4b09ba8b6e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 30 Mar 2012 18:36:43 -0700
Subject: [PATCH] CHUI-51 WIP notifications routing code cleanup object
 inventory offers don't increment system menu count added customizable merging
 behavior for duplicate "unique" notifications fixed overeager notification
 channels

---
 indra/llui/llnotifications.cpp              | 43 ++++++++++++---------
 indra/llui/llnotifications.h                |  8 ++++
 indra/llui/llnotificationtemplate.h         | 14 +++++++
 indra/newview/llchiclet.cpp                 | 10 ++++-
 indra/newview/llnotificationhandler.h       | 33 ++++++++--------
 indra/newview/llnotificationhinthandler.cpp |  2 +-
 indra/newview/llscreenchannel.cpp           |  9 ++++-
 7 files changed, 80 insertions(+), 39 deletions(-)

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index c45899a4bd7..79135d2c609 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -246,7 +246,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
 	LLParamSDParser parser;
 	parser.writeSD(mFormData, p.form_elements);
 
-	if (!mFormData.isArray())
+	if (!mFormData.isArray() && !mFormData.isUndefined())
 	{
 		// change existing contents to a one element array
 		LLSD new_llsd_array = LLSD::emptyArray();
@@ -407,6 +407,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
 	mURLOption(p.url.option),
 	mURLTarget(p.url.target),
 	mUnique(p.unique.isProvided()),
+	mCombineBehavior(p.unique.combine),
 	mPriority(p.priority),
 	mPersist(p.persist),
 	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()),
@@ -903,6 +904,10 @@ bool LLNotification::hasFormElements() const
 	return mTemplatep->mForm->getNumElements() != 0;
 }
 
+LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const
+{
+	return mTemplatep->mCombineBehavior;
+}
 
 
 
@@ -1242,22 +1247,25 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)
 		return false;
 	}
 
-	// Update the existing unique notification with the data from this particular instance...
-	// This guarantees that duplicate notifications will be collapsed to the one
-	// most recently triggered
-	for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
-		existing_it != mUniqueNotifications.end();
-		++existing_it)
+	if (pNotif->getCombineBehavior() == LLNotification::USE_NEWEST)
 	{
-		LLNotificationPtr existing_notification = existing_it->second;
-		if (pNotif != existing_notification 
-			&& pNotif->isEquivalentTo(existing_notification))
+		// Update the existing unique notification with the data from this particular instance...
+		// This guarantees that duplicate notifications will be collapsed to the one
+		// most recently triggered
+		for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
+			existing_it != mUniqueNotifications.end();
+			++existing_it)
 		{
-			// copy notification instance data over to oldest instance
-			// of this unique notification and update it
-			existing_notification->updateFrom(pNotif);
-			// then delete the new one
-			cancel(pNotif);
+			LLNotificationPtr existing_notification = existing_it->second;
+			if (pNotif != existing_notification 
+				&& pNotif->isEquivalentTo(existing_notification))
+			{
+				// copy notification instance data over to oldest instance
+				// of this unique notification and update it
+				existing_notification->updateFrom(pNotif);
+				// then delete the new one
+				cancel(pNotif);
+			}
 		}
 	}
 
@@ -1296,10 +1304,7 @@ void LLNotifications::createDefaultChannels()
 		boost::bind(&LLNotifications::isVisibleByRules, this, _1)));
 	mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules",
 		&LLNotificationFilters::includeEverything));
-
-	// create special persistent notification channel
-	// this isn't a leak, don't worry about the empty "new"
-	new LLPersistentNotificationChannel();
+	mDefaultChannels.push_back(new LLPersistentNotificationChannel());
 
 	// connect action methods to these channels
 	LLNotifications::instance().getChannel("Enabled")->
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 344108ecbf5..4e2b997156a 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -297,6 +297,7 @@ LOG_CLASS(LLNotification);
 friend class LLNotifications;
 
 public:
+
 	// parameter object used to instantiate a new notification
 	struct Params : public LLInitParam::Block<Params>
 	{
@@ -518,6 +519,13 @@ friend class LLNotifications;
 	bool canLogToIM() const;
 	bool hasFormElements() const;
 
+	typedef enum e_combine_behavior
+	{
+		USE_NEWEST,
+		USE_OLDEST
+	} ECombineBehavior;
+
+	ECombineBehavior getCombineBehavior() const;
 	const LLNotificationFormPtr getForm();
 
 	const LLDate getExpiration() const
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index 1df7205b234..8080acbf874 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -61,6 +61,17 @@ typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
 // from the appropriate local language directory).
 struct LLNotificationTemplate
 {
+	struct CombineBehaviorNames
+		:	public LLInitParam::TypeValuesHelper<LLNotification::ECombineBehavior, CombineBehaviorNames>
+	{
+		static void declareValues()
+		{
+			declare("newest", LLNotification::USE_NEWEST);
+			declare("oldest", LLNotification::USE_OLDEST);
+		}
+	};
+
+
 	struct GlobalString : public LLInitParam::Block<GlobalString>
 	{
 		Mandatory<std::string>	name,
@@ -94,9 +105,11 @@ struct LLNotificationTemplate
 		Optional<LLInitParam::Flag>	dummy_val;
 	public:
 		Multiple<UniquenessContext>	contexts;
+		Optional<LLNotification::ECombineBehavior, CombineBehaviorNames> combine;
 
 		UniquenessConstraint()
 		:	contexts("context"),
+			combine("combine", LLNotification::USE_NEWEST),
 			dummy_val("")
 		{}
 	};
@@ -249,6 +262,7 @@ struct LLNotificationTemplate
     // (used for things like progress indications, or repeating warnings
     // like "the grid is going down in N minutes")
     bool mUnique;
+	LLNotification::ECombineBehavior mCombineBehavior;
     // if we want to be unique only if a certain part of the payload or substitutions args
 	// are constant specify the field names for the payload. The notification will only be
     // combined if all of the fields named in the context are identical in the
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 67519a3ca6a..b4c70b6edbb 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -393,9 +393,15 @@ void LLNotificationChiclet::setCounter(S32 counter)
 	
 }
 
-bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notify )
+bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )
 {
-	return !(notify->canLogToIM() && notify->hasFormElements());
+	if( !(notification->canLogToIM() && notification->hasFormElements())
+		&& (!notification->getPayload().has("give_inventory_notification")
+			|| notification->getPayload()["give_inventory_notification"]))
+	{
+		return true;
+	}
+	return false;
 }
 
 //////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 419b8a14b63..21f3961d182 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -94,7 +94,7 @@ class LLSysHandler : public LLEventHandler, public LLNotificationChannel
 
 	// base interface functions
 	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); }
-	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
+	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); }
 	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel) mChannel->killToastByNotificationID(p->getID());}
 
 	virtual bool processNotification(const LLNotificationPtr& notify)=0;
@@ -130,7 +130,7 @@ class LLIMHandler : public LLSysHandler
 
 protected:
 	bool processNotification(const LLNotificationPtr& p);
-	virtual void initChannel();
+	/*virtual*/ void initChannel();
 };
 
 /**
@@ -144,11 +144,12 @@ class LLTipHandler : public LLSysHandler
 	virtual ~LLTipHandler();
 
 	// base interface functions
-	virtual bool processNotification(const LLNotificationPtr& p);
+	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
+	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
-	virtual void onRejectToast(const LLUUID& id);
-	virtual void initChannel();
+	/*virtual*/ void onRejectToast(const LLUUID& id);
+	/*virtual*/ void initChannel();
 };
 
 /**
@@ -161,13 +162,13 @@ class LLScriptHandler : public LLSysHandler
 	LLScriptHandler();
 	virtual ~LLScriptHandler();
 
-	virtual void onDelete(LLNotificationPtr p);
+	/*virtual*/ void onDelete(LLNotificationPtr p);
 	// base interface functions
-	virtual bool processNotification(const LLNotificationPtr& p);
+	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
-	virtual void onDeleteToast(LLToast* toast);
-	virtual void initChannel();
+	/*virtual*/ void onDeleteToast(LLToast* toast);
+	/*virtual*/ void initChannel();
 
 	// own handlers
 	void onRejectToast(LLUUID& id);
@@ -184,7 +185,8 @@ class LLGroupHandler : public LLSysHandler
 	virtual ~LLGroupHandler();
 	
 	// base interface functions
-	virtual bool processNotification(const LLNotificationPtr& p);
+	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
+	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
 	virtual void initChannel();
@@ -204,9 +206,7 @@ class LLAlertHandler : public LLSysHandler
 
 	/*virtual*/ void onChange(LLNotificationPtr p);
 	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); }
-
-	// base interface functions
-	virtual bool processNotification(const LLNotificationPtr& p);
+	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
 	virtual void initChannel();
@@ -225,11 +225,12 @@ class LLOfferHandler : public LLSysHandler
 	virtual ~LLOfferHandler();
 
 	// base interface functions
+	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
 	/*virtual*/ void onDelete(LLNotificationPtr notification);
-	virtual bool processNotification(const LLNotificationPtr& p);
+	/*virtual*/ bool processNotification(const LLNotificationPtr& p);
 
 protected:
-	virtual void initChannel();
+	/*virtual*/ void initChannel();
 
 	// own handlers
 	void onRejectToast(LLUUID& id);
@@ -246,7 +247,7 @@ class LLHintHandler : public LLNotificationChannel
 	virtual ~LLHintHandler() {}
 
 	/*virtual*/ void onAdd(LLNotificationPtr p);
-	/*virtual*/ void onChange(LLNotificationPtr p);
+	/*virtual*/ void onLoad(LLNotificationPtr p);
 	/*virtual*/ void onDelete(LLNotificationPtr p);
 };
 
diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp
index 47156a39152..271f4185076 100644
--- a/indra/newview/llnotificationhinthandler.cpp
+++ b/indra/newview/llnotificationhinthandler.cpp
@@ -34,5 +34,5 @@
 using namespace LLNotificationsUI;
 
 void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); }
-void LLHintHandler::onChange(LLNotificationPtr p) { LLHints::show(p); }
+void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); }
 void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); }
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 5301955964b..cc68c4c91af 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -251,7 +251,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
 {
 	bool store_toast = false, show_toast = false;
 
-	mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show);
+	if (mDisplayToastsAlways)
+	{
+		show_toast = true;
+	}
+	else
+	{
+		show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show);
+	}
 	store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;
 
 	if(!show_toast && !store_toast)
-- 
GitLab