diff options
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
-rw-r--r-- | indra/newview/llagent.cpp | 98 | ||||
-rw-r--r-- | indra/newview/llagent.h | 15 | ||||
-rw-r--r-- | indra/newview/llfloaternewfeaturenotification.cpp | 76 | ||||
-rw-r--r-- | indra/newview/llfloaternewfeaturenotification.h | 49 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llviewerfloaterreg.cpp | 4 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_new_feature_notification.xml | 60 |
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> |