From f149b87fcc152a7e6232d1a2eb81bb2ac72697da Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 29 Jun 2023 23:53:22 +0300
Subject: [PATCH] SL-19929 New inventory feature notification

---
 indra/newview/CMakeLists.txt                  |  2 +
 indra/newview/app_settings/settings.xml       | 11 ++++
 indra/newview/llagent.cpp                     | 33 +++++++++-
 indra/newview/llagent.h                       | 12 ++--
 .../llfloaternewfeaturenotification.cpp       | 63 +++++++++++++++++++
 .../newview/llfloaternewfeaturenotification.h | 49 +++++++++++++++
 indra/newview/llsidepanelinventory.cpp        |  2 +
 indra/newview/llstartup.cpp                   |  4 +-
 indra/newview/llviewerfloaterreg.cpp          |  4 ++
 .../en/floater_new_feature_notification.xml   | 54 ++++++++++++++++
 10 files changed, 224 insertions(+), 10 deletions(-)
 create mode 100644 indra/newview/llfloaternewfeaturenotification.cpp
 create mode 100644 indra/newview/llfloaternewfeaturenotification.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_new_feature_notification.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index eedc24f973e..c37d03221ca 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES
     llfloatermyscripts.cpp
     llfloatermyenvironment.cpp
     llfloaternamedesc.cpp
+    llfloaternewfeaturenotification.cpp
     llfloaternotificationsconsole.cpp
     llfloaternotificationstabbed.cpp
     llfloaterobjectweights.cpp
@@ -894,6 +895,7 @@ set(viewer_HEADER_FILES
     llfloatermyscripts.h
     llfloatermyenvironment.h
     llfloaternamedesc.h
+    llfloaternewfeaturenotification.h
     llfloaternotificationsconsole.h
     llfloaternotificationstabbed.h
     llfloaterobjectweights.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index dd87f827df9..df3dd65a0e8 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5497,6 +5497,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>LastUIFeatureVersion</key>
+    <map>
+        <key>Comment</key>
+        <string>UI Feature Version number for tracking feature notification between viewer builds</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>S32</string>
+        <key>Value</key>
+        <integer>0</integer>
+    </map>
     <key>LastFindPanel</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 8cc9be72445..2430ca5f83d 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -120,6 +120,8 @@ const F64 CHAT_AGE_FAST_RATE = 3.0;
 const F32 MIN_FIDGET_TIME = 8.f; // seconds
 const F32 MAX_FIDGET_TIME = 20.f; // seconds
 
+const S32 UI_FEATURE_VERSION = 1;
+
 // The agent instance.
 LLAgent gAgent;
 
@@ -372,7 +374,7 @@ LLAgent::LLAgent() :
 	mHideGroupTitle(FALSE),
 	mGroupID(),
 
-	mInitialized(FALSE),
+	mInitialized(false),
 	mListener(),
 
 	mDoubleTapRunTimer(),
@@ -447,7 +449,7 @@ LLAgent::LLAgent() :
 
 	mNextFidgetTime(0.f),
 	mCurrentFidget(0),
-	mFirstLogin(FALSE),
+	mFirstLogin(false),
 	mOutfitChosen(FALSE),
 
 	mVoiceConnected(false),
@@ -504,7 +506,7 @@ void LLAgent::init()
 
 	mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT);
 
-	mInitialized = TRUE;
+	mInitialized = true;
 }
 
 //-----------------------------------------------------------------------------
@@ -559,6 +561,31 @@ void LLAgent::onAppFocusGained()
 	}
 }
 
