summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llagent.cpp98
-rw-r--r--indra/newview/llagent.h15
-rw-r--r--indra/newview/llfloaternewfeaturenotification.cpp76
-rw-r--r--indra/newview/llfloaternewfeaturenotification.h49
-rw-r--r--indra/newview/llstartup.cpp4
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/skins/default/xui/en/floater_new_feature_notification.xml60
9 files changed, 309 insertions, 10 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c6d82ea260..d413c12de9 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
llfloateroutfitphotopreview.cpp
@@ -895,6 +896,7 @@ set(viewer_HEADER_FILES
llfloatermyscripts.h
llfloatermyenvironment.h
llfloaternamedesc.h
+ llfloaternewfeaturenotification.h
llfloaternotificationsconsole.h
llfloaternotificationstabbed.h
llfloateroutfitphotopreview.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index b92a829f36..85f6101050 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5519,6 +5519,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>LLSD</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>LastFindPanel</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index ea176dd8de..be764287cc 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -120,6 +120,11 @@ 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;
+// For version 1: 1 - inventory, 2 - gltf
+// Will need to change to 3 once either inventory or gltf releases and cause a conflict
+const S32 UI_FEATURE_FLAGS = 2;
+
// The agent instance.
LLAgent gAgent;
@@ -372,7 +377,7 @@ LLAgent::LLAgent() :
mHideGroupTitle(FALSE),
mGroupID(),
- mInitialized(FALSE),
+ mInitialized(false),
mListener(),
mDoubleTapRunTimer(),
@@ -447,7 +452,7 @@ LLAgent::LLAgent() :
mNextFidgetTime(0.f),
mCurrentFidget(0),
- mFirstLogin(FALSE),
+ mFirstLogin(false),
mOutfitChosen(FALSE),
mVoiceConnected(false),
@@ -504,7 +509,7 @@ void LLAgent::init()
mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT);
- mInitialized = TRUE;
+ mInitialized = true;
}
//-----------------------------------------------------------------------------
@@ -559,6 +564,93 @@ void LLAgent::onAppFocusGained()
}
}
+void LLAgent::setFirstLogin(bool b)
+{
+ mFirstLogin = b;
+
+ if (mFirstLogin)
+ {
+ // Don't notify new users about new features
+ if (getFeatureVersion() <= UI_FEATURE_VERSION)
+ {
+ setFeatureVersion(UI_FEATURE_VERSION, UI_FEATURE_FLAGS);
+ }
+ }
+}
+
+void LLAgent::setFeatureVersion(S32 version, S32 flags)
+{
+ LLSD updated_version;
+ updated_version["version"] = version;
+ updated_version["flags"] = flags;
+ gSavedSettings.setLLSD("LastUIFeatureVersion", updated_version);
+}
+
+S32 LLAgent::getFeatureVersion()
+{
+ S32 version;
+ S32 flags;
+ getFeatureVersionAndFlags(version, flags);
+ return version;
+}
+
+void LLAgent::getFeatureVersionAndFlags(S32& version, S32& flags)
+{
+ version = 0;
+ flags = 0;
+ LLSD feature_version = gSavedSettings.getLLSD("LastUIFeatureVersion");
+ if (feature_version.isInteger())
+ {
+ version = feature_version.asInteger();
+ flags = 1; // inventory flag
+ }
+ else if (feature_version.isMap())
+ {
+ version = feature_version["version"];
+ flags = feature_version["flags"];
+ }
+ else if (!feature_version.isString() && !feature_version.isUndefined())
+ {
+ // is something newer inside?
+ version = UI_FEATURE_VERSION;
+ flags = UI_FEATURE_FLAGS;
+ }
+}
+
+void LLAgent::showLatestFeatureNotification(const std::string key)
+{
+ S32 version;
+ S32 flags; // a single release can have multiple new features
+ getFeatureVersionAndFlags(version, flags);
+ if (version <= UI_FEATURE_VERSION && (flags & UI_FEATURE_FLAGS) != UI_FEATURE_FLAGS)
+ {
+ S32 flag = 0;
+
+ if (key == "inventory")
+ {
+ // Notify user about new thumbnail support
+ flag = 1;
+ }
+
+ if (key == "gltf")
+ {
+ flag = 2;
+ }
+
+ if ((flags & flag) == 0)
+ {
+ // Need to open on top even if called from onOpen,
+ // do on idle to make sure it's on top
+ LLSD floater_key(key);
+ doOnIdleOneTime([floater_key]()
+ {
+ LLFloaterReg::showInstance("new_feature_notification", floater_key);
+ });
+
+ setFeatureVersion(UI_FEATURE_VERSION, flags | flag);
+ }
+ }
+}
void LLAgent::ageChat()
{
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 498bea3c07..0ce6fda131 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -117,15 +117,20 @@ private:
//--------------------------------------------------------------------
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 setFeatureVersion(S32 version, S32 flags);
+ S32 getFeatureVersion();
+ void getFeatureVersionAndFlags(S32 &version, S32 &flags);
+ void showLatestFeatureNotification(const std::string key);
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 0000000000..3a2035b9b9
--- /dev/null
+++ b/indra/newview/llfloaternewfeaturenotification.cpp
@@ -0,0 +1,76 @@
+/**
+ * @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));
+
+ const std::string title_txt = "title_txt";
+ const std::string dsc_txt = "description_txt";
+ std::string feature = "_" + getKey().asString();
+
+ getChild<LLUICtrl>(title_txt)->setValue(getString(title_txt + feature));
+ getChild<LLUICtrl>(dsc_txt)->setValue(getString(dsc_txt + feature));
+
+ 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])));
+ LLFloaterView* parent = dynamic_cast<LLFloaterView*>(getParent());
+ if (parent)
+ {
+ parent->bringToFront(this);
+ }
+}
+
diff --git a/indra/newview/llfloaternewfeaturenotification.h b/indra/newview/llfloaternewfeaturenotification.h
new file mode 100644
index 0000000000..95501451dc
--- /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/llstartup.cpp b/indra/newview/llstartup.cpp
index e84894b395..8ffab761f4 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -3617,7 +3617,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.
@@ -3708,7 +3708,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 ca87ff0092..0d78bfd753 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -98,6 +98,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 @@ public:
"avatar_picker",
"camera",
"camera_presets",
+ "change_item_thumbnail"
"classified",
"add_landmark",
"delete_pref_preset",
@@ -247,6 +249,7 @@ public:
"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",
@@ -395,6 +398,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 0000000000..5f0eeab71c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml
@@ -0,0 +1,60 @@
+<?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">
+ <floater.string name="title_txt_inventory">
+New inventory features
+ </floater.string>
+ <floater.string name="description_txt_inventory">
+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]
+ </floater.string>
+ <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 feature
+ </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">
+Feature description
+ </text>
+ <button
+ follows="bottom|left|right"
+ layout="topleft"
+ height="24"
+ label="Got it!"
+ left="104"
+ bottom="-10"
+ name="close_btn"
+ width="90"/>
+</floater>