+void LLAgent::setFirstLogin(bool b)
+{
+    mFirstLogin = b;
+
+    if (mFirstLogin)
+    {
+        // Don't notify new users about new features
+        S32 feature_version = gSavedSettings.getS32("LastUIFeatureVersion");
+        if (feature_version < UI_FEATURE_VERSION)
+        {
+            gSavedSettings.setS32("LastUIFeatureVersion", UI_FEATURE_VERSION);
+        }
+    }
+}
+
+void LLAgent::showLatestFeatureNotification()
+{
+    // Notify user about new thumbnail support
+    S32 feature_version = gSavedSettings.getS32("LastUIFeatureVersion");
+    if (feature_version < UI_FEATURE_VERSION)
+    {
+        LLFloaterReg::showInstance("new_feature_notification");
+        gSavedSettings.setS32("LastUIFeatureVersion", UI_FEATURE_VERSION);
+    }
+}
 
 void LLAgent::ageChat()
 {
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 498bea3c070..fb9ac402e1e 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -117,15 +117,17 @@ class LLAgent : public LLOldEvents::LLObservable
 	//--------------------------------------------------------------------
 public:
 	void			onAppFocusGained();
-	void			setFirstLogin(BOOL b) 	{ mFirstLogin = b; }
+	void			setFirstLogin(bool b);
 	// Return TRUE if the database reported this login as the first for this particular user.
-	BOOL 			isFirstLogin() const 	{ return mFirstLogin; }
-	BOOL 			isInitialized() const 	{ return mInitialized; }
+	bool 			isFirstLogin() const 	{ return mFirstLogin; }
+	bool 			isInitialized() const 	{ return mInitialized; }
+
+    void            showLatestFeatureNotification();
 public:
 	std::string		mMOTD; 					// Message of the day
 private:
-	BOOL			mInitialized;
-	BOOL			mFirstLogin;
+	bool			mInitialized;
+	bool			mFirstLogin;
 	boost::shared_ptr<LLAgentListener> mListener;
 
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llfloaternewfeaturenotification.cpp b/indra/newview/llfloaternewfeaturenotification.cpp
new file mode 100644
index 00000000000..e04b1a5da5a
--- /dev/null
+++ b/indra/newview/llfloaternewfeaturenotification.cpp
@@ -0,0 +1,63 @@
+/** 
+ * @file llfloaternewfeaturenotification.cpp
+ * @brief LLFloaterNewFeatureNotification class implementation
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaternewfeaturenotification.h"
+
+
+LLFloaterNewFeatureNotification::LLFloaterNewFeatureNotification(const LLSD& key)
+	:	LLFloater(key)
+{
+}
+
+LLFloaterNewFeatureNotification::~LLFloaterNewFeatureNotification()
+{
+}
+
+BOOL LLFloaterNewFeatureNotification::postBuild()
+{
+	setCanDrag(FALSE);
+	getChild<LLButton>("close_btn")->setCommitCallback(boost::bind(&LLFloaterNewFeatureNotification::onCloseBtn, this));
+	return TRUE;
+}
+
+void LLFloaterNewFeatureNotification::onOpen(const LLSD& key)
+{
+	centerOnScreen();
+}
+
+void LLFloaterNewFeatureNotification::onCloseBtn()
+{
+	closeFloater();
+}
+
+void LLFloaterNewFeatureNotification::centerOnScreen()
+{
+	LLVector2 window_size = LLUI::getInstance()->getWindowSize();
+	centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY])));
+}
+
diff --git a/indra/newview/llfloaternewfeaturenotification.h b/indra/newview/llfloaternewfeaturenotification.h
new file mode 100644
index 00000000000..86e9683def8
--- /dev/null
+++ b/indra/newview/llfloaternewfeaturenotification.h
@@ -0,0 +1,49 @@
+/** 
+ * @file llfloaternewfeaturenotification.h
+ * @brief LLFloaterNewFeatureNotification class definition
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FLOATER_NEW_FEATURE_NOTOFICATION_H
+#define LL_FLOATER_NEW_FEATURE_NOTOFICATION_H
+
+#include "llfloater.h"
+
+class LLFloaterNewFeatureNotification:
+	public LLFloater
+{
+	friend class LLFloaterReg;
+public:
+	BOOL postBuild() override;
+	void onOpen(const LLSD& key) override;
+
+private:
+    LLFloaterNewFeatureNotification(const LLSD& key);
+    /*virtual*/	~LLFloaterNewFeatureNotification();
+
+	void centerOnScreen();
+
+	void onCloseBtn();	
+};
+
+#endif
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 5eb853f44c8..dde260eb7f1 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -400,6 +400,8 @@ void LLSidepanelInventory::onOpen(const LLSD& key)
 		gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());
 	}
 #endif
+
+    gAgent.showLatestFeatureNotification();
 }
 
 void LLSidepanelInventory::performActionOnSelection(const std::string &action)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index a37bde6eb83..edd46f74232 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -3627,7 +3627,7 @@ bool process_login_success_response()
 		std::string flag = login_flags["ever_logged_in"];
 		if(!flag.empty())
 		{
-			gAgent.setFirstLogin((flag == "N") ? TRUE : FALSE);
+			gAgent.setFirstLogin(flag == "N");
 		}
 
 		/*  Flag is currently ignored by the viewer.
@@ -3718,7 +3718,7 @@ bool process_login_success_response()
 	std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName");
 	if (!fake_initial_outfit_name.empty())
 	{
-		gAgent.setFirstLogin(TRUE);
+		gAgent.setFirstLogin(true);
 		sInitialOutfit = fake_initial_outfit_name;
 		if (sInitialOutfitGender.empty())
 		{
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 0c6e2de3ed1..060bdb6995a 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -100,6 +100,7 @@
 #include "llfloatermyscripts.h"
 #include "llfloatermyenvironment.h"
 #include "llfloaternamedesc.h"
+#include "llfloaternewfeaturenotification.h"
 #include "llfloaternotificationsconsole.h"
 #include "llfloaternotificationstabbed.h"
 #include "llfloaterobjectweights.h"
@@ -229,6 +230,7 @@ class LLFloaterOpenHandler : public LLCommandHandler
                 "avatar_picker",
                 "camera",
                 "camera_presets",
+                "change_item_thumbnail"
                 "classified",
                 "add_landmark",
                 "delete_pref_preset",
@@ -247,6 +249,7 @@ class LLFloaterOpenHandler : public LLCommandHandler
                 "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant
                 "message_tos", // Modal!!! Login specific.
                 "mute_object_by_name",
+                "new_feature_notification",
                 "publish_classified",
                 "save_pref_preset",
                 "save_camera_preset",
@@ -402,6 +405,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
 	LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
 	LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
+    LLFloaterReg::add("new_feature_notification", "floater_new_feature_notification.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNewFeatureNotification>);
 
 	LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
 	
diff --git a/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml
new file mode 100644
index 00000000000..370a08f16af
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ height="130"
+ width="300"
+ layout="topleft"
+ name="floater_new_feature_notification"
+ title="NEW FEATURE"
+ show_title="false"
+ header_height="0"
+ bg_opaque_image="Window_NoTitle_Foreground"
+ bg_alpha_image="Window_NoTitle_Background"
+ can_resize="false"
+ can_drag_on_left="false"
+ can_minimize="false"
+ can_close="false">
+  <text
+   type="string"
+   length="1"
+   follows="top|left|right"
+   font="SansSerifLargeBold"
+   text_color="White"
+   layout="topleft"
+   left="10"
+   height="14"
+   top="10"
+   right="-10"
+   name="title_txt">
+New inventory features
+  </text>
+  <text
+   type="string"
+   length="1"
+   follows="top|left|right"
+   text_color="White"
+   layout="topleft"
+   left="10"
+   height="40"
+   top_pad="14"
+   right="-10"
+   word_wrap="true"
+   name="description_txt">
+You can now add preview images to inventory items and view a folder in its own window.
+Learn more in this [https://community.secondlife.com/blogs/entry/13637-new-features-inventory-item-preview-and-single-folder-view/ blogpost]
+  </text>
+  <button
+   follows="bottom|left|right"
+   layout="topleft"
+   height="24"
+   label="Got it!"
+   left="104"
+   bottom="-10"
+   name="close_btn"
+   width="90"/>
+</floater>
-- 
GitLab