From 42e1a9ed870c537b5684cd15a7acc524a3672685 Mon Sep 17 00:00:00 2001
From: maxim_productengine <mnikolenko@productengine.com>
Date: Mon, 27 Jan 2020 17:54:02 +0200
Subject: SL-12475 add Inventory Favorites tab

# Conflicts:
#	indra/newview/llinventorybridge.cpp
#	indra/newview/llinventorypanel.cpp
---
 indra/llui/llfolderview.h                          |  2 +
 .../newview/app_settings/settings_per_account.xml  | 11 +++
 indra/newview/llinventorybridge.cpp                | 52 ++++++++++--
 indra/newview/llinventorymodel.cpp                 |  5 ++
 indra/newview/llinventorypanel.cpp                 | 96 ++++++++++++++++++++++
 indra/newview/llinventorypanel.h                   | 21 +++++
 indra/newview/llpanelmaininventory.cpp             | 12 ++-
 indra/newview/llpanelmaininventory.h               |  2 +
 .../skins/default/xui/en/menu_inventory.xml        |  7 ++
 .../skins/default/xui/en/panel_main_inventory.xml  | 40 +++++----
 indra/newview/skins/default/xui/en/strings.xml     |  1 +
 11 files changed, 225 insertions(+), 24 deletions(-)

diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 6bb5e6c02e..c175034d75 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -241,6 +241,8 @@ public:
 	void dumpSelectionInformation();
 
 	virtual S32	notify(const LLSD& info) ;
+
+	void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; }
 	
 	bool useLabelSuffix() { return mUseLabelSuffix; }
 	virtual void updateMenu();
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 8f4ca6c633..5eecf1b9f5 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -392,6 +392,17 @@
         <key>Value</key>
         <string></string>
       </map>
+      <key>FavoritesFolder</key>
+      <map>
+        <key>Comment</key>
+        <string>User's chosen folder which will be shown in the Favorites tab (UUID)</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>String</string>
+        <key>Value</key>
+        <string></string>
+      </map>
       <key>SnapshotBaseDir</key>
       <map>
         <key>Comment</key>
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 657c65c68d..03123689c5 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -138,6 +138,35 @@ bool isMarketplaceSendAction(const std::string& action)
 	return ("send_to_marketplace" == action);
 }
 
+bool isPanelActive(const std::string& panel_name)
+{
+    LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+    return (active_panel && (active_panel->getName() == panel_name));
+}
+
+bool isParentSystemFolder(const LLInventoryModel* model, const LLUUID& folder_id)
+{
+    if (!model || folder_id.isNull()) return false;
+
+    LLViewerInventoryCategory* cat = model->getCategory(folder_id);
+    if (cat)
+    {
+        if (cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY)
+        {
+            return false;
+        }
+        if (LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+        {
+            return true;
+        }
+        else
+        {
+            return isParentSystemFolder(model, cat->getParentUUID());
+        }
+    }
+    return false;
+}
+
 // Used by LLFolderBridge as callback for directory fetching recursion
 class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
 {
@@ -888,8 +917,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		disabled_items.push_back(std::string("Properties"));
 	}
 
-	LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
-	if (active_panel && (active_panel->getName() != "All Items"))
+	if (!isPanelActive("All Items"))
 	{
 		items.push_back(std::string("Show in Main Panel"));
 	}
@@ -980,7 +1008,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
 
 	items.push_back(std::string("Delete"));
 
-	if (!isItemRemovable())
+	if (!isItemRemovable() || isPanelActive("Favorite Items"))
 	{
 		disabled_items.push_back(std::string("Delete"));
 	}
@@ -4010,6 +4038,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		disabled_items.push_back(std::string("New Clothes"));
 		disabled_items.push_back(std::string("New Body Parts"));
 		disabled_items.push_back(std::string("upload_def"));
+		disabled_items.push_back(std::string("Set Favorites folder"));
 	}
 	if (favorites == mUUID)
 	{
@@ -4037,6 +4066,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		disabled_items.push_back(std::string("New Clothes"));
 		disabled_items.push_back(std::string("New Body Parts"));
 		disabled_items.push_back(std::string("upload_def"));
+		disabled_items.push_back(std::string("Set Favorites folder"));
     }
     if (marketplace_listings_id == mUUID)
     {
@@ -4045,14 +4075,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
         disabled_items.push_back(std::string("Cut"));
         disabled_items.push_back(std::string("Delete"));
     }
+
+	if (isPanelActive("Favorite Items"))
+	{
+		disabled_items.push_back(std::string("Delete"));
+	}
 	if(trash_id == mUUID)
 	{
-		bool is_recent_panel = false;
-		LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
-		if (active_panel && (active_panel->getName() == "Recent Items"))
-		{
-			is_recent_panel = true;
-		}
+		bool is_recent_panel = isPanelActive("Recent Items");
 
 		// This is the trash.
 		items.push_back(std::string("Empty Trash"));
@@ -4102,6 +4132,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
                     items.push_back(std::string("New Settings"));
                     items.push_back(std::string("upload_def"));
 
+                    if (!LLFolderType::lookupIsProtectedType(getPreferredType()) && !isParentSystemFolder(model, mUUID))
+                    {
+                        items.push_back(std::string("Set Favorites folder"));
+                    }
                     if (!LLEnvironment::instance().isInventoryEnabled())
                     {
                         disabled_items.push_back("New Settings");
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 17e80dca89..a44a54632c 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -542,6 +542,11 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
         cat_id = LLUUID(gSavedPerAccountSettings.getString("AnimationUploadFolder"));
         break;
     }
+    case LLFolderType::FT_FAVORITE:
+    {
+        cat_id = LLUUID(gSavedPerAccountSettings.getString("FavoritesFolder"));
+        break;
+    }
     default:
         break;
     }
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index c6075b4066..8e814916ad 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -179,6 +179,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
 	mCommitCallbackRegistrar.add("Inventory.Share",  boost::bind(&LLAvatarActions::shareWithAvatars, this));
 	mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryPanel::fileUploadLocation, this, _2));
+	mCommitCallbackRegistrar.add("Inventory.SetFavoritesFolder", boost::bind(&LLInventoryPanel::setFavoritesFolder, this, _2));
 }
 
 LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
@@ -1374,6 +1375,11 @@ void LLInventoryPanel::fileUploadLocation(const LLSD& userdata)
     }
 }
 
+void LLInventoryPanel::setFavoritesFolder(const LLSD& userdata)
+{
+    gSavedPerAccountSettings.setString("FavoritesFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
+}
+
 void LLInventoryPanel::purgeSelectedItems()
 {
     if (!mFolderRoot.get()) return;
@@ -1753,6 +1759,96 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
 	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
 }
 
+static LLDefaultChildRegistry::Register<LLInventoryFavoriteItemsPanel> t_favorites_inventory_panel("favorites_inventory_panel");
+
+LLInventoryFavoriteItemsPanel::LLInventoryFavoriteItemsPanel(const Params& params)
+    : LLInventoryPanel(params)
+{
+    std::string ctrl_name = "FavoritesFolder";
+    if (gSavedPerAccountSettings.controlExists(ctrl_name))
+    {
+        LLPointer<LLControlVariable> cntrl_ptr = gSavedPerAccountSettings.getControl(ctrl_name);
+        if (cntrl_ptr.notNull())
+        {
+            mFolderChangedSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLInventoryFavoriteItemsPanel::updateFavoritesRootFolder, this));
+        }
+    }
+}
+
+void LLInventoryFavoriteItemsPanel::setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)
+{
+    if (mFolderRoot.get())
+    {
+        mFolderRoot.get()->setSelectCallback(cb);
+        mSelectionCallback = cb;
+    }
+}
+
+void LLInventoryFavoriteItemsPanel::initFromParams(const Params& p)
+{
+    Params fav_params(p);
+    fav_params.start_folder.id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+    LLInventoryPanel::initFromParams(fav_params);
+    updateFavoritesRootFolder();
+}
+
+void LLInventoryFavoriteItemsPanel::updateFavoritesRootFolder()
+{
+    const LLUUID& folder_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+    bool is_favorites_set = (folder_id != gInventory.findCategoryUUIDForTypeInRoot(LLFolderType::FT_FAVORITE, true, gInventory.getRootFolderID()));
+
+    if (!is_favorites_set || folder_id != getRootFolderID())
+    {
+        LLUUID root_id = folder_id;
+        if (mFolderRoot.get())
+        {
+            removeItemID(getRootFolderID());
+            mFolderRoot.get()->destroyView();
+        }
+
+        mCommitCallbackRegistrar.pushScope();
+        {
+            LLFolderView* folder_view = createFolderRoot(root_id);
+            mFolderRoot = folder_view->getHandle();
+
+            addItemID(root_id, mFolderRoot.get());
+
+
+            LLRect scroller_view_rect = getRect();
+            scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+            LLScrollContainer::Params scroller_params(mParams.scroll());
+            scroller_params.rect(scroller_view_rect);
+
+            if (mScroller)
+            {
+                removeChild(mScroller);
+                delete mScroller;
+                mScroller = NULL;
+            }
+            mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
+            addChild(mScroller);
+            mScroller->addChild(mFolderRoot.get());
+            mFolderRoot.get()->setScrollContainer(mScroller);
+            mFolderRoot.get()->setFollowsAll();
+            mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox);
+
+            if (!mSelectionCallback.empty())
+            {
+                mFolderRoot.get()->setSelectCallback(mSelectionCallback);
+            }
+        }
+        mCommitCallbackRegistrar.popScope();
+        mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+        if (is_favorites_set)
+        {
+            buildNewViews(folder_id);
+        }
+        mFolderRoot.get()->setShowEmptyMessage(!is_favorites_set);
+    }
+}
+
 /************************************************************************/
 /* Asset Pre-Filtered Inventory Panel related class                     */
 /* Exchanges filter's flexibility for speed of generation and           */
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index b55eb2b828..d1c0b35e21 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -214,6 +214,7 @@ public:
 	void doCreate(const LLSD& userdata);
 	bool beginIMSession();
 	void fileUploadLocation(const LLSD& userdata);
+	void setFavoritesFolder(const LLSD& userdata);
 	void purgeSelectedItems();
 	bool attachObject(const LLSD& userdata);
 	static void idle(void* user_data);
@@ -338,4 +339,24 @@ private:
 	bool				mViewsInitialized; // Views have been generated
 };
 
+
+class LLInventoryFavoriteItemsPanel : public LLInventoryPanel
+{
+public:
+    struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+    {};
+
+    void initFromParams(const Params& p);
+    bool isSelectionRemovable() { return false; }
+    void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
+
+protected:
+    LLInventoryFavoriteItemsPanel::LLInventoryFavoriteItemsPanel(const Params& params);
+    ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); }
+    void updateFavoritesRootFolder();
+
+    boost::signals2::connection mFolderChangedSignal;
+    boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback;
+    friend class LLUICtrlFactory;
+};
 #endif // LL_LLINVENTORYPANEL_H
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 02cd22c307..89682d9576 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -188,6 +188,16 @@ BOOL LLPanelMainInventory::postBuild()
 		worn_filter.markDefault();
 		mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2));
 	}
+
+	mFavoriteItemsPanel = getChild<LLInventoryFavoriteItemsPanel>("Favorite Items");
+	if (mFavoriteItemsPanel)
+	{
+		LLInventoryFilter& recent_filter = mFavoriteItemsPanel->getFilter();
+		recent_filter.setEmptyLookupMessage("InventoryFavoritItemsNotSelected");
+		recent_filter.markDefault();
+		mFavoriteItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mFavoriteItemsPanel, _1, _2));
+	}
+
 	mSearchTypeCombo  = getChild<LLComboBox>("search_type");
 	if(mSearchTypeCombo)
 	{
@@ -1403,7 +1413,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
 	}
 	if (command_name == "delete")
 	{
-		return getActivePanel()->isSelectionRemovable();
+		return getActivePanel()->isSelectionRemovable() && (getActivePanel() != mFavoriteItemsPanel);
 	}
 	if (command_name == "save_texture")
 	{
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index a6bdee233d..c0b4a7b6fc 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -37,6 +37,7 @@
 class LLComboBox;
 class LLFolderViewItem;
 class LLInventoryPanel;
+class LLInventoryFavoriteItemsPanel;
 class LLSaveFolderState;
 class LLFilterEditor;
 class LLTabContainer;
@@ -136,6 +137,7 @@ private:
 	LLHandle<LLFloater>			mFinderHandle;
 	LLInventoryPanel*			mActivePanel;
 	LLInventoryPanel*			mWornItemsPanel;
+	LLInventoryFavoriteItemsPanel* mFavoriteItemsPanel;
 	bool						mResortActivePanel;
 	LLSaveFolderState*			mSavedFolderState;
 	std::string					mFilterText;
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 9aa84c1bac..adefa261aa 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -393,6 +393,13 @@
          parameter="model" />
       </menu_item_call>
     </menu>
+      <menu_item_call
+       label="Use as Favorites folder"
+       layout="topleft"
+       name="Set Favorites folder">
+        <menu_item_call.on_click
+         function="Inventory.SetFavoritesFolder"/>
+      </menu_item_call>
     <menu
      label="Change Type"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index d77fbdec0a..2745b9d302 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -117,20 +117,32 @@
      name="Recent Items"
      show_item_link_overlays="true"
      width="290" />
-       <inventory_panel
-      name="Worn Items"
-      label="WORN"
-      show_empty_message="false"
-      follows="all"
-      layout="topleft"
-      width="290"
-      bg_opaque_color="DkGray2"
-      bg_alpha_color="DkGray2"
-      background_visible="true"
-      border="false"
-      bevel_style="none"
-      scroll.reserve_scroll_corner="false">
-  </inventory_panel>
+    <inventory_panel
+     name="Worn Items"
+     label="WORN"
+     show_empty_message="false"
+     follows="all"
+     layout="topleft"
+     width="290"
+     bg_opaque_color="DkGray2"
+     bg_alpha_color="DkGray2"
+     background_visible="true"
+     border="false"
+     bevel_style="none"
+     scroll.reserve_scroll_corner="false"/>
+    <favorites_inventory_panel
+     name="Favorite Items"
+     label="FAVORITES"
+     show_empty_message="false"
+     follows="all"
+     layout="topleft"
+     width="290"
+     bg_opaque_color="DkGray2"
+     bg_alpha_color="DkGray2"
+     background_visible="true"
+     border="false"
+     bevel_style="none"
+     scroll.reserve_scroll_corner="false"/>
   </tab_container>
   <layout_stack
    animate="false"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1bfac6aeb7..b26ae0ebf8 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2295,6 +2295,7 @@ For AI Character: Get the closest navigable point to the point provided.
 	<!-- inventory -->
 	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
 	<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
+	<string name="InventoryFavoritItemsNotSelected">Click "Use as Favorites folder" on a folder of your choice. You can choose a different folder at any time. System folders cannot be used for Favorites.</string>
 	<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
 	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
 	<string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string>
-- 
cgit v1.2.3


From ae1e7c1231861aab49ddf348f914eba1b8993bbb Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Tue, 28 Jan 2020 14:50:32 +0200
Subject: SL-12475 Mac buildfix

---
 indra/newview/llinventorypanel.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index d1c0b35e21..32d122cab8 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -351,7 +351,7 @@ public:
     void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
 
 protected:
-    LLInventoryFavoriteItemsPanel::LLInventoryFavoriteItemsPanel(const Params& params);
+    LLInventoryFavoriteItemsPanel(const Params& params);
     ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); }
     void updateFavoritesRootFolder();
 
-- 
cgit v1.2.3


From 980cb570162f5f4e48a2de99726d83336e3d5f59 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 21 Aug 2020 15:20:23 +0300
Subject:  SL-13823  FIXED "Settings" are not shown in Inventory filter message

---
 indra/newview/llinventoryfilter.cpp            | 12 ++++++++++++
 indra/newview/skins/default/xui/en/strings.xml |  1 +
 2 files changed, 13 insertions(+)

diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 745b953996..8f18de0210 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -1230,6 +1230,18 @@ const std::string& LLInventoryFilter::getFilterText()
 		filtered_by_all_types = FALSE;
 	}
 
+	if (isFilterObjectTypesWith(LLInventoryType::IT_SETTINGS))
+	{
+		filtered_types +=  LLTrans::getString("Settings");
+		filtered_by_type = TRUE;
+		num_filter_types++;
+	}
+	else
+	{
+		not_filtered_types +=  LLTrans::getString("Settings");
+		filtered_by_all_types = FALSE;
+	}
+
 	if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()
 		&& filtered_by_type
 		&& !filtered_by_all_types)
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b26ae0ebf8..8a87199551 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2416,6 +2416,7 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="Scripts"       value=" Scripts," />
 	<string name="Sounds"        value=" Sounds," />
 	<string name="Textures"      value=" Textures," />
+	<string name="Settings"      value=" Settings," />
 	<string name="Snapshots"     value=" Snapshots," />
 	<string name="No Filters"    value="No " />
 	<string name="Since Logoff"  value=" - Since Logoff" />
-- 
cgit v1.2.3


From 0e829d2ecca9454f4d4bcced0fe9049b0f91465d Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 21 Aug 2020 16:40:53 +0300
Subject: SL-13824 Remove notification when joining a group

---
 indra/newview/llviewermessage.cpp                    |  1 -
 indra/newview/skins/default/xui/en/notifications.xml | 12 ------------
 2 files changed, 13 deletions(-)

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 06a8ebbe89..e78ace061e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -777,7 +777,6 @@ void response_group_invitation_coro(std::string url, LLUUID group_id, bool notif
             LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL;
             if (notify_and_update)
             {
-                LLNotificationsUtil::add("JoinGroupSuccess");
                 gAgent.sendAgentDataUpdateRequest();
 
                 LLGroupMgr::getInstance()->clearGroupData(group_id);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 32ae56e3af..fa1c15c411 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1022,18 +1022,6 @@ The group no longer has open enrollment.
        yestext="OK"/>
   </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   name="JoinGroupSuccess"
-   type="alertmodal">
-You have been added to the group
-    <tag>group_id</tag>
-    <tag>success</tag>
-    <usetemplate
-       name="okbutton"
-       yestext="OK"/>
-  </notification>
-  
   <notification
    icon="alertmodal.tga"
    name="JoinGroupInsufficientFunds"
-- 
cgit v1.2.3


From f8fb2dab5b93588fb3e7f4c1912fd253375e0ced Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 26 Aug 2020 12:26:07 +0300
Subject: SL-13824 Remove notification when both joining a group and leaving a
 group

---
 indra/newview/llviewermessage.cpp                    | 9 +++++++++
 indra/newview/skins/default/xui/en/notifications.xml | 7 -------
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e78ace061e..9c56766d0d 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5036,6 +5036,15 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
 		// notification was specified using the new mechanism, so we can just handle it here
 		std::string notificationID;
 		msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
+
+		//SL-13824 skip notification when both joining a group and leaving a group
+		//remove this after server stops sending these messages  
+		if (notificationID == "JoinGroupSuccess" ||
+			notificationID == "GroupDepart")
+		{
+			return true;
+		}
+
 		if (!LLNotifications::getInstance()->templateExists(notificationID))
 		{
 			return false;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index fa1c15c411..d141cfc313 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4214,13 +4214,6 @@ Leave Group?
      yestext="OK"/>
   </notification>
 
-  <notification
-   icon="notify.tga"
-   name="GroupDepart"
-   type="notify">
-You have left the group &apos;&lt;nolink&gt;[group_name]&lt;/nolink&gt;&apos;.
-    <tag>group</tag>
-  </notification>
 
   <notification
    icon="alertmodal.tga"
-- 
cgit v1.2.3


From bc07bc526cd9492e488380edcc5a6db102fad2d9 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 31 Aug 2020 21:27:37 +0300
Subject: SL-13852 Add visibility options to inventory search results

---
 indra/llui/lllineeditor.h                          |   3 +
 indra/llui/llsearcheditor.cpp                      |  22 +++++-
 indra/llui/llsearcheditor.h                        |  20 ++++-
 indra/newview/llfolderviewmodelinventory.h         |   1 +
 indra/newview/llinventoryfilter.cpp                |  85 ++++++++++++++++++++-
 indra/newview/llinventoryfilter.h                  |  17 ++++-
 indra/newview/llpanelmaininventory.cpp             |  35 +++++++++
 indra/newview/llpanelmaininventory.h               |   2 +
 .../icons/Inv_Toolbar_SearchVisibility.png         | Bin 0 -> 756 bytes
 indra/newview/skins/default/textures/textures.xml  |   3 +
 .../widgets/TextField_Search_Highlight.png         | Bin 0 -> 16287 bytes
 .../xui/en/menu_inventory_search_visibility.xml    |  44 +++++++++++
 .../skins/default/xui/en/panel_main_inventory.xml  |  40 ++++++----
 .../skins/default/xui/en/widgets/filter_editor.xml |   4 +-
 .../skins/default/xui/en/widgets/search_editor.xml |   4 +-
 15 files changed, 258 insertions(+), 22 deletions(-)
 create mode 100644 indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png
 create mode 100644 indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
 create mode 100644 indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml

diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index aa5779d45f..f84625bea7 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -283,6 +283,9 @@ public:
 
 	void			resetContextMenu() { setContextMenu(NULL); };
 
+	void			setBgImage(LLPointer<LLUIImage> image) { mBgImage = image; }
+	void			setBgImageFocused(LLPointer<LLUIImage> image) { mBgImageFocused = image; }
+
 private:
 	// private helper methods
 
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index 1fdd05a11c..bafeef41fb 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -34,7 +34,11 @@
 LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
 :	LLUICtrl(p),
 	mSearchButton(NULL),
-	mClearButton(NULL)
+	mClearButton(NULL),
+	mEditorImage(p.background_image),
+	mEditorImageFocused(p.background_image_focused),
+	mEditorSearchImage(p.background_image_highlight),
+	mHighlightTextField(p.highlight_text_field)
 {
 	S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
 	S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
@@ -57,6 +61,8 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
 	// Set up line editor.
 	LLLineEditor::Params line_editor_params(p);
 	line_editor_params.name("filter edit box");
+	line_editor_params.background_image(p.background_image);
+	line_editor_params.background_image_focused(p.background_image_focused);
 	line_editor_params.rect(getLocalRect());
 	line_editor_params.follows.flags(FOLLOWS_ALL);
 	line_editor_params.text_pad_left(text_pad_left);
@@ -104,6 +110,20 @@ void LLSearchEditor::draw()
 	if (mClearButton)
 		mClearButton->setVisible(!mSearchEditor->getWText().empty());
 
+	if (mHighlightTextField)
+	{	
+		if (!mSearchEditor->getWText().empty())
+		{
+			mSearchEditor->setBgImage(mEditorSearchImage);
+			mSearchEditor->setBgImageFocused(mEditorSearchImage);
+		}
+		else
+		{
+			mSearchEditor->setBgImage(mEditorImage);
+			mSearchEditor->setBgImageFocused(mEditorImageFocused);
+		}
+	}
+
 	LLUICtrl::draw();
 }
 
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index 3b12868225..c0f3c1d60c 100644
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -47,14 +47,23 @@ public:
 		Optional<LLButton::Params>	search_button, 
 									clear_button;
 		Optional<bool>				search_button_visible, 
-									clear_button_visible;
+									clear_button_visible,
+									highlight_text_field;
 		Optional<commit_callback_t> keystroke_callback;
 
+		Optional<LLUIImage*>		background_image,
+									background_image_focused,
+									background_image_highlight;
+
 		Params()
 		:	search_button("search_button"),
 			search_button_visible("search_button_visible"),
 			clear_button("clear_button"), 
-			clear_button_visible("clear_button_visible")
+			clear_button_visible("clear_button_visible"),
+			highlight_text_field("highlight_text_field"),
+			background_image("background_image"),
+			background_image_focused("background_image_focused"),
+			background_image_highlight("background_image_highlight")
 		{}
 	};
 
@@ -93,6 +102,13 @@ protected:
 	LLLineEditor* mSearchEditor;
 	LLButton* mSearchButton;
 	LLButton* mClearButton;
+
+	LLPointer<LLUIImage> mEditorImage;
+	LLPointer<LLUIImage> mEditorImageFocused;
+	LLPointer<LLUIImage> mEditorSearchImage;
+	LLPointer<LLUIImage> mEditorSearchImageFocused;
+
+	bool mHighlightTextField;
 };
 
 #endif  // LL_SEARCHEDITOR_H
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 06a908cccc..51b98339c4 100644
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -45,6 +45,7 @@ public:
 	virtual LLFolderType::EType getPreferredType() const = 0;
 	virtual void showProperties(void) = 0;
 	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual.
+	virtual BOOL isAgentInventory() const { return FALSE; }
 	virtual BOOL isUpToDate() const = 0;
 	virtual bool hasChildren() const = 0;
 	virtual LLInventoryType::EType getInventoryType() const = 0;
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 8f18de0210..1b99c90d5c 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -63,7 +63,8 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
 	mPermissions(p.permissions),
 	mFilterTypes(p.types),
 	mFilterUUID(p.uuid),
-	mFilterLinks(p.links)
+	mFilterLinks(p.links),
+	mSearchVisibility(0xffffFFFFffffFFFFULL)
 {
 }
 
@@ -154,6 +155,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
 	passed = passed && checkAgainstPermissions(listener);
 	passed = passed && checkAgainstFilterLinks(listener);
 	passed = passed && checkAgainstCreator(listener);
+	passed = passed && checkAgainstSearchVisibility(listener);
 
 	return passed;
 }
@@ -550,6 +552,27 @@ bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory
 	}
 }
 
+bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItemInventory* listener) const
+{
+	if (!listener || !hasFilterString()) return TRUE;
+
+	const LLUUID object_id = listener->getUUID();
+	const LLInventoryObject *object = gInventory.getObject(object_id);
+	if (!object) return TRUE;
+
+	const BOOL is_link = object->getIsLinkType();
+	if (is_link && ((mFilterOps.mSearchVisibility & VISIBILITY_LINKS) == 0))
+		return FALSE;
+
+	if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0))
+		return FALSE;
+
+	if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0))
+		return FALSE;
+
+	return TRUE;
+}
+
 const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
 {
 	return mFilterSubString;
@@ -718,6 +741,61 @@ void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_list
     }
 }
 
+
+void LLInventoryFilter::toggleSearchVisibilityLinks()
+{
+	bool hide_links = mFilterOps.mSearchVisibility & VISIBILITY_LINKS;
+	if (hide_links)
+	{
+		mFilterOps.mSearchVisibility &= ~VISIBILITY_LINKS;
+	}
+	else
+	{
+		mFilterOps.mSearchVisibility |= VISIBILITY_LINKS;
+	}
+
+	if (hasFilterString())
+	{
+		setModified(hide_links ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+	}
+}
+
+void LLInventoryFilter::toggleSearchVisibilityTrash()
+{
+	bool hide_trash = mFilterOps.mSearchVisibility & VISIBILITY_TRASH;
+	if (hide_trash)
+	{
+		mFilterOps.mSearchVisibility &= ~VISIBILITY_TRASH;
+	}
+	else
+	{
+		mFilterOps.mSearchVisibility |= VISIBILITY_TRASH;
+	}
+
+	if (hasFilterString())
+	{
+		setModified(hide_trash ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+	}
+}
+
+void LLInventoryFilter::toggleSearchVisibilityLibrary()
+{
+	bool hide_library = mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY;
+	if (hide_library)
+	{
+		mFilterOps.mSearchVisibility &= ~VISIBILITY_LIBRARY;
+	}
+	else
+	{
+		mFilterOps.mSearchVisibility |= VISIBILITY_LIBRARY;
+	}
+
+	if (hasFilterString())
+	{
+		setModified(hide_library ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+	}
+}
+
 void LLInventoryFilter::setFilterNoMarketplaceFolder()
 {
     mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS;
@@ -1349,6 +1427,11 @@ U64 LLInventoryFilter::getFilterSettingsTypes() const
     return mFilterOps.mFilterSettingsTypes;
 }
 
+U64 LLInventoryFilter::getSearchVisibilityTypes() const
+{
+	return mFilterOps.mSearchVisibility;
+}
+
 bool LLInventoryFilter::hasFilterString() const
 {
 	return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index be02ee3623..caba8315c4 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -99,6 +99,14 @@ public:
 		FILTERCREATOR_OTHERS
 	};
 
+	enum ESearchVisibility
+	{
+		VISIBILITY_NONE = 0,
+		VISIBILITY_TRASH = 0x1 << 0,
+		VISIBILITY_LIBRARY = 0x1 << 1,
+		VISIBILITY_LINKS	= 0x1 << 2
+	};
+
 	struct FilterOps
 	{
 		struct DateRange : public LLInitParam::Block<DateRange>
@@ -154,6 +162,7 @@ public:
 						mFilterWearableTypes,
                         mFilterSettingsTypes, // for _SETTINGS
 						mFilterLinks,
+						mSearchVisibility,
 						mFilterCategoryTypes; // For _CATEGORY
 		LLUUID      	mFilterUUID; 		  // for UUID
 
@@ -193,7 +202,8 @@ public:
 	U64 				getFilterObjectTypes() const;
 	U64					getFilterCategoryTypes() const;
 	U64					getFilterWearableTypes() const;
-    U64                 getFilterSettingsTypes() const;
+	U64					getFilterSettingsTypes() const;
+	U64					getSearchVisibilityTypes() const;
 
 	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const;
 	void 				setFilterObjectTypes(U64 types);
@@ -213,6 +223,10 @@ public:
 	ESearchType			getSearchType() { return mSearchType; }
 	void 				setFilterCreator(EFilterCreatorType type);
 
+	void				toggleSearchVisibilityLinks();
+	void				toggleSearchVisibilityTrash();
+	void				toggleSearchVisibilityLibrary();
+
 	void 				setFilterSubString(const std::string& string);
 	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;
 	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; } 
@@ -309,6 +323,7 @@ private:
 	bool 				checkAgainstPermissions(const LLInventoryItem* item) const;
 	bool 				checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const;
 	bool 				checkAgainstCreator(const class LLFolderViewModelItemInventory* listener) const;
+	bool				checkAgainstSearchVisibility(const class LLFolderViewModelItemInventory* listener) const;
 	bool				checkAgainstClipboard(const LLUUID& object_id) const;
 
 	FilterOps				mFilterOps;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 89682d9576..f845e9b056 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -115,6 +115,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
 	  mSavedFolderState(NULL),
 	  mFilterText(""),
 	  mMenuGearDefault(NULL),
+	  mMenuVisibility(NULL),
 	  mMenuAddHandle(),
 	  mNeedUploadCost(true)
 {
@@ -238,6 +239,7 @@ BOOL LLPanelMainInventory::postBuild()
 	}
 
 	mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
+	mVisibilityMenuButton = getChild<LLMenuButton>("options_visibility_btn");
 
 	initListCommandsHandlers();
 
@@ -1174,6 +1176,9 @@ void LLPanelMainInventory::initListCommandsHandlers()
 	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mMenuAddHandle = menu->getHandle();
 
+	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mVisibilityMenuButton->setMenu(mMenuVisibility);
+
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
 }
@@ -1363,6 +1368,21 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 		}
 		LLFloaterReg::showInstance("linkreplace", params);
 	}
+
+	if (command_name == "toggle_search_trash")
+	{
+		mActivePanel->getFilter().toggleSearchVisibilityTrash();
+	}
+
+	if (command_name == "toggle_search_library")
+	{
+		mActivePanel->getFilter().toggleSearchVisibilityLibrary();
+	}
+
+	if (command_name == "include_links")
+	{
+		mActivePanel->getFilter().toggleSearchVisibilityLinks();
+	}		
 }
 
 void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
@@ -1508,6 +1528,21 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
 		return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
 	}
 
+	if (command_name == "toggle_search_trash")
+	{
+		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0;
+	}
+
+	if (command_name == "toggle_search_library")
+	{
+		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0;
+	}
+
+	if (command_name == "include_links")
+	{
+		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0;	
+	}	
+
 	return FALSE;
 }
 
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index c0b4a7b6fc..903b33bdbf 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -171,7 +171,9 @@ protected:
 private:
 	LLDragAndDropButton*		mTrashButton;
 	LLToggleableMenu*			mMenuGearDefault;
+	LLToggleableMenu*			mMenuVisibility;
 	LLMenuButton*				mGearMenuButton;
+	LLMenuButton*				mVisibilityMenuButton;
 	LLHandle<LLView>			mMenuAddHandle;
 
 	bool						mNeedUploadCost;
diff --git a/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png b/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png
new file mode 100644
index 0000000000..048da25c92
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 7325d836d2..1302edda7a 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -333,6 +333,8 @@ with the same filename but different name
   <texture name="Inv_Unknown" file_name="icons/Inv_UnknownObject.png" preload="false" />
   <texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" />
   <texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" />
+
+  <texture name="Inv_Toolbar_SearchVisibility" file_name="icons/Inv_Toolbar_SearchVisibility.png" preload="false" />
   
   <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/>
   <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/>
@@ -648,6 +650,7 @@ with the same filename but different name
   <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
   <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
   <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+  <texture name="TextField_Search_Highlight" file_name="widgets/TextField_Search_Highlight.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
 
 
   <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
new file mode 100644
index 0000000000..e3944289c6
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png differ
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml b/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml
new file mode 100644
index 0000000000..46193f4a7a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_search_visibility"
+ visible="false">
+  <menu_item_check
+   label="Search Trash"
+   layout="topleft"
+   name="search_trash">
+    <on_click
+     function="Inventory.GearDefault.Custom.Action"
+     parameter="toggle_search_trash" />
+    <on_check
+     function="Inventory.GearDefault.Check"
+     parameter="toggle_search_trash" />
+  </menu_item_check>
+  <menu_item_check
+   label="Search Library"
+   layout="topleft"
+   name="search_library">
+    <on_click
+     function="Inventory.GearDefault.Custom.Action"
+     parameter="toggle_search_library" />
+    <on_check
+     function="Inventory.GearDefault.Check"
+     parameter="toggle_search_library" />
+  </menu_item_check>
+  <menu_item_separator
+   layout="topleft" />
+  <menu_item_check
+   label="Include links"
+   layout="topleft"
+   name="include_links">
+    <on_click
+     function="Inventory.GearDefault.Custom.Action"
+     parameter="include_links" />
+    <on_check
+     function="Inventory.GearDefault.Check"
+     parameter="include_links" />         
+  </menu_item_check>    
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index 2745b9d302..7bd5c9b548 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -32,30 +32,20 @@
     		 left="12"
 		     name="ItemcountText"
 		     font="SansSerifMedium"
-		     text_color="EmphasisColor"
+		     text_color="InventoryItemLinkColor"
 		     use_ellipses="true"
 		     top_pad="0"
 		     width="300">
     Items:
   </text>
-  <filter_editor
-   text_pad_left="10"
-   follows="left|top|right"
+  <combo_box
    height="23"
-   label="Enter search text"
    layout="topleft"
    left="10"
-   max_length_chars="300"
-   name="inventory search editor"
    top="18"
-   width="208" />
-  <combo_box
-   height="23"
-   layout="topleft"
-   left_pad="4"
    name="search_type"
-   follows="top|right"
-   width="90">
+   follows="top|left"
+   width="88">
     <item
      label="Name"
      name="Name"
@@ -72,7 +62,27 @@
      label="UUID"
      name="UUID"
      value="search_by_UUID"/>
-    </combo_box>
+  </combo_box>
+  <menu_button
+   follows="top|left"
+   tool_tip="Show search visibility options"
+   height="23"
+   image_overlay="Inv_Toolbar_SearchVisibility"
+   layout="topleft"
+   left_pad="3"
+   name="options_visibility_btn"
+   width="31" />
+  <filter_editor
+   text_pad_left="10"
+   follows="left|top|right"
+   height="23"
+   label="Enter search text"
+   layout="topleft"
+   left_pad="3"
+   max_length_chars="300"
+   highlight_text_field="true"
+   name="inventory search editor"
+   width="177" />
   <tab_container
      follows="all"
      halign="center"
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index 2cc4abdd30..1c4822b8d5 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -6,9 +6,11 @@
   text_pad_left="7"
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
+  highlight_text_field="false"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
-  background_image_focused="TextField_Search_Active">
+  background_image_focused="TextField_Search_Active"
+  background_image_highlight="TextField_Search_Highlight">
   <search_button label=""
     top_pad="4"
     left_pad="4"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index faa0404b35..dc5a07bf4f 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -7,9 +7,11 @@
   text_pad_right="6" 
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
+  highlight_text_field="false"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
-  background_image_focused="TextField_Search_Active" >
+  background_image_focused="TextField_Search_Active"
+  background_image_highlight="TextField_Search_Highlight">
   <search_button 
     top_pad="4"
     left_pad="4" 
-- 
cgit v1.2.3


From b8c5f35a907ebeb551c8122e2d1dc2b77822c726 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 1 Sep 2020 20:03:03 +0300
Subject: SL-13852 Show menu below the button

---
 indra/newview/llpanelmaininventory.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index f845e9b056..7d04c1dc67 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1178,6 +1178,7 @@ void LLPanelMainInventory::initListCommandsHandlers()
 
 	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mVisibilityMenuButton->setMenu(mMenuVisibility);
+	mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT);
 
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
-- 
cgit v1.2.3


From 73ece917247d550140c0ae193746ebf66cca1081 Mon Sep 17 00:00:00 2001
From: maxim_productengine <mnikolenko@productengine.com>
Date: Mon, 17 Feb 2020 17:43:00 +0200
Subject: =?UTF-8?q?SL-11867=20Show=20=E2=80=9CUnable=20to=20buy=E2=80=9D?=
 =?UTF-8?q?=20message=20via=20notification?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 indra/newview/llfloaterbuycurrency.cpp             | 37 +++----------------
 .../skins/default/xui/da/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/de/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/en/floater_buy_currency.xml  | 42 +++-------------------
 .../newview/skins/default/xui/en/notifications.xml | 12 +++++++
 .../skins/default/xui/es/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/fr/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/it/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/ja/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/pl/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/pt/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/ru/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/tr/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/zh/floater_buy_currency.xml  |  5 ++-
 14 files changed, 43 insertions(+), 103 deletions(-)

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 91436e52fe..25348474a1 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -74,7 +74,6 @@ public:
 
 	void onClickBuy();
 	void onClickCancel();
-	void onClickErrorWeb();
 };
 
 LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
@@ -132,7 +131,6 @@ BOOL LLFloaterBuyCurrencyUI::postBuild()
 	
 	getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this));
 	getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this));
-	getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickErrorWeb, this));
 	
 	center();
 	
@@ -173,7 +171,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
 
 	// hide most widgets - we'll turn them on as needed next
 	getChildView("info_buying")->setVisible(FALSE);
-	getChildView("info_cannot_buy")->setVisible(FALSE);
 	getChildView("info_need_more")->setVisible(FALSE);	
 	getChildView("purchase_warning_repurchase")->setVisible(FALSE);
 	getChildView("purchase_warning_notenough")->setVisible(FALSE);
@@ -183,32 +180,16 @@ void LLFloaterBuyCurrencyUI::updateUI()
 	if (hasError)
 	{
 		// display an error from the server
-		getChildView("normal_background")->setVisible(FALSE);
-		getChildView("error_background")->setVisible(TRUE);
-		getChildView("info_cannot_buy")->setVisible(TRUE);
-		getChildView("cannot_buy_message")->setVisible(TRUE);
-		getChildView("balance_label")->setVisible(FALSE);
-		getChildView("balance_amount")->setVisible(FALSE);
-		getChildView("buying_label")->setVisible(FALSE);
-		getChildView("buying_amount")->setVisible(FALSE);
-		getChildView("total_label")->setVisible(FALSE);
-		getChildView("total_amount")->setVisible(FALSE);
-
-        LLTextBox* message = getChild<LLTextBox>("cannot_buy_message");
-        if (message)
-		{
-			message->setText(mManager.errorMessage());
-		}
-
-		getChildView("error_web")->setVisible( !mManager.errorURI().empty());
+		LLSD args;
+		args["TITLE"] = getString("info_cannot_buy");
+		args["MESSAGE"] = mManager.errorMessage();
+		LLNotificationsUtil::add("CouldNotBuyCurrency", args);
+		closeFloater();
 	}
 	else
 	{
 		// display the main Buy L$ interface
 		getChildView("normal_background")->setVisible(TRUE);
-		getChildView("error_background")->setVisible(FALSE);
-		getChildView("cannot_buy_message")->setVisible(FALSE);
-		getChildView("error_web")->setVisible(FALSE);
 
 		if (mHasTarget)
 		{
@@ -278,14 +259,6 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
 	LLStatusBar::sendMoneyBalanceRequest();
 }
 
-void LLFloaterBuyCurrencyUI::onClickErrorWeb()
-{
-	LLWeb::loadURL(mManager.errorURI());
-	closeFloater();
-	// Update L$ balance
-	LLStatusBar::sendMoneyBalanceRequest();
-}
-
 // static
 void LLFloaterBuyCurrency::buyCurrency()
 {
diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
index 3c0428b2b0..b7ac181dd4 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
@@ -60,8 +60,7 @@ objektet.
 	</text>
 	<button label="Køb nu" name="buy_btn"/>
 	<button label="Annullér" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+  <floater.string name="info_cannot_buy">
 		Kan ikke købe
-	</text>
-	<button label="Fortsæt til web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index 65926c088c..eb94df1cad 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Jetzt kaufen" name="buy_btn"/>
 	<button label="Abbrechen" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+  <floater.string name="info_cannot_buy">
 		Kaufabbruch
-	</text>
-	<button label="Weiter zur Kontoseite" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 553c5d51d0..061af1b67c 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -13,6 +13,10 @@
      name="buy_currency">
         Buy L$ [LINDENS] for approx. [LOCALAMOUNT]
     </floater.string>
+    <floater.string
+     name="info_cannot_buy">
+        Unable to Buy
+    </floater.string>
     <icon
      height="215"
      image_name="Linden_Dollar_Background"
@@ -286,42 +290,4 @@ Re-enter amount to see the latest exchange rate.
      left_pad="10"
      name="cancel_btn"
      width="90"/>
-    <icon
-     height="215"
-     image_name="Linden_Dollar_Alert"
-     layout="topleft"
-     left="0"
-     name="error_background"
-     top="15"
-     use_draw_context_alpha="false"
-     width="350"/>
-    <text
-     type="string"
-     font="SansSerifHuge"
-     left="165"
-     width="360"
-     height="25"
-     top="25"
-     name="info_cannot_buy">
-        Unable to Buy
-    </text>
-     <text
-      type="string"
-      width="176"
-      height="125"
-      top="60"
-      left="165"
-      word_wrap="true"
-      follows="bottom|right"
-      name="cannot_buy_message">
-     </text>
-     <button
-      follows="bottom|left"
-      height="20"
-      label="Continue to the Web"
-      layout="topleft"
-      left="170"
-      name="error_web"
-      top="200"
-      width="160"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d141cfc313..3228603f45 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1329,6 +1329,18 @@ There was a problem uploading a report screenshot due to the following reason: [
 You must agree to the Second Life Terms and Conditions, Privacy Policy, and Terms of Service to continue logging into [SECOND_LIFE].
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="CouldNotBuyCurrency"
+   type="alertmodal">
+[TITLE]
+[MESSAGE]
+   <tag>fail</tag>
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+  
   <notification
    icon="alertmodal.tga"
    name="CouldNotPutOnOutfit"
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index dbff3fcf0e..086150dd57 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,8 +60,7 @@ no el objeto.
 	</text>
 	<button label="Comprar ahora" name="buy_btn"/>
 	<button label="Cancelar" name="cancel_btn"/>
-	<text name="info_cannot_buy" left="150" font="SansSerifBig">
+	<floater.string name="info_cannot_buy">
 		No se pudo hacer la compra
-	</text>
-	<button label="Ir a la web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index c295172abf..55b0d1825a 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,8 +60,7 @@ le Lindex...
 	</text>
 	<button label="Acheter" name="buy_btn"/>
 	<button label="Annuler" name="cancel_btn"/>
-	<text name="info_cannot_buy" left="160" width="200">
+	<floater.string name="info_cannot_buy" left="160" width="200">
 		Achat impossible
-	</text>
-	<button label="Accéder au Web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 53a2057455..522d26373e 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,8 +60,7 @@ l&apos;oggetto.
 	</text>
 	<button label="Acquista" name="buy_btn"/>
 	<button label="Annulla" name="cancel_btn"/>
-	<text name="info_cannot_buy" left="160" font="SansSerifBig">
+	<floater.string name="info_cannot_buy" left="160" font="SansSerifBig">
 		Non in grado di acquistare
-	</text>
-	<button label="Continua sul Web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index a472f163e3..ac2db917cc 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="購入する" name="buy_btn"/>
 	<button label="取り消し" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		購入できません
-	</text>
-	<button label="Web サイトに移動" name="error_web" width="140"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
index 72167e0d3c..a1d703a15a 100644
--- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
@@ -50,8 +50,7 @@
 	</text>
 	<button label="Kup teraz" name="buy_btn" />
 	<button label="Anuluj" name="cancel_btn" />
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		Nie można kupić
-	</text>
-	<button label="Odwiedź stronę WWW" name="error_web" />
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index 513400954b..c740b90472 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Comprar já!" name="buy_btn"/>
 	<button label="Fechar" name="cancel_btn"/>
-	<text name="info_cannot_buy" font="SansSerifBig">
+	<floater.string name="info_cannot_buy">
 		Transação incompleta
-	</text>
-	<button label="Prosseguir para a web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
index 87e8bd524e..ef55ce58d4 100644
--- a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Приобрести" name="buy_btn"/>
 	<button label="Отмена" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		Нельзя купить
-	</text>
-	<button label="Продолжить в Интернете" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
index d90985dcff..33c4b2287f 100644
--- a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Şimdi Satın Al" name="buy_btn"/>
 	<button label="İptal" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		Satın Alınamıyor
-	</text>
-	<button label="Web&apos;e devam et" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
index fcf2800728..41c8c26ccc 100644
--- a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="立即購買" name="buy_btn"/>
 	<button label="取消" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		無法購買
-	</text>
-	<button label="繼續到網頁" name="error_web"/>
+	</floater.string>
 </floater>
-- 
cgit v1.2.3


From 1fb0e233ff67ada0c6d6351494a4b61ce7ff71e1 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 3 Sep 2020 17:29:06 +0300
Subject: SL-13814 Clarify dialog for insufficient L$ balance

---
 indra/newview/llcurrencyuimanager.cpp              |   7 +-
 indra/newview/llfloaterbuycurrency.cpp             |  61 +-
 .../skins/default/xui/en/floater_buy_currency.xml  | 624 ++++++++++++---------
 3 files changed, 416 insertions(+), 276 deletions(-)

diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index df94e337da..cd7332c4d4 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -454,7 +454,7 @@ void LLCurrencyUIManager::Impl::updateUI()
 		
 		if (!mUserEnteredCurrencyBuy)
 		{
-			if (!mZeroMessage.empty() && mUserCurrencyBuy == 0)
+			if (mUserCurrencyBuy == 0)
 			{
 				lindenAmount->setText(LLStringUtil::null);
 			}
@@ -467,8 +467,9 @@ void LLCurrencyUIManager::Impl::updateUI()
 		}
 	}
 
-	mPanel.getChild<LLUICtrl>("currency_est")->setTextArg("[LOCALAMOUNT]", getLocalEstimate());
-	mPanel.getChildView("currency_est")->setVisible( hasEstimate() && mUserCurrencyBuy > 0);
+	std::string estimated = (mUserCurrencyBuy == 0) ? mPanel.getString("estimated_zero") : getLocalEstimate();
+	mPanel.getChild<LLUICtrl>("currency_est")->setTextArg("[LOCALAMOUNT]", estimated);
+	mPanel.getChildView("currency_est")->setVisible( hasEstimate() || mUserCurrencyBuy == 0);
 
 	mPanel.getChildView("currency_links")->setVisible( mSupportsInternationalBilling);
 	mPanel.getChildView("exchange_rate_note")->setVisible( mSupportsInternationalBilling);
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 25348474a1..b039475389 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -32,6 +32,8 @@
 #include "llcurrencyuimanager.h"
 #include "llfloater.h"
 #include "llfloaterreg.h"
+#include "lllayoutstack.h"
+#include "lliconctrl.h"
 #include "llnotificationsutil.h"
 #include "llstatusbar.h"
 #include "lltextbox.h"
@@ -60,6 +62,7 @@ public:
 	bool		mHasTarget;
 	std::string	mTargetName;
 	S32			mTargetPrice;
+	S32			mRequiredAmount;
 	
 public:
 	void noTarget();
@@ -68,6 +71,7 @@ public:
 	virtual BOOL postBuild();
 	
 	void updateUI();
+	void collapsePanels(bool collapse);
 
 	virtual void draw();
 	virtual BOOL canClose();
@@ -92,7 +96,9 @@ LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
 LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI(const LLSD& key)
 :	LLFloater(key),
 	mChildren(*this),
-	mManager(*this)
+	mManager(*this),
+	mHasTarget(false),
+	mTargetPrice(0)
 {
 }
 
@@ -104,7 +110,8 @@ LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI()
 void LLFloaterBuyCurrencyUI::noTarget()
 {
 	mHasTarget = false;
-	mManager.setAmount(STANDARD_BUY_AMOUNT);
+	mTargetPrice = 0;
+	mManager.setAmount(0);
 }
 
 void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
@@ -120,7 +127,8 @@ void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
 		need = 0;
 	}
 	
-	mManager.setAmount(need + MINIMUM_BALANCE_AMOUNT);
+	mRequiredAmount = need + MINIMUM_BALANCE_AMOUNT;
+	mManager.setAmount(0);
 }
 
 
@@ -175,7 +183,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
 	getChildView("purchase_warning_repurchase")->setVisible(FALSE);
 	getChildView("purchase_warning_notenough")->setVisible(FALSE);
 	getChildView("contacting")->setVisible(FALSE);
-	getChildView("buy_action")->setVisible(FALSE);
 
 	if (hasError)
 	{
@@ -208,8 +215,8 @@ void LLFloaterBuyCurrencyUI::updateUI()
 		{
 			if (mHasTarget)
 			{
-				getChildView("buy_action")->setVisible( true);
-				getChild<LLUICtrl>("buy_action")->setTextArg("[ACTION]", mTargetName);
+				getChild<LLUICtrl>("target_price")->setTextArg("[AMT]", llformat("%d", mTargetPrice));
+				getChild<LLUICtrl>("required_amount")->setTextArg("[AMT]", llformat("%d", mRequiredAmount));
 			}
 		}
 		
@@ -230,18 +237,40 @@ void LLFloaterBuyCurrencyUI::updateUI()
 
 		if (mHasTarget)
 		{
-			if (total >= mTargetPrice)
-			{
-				getChildView("purchase_warning_repurchase")->setVisible( true);
-			}
-			else
-			{
-				getChildView("purchase_warning_notenough")->setVisible( true);
-			}
+			getChildView("purchase_warning_repurchase")->setVisible( !getChildView("currency_links")->getVisible());
 		}
 	}
 
-	getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError);
+	getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError && !getChildView("currency_est")->getVisible());
+}
+
+void LLFloaterBuyCurrencyUI::collapsePanels(bool collapse)
+{
+	LLLayoutPanel* price_panel = getChild<LLLayoutPanel>("layout_panel_price");
+	
+	if (price_panel->isCollapsed() == collapse)
+		return;
+	
+	LLLayoutStack* outer_stack = getChild<LLLayoutStack>("outer_stack");	
+	LLLayoutPanel* required_panel = getChild<LLLayoutPanel>("layout_panel_required");
+	LLLayoutPanel* msg_panel = getChild<LLLayoutPanel>("layout_panel_msg");
+
+	S32 delta_height = price_panel->getRect().getHeight() + required_panel->getRect().getHeight() + msg_panel->getRect().getHeight();
+	delta_height *= (collapse ? -1 : 1);
+
+	LLIconCtrl* icon = getChild<LLIconCtrl>("normal_background");
+	LLRect rect = icon->getRect();
+	icon->setRect(rect.setOriginAndSize(rect.mLeft, rect.mBottom - delta_height, rect.getWidth(), rect.getHeight() + delta_height));
+
+	outer_stack->collapsePanel(price_panel, collapse);
+	outer_stack->collapsePanel(required_panel, collapse);
+	outer_stack->collapsePanel(msg_panel, collapse);
+
+	outer_stack->updateLayout();
+
+	LLRect floater_rect = getRect();
+	floater_rect.mBottom -= delta_height;
+	setShape(floater_rect, false);
 }
 
 void LLFloaterBuyCurrencyUI::onClickBuy()
@@ -265,6 +294,7 @@ void LLFloaterBuyCurrency::buyCurrency()
 	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
 	ui->noTarget();
 	ui->updateUI();
+	ui->collapsePanels(true);
 }
 
 // static
@@ -273,6 +303,7 @@ void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
 	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
 	ui->target(name, price);
 	ui->updateUI();
+	ui->collapsePanels(false);
 }
 
 
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 061af1b67c..e8e83301be 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <floater
- legacy_header_height="18"
+
  can_minimize="false"
- height="275"
+ height="285"
  layout="topleft"
  title="BUY L$"
  name="buy currency"
@@ -17,277 +17,385 @@
      name="info_cannot_buy">
         Unable to Buy
     </floater.string>
+    <floater.string
+     name="estimated_zero">
+        US$ 0.00
+    </floater.string>
     <icon
-     height="215"
+     height="245"
      image_name="Linden_Dollar_Background"
      layout="topleft"
      left="0"
      name="normal_background"
-     top="17"
+     top="0"
      use_draw_context_alpha="false"
      width="350" />
-   <text
-     type="string"
-     length="1"
-     follows="top|left|right"
-     font="SansSerifHuge"
-     layout="topleft"
-     left="20"
-     height="30"
-     top="25"
-     width="340"
-     name="info_need_more">
-        You need more L$
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     height="16"
+  <layout_stack
+    animate="false"
+    name="outer_stack"
+    layout="topleft"
+    follows="all"
+    orientation="vertical"
+    left="0"
+    top="0"
+    width="350"
+    height="285">
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_title"
      layout="topleft"
-     top="246"
-     left="15"
-     width="300"
-     name="contacting">
-        Contacting LindeX...
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     font="SansSerifHuge"
+     follows="all"
+     width="350"
+     height="35">
+      <text
+       type="string"
+       length="1"
+       follows="top|left|right"
+       font="SansSerifLarge"
+       layout="topleft"
+       left="20"
+       height="30"
+       top="8"
+       width="340"
+       name="info_need_more">
+          You need more L$
+      </text>
+      <text
+       type="string"
+       length="1"
+       follows="top|left|right"
+       font="SansSerifLarge"
+       layout="topleft"
+       left="20"
+       height="30"
+       top="8"
+       width="300"
+       name="info_buying">
+          Buy L$
+      </text>
+      <view_border
+       bevel_style="none"
+       height="0"
+       layout="topleft"
+       left="20"
+       name="text_border"
+       top_delta="25"
+       width="300"/>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_price"
      layout="topleft"
-     left="20"
-     height="30"
-     top="25"
-     width="300"
-     name="info_buying">
-        Buy L$
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     font="SansSerifMedium"
-     height="16"
+     follows="all"
+     width="350"
+     height="18">
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       font="SansSerifMedium"
+       height="16"
+       layout="topleft"
+       left="20"
+       name="target_price_label"
+       top_pad="3"
+       width="210">
+          You need
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       halign="right"
+       height="16"
+       layout="topleft"
+       left="200"
+       name="target_price"
+       top_delta="0"
+       width="120">
+          L$ [AMT]
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_balance"
      layout="topleft"
-     left="20"
-     name="balance_label"
-     top="65"
-     width="210">
-        I have
-    </text>
-    <text
-     type="string"
-     length="1"
-     font="SansSerifMedium"
-     follows="top|left"
-     halign="right"
-     height="16"
-     layout="topleft"
-     left="200"
-     name="balance_amount"
-     top_delta="0"
-     width="120">
+     follows="all"
+     width="350"
+     height="19">
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       font="SansSerifMedium"
+       height="16"
+       layout="topleft"
+       left="20"
+       name="balance_label"
+       top_pad="5"
+       width="210">
+        You now have
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       halign="right"
+       height="16"
+       layout="topleft"
+       left="200"
+       name="balance_amount"
+       top_delta="0"
+       width="120">
         L$ [AMT]
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     font="SansSerifMedium"
-     height="16"
-     top="95"
-     layout="topleft"
-     left="20"
-     name="currency_action"
-     width="210">
-        I want to buy
-    </text>
-    <text
-     font="SansSerifMedium"
-     type="string"
-     length="1"
-     follows="left|top"
-     height="16"
-     layout="topleft"
-     top_delta="0"
-     left="217"
-     name="currency_label"
-     width="15">
-      L$
-    </text>
-    <line_editor
-     type="string"
-     max_length_bytes="10"
-     halign="right"
-     font="SansSerifMedium"
-     select_on_focus="true"
-     follows="top|left"
-     top_delta="-7"
-     height="22"
-     label="L$"
-     left_pad="3"
-     name="currency_amt"
-     width="85">
-        1234
-    </line_editor>
-    <text
-     type="string"
-     font="SansSerifMedium"
-     length="1"
-     follows="top|left"
-     height="16"
-     layout="topleft"
-     left="20"
-     top="125"
-     name="buying_label"
-     width="210">
-        For the price
-    </text>
-    <text
-     type="string"
-     length="1"
-     font="SansSerifMedium"
-     text_color="EmphasisColor"
-     follows="top|left"
-     halign="right"
-     height="16"
-     top_delta="0"
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_required"
      layout="topleft"
-     left="150"
-     name="currency_est"
-     width="170">
-     approx. [LOCALAMOUNT]
-    </text>
-    <text
-     type="string"
-     font="SansSerifSmall"
-     text_color="EmphasisColor"
-     length="1"
-     follows="top|left"
-     height="16"
-     layout="topleft"
-     top="125"
-     left="170"
-     width="150"
-     halign="right"
-     name="getting_data">
-        Estimating...
-    </text>
-    <text
-     type="string"
-     font="SansSerifSmall"
-     top="145"
-     length="1"
-     follows="top|left"
-     height="16"
-     halign="right"
-     left="20"
-     width="300"
-     layout="topleft"
-     name="buy_action">
-        [ACTION]
-    </text>
-    <text
-     type="string"
-     font="SansSerifMedium"
-     length="1"
-     follows="top|left"
-     height="16"
-     layout="topleft"
-     left="20"
-     name="total_label"
-     top="165"
-     width="210">
-        My new balance will be
-    </text>
-    <text
-     type="string"
-     length="1"
-     font="SansSerifMedium"
-     follows="top|left"
-     top_delta="0"
-     height="16"
-     layout="topleft"
-     left="200"
-     halign="right"
-     name="total_amount"
-     width="120">
+     follows="all"
+     width="350"
+     height="22">
+      <text
+        type="string"
+        length="1"
+        follows="top|left"
+        font="SansSerifMedium"
+        font.style="BOLD"
+        height="16"
+        layout="topleft"
+        left="20"
+        name="required_label"
+        top_pad="6"
+        width="210">
+        You should buy at least
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       halign="right"
+       height="16"
+       layout="topleft"
+       left="200"
+       name="required_amount"
+       top_delta="0"
+       width="120">
         L$ [AMT]
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_action"
      layout="topleft"
-     halign="right"
-     top="189"
-     left="20"
-     width="300"
-     height="30"
-     name="currency_links">
-      [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
+     follows="all"
+     width="350"
+     height="90">
+      <view_border
+       bevel_style="none"
+       height="0"
+       layout="topleft"
+       left="20"
+       name="text_border_2"
+       top_pad="5"
+       width="300"/>
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       font="SansSerifMedium"
+       height="16"
+       top_pad="15"
+       layout="topleft"
+       left="20"
+       name="currency_action"
+       width="210">
+          Choose amount to buy
+      </text>
+      <text
+       font="SansSerifMedium"
+       type="string"
+       length="1"
+       follows="left|top"
+       height="16"
+       layout="topleft"
+       top_delta="0"
+       left="247"
+       name="currency_label"
+       width="15">
+        L$
+      </text>
+      <line_editor
+       type="string"
+       max_length_bytes="10"
+       halign="right"
+       font="SansSerifMedium"
+       select_on_focus="true"
+       follows="top|left"
+       top_delta="-4"
+       height="22"
+       label="L$"
+       left_pad="3"
+       name="currency_amt"
+       width="55">
+          1234
+      </line_editor>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       text_color="EmphasisColor"
+       follows="top|left"
+       halign="right"
+       height="16"
+       top_pad="4"
+       layout="topleft"
+       left="150"
+       name="currency_est"
+       width="170">
+       Approx. [LOCALAMOUNT]
+      </text>
+      <text
+       type="string"
+       font="SansSerifSmall"
+       text_color="EmphasisColor"
+       length="1"
+       follows="top|left"
+       height="16"
+       layout="topleft"
+       left="170"
+       top_delta="0"
+       width="150"
+       halign="right"
+       name="getting_data">
+          Estimating...
+      </text>
+      <text
+       type="string"
+       font="SansSerifMedium"
+       length="1"
+       follows="top|left"
+       height="16"
+       layout="topleft"
+       left="20"
+       name="total_label"
+       top_pad="10"
+       width="210">
+          Your new balance will be
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       top_delta="0"
+       height="16"
+       layout="topleft"
+       left="200"
+       halign="right"
+       name="total_amount"
+       width="120">
+          L$ [AMT]
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_msg"
      layout="topleft"
-     halign="right"
-     top="202"
-     left="20"
-     width="300"
-     height="30"
-     name="exchange_rate_note">
+     follows="all"
+     width="350"
+     height="50">
+      <view_border
+       bevel_style="none"
+       height="0"
+       layout="topleft"
+       left="20"
+       name="text_border_3"
+       top_pad="0"
+       width="300"/>
+      <text
+       type="string"
+       length="1"
+       text_color="LtGray_50"
+       follows="top|left"
+       layout="topleft"
+       halign="right"
+       top_pad="3"
+       left="20"
+       width="300"
+       height="30"
+       name="currency_links">
+        [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
+      </text>
+      <text
+       type="string"
+       length="1"
+       text_color="LtGray_50"
+       follows="top|left"
+       layout="topleft"
+       halign="right"
+       top="19"
+       left="20"
+       width="300"
+       height="30"
+       name="exchange_rate_note">
 Re-enter amount to see the latest exchange rate.
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
-     layout="topleft"
-     halign="right"
-     top="208"
-     left="10"
-     width="310"
-     height="35"
-     name="purchase_warning_repurchase">
-        Confirming this purchase only buys L$, not the object.
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
-     layout="topleft"
-     halign="right"
-     top="213"
-     left="20"
-     width="300"
-     height="30"
-     name="purchase_warning_notenough">
-        You aren&apos;t buying enough L$. Please increase the amount.
-    </text>
-
-    <button
-     follows="bottom|left"
-     height="20"
-     label="Buy Now"
-     layout="topleft"
-     left="151"
-     name="buy_btn"
-     top="242"
-     width="90"/>
-    <button
-     follows="bottom|right"
-     height="20"
-     label="Cancel"
+      </text>
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       layout="topleft"
+       font="SansSerifMedium"
+       top="10"
+       left="20"
+       width="310"
+       height="35"
+       name="purchase_warning_repurchase">
+After you receive your L$, you should try your
+purchase again.
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_buttons"
      layout="topleft"
-     left_pad="10"
-     name="cancel_btn"
-     width="90"/>
+     follows="all"
+     width="350"
+     height="40">
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       height="16"
+       layout="topleft"
+       top_pad="0"
+       left="15"
+       width="300"
+       name="contacting">
+          Contacting LindeX...
+        </text>
+      <button
+       follows="top|left|right"
+       height="20"
+       label="Buy L$ now"
+       layout="topleft"
+       left="151"
+       name="buy_btn"
+       bottom_delta ="8"
+       width="90"/>
+      <button
+       follows="top|left|right"
+       height="20"
+       label="Cancel"
+       layout="topleft"
+       left_pad="10"     
+       name="cancel_btn"
+       width="90"/>
+    </layout_panel>
+  </layout_stack>
 </floater>
-- 
cgit v1.2.3


From 9dd18e51c897fa9c3e1dab7c5abbc771c98361db Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 3 Sep 2020 19:39:57 +0300
Subject: SL-13814 mac build fix

---
 indra/newview/llfloaterbuycurrency.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index b039475389..b183ba6912 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -44,7 +44,6 @@
 #include "llwindow.h"
 #include "llappviewer.h"
 
-static const S32 STANDARD_BUY_AMOUNT = 2000;
 static const S32 MINIMUM_BALANCE_AMOUNT = 0;
 
 class LLFloaterBuyCurrencyUI
-- 
cgit v1.2.3


From 749464660f6241730231d9621e9bf05ba983480d Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 4 Sep 2020 19:55:26 +0300
Subject: SL-13814 Updated label text

---
 indra/newview/llfloaterbuycurrency.cpp         |  7 +++++--
 indra/newview/llviewermenu.cpp                 |  2 +-
 indra/newview/llviewermenufile.cpp             | 10 ++--------
 indra/newview/skins/default/xui/en/strings.xml |  8 ++++----
 4 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index b183ba6912..dfc755c370 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -59,7 +59,6 @@ public:
 	LLCurrencyUIManager	mManager;
 	
 	bool		mHasTarget;
-	std::string	mTargetName;
 	S32			mTargetPrice;
 	S32			mRequiredAmount;
 	
@@ -116,9 +115,13 @@ void LLFloaterBuyCurrencyUI::noTarget()
 void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
 {
 	mHasTarget = true;
-	mTargetName = name;
 	mTargetPrice = price;
 	
+	if (!name.empty())
+	{
+		getChild<LLUICtrl>("target_price_label")->setValue(name);
+	}
+
 	S32 balance = gStatusBar->getBalance();
 	S32 need = price - balance;
 	if (need < 0)
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b6c7be2ed3..4e635a88ce 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -4891,7 +4891,7 @@ void handle_buy_or_take()
 		{
 			LLStringUtil::format_map_t args;
 			args["AMOUNT"] = llformat("%d", total_price);
-			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "BuyingCosts", args ), total_price );
+			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price );
 		}
 	}
 	else
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index cd48b1e8e7..7d52607cba 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -825,10 +825,7 @@ void upload_done_callback(
 				
 				if(!(can_afford_transaction(expected_upload_cost)))
 				{
-					LLStringUtil::format_map_t args;
-					args["NAME"] = data->mAssetInfo.getName();
-					args["AMOUNT"] = llformat("%d", expected_upload_cost);
-					LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("UploadingCosts", args), expected_upload_cost );
+					LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost );
 					is_balance_sufficient = FALSE;
 				}
 				else if(region)
@@ -962,10 +959,7 @@ void upload_new_resource(
 			if (balance < uploadInfo->getExpectedUploadCost())
 			{
 				// insufficient funds, bail on this upload
-				LLStringUtil::format_map_t args;
-				args["NAME"] = uploadInfo->getName();
-                args["AMOUNT"] = llformat("%d", uploadInfo->getExpectedUploadCost());
-                LLBuyCurrencyHTML::openCurrencyFloater(LLTrans::getString("UploadingCosts", args), uploadInfo->getExpectedUploadCost());
+                LLBuyCurrencyHTML::openCurrencyFloater("", uploadInfo->getExpectedUploadCost());
 				return;
 			}
 		}
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 8a87199551..9e45e2e3bf 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2834,7 +2834,6 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="AcquiredItems">Acquired Items</string>
 	<string name="Cancel">Cancel</string>
 	<string name="UploadingCosts">Uploading [NAME] costs L$ [AMOUNT]</string>
-	<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>
 	<string name="UnknownFileExtension">
 		Unknown file extension .%s
 Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
@@ -3790,11 +3789,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="to upload">to upload</string>
   <string name="to publish a classified ad">to publish a classified ad</string>
 
-  <string name="giving">Giving L$ [AMOUNT]</string>
   <string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
   <string name="this_costs">This costs L$ [AMOUNT]</string>
-  <string name="buying_selected_land">Buying selected land for L$ [AMOUNT]</string>
-  <string name="this_object_costs">This object costs L$ [AMOUNT]</string>
+  
+  <string name="buying_selected_land">This land costs</string>
+  <string name="this_object_costs">This item costs</string>
+  <string name="giving">You want to give</string>
 
   <string name="group_role_everyone">Everyone</string>
   <string name="group_role_officers">Officers</string>
-- 
cgit v1.2.3


From 2c0814b00a26d99de00161f9307e706a49251017 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 22 Sep 2020 18:26:23 +0300
Subject: SL-13335 Friendlier L$ Buy flow when no payment method on file

---
 indra/llui/llnotifications.cpp                     |   1 +
 indra/llui/llnotifications.h                       |   1 +
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/llavatarpropertiesprocessor.cpp      |  13 ++
 indra/newview/llavatarpropertiesprocessor.h        |   2 +
 indra/newview/llfloateraddpaymentmethod.cpp        |  81 ++++++++++++
 indra/newview/llfloateraddpaymentmethod.h          |  52 ++++++++
 indra/newview/llfloaterbuycurrency.cpp             |  66 ++++++++--
 indra/newview/llfloaterbuycurrency.h               |  24 +++-
 indra/newview/lltoastalertpanel.cpp                |  35 ++++-
 indra/newview/lltoastalertpanel.h                  |   1 +
 indra/newview/llviewerfloaterreg.cpp               |   2 +
 indra/newview/skins/default/colors.xml             |   3 +
 indra/newview/skins/default/textures/textures.xml  |   4 +
 .../textures/windows/add_payment_image_center.png  | Bin 0 -> 31996 bytes
 .../textures/windows/add_payment_image_left.png    | Bin 0 -> 30102 bytes
 .../textures/windows/add_payment_image_right.png   | Bin 0 -> 29761 bytes
 .../default/xui/en/floater_add_payment_method.xml  | 141 +++++++++++++++++++++
 .../newview/skins/default/xui/en/notifications.xml |  23 +++-
 19 files changed, 434 insertions(+), 17 deletions(-)
 create mode 100644 indra/newview/llfloateraddpaymentmethod.cpp
 create mode 100644 indra/newview/llfloateraddpaymentmethod.h
 create mode 100644 indra/newview/skins/default/textures/windows/add_payment_image_center.png
 create mode 100644 indra/newview/skins/default/textures/windows/add_payment_image_left.png
 create mode 100644 indra/newview/skins/default/textures/windows/add_payment_image_right.png
 create mode 100644 indra/newview/skins/default/xui/en/floater_add_payment_method.xml

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 6a7075301b..8d522cd2e3 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -77,6 +77,7 @@ LLNotificationForm::FormButton::FormButton()
 	text("text"),
 	ignore("ignore"),
 	is_default("default"),
+	width("width", 0),
 	type("type")
 {
 	// set type here so it gets serialized
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index cac687f53d..048f07de9e 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -191,6 +191,7 @@ public:
 		Mandatory<std::string>	text;
 		Optional<std::string>	ignore;
 		Optional<bool>			is_default;
+		Optional<S32>			width;
 
 		Mandatory<std::string>	type;
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 88667bdc11..8bb5126b91 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -209,6 +209,7 @@ set(viewer_SOURCE_FILES
     llflexibleobject.cpp
     llfloaterabout.cpp
     llfloaterbvhpreview.cpp
+    llfloateraddpaymentmethod.cpp
     llfloaterauction.cpp
     llfloaterautoreplacesettings.cpp
     llfloateravatar.cpp
@@ -839,6 +840,7 @@ set(viewer_HEADER_FILES
     llflexibleobject.h
     llfloaterabout.h
     llfloaterbvhpreview.h
+    llfloateraddpaymentmethod.h
     llfloaterauction.h
     llfloaterautoreplacesettings.h
     llfloateravatar.h
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index 856eb3414e..f41eb3daf4 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -253,6 +253,19 @@ std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_
 	return LLTrans::getString(payment_text);
 }
 
+//static
+bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avatar_data)
+{
+	// Special accounts like M Linden don't have payment info revealed.
+	if (!avatar_data->caption_text.empty()) return true;
+
+	// Linden employees don't have payment info revealed
+	const S32 LINDEN_EMPLOYEE_INDEX = 3;
+	if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return true;
+
+	return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED));
+}
+
 void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**)
 {
 	LLAvatarData avatar_data;
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index d5c5c75c69..b063048c26 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -232,6 +232,8 @@ public:
 	// Used for profiles, inspectors.
 	static std::string paymentInfo(const LLAvatarData* avatar_data);
 
+	static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data);
+
 	static void processAvatarPropertiesReply(LLMessageSystem* msg, void**);
 
 	static void processAvatarInterestsReply(LLMessageSystem* msg, void**);
diff --git a/indra/newview/llfloateraddpaymentmethod.cpp b/indra/newview/llfloateraddpaymentmethod.cpp
new file mode 100644
index 0000000000..3952b48229
--- /dev/null
+++ b/indra/newview/llfloateraddpaymentmethod.cpp
@@ -0,0 +1,81 @@
+/** 
+ * @file llfloateraddpaymentmethod.cpp
+ * @brief LLFloaterAddPaymentMethod class implementation
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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 "llfloateraddpaymentmethod.h"
+#include "llnotificationsutil.h"
+#include "lluictrlfactory.h"
+#include "llweb.h"
+
+
+LLFloaterAddPaymentMethod::LLFloaterAddPaymentMethod(const LLSD& key)
+	:	LLFloater(key)
+{
+}
+
+LLFloaterAddPaymentMethod::~LLFloaterAddPaymentMethod()
+{
+}
+
+BOOL LLFloaterAddPaymentMethod::postBuild()
+{
+	setCanDrag(FALSE);
+	getChild<LLButton>("continue_btn")->setCommitCallback(boost::bind(&LLFloaterAddPaymentMethod::onContinueBtn, this));
+	getChild<LLButton>("close_btn")->setCommitCallback(boost::bind(&LLFloaterAddPaymentMethod::onCloseBtn, this));
+	return TRUE;
+}
+
+void LLFloaterAddPaymentMethod::onOpen(const LLSD& key)
+{
+	centerOnScreen();
+}
+
+void LLFloaterAddPaymentMethod::onContinueBtn()
+{
+	closeFloater();
+	LLNotificationsUtil::add("AddPaymentMethod", LLSD(), LLSD(),
+		[this](const LLSD&notif, const LLSD&resp)
+	{
+		S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+		if (opt == 0)
+		{
+			LLWeb::loadURL(this->getString("continue_url"));
+		}
+	}); 
+}
+
+void LLFloaterAddPaymentMethod::onCloseBtn()
+{
+	closeFloater();
+}
+
+void LLFloaterAddPaymentMethod::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/llfloateraddpaymentmethod.h b/indra/newview/llfloateraddpaymentmethod.h
new file mode 100644
index 0000000000..b3bb624484
--- /dev/null
+++ b/indra/newview/llfloateraddpaymentmethod.h
@@ -0,0 +1,52 @@
+/** 
+ * @file llfloateraddpaymentmethod.h
+ * @brief LLFloaterAddPaymentMethod class definition
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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_ADDPAYMENTMETHOD_H
+#define LL_FLOATER_ADDPAYMENTMETHOD_H
+
+#include "llfloater.h"
+
+class LLFloaterAddPaymentMethod:
+	public LLFloater
+{
+	friend class LLFloaterReg;
+public:
+	/*virtual*/	BOOL postBuild();
+	/*virtual*/ void onOpen(const LLSD& key);
+
+private:
+	LLFloaterAddPaymentMethod(const LLSD& key);
+
+	void centerOnScreen();
+
+	void onCloseBtn();
+	void onContinueBtn();
+	
+	/*virtual*/	~LLFloaterAddPaymentMethod();
+
+};
+
+#endif
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index dfc755c370..a3e9161ee8 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -290,22 +290,72 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
 	LLStatusBar::sendMoneyBalanceRequest();
 }
 
+LLFetchAvatarPaymentInfo* LLFloaterBuyCurrency::sPropertiesRequest = NULL;
+
 // static
 void LLFloaterBuyCurrency::buyCurrency()
 {
-	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
-	ui->noTarget();
-	ui->updateUI();
-	ui->collapsePanels(true);
+	delete sPropertiesRequest;
+	sPropertiesRequest = new LLFetchAvatarPaymentInfo(false);
 }
 
 // static
 void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
 {
-	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
-	ui->target(name, price);
-	ui->updateUI();
-	ui->collapsePanels(false);
+	delete sPropertiesRequest;
+	sPropertiesRequest = new LLFetchAvatarPaymentInfo(true, name, price);
 }
 
+// static
+void LLFloaterBuyCurrency::handleBuyCurrency(bool has_piof, bool has_target, const std::string& name, S32 price)
+{
+	delete sPropertiesRequest;
+	sPropertiesRequest = NULL;
 
+	if (has_piof)
+	{
+		LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
+		if (has_target)
+		{
+			ui->target(name, price);
+		}
+		else
+		{
+			ui->noTarget();			
+		}
+		ui->updateUI();
+		ui->collapsePanels(!has_target);
+	}
+	else
+	{
+		LLFloaterReg::showInstance("add_payment_method");
+	}
+}
+
+LLFetchAvatarPaymentInfo::LLFetchAvatarPaymentInfo(bool has_target, const std::string& name, S32 price)
+:	mAvatarID(gAgent.getID()),
+	mHasTarget(has_target),
+	mPrice(price),
+	mName(name)
+{
+	LLAvatarPropertiesProcessor* processor = LLAvatarPropertiesProcessor::getInstance();
+	// register ourselves as an observer
+	processor->addObserver(mAvatarID, this);
+	// send a request (duplicates will be suppressed inside the avatar
+	// properties processor)
+	processor->sendAvatarPropertiesRequest(mAvatarID);
+}
+
+LLFetchAvatarPaymentInfo::~LLFetchAvatarPaymentInfo()
+{
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarID, this);
+}
+
+void LLFetchAvatarPaymentInfo::processProperties(void* data, EAvatarProcessorType type)
+{
+	if (data && type == APT_PROPERTIES)
+	{
+		LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+		LLFloaterBuyCurrency::handleBuyCurrency(LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(avatar_data), mHasTarget, mName, mPrice);
+	}
+}
diff --git a/indra/newview/llfloaterbuycurrency.h b/indra/newview/llfloaterbuycurrency.h
index 7ff6c42384..1722f56dc1 100644
--- a/indra/newview/llfloaterbuycurrency.h
+++ b/indra/newview/llfloaterbuycurrency.h
@@ -27,15 +27,34 @@
 #ifndef LL_LLFLOATERBUYCURRENCY_H
 #define LL_LLFLOATERBUYCURRENCY_H
 
+#include "llavatarpropertiesprocessor.h"
 #include "stdtypes.h"
-
+#include "llagent.h"
 class LLFloater;
 
+class LLFetchAvatarPaymentInfo : public LLAvatarPropertiesObserver
+{
+public:
+	LLFetchAvatarPaymentInfo(bool has_target, const std::string& name = std::string(), S32 price = 0);
+	~LLFetchAvatarPaymentInfo();
+
+	void processProperties(void* data, EAvatarProcessorType type);
+
+private:
+	LLUUID mAvatarID;
+	bool mHasTarget;
+	std::string mName;
+    S32 mPrice;
+};
+
+
 class LLFloaterBuyCurrency
 {
 public:
 	static void buyCurrency();
 	static void buyCurrency(const std::string& name, S32 price);
+
+		static void handleBuyCurrency(bool has_piof, bool has_target, const std::string& name, S32 price);
 		/* name should be a noun phrase of the object or service being bought:
 				"That object costs"
 				"Trying to give"
@@ -44,7 +63,8 @@ public:
 		*/
 	
 	static LLFloater* buildFloater(const LLSD& key);
-};
 
+	static LLFetchAvatarPaymentInfo* sPropertiesRequest;
+};
 
 #endif
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 6a29be4aa1..af8cb8b5cb 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -121,6 +121,15 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 				data.mURLExternal = mNotification->getURLOpenExternally();
 			}
 
+			if((*it).has("width"))
+			{
+				data.mWidth = (*it)["width"].asInteger();
+			}
+			else
+			{
+				data.mWidth = 0;
+			}
+
 			mButtonData.push_back(data);
 			option_index++;
 		}
@@ -159,15 +168,29 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 	// Calc total width of buttons
 	S32 button_width = 0;
 	S32 sp = font->getWidth(std::string("OO"));
+	S32 btn_total_width = 0;
+	S32 default_size_btns = 0;
 	for( S32 i = 0; i < num_options; i++ )
-	{
+	{				
 		S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
-		button_width = llmax( w, button_width );
+		if (mButtonData[i].mWidth > w)
+		{
+			btn_total_width += mButtonData[i].mWidth;
+		}
+		else
+		{
+			button_width = llmax(w, button_width);
+			default_size_btns++;
+		}
 	}
-	S32 btn_total_width = button_width;
+
 	if( num_options > 1 )
 	{
-		btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD);
+		btn_total_width = btn_total_width + (button_width * default_size_btns) + ((num_options - 1) * BTN_HPAD);
+	}
+	else
+	{
+		btn_total_width = llmax(btn_total_width, button_width);
 	}
 
 	// Message: create text box using raw string, as text has been structure deliberately
@@ -333,7 +356,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 		if(btn)
 		{
 			btn->setName(options[i].first);
-			btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ));
+			btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, (mButtonData[i].mWidth == 0) ? button_width : mButtonData[i].mWidth, BTN_HEIGHT ));
 			btn->setLabel(options[i].second);
 			btn->setFont(font);
 
@@ -348,7 +371,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 				btn->setFocus(TRUE);
 			}
 		}
-		button_left += button_width + BTN_HPAD;
+		button_left += ((mButtonData[i].mWidth == 0) ? button_width : mButtonData[i].mWidth) + BTN_HPAD;
 	}
 
 	setCheckBoxes(HPAD, VPAD);
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index 9b4e054bf1..7ffe328439 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -85,6 +85,7 @@ private:
 		LLButton* mButton;
 		std::string mURL;
 		U32 mURLExternal;
+		S32 mWidth;
 	};
 	std::vector<ButtonData> mButtonData;
 
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 414ae1fad6..06587d6025 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -34,6 +34,7 @@
 #include "llcompilequeue.h"
 #include "llfasttimerview.h"
 #include "llfloaterabout.h"
+#include "llfloateraddpaymentmethod.h"
 #include "llfloaterauction.h"
 #include "llfloaterautoreplacesettings.h"
 #include "llfloateravatar.h"
@@ -194,6 +195,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterAboutUtil::registerFloater();
 	LLFloaterReg::add("block_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>);
 	LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);
+	LLFloaterReg::add("add_payment_method", "floater_add_payment_method.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAddPaymentMethod>);
 	LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
 	LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>);
 	LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index e0da7f5d9e..57325739e4 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -957,4 +957,7 @@
   <color
     name="OutfitGalleryItemUnselected"
     value="0.4 0.4 0.4 1" />
+  <color
+    name="AddPaymentPanel"
+    value="0.27 0.27 0.27 1" />
 </colors>
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 1302edda7a..f906843ef1 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -45,6 +45,10 @@ with the same filename but different name
   <texture name="AddItem_Off" file_name="icons/AddItem_Off.png" preload="false" />
   <texture name="AddItem_Press" file_name="icons/AddItem_Press.png" preload="false" />
 
+  <texture name="add_payment_image_center"  file_name="windows/add_payment_image_center.png" preload="true" />
+  <texture name="add_payment_image_left"  file_name="windows/add_payment_image_left.png" preload="true" />
+  <texture name="add_payment_image_right"  file_name="windows/add_payment_image_right.png" preload="true" />
+
   <texture name="Arrow_Left_Off" file_name="navbar/Arrow_Left_Off.png" preload="true" />
   <texture name="Arrow_Right_Off" file_name="navbar/Arrow_Right_Off.png" preload="true" />
 
diff --git a/indra/newview/skins/default/textures/windows/add_payment_image_center.png b/indra/newview/skins/default/textures/windows/add_payment_image_center.png
new file mode 100644
index 0000000000..b5459136cb
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/add_payment_image_center.png differ
diff --git a/indra/newview/skins/default/textures/windows/add_payment_image_left.png b/indra/newview/skins/default/textures/windows/add_payment_image_left.png
new file mode 100644
index 0000000000..7fb65e724a
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/add_payment_image_left.png differ
diff --git a/indra/newview/skins/default/textures/windows/add_payment_image_right.png b/indra/newview/skins/default/textures/windows/add_payment_image_right.png
new file mode 100644
index 0000000000..f1937b6318
Binary files /dev/null and b/indra/newview/skins/default/textures/windows/add_payment_image_right.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
new file mode 100644
index 0000000000..5296719339
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ height="405"
+ width="900"
+ layout="topleft"
+ name="floater_add_payment_method"
+ single_instance="true"
+ show_title="false"
+ legacy_header_height="0"
+ header_height="0"
+ background_visible="false"
+ can_resize="false"
+ can_drag_on_left="false"
+ can_minimize="false"
+ can_close="false">
+  <floater.string
+    name="continue_url">
+    https://secondlife.com/my/lindex/buy.php?associate_for_viewer=1
+  </floater.string>
+  <panel
+   background_opaque="false"
+   bg_alpha_color="AddPaymentPanel"
+   border_visible="false"
+   background_visible="true"
+   label="wrapper_panel"
+   layout="topleft"
+   left="0"
+   name="wrapper_panel"
+   top="0"
+   height="405"
+   width="900"
+   follows="all"
+   translate="false">
+    <text
+     type="string"
+     length="1"
+     follows="top|left|right"
+     font="SansSerifLargeBold"
+     text_color="White"
+     layout="topleft"
+     left="0"
+     height="14"
+     top_pad="30"
+     width="900"
+     halign="center"
+     name="title_txt">
+      Add a payment method to buy Linden dollars and enjoy more of Second Life.
+    </text>
+    <button
+     follows="top|left|right"
+     height="24"
+     label="Get started"
+     font="SansSerifMedium"
+     font.style="BOLD"
+     layout="topleft"
+     left="320"
+     name="continue_btn"
+     image_unselected="PushButton_Login"
+     image_pressed="PushButton_Login_Pressed"
+     image_hover_unselected="PushButton_Login_Over"
+     label_color="White"
+     top_pad ="15"
+     width="140"/>
+    <button
+     follows="top|left|right"
+     height="24"
+     label="Later"
+     layout="topleft"
+     left_pad="9"
+     name="close_btn"
+     width="90"/>
+    <icon
+     height="195"
+     width="260" 
+     image_name="add_payment_image_left"
+     layout="topleft"
+     left="30"
+     name="image_left"
+     top_pad="30"
+     use_draw_context_alpha="false"/>
+    <icon
+     height="195"
+     width="260"
+     image_name="add_payment_image_center"
+     layout="topleft"
+     left_pad="30"
+     name="image_center"
+     use_draw_context_alpha="false"/>
+    <icon
+     height="195"
+     width="260"
+     image_name="add_payment_image_right"
+     layout="topleft"
+     left_pad="30"
+     name="image_right"
+     use_draw_context_alpha="false"/>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifMedium"
+     text_color="White"
+     height="75"
+     width="260"
+     top_pad="15"
+     layout="topleft"
+     word_wrap="true"
+     left="30"
+     name="image_left_desc">
+      Create an avatar you love. Choose from millions of items in stores and the Second Life Marketplace. Your style is here.
+    </text>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifMedium"
+     text_color="White"
+     height="75"
+     width="260"
+     layout="topleft"
+     word_wrap="true"
+     left_pad="30"
+     name="image_center_desc">
+      Donate to your favorite performers and hosts. Your support helps them create great experiences.
+    </text>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifMedium"
+     text_color="White"
+     height="75"
+     width="260"
+     layout="topleft"
+     word_wrap="true"
+     left_pad="30"
+     name="image_right_desc">
+      Make the home of your dreams. With millions of items available to purchase, you can make your retreat unique.
+    </text>
+  </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 3228603f45..c53b4ca800 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -11446,7 +11446,28 @@ Cannot create large prims that intersect other residents.  Please re-try when ot
      name="okbutton"
      yestext="OK"/>
   </notification>
-  
+
+  <notification
+   icon="alertmodal.tga"
+   name="AddPaymentMethod"
+   type="alertmodal">
+On the following page, choose a L$ amount
+and click a place Order button. You will be
+able to add a payment method at checkout.
+    <tag>confirm</tag>
+    <form name="form">
+      <button
+       default="true"
+       index="0"
+       width="120"
+       name="Continue"
+       text="Continue"/>
+      <button
+       index="1"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
   
   <notification
    icon="alert.tga"
-- 
cgit v1.2.3


From 7ae4f766f03fa9046c30ee868697e7ec637b6ad0 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 16:57:54 +0300
Subject: SL-13335 Init default button width

---
 indra/newview/lltoastalertpanel.cpp | 4 ----
 indra/newview/lltoastalertpanel.h   | 4 ++++
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index af8cb8b5cb..4f46d1c0a2 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -125,10 +125,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 			{
 				data.mWidth = (*it)["width"].asInteger();
 			}
-			else
-			{
-				data.mWidth = 0;
-			}
 
 			mButtonData.push_back(data);
 			option_index++;
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index 7ffe328439..bd34e40642 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -82,6 +82,10 @@ private:
 
 	struct ButtonData
 	{
+		ButtonData()
+		: mWidth(0)
+		{}
+		
 		LLButton* mButton;
 		std::string mURL;
 		U32 mURLExternal;
-- 
cgit v1.2.3


From 3c381458525c234137ea4a51916d16291fdfd237 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 24 Sep 2020 19:06:58 +0300
Subject: SL-14001 New Inventory search visibility options should persist from
 login to login

---
 indra/newview/llinventoryfilter.cpp    | 42 +++++++++++++++++++++++++++++++++-
 indra/newview/llinventoryfilter.h      | 11 ++++++---
 indra/newview/llpanelmaininventory.cpp | 14 ++++++++++++
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 1b99c90d5c..2e0037aa57 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -64,7 +64,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
 	mFilterTypes(p.types),
 	mFilterUUID(p.uuid),
 	mFilterLinks(p.links),
-	mSearchVisibility(0xffffFFFFffffFFFFULL)
+	mSearchVisibility(p.search_visibility)
 {
 }
 
@@ -907,6 +907,44 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
 	}
 }
 
+void LLInventoryFilter::setSearchVisibilityTypes(U32 types)
+{
+	if (mFilterOps.mSearchVisibility != types)
+	{
+		// keep current items only if no perm bits getting turned off
+		BOOL fewer_bits_set = (mFilterOps.mSearchVisibility & ~types);
+		BOOL more_bits_set = (~mFilterOps.mSearchVisibility & types);
+		mFilterOps.mSearchVisibility = types;
+
+		if (more_bits_set && fewer_bits_set)
+		{
+			setModified(FILTER_RESTART);
+		}
+		else if (more_bits_set)
+		{
+			// target must have all requested permission bits, so more bits == more restrictive
+			setModified(FILTER_MORE_RESTRICTIVE);
+		}
+		else if (fewer_bits_set)
+		{
+			setModified(FILTER_LESS_RESTRICTIVE);
+		}
+	}
+}
+
+void LLInventoryFilter::setSearchVisibilityTypes(const Params& params)
+{
+	if (!params.validateBlock())
+	{
+		return;
+	}
+
+	if (params.filter_ops.search_visibility.isProvided())
+	{
+		setSearchVisibilityTypes(params.filter_ops.search_visibility);
+	}
+}
+
 void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
 {
 	if (mFilterOps.mPermissions != perms)
@@ -1375,6 +1413,7 @@ void LLInventoryFilter::toParams(Params& params) const
 	params.filter_ops.show_folder_state = getShowFolderState();
 	params.filter_ops.creator_type = getFilterCreatorType();
 	params.filter_ops.permissions = getFilterPermissions();
+	params.filter_ops.search_visibility = getSearchVisibilityTypes();
 	params.substring = getFilterSubString();
 	params.since_logoff = isSinceLogoff();
 }
@@ -1398,6 +1437,7 @@ void LLInventoryFilter::fromParams(const Params& params)
 	setShowFolderState(params.filter_ops.show_folder_state);
 	setFilterCreator(params.filter_ops.creator_type);
 	setFilterPermissions(params.filter_ops.permissions);
+	setSearchVisibilityTypes(params.filter_ops.search_visibility);
 	setFilterSubString(params.substring);
 	setDateRangeLastLogoff(params.since_logoff);
 }
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index caba8315c4..0580261c43 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -124,11 +124,13 @@ public:
 
 		struct Params : public LLInitParam::Block<Params>
 		{
-			Optional<U32>				types;
+			Optional<U32>				types,
+										search_visibility;
 			Optional<U64>				object_types,
 										wearable_types,
                                         settings_types,
 										category_types;
+										
 			Optional<EFilterLink>		links;
 			Optional<LLUUID>			uuid;
 			Optional<DateRange>			date_range;
@@ -145,6 +147,7 @@ public:
                 settings_types("settings_types", 0xffffFFFFffffFFFFULL),
 				category_types("category_types", 0xffffFFFFffffFFFFULL),
 				links("links", FILTERLINK_INCLUDE_LINKS),
+				search_visibility("search_visibility", 0xFFFFFFFF),
 				uuid("uuid"),
 				date_range("date_range"),
 				hours_ago("hours_ago", 0),
@@ -157,12 +160,12 @@ public:
 
 		FilterOps(const Params& = Params());
 
-		U32 			mFilterTypes;
+		U32 			mFilterTypes,
+						mSearchVisibility;
 		U64				mFilterObjectTypes,   // For _OBJECT
 						mFilterWearableTypes,
                         mFilterSettingsTypes, // for _SETTINGS
 						mFilterLinks,
-						mSearchVisibility,
 						mFilterCategoryTypes; // For _CATEGORY
 		LLUUID      	mFilterUUID; 		  // for UUID
 
@@ -226,6 +229,8 @@ public:
 	void				toggleSearchVisibilityLinks();
 	void				toggleSearchVisibilityTrash();
 	void				toggleSearchVisibilityLibrary();
+	void 				setSearchVisibilityTypes(U32 types);
+	void 				setSearchVisibilityTypes(const Params& params);
 
 	void 				setFilterSubString(const std::string& string);
 	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 7d04c1dc67..4691ee3849 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -229,6 +229,17 @@ BOOL LLPanelMainInventory::postBuild()
 				recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER));
 			}
 		}
+		if(mActivePanel)
+		{
+			if(savedFilterState.has(mActivePanel->getFilter().getName()))
+			{
+				LLSD items = savedFilterState.get(mActivePanel->getFilter().getName());
+				LLInventoryFilter::Params p;
+				LLParamSDParser parser;
+				parser.readSD(items, p);
+				mActivePanel->getFilter().setSearchVisibilityTypes(p);
+			}
+		}
 
 	}
 
@@ -265,6 +276,9 @@ BOOL LLPanelMainInventory::postBuild()
 LLPanelMainInventory::~LLPanelMainInventory( void )
 {
 	// Save the filters state.
+	// Some params types cannot be saved this way
+	// for example, LLParamSDParser doesn't know about U64,
+	// so some FilterOps params should be revised.
 	LLSD filterRoot;
 	LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
 	if (all_items_panel)
-- 
cgit v1.2.3


From 54beabc63665b3b431e901f36ea695712ca7e6bb Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 28 Sep 2020 19:36:02 +0300
Subject: SL-13335 Use regular font style for 'Get started' button

---
 indra/newview/skins/default/xui/en/floater_add_payment_method.xml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
index 5296719339..1f980564d4 100644
--- a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
+++ b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml
@@ -51,7 +51,6 @@
      height="24"
      label="Get started"
      font="SansSerifMedium"
-     font.style="BOLD"
      layout="topleft"
      left="320"
      name="continue_btn"
-- 
cgit v1.2.3


From 71537daefda469c390b10f48bd01c9a2d59b8624 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 2 Oct 2020 18:53:36 +0300
Subject: SL-14057 FIXED The viewer crashes when trying to make a transaction
 exceeding the L$ balance

---
 indra/newview/llfloaterbuycurrency.cpp | 2 +-
 indra/newview/llfloaterbuycurrency.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index a3e9161ee8..5ee6f122bf 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -307,7 +307,7 @@ void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
 }
 
 // static
-void LLFloaterBuyCurrency::handleBuyCurrency(bool has_piof, bool has_target, const std::string& name, S32 price)
+void LLFloaterBuyCurrency::handleBuyCurrency(bool has_piof, bool has_target, const std::string name, S32 price)
 {
 	delete sPropertiesRequest;
 	sPropertiesRequest = NULL;
diff --git a/indra/newview/llfloaterbuycurrency.h b/indra/newview/llfloaterbuycurrency.h
index 1722f56dc1..88d3d17cd6 100644
--- a/indra/newview/llfloaterbuycurrency.h
+++ b/indra/newview/llfloaterbuycurrency.h
@@ -54,7 +54,7 @@ public:
 	static void buyCurrency();
 	static void buyCurrency(const std::string& name, S32 price);
 
-		static void handleBuyCurrency(bool has_piof, bool has_target, const std::string& name, S32 price);
+		static void handleBuyCurrency(bool has_piof, bool has_target, const std::string name, S32 price);
 		/* name should be a noun phrase of the object or service being bought:
 				"That object costs"
 				"Trying to give"
-- 
cgit v1.2.3


From 4afbe638d9965578d53822300e41b00155df5386 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 6 Oct 2020 15:56:11 +0300
Subject: SL-14067 FIXED The 'Unable to Buy' (L$) error persists until relogin

---
 indra/newview/llcurrencyuimanager.cpp  | 5 +++++
 indra/newview/llcurrencyuimanager.h    | 2 ++
 indra/newview/llfloaterbuycurrency.cpp | 1 +
 3 files changed, 8 insertions(+)

diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index cd7332c4d4..731b2dbcdb 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -604,6 +604,11 @@ bool LLCurrencyUIManager::bought()
 	return impl.mBought;
 }
 
+void LLCurrencyUIManager::clearError()
+{
+	return impl.clearError();
+}
+
 bool LLCurrencyUIManager::hasError()
 {
 	return impl.mError;
diff --git a/indra/newview/llcurrencyuimanager.h b/indra/newview/llcurrencyuimanager.h
index 3f37db8db1..7c05acbb05 100644
--- a/indra/newview/llcurrencyuimanager.h
+++ b/indra/newview/llcurrencyuimanager.h
@@ -80,6 +80,8 @@ public:
 	bool buying();		// are we in the process of buying?
 	bool bought();		// did the buy() transaction complete successfully
 
+	void clearError();
+
 	bool hasError();
 	std::string errorMessage();
 	std::string errorURI();
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 5ee6f122bf..0cfac166c7 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -193,6 +193,7 @@ void LLFloaterBuyCurrencyUI::updateUI()
 		args["TITLE"] = getString("info_cannot_buy");
 		args["MESSAGE"] = mManager.errorMessage();
 		LLNotificationsUtil::add("CouldNotBuyCurrency", args);
+		mManager.clearError();
 		closeFloater();
 	}
 	else
-- 
cgit v1.2.3


From 2ae6df6095242c12e31774cfe044c447b5987c6c Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 7 Oct 2020 15:18:57 +0300
Subject: SL-14067 minor cleanup

---
 indra/newview/llcurrencyuimanager.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 731b2dbcdb..232e461fd0 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -606,7 +606,7 @@ bool LLCurrencyUIManager::bought()
 
 void LLCurrencyUIManager::clearError()
 {
-	return impl.clearError();
+	impl.clearError();
 }
 
 bool LLCurrencyUIManager::hasError()
-- 
cgit v1.2.3


From b484a2736524dc52ef81dd3e3d25ee0970674fd4 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 4 Nov 2020 18:53:56 +0200
Subject: SL-13826 Open a new inventory floater for "Find original" and "Show
 original" result

---
 indra/newview/llinventorybridge.cpp    | 20 +++++---------------
 indra/newview/llinventoryfunctions.cpp | 18 +++++++++++-------
 indra/newview/llinventorypanel.cpp     | 26 ++++++++++++++++++++++++++
 indra/newview/llinventorypanel.h       |  5 ++++-
 indra/newview/llpanelmaininventory.cpp | 15 ++++++++++++---
 indra/newview/llpanelmaininventory.h   |  3 ++-
 6 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 03123689c5..67d65547b6 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1881,6 +1881,7 @@ void LLItemBridge::gotoItem()
 			if (active_panel)
 			{
 				active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
+				active_panel->setFocus(TRUE);
 			}
 		}
 
@@ -7229,24 +7230,13 @@ void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string acti
 	}
 	LLItemBridge::performAction(model,action);
 }
+
 void LLLinkFolderBridge::gotoItem()
 {
-	const LLUUID &cat_uuid = getFolderID();
-	if (!cat_uuid.isNull())
-	{
-		LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid);
-		if (base_folder)
-		{
-			if (LLInventoryModel* model = getInventoryModel())
-			{
-				model->fetchDescendentsOf(cat_uuid);
-			}
-			base_folder->setOpen(TRUE);
-			mRoot->setSelection(base_folder,TRUE);
-			mRoot->scrollToShowSelection();
-		}
-	}
+    LLItemBridge::gotoItem();
+    LLInventoryPanel::getActiveInventoryPanel()->openFolderByID(getFolderID());
 }
+
 const LLUUID &LLLinkFolderBridge::getFolderID() const
 {
 	if (LLViewerInventoryItem *link_item = getItem())
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 646d92b9e1..9eb84ed259 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -737,9 +737,8 @@ void show_item_original(const LLUUID& item_uuid)
 	}
 
 	//sidetray inventory panel
-	LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+	LLSidepanelInventory *sidepanel_inventory =	LLPanelMainInventory::newWindow()->LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 
-	bool do_reset_inventory_filter = !floater_inventory->isInVisibleChain();
 
 	LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel();
 	if (!active_panel) 
@@ -758,11 +757,7 @@ void show_item_original(const LLUUID& item_uuid)
 		return;
 	}
 	active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES);
-	
-	if(do_reset_inventory_filter)
-	{
-		reset_inventory_filter();
-	}
+	active_panel->setFocus(TRUE);
 }
 
 
@@ -2446,6 +2441,15 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
     }
     else
     {
+        if (action == "goto")
+        {
+            LLSidepanelInventory *sidepanel_inventory = LLPanelMainInventory::newWindow()->LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+            if (sidepanel_inventory && sidepanel_inventory->getMainInventoryPanel())
+            {
+                model = sidepanel_inventory->getMainInventoryPanel()->getActivePanel()->getModel();
+            }
+        }
+        
         std::set<LLFolderViewItem*>::iterator set_iter;
         for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
         {
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index c65998cf90..740c27ae8b 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -339,6 +339,7 @@ void LLInventoryPanel::draw()
 {
 	// Select the desired item (in case it wasn't loaded when the selection was requested)
 	updateSelection();
+	updateFolderState();
 	
 	LLPanel::draw();
 }
@@ -1146,6 +1147,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::
 void LLInventoryPanel::clearSelection()
 {
 	mSelectThisID.setNull();
+	mOpenFolderID.setNull();
 }
 
 LLInventoryPanel::selected_items_t LLInventoryPanel::getSelectedItems() const
@@ -1646,6 +1648,30 @@ void LLInventoryPanel::updateSelection()
 	}
 }
 
+void LLInventoryPanel::openFolderByID( const LLUUID& folder_id)
+{
+    LLFolderViewItem* itemp = getItemByID(folder_id);
+    if(itemp && itemp->getViewModelItem())
+    {
+        itemp->setOpen(TRUE);
+        mOpenFolderID.setNull();
+        return;
+    }
+    else
+    {
+        // save the desired folder to be open later (if/when ready)
+        mOpenFolderID = folder_id;
+    }
+}
+
+void LLInventoryPanel::updateFolderState()
+{
+    if (mOpenFolderID.notNull())
+    {
+        openFolderByID(mOpenFolderID);
+    }
+}
+
 void LLInventoryPanel::doToSelected(const LLSD& userdata)
 {
 	if (("purge" == userdata.asString()))
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 7cb52dc1f3..e51281b4b3 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -244,7 +244,9 @@ public:
 	LLFolderViewItem* getItemByID(const LLUUID& id);
 	LLFolderViewFolder* getFolderByID(const LLUUID& id);
 	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus);
+	void openFolderByID(const LLUUID& folder_id);
 	void updateSelection();
+	void updateFolderState();
 
 	void setSuppressOpenItemAction(bool supress_open_item) { mSuppressOpenItemAction = supress_open_item; }
 
@@ -260,7 +262,8 @@ protected:
 	void openStartFolderOrMyInventory(); // open the first level of inventory
 	void onItemsCompletion();			// called when selected items are complete
 
-    LLUUID						mSelectThisID;	
+    LLUUID						mSelectThisID;
+	LLUUID						mOpenFolderID;	
 	LLInventoryModel*			mInventory;
 	LLInventoryObserver*		mInventoryObserver;
 	LLInvPanelComplObserver*	mCompletionObserver;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 4691ee3849..813a5b3c20 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -383,15 +383,16 @@ void LLPanelMainInventory::closeAllFolders()
 	getPanel()->getRootFolder()->closeAllFolders();
 }
 
-void LLPanelMainInventory::newWindow()
+LLFloaterSidePanelContainer* LLPanelMainInventory::newWindow()
 {
 	static S32 instance_num = 0;
 	instance_num = (instance_num + 1) % S32_MAX;
 
 	if (!gAgentCamera.cameraMouselook())
 	{
-		LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
+		return LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
 	}
+    return NULL;
 }
 
 void LLPanelMainInventory::doCreate(const LLSD& userdata)
@@ -1343,7 +1344,15 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 		{
 			return;
 		}
-		static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto");
+        LLSidepanelInventory *sidepanel_inventory = newWindow()->LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+        if (sidepanel_inventory)
+        {
+            LLPanelMainInventory* new_inventory = sidepanel_inventory->getMainInventoryPanel();
+            if (new_inventory)
+            {
+                static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(new_inventory->getActivePanel()->getModel(), "goto");
+            }
+        }
 	}
 
 	if (command_name == "find_links")
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 903b33bdbf..40f04da6e9 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -46,6 +46,7 @@ class LLMenuButton;
 class LLMenuGL;
 class LLToggleableMenu;
 class LLFloater;
+class LLFloaterSidePanelContainer;
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLPanelMainInventory
@@ -90,7 +91,7 @@ public:
 
 	void setFocusFilterEditor();
 
-	static void newWindow();
+	static LLFloaterSidePanelContainer* newWindow();
 
 	void toggleFindOptions();
 
-- 
cgit v1.2.3


From 8aa41b9e1c18f3b108c2e219e72b6e40762c4652 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 6 Nov 2020 19:41:21 +0200
Subject: SL-14203 add menu items to open Linden Homes and Premium Membership
 web pages

---
 indra/newview/llfloaterlandholdings.cpp            | 30 +++++++++++++++++-----
 indra/newview/llfloaterlandholdings.h              |  2 ++
 indra/newview/llstartup.cpp                        | 10 ++++++++
 indra/newview/llviewermenu.cpp                     | 25 ++++++++++++++++++
 indra/newview/skins/default/xui/en/menu_viewer.xml | 21 ++++++++++++---
 indra/newview/skins/default/xui/en/strings.xml     |  7 +++++
 6 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp
index f34760a6bf..749a3d2686 100644
--- a/indra/newview/llfloaterlandholdings.cpp
+++ b/indra/newview/llfloaterlandholdings.cpp
@@ -51,6 +51,9 @@
 
 #include "llgroupactions.h"
 
+const std::string LINDEN_HOMES_SKU = "131";
+bool LLFloaterLandHoldings::sHasLindenHome = false;
+
 // protected
 LLFloaterLandHoldings::LLFloaterLandHoldings(const LLSD& key)
 :	LLFloater(key),
@@ -148,10 +151,24 @@ void LLFloaterLandHoldings::refresh()
 void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**)
 {
 	LLFloaterLandHoldings* self = LLFloaterReg::findTypedInstance<LLFloaterLandHoldings>("land_holdings");
-
-	// Is this packet from an old, closed window?
+	S32 count = msg->getNumberOfBlocks("QueryData");
+	std::string land_sku;
+	sHasLindenHome = false;
 	if (!self)
 	{
+		for (S32 i = 0; i < count; i++)
+		{
+			if ( msg->getSizeFast(_PREHASH_QueryData, i, _PREHASH_ProductSKU) > 0 )
+			{
+				msg->getStringFast(	_PREHASH_QueryData, _PREHASH_ProductSKU, land_sku, i);
+
+				if (LINDEN_HOMES_SKU == land_sku)
+				{
+					sHasLindenHome = true;
+					return;
+				}
+			}
+		}
 		return;
 	}
 
@@ -174,12 +191,9 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**)
 	F32		global_x;
 	F32		global_y;
 	std::string	sim_name;
-	std::string land_sku;
 	std::string land_type;
 	
-	S32 i;
-	S32 count = msg->getNumberOfBlocks("QueryData");
-	for (i = 0; i < count; i++)
+	for (S32 i = 0; i < count; i++)
 	{
 		msg->getUUID("QueryData", "OwnerID", owner_id, i);
 		msg->getString("QueryData", "Name", name, i);
@@ -196,6 +210,10 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**)
 			msg->getStringFast(	_PREHASH_QueryData, _PREHASH_ProductSKU, land_sku, i);
 			LL_INFOS() << "Land sku: " << land_sku << LL_ENDL;
 			land_type = LLProductInfoRequestManager::instance().getDescriptionForSku(land_sku);
+			if (LINDEN_HOMES_SKU == land_sku)
+			{
+				sHasLindenHome = true;
+			}
 		}
 		else
 		{
diff --git a/indra/newview/llfloaterlandholdings.h b/indra/newview/llfloaterlandholdings.h
index d1d510bb40..90e75b1062 100644
--- a/indra/newview/llfloaterlandholdings.h
+++ b/indra/newview/llfloaterlandholdings.h
@@ -57,6 +57,8 @@ public:
 
 	static void onGrantList(void* data);
 
+	static bool sHasLindenHome;
+
 protected:
 	void refreshAggregates();
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3ef2d47d37..f307daa198 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -128,10 +128,12 @@
 #include "llpanelpick.h"
 #include "llpanelgrouplandmoney.h"
 #include "llpanelgroupnotices.h"
+#include "llparcel.h"
 #include "llpreview.h"
 #include "llpreviewscript.h"
 #include "llproxy.h"
 #include "llproductinforequest.h"
+#include "llqueryflags.h"
 #include "llselectmgr.h"
 #include "llsky.h"
 #include "llstatview.h"
@@ -2258,6 +2260,14 @@ bool idle_startup()
 
 		gAgentAvatarp->sendHoverHeight();
 
+		// look for parcels we own
+		send_places_query(LLUUID::null,
+			LLUUID::null,
+			"",
+			DFQ_AGENT_OWNED,
+			LLParcel::C_ANY,
+			"");
+
 		return TRUE;
 	}
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2d8757b673..3f0b744d94 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -64,6 +64,7 @@
 #include "llfloaterimcontainer.h"
 #include "llfloaterland.h"
 #include "llfloaterimnearbychat.h"
+#include "llfloaterlandholdings.h"
 #include "llfloaterpathfindingcharacters.h"
 #include "llfloaterpathfindinglinksets.h"
 #include "llfloaterpay.h"
@@ -5886,6 +5887,16 @@ class LLWorldSetHomeLocation : public view_listener_t
 	}
 };
 
+class LLWorldLindenHome : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url");
+		LLWeb::loadURL(url);
+		return true;
+	}
+};
+
 class LLWorldTeleportHome : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -8735,6 +8746,17 @@ public:
 	}
 };
 
+class LLUpdateMembershipLabel : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		const std::string label_str =  LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText");
+		gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str);
+
+		return true;
+	}
+};
+
 void handle_voice_morphing_subscribe()
 {
 	LLWeb::loadURL(LLTrans::getString("voice_morphing_url"));
@@ -8884,6 +8906,8 @@ void initialize_menus()
 
 	view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");
 
+	view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel");
+
 	enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed));
 
 	// Agent
@@ -8960,6 +8984,7 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
 	view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway");
 	view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb");
+	view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome");
 
 	view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
 	view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 5fa1847d1b..01c2b7f1d9 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -213,6 +213,15 @@
          name="ManageMyAccount_url"
          parameter="WebLaunchJoinNow,http://secondlife.com/account/" />
       </menu_item_call>
+      <menu_item_call
+           label="[Membership]"
+           name="Membership">
+            <menu_item_call.on_click
+             function="Advanced.ShowURL"
+             parameter="https://secondlife.com/my/account/membership.php"/>
+            <menu_item_call.on_visible
+                 function="Membership.UpdateLabel"/>
+      </menu_item_call>
 
       <menu_item_separator/>
 
@@ -524,12 +533,18 @@
              parameter="region_info" />
         </menu_item_call>
         <menu_item_call
-         label="My land holdings..."
-         name="My Land">
+         label="My Linden Home..."
+         name="Linden Home">
+            <menu_item_call.on_click
+             function="World.LindenHome"/>
+        </menu_item_call>
+        <menu_item_call
+             label="My land holdings..."
+             name="My Land">
             <menu_item_call.on_click
              function="Floater.Show"
              parameter="land_holdings" />
-        </menu_item_call>
+      </menu_item_call>
         <menu_item_call
          label="Buy this land"
          name="Buy Land">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 7398e457f0..0b95b43f39 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3768,6 +3768,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="voice_morphing_url">https://secondlife.com/destination/voice-island</string>
   <string name="premium_voice_morphing_url">https://secondlife.com/destination/voice-morphing-premium</string>
 
+  <string name="lindenhomes_get_home_url">https://secondlife.com/land/lindenhomes/member.php</string>
+  <string name="lindenhomes_my_home_url">https://land.secondlife.com/en-Us/lindenhomes/my-home.php</string>
+  <string name="membership_url">https://secondlife.com/my/account/membership.php</string>
+
   <!-- Financial operations strings -->
   <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT] [REASON].</string>
   <string name="paid_you_ldollars_gift">[NAME] paid you L$[AMOUNT]: [REASON]</string>
@@ -3959,6 +3963,9 @@ Please check http://status.secondlifegrid.net to see if there is a known problem
   <string name="Premium PlusMembership">Premium Plus</string>
   <string name="InternalMembership">Internal</string> <!-- No need to translate -->
 
+  <string name="MembershipUpgradeText">Upgrade to Premium</string>
+  <string name="MembershipPremiumText">My Premium membership</string>
+
   <!-- Question strings for delete items notifications -->
   <string name="DeleteItems">Delete selected items?</string>
   <string name="DeleteItem">Delete selected item?</string>
-- 
cgit v1.2.3


From 9420498eed9e819cdf1721174d6f1c94a3ca6e16 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Fri, 13 Nov 2020 19:30:15 +0200
Subject: Buildfix

---
 indra/newview/llinventorypanel.h | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index e13c68812e..2bcc3f3c0b 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -416,24 +416,4 @@ private:
     LLAssetType::EType mAssetType;
 };
 
-
-class LLInventoryFavoriteItemsPanel : public LLInventoryPanel
-{
-public:
-    struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
-    {};
-
-    void initFromParams(const Params& p);
-    bool isSelectionRemovable() { return false; }
-    void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
-
-protected:
-    LLInventoryFavoriteItemsPanel(const Params& params);
-    ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); }
-    void updateFavoritesRootFolder();
-
-    boost::signals2::connection mFolderChangedSignal;
-    boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback;
-    friend class LLUICtrlFactory;
-};
 #endif // LL_LLINVENTORYPANEL_H
-- 
cgit v1.2.3


From 8f8d26a770e71201d288301c67080f5a57220ba0 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 19 Jun 2020 17:53:51 +0300
Subject: SL-13479 Dedicated top-level menu for avatar editing

---
 indra/newview/llviewermenu.cpp                     |  54 ++-
 .../skins/default/xui/en/floater_avatar.xml        |   2 +-
 .../skins/default/xui/en/floater_my_appearance.xml |   2 +-
 .../skins/default/xui/en/floater_my_scripts.xml    |   2 +-
 .../skins/default/xui/en/menu_attachment_other.xml |   5 +-
 .../skins/default/xui/en/menu_attachment_self.xml  | 115 ++----
 .../skins/default/xui/en/menu_avatar_other.xml     |   5 +-
 .../skins/default/xui/en/menu_avatar_self.xml      | 451 ++++++++++-----------
 indra/newview/skins/default/xui/en/menu_viewer.xml | 279 +++++++------
 .../skins/default/xui/en/panel_edit_wearable.xml   |   2 +-
 .../skins/default/xui/en/panel_outfit_edit.xml     |   2 +-
 11 files changed, 443 insertions(+), 476 deletions(-)

diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 4605bccb13..34b4d7f3b3 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -677,19 +677,6 @@ class LLAdvancedCheckHUDInfo : public view_listener_t
 };
 
 
-//////////////
-// FLYING   //
-//////////////
-
-class LLAdvancedAgentFlyingInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD&)
-	{
-		return gAgent.getFlying();
-	}
-};
-
-
 ///////////////////////
 // CLEAR GROUP CACHE //
 ///////////////////////
@@ -3743,6 +3730,35 @@ bool enable_sitdown_self()
 	return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying();
 }
 
+class LLSelfToggleSitStand : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (isAgentAvatarValid())
+		{
+			if (gAgentAvatarp->isSitting())
+			{
+				gAgent.standUp();
+			}
+			else
+			{
+				gAgent.sitDown();
+			}
+		}
+		return true;
+	}
+};
+
+bool enable_sit_stand()
+{
+	return enable_sitdown_self() || enable_standup_self();
+}
+
+bool enable_fly_land()
+{
+	return gAgent.getFlying() || LLAgent::enableFlying();
+}
+
 class LLCheckPanelPeopleTab : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -8948,7 +8964,7 @@ void initialize_menus()
 
 	// Agent
 	commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
-	enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying));
+	enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land));
 	commit.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2));
 	commit.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2));
 	commit.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2));
@@ -8996,9 +9012,6 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb");
 	view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
 	
-	// Me > Movement
-	view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
-
 	//Communicate Nearby chat
 	view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat");
 
@@ -9263,11 +9276,8 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState");
 
 	// Self context menu
-	view_listener_t::addMenu(new LLSelfStandUp(), "Self.StandUp");
-	enable.add("Self.EnableStandUp", boost::bind(&enable_standup_self));
-	view_listener_t::addMenu(new LLSelfSitDown(), "Self.SitDown");
-	enable.add("Self.EnableSitDown", boost::bind(&enable_sitdown_self)); 
-	enable.add("Self.ShowSitDown", boost::bind(&show_sitdown_self));
+	view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand");
+	enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand));
 	view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
 
 	view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
diff --git a/indra/newview/skins/default/xui/en/floater_avatar.xml b/indra/newview/skins/default/xui/en/floater_avatar.xml
index 92c5d8bcbe..3df2683ca8 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar.xml
@@ -14,7 +14,7 @@
  help_topic="avatar"
  save_rect="true"
  save_visibility="true"
- title="CHOOSE AN AVATAR"
+ title="COMPLETE AVATARS"
  width="700">
     <web_browser
       top="25"
diff --git a/indra/newview/skins/default/xui/en/floater_my_appearance.xml b/indra/newview/skins/default/xui/en/floater_my_appearance.xml
index fdea7a821a..35ad87ceb0 100644
--- a/indra/newview/skins/default/xui/en/floater_my_appearance.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_appearance.xml
@@ -11,7 +11,7 @@
   save_rect="true"
   single_instance="true"
   reuse_instance="true"
-  title="APPEARANCE"
+  title="AVATAR"
   min_height="440"
   min_width="333"
   width="333">
diff --git a/indra/newview/skins/default/xui/en/floater_my_scripts.xml b/indra/newview/skins/default/xui/en/floater_my_scripts.xml
index 3b0b6723c7..ee6defce9d 100644
--- a/indra/newview/skins/default/xui/en/floater_my_scripts.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_scripts.xml
@@ -7,7 +7,7 @@
  layout="topleft"
  name="myscripts"
  save_rect="true"
- title="My Scripts"
+ title="ATTACHMENT SCRIPTS"
  min_width="620"
  width="620">
   <panel
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
index 38f4b7715f..7ad692038e 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
@@ -173,16 +173,13 @@
           parameter="avatar_render_settings" />
       </menu_item_call>
       </context_menu>
-  <menu_item_separator
-       layout="topleft" name="Impostor seperator"/>
-
   <menu_item_call
      enabled="false"
      label="Block Particle Owner"
      name="Mute Particle">
     <menu_item_call.on_click
      function="Particle.Mute" />
-    <menu_item_call.on_enable
+    <menu_item_call.on_visible
      function="EnableMuteParticle" />
   </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 59faf6a9f5..03c05e6591 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -4,7 +4,7 @@
  name="Attachment Pie">
     <menu_item_call
      enabled="false"
-     label="Touch"
+     label="Touch item"
      layout="topleft"
      name="Attachment Object Touch">
         <menu_item_call.on_click
@@ -13,19 +13,9 @@
          function="Object.EnableTouch"
          name="EnableTouch"/>
     </menu_item_call>
-    <!--menu_item_call
-     label="Stand Up"
-     layout="topleft"
-     name="Stand Up">
-        <menu_item_call.on_click
-         function="Self.StandUp"
-         parameter="" />
-        <menu_item_call.on_enable
-         function="Self.EnableStandUp" />
-    </menu_item_call-->
     <menu_item_call
      enabled="false"
-     label="Edit"
+     label="Edit item"
      layout="topleft"
      name="Edit...">
         <menu_item_call.on_click
@@ -35,7 +25,7 @@
     </menu_item_call>
     <menu_item_call
      enabled="false"
-     label="Detach"
+     label="Detach item"
      layout="topleft"
      name="Detach">
         <menu_item_call.on_click
@@ -46,36 +36,15 @@
   <menu_item_separator
     layout="topleft" />
 
-    <menu_item_call
-     label="Sit Down"
-     layout="topleft"
-     name="Sit Down Here">
-        <menu_item_call.on_click
-         function="Self.SitDown"
-         parameter="" />
-        <menu_item_call.on_enable
-         function="Self.EnableSitDown" />
-    </menu_item_call>
-
-  <menu_item_call
-label="Stand Up"
-layout="topleft"
-name="Stand Up">
-    <menu_item_call.on_click
-     function="Self.StandUp"
-     parameter="" />
-    <menu_item_call.on_enable
-     function="Self.EnableStandUp" />
-  </menu_item_call>
   <menu_item_call
-  label="My Appearance"
+  label="Outfits..."
   name="Change Outfit">
     <menu_item_call.on_click
      function="CustomizeAvatar" />
     <menu_item_call.on_enable
      function="Edit.EnableCustomizeAvatar" />
   </menu_item_call>
-  <menu_item_call label="Edit My Outfit"
+  <menu_item_call label="Edit current outfit..."
 layout="topleft"
 name="Edit Outfit">
     <menu_item_call.on_click
@@ -83,7 +52,7 @@ name="Edit Outfit">
     <menu_item_call.on_enable
      function="Edit.EnableCustomizeAvatar" />
   </menu_item_call>
-  <menu_item_call label="Edit My Shape"
+  <menu_item_call label="Shape..."
     layout="topleft"
     name="Edit My Shape">
     <menu_item_call.on_click
@@ -91,7 +60,7 @@ name="Edit Outfit">
     <menu_item_call.on_enable
      function="Edit.EnableEditShape" />
   </menu_item_call>
-  <menu_item_call label="Hover Height"
+  <menu_item_call label="Hover height..."
      layout="topleft"
      name="Hover Height">
      <menu_item_call.on_click
@@ -99,42 +68,42 @@ name="Edit Outfit">
      <menu_item_call.on_enable
       function="Edit.EnableHoverHeight" />
   </menu_item_call>
-  <menu_item_call label="Reset Skeleton"
-       layout="topleft"
-       name="Reset Skeleton">
-       <menu_item_call.on_click
-        function="Avatar.ResetSkeleton" />
-  </menu_item_call>
-  <menu_item_call label="Reset Skeleton And Animations"
-       layout="topleft"
-       name="Reset Skeleton And Animations">
-       <menu_item_call.on_click
-        function="Avatar.ResetSkeletonAndAnimations" />
-  </menu_item_call>
-
+  <menu_item_separator/>
   <menu_item_call
-    label="My Friends"
+    label="Sit / stand"
     layout="topleft"
-    name="Friends...">
+    name="Sit stand">
     <menu_item_call.on_click
-     function="SideTray.PanelPeopleTab"
-     parameter="friends_panel" />
+     function="Self.ToggleSitStand"/>
+    <menu_item_call.on_enable
+     function="Self.EnableSitStand" />
   </menu_item_call>
   <menu_item_call
-   label="My Groups"
-   layout="topleft"
-   name="Groups...">
+     label="Fly / land"
+     name="Fly land">
     <menu_item_call.on_click
-     function="SideTray.PanelPeopleTab"
-     parameter="groups_panel" />
+     function="Agent.toggleFlying" />
+    <menu_item_call.on_enable
+     function="Agent.enableFlyLand" />
   </menu_item_call>
   <menu_item_call
-    label="My Profile"
-    layout="topleft"
-    name="Profile...">
+     label="Stop animations"
+     name="Stop Animating My Avatar">
     <menu_item_call.on_click
-     function="ShowAgentProfile"
-     parameter="agent" />
+     function="Tools.StopAllAnimations" />
+  </menu_item_call>
+  <menu_item_separator/>
+  <menu_item_call label="Reset skeleton"
+       layout="topleft"
+       name="Reset Skeleton">
+       <menu_item_call.on_click
+        function="Avatar.ResetSkeleton" />
+  </menu_item_call>
+  <menu_item_call label="Reset skeleton and animations"
+       layout="topleft"
+       name="Reset Skeleton And Animations">
+       <menu_item_call.on_click
+        function="Avatar.ResetSkeletonAndAnimations" />
   </menu_item_call>
   <menu_item_call
  label="Debug Textures"
@@ -152,27 +121,13 @@ name="Edit Outfit">
             <menu_item_call.on_visible
              function="Advanced.EnableAppearanceToXML"/>
     </menu_item_call>
-  <menu_item_separator
-  layout="topleft" />
-  <menu_item_call
- enabled="false"
- label="Drop"
- layout="topleft"
- name="Drop">
-    <menu_item_call.on_click
-     function="Attachment.Drop" />
-    <menu_item_call.on_enable
-     function="Attachment.EnableDrop" />
-  </menu_item_call>
-  <menu_item_separator
-       layout="topleft" />
   <menu_item_call
      enabled="false"
      label="Block Particle Owner"
      name="Mute Particle">
     <menu_item_call.on_click
      function="Particle.Mute" />
-    <menu_item_call.on_enable
+    <menu_item_call.on_visible
      function="EnableMuteParticle" />
   </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
index f9fb847910..acbb9b860d 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
@@ -165,16 +165,13 @@
       </menu_item_call>
       </context_menu>
 
-  <menu_item_separator 
-    layout="topleft"  name="Impostor seperator"/>
-
   <menu_item_call
      enabled="false"
      label="Block Particle Owner"
      name="Mute Particle">
     <menu_item_call.on_click
      function="Particle.Mute" />
-    <menu_item_call.on_enable
+    <menu_item_call.on_visible
      function="EnableMuteParticle" />
   </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index 9e181d0b6d..3dcafb13ef 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -3,209 +3,7 @@
  layout="topleft"
  name="Self Pie">
     <menu_item_call
-     label="Sit Down"
-     layout="topleft"
-     name="Sit Down Here">
-        <menu_item_call.on_click
-         function="Self.SitDown"
-         parameter="" />
-        <menu_item_call.on_enable
-         function="Self.EnableSitDown" />
-    </menu_item_call>
-    <menu_item_call
-     label="Stand Up"
-     layout="topleft"
-     name="Stand Up">
-        <menu_item_call.on_click
-         function="Self.StandUp"
-         parameter="" />
-        <menu_item_call.on_enable
-         function="Self.EnableStandUp" />
-    </menu_item_call>
-    <context_menu
-     label="Take Off"
-     layout="topleft"
-     name="Take Off &gt;">
-        <context_menu
-         label="Clothes"
-         layout="topleft"
-         name="Clothes &gt;">
-            <menu_item_call
-             enabled="false"
-             label="Shirt"
-             layout="topleft"
-             name="Shirt">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="shirt" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="shirt" />
-            </menu_item_call>
-            <menu_item_call
-             enabled="false"
-             label="Pants"
-             layout="topleft"
-             name="Pants">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="pants" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="pants" />
-            </menu_item_call>
-            <menu_item_call
-             enabled="false"
-             label="Skirt"
-             layout="topleft"
-             name="Skirt">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="skirt" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="skirt" />
-            </menu_item_call>
-            <menu_item_call
-             enabled="false"
-             label="Shoes"
-             layout="topleft"
-             name="Shoes">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="shoes" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="shoes" />
-            </menu_item_call>
-            <menu_item_call
-             enabled="false"
-             label="Socks"
-             layout="topleft"
-             name="Socks">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="socks" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="socks" />
-            </menu_item_call>
-            <menu_item_call
-             enabled="false"
-             label="Jacket"
-             layout="topleft"
-             name="Jacket">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="jacket" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="jacket" />
-            </menu_item_call>
-            <menu_item_call
-             enabled="false"
-             label="Gloves"
-             layout="topleft"
-             name="Gloves">
-                <menu_item_call.on_click
-                 function="Edit.TakeOff"
-                 parameter="gloves" />
-                <menu_item_call.on_enable
-                 function="Edit.EnableTakeOff"
-                 parameter="gloves" />
-            </menu_item_call>
-           <menu_item_call
-                 enabled="false"
-                 label="Undershirt"
-                 layout="topleft"
-                 name="Self Undershirt">
-                    <menu_item_call.on_click
-                     function="Edit.TakeOff"
-                     parameter="undershirt" />
-                    <menu_item_call.on_enable
-                     function="Edit.EnableTakeOff"
-                     parameter="undershirt" />
-                </menu_item_call>
-               <menu_item_call
-                 enabled="false"
-                 label="Underpants"
-                 layout="topleft"
-                 name="Self Underpants">
-                    <menu_item_call.on_click
-                     function="Edit.TakeOff"
-                     parameter="underpants" />
-                    <menu_item_call.on_enable
-                     function="Edit.EnableTakeOff"
-                     parameter="underpants" />
-                </menu_item_call>
-               <menu_item_call
-                 enabled="false"
-                 label="Tattoo"
-                 layout="topleft"
-                 name="Self Tattoo">
-                    <menu_item_call.on_click
-                     function="Edit.TakeOff"
-                     parameter="tattoo" />
-                    <menu_item_call.on_enable
-                     function="Edit.EnableTakeOff"
-                     parameter="tattoo" />
-                </menu_item_call>
-               <menu_item_call
-                 enabled="false"
-                 label="Physics"
-                 layout="topleft"
-                 name="Self Physics">
-                    <menu_item_call.on_click
-                     function="Edit.TakeOff"
-                     parameter="physics" />
-                    <menu_item_call.on_enable
-                     function="Edit.EnableTakeOff"
-                     parameter="physics" />
-                </menu_item_call>
-               <menu_item_call
-                 enabled="false"
-                 label="Alpha"
-                 layout="topleft"
-                 name="Self Alpha">
-                    <menu_item_call.on_click
-                     function="Edit.TakeOff"
-                     parameter="alpha" />
-                    <menu_item_call.on_enable
-                     function="Edit.EnableTakeOff"
-                     parameter="alpha" />
-                </menu_item_call>
-                <menu_item_separator
-                 layout="topleft" />
-                <menu_item_call
-                 label="All Clothes"
-                 layout="topleft"
-                 name="All Clothes">
-                    <menu_item_call.on_click
-                     function="Edit.TakeOff"
-                     parameter="all" />
-                </menu_item_call>
-        </context_menu>
-        <context_menu
-         label="HUD"
-         layout="topleft"
-         name="Object Detach HUD" />
-        <context_menu
-         label="Detach"
-         layout="topleft"
-         name="Object Detach" />
-        <menu_item_call
-         label="Detach All"
-         layout="topleft"
-         name="Detach All">
-            <menu_item_call.on_click
-             function="Self.RemoveAllAttachments"
-             parameter="" />
-            <menu_item_call.on_enable
-             function="Self.EnableRemoveAllAttachments" />
-        </menu_item_call>
-    </context_menu>
-     <menu_item_call
-     label="My Appearance"
+     label="Outfits..."
      layout="topleft"
      name="Chenge Outfit">
         <menu_item_call.on_click
@@ -213,7 +11,7 @@
         <menu_item_call.on_enable
          function="Edit.EnableCustomizeAvatar" />
     </menu_item_call>
-    <menu_item_call label="Edit My Outfit" 
+    <menu_item_call label="Edit current outfit..." 
     layout="topleft"
     name="Edit Outfit">
        <menu_item_call.on_click
@@ -221,7 +19,7 @@
        <menu_item_call.on_enable
         function="Edit.EnableCustomizeAvatar" />
    </menu_item_call>
-    <menu_item_call label="Edit My Shape" 
+    <menu_item_call label="Shape..." 
     layout="topleft"
     name="Edit My Shape">
        <menu_item_call.on_click
@@ -229,7 +27,7 @@
        <menu_item_call.on_enable
         function="Edit.EnableEditShape" />
    </menu_item_call>
-   <menu_item_call label="Hover Height"
+   <menu_item_call label="Hover height..."
      layout="topleft"
      name="Hover Height">
      <menu_item_call.on_click
@@ -237,42 +35,225 @@
      <menu_item_call.on_enable
       function="Edit.EnableHoverHeight" />
    </menu_item_call>
-   <menu_item_call label="Reset Skeleton"
+  <context_menu
+    label="Take Off"
+    layout="topleft"
+    name="Take Off &gt;">
+    <context_menu
+     label="Clothes"
+     layout="topleft"
+     name="Clothes &gt;">
+      <menu_item_call
+       enabled="false"
+       label="Shirt"
+       layout="topleft"
+       name="Shirt">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="shirt" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="shirt" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Pants"
+       layout="topleft"
+       name="Pants">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="pants" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="pants" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Skirt"
+       layout="topleft"
+       name="Skirt">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="skirt" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="skirt" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Shoes"
+       layout="topleft"
+       name="Shoes">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="shoes" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="shoes" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Socks"
+       layout="topleft"
+       name="Socks">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="socks" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="socks" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Jacket"
+       layout="topleft"
+       name="Jacket">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="jacket" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="jacket" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Gloves"
+       layout="topleft"
+       name="Gloves">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="gloves" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="gloves" />
+      </menu_item_call>
+      <menu_item_call
+            enabled="false"
+            label="Undershirt"
+            layout="topleft"
+            name="Self Undershirt">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="undershirt" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="undershirt" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Underpants"
+        layout="topleft"
+        name="Self Underpants">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="underpants" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="underpants" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Tattoo"
+        layout="topleft"
+        name="Self Tattoo">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="tattoo" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="tattoo" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Physics"
+        layout="topleft"
+        name="Self Physics">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="physics" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="physics" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Alpha"
+        layout="topleft"
+        name="Self Alpha">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="alpha" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="alpha" />
+      </menu_item_call>
+      <menu_item_separator
+       layout="topleft" />
+      <menu_item_call
+       label="All Clothes"
+       layout="topleft"
+       name="All Clothes">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="all" />
+      </menu_item_call>
+    </context_menu>
+    <context_menu
+     label="HUD"
+     layout="topleft"
+     name="Object Detach HUD" />
+    <context_menu
+     label="Detach"
+     layout="topleft"
+     name="Object Detach" />
+    <menu_item_call
+     label="Detach All"
+     layout="topleft"
+     name="Detach All">
+      <menu_item_call.on_click
+       function="Self.RemoveAllAttachments"
+       parameter="" />
+      <menu_item_call.on_enable
+       function="Self.EnableRemoveAllAttachments" />
+    </menu_item_call>
+  </context_menu>
+  <menu_item_separator/>
+  <menu_item_call
+    label="Sit / stand"
+    layout="topleft"
+    name="Sit stand">
+      <menu_item_call.on_click
+       function="Self.ToggleSitStand"/>
+      <menu_item_call.on_enable
+       function="Self.EnableSitStand" />
+  </menu_item_call>
+  <menu_item_call
+     label="Fly / land"
+     name="Fly land">
+      <menu_item_call.on_click
+       function="Agent.toggleFlying" />
+      <menu_item_call.on_enable
+       function="Agent.enableFlyLand" />
+  </menu_item_call>
+  <menu_item_call
+     label="Stop animations"
+     name="Stop Animating My Avatar">
+        <menu_item_call.on_click
+         function="Tools.StopAllAnimations" />
+  </menu_item_call>
+  <menu_item_separator/>
+  <menu_item_call label="Reset skeleton"
      layout="topleft"
      name="Reset Skeleton">
      <menu_item_call.on_click
       function="Avatar.ResetSkeleton" />
-   </menu_item_call>
-  <menu_item_call label="Reset Skeleton And Animations"
+  </menu_item_call>
+  <menu_item_call label="Reset skeleton and animations"
        layout="topleft"
        name="Reset Skeleton And Animations">
        <menu_item_call.on_click
         function="Avatar.ResetSkeletonAndAnimations" />
   </menu_item_call>
-   <menu_item_call
-     label="My Friends"
-     layout="topleft"
-     name="Friends...">
-        <menu_item_call.on_click
-         function="SideTray.PanelPeopleTab"
-         parameter="friends_panel" />
-    </menu_item_call>
-    <menu_item_call
-     label="My Groups"
-     layout="topleft"
-     name="Groups...">
-        <menu_item_call.on_click
-         function="SideTray.PanelPeopleTab"
-         parameter="groups_panel" />
-    </menu_item_call>
-   <menu_item_call
-     label="My Profile"
-     layout="topleft"
-     name="Profile...">
-        <menu_item_call.on_click
-         function="ShowAgentProfile"
-         parameter="agent" />
-    </menu_item_call>
     <menu_item_call
 		 label="Debug Textures"
          name="Debug...">
@@ -289,8 +270,6 @@
             <menu_item_call.on_visible
              function="Advanced.EnableAppearanceToXML"/>
     </menu_item_call>
-  <menu_item_separator
-       layout="topleft" />
   <menu_item_call
      enabled="false"
      label="Block Particle Owner"
@@ -298,7 +277,7 @@
     <menu_item_call.on_click
      function="Particle.Mute" />
 
-    <menu_item_call.on_enable
+    <menu_item_call.on_visible
      function="EnableMuteParticle" />
   </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 01c2b7f1d9..c70d8097ae 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -15,24 +15,6 @@
          function="ShowAgentProfile"
          parameter="agent" />
       </menu_item_call>
-      <menu_item_call
-       label="Appearance..."
-       name="ChangeOutfit"
-       shortcut="control|O">
-        <menu_item_call.on_click
-         function="Floater.ToggleOrBringToFront"
-         parameter="appearance" />
-        <menu_item_call.on_enable
-         function="Edit.EnableCustomizeAvatar" />
-      </menu_item_call>
-      <menu_item_call
-       label="Choose an avatar..."
-       name="Avatar Picker">
-        <menu_item_call.on_click
-         function="Floater.ToggleOrBringToFront"
-         parameter="avatar" />
-      </menu_item_call>
-      <menu_item_separator/>
       <menu_item_check
          label="Inventory..."
          name="Inventory"
@@ -75,14 +57,6 @@
           function="Floater.ToggleOrBringToFront"
           parameter="experiences"/>
       </menu_item_call>
-      <menu_item_call
-        label="My Scripts..."
-        name="MyScripts">
-        <menu_item_call.on_click
-          function="Floater.ToggleOrBringToFront"
-          parameter="my_scripts"/>
-      </menu_item_call>
-      <menu_item_separator/>
       <menu_item_call
        label="Camera Controls..."
        name="Camera Controls">
@@ -90,105 +64,23 @@
          function="Floater.ToggleOrBringToFront"
          parameter="camera" />
       </menu_item_call>
-      <menu
-       create_jump_keys="true"
-       label="Movement"
-       name="Movement"
-       tear_off="true">
-        <menu_item_call
-         label="Sit Down"
-         layout="topleft"
-         shortcut="alt|shift|S"
-         name="Sit Down Here">
-          <menu_item_call.on_click
-           function="Self.SitDown"/>
-          <menu_item_call.on_visible
-           function="Self.ShowSitDown"/>
-          <menu_item_call.on_enable
-           function="Self.EnableSitDown" />
-        </menu_item_call>
-        <menu_item_call
-         label="Stand Up"
-         layout="topleft"
-         shortcut="alt|shift|S"
-         name="Stand up">
-          <menu_item_call.on_click
-           function="Self.StandUp"/>
-          <menu_item_call.on_visible
-           function="Self.EnableStandUp"/>
-          <menu_item_call.on_enable
-           function="Self.EnableStandUp" />
-        </menu_item_call>
-        <menu_item_check
-         label="Fly"
-         name="Fly"
-         shortcut="HOME">
-          <menu_item_check.on_check
-           function="Agent.getFlying" />
-          <menu_item_check.on_click
-           function="Agent.toggleFlying" />
-          <menu_item_check.on_enable
-           function="Agent.enableFlying" />
-        </menu_item_check>
-        <menu_item_call
-         label="Stop flying"
-         name="Stop flying"
-         shortcut="HOME">
-          <menu_item_call.on_click
-           function="Agent.toggleFlying" />
-          <menu_item_call.on_enable
-           function="Agent.getFlying" />
-        </menu_item_call>	
-        <menu_item_check
-         label="Always Run"
-         name="Always Run"
-         shortcut="control|R">
-          <menu_item_check.on_check
-           function="World.CheckAlwaysRun" />
-          <menu_item_check.on_click
-           function="World.AlwaysRun" />
-        </menu_item_check>
-        <menu_item_call
-         label="Stop Animating Me"
-         name="Stop Animating My Avatar">
-          <menu_item_call.on_click
-           function="Tools.StopAllAnimations" />
-        </menu_item_call>
-        <menu_item_check
-         label="Walk / run / fly..."
-         name="WalkRunFly">
-          <menu_item_check.on_check
-           function="Floater.Visible"
-           parameter="moveview" />
-          <menu_item_check.on_click
-           function="Floater.ToggleOrBringToFront"
-           parameter="moveview" />
-        </menu_item_check>
-      </menu>
-
-      <menu
-       create_jump_keys="true"
-       label="Status"
-       name="Status"
-       tear_off="true">
-        <menu_item_check
-         name="Away"
-         label="Away">
-          <menu_item_check.on_check
-           function="View.Status.CheckAway" />
-          <menu_item_check.on_click
-           function="World.SetAway" />
-        </menu_item_check>
-        <menu_item_check
-         name="Do Not Disturb"
-         label="Do Not Disturb">
-          <menu_item_check.on_check
-           function="View.Status.CheckDoNotDisturb" />
-          <menu_item_check.on_click
-           function="World.SetDoNotDisturb"/>
-        </menu_item_check>
-      
-    </menu>
+      <menu_item_separator/>
+      <menu_item_check
+       name="Away"
+       label="Away">
+        <menu_item_check.on_check
+         function="View.Status.CheckAway" />
+        <menu_item_check.on_click
+         function="World.SetAway" />
+      </menu_item_check>
+      <menu_item_check
+       name="Do Not Disturb"
+       label="Do Not Disturb">
+        <menu_item_check.on_check
+         function="View.Status.CheckDoNotDisturb" />
+        <menu_item_check.on_click
+         function="World.SetDoNotDisturb"/>
+      </menu_item_check>
 
       <menu_item_separator/>
 
@@ -267,6 +159,143 @@
              function="File.Quit" />
         </menu_item_call>
     </menu>
+    <menu
+     create_jump_keys="true"
+     label="Avatar"
+     name="Avatar"
+     tear_off="true">
+       <menu_item_call
+         label="Complete avatars..."
+         name="Avatar Picker">
+            <menu_item_call.on_click
+             function="Floater.ToggleOrBringToFront"
+             parameter="avatar" />
+       </menu_item_call>
+       <menu_item_call
+         label="Outfits..."
+         name="ChangeOutfit"
+         shortcut="control|O">
+            <menu_item_call.on_click
+             function="Floater.ToggleOrBringToFront"
+             parameter="appearance" />
+            <menu_item_call.on_enable
+             function="Edit.EnableCustomizeAvatar" />
+       </menu_item_call>
+       <menu_item_call 
+         label="Current outfit..."
+         layout="topleft"
+         name="Edit Outfit">
+            <menu_item_call.on_click
+             function="EditOutfit" />
+            <menu_item_call.on_enable
+             function="Edit.EnableCustomizeAvatar" />
+       </menu_item_call>
+       <menu_item_call 
+         label="Shape..."
+         layout="topleft"
+         name="Edit My Shape">
+            <menu_item_call.on_click
+             function="EditShape" />
+            <menu_item_call.on_enable
+             function="Edit.EnableEditShape" />
+      </menu_item_call>
+       <menu_item_call label="Hover height..."
+         layout="topleft"
+         name="Hover Height">
+            <menu_item_call.on_click
+             function="HoverHeight" />
+            <menu_item_call.on_enable
+             function="Edit.EnableHoverHeight" />
+      </menu_item_call>
+      <menu_item_separator/>
+
+       <menu_item_call
+         label="Sit / stand"
+         layout="topleft"
+         shortcut="alt|shift|S"
+         name="Sit stand">
+          <menu_item_call.on_click
+           function="Self.ToggleSitStand"/>
+          <menu_item_call.on_enable
+           function="Self.EnableSitStand" />
+        </menu_item_call>
+        <menu_item_call
+         label="Fly / land"
+         name="Fly land"
+         shortcut="HOME">
+          <menu_item_call.on_click
+           function="Agent.toggleFlying" />
+          <menu_item_call.on_enable
+           function="Agent.enableFlyLand" />
+        </menu_item_call>       
+        <menu_item_call
+         label="Stop animation"
+         name="Stop Animating My Avatar">
+          <menu_item_call.on_click
+           function="Tools.StopAllAnimations" />
+        </menu_item_call>
+        <menu_item_check
+          label="Walk / run / fly..."
+          name="WalkRunFly">
+          <menu_item_check.on_check
+           function="Floater.Visible"
+           parameter="moveview" />
+          <menu_item_check.on_click
+           function="Floater.ToggleOrBringToFront"
+           parameter="moveview" />
+        </menu_item_check>
+        <menu_item_check
+          label="Always run"
+          name="Always Run"
+          shortcut="control|R">
+          <menu_item_check.on_check
+           function="World.CheckAlwaysRun" />
+          <menu_item_check.on_click
+           function="World.AlwaysRun" />
+        </menu_item_check>
+      <menu_item_separator/>
+      <menu_item_check
+       label="Gestures..."
+       name="Gestures"
+       shortcut="control|G">
+        <menu_item_check.on_check
+         function="Floater.Visible"
+         parameter="gestures" />
+        <menu_item_check.on_click
+         function="Floater.Toggle"
+         parameter="gestures" />
+      </menu_item_check>
+      <menu_item_separator/>
+      <menu_item_call 
+       label="Reset skeleton"
+       layout="topleft"
+       name="Reset Skeleton">
+        <menu_item_call.on_click
+         function="Avatar.ResetSkeleton" />
+      </menu_item_call>
+      <menu_item_call 
+       label="Reset skeleton and animations"
+       layout="topleft"
+       name="Reset Skeleton And Animations">
+        <menu_item_call.on_click
+         function="Avatar.ResetSkeletonAndAnimations" />
+      </menu_item_call>
+      <menu_item_call
+       label="Attachment scripts..."
+       name="MyScripts">
+        <menu_item_call.on_click
+         function="Floater.ToggleOrBringToFront"
+         parameter="my_scripts"/>
+      </menu_item_call>
+      <menu_item_separator/>
+      <menu_item_call
+     label="Help with avatars..."
+     name="Help with avatars">
+        <menu_item_call.on_click
+            function="Advanced.ShowURL"
+            parameter="https://community.secondlife.com/search/?q=avatar"/>
+      </menu_item_call>
+    </menu>
     <menu
      create_jump_keys="true"
      label="Communicate"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index dc1553e6a3..85d73ece48 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -13,7 +13,7 @@
  width="333">
     <string
      name="edit_shape_title">
-        Editing Shape
+        Shape
     </string>
     <string
      name="edit_skin_title">
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index afce9f6eb5..adbeb09935 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -81,7 +81,7 @@
             name="title"
             text_color="LtGray"
             top="0"
-            value="Edit Outfit"
+            value="Current Outfit"
             use_ellipses="true"
             width="275" />
 
-- 
cgit v1.2.3


From 94cd34cc1762fbcc88930f095fb89b9ae4292928 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 8 Jul 2020 20:29:44 +0300
Subject: SL-13479 Avatar menu tweaks

---
 indra/llui/llmenugl.cpp                            |   4 +-
 indra/newview/llviewermenu.cpp                     |  10 +
 indra/newview/llviewermenu.h                       |   4 +
 indra/newview/llvoavatarself.cpp                   |   8 +-
 .../skins/default/xui/en/menu_attachment_self.xml  | 210 +++++++++++++++++++--
 .../skins/default/xui/en/menu_avatar_self.xml      |   2 +-
 indra/newview/skins/default/xui/en/menu_viewer.xml | 186 +++++++++++++++++-
 7 files changed, 404 insertions(+), 20 deletions(-)

diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 5568a84494..c2698fa648 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -79,7 +79,7 @@ const U32 LEFT_PAD_PIXELS = 3;
 const U32 LEFT_WIDTH_PIXELS = 15;
 const U32 LEFT_PLAIN_PIXELS = LEFT_PAD_PIXELS + LEFT_WIDTH_PIXELS;
 
-const U32 RIGHT_PAD_PIXELS = 2;
+const U32 RIGHT_PAD_PIXELS = 7;
 const U32 RIGHT_WIDTH_PIXELS = 15;
 const U32 RIGHT_PLAIN_PIXELS = RIGHT_PAD_PIXELS + RIGHT_WIDTH_PIXELS;
 
@@ -95,7 +95,7 @@ const std::string SEPARATOR_NAME("separator");
 const std::string VERTICAL_SEPARATOR_LABEL( "|" );
 
 const std::string LLMenuGL::BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK
-const std::string LLMenuGL::BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE
+const std::string LLMenuGL::BRANCH_SUFFIX( "\xe2\x96\xb8" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE
 const std::string LLMenuGL::ARROW_UP  ("^^^^^^^");
 const std::string LLMenuGL::ARROW_DOWN("vvvvvvv");
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 34b4d7f3b3..12d13a78a2 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -186,11 +186,15 @@ const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"
 LLMenuGL* gAttachSubMenu = NULL;
 LLMenuGL* gDetachSubMenu = NULL;
 LLMenuGL* gTakeOffClothes = NULL;
+LLMenuGL* gDetachAvatarMenu = NULL;
+LLMenuGL* gDetachHUDAvatarMenu = NULL;
 LLContextMenu* gAttachScreenPieMenu = NULL;
 LLContextMenu* gAttachPieMenu = NULL;
 LLContextMenu* gAttachBodyPartPieMenus[9];
 LLContextMenu* gDetachPieMenu = NULL;
 LLContextMenu* gDetachScreenPieMenu = NULL;
+LLContextMenu* gDetachAttSelfMenu = NULL;
+LLContextMenu* gDetachHUDAttSelfMenu = NULL;
 LLContextMenu* gDetachBodyPartPieMenus[9];
 
 //
@@ -445,6 +449,9 @@ void init_menus()
 	gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
 		"menu_attachment_other.xml", gMenuHolder, registry);
 
+	gDetachHUDAttSelfMenu = gMenuHolder->getChild<LLContextMenu>("Detach Self HUD", true);
+	gDetachAttSelfMenu = gMenuHolder->getChild<LLContextMenu>("Detach Self", true);
+
 	gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
 		"menu_land.xml", gMenuHolder, registry);
 
@@ -501,6 +508,9 @@ void init_menus()
 	gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
 	gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
 
+	gDetachAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach", true);
+	gDetachHUDAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach HUD", true);
+
 	// Don't display the Memory console menu if the feature is turned off
 	LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
 	if (memoryMenu)
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 0f63c8cf58..36b6971c81 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -188,10 +188,14 @@ extern LLContextMenu		*gMenuMuteParticle;
 extern LLMenuGL* gAttachSubMenu;
 extern LLMenuGL* gDetachSubMenu;
 extern LLMenuGL* gTakeOffClothes;
+extern LLMenuGL* gDetachAvatarMenu;
+extern LLMenuGL* gDetachHUDAvatarMenu;
 extern LLContextMenu* gAttachScreenPieMenu;
 extern LLContextMenu* gDetachScreenPieMenu;
+extern LLContextMenu* gDetachHUDAttSelfMenu;
 extern LLContextMenu* gAttachPieMenu;
 extern LLContextMenu* gDetachPieMenu;
+extern LLContextMenu* gDetachAttSelfMenu;
 extern LLContextMenu* gAttachBodyPartPieMenus[9];
 extern LLContextMenu* gDetachBodyPartPieMenus[9];
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index aea12380e8..d2dc139d4b 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -465,6 +465,8 @@ BOOL LLVOAvatarSelf::buildMenus()
 		if (gDetachBodyPartPieMenus[i])
 		{
 			gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] );
+			gDetachAttSelfMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]);
+			gDetachAvatarMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]);
 		}
 		else
 		{
@@ -493,12 +495,14 @@ BOOL LLVOAvatarSelf::buildMenus()
 					LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
 
 					gDetachPieMenu->addChild(item);
-						
+					gDetachAttSelfMenu->addChild(LLUICtrlFactory::create<LLMenuItemCallGL>(item_params));
+					gDetachAvatarMenu->addChild(LLUICtrlFactory::create<LLMenuItemCallGL>(item_params));
 					break;
 				}
 			}
 		}
 	}
+	
 
 	// add screen attachments
 	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
@@ -532,6 +536,8 @@ BOOL LLVOAvatarSelf::buildMenus()
 			item_params.on_enable.parameter = iter->first;
 			item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
 			gDetachScreenPieMenu->addChild(item);
+			gDetachHUDAttSelfMenu->addChild(LLUICtrlFactory::create<LLMenuItemCallGL>(item_params));
+			gDetachHUDAvatarMenu->addChild(LLUICtrlFactory::create<LLMenuItemCallGL>(item_params));
 		}
 	}
 
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 03c05e6591..856bf4ce73 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -2,17 +2,6 @@
 <context_menu
  layout="topleft"
  name="Attachment Pie">
-    <menu_item_call
-     enabled="false"
-     label="Touch item"
-     layout="topleft"
-     name="Attachment Object Touch">
-        <menu_item_call.on_click
-         function="Object.Touch" />
-        <menu_item_call.on_enable
-         function="Object.EnableTouch"
-         name="EnableTouch"/>
-    </menu_item_call>
     <menu_item_call
      enabled="false"
      label="Edit item"
@@ -33,8 +22,19 @@
         <menu_item_call.on_enable
          function="Attachment.EnableDetach" />
     </menu_item_call>
-  <menu_item_separator
-    layout="topleft" />
+    <menu_item_call
+     enabled="false"
+     label="Touch item"
+     layout="topleft"
+     name="Attachment Object Touch">
+        <menu_item_call.on_click
+         function="Object.Touch" />
+        <menu_item_call.on_enable
+         function="Object.EnableTouch"
+         name="EnableTouch"/>
+    </menu_item_call>
+    <menu_item_separator
+     layout="topleft" />
 
   <menu_item_call
   label="Outfits..."
@@ -44,7 +44,7 @@
     <menu_item_call.on_enable
      function="Edit.EnableCustomizeAvatar" />
   </menu_item_call>
-  <menu_item_call label="Edit current outfit..."
+  <menu_item_call label="Current outfit..."
 layout="topleft"
 name="Edit Outfit">
     <menu_item_call.on_click
@@ -68,6 +68,188 @@ name="Edit Outfit">
      <menu_item_call.on_enable
       function="Edit.EnableHoverHeight" />
   </menu_item_call>
+  <context_menu
+  label="Take Off"
+  layout="topleft"
+  name="Take Off &gt;">
+    <context_menu
+     label="Clothes"
+     layout="topleft"
+     name="Clothes &gt;">
+      <menu_item_call
+       enabled="false"
+       label="Shirt"
+       layout="topleft"
+       name="Shirt">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="shirt" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="shirt" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Pants"
+       layout="topleft"
+       name="Pants">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="pants" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="pants" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Skirt"
+       layout="topleft"
+       name="Skirt">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="skirt" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="skirt" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Shoes"
+       layout="topleft"
+       name="Shoes">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="shoes" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="shoes" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Socks"
+       layout="topleft"
+       name="Socks">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="socks" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="socks" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Jacket"
+       layout="topleft"
+       name="Jacket">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="jacket" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="jacket" />
+      </menu_item_call>
+      <menu_item_call
+       enabled="false"
+       label="Gloves"
+       layout="topleft"
+       name="Gloves">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="gloves" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="gloves" />
+      </menu_item_call>
+      <menu_item_call
+            enabled="false"
+            label="Undershirt"
+            layout="topleft"
+            name="Self Undershirt">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="undershirt" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="undershirt" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Underpants"
+        layout="topleft"
+        name="Self Underpants">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="underpants" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="underpants" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Tattoo"
+        layout="topleft"
+        name="Self Tattoo">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="tattoo" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="tattoo" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Physics"
+        layout="topleft"
+        name="Self Physics">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="physics" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="physics" />
+      </menu_item_call>
+      <menu_item_call
+        enabled="false"
+        label="Alpha"
+        layout="topleft"
+        name="Self Alpha">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="alpha" />
+        <menu_item_call.on_enable
+         function="Edit.EnableTakeOff"
+         parameter="alpha" />
+      </menu_item_call>
+      <menu_item_separator
+       layout="topleft" />
+      <menu_item_call
+       label="All Clothes"
+       layout="topleft"
+       name="All Clothes">
+        <menu_item_call.on_click
+         function="Edit.TakeOff"
+         parameter="all" />
+      </menu_item_call>
+    </context_menu>
+    <context_menu
+     label="HUD"
+     layout="topleft"
+     name="Detach Self HUD" />
+    <context_menu
+     label="Detach"
+     layout="topleft"
+     name="Detach Self" />
+    <menu_item_call
+     label="Detach All"
+     layout="topleft"
+     name="Detach All">
+      <menu_item_call.on_click
+       function="Self.RemoveAllAttachments"
+       parameter="" />
+      <menu_item_call.on_enable
+       function="Self.EnableRemoveAllAttachments" />
+    </menu_item_call>
+  </context_menu>
   <menu_item_separator/>
   <menu_item_call
     label="Sit / stand"
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index 3dcafb13ef..a46d9aed55 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -11,7 +11,7 @@
         <menu_item_call.on_enable
          function="Edit.EnableCustomizeAvatar" />
     </menu_item_call>
-    <menu_item_call label="Edit current outfit..." 
+    <menu_item_call label="Current outfit..." 
     layout="topleft"
     name="Edit Outfit">
        <menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index c70d8097ae..0d456ffe5d 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -207,6 +207,188 @@
             <menu_item_call.on_enable
              function="Edit.EnableHoverHeight" />
       </menu_item_call>
+      <menu
+        label="Take Off"
+        layout="topleft"
+        name="Take Off &gt;">
+        <menu
+         label="Clothes"
+         layout="topleft"
+         name="Clothes &gt;">
+          <menu_item_call
+           enabled="false"
+           label="Shirt"
+           layout="topleft"
+           name="Shirt">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="shirt" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="shirt" />
+          </menu_item_call>
+          <menu_item_call
+           enabled="false"
+           label="Pants"
+           layout="topleft"
+           name="Pants">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="pants" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="pants" />
+          </menu_item_call>
+          <menu_item_call
+           enabled="false"
+           label="Skirt"
+           layout="topleft"
+           name="Skirt">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="skirt" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="skirt" />
+          </menu_item_call>
+          <menu_item_call
+           enabled="false"
+           label="Shoes"
+           layout="topleft"
+           name="Shoes">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="shoes" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="shoes" />
+          </menu_item_call>
+          <menu_item_call
+           enabled="false"
+           label="Socks"
+           layout="topleft"
+           name="Socks">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="socks" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="socks" />
+          </menu_item_call>
+          <menu_item_call
+           enabled="false"
+           label="Jacket"
+           layout="topleft"
+           name="Jacket">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="jacket" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="jacket" />
+          </menu_item_call>
+          <menu_item_call
+           enabled="false"
+           label="Gloves"
+           layout="topleft"
+           name="Gloves">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="gloves" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="gloves" />
+          </menu_item_call>
+          <menu_item_call
+                enabled="false"
+                label="Undershirt"
+                layout="topleft"
+                name="Self Undershirt">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="undershirt" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="undershirt" />
+          </menu_item_call>
+          <menu_item_call
+            enabled="false"
+            label="Underpants"
+            layout="topleft"
+            name="Self Underpants">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="underpants" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="underpants" />
+          </menu_item_call>
+          <menu_item_call
+            enabled="false"
+            label="Tattoo"
+            layout="topleft"
+            name="Self Tattoo">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="tattoo" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="tattoo" />
+          </menu_item_call>
+          <menu_item_call
+            enabled="false"
+            label="Physics"
+            layout="topleft"
+            name="Self Physics">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="physics" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="physics" />
+          </menu_item_call>
+          <menu_item_call
+            enabled="false"
+            label="Alpha"
+            layout="topleft"
+            name="Self Alpha">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="alpha" />
+            <menu_item_call.on_enable
+             function="Edit.EnableTakeOff"
+             parameter="alpha" />
+          </menu_item_call>
+          <menu_item_separator
+           layout="topleft" />
+          <menu_item_call
+           label="All Clothes"
+           layout="topleft"
+           name="All Clothes">
+            <menu_item_call.on_click
+             function="Edit.TakeOff"
+             parameter="all" />
+          </menu_item_call>
+        </menu>
+        <menu
+         label="HUD"
+         layout="topleft"
+         name="Avatar Detach HUD" />
+        <menu
+         label="Detach"
+         layout="topleft"
+         name="Avatar Detach" />
+        <menu_item_call
+         label="Detach All"
+         layout="topleft"
+         name="Detach All">
+          <menu_item_call.on_click
+           function="Self.RemoveAllAttachments"
+           parameter="" />
+          <menu_item_call.on_enable
+           function="Self.EnableRemoveAllAttachments" />
+        </menu_item_call>
+      </menu>
       <menu_item_separator/>
 
        <menu_item_call
@@ -229,7 +411,7 @@
            function="Agent.enableFlyLand" />
         </menu_item_call>       
         <menu_item_call
-         label="Stop animation"
+         label="Stop animations"
          name="Stop Animating My Avatar">
           <menu_item_call.on_click
            function="Tools.StopAllAnimations" />
@@ -293,7 +475,7 @@
      name="Help with avatars">
         <menu_item_call.on_click
             function="Advanced.ShowURL"
-            parameter="https://community.secondlife.com/search/?q=avatar"/>
+            parameter="https://community.secondlife.com/search/?type=cms_records3&amp;tags=avatar&amp;nodes=30&amp;search_and_or=or"/>
       </menu_item_call>
     </menu>
     <menu
-- 
cgit v1.2.3


From d1789103c2a4307dd24280d61a83819e817da819 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 15 Jul 2020 18:35:59 +0300
Subject: SL-13612 Dedicated Avatar menu -- Revise toolbar button labels

---
 indra/newview/skins/default/xui/en/strings.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 0b95b43f39..db9d3bfa83 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4113,8 +4113,8 @@ Try enclosing path to the editor with double quotes.
   <!-- commands -->
 
   <string name="Command_AboutLand_Label">About land</string>
-  <string name="Command_Appearance_Label">Appearance</string>
-  <string name="Command_Avatar_Label">Avatar</string>
+  <string name="Command_Appearance_Label">Outfits</string>
+  <string name="Command_Avatar_Label">Complete avatars</string>
   <string name="Command_Build_Label">Build</string>
   <string name="Command_Chat_Label">Chat</string>
   <string name="Command_Conversations_Label">Conversations</string>
-- 
cgit v1.2.3


From 6ec194154be3d40f897d728925d1a565c6f8be78 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 10 Dec 2020 17:43:21 +0200
Subject: SL-13826 Show result of "Find original" and "Show original" in Main
 Inventory floater and reset the filters to guarantee success

---
 indra/newview/llinventorybridge.cpp    | 41 +++++++------------
 indra/newview/llinventoryfunctions.cpp | 73 +++++++++++++++++-----------------
 indra/newview/llinventorypanel.cpp     | 36 ++++-------------
 indra/newview/llinventorypanel.h       |  6 +--
 indra/newview/llpanelmaininventory.cpp | 15 ++-----
 indra/newview/llpanelmaininventory.h   |  6 +--
 6 files changed, 67 insertions(+), 110 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index ae96963b2a..27e222237e 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1863,29 +1863,11 @@ void LLItemBridge::restoreToWorld()
 
 void LLItemBridge::gotoItem()
 {
-	LLInventoryObject *obj = getInventoryObject();
-	if (obj && obj->getIsLinkType())
-	{
-		const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
-		if (gInventory.isObjectDescendentOf(obj->getLinkedUUID(), inbox_id))
-		{
-			LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-			if (sidepanel_inventory && sidepanel_inventory->getInboxPanel())
-			{
-				sidepanel_inventory->getInboxPanel()->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
-			}
-		}
-		else
-		{
-			LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
-			if (active_panel)
-			{
-				active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
-				active_panel->setFocus(TRUE);
-			}
-		}
-
-	}
+    LLInventoryObject *obj = getInventoryObject();
+    if (obj && obj->getIsLinkType())
+    {
+        show_item_original(obj->getUUID());
+    }
 }
 
 LLUIImagePtr LLItemBridge::getIcon() const
@@ -7251,13 +7233,20 @@ void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string acti
 	}
 	LLItemBridge::performAction(model,action);
 }
-
 void LLLinkFolderBridge::gotoItem()
 {
     LLItemBridge::gotoItem();
-    LLInventoryPanel::getActiveInventoryPanel()->openFolderByID(getFolderID());
-}
 
+    const LLUUID &cat_uuid = getFolderID();
+    if (!cat_uuid.isNull())
+    {
+        LLFolderViewItem *base_folder = LLInventoryPanel::getActiveInventoryPanel()->getItemByID(cat_uuid);
+        if (base_folder)
+        {
+            base_folder->setOpen(TRUE);
+        }
+    }
+}
 const LLUUID &LLLinkFolderBridge::getFolderID() const
 {
 	if (LLViewerInventoryItem *link_item = getItem())
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 628363a47e..181bc48571 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -774,35 +774,45 @@ void show_item_profile(const LLUUID& item_uuid)
 
 void show_item_original(const LLUUID& item_uuid)
 {
-	LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory");
-	if (!floater_inventory)
-	{
-		LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL;
-		return;
-	}
-
-	//sidetray inventory panel
-	LLSidepanelInventory *sidepanel_inventory =	LLPanelMainInventory::newWindow()->LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-
+    LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory");
+    if (!floater_inventory)
+    {
+        LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL;
+        return;
+    }
+    LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+    if (sidepanel_inventory)
+    {
+        LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
+        if (main_inventory)
+        {
+            main_inventory->resetFilters();
+        }
+        reset_inventory_filter();
 
-	LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel();
-	if (!active_panel) 
-	{
-		//this may happen when there is no floatera and other panel is active in inventory tab
+        if (!LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>("inventory")->isInVisibleChain())
+        {
+            LLFloaterReg::toggleInstanceOrBringToFront("inventory");
+        }
 
-		if	(sidepanel_inventory)
-		{
-			sidepanel_inventory->showInventoryPanel();
-		}
-	}
-	
-	active_panel = LLInventoryPanel::getActiveInventoryPanel();
-	if (!active_panel) 
-	{
-		return;
-	}
-	active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES);
-	active_panel->setFocus(TRUE);
+        const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
+        if (gInventory.isObjectDescendentOf(gInventory.getLinkedItemID(item_uuid), inbox_id))
+        {
+            if (sidepanel_inventory->getInboxPanel())
+            {
+                sidepanel_inventory->openInbox();
+                sidepanel_inventory->getInboxPanel()->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES);
+            }
+        }
+        else
+        {
+            sidepanel_inventory->selectAllItemsPanel();
+            if (sidepanel_inventory->getActivePanel())
+            {
+                sidepanel_inventory->getActivePanel()->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES);
+            }
+        }
+    }
 }
 
 
@@ -2486,15 +2496,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
     }
     else
     {
-        if (action == "goto")
-        {
-            LLSidepanelInventory *sidepanel_inventory = LLPanelMainInventory::newWindow()->LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-            if (sidepanel_inventory && sidepanel_inventory->getMainInventoryPanel())
-            {
-                model = sidepanel_inventory->getMainInventoryPanel()->getActivePanel()->getModel();
-            }
-        }
-        
         std::set<LLFolderViewItem*>::iterator set_iter;
         for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
         {
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 0246878ab6..1f5dfa6d5c 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -157,7 +157,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mViewsInitialized(false),
 	mInvFVBridgeBuilder(NULL),
 	mInventoryViewModel(p.name),
-	mGroupedItemBridge(new LLFolderViewGroupedItemBridge)
+	mGroupedItemBridge(new LLFolderViewGroupedItemBridge),
+	mFocusSelection(false)
 {
 	mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
 
@@ -339,7 +340,6 @@ void LLInventoryPanel::draw()
 {
 	// Select the desired item (in case it wasn't loaded when the selection was requested)
 	updateSelection();
-	updateFolderState();
 	
 	LLPanel::draw();
 }
@@ -1222,7 +1222,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::
 void LLInventoryPanel::clearSelection()
 {
 	mSelectThisID.setNull();
-	mOpenFolderID.setNull();
+	mFocusSelection = false;
 }
 
 LLInventoryPanel::selected_items_t LLInventoryPanel::getSelectedItems() const
@@ -1702,15 +1702,17 @@ LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id)
 void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL    take_keyboard_focus )
 {
 	LLFolderViewItem* itemp = getItemByID(obj_id);
-	if(itemp && itemp->getViewModelItem())
+	if(itemp && itemp->getViewModelItem() && itemp->passedFilter())
 	{
 		itemp->arrangeAndSet(TRUE, take_keyboard_focus);
 		mSelectThisID.setNull();
+		mFocusSelection = false;
 		return;
 	}
 	else
 	{
 		// save the desired item to be selected later (if/when ready)
+		mFocusSelection = take_keyboard_focus;
 		mSelectThisID = obj_id;
 	}
 }
@@ -1719,34 +1721,10 @@ void LLInventoryPanel::updateSelection()
 {
 	if (mSelectThisID.notNull())
 	{
-		setSelectionByID(mSelectThisID, false);
+		setSelectionByID(mSelectThisID, mFocusSelection);
 	}
 }
 
-void LLInventoryPanel::openFolderByID( const LLUUID& folder_id)
-{
-    LLFolderViewItem* itemp = getItemByID(folder_id);
-    if(itemp && itemp->getViewModelItem())
-    {
-        itemp->setOpen(TRUE);
-        mOpenFolderID.setNull();
-        return;
-    }
-    else
-    {
-        // save the desired folder to be open later (if/when ready)
-        mOpenFolderID = folder_id;
-    }
-}
-
-void LLInventoryPanel::updateFolderState()
-{
-    if (mOpenFolderID.notNull())
-    {
-        openFolderByID(mOpenFolderID);
-    }
-}
-
 void LLInventoryPanel::doToSelected(const LLSD& userdata)
 {
 	if (("purge" == userdata.asString()))
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 2bcc3f3c0b..447d24b959 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -244,9 +244,7 @@ public:
 	LLFolderViewItem* getItemByID(const LLUUID& id);
 	LLFolderViewFolder* getFolderByID(const LLUUID& id);
 	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus);
-	void openFolderByID(const LLUUID& folder_id);
 	void updateSelection();
-	void updateFolderState();
 
 	void setSuppressOpenItemAction(bool supress_open_item) { mSuppressOpenItemAction = supress_open_item; }
 
@@ -262,11 +260,11 @@ protected:
 	void openStartFolderOrMyInventory(); // open the first level of inventory
 	void onItemsCompletion();			// called when selected items are complete
 
-    LLUUID						mSelectThisID;
-	LLUUID						mOpenFolderID;	
+    LLUUID						mSelectThisID;	
 	LLInventoryModel*			mInventory;
 	LLInventoryObserver*		mInventoryObserver;
 	LLInvPanelComplObserver*	mCompletionObserver;
+	bool						mFocusSelection;
 	bool						mAcceptsDragAndDrop;
 	bool 						mAllowMultiSelect;
 	bool 						mAllowDrag;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 813a5b3c20..4691ee3849 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -383,16 +383,15 @@ void LLPanelMainInventory::closeAllFolders()
 	getPanel()->getRootFolder()->closeAllFolders();
 }
 
-LLFloaterSidePanelContainer* LLPanelMainInventory::newWindow()
+void LLPanelMainInventory::newWindow()
 {
 	static S32 instance_num = 0;
 	instance_num = (instance_num + 1) % S32_MAX;
 
 	if (!gAgentCamera.cameraMouselook())
 	{
-		return LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
+		LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
 	}
-    return NULL;
 }
 
 void LLPanelMainInventory::doCreate(const LLSD& userdata)
@@ -1344,15 +1343,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 		{
 			return;
 		}
-        LLSidepanelInventory *sidepanel_inventory = newWindow()->LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
-        if (sidepanel_inventory)
-        {
-            LLPanelMainInventory* new_inventory = sidepanel_inventory->getMainInventoryPanel();
-            if (new_inventory)
-            {
-                static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(new_inventory->getActivePanel()->getModel(), "goto");
-            }
-        }
+		static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto");
 	}
 
 	if (command_name == "find_links")
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 40f04da6e9..313e478bfe 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -46,7 +46,6 @@ class LLMenuButton;
 class LLMenuGL;
 class LLToggleableMenu;
 class LLFloater;
-class LLFloaterSidePanelContainer;
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLPanelMainInventory
@@ -91,10 +90,12 @@ public:
 
 	void setFocusFilterEditor();
 
-	static LLFloaterSidePanelContainer* newWindow();
+	static void newWindow();
 
 	void toggleFindOptions();
 
+    void resetFilters();
+
 protected:
 	//
 	// Misc functions
@@ -119,7 +120,6 @@ protected:
 	void doToSelected(const LLSD& userdata);
 	void closeAllFolders();
 	void doCreate(const LLSD& userdata);
-	void resetFilters();
 	void setSortBy(const LLSD& userdata);
 	void saveTexture(const LLSD& userdata);
 	bool isSaveTextureEnabled(const LLSD& userdata);
-- 
cgit v1.2.3


From ba47d9315470049bc19a7c07b6a333f56b490bad Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 4 Jan 2021 20:26:23 +0200
Subject: SL-14491 llDialog spacing inconsistent between string and buttons

---
 doc/contributions.txt                | 2 ++
 indra/newview/lltoastnotifypanel.cpp | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index bbdfaf655d..c33bc2607f 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -358,6 +358,8 @@ Chaser Zaks
     BUG-227485
 Cherry Cheevers
 ChickyBabes Zuzu
+Chorazin Allen
+    BUG-229753
 Christopher  Organiser
 Ciaran Laval
 Cinder Roxley
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index bccf88128d..024f25bc98 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -387,9 +387,9 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
             if (mIsScriptDialog)
             {
                 // we are using default width for script buttons so we can determinate button_rows
-                //to get a number of rows we divide the required width of the buttons to button_panel_width
-                S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width);
-                //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width;
+                // to get a number of rows we divide the required width of the buttons to button_panel_width
+                // buttons.size() is reduced by -2 due to presence of ignore button which is calculated independently a bit lower
+                S32 button_rows = llceil(F32(buttons.size() - 2) * (BUTTON_WIDTH + h_pad) / (button_panel_width + h_pad));
                 //reserve one row for the ignore_btn
                 button_rows++;
                 //calculate required panel height for scripdialog notification.
-- 
cgit v1.2.3


From 8c41c00888bbfe7b1c6501e995554a39a8bf944b Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 5 Jan 2021 17:43:14 +0200
Subject: SL-14632 FIXED The viewer is crashed after deleting the new favorite
 folder

---
 indra/newview/llviewerinventory.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index bbed741a33..ed1d726528 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1422,6 +1422,11 @@ void remove_inventory_category(
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
 			return;
 		}
+		const LLUUID fav_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+		if ((cat_id == fav_id) || gInventory.isObjectDescendentOf(fav_id, cat_id))
+		{
+			gSavedPerAccountSettings.setString("FavoritesFolder", "");
+		}
         AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
         AISAPI::RemoveCategory(cat_id, cr);
 	}
-- 
cgit v1.2.3


From 1087c26de7ba89465618518ba93dc7161f075f47 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 6 Jan 2021 12:08:21 +0200
Subject: SL-14633 FIXED The item from the favorite tab in the inventory
 floater can be purged

---
 indra/newview/llinventorybridge.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 27e222237e..34e2dc7904 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -987,7 +987,7 @@ void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items,
 		}
 	}
 	items.push_back(std::string("Purge Item"));
-	if (!isItemRemovable())
+	if (!isItemRemovable() || isPanelActive("Favorite Items"))
 	{
 		disabled_items.push_back(std::string("Purge Item"));
 	}
-- 
cgit v1.2.3


From 1dd32bb772bb2f0d6d4f3180965a8bdcf9c1000d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 2 Feb 2021 23:47:48 +0200
Subject: SL-14796 After teleporting, add notation into Nearby Chat

---
 indra/llui/llchat.h                            |  6 ++-
 indra/newview/llagent.cpp                      | 60 +++++++++++++++++++++++++
 indra/newview/llagent.h                        |  3 ++
 indra/newview/llchathistory.cpp                | 62 +++++++++++++++++++-------
 indra/newview/llviewerdisplay.cpp              |  1 +
 indra/newview/skins/default/colors.xml         |  3 ++
 indra/newview/skins/default/xui/en/strings.xml |  3 ++
 7 files changed, 120 insertions(+), 18 deletions(-)

diff --git a/indra/llui/llchat.h b/indra/llui/llchat.h
index f5b242fdfc..c39e44200c 100644
--- a/indra/llui/llchat.h
+++ b/indra/llui/llchat.h
@@ -37,7 +37,8 @@ typedef enum e_chat_source_type
 	CHAT_SOURCE_SYSTEM = 0,
 	CHAT_SOURCE_AGENT = 1,
 	CHAT_SOURCE_OBJECT = 2,
-	CHAT_SOURCE_UNKNOWN = 3
+	CHAT_SOURCE_TELEPORT = 3,
+	CHAT_SOURCE_UNKNOWN = 4
 } EChatSourceType;
 
 typedef enum e_chat_type
@@ -64,7 +65,8 @@ typedef enum e_chat_style
 {
 	CHAT_STYLE_NORMAL,
 	CHAT_STYLE_IRC,
-	CHAT_STYLE_HISTORY
+	CHAT_STYLE_HISTORY,
+	CHAT_STYLE_TELEPORT_SEP
 }EChatStyle;
 
 // A piece of chat
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index c65bc0fa50..f31135ad4c 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -519,6 +519,10 @@ void LLAgent::cleanup()
 	{
 		mTeleportFailedSlot.disconnect();
 	}
+    if (mParcelMgrConnection.connected())
+    {
+        mParcelMgrConnection.disconnect();
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -3934,6 +3938,10 @@ void LLAgent::clearTeleportRequest()
         LLVoiceClient::getInstance()->setHidden(FALSE);
     }
 	mTeleportRequest.reset();
+    if (mParcelMgrConnection.connected())
+    {
+        mParcelMgrConnection.disconnect();
+    }
 }
 
 void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange)
@@ -3942,6 +3950,12 @@ void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange)
 	mMaturityRatingChange = pMaturityRatingChange;
 }
 
+void LLAgent::sheduleTeleportIM()
+{
+    // is supposed to be called during teleport so we are still waiting for parcel
+    mParcelMgrConnection = addParcelChangedCallback(onParcelReadyAfterTeleport);
+}
+
 bool LLAgent::hasPendingTeleportRequest()
 {
 	return ((mTeleportRequest != NULL) &&
@@ -4051,6 +4065,52 @@ void LLAgent::handleTeleportFailed()
 		LLNotificationsUtil::add("PreferredMaturityChanged", args);
 		mIsMaturityRatingChangingDuringTeleport = false;
 	}
+
+    if (mParcelMgrConnection.connected())
+    {
+        mParcelMgrConnection.disconnect();
+    }
+}
+
+/*static*/
+void LLAgent::onParcelReadyAfterTeleport()
+{
+    LLViewerRegion* agent_region = gAgent.getRegion();
+    LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+    if (!agent_region || !agent_parcel)
+    {
+        return;
+    }
+
+    LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
+    if (nearby_chat)
+    {
+        std::string location_name;
+        LLAgentUI::ELocationFormat format = LLAgentUI::LOCATION_FORMAT_NO_MATURITY;
+
+        // Might be better to provide slurl to chat
+        if (!LLAgentUI::buildLocationString(location_name, format))
+        {
+            location_name = "Teleport to new region"; // Shouldn't happen
+        }
+
+        LLChat chat;
+        chat.mFromName = location_name;
+        chat.mMuted = FALSE;
+        chat.mFromID = LLUUID::null;
+        chat.mSourceType = CHAT_SOURCE_TELEPORT;
+        chat.mChatStyle = CHAT_STYLE_TELEPORT_SEP;
+        chat.mText = "";
+
+        LLSD args;
+        args["do_not_log"] = TRUE;
+        nearby_chat->addMessage(chat, true, args);
+    }
+
+    if (gAgent.mParcelMgrConnection.connected())
+    {
+        gAgent.mParcelMgrConnection.disconnect();
+    }
 }
 
 /*static*/
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index d46c99db8c..8f8c2f6007 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -653,6 +653,7 @@ public:
 	void            restartFailedTeleportRequest();
 	void            clearTeleportRequest();
 	void            setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange);
+	void            sheduleTeleportIM();
 
 private:
 
@@ -667,6 +668,7 @@ private:
 	LLTeleportRequestPtr        mTeleportCanceled;
 	boost::signals2::connection mTeleportFinishedSlot;
 	boost::signals2::connection mTeleportFailedSlot;
+	boost::signals2::connection	mParcelMgrConnection;
 
 	bool            mIsMaturityRatingChangingDuringTeleport;
 	U8              mMaturityRatingChange;
@@ -685,6 +687,7 @@ private:
 	void            handleTeleportFinished();
 	void            handleTeleportFailed();
 
+    static void     onParcelReadyAfterTeleport();
     static void     onCapabilitiesReceivedAfterTeleport();
 
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 2ba2c6d8b5..2bb68dbbbe 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -122,6 +122,7 @@ public:
 		mUserNameFont(NULL),
 		mUserNameTextBox(NULL),
 		mTimeBoxTextBox(NULL),
+		mNeedsTimeBox(true),
 		mAvatarNameCacheConnection()
 	{}
 
@@ -643,8 +644,19 @@ public:
 		user_name->setReadOnlyColor(style_params.readonly_color());
 		user_name->setColor(style_params.color());
 
-		if (chat.mFromName.empty()
-			|| mSourceType == CHAT_SOURCE_SYSTEM)
+        if (mSourceType == CHAT_SOURCE_TELEPORT
+            && chat.mChatStyle == CHAT_STYLE_TELEPORT_SEP)
+        {
+            mFrom = chat.mFromName;
+            mNeedsTimeBox = false;
+            user_name->setValue(mFrom);
+            updateMinUserNameWidth();
+            LLColor4 sep_color = LLUIColorTable::instance().getColor("ChatTeleportSeparatorColor");
+            setTransparentColor(sep_color);
+            mTimeBoxTextBox->setVisible(FALSE);
+        }
+        else if (chat.mFromName.empty()
+                 || mSourceType == CHAT_SOURCE_SYSTEM)
 		{
 			mFrom = LLTrans::getString("SECOND_LIFE");
 			if(!chat.mFromName.empty() && (mFrom != chat.mFromName))
@@ -727,6 +739,8 @@ public:
 				break;
 			case CHAT_SOURCE_SYSTEM:
 				icon->setValue(LLSD("SL_Logo"));
+			case CHAT_SOURCE_TELEPORT:
+				icon->setValue(LLSD("Command_Destinations_Icon"));
 				break;
 			case CHAT_SOURCE_UNKNOWN: 
 				icon->setValue(LLSD("Unknown_Icon"));
@@ -766,7 +780,7 @@ public:
 		S32 user_name_width = user_name_rect.getWidth();
 		S32 time_box_width = time_box->getRect().getWidth();
 
-		if (!time_box->getVisible() && user_name_width > mMinUserNameWidth)
+		if (mNeedsTimeBox && !time_box->getVisible() && user_name_width > mMinUserNameWidth)
 		{
 			user_name_rect.mRight -= time_box_width;
 			user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight());
@@ -968,6 +982,8 @@ protected:
 	LLTextBox*			mUserNameTextBox;
 	LLTextBox*			mTimeBoxTextBox; 
 
+    bool				mNeedsTimeBox;
+
 private:
 	boost::signals2::connection mAvatarNameCacheConnection;
 };
@@ -1202,6 +1218,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 	}
 
 	bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;
+	bool teleport_separator = chat.mSourceType == CHAT_SOURCE_TELEPORT;
 	// We graying out chat history by graying out messages that contains full date in a time string
 	if (message_from_log)
 	{
@@ -1222,14 +1239,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		LLStyle::Params timestamp_style(body_message_params);
 
 		// out of the timestamp
-		if (args["show_time"].asBoolean())
+		if (args["show_time"].asBoolean() && !teleport_separator)
 		{
-		if (!message_from_log)
-		{
-			LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor");
-			timestamp_style.color(timestamp_color);
-			timestamp_style.readonly_color(timestamp_color);
-		}
+			if (!message_from_log)
+			{
+				LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor");
+				timestamp_style.color(timestamp_color);
+				timestamp_style.readonly_color(timestamp_color);
+			}
 			mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style);
 			prependNewLineState = false;
 		}
@@ -1272,6 +1289,13 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 					prependNewLineState, link_params);
 				prependNewLineState = false;
 			}
+            else if (teleport_separator)
+            {
+                std::string tp_text = LLTrans::getString("teleport_preamble_compact_chat");
+                mEditor->appendText(tp_text + " <nolink>" + chat.mFromName + "</nolink>",
+                    prependNewLineState, body_message_params);
+                                prependNewLineState = false;
+            }
 			else
 			{
 				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter,
@@ -1290,8 +1314,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		p.right_pad = mRightWidgetPad;
 
 		LLDate new_message_time = LLDate::now();
-
-		if (mLastFromName == chat.mFromName 
+		if (!teleport_separator
+			&& mLastFromName == chat.mFromName
 			&& mLastFromID == chat.mFromID
 			&& mLastMessageTime.notNull() 
 			&& (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0
@@ -1314,7 +1338,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 				p.top_pad = 0;
 			else
 				p.top_pad = mTopHeaderPad;
-            p.bottom_pad = mBottomHeaderPad;
+            if (teleport_separator)
+            {
+                p.bottom_pad = mBottomSeparatorPad;
+            }
+            else
+            {
+                p.bottom_pad = mBottomHeaderPad;
+            }
             if (!view)
             {
                 LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL;
@@ -1392,9 +1423,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 			}
 		}
 	}
-
 	// usual messages showing
-	else
+	else if(!teleport_separator)
 	{
 		std::string message = irc_me ? chat.mText.substr(3) : chat.mText;
 
@@ -1427,7 +1457,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		if (square_brackets)
 		{
 			message += "]";
-	}
+		}
 
 		mEditor->appendText(message, prependNewLineState, body_message_params);
 		prependNewLineState = false;
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index d314b1477a..5679c3c325 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -474,6 +474,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
 			gAgent.setTeleportMessage(
 				LLAgent::sTeleportProgressMessages["arriving"]);
+			gAgent.sheduleTeleportIM();
 			gTextureList.mForceResetTextureStats = TRUE;
 			gAgentCamera.resetView(TRUE, TRUE);
 			
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 034576d30c..92398857ba 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -850,6 +850,9 @@
     <color
     name="ColorSwatchBorderColor"
     value="0.45098 0.517647 0.607843 1"/>
+    <color
+     name="ChatTeleportSeparatorColor"
+     reference="Black" />
     <color
      name="ChatTimestampColor"
      reference="White" />
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index db9d3bfa83..c2b5286fc3 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3758,6 +3758,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   </string>
   <string name="unread_chat_multiple">
     [SOURCES] have said something new
+  </string>
+  <string name="teleport_preamble_compact_chat">
+    You are now at
   </string>
 	<string name="session_initialization_timed_out_error">
 		The session initialization is timed out
-- 
cgit v1.2.3


From 2351809b5cb71d17461a6bec2041cbc1ad2efc91 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 4 Feb 2021 18:04:42 +0200
Subject: SL-14796 Resolved encountered merge issue

---
 indra/newview/llviewerparcelmgr.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index d5365e4ee8..06172e366d 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1715,9 +1715,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 			// Let interesting parties know about agent parcel change.
 			LLViewerParcelMgr* instance = LLViewerParcelMgr::getInstance();
 
-			// Notify anything that wants to know when the agent changes parcels
-			gAgent.changeParcels();
-
 			if (instance->mTeleportInProgress)
 			{
 				instance->mTeleportInProgress = FALSE;
@@ -1733,6 +1730,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 			}
             parcel->setParcelEnvironmentVersion(parcel_environment_version);
             LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
+
             // Notify anything that wants to know when the agent changes parcels
             gAgent.changeParcels();
             instance->mTeleportInProgress = FALSE;
-- 
cgit v1.2.3


From ca6121979c6716aaf986fc6d0d469383471469f4 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 4 Feb 2021 18:06:17 +0200
Subject: SL-14796 Updated code accordingly to changed event order

---
 indra/newview/llagent.cpp       | 30 +++++++++++-------------------
 indra/newview/llagent.h         |  4 ++--
 indra/newview/llchathistory.cpp |  1 +
 3 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f31135ad4c..3c50493d79 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -387,6 +387,7 @@ LLAgent::LLAgent() :
 	mTeleportFinishedSlot(),
 	mTeleportFailedSlot(),
 	mIsMaturityRatingChangingDuringTeleport(false),
+	mTPNeedsNeabyChatSeparator(false),
 	mMaturityRatingChange(0U),
 	mIsDoSendMaturityPreferenceToServer(false),
 	mMaturityPreferenceRequestId(0U),
@@ -519,10 +520,6 @@ void LLAgent::cleanup()
 	{
 		mTeleportFailedSlot.disconnect();
 	}
-    if (mParcelMgrConnection.connected())
-    {
-        mParcelMgrConnection.disconnect();
-    }
 }
 
 //-----------------------------------------------------------------------------
@@ -3938,10 +3935,7 @@ void LLAgent::clearTeleportRequest()
         LLVoiceClient::getInstance()->setHidden(FALSE);
     }
 	mTeleportRequest.reset();
-    if (mParcelMgrConnection.connected())
-    {
-        mParcelMgrConnection.disconnect();
-    }
+    mTPNeedsNeabyChatSeparator = false;
 }
 
 void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange)
@@ -3953,7 +3947,7 @@ void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange)
 void LLAgent::sheduleTeleportIM()
 {
     // is supposed to be called during teleport so we are still waiting for parcel
-    mParcelMgrConnection = addParcelChangedCallback(onParcelReadyAfterTeleport);
+    mTPNeedsNeabyChatSeparator = true;
 }
 
 bool LLAgent::hasPendingTeleportRequest()
@@ -4003,6 +3997,12 @@ void LLAgent::startTeleportRequest()
 void LLAgent::handleTeleportFinished()
 {
     LL_INFOS("Teleport") << "Agent handling teleport finished." << LL_ENDL;
+    if (mTPNeedsNeabyChatSeparator)
+    {
+        // parcel is ready at this point
+        addTPNearbyChatSeparator();
+        mTPNeedsNeabyChatSeparator = false;
+    }
 	clearTeleportRequest();
     mTeleportCanceled.reset();
 	if (mIsMaturityRatingChangingDuringTeleport)
@@ -4066,14 +4066,11 @@ void LLAgent::handleTeleportFailed()
 		mIsMaturityRatingChangingDuringTeleport = false;
 	}
 
-    if (mParcelMgrConnection.connected())
-    {
-        mParcelMgrConnection.disconnect();
-    }
+    mTPNeedsNeabyChatSeparator = false;
 }
 
 /*static*/
-void LLAgent::onParcelReadyAfterTeleport()
+void LLAgent::addTPNearbyChatSeparator()
 {
     LLViewerRegion* agent_region = gAgent.getRegion();
     LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
@@ -4106,11 +4103,6 @@ void LLAgent::onParcelReadyAfterTeleport()
         args["do_not_log"] = TRUE;
         nearby_chat->addMessage(chat, true, args);
     }
-
-    if (gAgent.mParcelMgrConnection.connected())
-    {
-        gAgent.mParcelMgrConnection.disconnect();
-    }
 }
 
 /*static*/
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 8f8c2f6007..a792d3e11f 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -668,9 +668,9 @@ private:
 	LLTeleportRequestPtr        mTeleportCanceled;
 	boost::signals2::connection mTeleportFinishedSlot;
 	boost::signals2::connection mTeleportFailedSlot;
-	boost::signals2::connection	mParcelMgrConnection;
 
 	bool            mIsMaturityRatingChangingDuringTeleport;
+	bool            mTPNeedsNeabyChatSeparator;
 	U8              mMaturityRatingChange;
 
 	bool            hasPendingTeleportRequest();
@@ -687,7 +687,7 @@ private:
 	void            handleTeleportFinished();
 	void            handleTeleportFailed();
 
-    static void     onParcelReadyAfterTeleport();
+    static void     addTPNearbyChatSeparator();
     static void     onCapabilitiesReceivedAfterTeleport();
 
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 2bb68dbbbe..c110e0d815 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -739,6 +739,7 @@ public:
 				break;
 			case CHAT_SOURCE_SYSTEM:
 				icon->setValue(LLSD("SL_Logo"));
+				break;
 			case CHAT_SOURCE_TELEPORT:
 				icon->setValue(LLSD("Command_Destinations_Icon"));
 				break;
-- 
cgit v1.2.3


From 99278b2f6259cd6e7b48dfbccb2528d428f83ec6 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 5 Feb 2021 11:15:06 +0200
Subject: SL-14797 Normalize right-click menus on Landmarks & Picks Part#1

---
 indra/newview/llpanellandmarks.cpp                 | 37 +++++++++++++
 indra/newview/llpanelplaces.cpp                    |  2 +-
 .../default/xui/en/menu_places_gear_folder.xml     |  3 ++
 .../default/xui/en/menu_places_gear_landmark.xml   | 62 +++++++++-------------
 4 files changed, 67 insertions(+), 37 deletions(-)

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index ccd8497484..578485c967 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -40,6 +40,7 @@
 #include "llagent.h"
 #include "llagentpicksinfo.h"
 #include "llagentui.h"
+#include "llavataractions.h"
 #include "llcallbacklist.h"
 #include "lldndbutton.h"
 #include "llfloatersidepanelcontainer.h"
@@ -1051,6 +1052,38 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 		}
 		return false;
 	}
+    else if ("add_landmark" == command_name)
+    {
+        bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1;
+        if (!is_single_selection)
+        {
+            return false;
+        }
+        LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem();
+        if (!view_model || view_model->getInventoryType() != LLInventoryType::IT_CATEGORY)
+        {
+            return false;
+        }
+        LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
+        if (landmark)
+        {
+            //already exists
+            return false;
+        }
+        return true;
+    }
+    else if ("share" == command_name)
+    {
+        if (!mCurrentSelectedList)
+        {
+            return false;
+        }
+        if (!LLAvatarActions::canShareSelectedItems(mCurrentSelectedList))
+        {
+            return false;
+        }
+        return true;
+    }
 	else
 	{
 		LL_WARNS() << "Unprocessed command has come: " << command_name << LL_ENDL;
@@ -1078,6 +1111,10 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
 	{
 		doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1));
 	}
+    else if ("share" == command_name && mCurrentSelectedList)
+    {
+        LLAvatarActions::shareWithAvatars(mCurrentSelectedList);
+    }
 	else if ("restore" == command_name && mCurrentSelectedList)
 	{
 		mCurrentSelectedList->doToSelected(userdata);
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 53870fb5c7..abec3ba733 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -388,7 +388,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
 			// Update the buttons at the bottom of the panel
 			updateVerbs();
 		}
-		else
+		else // "create_landmark"
 		{
 			mFilterEditor->clear();
 			onFilterEdit("", false);
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index 1aeb166e01..4d59ab0631 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -13,6 +13,9 @@
         <on_click
          function="Places.LandmarksGear.Add.Action"
          parameter="add_landmark" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="add_landmark" />
     </menu_item_call>
     <menu_item_call
      label="Add Folder"
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
index ff5fdd3795..b8249b621b 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -18,7 +18,18 @@
          parameter="teleport" />
     </menu_item_call>
     <menu_item_call
-     label="More Information"
+     label="Share"
+     layout="topleft"
+     name="share">
+        <on_click
+         function="Places.LandmarksGear.Custom.Action"
+         parameter="share" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="share" />
+    </menu_item_call>
+    <menu_item_call
+     label="View/Edit Landmark"
      layout="topleft"
      name="more_info">
         <on_click
@@ -39,26 +50,27 @@
          function="Places.LandmarksGear.Enable"
          parameter="show_on_map" />
     </menu_item_call>
-    <menu_item_separator
-     layout="topleft" />
     <menu_item_call
-     label="Add Landmark"
+     label="Copy SLurl"
      layout="topleft"
-     name="add_landmark">
+     name="copy_slurl">
         <on_click
-         function="Places.LandmarksGear.Add.Action"
-         parameter="add_landmark" />
-    </menu_item_call>
+         function="Places.LandmarksGear.CopyPaste.Action"
+         parameter="copy_slurl" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="copy_slurl" />
+    </menu_item_call> 
     <menu_item_call
-     label="Add Folder"
+     label="Create Pick"
      layout="topleft"
-     name="add_folder">
+     name="create_pick">
         <on_click
-         function="Places.LandmarksGear.Add.Action"
-         parameter="category" />
+         function="Places.LandmarksGear.Custom.Action"
+         parameter="create_pick" />
         <on_enable
          function="Places.LandmarksGear.Enable"
-         parameter="category" />
+         parameter="create_pick" />
     </menu_item_call>
     <menu_item_call
      label="Restore Item"
@@ -82,24 +94,13 @@
          parameter="cut" />
     </menu_item_call>
     <menu_item_call
-     label="Copy Landmark"
+     label="Copy"
      layout="topleft"
      name="copy_landmark">
         <on_click
          function="Places.LandmarksGear.CopyPaste.Action"
          parameter="copy" />
     </menu_item_call>
-    <menu_item_call
-     label="Copy SLurl"
-     layout="topleft"
-     name="copy_slurl">
-        <on_click
-         function="Places.LandmarksGear.CopyPaste.Action"
-         parameter="copy_slurl" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="copy_slurl" />
-    </menu_item_call>
     <menu_item_call
      label="Paste"
      layout="topleft"
@@ -171,15 +172,4 @@
          function="Places.LandmarksGear.Enable"
          parameter="sort_by_date" />
     </menu_item_check>
-    <menu_item_call
-     label="Create Pick"
-     layout="topleft"
-     name="create_pick">
-        <on_click
-         function="Places.LandmarksGear.Custom.Action"
-         parameter="create_pick" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="create_pick" />
-    </menu_item_call>
 </toggleable_menu>
-- 
cgit v1.2.3


From 74d3f9d017a424d69bfc256ecc1062fdaa3b18c3 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 5 Feb 2021 20:31:22 +0200
Subject: SL-14797 Normalize right-click menus on Landmarks & Picks Part#2

---
 indra/newview/llpanellandmarkinfo.cpp              | 14 +++++++++++-
 indra/newview/llpanellandmarkinfo.h                | 16 +++++++++----
 indra/newview/llpanellandmarks.cpp                 |  9 +++++++-
 indra/newview/llpanelplaces.cpp                    |  3 ++-
 indra/newview/skins/default/xui/en/menu_picks.xml  | 26 +++++++++++-----------
 .../default/xui/en/menu_places_gear_folder.xml     |  4 ++--
 6 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index 6751c25fb9..069fb32a56 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -106,6 +106,18 @@ void LLPanelLandmarkInfo::resetLocation()
 
 // virtual
 void LLPanelLandmarkInfo::setInfoType(EInfoType type)
+{
+    LLUUID dest_folder;
+    setInfoType(type, dest_folder);
+}
+
+// Sets CREATE_LANDMARK infotype and creates landmark at desired folder
+void LLPanelLandmarkInfo::setInfoAndCreateLandmark(const LLUUID& fodler_id)
+{
+    setInfoType(CREATE_LANDMARK, fodler_id);
+}
+
+void LLPanelLandmarkInfo::setInfoType(EInfoType type, const LLUUID &folder_id)
 {
 	LLPanel* landmark_info_panel = getChild<LLPanel>("landmark_info_panel");
 
@@ -183,7 +195,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
 			// remote parcel request to complete.
 			if (!LLLandmarkActions::landmarkAlreadyExists())
 			{
-				createLandmark(LLUUID());
+				createLandmark(folder_id);
 			}
 		}
 		break;
diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h
index 9712736182..9a2e0c8f59 100644
--- a/indra/newview/llpanellandmarkinfo.h
+++ b/indra/newview/llpanellandmarkinfo.h
@@ -43,8 +43,12 @@ public:
 
 	/*virtual*/ void resetLocation();
 
+    // If landmark doesn't exists, will create it at default folder
 	/*virtual*/ void setInfoType(EInfoType type);
 
+    // Sets CREATE_LANDMARK infotype and creates landmark at desired folder
+    void setInfoAndCreateLandmark(const LLUUID& fodler_id);
+
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 
 	// Displays landmark owner, creator and creation date info.
@@ -59,13 +63,17 @@ public:
 	// Select current landmark folder in combobox.
 	BOOL setLandmarkFolder(const LLUUID& id);
 
-	// Create a landmark for the current location
-	// in a folder specified by folder_id.
-	void createLandmark(const LLUUID& folder_id);
-
 	static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
 
 private:
+    // Create a landmark for the current location
+    // in a folder specified by folder_id.
+    // Expects title and description to be initialized
+    void createLandmark(const LLUUID& folder_id);
+
+    // If landmark doesn't exists, will create it at specified folder
+    void setInfoType(EInfoType type, const LLUUID &folder_id);
+
 	void populateFoldersList();
 
 	LLTextBox*			mOwner;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 578485c967..46c23961f4 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -785,7 +785,14 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 		}
 		else
 		{
-			LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
+            LLSD args;
+            args["type"] = "create_landmark";
+            if (view_model->getInventoryType()
+                == LLInventoryType::IT_CATEGORY)
+            {
+                args["dest_folder"] = view_model->getUUID();
+            }
+			LLFloaterSidePanelContainer::showPanel("places", args);
 		}
 	} 
 	else if ("category" == command_name)
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index abec3ba733..c038207628 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -409,7 +409,8 @@ void LLPanelPlaces::onOpen(const LLSD& key)
 			}
 			else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
 			{
-				mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
+				LLUUID dest_folder = key["dest_folder"];
+				mLandmarkInfo->setInfoAndCreateLandmark(dest_folder);
 
 				if (key.has("x") && key.has("y") && key.has("z"))
 				{
diff --git a/indra/newview/skins/default/xui/en/menu_picks.xml b/indra/newview/skins/default/xui/en/menu_picks.xml
index ebb49c9004..a408e6136c 100644
--- a/indra/newview/skins/default/xui/en/menu_picks.xml
+++ b/indra/newview/skins/default/xui/en/menu_picks.xml
@@ -3,7 +3,17 @@
  layout="topleft"
  name="Picks">
     <menu_item_call
-     label="Info"
+     label="Teleport"
+     layout="topleft"
+     name="pick_teleport">
+        <menu_item_call.on_click
+         function="Pick.Teleport" />
+        <menu_item_call.on_enable
+         function="Pick.Enable" 
+         parameter="teleport" />
+    </menu_item_call>
+    <menu_item_call
+     label="View Pick"
      layout="topleft"
      name="pick_info">
         <menu_item_call.on_click
@@ -13,7 +23,7 @@
          parameter="info" />
     </menu_item_call>
     <menu_item_call
-     label="Edit"
+     label="Edit Pick"
      layout="topleft"
      name="pick_edit"
      visible="false">
@@ -24,17 +34,7 @@
          parameter="edit" />
     </menu_item_call>
     <menu_item_call
-     label="Teleport"
-     layout="topleft"
-     name="pick_teleport">
-        <menu_item_call.on_click
-         function="Pick.Teleport" />
-        <menu_item_call.on_enable
-         function="Pick.Enable" 
-         parameter="teleport" />
-    </menu_item_call>
-    <menu_item_call
-     label="Map"
+     label="Show on map"
      layout="topleft"
      name="pick_map">
         <menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index 4d59ab0631..eb76f58722 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -7,7 +7,7 @@
  name="menu_folder_gear"
  visible="false">
     <menu_item_call
-     label="Add Landmark"
+     label="Landmark current location"
      layout="topleft"
      name="add_landmark">
         <on_click
@@ -18,7 +18,7 @@
          parameter="add_landmark" />
     </menu_item_call>
     <menu_item_call
-     label="Add Folder"
+     label="Create subfolder"
      layout="topleft"
      name="add_folder">
         <on_click
-- 
cgit v1.2.3


From d12514af8193888f9eb66bb92a9c2ac3d4e0e56e Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 9 Feb 2021 01:59:15 +0200
Subject: SL-14797 Normalize right-click menus on Landmarks & Picks Part#3

---
 indra/llinventory/llparcel.h                       |  6 ----
 indra/llinventory/llparcelflags.h                  |  2 +-
 indra/newview/lllandmarkactions.cpp                | 22 -------------
 indra/newview/lllandmarkactions.h                  |  6 ----
 indra/newview/llpanelteleporthistory.cpp           | 38 ++++++++++++----------
 indra/newview/llpanelteleporthistory.h             |  4 +--
 indra/newview/llteleporthistorystorage.cpp         | 22 +++++++++++++
 indra/newview/llteleporthistorystorage.h           |  7 ++++
 .../default/xui/en/menu_teleport_history_item.xml  | 19 ++++++++---
 9 files changed, 67 insertions(+), 59 deletions(-)

diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 3b39aeb56b..5d08c1f4c6 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -295,7 +295,6 @@ public:
 	void	setAllowTerraform(BOOL b){setParcelFlag(PF_ALLOW_TERRAFORM, b); }
 	void	setAllowDamage(BOOL b)	{ setParcelFlag(PF_ALLOW_DAMAGE, b); }
 	void	setAllowFly(BOOL b)		{ setParcelFlag(PF_ALLOW_FLY, b); }
-	void	setAllowLandmark(BOOL b){ setParcelFlag(PF_ALLOW_LANDMARK, b); }
 	void	setAllowGroupScripts(BOOL b)	{ setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, b); }
 	void	setAllowOtherScripts(BOOL b)	{ setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, b); }
 	void	setAllowDeedToGroup(BOOL b) { setParcelFlag(PF_ALLOW_DEED_TO_GROUP, b); }
@@ -476,11 +475,6 @@ public:
 	BOOL	getAllowFly() const
 					{ return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; }
 
-	// Remove permission restrictions for creating landmarks.
-	// We should eventually remove this flag completely.
-	BOOL	getAllowLandmark() const
-					{ return TRUE; }
-
 	BOOL	getAllowGroupScripts() const
 					{ return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; }
 
diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h
index 25b27a281a..4cffa83cc1 100644
--- a/indra/llinventory/llparcelflags.h
+++ b/indra/llinventory/llparcelflags.h
@@ -33,7 +33,7 @@ const U32 PF_ALLOW_FLY			= 1 << 0;// Can start flying
 const U32 PF_ALLOW_OTHER_SCRIPTS= 1 << 1;// Scripts by others can run.
 const U32 PF_FOR_SALE			= 1 << 2;// Can buy this land
 const U32 PF_FOR_SALE_OBJECTS	= 1 << 7;// Can buy all objects on this land
-const U32 PF_ALLOW_LANDMARK		= 1 << 3;
+const U32 PF_ALLOW_LANDMARK		= 1 << 3;// Always true/deprecated
 const U32 PF_ALLOW_TERRAFORM	= 1 << 4;
 const U32 PF_ALLOW_DAMAGE		= 1 << 5;
 const U32 PF_CREATE_OBJECTS		= 1 << 6;
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index c243f8b4f0..a17dc674ac 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -228,23 +228,6 @@ LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos()
 	return findLandmarkForGlobalPos(gAgent.getPositionGlobal());
 }
 
-bool LLLandmarkActions::canCreateLandmarkHere()
-{
-	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if(!agent_parcel)
-	{
-		LL_WARNS() << "No agent region" << LL_ENDL;
-		return false;
-	}
-	if (agent_parcel->getAllowLandmark()
-		|| LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK))
-	{
-		return true;
-	}
-
-	return false;
-}
-
 void LLLandmarkActions::createLandmarkHere(
 	const std::string& name, 
 	const std::string& desc, 
@@ -261,11 +244,6 @@ void LLLandmarkActions::createLandmarkHere(
 		LL_WARNS() << "No agent parcel" << LL_ENDL;
 		return;
 	}
-	if (!canCreateLandmarkHere())
-	{
-		LLNotificationsUtil::add("CannotCreateLandmarkNotOwner");
-		return;
-	}
 
 	create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
 		folder_id, LLTransactionID::tnull,
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
index 870d92811e..ae7b072fcb 100644
--- a/indra/newview/lllandmarkactions.h
+++ b/indra/newview/lllandmarkactions.h
@@ -72,12 +72,6 @@ public:
 	 */
 	static LLViewerInventoryItem* findLandmarkForAgentPos();
 
-
-	/**
-	 * @brief Checks whether agent has rights to create landmark for current parcel.
-	 */
-	static bool canCreateLandmarkHere();
-
 	/**
 	 * @brief Creates landmark for current parcel.
 	 */
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index fe0608d544..3f5664f431 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -396,9 +396,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
 	// (N.B. callbacks don't take const refs as mID is local scope)
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 
-	registrar.add("TeleportHistory.Teleport",	boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this));
-	registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this));
-	registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
+	registrar.add("TeleportHistory.Action", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onUserAction, this, _2));
 
 	// create the context menu from the XUI
 	llassert(LLMenuGL::sMenuContainer != NULL);
@@ -406,14 +404,27 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
 		"menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 }
 
-void LLTeleportHistoryPanel::ContextMenu::onTeleport()
+void LLTeleportHistoryPanel::ContextMenu::onUserAction(const LLSD& userdata)
 {
-	confirmTeleport(mIndex);
-}
-
-void LLTeleportHistoryPanel::ContextMenu::onInfo()
-{
-	LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
+    std::string command_name = userdata.asString();
+    if ("teleport" == command_name)
+    {
+        confirmTeleport(mIndex);
+    }
+    else if ("view" == command_name)
+    {
+        LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
+    }
+    else if ("show_on_map" == command_name)
+    {
+        LLTeleportHistoryStorage::getInstance()->showItemOnMap(mIndex);
+    }
+    else if ("copy_slurl" == command_name)
+    {
+        LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
+        LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
+            boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
+    }
 }
 
 //static
@@ -427,13 +438,6 @@ void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& sl
 	LLNotificationsUtil::add("CopySLURL", args);
 }
 
-void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard()
-{
-	LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
-	LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
-		boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
-}
-
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
 
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index b88861c5c6..e0abbc47db 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -52,9 +52,7 @@ public:
 
 	private:
 		LLContextMenu* createMenu();
-		void onTeleport();
-		void onInfo();
-		void onCopyToClipboard();
+		void onUserAction(const LLSD& userdata);
 
 		static void gotSLURLCallback(const std::string& slurl);
 
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index 8a5704939a..93fa457bd0 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -33,6 +33,8 @@
 #include "lldir.h"
 #include "llteleporthistory.h"
 #include "llagent.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
 
 // Max offset for two global positions to consider them as equal
 const F64 MAX_GLOBAL_POS_OFFSET = 5.0f;
@@ -253,3 +255,23 @@ void LLTeleportHistoryStorage::goToItem(S32 idx)
 	gAgent.teleportViaLocation(mItems[idx].mGlobalPos);
 }
 
+void LLTeleportHistoryStorage::showItemOnMap(S32 idx)
+{
+    // Validate specified index.
+    if (idx < 0 || idx >= (S32)mItems.size())
+    {
+        LL_WARNS() << "Invalid teleport history index (" << idx << ") specified" << LL_ENDL;
+        dump();
+        return;
+    }
+
+    LLVector3d landmark_global_pos = mItems[idx].mGlobalPos;
+
+    LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+    if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
+    {
+        worldmap_instance->trackLocation(landmark_global_pos);
+        LLFloaterReg::showInstance("world_map", "center");
+    }
+}
+
diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h
index 946ac0af1a..3578923fd7 100644
--- a/indra/newview/llteleporthistorystorage.h
+++ b/indra/newview/llteleporthistorystorage.h
@@ -107,6 +107,13 @@ public:
 	 */
 	void					goToItem(S32 idx);
 
+    /**
+     * Show specific item on map.
+     *
+     * The item is specified by its index (starting from 0).
+     */
+    void					showItemOnMap(S32 idx);
+
 private:
 
 	void load();
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index f939c3996d..52da591e35 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -7,20 +7,31 @@
      layout="topleft"
      name="Teleport">
         <menu_item_call.on_click
-         function="TeleportHistory.Teleport" />
+         function="TeleportHistory.Action"
+         parameter="teleport" />
     </menu_item_call>
     <menu_item_call
-     label="More Information"
+     label="View"
      layout="topleft"
      name="More Information">
         <menu_item_call.on_click
-         function="TeleportHistory.MoreInformation" />
+         function="TeleportHistory.Action"
+         parameter="view" />
+    </menu_item_call>
+    <menu_item_call
+     label="Show on map"
+     layout="topleft"
+     name="show_on_map">
+        <menu_item_call.on_click
+         function="TeleportHistory.Action"
+         parameter="show_on_map" />
     </menu_item_call>
     <menu_item_call
      label="Copy SLurl"
      layout="topleft"
      name="CopyToClipboard">
         <menu_item_call.on_click
-         function="TeleportHistory.CopyToClipboard" />
+         function="TeleportHistory.Action"
+         parameter="copy_slurl" />
     </menu_item_call>
 </context_menu>
-- 
cgit v1.2.3


From b23feb2c623df8a58a52afb5fd4e5806a630d3d4 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 9 Feb 2021 23:00:44 +0200
Subject: SL-14797 Do not allow creation of landmarks nor folders in library

---
 indra/newview/llpanellandmarks.cpp | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 46c23961f4..6e8eac19fc 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -1044,8 +1044,12 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 			// ... but except Received folder
 			return !isReceivedFolderSelected();
 		}
+		if (mCurrentSelectedList == mLibraryInventoryPanel)
+		{
+			return false;
+		}
 		//"Add a folder" is enabled by default (case when My Landmarks is empty)
-		else return true;
+		return true;
 	}
 	else if("create_pick" == command_name)
 	{
@@ -1066,6 +1070,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
         {
             return false;
         }
+        if (mCurrentSelectedList == mLibraryInventoryPanel)
+        {
+            return false;
+        }
         LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem();
         if (!view_model || view_model->getInventoryType() != LLInventoryType::IT_CATEGORY)
         {
-- 
cgit v1.2.3


From 48597039b24ffbc976572d24bfc0835922bce43b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Feb 2021 15:29:20 +0000
Subject: SL-14862 - LLViewerStats logs which UI features get used

---
 indra/llui/CMakeLists.txt       |  2 ++
 indra/llui/llfloaterreg.cpp     |  8 ++++++
 indra/llui/lluictrl.cpp         | 21 +++++++++++++-
 indra/llui/lluictrl.h           |  4 +++
 indra/llui/lluiusage.cpp        | 61 +++++++++++++++++++++++++++++++++++++++++
 indra/llui/lluiusage.h          | 49 +++++++++++++++++++++++++++++++++
 indra/newview/llviewerstats.cpp |  3 ++
 7 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 indra/llui/lluiusage.cpp
 create mode 100644 indra/llui/lluiusage.h

diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index cce618487b..f781ff4110 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -122,6 +122,7 @@ set(llui_SOURCE_FILES
     lluictrl.cpp
     lluictrlfactory.cpp
     lluistring.cpp
+    lluiusage.cpp
     llundo.cpp
     llurlaction.cpp
     llurlentry.cpp
@@ -241,6 +242,7 @@ set(llui_HEADER_FILES
     llui.h
     lluicolor.h
     lluistring.h
+    lluiusage.h
     llundo.h
     llurlaction.h
     llurlentry.h
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 85e07fc6a6..6307bf1028 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -32,6 +32,7 @@
 #include "llfloater.h"
 #include "llmultifloater.h"
 #include "llfloaterreglistener.h"
+#include "lluiusage.h"
 
 //*******************************************************
 
@@ -243,6 +244,8 @@ LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::str
 //static
 LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) 
 {
+	LL_DEBUGS("UIUsage") << "floater showInstance " << name << LL_ENDL;
+	LLUIUsage::instance().logFloater(name);
 	if( sBlockShowFloaters
 			// see EXT-7090
 			&& sAlwaysShowableList.find(name) == sAlwaysShowableList.end())
@@ -273,6 +276,9 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
 // returns true if the instance is visible when completed
 bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
 {
+	LL_DEBUGS("UIUsage") << "floater toggleInstance " << name << LL_ENDL;
+	LLUIUsage::instance().logFloater(name);
+
 	LLFloater* instance = findInstance(name, key); 
 	if (LLFloater::isShown(instance))
 	{
@@ -473,6 +479,8 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
 	LLFloater* instance = getInstance(name, key); 
 	
 
+	LL_DEBUGS("UIUsage") << "floater toggleInstanceOrBringToFront " << name << LL_ENDL;
+	LLUIUsage::instance().logFloater(name);
 	if (!instance)
 	{
 		LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL;
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 544a76e8d5..0e1c8439ea 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -35,6 +35,7 @@
 #include "lluictrlfactory.h"
 #include "lltabcontainer.h"
 #include "llaccordionctrltab.h"
+#include "lluiusage.h"
 
 static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
 
@@ -282,6 +283,7 @@ LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCa
 	else
 	{
 		std::string function_name = cb.function_name;
+		setFunctionName(function_name);
 		commit_callback_t* func = (CommitCallbackRegistry::getValue(function_name));
 		if (func)
 		{
@@ -422,7 +424,18 @@ BOOL LLUICtrl::canFocusChildren() const
 void LLUICtrl::onCommit()
 {
 	if (mCommitSignal)
-	(*mCommitSignal)(this, getValue());
+	{
+		if (!mFunctionName.empty())
+		{
+			LL_DEBUGS("UIUsage") << "calling commit function " << mFunctionName << LL_ENDL;
+			LLUIUsage::instance().logCommand(mFunctionName);
+		}
+		else
+		{
+			//LL_DEBUGS("UIUsage") << "calling commit function " << "UNKNOWN" << LL_ENDL;
+		}
+		(*mCommitSignal)(this, getValue());
+	}
 }
 
 //virtual
@@ -597,6 +610,12 @@ void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control)
 		setVisible(!(mMakeInvisibleControlVariable->getValue().asBoolean()));
 	}
 }
+
+void LLUICtrl::setFunctionName(const std::string& function_name)
+{
+	mFunctionName = function_name;
+}
+
 // static
 bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type)
 {
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 7360bd7659..67dd24341c 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -183,6 +183,8 @@ public:
 	void setMakeVisibleControlVariable(LLControlVariable* control);
 	void setMakeInvisibleControlVariable(LLControlVariable* control);
 
+	void setFunctionName(const std::string& function_name);
+	
 	virtual void	setTentative(BOOL b);
 	virtual BOOL	getTentative() const;
 	virtual void	setValue(const LLSD& value);
@@ -310,6 +312,8 @@ protected:
 	LLControlVariable* mMakeInvisibleControlVariable;
 	boost::signals2::connection mMakeInvisibleControlConnection;
 
+	std::string mFunctionName;
+
 	static F32 sActiveControlTransparency;
 	static F32 sInactiveControlTransparency;
 	
diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
new file mode 100644
index 0000000000..e1237031cd
--- /dev/null
+++ b/indra/llui/lluiusage.cpp
@@ -0,0 +1,61 @@
+/**
+* @file lluiuisage.cpp
+* @brief Source file for LLUIUsage
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, 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 "linden_common.h"
+#include "lluiusage.h"
+
+LLUIUsage::LLUIUsage()
+{
+}
+
+LLUIUsage::~LLUIUsage()
+{
+}
+
+void LLUIUsage::logFloater(const std::string& floater)
+{
+	mFloaterCounts[floater]++;
+}
+
+void LLUIUsage::logCommand(const std::string& command)
+{
+	mCommandCounts[command]++;
+}
+
+LLSD LLUIUsage::asLLSD() const
+{
+	LLSD result;
+	for (auto const& it : mFloaterCounts)
+	{
+		result["floaters"][it.first] = LLSD::Integer(it.second);
+	}
+	for (auto const& it : mCommandCounts)
+	{
+		result["commands"][it.first] = LLSD::Integer(it.second);
+	}
+	return result;
+}
+
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
new file mode 100644
index 0000000000..0c076c2b2c
--- /dev/null
+++ b/indra/llui/lluiusage.h
@@ -0,0 +1,49 @@
+/**
+* @file lluiuisage.h
+* @brief Header file for LLUIUsage
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, 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_LLUIUSAGE_H
+#define LL_LLUIUSAGE_H
+
+#include <map>
+#include "llsd.h"
+#include "llsingleton.h"
+
+// UIUsage tracking to see which operations and UI elements are most popular in a session
+class LLUIUsage : public LLSingleton<LLUIUsage>
+{
+public:
+	LLSINGLETON(LLUIUsage);
+	~LLUIUsage();
+public:
+	void logFloater(const std::string& floater);
+	void logCommand(const std::string& command);
+	LLSD asLLSD() const;
+private:
+	std::map<std::string,U32> mFloaterCounts;
+	std::map<std::string,U32> mCommandCounts;
+};
+
+#endif // LLUIUIUSAGE.h
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 05f88b0a75..314c1a1f1e 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -63,6 +63,7 @@
 #include "llsdutil.h"
 #include "llcorehttputil.h"
 #include "llvoicevivox.h"
+#include "lluiusage.h"
 
 namespace LLStatViewer
 {
@@ -577,6 +578,8 @@ void send_viewer_stats(bool include_preferences)
 	fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets;
 	fail["missing_updater"] = (S32) LLAppViewer::instance()->isUpdaterMissing();
 
+	body["ui"] = LLUIUsage::instance().asLLSD();
+		
 	body["stats"]["voice"] = LLVoiceVivoxStats::getInstance()->read();
 
 	// Misc stats, two strings and two ints
-- 
cgit v1.2.3


From 8a718a9ca28a7a544c7622a033fcd2791935909d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Feb 2021 16:05:46 +0000
Subject: SL-14862 - line endings fix, avoid period in key names

---
 indra/llui/lluiusage.cpp | 131 +++++++++++++++++++++++++----------------------
 indra/llui/lluiusage.h   |  99 +++++++++++++++++------------------
 2 files changed, 120 insertions(+), 110 deletions(-)

diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
index e1237031cd..50eeccd214 100644
--- a/indra/llui/lluiusage.cpp
+++ b/indra/llui/lluiusage.cpp
@@ -1,61 +1,70 @@
-/**
-* @file lluiuisage.cpp
-* @brief Source file for LLUIUsage
-*
-* $LicenseInfo:firstyear=2021&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2021, 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 "linden_common.h"
-#include "lluiusage.h"
-
-LLUIUsage::LLUIUsage()
-{
-}
-
-LLUIUsage::~LLUIUsage()
-{
-}
-
-void LLUIUsage::logFloater(const std::string& floater)
-{
-	mFloaterCounts[floater]++;
-}
-
-void LLUIUsage::logCommand(const std::string& command)
-{
-	mCommandCounts[command]++;
-}
-
-LLSD LLUIUsage::asLLSD() const
-{
-	LLSD result;
-	for (auto const& it : mFloaterCounts)
-	{
-		result["floaters"][it.first] = LLSD::Integer(it.second);
-	}
-	for (auto const& it : mCommandCounts)
-	{
-		result["commands"][it.first] = LLSD::Integer(it.second);
-	}
-	return result;
-}
-
+/**
+* @file lluiuisage.cpp
+* @brief Source file for LLUIUsage
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, 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 "linden_common.h"
+#include "lluiusage.h"
+
+LLUIUsage::LLUIUsage()
+{
+}
+
+LLUIUsage::~LLUIUsage()
+{
+}
+
+// static
+std::string LLUIUsage::sanitized(const std::string& s)
+{
+	// ViewerStats db doesn't like "." in keys
+	std::string result(s);
+	std::replace(result.begin(), result.end(), '.', '_');
+	return result;
+}
+
+void LLUIUsage::logFloater(const std::string& floater)
+{
+	mFloaterCounts[sanitized(floater)]++;
+}
+
+void LLUIUsage::logCommand(const std::string& command)
+{
+	mCommandCounts[sanitized(command)]++;
+}
+
+LLSD LLUIUsage::asLLSD() const
+{
+	LLSD result;
+	for (auto const& it : mFloaterCounts)
+	{
+		result["floaters"][it.first] = LLSD::Integer(it.second);
+	}
+	for (auto const& it : mCommandCounts)
+	{
+		result["commands"][it.first] = LLSD::Integer(it.second);
+	}
+	return result;
+}
+
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
index 0c076c2b2c..bac607aa60 100644
--- a/indra/llui/lluiusage.h
+++ b/indra/llui/lluiusage.h
@@ -1,49 +1,50 @@
-/**
-* @file lluiuisage.h
-* @brief Header file for LLUIUsage
-*
-* $LicenseInfo:firstyear=2021&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2021, 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_LLUIUSAGE_H
-#define LL_LLUIUSAGE_H
-
-#include <map>
-#include "llsd.h"
-#include "llsingleton.h"
-
-// UIUsage tracking to see which operations and UI elements are most popular in a session
-class LLUIUsage : public LLSingleton<LLUIUsage>
-{
-public:
-	LLSINGLETON(LLUIUsage);
-	~LLUIUsage();
-public:
-	void logFloater(const std::string& floater);
-	void logCommand(const std::string& command);
-	LLSD asLLSD() const;
-private:
-	std::map<std::string,U32> mFloaterCounts;
-	std::map<std::string,U32> mCommandCounts;
-};
-
-#endif // LLUIUIUSAGE.h
+/**
+* @file lluiuisage.h
+* @brief Header file for LLUIUsage
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, 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_LLUIUSAGE_H
+#define LL_LLUIUSAGE_H
+
+#include <map>
+#include "llsd.h"
+#include "llsingleton.h"
+
+// UIUsage tracking to see which operations and UI elements are most popular in a session
+class LLUIUsage : public LLSingleton<LLUIUsage>
+{
+public:
+	LLSINGLETON(LLUIUsage);
+	~LLUIUsage();
+public:
+	static std::string sanitized(const std::string& s);
+	void logFloater(const std::string& floater);
+	void logCommand(const std::string& command);
+	LLSD asLLSD() const;
+private:
+	std::map<std::string,U32> mFloaterCounts;
+	std::map<std::string,U32> mCommandCounts;
+};
+
+#endif // LLUIUIUSAGE.h
-- 
cgit v1.2.3


From 5971c647e4abd11c4c4f055f124ac2251b720c25 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 15 Feb 2021 16:49:08 +0200
Subject: SL-14632 FIXED The viewer is crashed after purging the trash with
 favorites folder

---
 indra/newview/llviewerinventory.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index ed1d726528..2b200c17c1 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1466,6 +1466,12 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id);
 	if (cat.notNull())
 	{
+		const LLUUID fav_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+		if ((id == fav_id) || gInventory.isObjectDescendentOf(fav_id, id))
+		{
+			gSavedPerAccountSettings.setString("FavoritesFolder", "");
+		}
+
 		if (LLClipboard::instance().hasContents())
 		{
 			// Remove items from clipboard or it will remain active even if there is nothing to paste/copy
-- 
cgit v1.2.3


From 58827cb2752b9a184d638ed6a4f0efa0e9740d64 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Sat, 13 Feb 2021 01:50:04 +0200
Subject: SL-14725 Rotation sliders for sun and moon panels

---
 indra/llui/llvirtualtrackball.cpp                  |  46 ++++++
 indra/llui/llvirtualtrackball.h                    |   3 +
 indra/newview/llpaneleditsky.cpp                   | 119 +++++++++++++--
 indra/newview/llpaneleditsky.h                     |   2 +
 .../default/xui/en/floater_fixedenvironment.xml    |   2 +-
 .../skins/default/xui/en/menu_favorites.xml        |  12 +-
 .../default/xui/en/panel_settings_sky_sunmoon.xml  | 162 ++++++++++++++++-----
 7 files changed, 294 insertions(+), 52 deletions(-)

diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp
index 723643dd25..15847a7282 100644
--- a/indra/llui/llvirtualtrackball.cpp
+++ b/indra/llui/llvirtualtrackball.cpp
@@ -348,6 +348,52 @@ LLQuaternion LLVirtualTrackball::getRotation() const
 	return mValue;
 }
 
+// static
+void LLVirtualTrackball::getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation)
+{
+    // LLQuaternion has own function to get azimuth, but it doesn't appear to return correct values (meant for 2d?)
+    const LLVector3 VectorZero(10000.0f, 0.0f, 0.0f);
+    LLVector3 point = VectorZero * quat;
+
+    if (!is_approx_zero(point.mV[VX]) || !is_approx_zero(point.mV[VY]))
+    {
+        azimuth = atan2f(point.mV[VX], point.mV[VY]);
+    }
+    else
+    {
+        azimuth = 0;
+    }
+
+    azimuth -= F_PI_BY_TWO;
+
+    if (azimuth < 0)
+    {
+        azimuth += F_PI * 2;
+    }
+
+    if (abs(point.mV[VY]) > abs(point.mV[VX]) && !is_approx_zero(point.mV[VY])) // to avoid precision drop
+    {
+        elevation = atanl((F64)point.mV[VZ] / (F64)abs(point.mV[VY]));
+    }
+    else if (!is_approx_zero(point.mV[VX]))
+    {
+        elevation = atanl((F64)point.mV[VZ] / (F64)abs(point.mV[VX]));
+    }
+    else
+    {
+        // both VX and VY are near zero, VZ should be high
+        elevation = point.mV[VZ] > 0 ? F_PI_BY_TWO : -F_PI_BY_TWO;
+    }
+}
+
+// static
+void LLVirtualTrackball::getAzimuthAndElevationDeg(const LLQuaternion &quat, F32 &azimuth, F32 &elevation)
+{
+    getAzimuthAndElevation(quat, azimuth, elevation);
+    azimuth *= RAD_TO_DEG;
+    elevation *= RAD_TO_DEG;
+}
+
 BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask)
 {
     if (hasMouseCapture())
diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h
index 2d4b1ece17..c7a893877b 100644
--- a/indra/llui/llvirtualtrackball.h
+++ b/indra/llui/llvirtualtrackball.h
@@ -96,6 +96,9 @@ public:
     void            setRotation(const LLQuaternion &value);
     LLQuaternion    getRotation() const;
 
+    static void             getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation);
+    static void             getAzimuthAndElevationDeg(const LLQuaternion &quat, F32 &azimuth, F32 &elevation);
+
 protected:
     friend class LLUICtrlFactory;
     LLVirtualTrackball(const Params&);
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index 2e26b69144..06e406e2ab 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -69,11 +69,15 @@ namespace
     const std::string   FIELD_SKY_GLOW_SIZE("glow_size");
     const std::string   FIELD_SKY_STAR_BRIGHTNESS("star_brightness");
     const std::string   FIELD_SKY_SUN_ROTATION("sun_rotation");
+    const std::string   FIELD_SKY_SUN_AZIMUTH("sun_azimuth");
+    const std::string   FIELD_SKY_SUN_ELEVATION("sun_elevation");
     const std::string   FIELD_SKY_SUN_IMAGE("sun_image");
     const std::string   FIELD_SKY_SUN_SCALE("sun_scale");
     const std::string   FIELD_SKY_SUN_BEACON("sunbeacon");
     const std::string   FIELD_SKY_MOON_BEACON("moonbeacon");
     const std::string   FIELD_SKY_MOON_ROTATION("moon_rotation");
+    const std::string   FIELD_SKY_MOON_AZIMUTH("moon_azimuth");
+    const std::string   FIELD_SKY_MOON_ELEVATION("moon_elevation");
     const std::string   FIELD_SKY_MOON_IMAGE("moon_image");
     const std::string   FIELD_SKY_MOON_SCALE("moon_scale");
     const std::string   FIELD_SKY_MOON_BRIGHTNESS("moon_brightness");
@@ -473,12 +477,16 @@ BOOL LLPanelSettingsSkySunMoonTab::postBuild()
     getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onStarBrightnessChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_SUN_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_SUN_IMAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunImageChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunScaleChanged(); });
     getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setBlankImageAssetID(LLSettingsSky::GetBlankSunTextureId());
     getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setDefaultImageAssetID(LLSettingsSky::GetBlankSunTextureId());
     getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setAllowNoTexture(TRUE);
     getChild<LLUICtrl>(FIELD_SKY_MOON_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_MOON_IMAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonImageChanged(); });
     getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setDefaultImageAssetID(LLSettingsSky::GetDefaultMoonTextureId());
     getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setBlankImageAssetID(LLSettingsSky::GetDefaultMoonTextureId());
@@ -537,13 +545,29 @@ void LLPanelSettingsSkySunMoonTab::refresh()
     getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B);
 
     getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mSkySettings->getStarBrightness());
-    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(mSkySettings->getSunRotation());
     getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setValue(mSkySettings->getSunTextureId());
     getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setValue(mSkySettings->getSunScale());
-    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(mSkySettings->getMoonRotation());
     getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setValue(mSkySettings->getMoonTextureId());
     getChild<LLUICtrl>(FIELD_SKY_MOON_SCALE)->setValue(mSkySettings->getMoonScale());
     getChild<LLUICtrl>(FIELD_SKY_MOON_BRIGHTNESS)->setValue(mSkySettings->getMoonBrightness());
+
+    // Sun rotation values
+    F32 azimuth, elevation;
+    LLQuaternion quat = mSkySettings->getSunRotation();
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(quat);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->setValue(elevation);
+
+    // Moon rotation values
+    quat = mSkySettings->getMoonRotation();
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(quat);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setValue(elevation);
+
 }
 
 //-------------------------------------------------------------------------
@@ -583,10 +607,47 @@ void LLPanelSettingsSkySunMoonTab::onStarBrightnessChanged()
 
 void LLPanelSettingsSkySunMoonTab::onSunRotationChanged()
 {
-    if (!mSkySettings) return;
-    mSkySettings->setSunRotation(getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation());
-    mSkySettings->update();
-    setIsDirty();
+    LLQuaternion quat = getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation();
+
+    F32 azimuth, elevation;
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->setValue(elevation);
+    if (mSkySettings)
+    {
+        mSkySettings->setSunRotation(quat);
+        mSkySettings->update();
+        setIsDirty();
+    }
+}
+
+void LLPanelSettingsSkySunMoonTab::onSunAzimElevChanged()
+{
+    F32 azimuth = getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->getValue().asReal();
+    F32 elevation = getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->getValue().asReal();
+    LLQuaternion quat = mSkySettings->getSunRotation();
+
+    azimuth *= DEG_TO_RAD;
+    elevation *= DEG_TO_RAD;
+
+    if (is_approx_zero(elevation))
+    {
+        elevation = F_APPROXIMATELY_ZERO;
+    }
+
+    quat.setAngleAxis(-elevation, 0, 1, 0);
+    LLQuaternion az_quat;
+    az_quat.setAngleAxis(F_TWO_PI - azimuth, 0, 0, 1);
+    quat *= az_quat;
+
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(quat);
+
+    if (mSkySettings)
+    {
+        mSkySettings->setSunRotation(quat);
+        mSkySettings->update();
+        setIsDirty();
+    }
 }
 
 void LLPanelSettingsSkySunMoonTab::onSunScaleChanged()
@@ -607,10 +668,48 @@ void LLPanelSettingsSkySunMoonTab::onSunImageChanged()
 
 void LLPanelSettingsSkySunMoonTab::onMoonRotationChanged()
 {
-    if (!mSkySettings) return;
-    mSkySettings->setMoonRotation(getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation());
-    mSkySettings->update();
-    setIsDirty();
+    LLQuaternion quat = getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation();
+
+    F32 azimuth, elevation;
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setValue(elevation);
+
+    if (mSkySettings)
+    {
+        mSkySettings->setMoonRotation(quat);
+        mSkySettings->update();
+        setIsDirty();
+    }
+}
+
+void LLPanelSettingsSkySunMoonTab::onMoonAzimElevChanged()
+{
+    F32 azimuth = getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->getValue().asReal();
+    F32 elevation = getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->getValue().asReal();
+    LLQuaternion quat = mSkySettings->getMoonRotation();
+
+    azimuth *= DEG_TO_RAD;
+    elevation *= DEG_TO_RAD;
+
+    if (is_approx_zero(elevation))
+    {
+        elevation = F_APPROXIMATELY_ZERO;
+    }
+
+    quat.setAngleAxis(-elevation, 0, 1, 0);
+    LLQuaternion az_quat;
+    az_quat.setAngleAxis(F_TWO_PI- azimuth, 0, 0, 1);
+    quat *= az_quat;
+
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(quat);
+
+    if (mSkySettings)
+    {
+        mSkySettings->setMoonRotation(quat);
+        mSkySettings->update();
+        setIsDirty();
+    }
 }
 
 void LLPanelSettingsSkySunMoonTab::onMoonImageChanged()
diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h
index c02c9c95a0..d1c558c902 100644
--- a/indra/newview/llpaneleditsky.h
+++ b/indra/newview/llpaneleditsky.h
@@ -124,9 +124,11 @@ private:
     void                    onGlowChanged();
     void                    onStarBrightnessChanged();
     void                    onSunRotationChanged();
+    void                    onSunAzimElevChanged();
     void                    onSunScaleChanged();
     void                    onSunImageChanged();
     void                    onMoonRotationChanged();
+    void                    onMoonAzimElevChanged();
     void                    onMoonScaleChanged();
     void                    onMoonBrightnessChanged();
     void                    onMoonImageChanged();
diff --git a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
index dbf91b0834..2cc73361f5 100644
--- a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
+++ b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
@@ -89,7 +89,7 @@
                 follows="left|top|right|bottom"
                 auto_resize="false"
                 user_resize="false"
-                height="40"
+                height="35"
                 visible="true">
             <layout_stack
                     follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml
index be380e11e5..082f2f9670 100644
--- a/indra/newview/skins/default/xui/en/menu_favorites.xml
+++ b/indra/newview/skins/default/xui/en/menu_favorites.xml
@@ -21,20 +21,20 @@
          parameter="about" />
     </menu_item_call>
     <menu_item_call
-     label="Copy SLurl"
+     label="Show on Map"
      layout="topleft"
-     name="Copy slurl">
+     name="Show On Map">
         <menu_item_call.on_click
          function="Favorites.DoToSelected"
-         parameter="copy_slurl" />
+         parameter="show_on_map" />
     </menu_item_call>
     <menu_item_call
-     label="Show on Map"
+     label="Copy SLurl"
      layout="topleft"
-     name="Show On Map">
+     name="Copy slurl">
         <menu_item_call.on_click
          function="Favorites.DoToSelected"
-         parameter="show_on_map" />
+         parameter="copy_slurl" />
     </menu_item_call>
 
     <menu_item_separator
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
index 0e3de821d1..6be5aba545 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
@@ -38,7 +38,7 @@
                     height="10"
                     layout="topleft"
                     left_delta="10"
-                    top_delta="30"
+                    top_delta="25"
                     width="100">
                 Position:
             </text>
@@ -93,7 +93,7 @@
                     follows="left|top"
                     height="10"
                     layout="topleft"
-                    left_delta="-5"
+                    left_delta="65"
                     top_delta="20"
                     width="80">
                 Color:
@@ -108,12 +108,58 @@
                     name="sun_moon_color"
                     top_pad="5"
                     width="60" />
+          <text
+            follows="left|top"
+            height="10"
+            layout="topleft"
+            left_delta="-235"
+            top_delta="-3"
+            width="200">
+            Azimuth:
+          </text>
+          <slider
+            decimal_digits="2"
+            follows="left|top"
+            height="16"
+            increment="0.01"
+            initial_value="0"
+            layout="topleft"
+            left_delta="5"
+            min_val="0"
+            max_val="359.99"
+            name="sun_azimuth"
+            top_delta="13"
+            width="215"
+            can_edit_text="true"/>
+          <text
+            follows="left|top"
+            height="10"
+            layout="topleft"
+            left_delta="-5"
+            top_delta="22"
+            width="200">
+            Elevation:
+          </text>
+          <slider
+            decimal_digits="2"
+            follows="left|top"
+            height="16"
+            increment="0.01"
+            initial_value="0"
+            layout="topleft"
+            left_delta="5"
+            min_val="-90"
+            max_val="90"
+            name="sun_elevation"
+            top_delta="13"
+            width="215"
+            can_edit_text="true"/>
             <text
                     follows="left|top"
                     height="10"
                     layout="topleft"
-                    left_delta="-160"
-                    top_delta="27"
+                    left_delta="-5"
+                    top_delta="22"
                     width="200">
                 Glow Focus:
             </text>
@@ -128,8 +174,8 @@
                     min_val="-2"
                     max_val="2"
                     name="glow_focus"
-                    top_delta="15"
-                    width="250"
+                    top_delta="13"
+                    width="215"
                     can_edit_text="true"/>
             <text
                     follows="left|top"
@@ -151,8 +197,8 @@
                     min_val="0"
                     max_val="1.99"
                     name="glow_size"
-                    top_delta="15"
-                    width="250"
+                    top_delta="13"
+                    width="215"
                     can_edit_text="true"/>
             <text
                     follows="left|top"
@@ -174,8 +220,8 @@
                     min_val="0"
                     max_val="500"
                     name="star_brightness"
-                    top_delta="15"
-                    width="250"
+                    top_delta="13"
+                    width="215"
                     can_edit_text="true"/>
                     
             <check_box
@@ -227,7 +273,7 @@
                             height="10"
                             layout="topleft"
                             left_delta="10"
-                            top_delta="30"
+                            top_delta="25"
                             width="100">
                         Position:
                     </text>
@@ -278,30 +324,76 @@
                             top_delta="15"
                             width="130"
                             can_edit_text="true"/>
-                    <text
-                            follows="left|top"
-                            height="10"
-                            layout="topleft"
-                            left_delta="-5"
-                            top_delta="22"
-                            width="200">
-                        Brightness:
-                    </text>
-                    <slider
-                            decimal_digits="2"
-                            follows="left|top"
-                            height="16"
-                            increment="0.01"
-                            initial_value="0"
-                            layout="topleft"
-                            left_delta="5"
-                            min_val="0.0"
-                            max_val="1.0"
-                            name="moon_brightness"
-                            top_delta="15"
-                            width="130"
-                            can_edit_text="true"/>
-                <check_box
+                  <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-170"
+                    top_delta="32"
+                    width="200">
+                    Azimuth:
+                  </text>
+                  <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="359.99"
+                    name="moon_azimuth"
+                    top_delta="13"
+                    width="215"
+                    can_edit_text="true"/>
+                  <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="22"
+                    width="200">
+                    Elevation:
+                  </text>
+                  <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="-90"
+                    max_val="90"
+                    name="moon_elevation"
+                    top_delta="13"
+                    width="215"
+                    can_edit_text="true"/>
+                  <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="22"
+                    width="200">
+                    Brightness:
+                  </text>
+                  <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0.0"
+                    max_val="1.0"
+                    name="moon_brightness"
+                    top_delta="13"
+                    width="215"
+                    can_edit_text="true"/>
+                  <check_box
                         control_name="moonbeacon"
                         width="60"
                         height="16"
-- 
cgit v1.2.3


From 7b6c7c249645a0d3e9626c793b29348e9a549582 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 15 Feb 2021 18:08:55 +0200
Subject: SL-14725 Move environment editors' ok and cancel buttons to center

---
 indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml | 2 +-
 indra/newview/skins/default/xui/en/floater_fixedenvironment.xml   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
index 30e9002230..c609e3bd3a 100644
--- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
@@ -616,7 +616,7 @@
                     follows="top|left"
                     height="23"
                     label="Save"
-                    left="5"
+                    left="200"
                     top_pad="0"
                     name="save_btn"
                     width="156" />
diff --git a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
index 2cc73361f5..37c56d3235 100644
--- a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
+++ b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
@@ -97,7 +97,7 @@
                     layout="topleft"
                     mouse_opaque="false"
                     name="button_bar_ls"
-                    left="0"
+                    left="212"
                     orientation="horizontal"
                     top="0"
                     width="313">
-- 
cgit v1.2.3


From fa35eeecd7854b92e52f7bac2dc31bfc07ce012b Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 15 Feb 2021 22:53:54 +0200
Subject: SL-14725 Add elevation and azimuth to local lighting

---
 indra/llui/llvirtualtrackball.cpp                  |  15 +--
 indra/newview/llfloaterenvironmentadjust.cpp       | 113 +++++++++++++++++++--
 indra/newview/llfloaterenvironmentadjust.h         |   2 +
 indra/newview/llpaneleditsky.cpp                   |   4 +-
 .../default/xui/en/floater_adjust_environment.xml  |  96 +++++++++++++++--
 5 files changed, 194 insertions(+), 36 deletions(-)

diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp
index 15847a7282..728e86af08 100644
--- a/indra/llui/llvirtualtrackball.cpp
+++ b/indra/llui/llvirtualtrackball.cpp
@@ -352,7 +352,6 @@ LLQuaternion LLVirtualTrackball::getRotation() const
 void LLVirtualTrackball::getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation)
 {
     // LLQuaternion has own function to get azimuth, but it doesn't appear to return correct values (meant for 2d?)
-    const LLVector3 VectorZero(10000.0f, 0.0f, 0.0f);
     LLVector3 point = VectorZero * quat;
 
     if (!is_approx_zero(point.mV[VX]) || !is_approx_zero(point.mV[VY]))
@@ -371,19 +370,7 @@ void LLVirtualTrackball::getAzimuthAndElevation(const LLQuaternion &quat, F32 &a
         azimuth += F_PI * 2;
     }
 
-    if (abs(point.mV[VY]) > abs(point.mV[VX]) && !is_approx_zero(point.mV[VY])) // to avoid precision drop
-    {
-        elevation = atanl((F64)point.mV[VZ] / (F64)abs(point.mV[VY]));
-    }
-    else if (!is_approx_zero(point.mV[VX]))
-    {
-        elevation = atanl((F64)point.mV[VZ] / (F64)abs(point.mV[VX]));
-    }
-    else
-    {
-        // both VX and VY are near zero, VZ should be high
-        elevation = point.mV[VZ] > 0 ? F_PI_BY_TWO : -F_PI_BY_TWO;
-    }
+    elevation = asin(point.mV[VZ]); // because VectorZero is '1'
 }
 
 // static
diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp
index 4eb5e03603..95d6a2d652 100644
--- a/indra/newview/llfloaterenvironmentadjust.cpp
+++ b/indra/newview/llfloaterenvironmentadjust.cpp
@@ -53,11 +53,15 @@ namespace
     const std::string FIELD_SKY_CLOUD_SCALE("cloud_scale");
     const std::string FIELD_SKY_SCENE_GAMMA("scene_gamma");
     const std::string FIELD_SKY_SUN_ROTATION("sun_rotation");
+    const std::string FIELD_SKY_SUN_AZIMUTH("sun_azimuth");
+    const std::string FIELD_SKY_SUN_ELEVATION("sun_elevation");
     const std::string FIELD_SKY_SUN_SCALE("sun_scale");
     const std::string FIELD_SKY_GLOW_FOCUS("glow_focus");
     const std::string FIELD_SKY_GLOW_SIZE("glow_size");
     const std::string FIELD_SKY_STAR_BRIGHTNESS("star_brightness");
     const std::string FIELD_SKY_MOON_ROTATION("moon_rotation");
+    const std::string FIELD_SKY_MOON_AZIMUTH("moon_azimuth");
+    const std::string FIELD_SKY_MOON_ELEVATION("moon_elevation");
     const std::string BTN_RESET("btn_reset");
 
     const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f);
@@ -96,9 +100,13 @@ BOOL LLFloaterEnvironmentAdjust::postBuild()
     getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onStarBrightnessChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_SUN_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); });
     getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunScaleChanged(); });
 
     getChild<LLUICtrl>(FIELD_SKY_MOON_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); });
     getChild<LLUICtrl>(BTN_RESET)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onButtonReset(); });
 
     getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudMapChanged(); });
@@ -169,10 +177,25 @@ void LLFloaterEnvironmentAdjust::refresh()
     getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setValue(2.0 - (glow.mV[0] / SLIDER_SCALE_GLOW_R));
     getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B);
     getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mLiveSky->getStarBrightness());
-    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(mLiveSky->getSunRotation());
     getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setValue(mLiveSky->getSunScale());
-    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(mLiveSky->getMoonRotation());
 
+    // Sun rotation
+    LLQuaternion quat = mLiveSky->getSunRotation();
+    F32 azimuth;
+    F32 elevation;
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+
+    getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->setValue(elevation);
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(quat);
+
+    // Moon rotation
+    quat = mLiveSky->getMoonRotation();
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+
+    getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setValue(elevation);
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(quat);
 }
 
 
@@ -325,10 +348,45 @@ void LLFloaterEnvironmentAdjust::onStarBrightnessChanged()
 
 void LLFloaterEnvironmentAdjust::onSunRotationChanged()
 {
-    if (!mLiveSky)
-        return;
-    mLiveSky->setSunRotation(getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation());
-    mLiveSky->update();
+    LLQuaternion quat = getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation();
+    F32 azimuth;
+    F32 elevation;
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->setValue(elevation);
+    if (mLiveSky)
+    {
+        mLiveSky->setSunRotation(quat);
+        mLiveSky->update();
+    }
+}
+
+void LLFloaterEnvironmentAdjust::onSunAzimElevChanged()
+{
+    F32 azimuth = getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->getValue().asReal();
+    F32 elevation = getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->getValue().asReal();
+    LLQuaternion quat;
+
+    azimuth *= DEG_TO_RAD;
+    elevation *= DEG_TO_RAD;
+
+    if (is_approx_zero(elevation))
+    {
+        elevation = F_APPROXIMATELY_ZERO;
+    }
+
+    quat.setAngleAxis(-elevation, 0, 1, 0);
+    LLQuaternion az_quat;
+    az_quat.setAngleAxis(F_TWO_PI - azimuth, 0, 0, 1);
+    quat *= az_quat;
+
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(quat);
+
+    if (mLiveSky)
+    {
+        mLiveSky->setSunRotation(quat);
+        mLiveSky->update();
+    }
 }
 
 void LLFloaterEnvironmentAdjust::onSunScaleChanged()
@@ -341,10 +399,45 @@ void LLFloaterEnvironmentAdjust::onSunScaleChanged()
 
 void LLFloaterEnvironmentAdjust::onMoonRotationChanged()
 {
-    if (!mLiveSky)
-        return;
-    mLiveSky->setMoonRotation(getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation());
-    mLiveSky->update();
+    LLQuaternion quat = getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation();
+    F32 azimuth;
+    F32 elevation;
+    LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setValue(elevation);
+    if (mLiveSky)
+    {
+        mLiveSky->setMoonRotation(quat);
+        mLiveSky->update();
+    }
+}
+
+void LLFloaterEnvironmentAdjust::onMoonAzimElevChanged()
+{
+    F32 azimuth = getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->getValue().asReal();
+    F32 elevation = getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->getValue().asReal();
+    LLQuaternion quat;
+
+    azimuth *= DEG_TO_RAD;
+    elevation *= DEG_TO_RAD;
+
+    if (is_approx_zero(elevation))
+    {
+        elevation = F_APPROXIMATELY_ZERO;
+    }
+
+    quat.setAngleAxis(-elevation, 0, 1, 0);
+    LLQuaternion az_quat;
+    az_quat.setAngleAxis(F_TWO_PI - azimuth, 0, 0, 1);
+    quat *= az_quat;
+
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(quat);
+
+    if (mLiveSky)
+    {
+        mLiveSky->setMoonRotation(quat);
+        mLiveSky->update();
+    }
 }
 
 void LLFloaterEnvironmentAdjust::onCloudMapChanged()
diff --git a/indra/newview/llfloaterenvironmentadjust.h b/indra/newview/llfloaterenvironmentadjust.h
index cb38dbcfa8..05ff011be5 100644
--- a/indra/newview/llfloaterenvironmentadjust.h
+++ b/indra/newview/llfloaterenvironmentadjust.h
@@ -73,9 +73,11 @@ private:
     void                        onGlowChanged();
     void                        onStarBrightnessChanged();
     void                        onSunRotationChanged();
+    void                        onSunAzimElevChanged();
     void                        onSunScaleChanged();
 
     void                        onMoonRotationChanged();
+    void                        onMoonAzimElevChanged();
 
     void                        onCloudMapChanged();
     void                        onWaterMapChanged();
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index 06e406e2ab..a169712bd8 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -625,7 +625,7 @@ void LLPanelSettingsSkySunMoonTab::onSunAzimElevChanged()
 {
     F32 azimuth = getChild<LLUICtrl>(FIELD_SKY_SUN_AZIMUTH)->getValue().asReal();
     F32 elevation = getChild<LLUICtrl>(FIELD_SKY_SUN_ELEVATION)->getValue().asReal();
-    LLQuaternion quat = mSkySettings->getSunRotation();
+    LLQuaternion quat;
 
     azimuth *= DEG_TO_RAD;
     elevation *= DEG_TO_RAD;
@@ -687,7 +687,7 @@ void LLPanelSettingsSkySunMoonTab::onMoonAzimElevChanged()
 {
     F32 azimuth = getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->getValue().asReal();
     F32 elevation = getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->getValue().asReal();
-    LLQuaternion quat = mSkySettings->getMoonRotation();
+    LLQuaternion quat;
 
     azimuth *= DEG_TO_RAD;
     elevation *= DEG_TO_RAD;
diff --git a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
index 59589e3665..f4a686bae1 100644
--- a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
+++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
@@ -5,14 +5,14 @@
          save_rect="false"
          title="Personal Lighting"
          width="845"
-         height="240"
+         height="280"
          min_width="500"
-         min_height="235"
+         min_height="275"
          single_instance="true"
          can_resize="false">
     <layout_stack name="outer_stack"
                   width="845"
-                  height="230"
+                  height="275"
                   follows="all"
                   animate="false"
                   top="0"
@@ -276,19 +276,57 @@
                                         height="150"
                                         width="150"
                                         thumb_mode="sun"/>
+                  <text follows="left|top"
+                        height="10"
+                        layout="topleft"
+                        left_delta="0"
+                        top_pad="5"
+                        width="200">Azimuth:</text>
+                  <slider decimal_digits="2"
+                          follows="left|top"
+                          height="16"
+                          increment="0.01"
+                          initial_value="0"
+                          layout="topleft"
+                          left_delta="5"
+                          min_val="0"
+                          max_val="359.99"
+                          name="sun_azimuth"
+                          top_pad="5"
+                          width="130"
+                          can_edit_text="true"/>
+                  <text follows="left|top"
+                        height="10"
+                        layout="topleft"
+                        left_delta="-5"
+                        top_pad="5"
+                        width="200">Elevation:</text>
+                  <slider decimal_digits="2"
+                          follows="left|top"
+                          height="16"
+                          increment="0.01"
+                          initial_value="0"
+                          layout="topleft"
+                          left_delta="5"
+                          min_val="-90"
+                          max_val="90"
+                          name="sun_elevation"
+                          top_pad="5"
+                          width="130"
+                          can_edit_text="true"/>
                     <check_box control_name="sunbeacon"
                                width="60"
                                height="16"
                                label="Show Beacon"
                                layout="topleft"
                                name="sunbeacon"
-                               left_delta="55"
-                               bottom="-20"
-                               follows="bottom|right"/>
+                               left_delta="-5"
+                               top_pad="8"
+                               follows="left|top"/>
                     <text follows="left|top"
                           height="10"
                           layout="topleft"
-                          left_pad="40"
+                          left_pad="95"
                           top="25"
                           width="80">Scale:</text>
                     <slider decimal_digits="2"
@@ -385,15 +423,53 @@
                                         height="150"
                                         width="150"
                                         thumb_mode="moon"/>
+                  <text follows="left|top"
+                        height="10"
+                        layout="topleft"
+                        left_delta="0"
+                        top_pad="5"
+                        width="200">Azimuth:</text>
+                  <slider decimal_digits="2"
+                          follows="left|top"
+                          height="16"
+                          increment="0.01"
+                          initial_value="0"
+                          layout="topleft"
+                          left_delta="5"
+                          min_val="0"
+                          max_val="359.99"
+                          name="moon_azimuth"
+                          top_pad="5"
+                          width="130"
+                          can_edit_text="true"/>
+                  <text follows="left|top"
+                        height="10"
+                        layout="topleft"
+                        left_delta="-5"
+                        top_pad="5"
+                        width="200">Elevation:</text>
+                  <slider decimal_digits="2"
+                          follows="left|top"
+                          height="16"
+                          increment="0.01"
+                          initial_value="0"
+                          layout="topleft"
+                          left_delta="5"
+                          min_val="-90"
+                          max_val="90"
+                          name="moon_elevation"
+                          top_pad="5"
+                          width="130"
+                          can_edit_text="true"/>
                     <check_box control_name="moonbeacon"
+                               follows="left|top"
                                width="60"
                                height="16"
                                label="Show Beacon"
                                layout="topleft"
                                name="moonbeacon"
-                               right="-50"
-                               bottom="-20"
-                               follows="bottom|right"/>
+                               left_delta="0"
+                               top_pad="8"/>
                 </layout_panel>
             </layout_stack>
         </layout_panel>
-- 
cgit v1.2.3


From 9eae41e5825662564125b9f5edf87e1aa3c0c508 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 16 Feb 2021 21:47:34 +0200
Subject: SL-14725 Validate trackball elevation

---
 indra/llui/llvirtualtrackball.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp
index 728e86af08..6e0aef740d 100644
--- a/indra/llui/llvirtualtrackball.cpp
+++ b/indra/llui/llvirtualtrackball.cpp
@@ -370,7 +370,10 @@ void LLVirtualTrackball::getAzimuthAndElevation(const LLQuaternion &quat, F32 &a
         azimuth += F_PI * 2;
     }
 
-    elevation = asin(point.mV[VZ]); // because VectorZero is '1'
+    // while vector is '1', F32 is not sufficiently precise and we can get
+    // values like 1.0000012 which will result in -90deg angle instead of 90deg
+    F32 z = llclamp(point.mV[VZ], -1.f, 1.f);
+    elevation = asin(z); // because VectorZero's length is '1'
 }
 
 // static
@@ -442,6 +445,10 @@ BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask)
             mValue *= az_quat;
         }
 
+        // we are doing a lot of F32 mathematical operations with loss of precision,
+        // re-normalize to compensate
+        mValue.normalize();
+
         mPrevX = x;
         mPrevY = y;
         onCommit();
-- 
cgit v1.2.3


From d15156d4e091ee7a095df70cfda04fea4ee2935a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 18 Feb 2021 14:24:54 +0000
Subject: SL-14862 - catching more commands in LLUIUsage

---
 indra/llui/lltoolbar.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index e6f466ec78..4868c66d1b 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -967,6 +967,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
 			executeStopParam.function_name = executeStopFunction;
 			executeStopParam.parameter = commandp->executeStopParameters();
 			LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam);
+			button->setFunctionName(commandp->executeFunctionName());
+			LL_DEBUGS("UIUsage") << "button function name a -> " << commandp->executeFunctionName() << LL_ENDL;
 			LLUICtrl::commit_callback_t stop_func = initCommitCallback(executeStopParam);
 			
 			button->setMouseDownCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2));
@@ -974,6 +976,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
 		}
 		else
 		{
+			button->setFunctionName(commandp->executeFunctionName());
+			LL_DEBUGS("UIUsage") << "button function name b -> " << commandp->executeFunctionName() << LL_ENDL;
 			button->setCommitCallback(executeParam);
 		}
 
-- 
cgit v1.2.3


From 53343bc708339b95f18804e11d6a130b542e0c5b Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 17 Feb 2021 01:20:24 +0200
Subject: SL-14797 Normalize right-click - favorites panel, part #4

---
 indra/newview/llfavoritesbar.cpp                   | 44 ++++++++++++++++++++++
 indra/newview/llfavoritesbar.h                     |  1 +
 indra/newview/llpanellandmarks.cpp                 | 33 ++++++++++------
 indra/newview/llpanellandmarks.h                   |  6 ++-
 indra/newview/llpanelplaces.cpp                    | 16 ++++++++
 .../skins/default/xui/en/menu_favorites.xml        | 23 +++++++++--
 .../newview/skins/default/xui/en/notifications.xml | 25 +++++++++++-
 7 files changed, 130 insertions(+), 18 deletions(-)

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 347997a69a..2394a763ee 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -38,6 +38,7 @@
 #include "lltooltip.h"
 
 #include "llagent.h"
+#include "llagentpicksinfo.h"
 #include "llavatarnamecache.h"
 #include "llclipboard.h"
 #include "llinventorybridge.h"
@@ -1194,6 +1195,10 @@ bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata)
     {
         return isClipboardPasteable();
     }
+    else if (param == "create_pick")
+    {
+        return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
+    }
 
     return false;
 }
@@ -1242,6 +1247,13 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
 			LLFloaterReg::showInstance("world_map", "center");
 		}
 	}
+    else if (action == "create_pick")
+    {
+        LLSD args;
+        args["type"] = "create_pick";
+        args["item_id"] = item->getUUID();
+        LLFloaterSidePanelContainer::showPanel("places", args);
+    }
 	else if (action == "cut")
 	{
 	}
@@ -1257,6 +1269,16 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
 	{
 		gInventory.removeItem(mSelectedItemID);
 	}
+    else if (action == "rename")
+    {
+        LLSD args;
+        args["NAME"] = item->getName();
+
+        LLSD payload;
+        payload["id"] = mSelectedItemID;
+
+        LLNotificationsUtil::add("RenameLandmark", args, payload, boost::bind(onRenameCommit, _1, _2));
+    }
 
 	// Pop-up the overflow menu again (it gets hidden whenever the user clicks a context menu item).
 	// See EXT-4217 and STORM-207.
@@ -1269,6 +1291,28 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
 	}
 }
 
+bool LLFavoritesBarCtrl::onRenameCommit(const LLSD& notification, const LLSD& response)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+    if (0 == option)
+    {
+        LLUUID id = notification["payload"]["id"].asUUID();
+        LLInventoryItem *item = gInventory.getItem(id);
+        std::string landmark_name = response["new_name"].asString();
+        LLStringUtil::trim(landmark_name);
+
+        if (!landmark_name.empty() && item && item->getName() != landmark_name)
+        {
+            LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+            new_item->rename(landmark_name);
+            new_item->updateServer(FALSE);
+            gInventory.updateItem(new_item);
+        }
+    }
+
+    return false;
+}
+
 BOOL LLFavoritesBarCtrl::isClipboardPasteable() const
 {
 	if (!LLClipboard::instance().hasContents())
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 571208aa31..147308c0ba 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -91,6 +91,7 @@ protected:
 
 	bool enableSelected(const LLSD& userdata);
 	void doToSelected(const LLSD& userdata);
+	static bool onRenameCommit(const LLSD& notification, const LLSD& response);
 	BOOL isClipboardPasteable() const;
 	void pasteFromClipboard() const;
 	
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 6e8eac19fc..7eda9c1aa7 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -512,14 +512,20 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
 {
 	//this function will be called after user will try to create a pick for selected landmark.
 	// We have to make request to sever to get parcel_id and snaption_id. 
-	if(isLandmarkSelected())
+	if(mCreatePickItemId.notNull())
 	{
-		LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();
-		if (!cur_item) return;
-		LLUUID id = cur_item->getUUID();
-		LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
-		doActionOnCurSelectedLandmark(boost::bind(
-				&LLLandmarksPanel::doProcessParcelInfo, this, _1, getCurSelectedItem(), inv_item, parcel_data));
+		LLInventoryItem* inv_item = gInventory.getItem(mCreatePickItemId);
+
+        if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_LANDMARK)
+        {
+            // we are processing response for doCreatePick, landmark should be already loaded
+            LLLandmark* landmark = LLLandmarkActions::getLandmark(inv_item->getUUID());
+            if (landmark)
+            {
+                doProcessParcelInfo(landmark, inv_item, parcel_data);
+            }
+        }
+        mCreatePickItemId.setNull();
 	}
 }
 
@@ -1124,7 +1130,11 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
 	}
 	else if ("create_pick" == command_name)
 	{
-		doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1));
+        LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();
+        if (cur_item)
+        {
+            doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1, cur_item->getUUID()));
+        }
 	}
     else if ("share" == command_name && mCurrentSelectedList)
     {
@@ -1344,7 +1354,6 @@ void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)
 }
 
 void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark,
-										   LLFolderViewItem* cur_item,
 										   LLInventoryItem* inv_item,
 										   const LLParcelData& parcel_data)
 {
@@ -1373,7 +1382,7 @@ void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark,
 
 	LLPickData data;
 	data.pos_global = landmark_global_pos;
-	data.name = cur_item->getName();
+	data.name = inv_item->getName();
 	data.desc = inv_item->getDescription();
 	data.snapshot_id = parcel_data.snapshot_id;
 	data.parcel_id = parcel_data.parcel_id;
@@ -1393,11 +1402,13 @@ void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark,
 					panel_pick, panel_places,params));
 }
 
-void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)
+void LLLandmarksPanel::doCreatePick(LLLandmark* landmark, const LLUUID &item_id)
 {
 	LLViewerRegion* region = gAgent.getRegion();
 	if (!region) return;
 
+    mCreatePickItemId = item_id;
+
 	LLGlobalVec pos_global;
 	LLUUID region_id;
 	landmark->getGlobalPos(pos_global);
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index c11cbe05ae..e8fb62e0e8 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -82,6 +82,8 @@ public:
 
 	void updateMenuVisibility(LLUICtrl* menu);
 
+	void doCreatePick(LLLandmark* landmark, const LLUUID &item_id );
+
 protected:
 	/**
 	 * @return true - if current selected panel is not null and selected item is a landmark
@@ -160,10 +162,8 @@ private:
 	 */
 	void doShowOnMap(LLLandmark* landmark);
 	void doProcessParcelInfo(LLLandmark* landmark,
-							 LLFolderViewItem* cur_item,
 							 LLInventoryItem* inv_item,
 							 const LLParcelData& parcel_data);
-	void doCreatePick(LLLandmark* landmark);
 
 private:
 	LLPlacesInventoryPanel*		mFavoritesInventoryPanel;
@@ -183,6 +183,8 @@ private:
 	accordion_tabs_t			mAccordionTabs;
 
 	LLAccordionCtrlTab*			mMyLandmarksAccordionTab;
+
+    LLUUID                      mCreatePickItemId; // item we requested a pick for
 };
 
 #endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index c038207628..427b3fbf57 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -79,6 +79,7 @@
 static const F32 PLACE_INFO_UPDATE_INTERVAL = 3.0;
 static const std::string AGENT_INFO_TYPE			= "agent";
 static const std::string CREATE_LANDMARK_INFO_TYPE	= "create_landmark";
+static const std::string CREATE_PICK_TYPE			= "create_pick";
 static const std::string LANDMARK_INFO_TYPE			= "landmark";
 static const std::string REMOTE_PLACE_INFO_TYPE		= "remote_place";
 static const std::string TELEPORT_HISTORY_INFO_TYPE	= "teleport_history";
@@ -388,6 +389,21 @@ void LLPanelPlaces::onOpen(const LLSD& key)
 			// Update the buttons at the bottom of the panel
 			updateVerbs();
 		}
+        else if (key_type == CREATE_PICK_TYPE)
+        {
+            LLUUID item_id = key["item_id"];
+
+            LLLandmarksPanel* landmarks_panel =
+                dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
+            if (landmarks_panel && item_id.notNull())
+            {
+                LLLandmark* landmark = LLLandmarkActions::getLandmark(item_id, boost::bind(&LLLandmarksPanel::doCreatePick, landmarks_panel, _1, item_id));
+                if (landmark)
+                {
+                    landmarks_panel->doCreatePick(landmark, item_id);
+                }
+            }
+        }
 		else // "create_landmark"
 		{
 			mFilterEditor->clear();
diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml
index 082f2f9670..6c28032e3f 100644
--- a/indra/newview/skins/default/xui/en/menu_favorites.xml
+++ b/indra/newview/skins/default/xui/en/menu_favorites.xml
@@ -36,6 +36,17 @@
          function="Favorites.DoToSelected"
          parameter="copy_slurl" />
     </menu_item_call>
+    <menu_item_call
+     label="Create Pick"
+     layout="topleft"
+     name="create_pick">
+        <menu_item_call.on_click
+         function="Favorites.DoToSelected"
+         parameter="create_pick" />
+        <menu_item_call.on_enable
+         function="Favorites.EnableSelected"
+         parameter="create_pick" />
+    </menu_item_call>
 
     <menu_item_separator
      layout="topleft" />
@@ -59,10 +70,14 @@
          function="Favorites.EnableSelected"
          parameter="can_paste" />
     </menu_item_call>
-
-    <menu_item_separator
-     layout="topleft" />
-
+    <menu_item_call
+     label="Rename"
+     layout="topleft"
+     name="rename">
+        <menu_item_call.on_click
+         function="Favorites.DoToSelected"
+         parameter="rename" />
+    </menu_item_call>
     <menu_item_call
      label="Delete"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index fd243d8b19..23bf3191ae 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3141,7 +3141,30 @@ See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries
        text="Cancel"/>
     </form>
   </notification>
-  
+
+  <notification
+   icon="alertmodal.tga"
+   label="Rename Landmark"
+   name="RenameLandmark"
+   type="alertmodal">
+    Choose a new name for [NAME]
+    <tag>confirm</tag>
+    <form name="form">
+      <input name="new_name" type="text" width="300">
+        [NAME]
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="OK"
+       text="OK"/>
+      <button
+       index="1"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="RemoveFromFriends"
-- 
cgit v1.2.3


From 18717562eef9a333ad6d3598180823bd9821d06f Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 18 Feb 2021 23:40:03 +0200
Subject: SL-14654 [EEP] Aplying settings locally now takes 1 second insterad
 of 5

---
 indra/newview/llenvironment.cpp     | 25 +++++++++++++++----------
 indra/newview/llenvironment.h       | 15 ++++++++-------
 indra/newview/llinventorybridge.cpp |  4 ++--
 indra/newview/llviewermenu.cpp      | 23 +++++++++--------------
 4 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 74c1b99e4d..a1b27e48ce 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -785,11 +785,11 @@ namespace
 }
 
 //=========================================================================
-const F32Seconds LLEnvironment::TRANSITION_INSTANT(0.0f);
-const F32Seconds LLEnvironment::TRANSITION_FAST(1.0f);
-const F32Seconds LLEnvironment::TRANSITION_DEFAULT(5.0f);
-const F32Seconds LLEnvironment::TRANSITION_SLOW(10.0f);
-const F32Seconds LLEnvironment::TRANSITION_ALTITUDE(5.0f);
+const F64Seconds LLEnvironment::TRANSITION_INSTANT(0.0f);
+const F64Seconds LLEnvironment::TRANSITION_FAST(1.0f);
+const F64Seconds LLEnvironment::TRANSITION_DEFAULT(5.0f);
+const F64Seconds LLEnvironment::TRANSITION_SLOW(10.0f);
+const F64Seconds LLEnvironment::TRANSITION_ALTITUDE(5.0f);
 
 const LLUUID LLEnvironment::KNOWN_SKY_SUNRISE("01e41537-ff51-2f1f-8ef7-17e4df760bfb");
 const LLUUID LLEnvironment::KNOWN_SKY_MIDDAY("6c83e853-e7f8-cad7-8ee6-5f31c453721c");
@@ -1217,20 +1217,25 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe
 
 void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version)
 {
-    setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET);
+    setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, TRANSITION_DEFAULT, env_version);
 }
 
+void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsBase::Seconds transition, S32 env_version)
+{
+    setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, transition, env_version);
+}
 
 void LLEnvironment::setEnvironment(EnvSelection_t env,
                                    const LLUUID &assetId,
                                    LLSettingsDay::Seconds daylength,
                                    LLSettingsDay::Seconds dayoffset,
+                                   LLSettingsBase::Seconds transition,
                                    S32 env_version)
 {
     LLSettingsVOBase::getSettingsAsset(assetId,
-        [this, env, daylength, dayoffset, env_version](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
+        [this, env, daylength, dayoffset, env_version, transition](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
         {
-            onSetEnvAssetLoaded(env, asset_id, settings, daylength, dayoffset, TRANSITION_DEFAULT, status, env_version);
+            onSetEnvAssetLoaded(env, asset_id, settings, daylength, dayoffset, transition, status, env_version);
         });
 }
 
@@ -1685,7 +1690,7 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI
         if (!envinfo->mDayCycle)
         {
             clearEnvironment(ENV_PARCEL);
-            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, envinfo->mEnvVersion);
+            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, TRANSITION_DEFAULT, envinfo->mEnvVersion);
             updateEnvironment();
         }
         else if (envinfo->mDayCycle->isTrackEmpty(LLSettingsDay::TRACK_WATER)
@@ -1693,7 +1698,7 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI
         {
             LL_WARNS("ENVIRONMENT") << "Invalid day cycle for region" << LL_ENDL;
             clearEnvironment(ENV_PARCEL);
-            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, envinfo->mEnvVersion);
+            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, TRANSITION_DEFAULT, envinfo->mEnvVersion);
             updateEnvironment();
         }
         else
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 6ab0db7501..5c1a62d0ab 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -52,11 +52,11 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
     LOG_CLASS(LLEnvironment);
 
 public:
-    static const F32Seconds     TRANSITION_INSTANT;
-    static const F32Seconds     TRANSITION_FAST;
-    static const F32Seconds     TRANSITION_DEFAULT;
-    static const F32Seconds     TRANSITION_SLOW;
-    static const F32Seconds     TRANSITION_ALTITUDE;
+    static const F64Seconds     TRANSITION_INSTANT;
+    static const F64Seconds     TRANSITION_FAST;
+    static const F64Seconds     TRANSITION_DEFAULT;
+    static const F64Seconds     TRANSITION_SLOW;
+    static const F64Seconds     TRANSITION_ALTITUDE;
 
     static const LLUUID         KNOWN_SKY_SUNRISE;
     static const LLUUID         KNOWN_SKY_MIDDAY;
@@ -144,8 +144,9 @@ public:
     void                        setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixed, LLSettingsWater::ptr_t()), env_version); }
     void                        setEnvironment(EnvSelection_t env, const LLSettingsWater::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(LLSettingsSky::ptr_t(), fixed), env_version); }
     void                        setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixeds, const LLSettingsWater::ptr_t & fixedw, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixeds, fixedw), env_version); }
-    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version = NO_VERSION);
-    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version = NO_VERSION);
+    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 env_version);
+    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version);
+    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, S32 env_version = NO_VERSION);
 
     void                        setSharedEnvironment();
     void                        clearEnvironment(EnvSelection_t env);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 04f89af989..0e7e762d81 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -7060,8 +7060,8 @@ void LLSettingsBridge::performAction(LLInventoryModel* model, std::string action
         if (!item) 
             return;
         LLUUID asset_id = item->getAssetUUID();
-        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id);
-        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id, LLEnvironment::TRANSITION_FAST);
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
     }
     else if ("apply_settings_parcel" == action)
     {
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b04043ede9..7d7fdf53e2 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -8608,37 +8608,32 @@ class LLWorldEnvSettings : public view_listener_t
 		
 		if (event_name == "sunrise")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().updateEnvironment();
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
             defocusEnvFloaters();
 		}
 		else if (event_name == "noon")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().updateEnvironment();
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
             defocusEnvFloaters();
 		}
 		else if (event_name == "sunset")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().updateEnvironment();
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
             defocusEnvFloaters();
 		}
 		else if (event_name == "midnight")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().updateEnvironment();
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
             defocusEnvFloaters();
 		}
         else if (event_name == "region")
 		{
             LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().updateEnvironment();
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
             defocusEnvFloaters();
 		}
         else if (event_name == "pause_clouds")
-- 
cgit v1.2.3


From 5bdc96784c696f7a36aab1e18e70dafbe4a27d73 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 23 Feb 2021 18:41:15 +0200
Subject: SL-12475 Add the way to reset current Favorites folders

---
 indra/newview/llinventorybridge.cpp                   | 6 +++++-
 indra/newview/llinventorypanel.cpp                    | 6 ++++++
 indra/newview/llinventorypanel.h                      | 1 +
 indra/newview/skins/default/xui/en/menu_inventory.xml | 7 +++++++
 indra/newview/skins/default/xui/en/strings.xml        | 2 +-
 5 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 0e7e762d81..065a3cb9ae 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4115,7 +4115,11 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
                     items.push_back(std::string("New Settings"));
                     items.push_back(std::string("upload_def"));
 
-                    if (!LLFolderType::lookupIsProtectedType(getPreferredType()) && !isParentSystemFolder(model, mUUID))
+                    if (model->findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE) == mUUID)
+                    {
+                        items.push_back(std::string("Reset Favorites folder"));
+                    }
+                    else if (!LLFolderType::lookupIsProtectedType(getPreferredType()) && !isParentSystemFolder(model, mUUID))
                     {
                         items.push_back(std::string("Set Favorites folder"));
                     }
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index bca3cc0cf7..cda39c716b 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -182,6 +182,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mCommitCallbackRegistrar.add("Inventory.Share",  boost::bind(&LLAvatarActions::shareWithAvatars, this));
 	mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryPanel::fileUploadLocation, this, _2));
 	mCommitCallbackRegistrar.add("Inventory.SetFavoritesFolder", boost::bind(&LLInventoryPanel::setFavoritesFolder, this, _2));
+    mCommitCallbackRegistrar.add("Inventory.ResetFavoritesFolder", boost::bind(&LLInventoryPanel::resetFavoritesFolder, this, _2));
 }
 
 LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
@@ -1477,6 +1478,11 @@ void LLInventoryPanel::setFavoritesFolder(const LLSD& userdata)
     gSavedPerAccountSettings.setString("FavoritesFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
 }
 
+void LLInventoryPanel::resetFavoritesFolder(const LLSD& userdata)
+{
+    gSavedPerAccountSettings.setString("FavoritesFolder", "");
+}
+
 void LLInventoryPanel::purgeSelectedItems()
 {
     if (!mFolderRoot.get()) return;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 9d6d56dd69..e6d23eb649 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -221,6 +221,7 @@ public:
 	bool beginIMSession();
 	void fileUploadLocation(const LLSD& userdata);
 	void setFavoritesFolder(const LLSD& userdata);
+	void resetFavoritesFolder(const LLSD& userdata);
 	void purgeSelectedItems();
 	bool attachObject(const LLSD& userdata);
 	static void idle(void* user_data);
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index e7782a4ca0..b5cde602bd 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -400,6 +400,13 @@
         <menu_item_call.on_click
          function="Inventory.SetFavoritesFolder"/>
       </menu_item_call>
+      <menu_item_call
+       label="Reset Favorites folder"
+       layout="topleft"
+       name="Reset Favorites folder">
+          <menu_item_call.on_click
+           function="Inventory.ResetFavoritesFolder"/>
+      </menu_item_call>
     <menu
      label="Change Type"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c2b5286fc3..20ef10f172 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2297,7 +2297,7 @@ For AI Character: Get the closest navigable point to the point provided.
 	<!-- inventory -->
 	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
 	<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
-	<string name="InventoryFavoritItemsNotSelected">Click "Use as Favorites folder" on a folder of your choice. You can choose a different folder at any time. System folders cannot be used for Favorites.</string>
+	<string name="InventoryFavoritItemsNotSelected">Click "Use as Favorites folder" on a folder of your choice. You can choose a different folder at any time. System folders and folders inside them cannot be used for Favorites.</string>
 	<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
 	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
 	<string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string>
-- 
cgit v1.2.3


From 59f61e2ff2f6cedb480d691f130a8d5e6b16c302 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 22 Feb 2021 21:34:17 +0200
Subject: SL-14842 Apply toolstrip layout to Places floater Part #1

Menus
---
 indra/newview/llpanellandmarks.cpp                 | 163 +++++-----
 indra/newview/llpanellandmarks.h                   |  44 +--
 indra/newview/llpanelplaces.cpp                    |  85 ++++-
 indra/newview/llpanelplaces.h                      |  12 +
 indra/newview/llpanelplacestab.h                   |  12 +
 indra/newview/llpanelteleporthistory.cpp           | 346 +++++++++++----------
 indra/newview/llpanelteleporthistory.h             |  50 ++-
 .../skins/default/xui/en/menu_place_add_button.xml |  23 +-
 .../default/xui/en/menu_places_gear_folder.xml     |  33 --
 .../default/xui/en/menu_places_gear_landmark.xml   |  38 ---
 .../default/xui/en/menu_places_gear_sorting.xml    |  43 +++
 .../default/xui/en/menu_teleport_history_gear.xml  |  12 +-
 .../default/xui/en/menu_teleport_history_item.xml  |  37 ++-
 .../skins/default/xui/en/panel_landmarks.xml       | 102 +-----
 .../newview/skins/default/xui/en/panel_places.xml  | 129 +++++++-
 .../default/xui/en/panel_teleport_history.xml      |  35 +--
 16 files changed, 618 insertions(+), 546 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 7eda9c1aa7..3902c615a1 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -42,7 +42,6 @@
 #include "llagentui.h"
 #include "llavataractions.h"
 #include "llcallbacklist.h"
-#include "lldndbutton.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llfloaterworldmap.h"
 #include "llfolderviewitem.h"
@@ -61,12 +60,6 @@
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
 
-static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
-static const std::string ADD_BUTTON_NAME = "add_btn";
-static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
-static const std::string TRASH_BUTTON_NAME = "trash_btn";
-
-
 // helper functions
 static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
 static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
@@ -196,10 +189,10 @@ LLLandmarksPanel::LLLandmarksPanel()
 	,	mMyInventoryPanel(NULL)
 	,	mLibraryInventoryPanel(NULL)
 	,	mCurrentSelectedList(NULL)
-	,	mListCommands(NULL)
-	,	mGearButton(NULL)
 	,	mGearFolderMenu(NULL)
 	,	mGearLandmarkMenu(NULL)
+	,	mSortingMenu(NULL)
+	,	mAddMenu(NULL)
 {
 	mInventoryObserver = new LLLandmarksPanelObserver(this);
 	gInventory.addObserver(mInventoryObserver);
@@ -304,6 +297,12 @@ void LLLandmarksPanel::onTeleport()
 	}
 }
 
+/*virtual*/
+void LLLandmarksPanel::onRemoveSelected()
+{
+    onClipboardAction("delete");
+}
+
 // virtual
 bool LLLandmarksPanel::isSingleItemSelected()
 {
@@ -322,6 +321,37 @@ bool LLLandmarksPanel::isSingleItemSelected()
 	return result;
 }
 
+// virtual
+LLToggleableMenu* LLLandmarksPanel::getSelectionMenu()
+{
+    LLToggleableMenu* menu = mGearFolderMenu;
+
+    if (mCurrentSelectedList)
+    {
+        LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();
+        if (!listenerp)
+            return menu;
+
+        if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+        {
+            menu = mGearLandmarkMenu;
+        }
+    }
+    return menu;
+}
+
+// virtual
+LLToggleableMenu* LLLandmarksPanel::getSortingMenu()
+{
+    return mSortingMenu;
+}
+
+// virtual
+LLToggleableMenu* LLLandmarksPanel::getCreateMenu()
+{
+    return mAddMenu;
+}
+
 // virtual
 void LLLandmarksPanel::updateVerbs()
 {
@@ -336,8 +366,6 @@ void LLLandmarksPanel::updateVerbs()
 	// TODO: mantipov: Uncomment when mShareBtn is supported
 	// Share button should be enabled when neither a folder nor a landmark is selected
 	//mShareBtn->setEnabled(NULL != current_item);
-
-	updateListCommands();
 }
 
 void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
@@ -668,40 +696,29 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory
 	if (inventory_list != mFavoritesInventoryPanel)
 	{
 		mFavoritesInventoryPanel->clearSelection();
+		mFavoritesInventoryPanel->getRootFolder()->clearSelection();
 	}
 
 	if (inventory_list != mLandmarksInventoryPanel)
 	{
 		mLandmarksInventoryPanel->clearSelection();
+		mLandmarksInventoryPanel->getRootFolder()->clearSelection();
 	}
 	if (inventory_list != mMyInventoryPanel)
 	{
 		mMyInventoryPanel->clearSelection();
+		mMyInventoryPanel->getRootFolder()->clearSelection();
 	}
 	if (inventory_list != mLibraryInventoryPanel)
 	{
 		mLibraryInventoryPanel->clearSelection();
+		mLibraryInventoryPanel->getRootFolder()->clearSelection();
 	}
 }
 
 // List Commands Handlers
 void LLLandmarksPanel::initListCommandsHandlers()
 {
-	mListCommands = getChild<LLPanel>("bottom_panel");
-
-	mGearButton = getChild<LLMenuButton>(OPTIONS_BUTTON_NAME);
-	mGearButton->setMouseDownCallback(boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
-
-	mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
-
-	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
-	trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
-			,	_4 // BOOL drop
-			,	_5 // EDragAndDropType cargo_type
-			,	_6 // void* cargo_data
-			,	_7 // EAcceptance* accept
-			));
-
 	mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
 	mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2));
 	mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
@@ -710,23 +727,15 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
 	mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_sorting.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mAddMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 
 	mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
 	mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
 
-	mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME));
-}
-
-
-void LLLandmarksPanel::updateListCommands()
-{
-	bool add_folder_enabled = isActionEnabled("category");
-	bool trash_enabled = isActionEnabled("delete") && (isFolderSelected() || isLandmarkSelected());
-
-	// keep Options & Add Landmark buttons always enabled
-	mListCommands->getChildView(ADD_FOLDER_BUTTON_NAME)->setEnabled(add_folder_enabled);
-	mListCommands->getChildView(TRASH_BUTTON_NAME)->setEnabled(trash_enabled);
+	// show menus even if all items are disabled
+	mGearLandmarkMenu->setAlwaysShowMenu(TRUE);
+	mGearFolderMenu->setAlwaysShowMenu(TRUE);
 }
 
 void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu)
@@ -734,43 +743,6 @@ void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu)
 	onMenuVisibilityChange(menu, LLSD().with("visibility", true));
 }
 
-void LLLandmarksPanel::onActionsButtonClick()
-{
-	LLToggleableMenu* menu = mGearFolderMenu;
-
-	if(mCurrentSelectedList)
-	{
-		LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();
-		if(!listenerp)
-			return;
-
-		if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
-		{
-			menu = mGearLandmarkMenu;
-		}
-	}
-
-	mGearButton->setMenu(menu);
-}
-
-void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
-{
-	if (menu)
-	{
-		menu->buildDrawLabels();
-		menu->updateParent(LLMenuGL::sMenuContainer);
-		menu->arrangeAndClear();
-
-		LLView* spawning_view = getChild<LLView>(spawning_view_name);
-
-		S32 menu_x, menu_y;
-		//show menu in co-ordinates of panel
-		spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
-		menu_y += menu->getRect().getHeight();
-		LLMenuGL::showPopup(this, menu, menu_x, menu_y);
-	}
-}
-
 void LLLandmarksPanel::onTrashButtonClick() const
 {
 	onClipboardAction("delete");
@@ -782,7 +754,8 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 	LLFolderViewItem* item = getCurSelectedItem();
 
 	std::string command_name = userdata.asString();
-	if("add_landmark" == command_name)
+	if("add_landmark" == command_name
+        || "add_landmark_root" == command_name)
 	{
 		LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
 		if(landmark)
@@ -793,8 +766,8 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 		{
             LLSD args;
             args["type"] = "create_landmark";
-            if (view_model->getInventoryType()
-                == LLInventoryType::IT_CATEGORY)
+            if ("add_landmark" == command_name
+                && view_model->getInventoryType() == LLInventoryType::IT_CATEGORY)
             {
                 args["dest_folder"] = view_model->getUUID();
             }
@@ -837,6 +810,17 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 			}
 		}
 	}
+    else if ("category_root" == command_name)
+    {
+        //in case My Landmarks tab is completely empty (thus cannot be determined as being selected)
+        menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"),
+            gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
+
+        if (mMyLandmarksAccordionTab)
+        {
+            mMyLandmarksAccordionTab->changeOpenClose(false);
+        }
+    }
 }
 
 void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
@@ -1031,9 +1015,9 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 			// Disable "Show on Map" if landmark loading is in progress.
 			return !gLandmarkList.isAssetInLoadedCallbackMap(asset_uuid);
-	}
-	else if ("rename" == command_name)
-	{
+		}
+		else if ("rename" == command_name)
+		{
 			LLFolderViewItem* selected_item = getCurSelectedItem();
 			if (!selected_item) return false;
 
@@ -1042,6 +1026,11 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 		return true;
 	}
+    if ("category_root" == command_name)
+    {
+        // Landmarks Accordion
+        return true;
+    }
 	else if("category" == command_name)
 	{
 		// we can add folder only in Landmarks Accordion
@@ -1093,6 +1082,16 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
         }
         return true;
     }
+    else if ("add_landmark_root" == command_name)
+    {
+        LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
+        if (landmark)
+        {
+            //already exists
+            return false;
+        }
+        return true;
+    }
     else if ("share" == command_name)
     {
         if (!mCurrentSelectedList)
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index e8fb62e0e8..4db77be50b 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -52,13 +52,23 @@ public:
 	LLLandmarksPanel();
 	virtual ~LLLandmarksPanel();
 
-	/*virtual*/ BOOL postBuild();
-	/*virtual*/ void onSearchEdit(const std::string& string);
-	/*virtual*/ void onShowOnMap();
-	/*virtual*/ void onShowProfile();
-	/*virtual*/ void onTeleport();
-	/*virtual*/ void updateVerbs();
-	/*virtual*/ bool isSingleItemSelected();
+	BOOL postBuild() override;
+	void onSearchEdit(const std::string& string) override;
+	void onShowOnMap() override;
+	void onShowProfile() override;
+	void onTeleport() override;
+	void onRemoveSelected() override;
+	void updateVerbs() override;
+	bool isSingleItemSelected() override;
+
+    LLToggleableMenu* getSelectionMenu() override;
+    LLToggleableMenu* getSortingMenu() override;
+    LLToggleableMenu* getCreateMenu() override;
+
+    /**
+     * Processes drag-n-drop of the Landmarks and folders into trash button.
+     */
+    bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override;
 
 	void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
 	void onSelectorButtonClicked();
@@ -108,9 +118,9 @@ protected:
 	void updateSortOrder(LLInventoryPanel* panel, bool byDate);
 
 	//LLRemoteParcelInfoObserver interface
-	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
-	/*virtual*/ void setParcelID(const LLUUID& parcel_id);
-	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
+	void processParcelInfo(const LLParcelData& parcel_data) override;
+	void setParcelID(const LLUUID& parcel_id) override;
+	void setErrorStatus(S32 status, const std::string& reason) override;
 	
 private:
 	void initFavoritesInventoryPanel();
@@ -124,9 +134,6 @@ private:
 
 	// List Commands Handlers
 	void initListCommandsHandlers();
-	void updateListCommands();
-	void onActionsButtonClick();
-	void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
 	void onTrashButtonClick() const;
 	void onAddAction(const LLSD& command_name) const;
 	void onClipboardAction(const LLSD& command_name) const;
@@ -152,11 +159,6 @@ private:
 	bool canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const;
 	void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params);
 
-	/**
-	 * Processes drag-n-drop of the Landmarks and folders into trash button.
-	 */
-	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept);
-
 	/**
 	 * Landmark actions callbacks. Fire when a landmark is loaded from the list.
 	 */
@@ -170,14 +172,12 @@ private:
 	LLPlacesInventoryPanel*		mLandmarksInventoryPanel;
 	LLPlacesInventoryPanel*		mMyInventoryPanel;
 	LLPlacesInventoryPanel*		mLibraryInventoryPanel;
-	LLMenuButton*				mGearButton;
 	LLToggleableMenu*			mGearLandmarkMenu;
 	LLToggleableMenu*			mGearFolderMenu;
-	LLMenuGL*					mMenuAdd;
+	LLToggleableMenu*			mSortingMenu;
+	LLToggleableMenu*			mAddMenu;
 	LLPlacesInventoryPanel*		mCurrentSelectedList;
 	LLInventoryObserver*		mInventoryObserver;
-
-	LLPanel*					mListCommands;
 	
 	typedef	std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
 	accordion_tabs_t			mAccordionTabs;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 427b3fbf57..00752d5a25 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -53,6 +53,7 @@
 #include "llagentpicksinfo.h"
 #include "llavatarpropertiesprocessor.h"
 #include "llcommandhandler.h"
+#include "lldndbutton.h"
 #include "llfloaterworldmap.h"
 #include "llinventorybridge.h"
 #include "llinventoryobserver.h"
@@ -297,6 +298,26 @@ BOOL LLPanelPlaces::postBuild()
 	mPlaceInfoBtn = getChild<LLButton>("profile_btn");
 	mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this));
 
+    mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
+    mGearMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onGearMenuClick, this));
+
+    mSortingMenuButton = getChild<LLMenuButton>("sorting_menu_btn");
+    mSortingMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onSortingMenuClick, this));
+
+    mAddMenuButton = getChild<LLMenuButton>("add_menu_btn");
+    mAddMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onAddMenuClick, this));
+
+    mRemoveSelectedBtn = getChild<LLButton>("trash_btn");
+    mRemoveSelectedBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onRemoveButtonClicked, this));
+
+    LLDragAndDropButton* trash_btn = (LLDragAndDropButton*)mRemoveSelectedBtn;
+    trash_btn->setDragAndDropHandler(boost::bind(&LLPanelPlaces::handleDragAndDropToTrash, this
+        , _4 // BOOL drop
+        , _5 // EDragAndDropType cargo_type
+        , _6 // void* cargo_data
+        , _7 // EAcceptance* accept
+    ));
+
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 	registrar.add("Places.OverflowMenu.Action",  boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2));
 	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
@@ -629,6 +650,12 @@ void LLPanelPlaces::onTabSelected()
 
 	onFilterEdit(mActivePanel->getFilterSubString(), true);
 	mActivePanel->updateVerbs();
+
+    // History panel does not support deletion nor creation
+    // Hide menus
+    bool supports_create = mActivePanel->getCreateMenu() != NULL;
+    childSetVisible("add_btn_panel", supports_create);
+    childSetVisible("trash_btn_panel", supports_create);
 }
 
 void LLPanelPlaces::onTeleportButtonClicked()
@@ -998,6 +1025,50 @@ void LLPanelPlaces::onBackButtonClicked()
 	updateVerbs();
 }
 
+void LLPanelPlaces::onGearMenuClick()
+{
+    if (mActivePanel)
+    {
+        LLToggleableMenu* menu = mActivePanel->getSelectionMenu();
+        mGearMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT);
+    }
+}
+
+void LLPanelPlaces::onSortingMenuClick()
+{
+    if (mActivePanel)
+    {
+        LLToggleableMenu* menu = mActivePanel->getSortingMenu();
+        mSortingMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT);
+    }
+}
+
+void LLPanelPlaces::onAddMenuClick()
+{
+    if (mActivePanel)
+    {
+        LLToggleableMenu* menu = mActivePanel->getCreateMenu();
+        mAddMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT);
+    }
+}
+
+void LLPanelPlaces::onRemoveButtonClicked()
+{
+    if (mActivePanel)
+    {
+        mActivePanel->onRemoveSelected();
+    }
+}
+
+bool LLPanelPlaces::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept)
+{
+    if (mActivePanel)
+    {
+        return mActivePanel->handleDragAndDropToTrash(drop, cargo_type, cargo_data, accept);
+    }
+    return false;
+}
+
 void LLPanelPlaces::togglePickPanel(BOOL visible)
 {
 	if (mPickPanel)
@@ -1168,9 +1239,17 @@ void LLPanelPlaces::createTabs()
 
 	mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
 
-	// Filter applied to show all items.
-	if (mActivePanel)
-		mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
+    if (mActivePanel)
+    {
+        // Filter applied to show all items.
+        mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
+
+        // History panel does not support deletion nor creation
+        // Hide menus
+        bool supports_create = mActivePanel->getCreateMenu() != NULL;
+        childSetVisible("add_btn_panel", supports_create);
+        childSetVisible("trash_btn_panel", supports_create);
+    }
 
 	mTabsCreated = true;
 }
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 978b030b2e..610ee283c8 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -97,6 +97,12 @@ private:
 	void onCreateLandmarkButtonClicked(const LLUUID& folder_id);
 	void onBackButtonClicked();
 	void onProfileButtonClicked();
+    void onGearMenuClick();
+    void onSortingMenuClick();
+    void onAddMenuClick();
+    void onRemoveButtonClicked();
+    bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept);
+
 
 	void toggleMediaPanel();
 	void togglePickPanel(BOOL visible);
@@ -127,6 +133,12 @@ private:
 	LLMenuButton*				mOverflowBtn;
 	LLButton*					mPlaceInfoBtn;
 
+    // Top menu
+    LLMenuButton*				mGearMenuButton;
+    LLMenuButton*				mSortingMenuButton;
+    LLMenuButton*				mAddMenuButton;
+    LLButton*					mRemoveSelectedBtn;
+
 	LLPlacesInventoryObserver*	mInventoryObserver;
 	LLPlacesParcelObserver*		mParcelObserver;
 	LLRemoteParcelInfoObserver* mRemoteParcelObserver;
diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h
index 367ce46e2e..6c9a6e9da7 100644
--- a/indra/newview/llpanelplacestab.h
+++ b/indra/newview/llpanelplacestab.h
@@ -30,6 +30,7 @@
 #include "llpanel.h"
 
 class LLPanelPlaces;
+class LLToggleableMenu;
 
 class LLPanelPlacesTab : public LLPanel
 {
@@ -42,8 +43,19 @@ public:
 	virtual void onShowOnMap() = 0;
 	virtual void onShowProfile() = 0;
 	virtual void onTeleport() = 0;
+	virtual void onRemoveSelected() = 0;
 	virtual bool isSingleItemSelected() = 0;
 
+    // returns menu for current selection
+    virtual LLToggleableMenu* getSelectionMenu() = 0;
+    virtual LLToggleableMenu* getSortingMenu() = 0;
+    virtual LLToggleableMenu* getCreateMenu() = 0;
+
+    /**
+    * Processes drag-n-drop of the Landmarks and folders into trash button.
+    */
+    virtual bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) = 0;
+
 	bool isTabVisible(); // Check if parent TabContainer is visible.
 
 	void setPanelPlacesButtons(LLPanelPlaces* panel);
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 3f5664f431..812ddf874e 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -56,7 +56,7 @@ static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
 class LLTeleportHistoryFlatItem : public LLPanel
 {
 public:
-	LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name,
+	LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
 										 	 LLDate date, const std::string &hl);
 	virtual ~LLTeleportHistoryFlatItem();
 
@@ -86,12 +86,13 @@ public:
 
 private:
 	void onProfileBtnClick();
+    void showMenu(S32 x, S32 y);
 
 	LLButton* mProfileBtn;
 	LLTextBox* mTitle;
 	LLTextBox* mTimeTextBox;
 	
-	LLTeleportHistoryPanel::ContextMenu *mContextMenu;
+	LLToggleableMenu *mMenu;
 
 	S32 mIndex;
 	std::string mRegionName;
@@ -112,7 +113,7 @@ protected:
 
 public:
 	LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
-		LLTeleportHistoryPanel::ContextMenu *context_menu,
+		LLToggleableMenu *menu,
 		const LLTeleportHistoryPersistentItem& persistent_item,
 		const S32 cur_item_index,
 		const std::string &hl);
@@ -130,16 +131,16 @@ private:
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
-LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name,
+LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
 																LLDate date, const std::string &hl)
 :	LLPanel(),
 	mIndex(index),
-	mContextMenu(context_menu),
+	mMenu(menu),
 	mRegionName(region_name),
 	mDate(date),
 	mHighlight(hl)
 {
-	buildFromFile( "panel_teleport_history_item.xml");
+	buildFromFile("panel_teleport_history_item.xml");
 }
 
 LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
@@ -266,10 +267,9 @@ void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
 // virtual
 BOOL LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	if (mContextMenu)
-		mContextMenu->show(this, mIndex, x, y);
-
-	return LLPanel::handleRightMouseDown(x, y, mask);
+    LLPanel::handleRightMouseDown(x, y, mask);
+	showMenu(x, y);
+    return TRUE;
 }
 
 void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
@@ -286,13 +286,23 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick()
 	LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
 }
 
+void LLTeleportHistoryFlatItem::showMenu(S32 x, S32 y)
+{
+    mMenu->setButtonRect(this);
+    mMenu->buildDrawLabels();
+    mMenu->arrangeAndClear();
+    mMenu->updateParent(LLMenuGL::sMenuContainer);
+
+    LLMenuGL::showPopup(this, mMenu, x, y);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
 LLTeleportHistoryFlatItem*
 LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
-	LLTeleportHistoryPanel::ContextMenu *context_menu,
+	LLToggleableMenu *menu,
 	const LLTeleportHistoryPersistentItem& persistent_item,
 	const S32 cur_item_index,
 	const std::string &hl)
@@ -321,7 +331,7 @@ LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
 	if ( !item )
 	{
 		item = new LLTeleportHistoryFlatItem(cur_item_index,
-											 context_menu,
+											 menu,
 											 persistent_item.mTitle,
 											 persistent_item.mDate,
 											 hl);
@@ -365,78 +375,6 @@ void LLTeleportHistoryFlatItemStorage::purge()
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
-LLTeleportHistoryPanel::ContextMenu::ContextMenu() :
-	mMenu(NULL), mIndex(0)
-{
-}
-
-void LLTeleportHistoryPanel::ContextMenu::show(LLView* spawning_view, S32 index, S32 x, S32 y)
-{
-	if (mMenu)
-	{
-		//preventing parent (menu holder) from deleting already "dead" context menus on exit
-		LLView* parent = mMenu->getParent();
-		if (parent)
-		{
-			parent->removeChild(mMenu);
-		}
-		delete mMenu;
-	}
-
-	mIndex = index;
-	mMenu = createMenu();
-
-	mMenu->show(x, y);
-	LLMenuGL::showPopup(spawning_view, mMenu, x, y);
-}
-
-LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
-{
-	// set up the callbacks for all of the avatar menu items
-	// (N.B. callbacks don't take const refs as mID is local scope)
-	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
-	registrar.add("TeleportHistory.Action", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onUserAction, this, _2));
-
-	// create the context menu from the XUI
-	llassert(LLMenuGL::sMenuContainer != NULL);
-	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
-		"menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
-}
-
-void LLTeleportHistoryPanel::ContextMenu::onUserAction(const LLSD& userdata)
-{
-    std::string command_name = userdata.asString();
-    if ("teleport" == command_name)
-    {
-        confirmTeleport(mIndex);
-    }
-    else if ("view" == command_name)
-    {
-        LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
-    }
-    else if ("show_on_map" == command_name)
-    {
-        LLTeleportHistoryStorage::getInstance()->showItemOnMap(mIndex);
-    }
-    else if ("copy_slurl" == command_name)
-    {
-        LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
-        LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
-            boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
-    }
-}
-
-//static
-void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl)
-{
-	LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size());
-
-	LLSD args;
-	args["SLURL"] = slurl;
-
-	LLNotificationsUtil::add("CopySLURL", args);
-}
 
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
@@ -450,7 +388,8 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
 		mAccordionTabMenu(NULL),
 		mLastSelectedFlatlList(NULL),
 		mLastSelectedItemIndex(-1),
-		mMenuGearButton(NULL)
+		mGearItemMenu(NULL),
+		mSortingMenu(NULL)
 {
 	buildFromFile( "panel_teleport_history.xml");
 }
@@ -458,12 +397,19 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
 LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
 {
 	LLTeleportHistoryFlatItemStorage::instance().purge();
-	if (mGearMenuHandle.get()) mGearMenuHandle.get()->die();
 	mTeleportHistoryChangedConnection.disconnect();
 }
 
 BOOL LLTeleportHistoryPanel::postBuild()
 {
+    mCommitCallbackRegistrar.add("TeleportHistory.GearMenu.Action", boost::bind(&LLTeleportHistoryPanel::onGearMenuAction, this, _2));
+    mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
+
+    // init menus before list, since menus are passed to list
+    mGearItemMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_item.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+    mGearItemMenu->setAlwaysShowMenu(TRUE); // all items can be disabled if nothing is selected, show anyway
+    mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
 	mTeleportHistory = LLTeleportHistoryStorage::getInstance();
 	if (mTeleportHistory)
 	{
@@ -515,22 +461,6 @@ BOOL LLTeleportHistoryPanel::postBuild()
 		}
 	}
 
-	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
-	registrar.add("TeleportHistory.ExpandAllFolders",  boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders,  this));
-	registrar.add("TeleportHistory.CollapseAllFolders",  boost::bind(&LLTeleportHistoryPanel::onCollapseAllFolders,  this));
-	registrar.add("TeleportHistory.ClearTeleportHistory",  boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory,  this));
-	mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
-
-	mMenuGearButton = getChild<LLMenuButton>("gear_btn");
-
-	LLToggleableMenu* gear_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());;
-	if(gear_menu)
-	{
-		mGearMenuHandle  = gear_menu->getHandle();
-		mMenuGearButton->setMenu(gear_menu);
-	}
-
 	return TRUE;
 }
 
@@ -649,6 +579,24 @@ void LLTeleportHistoryPanel::updateVerbs()
 	mShowOnMapBtn->setEnabled(NULL != itemp);
 }
 
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getSelectionMenu()
+{
+    return mGearItemMenu;
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getSortingMenu()
+{
+    return mSortingMenu;
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getCreateMenu()
+{
+    return NULL;
+}
+
 void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
 {
 	const U32 seconds_in_day = 24 * 60 * 60;
@@ -782,7 +730,7 @@ void LLTeleportHistoryPanel::refresh()
 		{
 			LLTeleportHistoryFlatItem* item =
 				LLTeleportHistoryFlatItemStorage::instance()
-				.getFlatItemForPersistentItem(&mContextMenu,
+				.getFlatItemForPersistentItem(mGearItemMenu,
 											  items[mCurrentItem],
 											  mCurrentItem,
 											  filter_string);
@@ -851,7 +799,7 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
 
 	const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
 	LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
-		.getFlatItemForPersistentItem(&mContextMenu,
+		.getFlatItemForPersistentItem(mGearItemMenu,
 									  history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
 									  history_items.size(), // index will be decremented inside loop below
 									  sFilterSubString);
@@ -1023,38 +971,6 @@ void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab)
 	mHistoryAccordion->arrange();
 }
 
-void LLTeleportHistoryPanel::onExpandAllFolders()
-{
-	S32 tabs_cnt = mItemContainers.size();
-
-	for (S32 n = 0; n < tabs_cnt; n++)
-	{
-		mItemContainers.at(n)->setDisplayChildren(true);
-	}
-	mHistoryAccordion->arrange();
-}
-
-void LLTeleportHistoryPanel::onCollapseAllFolders()
-{
-	S32 tabs_cnt = mItemContainers.size();
-
-	for (S32 n = 0; n < tabs_cnt; n++)
-	{
-		mItemContainers.at(n)->setDisplayChildren(false);
-	}
-	mHistoryAccordion->arrange();
-
-	if (mLastSelectedFlatlList)
-	{
-		mLastSelectedFlatlList->resetSelection();
-	}
-}
-
-void LLTeleportHistoryPanel::onClearTeleportHistory()
-{
-	LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
-}
-
 bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response)
 {
 
@@ -1086,45 +1002,141 @@ LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTa
 	return NULL;
 }
 
-bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
+void LLTeleportHistoryPanel::gotSLURLCallback(const std::string& slurl)
 {
-	S32 tabs_cnt = mItemContainers.size();
+    LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, slurl.size());
 
-	bool has_expanded_tabs = false;
-	bool has_collapsed_tabs = false;
+    LLSD args;
+    args["SLURL"] = slurl;
 
-	for (S32 n = 0; n < tabs_cnt; n++)
-	{
-		LLAccordionCtrlTab* tab = mItemContainers.at(n);
-		if (!tab->getVisible())
-			continue;
+    LLNotificationsUtil::add("CopySLURL", args);
+}
 
-		if (tab->getDisplayChildren())
-		{
-			has_expanded_tabs = true;
-		}
-		else
-		{
-			has_collapsed_tabs = true;
-		}
+void LLTeleportHistoryPanel::onGearMenuAction(const LLSD& userdata)
+{
+    std::string command_name = userdata.asString();
 
-		if (has_expanded_tabs && has_collapsed_tabs)
-		{
-			break;
-		}
-	}
+    if ("expand_all" == command_name)
+    {
+        S32 tabs_cnt = mItemContainers.size();
 
-	std::string command_name = userdata.asString();
+        for (S32 n = 0; n < tabs_cnt; n++)
+        {
+            mItemContainers.at(n)->setDisplayChildren(true);
+        }
+        mHistoryAccordion->arrange();
+    }
+    else if ("collapse_all" == command_name)
+    {
+        S32 tabs_cnt = mItemContainers.size();
+
+        for (S32 n = 0; n < tabs_cnt; n++)
+        {
+            mItemContainers.at(n)->setDisplayChildren(false);
+        }
+        mHistoryAccordion->arrange();
+
+        if (mLastSelectedFlatlList)
+        {
+            mLastSelectedFlatlList->resetSelection();
+        }
+    }
+    else if ("clear_history" == command_name)
+    {
+        LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
+    }
 
-	if (has_expanded_tabs && command_name == "collapse_all")
-	{
-		return true;
-	}
+    S32 index = -1;
+    if (mLastSelectedFlatlList)
+    {
+        LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+        if (itemp)
+        {
+            index = itemp->getIndex();
+        }
+    }
 
-	if (has_collapsed_tabs && command_name ==  "expand_all")
-	{
-		return true;
-	}
+    if ("teleport" == command_name)
+    {
+        confirmTeleport(index);
+    }
+    else if ("view" == command_name)
+    {
+        LLTeleportHistoryFlatItem::showPlaceInfoPanel(index);
+    }
+    else if ("show_on_map" == command_name)
+    {
+        LLTeleportHistoryStorage::getInstance()->showItemOnMap(index);
+    }
+    else if ("copy_slurl" == command_name)
+    {
+        LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[index].mGlobalPos;
+        LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
+            boost::bind(&LLTeleportHistoryPanel::gotSLURLCallback, _1));
+    }
+}
+
+bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
+{
+    std::string command_name = userdata.asString();
+
+    if (command_name == "collapse_all"
+        || command_name == "expand_all")
+    {
+        S32 tabs_cnt = mItemContainers.size();
+
+        bool has_expanded_tabs = false;
+        bool has_collapsed_tabs = false;
+
+        for (S32 n = 0; n < tabs_cnt; n++)
+        {
+            LLAccordionCtrlTab* tab = mItemContainers.at(n);
+            if (!tab->getVisible())
+                continue;
+
+            if (tab->getDisplayChildren())
+            {
+                has_expanded_tabs = true;
+            }
+            else
+            {
+                has_collapsed_tabs = true;
+            }
+
+            if (has_expanded_tabs && has_collapsed_tabs)
+            {
+                break;
+            }
+        }
+
+        if (command_name == "collapse_all")
+        {
+            return has_expanded_tabs;
+        }
+
+        if (command_name == "expand_all")
+        {
+            return has_collapsed_tabs;
+        }
+    }
+
+    if (command_name == "clear_history")
+    {
+        return mTeleportHistory->getItems().size() > 0;
+    }
+    
+    if ("teleport" == command_name
+        || "view" == command_name
+        || "show_on_map" == command_name
+        || "copy_slurl" == command_name)
+    {
+        if (!mLastSelectedFlatlList)
+        {
+            return false;
+        }
+        LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+        return itemp != NULL;
+    }
 
 	return false;
 }
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index e0abbc47db..241a2e9509 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -43,36 +43,26 @@ class LLMenuButton;
 class LLTeleportHistoryPanel : public LLPanelPlacesTab
 {
 public:
-	// *TODO: derive from LLListContextMenu?
-	class ContextMenu
-	{
-	public:
-		ContextMenu();
-		void show(LLView* spawning_view, S32 index, S32 x, S32 y);
-
-	private:
-		LLContextMenu* createMenu();
-		void onUserAction(const LLSD& userdata);
-
-		static void gotSLURLCallback(const std::string& slurl);
-
-		LLContextMenu* mMenu;
-		S32 mIndex;
-	};
-
 	LLTeleportHistoryPanel();
 	virtual ~LLTeleportHistoryPanel();
 
-	/*virtual*/ BOOL postBuild();
-	/*virtual*/ void draw();
+    BOOL postBuild() override;
+    void draw() override;
 
-	/*virtual*/ void onSearchEdit(const std::string& string);
-	/*virtual*/ void onShowOnMap();
-	/*virtual*/ void onShowProfile();
-	/*virtual*/ void onTeleport();
-	///*virtual*/ void onCopySLURL();
-	/*virtual*/ void updateVerbs();
-	/*virtual*/ bool isSingleItemSelected();
+    void onSearchEdit(const std::string& string) override;
+    void onShowOnMap() override;
+    void onShowProfile() override;
+    void onTeleport() override;
+    ///*virtual*/ void onCopySLURL();
+    void onRemoveSelected() override {};
+    void updateVerbs() override;
+    bool isSingleItemSelected() override;
+
+    LLToggleableMenu* getSelectionMenu() override;
+    LLToggleableMenu* getSortingMenu() override;
+    LLToggleableMenu* getCreateMenu() override;
+
+    bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override { return false; }
 
 private:
 
@@ -93,6 +83,8 @@ private:
 	void showTeleportHistory();
 	void handleItemSelect(LLFlatListView* );
 	LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);
+	static void gotSLURLCallback(const std::string& slurl);
+	void onGearMenuAction(const LLSD& userdata);
 	bool isActionEnabled(const LLSD& userdata) const;
 
 	void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
@@ -113,10 +105,10 @@ private:
 	typedef std::vector<LLAccordionCtrlTab*> item_containers_t;
 	item_containers_t mItemContainers;
 
-	ContextMenu mContextMenu;
 	LLContextMenu*			mAccordionTabMenu;
-	LLHandle<LLView>		mGearMenuHandle;
-	LLMenuButton*			mMenuGearButton;
+
+    LLToggleableMenu*			mGearItemMenu;
+    LLToggleableMenu*			mSortingMenu;
 
 	boost::signals2::connection mTeleportHistoryChangedConnection;
 };
diff --git a/indra/newview/skins/default/xui/en/menu_place_add_button.xml b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
index e3a39a1242..ad49f7c3a8 100644
--- a/indra/newview/skins/default/xui/en/menu_place_add_button.xml
+++ b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
@@ -1,27 +1,30 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
  layout="topleft"
  left="0"
  mouse_opaque="false"
- name="menu_folder_gear"
+ name="menu_create"
  visible="false">
     <menu_item_call
-     label="Add Folder"
+     label="Landmark current location"
      layout="topleft"
-     name="add_folder">
+     name="add_landmark">
         <on_click
          function="Places.LandmarksGear.Add.Action"
-         parameter="category" />
+         parameter="add_landmark_root" />
         <on_enable
          function="Places.LandmarksGear.Enable"
-         parameter="category" />
+         parameter="add_landmark_root" />
     </menu_item_call>
     <menu_item_call
-     label="Add Landmark"
+     label="Create folder"
      layout="topleft"
-     name="add_landmark">
+     name="add_folder">
         <on_click
          function="Places.LandmarksGear.Add.Action"
-         parameter="add_landmark" />
+         parameter="category_root" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="category_root" />
     </menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index eb76f58722..df1139c98f 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -123,37 +123,4 @@
          function="Places.LandmarksGear.Enable"
          parameter="collapse" />
     </menu_item_call>
-    <menu_item_call
-     label="Expand all folders"
-     layout="topleft"
-     name="expand_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="expand_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="expand_all" />
-    </menu_item_call>
-    <menu_item_call
-     label="Collapse all folders"
-     layout="topleft"
-     name="collapse_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="collapse_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="collapse_all" />
-    </menu_item_call>
-    <menu_item_check
-     label="Sort by Date"
-     layout="topleft"
-     name="sort_by_date">
-        <on_check
-         function="Places.LandmarksGear.Check"
-         parameter="sort_by_date" />
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="sort_by_date" />
-    </menu_item_check>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
index b8249b621b..7a7edc0ab7 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -134,42 +134,4 @@
          function="Places.LandmarksGear.Enable"
          parameter="delete" />
     </menu_item_call>
-    <menu_item_separator
-     layout="topleft" />
-    <menu_item_call
-     label="Expand all folders"
-     layout="topleft"
-     name="expand_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="expand_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="expand_all" />
-    </menu_item_call>
-    <menu_item_call
-     label="Collapse all folders"
-     layout="topleft"
-     name="collapse_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="collapse_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="collapse_all" />
-    </menu_item_call>
-    <menu_item_check
-     label="Sort by Date"
-     layout="topleft"
-     name="sort_by_date">
-        <on_check
-         function="Places.LandmarksGear.Check"
-         parameter="sort_by_date" />
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="sort_by_date" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="sort_by_date" />
-    </menu_item_check>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml b/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
new file mode 100644
index 0000000000..6548fadfa5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_sorter_gear"
+ visible="false">
+    <menu_item_call
+     label="Expand all folders"
+     layout="topleft"
+     name="expand_all">
+        <on_click
+         function="Places.LandmarksGear.Folding.Action"
+         parameter="expand_all" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="expand_all" />
+    </menu_item_call>
+    <menu_item_call
+     label="Collapse all folders"
+     layout="topleft"
+     name="collapse_all">
+        <on_click
+         function="Places.LandmarksGear.Folding.Action"
+         parameter="collapse_all" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="collapse_all" />
+    </menu_item_call>
+    <menu_item_separator
+     layout="topleft" />
+    <menu_item_check
+     label="Sort by Date"
+     layout="topleft"
+     name="sort_by_date">
+        <on_check
+         function="Places.LandmarksGear.Check"
+         parameter="sort_by_date" />
+        <on_click
+         function="Places.LandmarksGear.Folding.Action"
+         parameter="sort_by_date" />
+    </menu_item_check>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
index bc7d4fe33b..0b75fd781a 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
@@ -12,7 +12,8 @@
      label="Expand all folders"
      name="Expand all folders">
         <menu_item_call.on_click
-         function="TeleportHistory.ExpandAllFolders" />
+         function="TeleportHistory.GearMenu.Action"
+         parameter="expand_all" />
         <on_enable
          function="TeleportHistory.GearMenu.Enable"
          parameter="expand_all" />
@@ -21,7 +22,8 @@
      label="Collapse all folders"
      name="Collapse all folders">
         <menu_item_call.on_click
-         function="TeleportHistory.CollapseAllFolders" />
+         function="TeleportHistory.GearMenu.Action"
+         parameter="collapse_all" />
         <on_enable
          function="TeleportHistory.GearMenu.Enable"
          parameter="collapse_all" />
@@ -31,6 +33,10 @@
      label="Clear Teleport History"
      name="Clear Teleport History">
         <menu_item_call.on_click
-         function="TeleportHistory.ClearTeleportHistory" />
+         function="TeleportHistory.GearMenu.Action"
+         parameter="clear_history" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
+         parameter="clear_history" />
     </menu_item_call>    
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index 52da591e35..153e5a70a9 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -1,37 +1,52 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<context_menu
+<toggleable_menu
+ name="Teleport History Item Menu"
  layout="topleft"
- name="Teleport History Item Context Menu">
+ left="0"
+ mouse_opaque="false"
+ visible="false">
     <menu_item_call
      label="Teleport"
      layout="topleft"
      name="Teleport">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="teleport" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="teleport" />
     </menu_item_call>
     <menu_item_call
      label="View"
      layout="topleft"
      name="More Information">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="view" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="view" />
     </menu_item_call>
     <menu_item_call
      label="Show on map"
      layout="topleft"
      name="show_on_map">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="show_on_map" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="show_on_map" />
     </menu_item_call>
     <menu_item_call
      label="Copy SLurl"
      layout="topleft"
      name="CopyToClipboard">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="copy_slurl" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="copy_slurl" />
     </menu_item_call>
-</context_menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index 67a09949ce..af2115156e 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -16,7 +16,7 @@
      bg_alpha_color="DkGray2"
      bg_opaque_color="DkGray2"
      follows="all"
-     height="373"
+     height="398"
      layout="topleft"
      left="3"
      name="landmarks_accordion"
@@ -95,104 +95,4 @@
              width="313"/>
         </accordion_tab>
     </accordion>
-    <panel
-       background_visible="true"
-     bevel_style="none"
-     bottom="0"
-     follows="left|right|bottom"
-     height="27"
-     layout="bottomleft"
-     left="3"
-     name="bottom_panel"
-     width="313">
-     	
-     	  <layout_stack
-		   animate="false"
-		   border_size="0"
-		   follows="left|right|bottom"
-		   height="25"
-		   layout="topleft"
-		   orientation="horizontal"
-		   top_pad="1"
-		   left="0"
-		   name="bottom_panel"
-		   width="307">
-		      <layout_panel
-		       auto_resize="false"
-		       height="25"
-		       layout="topleft"
-		       name="options_gear_btn_panel"
-		       width="32">
-		          <menu_button
-		           follows="bottom|left"
-		           tool_tip="Show additional options"
-		           height="25"
-		           image_hover_unselected="Toolbar_Left_Over"
-		           image_overlay="OptionsMenu_Off"
-		           image_selected="Toolbar_Left_Selected"
-		           image_unselected="Toolbar_Left_Off"
-		           layout="topleft"
-		           left="0"
-		           name="options_gear_btn"
-		           top="0"
-		           width="31" />
-		      </layout_panel>
-		      <layout_panel
-		       auto_resize="false"
-		       height="25"
-		       layout="topleft"
-		       name="add_btn_panel"
-		       width="32">
-		          <button
-		           follows="bottom|left"
-		           height="25"
-		           image_hover_unselected="Toolbar_Middle_Over"
-		           image_overlay="AddItem_Off"
-		           image_selected="Toolbar_Middle_Selected"
-		           image_unselected="Toolbar_Middle_Off"
-		           layout="topleft"
-		           left="0"
-		           name="add_btn"
-		           tool_tip="Add new landmark"
-		           top="0"
-		           width="31" />
-		      </layout_panel>
-		      <layout_panel
-		       auto_resize="true"
-		       height="25"
-		       layout="topleft"
-		       name="dummy_panel"
-		       width="212">
-		          <icon
-		           follows="bottom|left|right"
-		           height="25"
-		           image_name="Toolbar_Middle_Off"
-		           layout="topleft"
-		           left="0"
-		           top="0"
-		           name="dummy_icon"
-		           width="211" />
-		      </layout_panel>
-		      <layout_panel
-		       auto_resize="false"
-		       height="25"
-		       layout="topleft"
-		       name="trash_btn_panel"
-		       width="31">
-		          <dnd_button
-		           follows="bottom|left"
-		           height="25"
-		           image_hover_unselected="Toolbar_Right_Over"
-		           image_overlay="TrashItem_Off"
-		           image_selected="Toolbar_Right_Selected"
-		           image_unselected="Toolbar_Right_Off"
-		           left="0"
-		           layout="topleft"
-		           name="trash_btn"
-		           tool_tip="Remove selected landmark"
-		           top="0"
-		           width="31"/>
-		      </layout_panel>
-  	</layout_stack>
-   </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 1f32ae53ba..75becf6b15 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -17,19 +17,121 @@ background_visible="true"
     <string
      name="teleport_history_tab_title"
      value="TELEPORT HISTORY" />
-    <filter_editor
-     text_pad_left="10"
-     follows="left|top|right"
-     font="SansSerifSmall"
-     height="23"
-     layout="topleft"
-     left="10"
-     label="Filter My Places"
-     max_length_chars="300"
-     name="Filter"
-     tab_group="1"
-     top="3"
-     width="303" />
+    <layout_stack
+      animate="false"
+      border_size="0"
+      follows="left|top|right"
+      height="25"
+      layout="topleft"
+      orientation="horizontal"
+      top_pad="1"
+      left="0"
+      name="bottom_panel"
+      width="320">
+      <layout_panel
+        auto_resize="true"
+        height="25"
+        layout="topleft"
+        name="filter_panel"
+        width="193">
+        <filter_editor
+          text_pad_left="10"
+          follows="left|top|right"
+          font="SansSerifSmall"
+          height="23"
+          layout="topleft"
+          left="10"
+          label="Filter My Places"
+          max_length_chars="300"
+          name="Filter"
+          tab_group="1"
+          top="3"
+          width="181" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="options_gear_btn_panel"
+        width="32">
+        <menu_button
+          follows="bottom|left"
+          tool_tip="Show options"
+          height="25"
+          image_hover_unselected="Toolbar_Middle_Over"
+          image_overlay="OptionsMenu_Off"
+          image_selected="Toolbar_Middle_Selected"
+          image_unselected="Toolbar_Middle_Off"
+          menu_position="bottomleft"
+          layout="topleft"
+          left="0"
+          name="options_gear_btn"
+          top="0"
+          width="31" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="options_sort_btn_panel"
+        width="32">
+        <menu_button
+          follows="bottom|left"
+          tool_tip="Show sorting options"
+          height="25"
+          image_hover_unselected="Toolbar_Middle_Over"
+          image_overlay="Conv_toolbar_sort"
+          image_selected="Toolbar_Middle_Selected"
+          image_unselected="Toolbar_Middle_Off"
+          menu_position="bottomleft"
+          layout="topleft"
+          left="0"
+          name="sorting_menu_btn"
+          top="0"
+          width="31" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="add_btn_panel"
+        width="32">
+        <menu_button
+          follows="bottom|left"
+          height="25"
+          image_hover_unselected="Toolbar_Middle_Over"
+          image_overlay="AddItem_Off"
+          image_selected="Toolbar_Middle_Selected"
+          image_unselected="Toolbar_Middle_Off"
+          menu_position="bottomleft"
+          layout="topleft"
+          left="0"
+          name="add_menu_btn"
+          tool_tip="Add new landmark or folder"
+          top="0"
+          width="31" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="trash_btn_panel"
+        width="31">
+        <dnd_button
+          follows="bottom|left"
+          height="25"
+          image_hover_unselected="Toolbar_Right_Over"
+          image_overlay="TrashItem_Off"
+          image_selected="Toolbar_Right_Selected"
+          image_unselected="Toolbar_Right_Off"
+          left="0"
+          layout="topleft"
+          name="trash_btn"
+          tool_tip="Remove selected landmark or folder"
+          top="0"
+          width="31"/>
+      </layout_panel>
+    </layout_stack>
     <tab_container
      follows="all"
      halign="center"
@@ -265,6 +367,7 @@ background_visible="true"
 		
 		<layout_stack
      	follows="bottom|left|right"
+      animate="false"
 		height="23"
 		layout="topleft"
 		mouse_opaque="false"
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
index 768efc2f3f..55c47c90a4 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -6,7 +6,7 @@
      bg_alpha_color="DkGray">     
     <accordion
      follows="left|top|right|bottom"
-     height="373"
+     height="400"
      layout="topleft"
      left="3"
      top="0"
@@ -147,37 +147,4 @@
 	        </flat_list_view>
 	    </accordion_tab>
     </accordion>
-    <panel
-     background_visible="true"
-     bevel_style="none"
-     bottom="0"
-     follows="left|right|bottom"
-     height="27"
-     layout="bottomleft"
-     left="3"
-     name="bottom_panel"
-     width="313">
-        <menu_button
-         follows="bottom|left"
-         tool_tip="Show additional options"
-         height="25"
-         image_hover_unselected="Toolbar_Left_Over"
-         image_overlay="OptionsMenu_Off"
-         image_selected="Toolbar_Left_Selected"
-         image_unselected="Toolbar_Left_Off"
-         layout="topleft"
-         left="0"
-         name="gear_btn"
-         top="1"
-         width="31" />
-        <icon
-         follows="bottom|left|right"
-         height="25"
-         image_name="Toolbar_Right_Off"
-         layout="topleft"
-         left_pad="1"
-         name="dummy_icon"
-         width="273"
-        />
-    </panel>
 </panel>
-- 
cgit v1.2.3


From 05aeeedfb9171ca95c0a3400f9704b146dcd2b1c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 24 Feb 2021 11:10:25 +0200
Subject: SL-14842 Mac build fix

---
 indra/newview/llpanelteleporthistory.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index 241a2e9509..f76dc139bd 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -76,7 +76,7 @@ private:
 	void onClearTeleportHistory();
 	bool onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response);
 
-	void refresh();
+	void refresh() override;
 	void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date);
 	void onTeleportHistoryChange(S32 removed_index);
 	void replaceItem(S32 removed_index);
-- 
cgit v1.2.3


From 02036560a68fc2da6f463320b9572714cbe22916 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 24 Feb 2021 22:32:42 +0200
Subject: SL-14842 Apply toolstrip layout to Places floater Part #2

Hide buttons
---
 indra/newview/llpanelplaces.cpp                    | 15 ++---
 indra/newview/llpanelplaces.h                      |  3 +
 .../skins/default/xui/en/panel_landmark_info.xml   |  4 +-
 .../skins/default/xui/en/panel_place_profile.xml   |  2 +-
 .../newview/skins/default/xui/en/panel_places.xml  | 69 +++++++++++++++-------
 5 files changed, 60 insertions(+), 33 deletions(-)

diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 00752d5a25..2a08a1b40d 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -345,6 +345,10 @@ BOOL LLPanelPlaces::postBuild()
 		mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this));
 	}
 
+    mButtonsContainer = getChild<LLPanel>("button_layout_panel");
+    mButtonsContainer->setVisible(FALSE);
+    mFilterContainer = getChild<LLLayoutStack>("top_menu_panel");
+
 	mFilterEditor = getChild<LLFilterEditor>("Filter");
 	if (mFilterEditor)
 	{
@@ -1085,8 +1089,9 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
 	if (!mPlaceProfile || !mLandmarkInfo)
 		return;
 
-	mFilterEditor->setVisible(!visible);
 	mTabContainer->setVisible(!visible);
+	mButtonsContainer->setVisible(visible);
+	mFilterContainer->setVisible(!visible);
 
 	if (mPlaceInfoType == AGENT_INFO_TYPE ||
 		mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
@@ -1102,10 +1107,6 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
 			// to avoid text blinking.
 			mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL);
 
-			LLRect rect = getRect();
-			LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
-			mPlaceProfile->reshape(new_rect.getWidth(), new_rect.getHeight());
-
 			mLandmarkInfo->setVisible(FALSE);
 		}
 		else if (mPlaceInfoType == AGENT_INFO_TYPE)
@@ -1126,10 +1127,6 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
 		if (visible)
 		{
 			mLandmarkInfo->resetLocation();
-
-			LLRect rect = getRect();
-			LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
-			mLandmarkInfo->reshape(new_rect.getWidth(), new_rect.getHeight());
 		}
 		else
 		{
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 610ee283c8..576a0fb931 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -48,6 +48,7 @@ class LLRemoteParcelInfoObserver;
 class LLTabContainer;
 class LLToggleableMenu;
 class LLMenuButton;
+class LLLayoutStack;
 
 typedef std::pair<LLUUID, std::string>	folder_pair_t;
 
@@ -117,6 +118,8 @@ private:
 	LLFilterEditor*				mFilterEditor;
 	LLPanelPlacesTab*			mActivePanel;
 	LLTabContainer*				mTabContainer;
+	LLPanel*					mButtonsContainer;
+	LLLayoutStack*				mFilterContainer;
 	LLPanelPlaceProfile*		mPlaceProfile;
 	LLPanelLandmarkInfo*		mLandmarkInfo;
 
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index 7935d66aee..0101516792 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -91,7 +91,7 @@
      name="place_scroll"
      opaque="true"
      top_pad="10"
-     width="310">
+     width="331">
         <panel
          bg_alpha_color="DkGray2"
          follows="left|top|right"
@@ -282,7 +282,6 @@
                  enabled="false"
                  use_bg_color="true"
                  bg_color="DkGray0"
-                 parse_urls="false"
                  follows="left|top|right"
                  height="22"
                  layout="topleft"
@@ -290,7 +289,6 @@
                  name="title_value"
                  text_color="white"
                  top_pad="5"
-                 use_ellipses="true"
                  width="290" /> 
                 <line_editor
                  follows="left|top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index 36b7b0501b..57b8032312 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -196,7 +196,7 @@
      name="place_scroll"
      opaque="true"
      top_pad="10"
-     width="310">
+     width="331">
         <panel
          bg_alpha_color="DkGray2"
          follows="left|top|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 75becf6b15..56975288ae 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -11,12 +11,29 @@ background_visible="true"
  top="0"
  left="0"
  width="333">
-    <string
-     name="landmarks_tab_title"
-     value="MY LANDMARKS" />
-    <string
-     name="teleport_history_tab_title"
-     value="TELEPORT HISTORY" />
+  <string
+   name="landmarks_tab_title"
+   value="MY LANDMARKS" />
+  <string
+   name="teleport_history_tab_title"
+   value="PLACES VISITED" />
+  <layout_stack
+    animate="false"
+    border_size="0"
+    follows="all"
+    height="564"
+    layout="topleft"
+    orientation="vertical"
+    top="1"
+    left="0"
+    name="places_layout_panel"
+    width="333">
+    <layout_panel
+      auto_resize="true"
+      height="538"
+      layout="topleft"
+      name="main_panel"
+      width="333">
     <layout_stack
       animate="false"
       border_size="0"
@@ -24,9 +41,9 @@ background_visible="true"
       height="25"
       layout="topleft"
       orientation="horizontal"
-      top_pad="1"
+      top="0"
       left="0"
-      name="bottom_panel"
+      name="top_menu_panel"
       width="320">
       <layout_panel
         auto_resize="true"
@@ -134,9 +151,9 @@ background_visible="true"
     </layout_stack>
     <tab_container
      follows="all"
-     halign="center"
-     height="503"
      layout="topleft"
+     halign="center"
+     height="504"
      left="6"
      name="Places Tabs"
      tab_min_width="80"
@@ -144,40 +161,50 @@ background_visible="true"
      tab_height="30"
      tab_group="2"
      tab_position="top"
-     top_pad="10"
-     width="315" />
+     top_pad="9"
+     width="318"
+     visible="true"/>
     <panel
      class="panel_place_profile"
      filename="panel_place_profile.xml"
      follows="all"
-     height="533"
      layout="topleft"
+     height="533"
      left="0"
+     top="4"
      help_topic="place_profile"
      name="panel_place_profile"
-     top="5"
      visible="false"
-     width="315" />
+     width="318" />
     <panel
      class="panel_landmark_info"
      filename="panel_landmark_info.xml"
      follows="all"
-     height="533"
      layout="topleft"
+     height="533"
      left="0"
+     top="4"
      help_topic="landmark"
      name="panel_landmark_info"
-     top="5"
      visible="false"
-     width="315" />
+     width="318" />
+    </layout_panel>
+
+    <!--*********************** Button wrappers ***********************-->
+    <layout_panel
+     auto_resize="false"
+     layout="topleft"
+     height="25"
+     name="button_layout_panel">
     <panel
      follows="bottom|left|right"
      height="23"
      layout="topleft"
      left="4"
+     top="2"
      name="button_panel"
-     width="315">
-     
+     width="318">
+    
        <layout_stack
      	follows="bottom|left|right"
 		height="23"
@@ -422,4 +449,6 @@ background_visible="true"
 			</layout_panel>		
 		</layout_stack>
     </panel>
+    </layout_panel>
+  </layout_stack>
 </panel>
-- 
cgit v1.2.3


From 554ccd718131d469a7cde1e188d9ef0f712a6ed9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 24 Feb 2021 22:41:42 +0200
Subject: SL-14842 Apply toolstrip layout to Places floater Part #3

Removed unused buttons, moved some UI elements to be more in line with each other
---
 indra/newview/llpanellandmarks.cpp                 | 15 --------
 indra/newview/llpanelplaces.cpp                    | 18 ----------
 indra/newview/llpanelplaces.h                      |  2 --
 indra/newview/llpanelplacestab.cpp                 |  7 ----
 indra/newview/llpanelplacestab.h                   |  5 ---
 indra/newview/llpanelteleporthistory.cpp           |  9 -----
 .../skins/default/xui/en/panel_edit_pick.xml       |  8 ++---
 .../skins/default/xui/en/panel_landmark_info.xml   | 10 +++---
 .../skins/default/xui/en/panel_place_profile.xml   | 10 +++---
 .../newview/skins/default/xui/en/panel_places.xml  | 40 ++--------------------
 10 files changed, 16 insertions(+), 108 deletions(-)

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 3902c615a1..dfbdfad3bb 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -268,11 +268,6 @@ void LLLandmarksPanel::onShowOnMap()
 		return;
 	}
 
-	// Disable the "Map" button because loading landmark can take some time.
-	// During this time the button is useless. It will be enabled on callback finish
-	// or upon switching to other item.
-	mShowOnMapBtn->setEnabled(FALSE);
-
 	doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doShowOnMap, this, _1));
 }
 
@@ -357,15 +352,6 @@ void LLLandmarksPanel::updateVerbs()
 {
 	if (!isTabVisible()) 
 		return;
-
-	bool landmark_selected = isLandmarkSelected();
-	mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));
-	mShowProfile->setEnabled(landmark_selected && isActionEnabled("more_info"));
-	mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));
-
-	// TODO: mantipov: Uncomment when mShareBtn is supported
-	// Share button should be enabled when neither a folder nor a landmark is selected
-	//mShareBtn->setEnabled(NULL != current_item);
 }
 
 void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
@@ -1348,7 +1334,6 @@ void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)
 		LLFloaterReg::showInstance("world_map", "center");
 	}
 
-	mShowOnMapBtn->setEnabled(TRUE);
 	mGearLandmarkMenu->setItemEnabled("show_on_map", TRUE);
 }
 
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 2a08a1b40d..d56194e5b4 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -295,9 +295,6 @@ BOOL LLPanelPlaces::postBuild()
 	mOverflowBtn = getChild<LLMenuButton>("overflow_btn");
 	mOverflowBtn->setMouseDownCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
 
-	mPlaceInfoBtn = getChild<LLButton>("profile_btn");
-	mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this));
-
     mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
     mGearMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onGearMenuClick, this));
 
@@ -933,14 +930,6 @@ void LLPanelPlaces::onOverflowButtonClicked()
 	mOverflowBtn->setMenu(menu, LLMenuButton::MP_TOP_RIGHT);
 }
 
-void LLPanelPlaces::onProfileButtonClicked()
-{
-	if (!mActivePanel)
-		return;
-
-	mActivePanel->onShowProfile();
-}
-
 bool LLPanelPlaces::onOverflowMenuItemEnable(const LLSD& param)
 {
 	std::string value = param.asString();
@@ -1211,8 +1200,6 @@ void LLPanelPlaces::createTabs()
 	LLLandmarksPanel* landmarks_panel = new LLLandmarksPanel();
 	if (landmarks_panel)
 	{
-		landmarks_panel->setPanelPlacesButtons(this);
-
 		mTabContainer->addTabPanel(
 			LLTabContainer::TabPanelParams().
 			panel(landmarks_panel).
@@ -1223,8 +1210,6 @@ void LLPanelPlaces::createTabs()
 	LLTeleportHistoryPanel* teleport_history_panel = new LLTeleportHistoryPanel();
 	if (teleport_history_panel)
 	{
-		teleport_history_panel->setPanelPlacesButtons(this);
-
 		mTabContainer->addTabPanel(
 			LLTabContainer::TabPanelParams().
 			panel(teleport_history_panel).
@@ -1312,15 +1297,12 @@ void LLPanelPlaces::updateVerbs()
 	mSaveBtn->setVisible(isLandmarkEditModeOn);
 	mCancelBtn->setVisible(isLandmarkEditModeOn);
 	mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
-	mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
 
 	bool show_options_btn = is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn;
 	mOverflowBtn->setVisible(show_options_btn);
 	getChild<LLLayoutPanel>("lp_options")->setVisible(show_options_btn);
 	getChild<LLLayoutPanel>("lp2")->setVisible(!show_options_btn);
 
-	mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);
-
 	if (is_place_info_visible)
 	{
 		mShowOnMapBtn->setEnabled(have_3d_pos);
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 576a0fb931..3b87eb6cb9 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -97,7 +97,6 @@ private:
 	bool onOverflowMenuItemEnable(const LLSD& param);
 	void onCreateLandmarkButtonClicked(const LLUUID& folder_id);
 	void onBackButtonClicked();
-	void onProfileButtonClicked();
     void onGearMenuClick();
     void onSortingMenuClick();
     void onAddMenuClick();
@@ -134,7 +133,6 @@ private:
 	LLButton*					mCancelBtn;
 	LLButton*					mCloseBtn;
 	LLMenuButton*				mOverflowBtn;
-	LLButton*					mPlaceInfoBtn;
 
     // Top menu
     LLMenuButton*				mGearMenuButton;
diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp
index 9644b7518e..9601ac54a4 100644
--- a/indra/newview/llpanelplacestab.cpp
+++ b/indra/newview/llpanelplacestab.cpp
@@ -47,13 +47,6 @@ bool LLPanelPlacesTab::isTabVisible()
 	return true;
 }
 
-void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel)
-{
-	mTeleportBtn = panel->getChild<LLButton>("teleport_btn");
-	mShowOnMapBtn = panel->getChild<LLButton>("map_btn");
-	mShowProfile = panel->getChild<LLButton>("profile_btn");
-}
-
 void LLPanelPlacesTab::onRegionResponse(const LLVector3d& landmark_global_pos,
 										U64 region_handle,
 										const std::string& url,
diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h
index 6c9a6e9da7..886f4ce9c0 100644
--- a/indra/newview/llpanelplacestab.h
+++ b/indra/newview/llpanelplacestab.h
@@ -58,7 +58,6 @@ public:
 
 	bool isTabVisible(); // Check if parent TabContainer is visible.
 
-	void setPanelPlacesButtons(LLPanelPlaces* panel);
 	void onRegionResponse(const LLVector3d& landmark_global_pos,
 										U64 region_handle,
 										const std::string& url,
@@ -69,10 +68,6 @@ public:
 	void setFilterSubString(const std::string& string) { sFilterSubString = string; }
 
 protected:
-	LLButton*				mTeleportBtn;
-	LLButton*				mShowOnMapBtn;
-	LLButton*				mShowProfile;
-
 	// Search string for filtering landmarks and teleport history locations
 	static std::string		sFilterSubString;
 };
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 812ddf874e..48614e1e47 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -566,17 +566,8 @@ void LLTeleportHistoryPanel::updateVerbs()
 
 	if (!mLastSelectedFlatlList)
 	{
-		mTeleportBtn->setEnabled(false);
-		mShowProfile->setEnabled(false);
-		mShowOnMapBtn->setEnabled(false);
 		return;
 	}
-
-	LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
-
-	mTeleportBtn->setEnabled(NULL != itemp);
-	mShowProfile->setEnabled(NULL != itemp);
-	mShowOnMapBtn->setEnabled(NULL != itemp);
 }
 
 // virtual
diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
index 553c112e6f..357a5559bf 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -26,7 +26,7 @@
      name="back_btn"
      left="10"
      tab_stop="false"
-     top="2"
+     top="4"
      width="30"
      use_draw_context_alpha="false" />
    <text
@@ -39,17 +39,17 @@
      left_pad="4"
      name="title"
      text_color="LtGray"
-     top="2"
+     top="4"
      width="250">
         Edit Pick
     </text>
    <scroll_container
      color="DkGray2"
      follows="all"
-     height="502"
+     height="501"
      layout="topleft"
      left="8"
-     top_pad="10"
+     top_pad="9"
      name="profile_scroll"
      opaque="true"
      width="312">
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index 0101516792..f00d25ff05 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -67,7 +67,7 @@
      name="back_btn"
      tool_tip="Back"
      tab_stop="false"
-     top="4"
+     top="2"
      width="30"
      use_draw_context_alpha="false" />
     <text
@@ -78,20 +78,20 @@
      left_pad="7"
      name="title"
      text_color="LtGray"
-     top="3"
+     top="2"
      use_ellipses="true"
      value="Place Profile"
      width="280" />
     <scroll_container
      color="DkGray2"
      follows="all"
-     height="532"
+     height="534"
      layout="topleft"
      left="9"
      name="place_scroll"
      opaque="true"
-     top_pad="10"
-     width="331">
+     top_pad="9"
+     width="324">
         <panel
          bg_alpha_color="DkGray2"
          follows="left|top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index 57b8032312..bdde2cab20 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -172,7 +172,7 @@
      name="back_btn"
      tool_tip="Back"
      tab_stop="false"
-     top="4"
+     top="2"
      width="30"
      use_draw_context_alpha="false" />
     <text
@@ -183,20 +183,20 @@
      left_pad="10"
      name="title"
      text_color="LtGray"
-     top="4"
+     top="2"
      use_ellipses="true"
      value="Place Profile"
      width="280" />
     <scroll_container
      color="DkGray2"
      follows="all"
-     height="572"
+     height="575"
      layout="topleft"
      left="9"
      name="place_scroll"
      opaque="true"
-     top_pad="10"
-     width="331">
+     top_pad="9"
+     width="324">
         <panel
          bg_alpha_color="DkGray2"
          follows="left|top|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 56975288ae..eed56209b7 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -38,7 +38,7 @@ background_visible="true"
       animate="false"
       border_size="0"
       follows="left|top|right"
-      height="25"
+      height="27"
       layout="topleft"
       orientation="horizontal"
       top="0"
@@ -47,7 +47,6 @@ background_visible="true"
       width="320">
       <layout_panel
         auto_resize="true"
-        height="25"
         layout="topleft"
         name="filter_panel"
         width="193">
@@ -161,7 +160,7 @@ background_visible="true"
      tab_height="30"
      tab_group="2"
      tab_position="top"
-     top_pad="9"
+     top_pad="7"
      width="318"
      visible="true"/>
     <panel
@@ -315,41 +314,6 @@ background_visible="true"
 			name="lp2"
 			auto_resize="true"
 			width="116">
-
-		<!--*********************** Profile button ***********************-->		
-				
-				<layout_stack
-		     	follows="bottom|left|right"
-				height="23"
-				layout="topleft"
-				mouse_opaque="false"
-				name="bottom_bar_profile_ls"
-				left="0"
-				orientation="horizontal"
-				top="0"
-				width="110">		
-					<layout_panel
-					follows="bottom|left|right"
-					height="23"
-					layout="bottomleft"
-					left_pad="3"			
-					mouse_opaque="false"
-					name="profile_btn_lp"
-				    auto_resize="true"
-					width="102">
-						<button
-				         follows="bottom|left|right"
-				         height="23"
-				         label="Profile"
-				         layout="topleft"
-						 mouse_opaque="false"
-				         name="profile_btn"
-				         left="1"
-				         tool_tip="Show place profile"
-				         top="0"
-				         width="101" />		
-					</layout_panel>
-				</layout_stack>
 		
 		<!--*********************** Close button ***********************-->
 				
-- 
cgit v1.2.3


From c1139ed9b58025684c6ba7f5779e7e3245bd9a40 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 25 Feb 2021 20:35:07 +0200
Subject: SL-14901 Add a button on the Landmarks bar to open the Places floater

---
 indra/newview/llfavoritesbar.cpp                   |  2 +-
 indra/newview/llnavigationbar.cpp                  | 10 +++++++++
 indra/newview/llnavigationbar.h                    |  2 ++
 indra/newview/llpanellandmarks.cpp                 | 12 ++++++++--
 indra/newview/llpanellandmarks.h                   |  2 ++
 indra/newview/llpanelplaces.cpp                    |  4 ++++
 .../skins/default/xui/en/panel_navigation_bar.xml  | 26 +++++++++++++++++-----
 7 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 2394a763ee..3bebe6fc59 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -838,7 +838,7 @@ void LLFavoritesBarCtrl::updateButtons()
 		int j = first_changed_item_index;
 		for (; j < mItems.size(); j++)
 		{
-			last_new_button = createButton(mItems[j], button_params, last_right_edge);
+			last_new_button = createButton(mItems[j], button_params, j == 0? last_right_edge + 4 : last_right_edge);
 			if (!last_new_button)
 			{
 				break;
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index 179c64b5c5..19dbbeb60e 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -58,6 +58,7 @@
 #include "llweb.h"
 #include "llhints.h"
 
+#include "llfloatersidepanelcontainer.h"
 #include "llinventorymodel.h"
 #include "lllandmarkactions.h"
 
@@ -290,6 +291,7 @@ BOOL LLNavigationBar::postBuild()
 	mBtnBack	= getChild<LLPullButton>("back_btn");
 	mBtnForward	= getChild<LLPullButton>("forward_btn");
 	mBtnHome	= getChild<LLButton>("home_btn");
+	mBtnLandmarks = getChild<LLButton>("landmarks_btn");
 
 	mCmbLocation= getChild<LLLocationInputCtrl>("location_combo");
 
@@ -305,6 +307,8 @@ BOOL LLNavigationBar::postBuild()
 
 	mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this));
 
+	mBtnLandmarks->setClickedCallback(boost::bind(&LLNavigationBar::onLandmarksButtonClicked, this));
+
 	mCmbLocation->setCommitCallback(boost::bind(&LLNavigationBar::onLocationSelection, this));
 
 	mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
@@ -401,6 +405,12 @@ void LLNavigationBar::onHomeButtonClicked()
 	gAgent.teleportHome();
 }
 
+void LLNavigationBar::onLandmarksButtonClicked()
+{
+	LLFloaterReg::toggleInstanceOrBringToFront("places");
+	LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "open_landmark_tab"));
+}
+
 void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata)
 {
 	int idx = userdata.asInteger();
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index a44c6dd699..646911a62c 100755
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -119,6 +119,7 @@ private:
 	void onNavigationButtonHeldUp(LLButton* nav_button);
 	void onForwardButtonClicked();
 	void onHomeButtonClicked();
+	void onLandmarksButtonClicked();
 	void onLocationSelection();
 	void onLocationPrearrange(const LLSD& data);
 	void onTeleportFinished(const LLVector3d& global_agent_pos);
@@ -144,6 +145,7 @@ private:
 	LLPullButton*				mBtnBack;
 	LLPullButton*				mBtnForward;
 	LLButton*					mBtnHome;
+	LLButton*					mBtnLandmarks;
 	LLLocationInputCtrl*		mCmbLocation;
 	LLRect						mDefaultNbRect;
 	LLRect						mDefaultFpRect;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index dfbdfad3bb..9d0c8b015a 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -60,6 +60,8 @@
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
 
+static const std::string TAB_FAVORITES = "tab_favorites";
+
 // helper functions
 static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
 static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
@@ -398,7 +400,7 @@ void LLLandmarksPanel::updateShowFolderState()
 
 void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
 {
-	if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus))
+	if (selectItemInAccordionTab(mFavoritesInventoryPanel, TAB_FAVORITES, obj_id, take_keyboard_focus))
 	{
 		return;
 	}
@@ -521,6 +523,12 @@ void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
 	}
 }
 
+void LLLandmarksPanel::resetSelection()
+{
+	getChild<LLAccordionCtrlTab>(TAB_FAVORITES)->setDisplayChildren(true);
+	getChild<LLAccordionCtrlTab>(TAB_FAVORITES)->showAndFocusHeader();
+}
+
 // virtual
 void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
 {
@@ -571,7 +579,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel()
 	initLandmarksPanel(mFavoritesInventoryPanel);
 	mFavoritesInventoryPanel->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems");
 
-	initAccordion("tab_favorites", mFavoritesInventoryPanel, true);
+	initAccordion(TAB_FAVORITES, mFavoritesInventoryPanel, true);
 }
 
 void LLLandmarksPanel::initLandmarksInventoryPanel()
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 4db77be50b..95256f4bb4 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -94,6 +94,8 @@ public:
 
 	void doCreatePick(LLLandmark* landmark, const LLUUID &item_id );
 
+	void resetSelection();
+
 protected:
 	/**
 	 * @return true - if current selected panel is not null and selected item is a landmark
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index d56194e5b4..11ae980941 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -1130,6 +1130,10 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
 				{
 					landmarks_panel->setItemSelected(mItem->getUUID(), TRUE);
 				}
+				else
+				{
+					landmarks_panel->resetSelection();
+				}
 			}
 		}
 	}
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index c7edba21f8..4cc05fedc9 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -151,7 +151,7 @@
 	         layout="topleft"
            auto_resize="true"
            user_resize="true"
-           min_width="185"
+           min_width="242"
            name="favorites_layout_panel"
            width="320">
            <icon
@@ -163,18 +163,32 @@
              name="resize_handle"
              top="4"
              width="5" />
-
+           <button
+             height="16"
+             width="16"
+             layout="topleft"
+             mouse_opaque="true"
+             follows="left|top"
+             name="landmarks_btn"
+             tool_tip="My Landmarks"
+             top="9"
+             left_pad="10"
+             image_selected="Icon_Gear"
+             image_pressed="Icon_Gear"
+             image_unselected="Icon_Gear"
+             is_toggle="true">
+           </button>
            <favorites_bar
              follows="left|right|top"
              font="SansSerifSmall"
              height="20"
              layout="topleft"
-             left="0"
+             left_pad="0"
              top="4"
              name="favorite"
              image_drag_indication="Accordion_ArrowOpened_Off"
              tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
-             width="320">
+             width="268">
             <label
              follows="left|top"
              height="13"
@@ -185,8 +199,8 @@
              tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
              top="13"
 	     valign="bottom"
-             width="102">
-              Favorites Bar
+             width="205">
+              Your saved locations will appear here.
             </label>
               <!-- More button actually is a text box. -->
               <more_button
-- 
cgit v1.2.3


From a738bbff85e97bbc5b32bc1d233f36c71587a9ea Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 25 Feb 2021 22:41:18 +0200
Subject: SL-14916 Warn user about detailed logging slowing down model imports

---
 indra/newview/skins/default/xui/en/floater_model_preview.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index 02a21764ce..7f863756eb 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -1362,7 +1362,7 @@
          top_pad="9"
          left="6"
          width="70"
-         label="Enable detailed logging"
+         label="Enable detailed logging (can be very slow)"
          name="verbose_logging"/>
       </panel>
     </tab_container>
-- 
cgit v1.2.3


From 14826e17dccb3a12fe7551effc60a2a3c62a4946 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 25 Feb 2021 23:48:48 +0200
Subject: SL-14654 [EEP] Aplying settings locally now is instant

The 1 second fade makes it harder to compare different settings.
---
 indra/newview/llenvironment.cpp     | 25 +++++++------------------
 indra/newview/llenvironment.h       |  3 +--
 indra/newview/llinventorybridge.cpp |  4 ++--
 indra/newview/llviewermenu.cpp      | 18 +++++++++---------
 4 files changed, 19 insertions(+), 31 deletions(-)

diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index a1b27e48ce..90d22c57b0 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1217,33 +1217,24 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe
 
 void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version)
 {
-    setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, TRANSITION_DEFAULT, env_version);
-}
-
-void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsBase::Seconds transition, S32 env_version)
-{
-    setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, transition, env_version);
+    setEnvironment(env, assetId, TRANSITION_DEFAULT, env_version);
 }
 
 void LLEnvironment::setEnvironment(EnvSelection_t env,
                                    const LLUUID &assetId,
-                                   LLSettingsDay::Seconds daylength,
-                                   LLSettingsDay::Seconds dayoffset,
                                    LLSettingsBase::Seconds transition,
                                    S32 env_version)
 {
     LLSettingsVOBase::getSettingsAsset(assetId,
-        [this, env, daylength, dayoffset, env_version, transition](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
+        [this, env, env_version, transition](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
         {
-            onSetEnvAssetLoaded(env, asset_id, settings, daylength, dayoffset, transition, status, env_version);
+            onSetEnvAssetLoaded(env, asset_id, settings, transition, status, env_version);
         });
 }
 
 void LLEnvironment::onSetEnvAssetLoaded(EnvSelection_t env,
                                         LLUUID asset_id,
                                         LLSettingsBase::ptr_t settings,
-                                        LLSettingsDay::Seconds daylength,
-                                        LLSettingsDay::Seconds dayoffset,
                                         LLSettingsBase::Seconds transition,
                                         S32 status,
                                         S32 env_version)
@@ -1690,7 +1681,7 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI
         if (!envinfo->mDayCycle)
         {
             clearEnvironment(ENV_PARCEL);
-            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, TRANSITION_DEFAULT, envinfo->mEnvVersion);
+            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), TRANSITION_DEFAULT, envinfo->mEnvVersion);
             updateEnvironment();
         }
         else if (envinfo->mDayCycle->isTrackEmpty(LLSettingsDay::TRACK_WATER)
@@ -1698,7 +1689,7 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI
         {
             LL_WARNS("ENVIRONMENT") << "Invalid day cycle for region" << LL_ENDL;
             clearEnvironment(ENV_PARCEL);
-            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, TRANSITION_DEFAULT, envinfo->mEnvVersion);
+            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), TRANSITION_DEFAULT, envinfo->mEnvVersion);
             updateEnvironment();
         }
         else
@@ -2944,17 +2935,15 @@ bool LLEnvironment::loadFromSettings()
 
     if (env_data.has("day_id"))
     {
-        LLSettingsDay::Seconds length = LLSettingsDay::Seconds(env_data["day_length"].asInteger());
-        LLSettingsDay::Seconds offset = LLSettingsDay::Seconds(env_data["day_offset"].asInteger());
         LLUUID assetId = env_data["day_id"].asUUID();
 
         LLSettingsVOBase::getSettingsAsset(assetId,
-            [this, length, offset, env_data](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
+            [this, env_data](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
         {
             // Day should be always applied first,
             // otherwise it will override sky or water that was set earlier
             // so wait for asset to load before applying sky/water
-            onSetEnvAssetLoaded(ENV_LOCAL, asset_id, settings, length, offset, TRANSITION_DEFAULT, status, NO_VERSION);
+            onSetEnvAssetLoaded(ENV_LOCAL, asset_id, settings, TRANSITION_DEFAULT, status, NO_VERSION);
             bool valid = false, has_assets = false;
             loadSkyWaterFromSettings(env_data, valid, has_assets);
             if (!has_assets && valid)
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 5c1a62d0ab..7cbf2d25bb 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -144,7 +144,6 @@ public:
     void                        setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixed, LLSettingsWater::ptr_t()), env_version); }
     void                        setEnvironment(EnvSelection_t env, const LLSettingsWater::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(LLSettingsSky::ptr_t(), fixed), env_version); }
     void                        setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixeds, const LLSettingsWater::ptr_t & fixedw, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixeds, fixedw), env_version); }
-    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 env_version);
     void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version);
     void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, S32 env_version = NO_VERSION);
 
@@ -435,7 +434,7 @@ private:
 
     void                        onAgentPositionHasChanged(const LLVector3 &localpos);
 
-    void                        onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 status, S32 env_version);
+    void                        onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, LLSettingsBase::Seconds transition, S32 status, S32 env_version);
     void                        onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, S32 parcel_id, S32 day_length, S32 day_offset, altitudes_vect_t altitudes);
 
     void                        handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 065a3cb9ae..a0c3608107 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -7064,8 +7064,8 @@ void LLSettingsBridge::performAction(LLInventoryModel* model, std::string action
         if (!item) 
             return;
         LLUUID asset_id = item->getAssetUUID();
-        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id, LLEnvironment::TRANSITION_FAST);
-        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id, LLEnvironment::TRANSITION_INSTANT);
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
     }
     else if ("apply_settings_parcel" == action)
     {
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 7d7fdf53e2..c09654236c 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -8608,32 +8608,32 @@ class LLWorldEnvSettings : public view_listener_t
 		
 		if (event_name == "sunrise")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_FAST);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_INSTANT);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
             defocusEnvFloaters();
 		}
 		else if (event_name == "noon")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_FAST);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_INSTANT);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
             defocusEnvFloaters();
 		}
 		else if (event_name == "sunset")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_FAST);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_INSTANT);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
             defocusEnvFloaters();
 		}
 		else if (event_name == "midnight")
 		{
-            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_FAST);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_INSTANT);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
             defocusEnvFloaters();
 		}
         else if (event_name == "region")
 		{
             LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
-            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
             defocusEnvFloaters();
 		}
         else if (event_name == "pause_clouds")
-- 
cgit v1.2.3


From 34b971150835872eb04fcd08af6f485601c79b54 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 26 Feb 2021 19:44:58 +0200
Subject: SL-14725 Adjust "Show Beacon" position

---
 .../skins/default/xui/en/floater_fixedenvironment.xml  |  2 +-
 .../default/xui/en/panel_settings_sky_sunmoon.xml      | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
index 37c56d3235..a6e20880a9 100644
--- a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
+++ b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
@@ -89,7 +89,7 @@
                 follows="left|top|right|bottom"
                 auto_resize="false"
                 user_resize="false"
-                height="35"
+                height="29"
                 visible="true">
             <layout_stack
                     follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
index 6be5aba545..1ad78dbb13 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
@@ -226,14 +226,14 @@
                     
             <check_box
                     control_name="sunbeacon"
+                    follows="left|top"
+                    layout="topleft"
                     width="60"
                     height="16"
                     label="Show Beacon"
-                    layout="topleft"
-                    name="sunbeacon" 
-                    right="-50"
-                    bottom="-10"
-                    follows="bottom|right"/>
+                    name="sunbeacon"
+                    top_pad="5"
+                    left_delta="-8"/>
                     
         </layout_panel>
         <layout_panel
@@ -395,14 +395,14 @@
                     can_edit_text="true"/>
                   <check_box
                         control_name="moonbeacon"
+                        follows="left|top"
+                        layout="topleft"
                         width="60"
                         height="16"
                         label="Show Beacon"
-                        layout="topleft"
                         name="moonbeacon" 
-                        right="-50"
-                        bottom="-10"
-                        follows="bottom|right"/>
+                        top_pad="5"
+                        left_delta="-8"/>
                             
                 </layout_panel>
             </layout_stack>
-- 
cgit v1.2.3


From 4a2f7c82cc6c9628f6be6b4e322b172478d65b9c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 26 Feb 2021 21:38:13 +0200
Subject: SL-14612 Wording improvement for hitting TP throttle

Teleport uses teleport_strings.xml, updating noifications.xml as well in case it can be triggered by server directly.
---
 indra/newview/skins/default/xui/en/notifications.xml    | 5 ++---
 indra/newview/skins/default/xui/en/teleport_strings.xml | 3 +--
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 23bf3191ae..cdde9d2107 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2431,9 +2431,8 @@ Teleport failed.
    icon="alertmodal.tga"
    name="invalid_tport"
    type="alertmodal">
-Problem encountered processing your teleport request. You may need to log back in before you can teleport.
-If you continue to get this message, please check the [SUPPORT_SITE].
-  <tag>fail</tag>
+Teleport attempts are limited to 6 per minute. If you are having trouble, wait one minute and try teleporting again. If the problem persists, log out and log in again.
+    <tag>fail</tag>
   </notification>
   <notification
    icon="alertmodal.tga"
diff --git a/indra/newview/skins/default/xui/en/teleport_strings.xml b/indra/newview/skins/default/xui/en/teleport_strings.xml
index 57f8bb542d..1456114b25 100644
--- a/indra/newview/skins/default/xui/en/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/en/teleport_strings.xml
@@ -2,8 +2,7 @@
 <teleport_messages>
 	<message_set name="errors">
 		<message name="invalid_tport">
-			Problem encountered processing your teleport request. You may need to log back in before you can teleport.
-If you continue to get this message, please check the [SUPPORT_SITE].
+			Teleport attempts are limited to 6 per minute. If you are having trouble, wait one minute and try teleporting again. If the problem persists, log out and log in again.
 		</message>
 		<message name="invalid_region_handoff">
 			Problem encountered processing your region crossing. You may need to log back in before you can cross regions.
-- 
cgit v1.2.3


From dd89dec893411c22d4916de14593a56f87d3a284 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 1 Mar 2021 21:38:46 +0000
Subject: SL-14862 - more types of UI usage logs

---
 indra/llui/llbutton.cpp                 |  8 ++++++++
 indra/llui/lluictrl.cpp                 |  1 +
 indra/llui/lluiusage.cpp                | 12 ++++++++++++
 indra/llui/lluiusage.h                  |  2 ++
 indra/newview/llchatbar.cpp             |  3 +++
 indra/newview/llfloaterimnearbychat.cpp |  2 ++
 indra/newview/llworldmipmap.cpp         |  2 ++
 7 files changed, 30 insertions(+)

diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 9682c3bc10..3a3d9254fd 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -47,6 +47,7 @@
 #include "llnotificationsutil.h"
 #include "llrender.h"
 #include "lluictrlfactory.h"
+#include "lluiusage.h"
 #include "llhelp.h"
 #include "lldockablefloater.h"
 #include "llviewereventrecorder.h"
@@ -437,6 +438,13 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
 			setFocus(TRUE);
 		}
 
+		if (!mFunctionName.empty())
+		{
+			LL_DEBUGS("UIUsage") << "calling mouse down function " << mFunctionName << LL_ENDL;
+			LLUIUsage::instance().logCommand(mFunctionName);
+			LLUIUsage::instance().logWidget(getPathname());
+		}
+
 		/*
 		 * ATTENTION! This call fires another mouse down callback.
 		 * If you wish to remove this call emit that signal directly
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 0e1c8439ea..426c931d07 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -429,6 +429,7 @@ void LLUICtrl::onCommit()
 		{
 			LL_DEBUGS("UIUsage") << "calling commit function " << mFunctionName << LL_ENDL;
 			LLUIUsage::instance().logCommand(mFunctionName);
+			LLUIUsage::instance().logWidget(getPathname());
 		}
 		else
 		{
diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
index 50eeccd214..99de4ff78a 100644
--- a/indra/llui/lluiusage.cpp
+++ b/indra/llui/lluiusage.cpp
@@ -47,11 +47,19 @@ std::string LLUIUsage::sanitized(const std::string& s)
 void LLUIUsage::logFloater(const std::string& floater)
 {
 	mFloaterCounts[sanitized(floater)]++;
+	LL_DEBUGS("UIUsage") << "floater " << floater << LL_ENDL;
 }
 
 void LLUIUsage::logCommand(const std::string& command)
 {
 	mCommandCounts[sanitized(command)]++;
+	LL_DEBUGS("UIUsage") << "command " << command << LL_ENDL;
+}
+
+void LLUIUsage::logWidget(const std::string& w)
+{
+	mWidgetCounts[sanitized(w)]++;
+	LL_DEBUGS("UIUsage") << "widget " << w << LL_ENDL;
 }
 
 LLSD LLUIUsage::asLLSD() const
@@ -65,6 +73,10 @@ LLSD LLUIUsage::asLLSD() const
 	{
 		result["commands"][it.first] = LLSD::Integer(it.second);
 	}
+	for (auto const& it : mWidgetCounts)
+	{
+		result["widgets"][it.first] = LLSD::Integer(it.second);
+	}
 	return result;
 }
 
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
index bac607aa60..efc8bb4032 100644
--- a/indra/llui/lluiusage.h
+++ b/indra/llui/lluiusage.h
@@ -41,10 +41,12 @@ public:
 	static std::string sanitized(const std::string& s);
 	void logFloater(const std::string& floater);
 	void logCommand(const std::string& command);
+	void logWidget(const std::string& w);
 	LLSD asLLSD() const;
 private:
 	std::map<std::string,U32> mFloaterCounts;
 	std::map<std::string,U32> mCommandCounts;
+	std::map<std::string,U32> mWidgetCounts;
 };
 
 #endif // LLUIUIUSAGE.h
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 3ab5c669c4..e400609a74 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -58,6 +58,7 @@
 #include "llmultigesture.h"
 #include "llui.h"
 #include "lluictrlfactory.h"
+#include "lluiusage.h"
 
 //
 // Globals
@@ -566,6 +567,8 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
 	// as soon as we say something, we no longer care about teaching the user
 	// how to chat
 	gWarningSettings.setBOOL("FirstOtherChatBeforeUser", FALSE);
+
+	LLUIUsage::instance().logCommand("Chat.Send"); // Pseudo-command
 	
 	// Look for "/20 foo" channel chats.
 	S32 channel = 0;
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index a6531ed7e1..3a850d4b68 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -67,6 +67,7 @@
 #include "llviewerchat.h"
 #include "lltranslate.h"
 #include "llautoreplace.h"
+#include "lluiusage.h"
 
 S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
 
@@ -697,6 +698,7 @@ void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, ECha
 
 void LLFloaterIMNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
 {
+	LLUIUsage::instance().logCommand("Chat.Send"); // pseuo-command
 	// Look for "/20 foo" channel chats.
 	S32 channel = 0;
 	LLWString out_text = stripChannelNumber(wtext, &channel);
diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
index a2e519a61a..040d0deaf3 100644
--- a/indra/newview/llworldmipmap.cpp
+++ b/indra/newview/llworldmipmap.cpp
@@ -190,6 +190,8 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32
 	//LL_INFOS("WorldMap") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL;
 
 	LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+	LL_INFOS("MAPURL") << "fetching map tile from " << imageurl << LL_ENDL;
+
 	img->setBoostLevel(LLGLTexture::BOOST_MAP);
 
 	// Return the smart pointer
-- 
cgit v1.2.3


From c06f43adde3aeb87a1510583b6f35b9327598408 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 5 Mar 2021 16:50:41 +0200
Subject: SL-14931 Change messaging on empty lists in  People floater

---
 indra/newview/llfloaterhandler.cpp                  |  9 ++++++++-
 indra/newview/llpanelpeople.cpp                     |  1 +
 indra/newview/skins/default/xui/en/panel_people.xml | 18 +++++++++++++-----
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llfloaterhandler.cpp b/indra/newview/llfloaterhandler.cpp
index e2160498e9..8ebb14149c 100644
--- a/indra/newview/llfloaterhandler.cpp
+++ b/indra/newview/llfloaterhandler.cpp
@@ -26,6 +26,7 @@
 
 #include "llfloater.h"
 #include "llmediactrl.h"
+#include "llfloaterreg.h"
 
 // register with dispatch via global object
 LLFloaterHandler gFloaterHandler;
@@ -50,9 +51,15 @@ LLFloater* get_parent_floater(LLView* view)
 
 bool LLFloaterHandler::handle(const LLSD &params, const LLSD &query_map, LLMediaCtrl *web)
 {
-	if (params.size() < 2) return false;
+	if (params.size() < 1) return false;
 	LLFloater* floater = NULL;
 	// *TODO: implement floater lookup by name
+
+	if (params[0].asString() == "destinations")
+	{
+		LLFloaterReg::toggleInstanceOrBringToFront("destinations");
+		return true;
+	}
 	if (params[0].asString() == "self")
 	{
 		if (web)
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index e5142f2b5f..5997d522c4 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -661,6 +661,7 @@ BOOL LLPanelPeople::postBuild()
 	mRecentList->setShowIcons("RecentListShowIcons");
 
 	mGroupList = getChild<LLGroupList>("group_list");
+	mGroupList->setNoItemsCommentText(getString("no_groups_msg"));
 	mGroupList->setNoItemsMsg(getString("no_groups_msg"));
 	mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg"));
 
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index c4248d9b92..3c8a2fe4f4 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -12,7 +12,7 @@
  width="333">
     <string
      name="no_recent_people"
-     value="No recent people. Looking for people to hang out with? Try [secondlife:///app/search/people Search] or the [secondlife:///app/worldmap World Map]." />
+     value="No recent people." />
     <string
      name="no_filtered_recent_people"
      value="Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]." />
@@ -30,8 +30,13 @@
      value="No friends" />
     <string
      name="no_friends_msg">
-         Find friends using [secondlife:///app/search/people Search] or right-click on a Resident to add them as a friend.
-Looking for people to hang out with? Try the [secondlife:///app/worldmap World Map].
+      To add someone as a friend, right-click on their avatar or their name.
+
+Looking for places with more people?
+
+[secondlife:///app/floater/destinations Destination Guide] has locations chosen by Second Life staff.
+
+[secondlife:///app/search/people Search] lets you search all of Second Life for certain keywords.
     </string>
     <string
      name="no_filtered_friends_msg">
@@ -45,8 +50,11 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
      name="no_filtered_groups_msg"
      value="Didn't find what you're looking for? Try [secondlife:///app/search/groups/[SEARCH_TERM] Search]." />
     <string
-     name="no_groups_msg"
-     value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]." />
+     name="no_groups_msg">
+You are not a member of any groups.
+
+Learn about [https://community.secondlife.com/knowledgebase/joining-and-participating-in-groups-r51/ groups in Second Life.]
+  </string>
 	<string
 	 name="MiniMapToolTipMsg"
 	 value="[REGION](Double-click to open Map, shift-drag to pan)"/>
-- 
cgit v1.2.3


From 446253df44dd82a7c5e711b9a69369cbbeb2acb7 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 10 Mar 2021 17:54:44 +0200
Subject: SL-14901 Updated button according to new spec

---
 indra/newview/llfavoritesbar.cpp                   |   2 +-
 .../skins/default/textures/navbar/Landmarks.png    | Bin 0 -> 15870 bytes
 indra/newview/skins/default/textures/textures.xml  |   4 +++-
 .../skins/default/xui/en/panel_navigation_bar.xml  |  21 ++++++++++-----------
 4 files changed, 14 insertions(+), 13 deletions(-)
 create mode 100644 indra/newview/skins/default/textures/navbar/Landmarks.png

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 3bebe6fc59..2394a763ee 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -838,7 +838,7 @@ void LLFavoritesBarCtrl::updateButtons()
 		int j = first_changed_item_index;
 		for (; j < mItems.size(); j++)
 		{
-			last_new_button = createButton(mItems[j], button_params, j == 0? last_right_edge + 4 : last_right_edge);
+			last_new_button = createButton(mItems[j], button_params, last_right_edge);
 			if (!last_new_button)
 			{
 				break;
diff --git a/indra/newview/skins/default/textures/navbar/Landmarks.png b/indra/newview/skins/default/textures/navbar/Landmarks.png
new file mode 100644
index 0000000000..2b35de913b
Binary files /dev/null and b/indra/newview/skins/default/textures/navbar/Landmarks.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 8d609afeae..03878d9fe7 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -339,7 +339,9 @@ with the same filename but different name
   <texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" />
 
   <texture name="Inv_Toolbar_SearchVisibility" file_name="icons/Inv_Toolbar_SearchVisibility.png" preload="false" />
-  
+
+  <texture name="Landmarks_overlay" file_name="navbar/Landmarks.png" preload="false" />
+
   <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/>
   <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/>
 
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 4cc05fedc9..d3448ed0ba 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -151,32 +151,31 @@
 	         layout="topleft"
            auto_resize="true"
            user_resize="true"
-           min_width="242"
+           min_width="254"
            name="favorites_layout_panel"
-           width="320">
+           width="342">
            <icon
              follows="top|left"
              height="25"
              image_name="ChatBarHandle"
              layout="topleft"
-             left="-323"
+             left="-345"
              name="resize_handle"
              top="4"
              width="5" />
            <button
-             height="16"
-             width="16"
+             height="23"
+             width="32"
              layout="topleft"
              mouse_opaque="true"
              follows="left|top"
              name="landmarks_btn"
              tool_tip="My Landmarks"
-             top="9"
-             left_pad="10"
-             image_selected="Icon_Gear"
-             image_pressed="Icon_Gear"
-             image_unselected="Icon_Gear"
-             is_toggle="true">
+             top_delta="1"
+             left_pad="8"
+             scale_image="false"
+             image_overlay="Landmarks_overlay"
+             image_hover_unselected="PushButton_Over">
            </button>
            <favorites_bar
              follows="left|right|top"
-- 
cgit v1.2.3


From 89bd4269018fa5a36a15eac8d2c3f99674d18b2d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 10 Mar 2021 16:23:20 +0000
Subject: SL-14862 - use nested LLSD for widget info, condensed to the two
 leaf-most elements of the path. Simplified floater logging.

---
 indra/llui/llfloater.cpp          |  2 ++
 indra/llui/llfloaterreg.cpp       |  8 --------
 indra/llui/lluiusage.cpp          | 33 ++++++++++++++++++++++++++++++++-
 indra/llui/lluiusage.h            |  1 +
 indra/newview/llviewermessage.cpp |  1 -
 5 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index e9c980ad9a..c03b024dd5 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -58,6 +58,7 @@
 #include "llhelp.h"
 #include "llmultifloater.h"
 #include "llsdutil.h"
+#include "lluiusage.h"
 #include <boost/foreach.hpp>
 
 
@@ -1631,6 +1632,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
 // virtual
 void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
 {
+	LLUIUsage::instance().logFloater(getInstanceName());
 	LLMultiFloater* hostp = getHost();
 	if (hostp)
 	{
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 6307bf1028..7c0933f554 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -244,8 +244,6 @@ LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::str
 //static
 LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) 
 {
-	LL_DEBUGS("UIUsage") << "floater showInstance " << name << LL_ENDL;
-	LLUIUsage::instance().logFloater(name);
 	if( sBlockShowFloaters
 			// see EXT-7090
 			&& sAlwaysShowableList.find(name) == sAlwaysShowableList.end())
@@ -276,9 +274,6 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
 // returns true if the instance is visible when completed
 bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
 {
-	LL_DEBUGS("UIUsage") << "floater toggleInstance " << name << LL_ENDL;
-	LLUIUsage::instance().logFloater(name);
-
 	LLFloater* instance = findInstance(name, key); 
 	if (LLFloater::isShown(instance))
 	{
@@ -478,9 +473,6 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
 	std::string name = sdname.asString();
 	LLFloater* instance = getInstance(name, key); 
 	
-
-	LL_DEBUGS("UIUsage") << "floater toggleInstanceOrBringToFront " << name << LL_ENDL;
-	LLUIUsage::instance().logFloater(name);
 	if (!instance)
 	{
 		LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL;
diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
index 99de4ff78a..824c59730b 100644
--- a/indra/llui/lluiusage.cpp
+++ b/indra/llui/lluiusage.cpp
@@ -26,6 +26,7 @@
 
 #include "linden_common.h"
 #include "lluiusage.h"
+#include <boost/algorithm/string.hpp>
 
 LLUIUsage::LLUIUsage()
 {
@@ -41,9 +42,39 @@ std::string LLUIUsage::sanitized(const std::string& s)
 	// ViewerStats db doesn't like "." in keys
 	std::string result(s);
 	std::replace(result.begin(), result.end(), '.', '_');
+	std::replace(result.begin(), result.end(), ' ', '_');
 	return result;
 }
 
+void LLUIUsage::setLLSDNested(LLSD& sd, const std::string& path, S32 max_elts, S32 val) const
+{
+	std::vector<std::string> fields;
+	boost::split(fields, path, boost::is_any_of("/"));
+	auto first_pos = std::max(fields.begin(), fields.end() - max_elts);
+	auto end_pos = fields.end();
+	std::vector<std::string> last_fields(first_pos,end_pos);
+
+	// Code below is just to accomplish the equivalent of
+	//   sd[last_fields[0]][last_fields[1]] = LLSD::Integer(val);
+	// for an arbitrary number of fields.
+	LLSD* fsd = &sd;
+	for (auto it=last_fields.begin(); it!=last_fields.end(); ++it)
+	{
+		if (it == last_fields.end()-1)
+		{
+			(*fsd)[*it] = LLSD::Integer(val);
+		}
+		else
+		{
+			if (!(*fsd)[*it].isMap())
+			{
+				(*fsd)[*it] = LLSD::emptyMap();
+			}
+			fsd = &(*fsd)[*it];
+		}
+	}
+}
+
 void LLUIUsage::logFloater(const std::string& floater)
 {
 	mFloaterCounts[sanitized(floater)]++;
@@ -75,7 +106,7 @@ LLSD LLUIUsage::asLLSD() const
 	}
 	for (auto const& it : mWidgetCounts)
 	{
-		result["widgets"][it.first] = LLSD::Integer(it.second);
+		setLLSDNested(result["widgets"], it.first, 2, it.second);
 	}
 	return result;
 }
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
index efc8bb4032..956e184edc 100644
--- a/indra/llui/lluiusage.h
+++ b/indra/llui/lluiusage.h
@@ -39,6 +39,7 @@ public:
 	~LLUIUsage();
 public:
 	static std::string sanitized(const std::string& s);
+	void setLLSDNested(LLSD& sd, const std::string& path, S32 max_elts, S32 val) const;
 	void logFloater(const std::string& floater);
 	void logCommand(const std::string& command);
 	void logWidget(const std::string& w);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 458fc3b13d..0d1b074743 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -116,7 +116,6 @@
 #include "llviewerregion.h"
 #include "llfloaterregionrestarting.h"
 
-#include <boost/algorithm/string/split.hpp> //
 #include <boost/foreach.hpp>
 
 #include "llnotificationmanager.h" //
-- 
cgit v1.2.3


From 92a17bf53b33050402c292c22614b361dba0e292 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 10 Mar 2021 17:49:06 +0000
Subject: SL-14862 - tab logging

---
 indra/llui/lltabcontainer.cpp |  3 +++
 indra/llui/lluiusage.cpp      | 27 ++++++++++++++++++++++++---
 indra/llui/lluiusage.h        |  7 +++++--
 indra/newview/llstartup.cpp   |  3 +++
 4 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index e6b43da8e5..459fdcf2ae 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -38,6 +38,7 @@
 #include "llrender.h"
 #include "llfloater.h"
 #include "lltrans.h"
+#include "lluiusage.h"
 
 //----------------------------------------------------------------------------
 
@@ -1556,6 +1557,8 @@ BOOL LLTabContainer::setTab(S32 which)
 			
 			if (is_selected)
 			{
+				LLUIUsage::instance().logPanel(tuple->mTabPanel->getName());
+
 				// Make sure selected tab is within scroll region
 				if (mIsVertical)
 				{
diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
index 824c59730b..c0d945438f 100644
--- a/indra/llui/lluiusage.cpp
+++ b/indra/llui/lluiusage.cpp
@@ -75,16 +75,22 @@ void LLUIUsage::setLLSDNested(LLSD& sd, const std::string& path, S32 max_elts, S
 	}
 }
 
+void LLUIUsage::logCommand(const std::string& command)
+{
+	mCommandCounts[sanitized(command)]++;
+	LL_DEBUGS("UIUsage") << "command " << command << LL_ENDL;
+}
+
 void LLUIUsage::logFloater(const std::string& floater)
 {
 	mFloaterCounts[sanitized(floater)]++;
 	LL_DEBUGS("UIUsage") << "floater " << floater << LL_ENDL;
 }
 
-void LLUIUsage::logCommand(const std::string& command)
+void LLUIUsage::logPanel(const std::string& p)
 {
-	mCommandCounts[sanitized(command)]++;
-	LL_DEBUGS("UIUsage") << "command " << command << LL_ENDL;
+	mPanelCounts[sanitized(p)]++;
+	LL_DEBUGS("UIUsage") << "panel " << p << LL_ENDL;
 }
 
 void LLUIUsage::logWidget(const std::string& w)
@@ -104,6 +110,10 @@ LLSD LLUIUsage::asLLSD() const
 	{
 		result["commands"][it.first] = LLSD::Integer(it.second);
 	}
+	for (auto const& it : mPanelCounts)
+	{
+		result["panels"][it.first] = LLSD::Integer(it.second);
+	}
 	for (auto const& it : mWidgetCounts)
 	{
 		setLLSDNested(result["widgets"], it.first, 2, it.second);
@@ -111,3 +121,14 @@ LLSD LLUIUsage::asLLSD() const
 	return result;
 }
 
+// Clear up some junk content generated during initial login/UI initialization
+void LLUIUsage::clear()
+{
+
+	LL_DEBUGS("UIUsage") << "clear" << LL_ENDL;
+	mCommandCounts.clear();
+	mFloaterCounts.clear();
+	mPanelCounts.clear();
+	mWidgetCounts.clear();
+}
+
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
index 956e184edc..df7360c210 100644
--- a/indra/llui/lluiusage.h
+++ b/indra/llui/lluiusage.h
@@ -40,13 +40,16 @@ public:
 public:
 	static std::string sanitized(const std::string& s);
 	void setLLSDNested(LLSD& sd, const std::string& path, S32 max_elts, S32 val) const;
-	void logFloater(const std::string& floater);
 	void logCommand(const std::string& command);
+	void logFloater(const std::string& floater);
+	void logPanel(const std::string& p);
 	void logWidget(const std::string& w);
 	LLSD asLLSD() const;
+	void clear();
 private:
-	std::map<std::string,U32> mFloaterCounts;
 	std::map<std::string,U32> mCommandCounts;
+	std::map<std::string,U32> mFloaterCounts;
+	std::map<std::string,U32> mPanelCounts;
 	std::map<std::string,U32> mWidgetCounts;
 };
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 17777c3ceb..b458582fa8 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -142,6 +142,7 @@
 #include "lltoolmgr.h"
 #include "lltrans.h"
 #include "llui.h"
+#include "lluiusage.h"
 #include "llurldispatcher.h"
 #include "llurlentry.h"
 #include "llslurl.h"
@@ -2257,6 +2258,8 @@ bool idle_startup()
 
 		gAgentAvatarp->sendHoverHeight();
 
+		LLUIUsage::instance().clear();
+
 		return TRUE;
 	}
 
-- 
cgit v1.2.3


From e3babd1f8d6d5347f9cf1ec5fee976718e0c6a44 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Mar 2021 14:26:36 +0000
Subject: SL-14862 - more generalized LLSD funcs

---
 indra/llui/lluiusage.cpp | 26 ++++++++++++++++++--------
 indra/llui/lluiusage.h   |  3 ++-
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
index c0d945438f..60c124b711 100644
--- a/indra/llui/lluiusage.cpp
+++ b/indra/llui/lluiusage.cpp
@@ -46,23 +46,33 @@ std::string LLUIUsage::sanitized(const std::string& s)
 	return result;
 }
 
-void LLUIUsage::setLLSDNested(LLSD& sd, const std::string& path, S32 max_elts, S32 val) const
+// static
+void LLUIUsage::setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val)
 {
+	// Keep the last max_elts components of the specified path
 	std::vector<std::string> fields;
 	boost::split(fields, path, boost::is_any_of("/"));
 	auto first_pos = std::max(fields.begin(), fields.end() - max_elts);
 	auto end_pos = fields.end();
 	std::vector<std::string> last_fields(first_pos,end_pos);
 
-	// Code below is just to accomplish the equivalent of
-	//   sd[last_fields[0]][last_fields[1]] = LLSD::Integer(val);
-	// for an arbitrary number of fields.
+	setLLSDNested(sd, last_fields, val);
+}
+
+// setLLSDNested
+// Accomplish the equivalent of 
+//   sd[fields[0]][fields[1]]... = val;
+// for an arbitrary number of fields.
+// 
+// static
+void LLUIUsage::setLLSDNested(LLSD& sd, const std::vector<std::string>& fields, const LLSD& val)
+{
 	LLSD* fsd = &sd;
-	for (auto it=last_fields.begin(); it!=last_fields.end(); ++it)
+	for (auto it=fields.begin(); it!=fields.end(); ++it)
 	{
-		if (it == last_fields.end()-1)
+		if (it == fields.end()-1)
 		{
-			(*fsd)[*it] = LLSD::Integer(val);
+			(*fsd)[*it] = val;
 		}
 		else
 		{
@@ -116,7 +126,7 @@ LLSD LLUIUsage::asLLSD() const
 	}
 	for (auto const& it : mWidgetCounts)
 	{
-		setLLSDNested(result["widgets"], it.first, 2, it.second);
+		setLLSDPath(result["widgets"], it.first, 2, LLSD::Integer(it.second));
 	}
 	return result;
 }
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
index df7360c210..e642c55e0f 100644
--- a/indra/llui/lluiusage.h
+++ b/indra/llui/lluiusage.h
@@ -39,7 +39,8 @@ public:
 	~LLUIUsage();
 public:
 	static std::string sanitized(const std::string& s);
-	void setLLSDNested(LLSD& sd, const std::string& path, S32 max_elts, S32 val) const;
+	static void setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val);
+	static void setLLSDNested(LLSD& sd, const std::vector<std::string>& fields, const LLSD& val);
 	void logCommand(const std::string& command);
 	void logFloater(const std::string& floater);
 	void logPanel(const std::string& p);
-- 
cgit v1.2.3


From acb2e87d9425c8f671d9772409fd291d7fed9aa7 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Mar 2021 15:11:51 +0000
Subject: SL-14862 - renamed widgets to the more descriptive controls

---
 indra/llui/llbutton.cpp  |  2 +-
 indra/llui/lluictrl.cpp  |  2 +-
 indra/llui/lluiusage.cpp | 36 +++++++++++++++++++-----------------
 indra/llui/lluiusage.h   |  4 ++--
 4 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 3a3d9254fd..0e59fdf519 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -442,7 +442,7 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
 		{
 			LL_DEBUGS("UIUsage") << "calling mouse down function " << mFunctionName << LL_ENDL;
 			LLUIUsage::instance().logCommand(mFunctionName);
-			LLUIUsage::instance().logWidget(getPathname());
+			LLUIUsage::instance().logControl(getPathname());
 		}
 
 		/*
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 426c931d07..5924542a19 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -429,7 +429,7 @@ void LLUICtrl::onCommit()
 		{
 			LL_DEBUGS("UIUsage") << "calling commit function " << mFunctionName << LL_ENDL;
 			LLUIUsage::instance().logCommand(mFunctionName);
-			LLUIUsage::instance().logWidget(getPathname());
+			LLUIUsage::instance().logControl(getPathname());
 		}
 		else
 		{
diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
index 60c124b711..ccae6643b9 100644
--- a/indra/llui/lluiusage.cpp
+++ b/indra/llui/lluiusage.cpp
@@ -39,7 +39,7 @@ LLUIUsage::~LLUIUsage()
 // static
 std::string LLUIUsage::sanitized(const std::string& s)
 {
-	// ViewerStats db doesn't like "." in keys
+	// Remove characters that make the ViewerStats db unhappy
 	std::string result(s);
 	std::replace(result.begin(), result.end(), '.', '_');
 	std::replace(result.begin(), result.end(), ' ', '_');
@@ -59,10 +59,11 @@ void LLUIUsage::setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, con
 	setLLSDNested(sd, last_fields, val);
 }
 
-// setLLSDNested
+// setLLSDNested()
 // Accomplish the equivalent of 
 //   sd[fields[0]][fields[1]]... = val;
 // for an arbitrary number of fields.
+// This might be useful as an LLSD utility function; is not specific to LLUIUsage
 // 
 // static
 void LLUIUsage::setLLSDNested(LLSD& sd, const std::vector<std::string>& fields, const LLSD& val)
@@ -91,6 +92,13 @@ void LLUIUsage::logCommand(const std::string& command)
 	LL_DEBUGS("UIUsage") << "command " << command << LL_ENDL;
 }
 
+void LLUIUsage::logControl(const std::string& control)
+{
+	mControlCounts[sanitized(control)]++;
+	LL_DEBUGS("UIUsage") << "control " << control << LL_ENDL;
+}
+
+
 void LLUIUsage::logFloater(const std::string& floater)
 {
 	mFloaterCounts[sanitized(floater)]++;
@@ -103,30 +111,24 @@ void LLUIUsage::logPanel(const std::string& p)
 	LL_DEBUGS("UIUsage") << "panel " << p << LL_ENDL;
 }
 
-void LLUIUsage::logWidget(const std::string& w)
-{
-	mWidgetCounts[sanitized(w)]++;
-	LL_DEBUGS("UIUsage") << "widget " << w << LL_ENDL;
-}
-
 LLSD LLUIUsage::asLLSD() const
 {
 	LLSD result;
-	for (auto const& it : mFloaterCounts)
-	{
-		result["floaters"][it.first] = LLSD::Integer(it.second);
-	}
 	for (auto const& it : mCommandCounts)
 	{
 		result["commands"][it.first] = LLSD::Integer(it.second);
 	}
-	for (auto const& it : mPanelCounts)
+	for (auto const& it : mControlCounts)
 	{
-		result["panels"][it.first] = LLSD::Integer(it.second);
+		setLLSDPath(result["controls"], it.first, 2, LLSD::Integer(it.second));
 	}
-	for (auto const& it : mWidgetCounts)
+	for (auto const& it : mFloaterCounts)
 	{
-		setLLSDPath(result["widgets"], it.first, 2, LLSD::Integer(it.second));
+		result["floaters"][it.first] = LLSD::Integer(it.second);
+	}
+	for (auto const& it : mPanelCounts)
+	{
+		result["panels"][it.first] = LLSD::Integer(it.second);
 	}
 	return result;
 }
@@ -137,8 +139,8 @@ void LLUIUsage::clear()
 
 	LL_DEBUGS("UIUsage") << "clear" << LL_ENDL;
 	mCommandCounts.clear();
+	mControlCounts.clear();
 	mFloaterCounts.clear();
 	mPanelCounts.clear();
-	mWidgetCounts.clear();
 }
 
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
index e642c55e0f..a30cd80db3 100644
--- a/indra/llui/lluiusage.h
+++ b/indra/llui/lluiusage.h
@@ -42,16 +42,16 @@ public:
 	static void setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val);
 	static void setLLSDNested(LLSD& sd, const std::vector<std::string>& fields, const LLSD& val);
 	void logCommand(const std::string& command);
+	void logControl(const std::string& control);
 	void logFloater(const std::string& floater);
 	void logPanel(const std::string& p);
-	void logWidget(const std::string& w);
 	LLSD asLLSD() const;
 	void clear();
 private:
 	std::map<std::string,U32> mCommandCounts;
+	std::map<std::string,U32> mControlCounts;
 	std::map<std::string,U32> mFloaterCounts;
 	std::map<std::string,U32> mPanelCounts;
-	std::map<std::string,U32> mWidgetCounts;
 };
 
 #endif // LLUIUIUSAGE.h
-- 
cgit v1.2.3


From cdd71c5e64782b33aaf5f8caac8ef61eaa78f607 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 16 Mar 2021 19:29:23 +0200
Subject: SL-14938 Remove Library and Inventory from Places floater

---
 indra/newview/llpanellandmarks.cpp                 | 464 +++------------------
 indra/newview/llpanellandmarks.h                   |  57 +--
 indra/newview/llpanelplaces.cpp                    |  22 +-
 .../default/xui/en/menu_places_gear_folder.xml     |   3 +
 .../default/xui/en/menu_places_gear_sorting.xml    |   3 +
 .../skins/default/xui/en/panel_favorites.xml       |  22 +
 .../skins/default/xui/en/panel_landmarks.xml       |  99 +----
 .../newview/skins/default/xui/en/panel_places.xml  |   7 +-
 indra/newview/skins/default/xui/en/strings.xml     |   4 +-
 9 files changed, 153 insertions(+), 528 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/panel_favorites.xml

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 9d0c8b015a..1a10654a71 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -36,7 +36,6 @@
 #include "llregionhandle.h"
 
 #include "llaccordionctrl.h"
-#include "llaccordionctrltab.h"
 #include "llagent.h"
 #include "llagentpicksinfo.h"
 #include "llagentui.h"
@@ -60,8 +59,6 @@
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
 
-static const std::string TAB_FAVORITES = "tab_favorites";
-
 // helper functions
 static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
 static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
@@ -145,69 +142,37 @@ void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder)
 	}
 }
 
-/**
- * Bridge to support knowing when the inventory has changed to update Landmarks tab
- * ShowFolderState filter setting to show all folders when the filter string is empty and
- * empty folder message when Landmarks inventory category has no children.
- * Ensures that "Landmarks" folder in the Library is open on strart up.
- */
-class LLLandmarksPanelObserver : public LLInventoryObserver
-{
-public:
-	LLLandmarksPanelObserver(LLLandmarksPanel* lp)
-	:	mLP(lp),
-	 	mIsLibraryLandmarksOpen(false)
-	{}
-	virtual ~LLLandmarksPanelObserver() {}
-	/*virtual*/ void changed(U32 mask);
-
-private:
-	LLLandmarksPanel* mLP;
-	bool mIsLibraryLandmarksOpen;
-};
-
-void LLLandmarksPanelObserver::changed(U32 mask)
+LLLandmarksPanel::LLLandmarksPanel()
+	:	LLPanelPlacesTab()
+	,	mLandmarksInventoryPanel(NULL)
+	,	mCurrentSelectedList(NULL)
+	,	mGearFolderMenu(NULL)
+	,	mGearLandmarkMenu(NULL)
+	,	mSortingMenu(NULL)
+	,	mAddMenu(NULL)
+	,	isLandmarksPanel(true)
 {
-	mLP->updateShowFolderState();
-
-	LLPlacesInventoryPanel* library = mLP->getLibraryInventoryPanel();
-	if (!mIsLibraryLandmarksOpen && library)
-	{
-		// Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827.
-		const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
-		if (landmarks_cat.notNull())
-		{
-			LLOpenFolderByID opener(landmarks_cat);
-			library->getRootFolder()->applyFunctorRecursively(opener);
-			mIsLibraryLandmarksOpen = opener.isFolderOpen();
-		}
-	}
+	buildFromFile("panel_landmarks.xml");
 }
 
-LLLandmarksPanel::LLLandmarksPanel()
+LLLandmarksPanel::LLLandmarksPanel(bool is_landmark_panel)
 	:	LLPanelPlacesTab()
-	,	mFavoritesInventoryPanel(NULL)
 	,	mLandmarksInventoryPanel(NULL)
-	,	mMyInventoryPanel(NULL)
-	,	mLibraryInventoryPanel(NULL)
 	,	mCurrentSelectedList(NULL)
 	,	mGearFolderMenu(NULL)
 	,	mGearLandmarkMenu(NULL)
 	,	mSortingMenu(NULL)
 	,	mAddMenu(NULL)
+	,	isLandmarksPanel(is_landmark_panel)
 {
-	mInventoryObserver = new LLLandmarksPanelObserver(this);
-	gInventory.addObserver(mInventoryObserver);
-
-	buildFromFile( "panel_landmarks.xml");
+	if (is_landmark_panel)
+	{
+		buildFromFile("panel_landmarks.xml");
+	}
 }
 
 LLLandmarksPanel::~LLLandmarksPanel()
 {
-	if (gInventory.containsObserver(mInventoryObserver))
-	{
-		gInventory.removeObserver(mInventoryObserver);
-	}
 }
 
 BOOL LLLandmarksPanel::postBuild()
@@ -217,17 +182,7 @@ BOOL LLLandmarksPanel::postBuild()
 
 	// mast be called before any other initXXX methods to init Gear menu
 	initListCommandsHandlers();
-
-	initFavoritesInventoryPanel();
 	initLandmarksInventoryPanel();
-	initMyInventoryPanel();
-	initLibraryInventoryPanel();
-
-	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
-	if (accordion)
-	{
-		accordion->setSkipScrollToChild(true);
-	}
 
 	return TRUE;
 }
@@ -235,30 +190,10 @@ BOOL LLLandmarksPanel::postBuild()
 // virtual
 void LLLandmarksPanel::onSearchEdit(const std::string& string)
 {
-	// give FolderView a chance to be refreshed. So, made all accordions visible
-	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
-	{
-		LLAccordionCtrlTab* tab = *iter;
-		tab->setVisible(TRUE);
-
-		// expand accordion to see matched items in each one. See EXT-2014.
-		if (string != "")
-		{
-			tab->changeOpenClose(false);
-		}
-
-		LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());
-		if (NULL == inventory_list) continue;
-
-		filter_list(inventory_list, string);
-	}
+	filter_list(mCurrentSelectedList, string);
 
 	if (sFilterSubString != string)
 		sFilterSubString = string;
-
-	// show all folders in Landmarks Accordion for empty filter
-	// only if Landmarks inventory folder is not empty
-	updateShowFolderState();
 }
 
 // virtual
@@ -349,76 +284,21 @@ LLToggleableMenu* LLLandmarksPanel::getCreateMenu()
     return mAddMenu;
 }
 
-// virtual
 void LLLandmarksPanel::updateVerbs()
 {
-	if (!isTabVisible()) 
-		return;
-}
-
-void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
-{
-	if (user_action && (items.size() > 0))
-	{
-		deselectOtherThan(inventory_list);
-		mCurrentSelectedList = inventory_list;
-	}
-	updateVerbs();
-}
-
-void LLLandmarksPanel::onSelectorButtonClicked()
-{
-	// TODO: mantipov: update getting of selected item
-	// TODO: bind to "i" button
-	LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
-	if (!cur_item) return;
-
-	LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem());
-	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
-	{
-		LLSD key;
-		key["type"] = "landmark";
-		key["id"] = listenerp->getUUID();
-
-		LLFloaterSidePanelContainer::showPanel("places", key);
-	}
-}
-
-void LLLandmarksPanel::updateShowFolderState()
-{
-	bool show_all_folders =   mLandmarksInventoryPanel->getFilterSubString().empty();
-	if (show_all_folders)
-	{
-		show_all_folders = category_has_descendents(mLandmarksInventoryPanel);
-	}
-
-	mLandmarksInventoryPanel->setShowFolderState(show_all_folders ?
-		LLInventoryFilter::SHOW_ALL_FOLDERS :
-		LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
-		);
 }
 
 void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
 {
-	if (selectItemInAccordionTab(mFavoritesInventoryPanel, TAB_FAVORITES, obj_id, take_keyboard_focus))
-	{
-		return;
-	}
-
-	if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus))
-	{
+	if (!mCurrentSelectedList)
 		return;
-	}
-
-	if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus))
-	{
-		return;
-	}
 
-	if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus))
-	{
+	LLFolderView* root = mCurrentSelectedList->getRootFolder();
+	LLFolderViewItem* item = mCurrentSelectedList->getItemByID(obj_id);
+	if (!item)
 		return;
-	}
+	root->setSelection(item, FALSE, take_keyboard_focus);
+	root->scrollToShowSelection();
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -437,18 +317,6 @@ bool LLLandmarksPanel::isFolderSelected() const
 	return current_item && (current_item->getInventoryType() == LLInventoryType::IT_CATEGORY);
 }
 
-bool LLLandmarksPanel::isReceivedFolderSelected() const
-{
-	// Received Folder can be only in Landmarks accordion
-	if (mCurrentSelectedList != mLandmarksInventoryPanel) return false;
-
-	// *TODO: it should be filled with logic when EXT-976 is done.
-
-	LL_WARNS() << "Not implemented yet until EXT-976 is done." << LL_ENDL;
-
-	return false;
-}
-
 void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)
 {
 	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();
@@ -478,36 +346,6 @@ LLFolderViewModelItemInventory* LLLandmarksPanel::getCurSelectedViewModelItem()
 }
 
 
-LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
-															 const std::string& tab_name,
-															 const LLUUID& obj_id,
-															 BOOL take_keyboard_focus) const
-{
-	if (!inventory_list)
-		return NULL;
-
-	LLFolderView* root = inventory_list->getRootFolder();
-
-	LLFolderViewItem* item = inventory_list->getItemByID(obj_id);
-	if (!item)
-		return NULL;
-
-	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(tab_name);
-	if (!tab->isExpanded())
-	{
-		tab->changeOpenClose(false);
-	}
-
-	root->setSelection(item, FALSE, take_keyboard_focus);
-
-	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
-	LLRect screen_rc;
-	localRectToScreen(item->getRect(), &screen_rc);
-	accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue()));
-
-	return item;
-}
-
 void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
 {
 	if(!panel) return; 
@@ -525,8 +363,6 @@ void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
 
 void LLLandmarksPanel::resetSelection()
 {
-	getChild<LLAccordionCtrlTab>(TAB_FAVORITES)->setDisplayChildren(true);
-	getChild<LLAccordionCtrlTab>(TAB_FAVORITES)->showAndFocusHeader();
 }
 
 // virtual
@@ -572,16 +408,6 @@ void LLLandmarksPanel::setErrorStatus(S32 status, const std::string& reason)
 // PRIVATE METHODS
 //////////////////////////////////////////////////////////////////////////
 
-void LLLandmarksPanel::initFavoritesInventoryPanel()
-{
-	mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");
-
-	initLandmarksPanel(mFavoritesInventoryPanel);
-	mFavoritesInventoryPanel->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems");
-
-	initAccordion(TAB_FAVORITES, mFavoritesInventoryPanel, true);
-}
-
 void LLLandmarksPanel::initLandmarksInventoryPanel()
 {
 	mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list");
@@ -593,40 +419,13 @@ void LLLandmarksPanel::initLandmarksInventoryPanel()
 	// subscribe to have auto-rename functionality while creating New Folder
 	mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2));
 
-	mMyLandmarksAccordionTab = initAccordion("tab_landmarks", mLandmarksInventoryPanel, true);
-}
-
-void LLLandmarksPanel::initMyInventoryPanel()
-{
-	mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list");
-
-	initLandmarksPanel(mMyInventoryPanel);
-
-	initAccordion("tab_inventory", mMyInventoryPanel, false);
-}
-
-void LLLandmarksPanel::initLibraryInventoryPanel()
-{
-	mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list");
-
-	initLandmarksPanel(mLibraryInventoryPanel);
-
-	// We want to fetch only "Landmarks" category from the library.
-	const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
-	if (landmarks_cat.notNull())
-	{
-		LLInventoryModelBackgroundFetch::instance().start(landmarks_cat);
-	}
-
-	// Expanding "Library" tab for new users who have no landmarks in "My Inventory".
-	initAccordion("tab_library", mLibraryInventoryPanel, true);
+	mCurrentSelectedList = mLandmarksInventoryPanel;
 }
 
 void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list)
 {
 	inventory_list->getFilter().setEmptyLookupMessage("PlacesNoMatchingItems");
 	inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
-	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
 
 	inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
 	bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
@@ -644,71 +443,6 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list
 	inventory_list->saveFolderState();
 }
 
-LLAccordionCtrlTab* LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list,	bool expand_tab)
-{
-	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
-
-	mAccordionTabs.push_back(accordion_tab);
-	accordion_tab->setDropDownStateChangedCallback(
-		boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
-	accordion_tab->setDisplayChildren(expand_tab);
-	return accordion_tab;
-}
-
-void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list)
-{
-	bool expanded = param.asBoolean();
-
-	if(!expanded && (mCurrentSelectedList == inventory_list))
-	{
-		inventory_list->getRootFolder()->clearSelection();
-
-		mCurrentSelectedList = NULL;
-		updateVerbs();
-	}
-
-	// Start background fetch, mostly for My Inventory and Library
-	if (expanded)
-	{
-		const LLUUID &cat_id = inventory_list->getRootFolderID();
-		// Just because the category itself has been fetched, doesn't mean its child folders have.
-		/*
-		  if (!gInventory.isCategoryComplete(cat_id))
-		*/
-		{
-			LLInventoryModelBackgroundFetch::instance().start(cat_id);
-		}
-
-		// Apply filter substring because it might have been changed
-		// while accordion was closed. See EXT-3714.
-		filter_list(inventory_list, sFilterSubString);
-	}
-}
-
-void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list)
-{
-	if (inventory_list != mFavoritesInventoryPanel)
-	{
-		mFavoritesInventoryPanel->clearSelection();
-		mFavoritesInventoryPanel->getRootFolder()->clearSelection();
-	}
-
-	if (inventory_list != mLandmarksInventoryPanel)
-	{
-		mLandmarksInventoryPanel->clearSelection();
-		mLandmarksInventoryPanel->getRootFolder()->clearSelection();
-	}
-	if (inventory_list != mMyInventoryPanel)
-	{
-		mMyInventoryPanel->clearSelection();
-		mMyInventoryPanel->getRootFolder()->clearSelection();
-	}
-	if (inventory_list != mLibraryInventoryPanel)
-	{
-		mLibraryInventoryPanel->clearSelection();
-		mLibraryInventoryPanel->getRootFolder()->clearSelection();
-	}
-}
 
 // List Commands Handlers
 void LLLandmarksPanel::initListCommandsHandlers()
@@ -730,6 +464,7 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	// show menus even if all items are disabled
 	mGearLandmarkMenu->setAlwaysShowMenu(TRUE);
 	mGearFolderMenu->setAlwaysShowMenu(TRUE);
+	mAddMenu->setAlwaysShowMenu(TRUE);
 }
 
 void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu)
@@ -797,11 +532,6 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 			//in case My Landmarks tab is completely empty (thus cannot be determined as being selected)
 			menu_create_inventory_item(mLandmarksInventoryPanel, NULL,  LLSD("category"), 
 				gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
-
-			if (mMyLandmarksAccordionTab)
-			{
-				mMyLandmarksAccordionTab->changeOpenClose(false);
-			}
 		}
 	}
     else if ("category_root" == command_name)
@@ -809,11 +539,6 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
         //in case My Landmarks tab is completely empty (thus cannot be determined as being selected)
         menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"),
             gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
-
-        if (mMyLandmarksAccordionTab)
-        {
-            mMyLandmarksAccordionTab->changeOpenClose(false);
-        }
     }
 }
 
@@ -848,27 +573,11 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
 
 	if ("expand_all" == command_name)
 	{
-		expand_all_folders(mFavoritesInventoryPanel->getRootFolder());
-		expand_all_folders(mLandmarksInventoryPanel->getRootFolder());
-		expand_all_folders(mMyInventoryPanel->getRootFolder());
-		expand_all_folders(mLibraryInventoryPanel->getRootFolder());
-
-		for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
-		{
-			(*iter)->changeOpenClose(false);
-		}
+		expand_all_folders(mCurrentSelectedList->getRootFolder());
 	}
 	else if ("collapse_all" == command_name)
 	{
-		collapse_all_folders(mFavoritesInventoryPanel->getRootFolder());
-		collapse_all_folders(mLandmarksInventoryPanel->getRootFolder());
-		collapse_all_folders(mMyInventoryPanel->getRootFolder());
-		collapse_all_folders(mLibraryInventoryPanel->getRootFolder());
-
-		for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
-		{
-			(*iter)->changeOpenClose(true);
-		}
+		collapse_all_folders(mCurrentSelectedList->getRootFolder());
 	}
 	else if ("sort_by_date" == command_name)
 	{
@@ -876,8 +585,6 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
 		sorting_order=!sorting_order;
 		gSavedSettings.setBOOL("LandmarksSortedByDate",sorting_order);
 		updateSortOrder(mLandmarksInventoryPanel, sorting_order);
-		updateSortOrder(mMyInventoryPanel, sorting_order);
-		updateSortOrder(mLibraryInventoryPanel, sorting_order);
 	}
 	else
 	{
@@ -911,49 +618,17 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 	if ("collapse_all" == command_name)
 	{
-		bool disable_collapse_all =	!has_expanded_folders(mFavoritesInventoryPanel->getRootFolder())
-									&& !has_expanded_folders(mLandmarksInventoryPanel->getRootFolder())
-									&& !has_expanded_folders(mMyInventoryPanel->getRootFolder())
-									&& !has_expanded_folders(mLibraryInventoryPanel->getRootFolder());
-		if (disable_collapse_all)
-		{
-			for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
-			{
-				if ((*iter)->isExpanded())
-				{
-					disable_collapse_all = false;
-					break;
-				}
-			}
-		}
-
-		return !disable_collapse_all;
+		return has_expanded_folders(mCurrentSelectedList->getRootFolder());
 	}
 	else if ("expand_all" == command_name)
 	{
-		bool disable_expand_all = !has_collapsed_folders(mFavoritesInventoryPanel->getRootFolder())
-								  && !has_collapsed_folders(mLandmarksInventoryPanel->getRootFolder())
-								  && !has_collapsed_folders(mMyInventoryPanel->getRootFolder())
-								  && !has_collapsed_folders(mLibraryInventoryPanel->getRootFolder());
-		if (disable_expand_all)
-		{
-			for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
-			{
-				if (!(*iter)->isExpanded())
-				{
-					disable_expand_all = false;
-					break;
-				}
-			}
-		}
-
-		return !disable_expand_all;
+		return has_collapsed_folders(mCurrentSelectedList->getRootFolder());
 	}
 	else if ("sort_by_date"	== command_name)
 	{
-		// disable "sort_by_date" for Favorites accordion because
+		// disable "sort_by_date" for Favorites tab because
 		// it has its own items order. EXT-1758
-		if (mCurrentSelectedList == mFavoritesInventoryPanel)
+		if (!isLandmarksPanel)
 		{
 			return false;
 		}
@@ -970,6 +645,11 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 		std::set<LLFolderViewItem*> selected_uuids =    root_folder_view->getSelectionList();
 
+		if (selected_uuids.empty())
+		{
+			return false;
+		}
+		
 		// Allow to execute the command only if it can be applied to all selected items.
 		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_uuids.begin(); iter != selected_uuids.end(); ++iter)
 		{
@@ -1020,25 +700,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 		return true;
 	}
-    if ("category_root" == command_name)
+    if ("category_root" == command_name || "category" == command_name)
     {
-        // Landmarks Accordion
-        return true;
-    }
-	else if("category" == command_name)
-	{
-		// we can add folder only in Landmarks Accordion
-		if (mCurrentSelectedList == mLandmarksInventoryPanel)
-		{
-			// ... but except Received folder
-			return !isReceivedFolderSelected();
-		}
-		if (mCurrentSelectedList == mLibraryInventoryPanel)
-		{
-			return false;
-		}
-		//"Add a folder" is enabled by default (case when My Landmarks is empty)
-		return true;
+		// we can add folder only in Landmarks tab
+		return isLandmarksPanel;
 	}
 	else if("create_pick" == command_name)
 	{
@@ -1059,10 +724,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
         {
             return false;
         }
-        if (mCurrentSelectedList == mLibraryInventoryPanel)
-        {
-            return false;
-        }
+
         LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem();
         if (!view_model || view_model->getInventoryType() != LLInventoryType::IT_CATEGORY)
         {
@@ -1203,29 +865,17 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold
 
 	if (!item) return false;
 
-	// nothing can be modified in Library
-	if (mLibraryInventoryPanel == mCurrentSelectedList) return false;
-
 	bool can_be_modified = false;
 
 	// landmarks can be modified in any other accordion...
 	if (static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem())->getInventoryType() == LLInventoryType::IT_LANDMARK)
 	{
 		can_be_modified = true;
-
-		// we can modify landmarks anywhere except paste to My Inventory
-		if ("paste" == command_name)
-		{
-			can_be_modified = (mCurrentSelectedList != mMyInventoryPanel);
-		}
 	}
 	else
 	{
 		// ...folders only in the Landmarks accordion...
-		can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList;
-
-		// ...except "Received" folder
-		can_be_modified &= !isReceivedFolderSelected();
+		can_be_modified = isLandmarksPanel;
 	}
 
 	// then ask LLFolderView permissions
@@ -1325,7 +975,6 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
 		break;
 	}
 
-	updateVerbs();
 	return true;
 }
 
@@ -1470,10 +1119,6 @@ static void collapse_all_folders(LLFolderView* root_folder)
 		return;
 
 	root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
-
-	// The top level folder is invisible, it must be open to
-	// display its sub-folders.
-	root_folder->openTopLevelFolders();
 	root_folder->arrangeAll();
 }
 
@@ -1540,4 +1185,31 @@ void toggle_restore_menu(LLMenuGL *menu, BOOL visible, BOOL enabled)
 		}
 	}
 }
+
+LLFavoritesPanel::LLFavoritesPanel()
+	:	LLLandmarksPanel(false)
+{
+	buildFromFile("panel_favorites.xml");
+}
+
+BOOL LLFavoritesPanel::postBuild()
+{
+	if (!gInventory.isInventoryUsable())
+		return FALSE;
+
+	// mast be called before any other initXXX methods to init Gear menu
+	LLLandmarksPanel::initListCommandsHandlers();
+
+	initFavoritesInventoryPanel();
+
+	return TRUE;
+}
+
+void LLFavoritesPanel::initFavoritesInventoryPanel()
+{
+	mCurrentSelectedList = getChild<LLPlacesInventoryPanel>("favorites_list");
+
+	LLLandmarksPanel::initLandmarksPanel(mCurrentSelectedList);
+	mCurrentSelectedList->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems");
+}
 // EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 95256f4bb4..d7408269b5 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -50,6 +50,7 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 {
 public:
 	LLLandmarksPanel();
+	LLLandmarksPanel(bool is_landmark_panel);
 	virtual ~LLLandmarksPanel();
 
 	BOOL postBuild() override;
@@ -70,26 +71,16 @@ public:
      */
     bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override;
 
-	void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
-	void onSelectorButtonClicked();
 	void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list)
 	{
 		mCurrentSelectedList = inventory_list;
 	}
 
-	/**
-	 * 	Update filter ShowFolderState setting to show empty folder message
-	 *  if Landmarks inventory folder is empty.
-	 */
-	void updateShowFolderState();
-
 	/**
 	 * Selects item with "obj_id" in one of accordion tabs.
 	 */
 	void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus);
 
-	LLPlacesInventoryPanel* getLibraryInventoryPanel() { return mLibraryInventoryPanel; }
-
 	void updateMenuVisibility(LLUICtrl* menu);
 
 	void doCreatePick(LLLandmark* landmark, const LLUUID &item_id );
@@ -102,40 +93,26 @@ protected:
 	 */
 	bool isLandmarkSelected() const;
 	bool isFolderSelected() const;
-	bool isReceivedFolderSelected() const;
 	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);
 	LLFolderViewItem* getCurSelectedItem() const;
 	LLFolderViewModelItemInventory* getCurSelectedViewModelItem() const;
 
-	/**
-	 * Selects item with "obj_id" in "inventory_list" and scrolls accordion
-	 * scrollbar to show the item.
-	 * Returns pointer to the item if it is found in "inventory_list", otherwise NULL.
-	 */
-	LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
-											   const std::string& tab_name,
-											   const LLUUID& obj_id,
-											   BOOL take_keyboard_focus) const;
-
 	void updateSortOrder(LLInventoryPanel* panel, bool byDate);
 
 	//LLRemoteParcelInfoObserver interface
 	void processParcelInfo(const LLParcelData& parcel_data) override;
 	void setParcelID(const LLUUID& parcel_id) override;
 	void setErrorStatus(S32 status, const std::string& reason) override;
+
+	// List Commands Handlers
+	void initListCommandsHandlers();
+	void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list);
+
+	LLPlacesInventoryPanel*		mCurrentSelectedList;
 	
 private:
-	void initFavoritesInventoryPanel();
 	void initLandmarksInventoryPanel();
-	void initMyInventoryPanel();
-	void initLibraryInventoryPanel();
-	void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list);
-	LLAccordionCtrlTab* initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list, bool expand_tab);
-	void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list);
-	void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list);
 
-	// List Commands Handlers
-	void initListCommandsHandlers();
 	void onTrashButtonClick() const;
 	void onAddAction(const LLSD& command_name) const;
 	void onClipboardAction(const LLSD& command_name) const;
@@ -170,23 +147,25 @@ private:
 							 const LLParcelData& parcel_data);
 
 private:
-	LLPlacesInventoryPanel*		mFavoritesInventoryPanel;
 	LLPlacesInventoryPanel*		mLandmarksInventoryPanel;
-	LLPlacesInventoryPanel*		mMyInventoryPanel;
-	LLPlacesInventoryPanel*		mLibraryInventoryPanel;
 	LLToggleableMenu*			mGearLandmarkMenu;
 	LLToggleableMenu*			mGearFolderMenu;
 	LLToggleableMenu*			mSortingMenu;
 	LLToggleableMenu*			mAddMenu;
-	LLPlacesInventoryPanel*		mCurrentSelectedList;
-	LLInventoryObserver*		mInventoryObserver;
+
+	bool						isLandmarksPanel;
 	
-	typedef	std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
-	accordion_tabs_t			mAccordionTabs;
+    LLUUID                      mCreatePickItemId; // item we requested a pick for
+};
 
-	LLAccordionCtrlTab*			mMyLandmarksAccordionTab;
 
-    LLUUID                      mCreatePickItemId; // item we requested a pick for
+class LLFavoritesPanel : public LLLandmarksPanel
+{
+public:
+	LLFavoritesPanel();
+
+	BOOL postBuild() override;
+	void initFavoritesInventoryPanel();
 };
 
 #endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 11ae980941..7928896d96 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -1119,8 +1119,16 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
 		}
 		else
 		{
-			LLLandmarksPanel* landmarks_panel =
-					dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
+			std::string tab_panel_name("Landmarks");
+			if (mItem.notNull())
+			{
+				if (gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)))
+				{
+					tab_panel_name = "Favorites";
+				}
+			}
+			
+			LLLandmarksPanel* landmarks_panel = dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName(tab_panel_name));
 			if (landmarks_panel)
 			{
 				// If a landmark info is being closed we open the landmarks tab
@@ -1201,6 +1209,16 @@ void LLPanelPlaces::createTabs()
 	if (!(gInventory.isInventoryUsable() && LLTeleportHistory::getInstance() && !mTabsCreated))
 		return;
 
+	LLFavoritesPanel* favorites_panel = new LLFavoritesPanel();
+	if (favorites_panel)
+	{
+		mTabContainer->addTabPanel(
+			LLTabContainer::TabPanelParams().
+			panel(favorites_panel).
+			label(getString("favorites_tab_title")).
+			insert_at(LLTabContainer::END));
+	}
+
 	LLLandmarksPanel* landmarks_panel = new LLLandmarksPanel();
 	if (landmarks_panel)
 	{
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index df1139c98f..e9ada52a8f 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -27,6 +27,9 @@
         <on_enable
          function="Places.LandmarksGear.Enable"
          parameter="category" />
+        <on_visible
+         function="Places.LandmarksGear.Enable"
+         parameter="category" />
     </menu_item_call>
     <menu_item_call
      label="Restore Item"
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml b/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
index 6548fadfa5..4193a72e2e 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
@@ -39,5 +39,8 @@
         <on_click
          function="Places.LandmarksGear.Folding.Action"
          parameter="sort_by_date" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="sort_by_date" />
     </menu_item_check>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_favorites.xml b/indra/newview/skins/default/xui/en/panel_favorites.xml
new file mode 100644
index 0000000000..1e8ea34ad2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_favorites.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+   name="Favorites"
+   layout="topleft" 
+   left="0"
+   border="false"
+   background_visible="true"
+   bg_alpha_color="DkGray"
+   follows="all">
+    <places_inventory_panel
+      allow_multi_select="true"
+      border="false"
+      top="1"
+      left="3"
+      bottom="0"
+      follows="all"
+      right="-3"
+      mouse_opaque="true"
+      name="favorites_list"
+      folder_view.use_ellipses="true"
+      start_folder.name="Favorites"/>        
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index af2115156e..10b925ec93 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -1,98 +1,23 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
    name="Landmarks"
-   top="0"
-   height="400"
    layout="topleft" 
    left="0"
-   width="313"
    help_topic="panel_landmarks"
    border="false"
    background_visible="true"
    bg_alpha_color="DkGray"
    follows="all">
-    <accordion
-     background_visible="true"
-     bg_alpha_color="DkGray2"
-     bg_opaque_color="DkGray2"
-     follows="all"
-     height="398"
-     layout="topleft"
-     left="3"
-     name="landmarks_accordion"
-     top="0"
-     width="307">
-        <accordion_tab
-         layout="topleft"
-         name="tab_favorites"
-         title="Favorites bar">
-            <places_inventory_panel
-             allow_multi_select="true"
-             border="false"
-             bottom="0"
-             follows="all"
-             height="126"
-             left="0"
-             mouse_opaque="true"
-             name="favorites_list"
-             scroll.hide_scrollbar="true"
-             folder_view.use_ellipses="true"
-             start_folder.name="Favorites"
-             width="307"/>
-        </accordion_tab>
-        <accordion_tab
-         layout="topleft"
-         name="tab_landmarks"
-         title="My Landmarks">
-            <places_inventory_panel
-             allow_multi_select="true"
-             border="false"
-             bottom="0"
-             follows="all"
-             height="126"
-             left="0"
-             mouse_opaque="true"
-             name="landmarks_list"
-             scroll.hide_scrollbar="true"
-             folder_view.use_ellipses="true"
-             start_folder.name="Landmarks"
-             width="307"/>
-        </accordion_tab>
-        <accordion_tab
-         layout="topleft"
-         name="tab_inventory"
-         title="My Inventory">
-            <places_inventory_panel
-             allow_multi_select="true"
-             border="false"
-             bottom="0"
-             follows="all"
-             height="126"
-             left="0"
-             mouse_opaque="true"
-             name="my_inventory_list"
-             scroll.hide_scrollbar="true"
-             folder_view.use_ellipses="true"
-             start_folder.name="My Inventory"
-             width="307"/>
-          </accordion_tab>
-          <accordion_tab
-           layout="topleft"
-           name="tab_library"
-           title="Library">
-            <places_inventory_panel
-             allow_multi_select="true"
-             border="false"
-             bottom="0"
-             follows="all"
-             height="126"
-             left="0"
-             mouse_opaque="true"
-             name="library_list"
-             scroll.hide_scrollbar="true"
-             folder_view.use_ellipses="true"
-             start_folder.name="LIBRARY"
-             width="313"/>
-        </accordion_tab>
-    </accordion>
+    <places_inventory_panel
+      allow_multi_select="true"
+      border="false"
+      top="1"
+      follows="all"
+      left="3"
+      bottom="0"
+      right="-3"
+      mouse_opaque="true"
+      name="landmarks_list"
+      folder_view.use_ellipses="true"
+      start_folder.name="Landmarks"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index eed56209b7..dd4cf7ab4e 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -13,10 +13,13 @@ background_visible="true"
  width="333">
   <string
    name="landmarks_tab_title"
-   value="MY LANDMARKS" />
+   value="LANDMARKS" />
   <string
    name="teleport_history_tab_title"
-   value="PLACES VISITED" />
+   value="VISITED" />
+  <string
+   name="favorites_tab_title"
+   value="FAVORITES" />
   <layout_stack
     animate="false"
     border_size="0"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 20ef10f172..d9d0b659cc 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2298,8 +2298,8 @@ For AI Character: Get the closest navigable point to the point provided.
 	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
 	<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
 	<string name="InventoryFavoritItemsNotSelected">Click "Use as Favorites folder" on a folder of your choice. You can choose a different folder at any time. System folders and folders inside them cannot be used for Favorites.</string>
-	<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
-	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
+	<string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string>
+	<string name="FavoritesNoMatchingItems">To add a place to your favorites bar, click the star to the right of the location name.</string>
 	<string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string>
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
 	<string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string>
-- 
cgit v1.2.3


From e48ce282784d508ecc58efbb771d2e717df5d3c8 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 16 Mar 2021 20:32:31 +0200
Subject: SL-14936 Do not create a saved outfit automatically for new users

---
 indra/newview/llstartup.cpp | 23 -----------------------
 indra/newview/llstartup.h   |  3 ---
 2 files changed, 26 deletions(-)

diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3c250b3bb3..aa206a3cce 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -230,7 +230,6 @@ extern S32 gStartImageHeight;
 static bool gGotUseCircuitCodeAck = false;
 static std::string sInitialOutfit;
 static std::string sInitialOutfitGender;	// "male" or "female"
-static boost::signals2::connection sWearablesLoadedCon;
 
 static bool gUseCircuitCallbackCalled = false;
 
@@ -2702,11 +2701,6 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 	}
 	else
 	{
-		// FIXME SH-3860 - this creates a race condition, where COF
-		// changes (base outfit link added) after appearance update
-		// request has been submitted.
-		sWearablesLoadedCon = gAgentWearables.addLoadedCallback(LLStartUp::saveInitialOutfit);
-
 		bool do_copy = true;
 		bool do_append = false;
 		LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
@@ -2720,23 +2714,6 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 	gAgentWearables.sendDummyAgentWearablesUpdate();
 }
 
-//static
-void LLStartUp::saveInitialOutfit()
-{
-	if (sInitialOutfit.empty()) {
-		LL_DEBUGS() << "sInitialOutfit is empty" << LL_ENDL;
-		return;
-	}
-	
-	if (sWearablesLoadedCon.connected())
-	{
-		LL_DEBUGS("Avatar") << "sWearablesLoadedCon is connected, disconnecting" << LL_ENDL;
-		sWearablesLoadedCon.disconnect();
-	}
-	LL_DEBUGS("Avatar") << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << LL_ENDL;
-	LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false);
-}
-
 std::string& LLStartUp::getInitialOutfitName()
 {
 	return sInitialOutfit;
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index 3ec3ff4133..116aeb36a7 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -110,9 +110,6 @@ public:
 	static void loadInitialOutfit( const std::string& outfit_folder_name,
 								   const std::string& gender_name );
 
-	//save loaded initial outfit into My Outfits category
-	static void saveInitialOutfit();
-
 	static std::string& getInitialOutfitName();
 	static std::string getUserId();
 	
-- 
cgit v1.2.3


From 38db12920c92b00e11aa533980790e8572ba6908 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 18 Mar 2021 20:18:23 +0200
Subject: SL-14901 adjusted 'More' button

---
 indra/newview/llfavoritesbar.cpp                            | 2 ++
 indra/newview/skins/default/xui/en/panel_navigation_bar.xml | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 2394a763ee..8791f605e9 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -402,6 +402,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
 	mMoreTextBox = LLUICtrlFactory::create<LLTextBox> (more_button_params);
 	mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
 	addChild(mMoreTextBox);
+	LLRect rect = mMoreTextBox->getRect();
+	mMoreTextBox->setRect(LLRect(rect.mLeft - rect.getWidth(), rect.mTop, rect.mRight, rect.mBottom));
 
 	mDropDownItemsCount = 0;
 
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index d3448ed0ba..2dae2649a9 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -187,7 +187,7 @@
              name="favorite"
              image_drag_indication="Accordion_ArrowOpened_Off"
              tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
-             width="268">
+             width="310">
             <label
              follows="left|top"
              height="13"
-- 
cgit v1.2.3


From d43d8bc68b4cbe40e2fb39dea0530a152463d1f9 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 23 Mar 2021 17:38:22 +0200
Subject: SL-14900 new Landmark creation flow

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/llfloatercreatelandmark.cpp          | 314 +++++++++++++++++++++
 indra/newview/llfloatercreatelandmark.h            |  75 +++++
 indra/newview/lllocationinputctrl.cpp              |   5 +-
 indra/newview/llpanellandmarkinfo.cpp              |  29 +-
 indra/newview/llpanellandmarkinfo.h                |  16 ++
 indra/newview/llpanellandmarks.cpp                 |   2 +-
 indra/newview/llpanelplaces.cpp                    |  28 --
 indra/newview/llpaneltopinfobar.cpp                |   3 +-
 indra/newview/lltoastalertpanel.cpp                |   2 +-
 indra/newview/llviewerfloaterreg.cpp               |   2 +
 indra/newview/llviewermenu.cpp                     |   2 +-
 .../default/xui/en/floater_create_landmark.xml     | 110 ++++++++
 .../newview/skins/default/xui/en/notifications.xml |  23 ++
 14 files changed, 566 insertions(+), 47 deletions(-)
 create mode 100644 indra/newview/llfloatercreatelandmark.cpp
 create mode 100644 indra/newview/llfloatercreatelandmark.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_create_landmark.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1520c0ee69..5437f48abe 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -233,6 +233,7 @@ set(viewer_SOURCE_FILES
     llfloatercolorpicker.cpp
     llfloaterconversationlog.cpp
     llfloaterconversationpreview.cpp
+    llfloatercreatelandmark.cpp
     llfloaterdeleteprefpreset.cpp
     llfloaterdestinations.cpp
     llfloatereditextdaycycle.cpp
@@ -865,6 +866,7 @@ set(viewer_HEADER_FILES
     llfloatercolorpicker.h
     llfloaterconversationlog.h
     llfloaterconversationpreview.h
+    llfloatercreatelandmark.h
     llfloaterdeleteprefpreset.h
     llfloaterdestinations.h
     llfloatereditextdaycycle.h
diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
new file mode 100644
index 0000000000..95ddacbb6c
--- /dev/null
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -0,0 +1,314 @@
+/** 
+ * @file llfloatercreatelandmark.cpp
+ * @brief LLFloaterCreateLandmark class implementation
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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 "llfloatercreatelandmark.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "llcombobox.h"
+#include "llinventoryfunctions.h"
+#include "llinventoryobserver.h"
+#include "lllandmarkactions.h"
+#include "llnotificationsutil.h"
+#include "llpanellandmarkinfo.h"
+#include "llparcel.h"
+#include "lltextbox.h"
+#include "lltexteditor.h"
+#include "lluictrlfactory.h"
+#include "llviewermessage.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+
+typedef std::pair<LLUUID, std::string> folder_pair_t;
+
+class LLLandmarksInventoryObserver : public LLInventoryAddedObserver
+{
+public:
+	LLLandmarksInventoryObserver(LLFloaterCreateLandmark* create_landmark_floater) :
+		mFloater(create_landmark_floater)
+	{}
+
+protected:
+	/*virtual*/ void done()
+	{
+		mFloater->setItem(gInventory.getAddedIDs());
+	}
+
+private:
+	LLFloaterCreateLandmark* mFloater;
+};
+
+LLFloaterCreateLandmark::LLFloaterCreateLandmark(const LLSD& key)
+	:	LLFloater("add_landmark"),
+		mItem(NULL)
+{
+	mInventoryObserver = new LLLandmarksInventoryObserver(this);
+}
+
+LLFloaterCreateLandmark::~LLFloaterCreateLandmark()
+{
+	removeObserver();
+}
+
+BOOL LLFloaterCreateLandmark::postBuild()
+{
+	mFolderCombo = getChild<LLComboBox>("folder_combo");
+	mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor");
+	mNotesEditor = getChild<LLTextEditor>("notes_editor");
+
+	getChild<LLTextBox>("new_folder_textbox")->setURLClickedCallback(boost::bind(&LLFloaterCreateLandmark::onCreateFolderClicked, this));
+	getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onSaveClicked, this));
+	getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onCancelClicked, this));
+
+	mLandmarksID = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
+
+	return TRUE;
+}
+
+void LLFloaterCreateLandmark::removeObserver()
+{
+	if (gInventory.containsObserver(mInventoryObserver))
+		gInventory.removeObserver(mInventoryObserver);
+}
+
+void LLFloaterCreateLandmark::onOpen(const LLSD& key)
+{
+	LLUUID dest_folder = LLUUID();
+	if (key.has("dest_folder"))
+	{
+		dest_folder = key["dest_folder"].asUUID();
+	}
+	mItem = NULL;
+	gInventory.addObserver(mInventoryObserver);
+	setLandmarkInfo(dest_folder);
+	populateFoldersList(dest_folder);
+}
+
+void LLFloaterCreateLandmark::setLandmarkInfo(const LLUUID &folder_id)
+{
+	LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+	LLParcel* parcel = parcel_mgr->getAgentParcel();
+	std::string name = parcel->getName();
+	LLVector3 agent_pos = gAgent.getPositionAgent();
+
+	if (name.empty())
+	{
+		S32 region_x = ll_round(agent_pos.mV[VX]);
+		S32 region_y = ll_round(agent_pos.mV[VY]);
+		S32 region_z = ll_round(agent_pos.mV[VZ]);
+
+		std::string region_name;
+		LLViewerRegion* region = parcel_mgr->getSelectionRegion();
+		if (region)
+		{
+			region_name = region->getName();
+		}
+		else
+		{
+			std::string desc;
+			LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos);
+			region_name = desc;
+		}
+
+		mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)",
+			region_name.c_str(), region_x, region_y, region_z));
+	}
+	else
+	{
+		mLandmarkTitleEditor->setText(name);
+	}
+
+	LLLandmarkActions::createLandmarkHere(name, "", folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
+}
+
+bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
+{
+	return left.second < right.second;
+}
+
+void LLFloaterCreateLandmark::populateFoldersList(const LLUUID &folder_id)
+{
+	// Collect all folders that can contain landmarks.
+	LLInventoryModel::cat_array_t cats;
+	LLPanelLandmarkInfo::collectLandmarkFolders(cats);
+
+	mFolderCombo->removeall();
+
+	// Put the "My Favorites" folder first in list.
+	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+	LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id);
+	if (!favorites_cat)
+	{
+		LL_WARNS() << "Cannot find the favorites folder" << LL_ENDL;
+	}
+	else
+	{
+		mFolderCombo->add(getString("favorites_bar"), favorites_cat->getUUID());
+	}
+
+	// Add the "Landmarks" category. 
+	const LLViewerInventoryCategory* lmcat = gInventory.getCategory(mLandmarksID);
+	if (!lmcat)
+	{
+		LL_WARNS() << "Cannot find the landmarks folder" << LL_ENDL;
+	}
+	else
+	{
+		std::string cat_full_name = LLPanelLandmarkInfo::getFullFolderName(lmcat);
+		mFolderCombo->add(cat_full_name, lmcat->getUUID());
+	}
+
+	typedef std::vector<folder_pair_t> folder_vec_t;
+	folder_vec_t folders;
+	// Sort the folders by their full name.
+	for (S32 i = 0; i < cats.size(); i++)
+	{
+		const LLViewerInventoryCategory* cat = cats.at(i);
+		std::string cat_full_name = LLPanelLandmarkInfo::getFullFolderName(cat);
+		folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name));
+	}
+	sort(folders.begin(), folders.end(), cmp_folders);
+
+	// Finally, populate the combobox.
+	for (folder_vec_t::const_iterator it = folders.begin(); it != folders.end(); it++)
+		mFolderCombo->add(it->second, LLSD(it->first));
+
+	if (folder_id.notNull())
+	{
+		mFolderCombo->setCurrentByID(folder_id);
+	}
+}
+
+void LLFloaterCreateLandmark::onCreateFolderClicked()
+{
+	LLNotificationsUtil::add("CreateLandmarkFolder", LLSD(), LLSD(),
+		[this](const LLSD&notif, const LLSD&resp)
+	{
+		S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+		if (opt == 0)
+		{
+			std::string folder_name = resp["message"].asString();
+			if (!folder_name.empty())
+			{
+				inventory_func_type func = boost::bind(&LLFloaterCreateLandmark::folderCreatedCallback, this, _1);
+				LLUUID test = gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, func);
+				gInventory.notifyObservers();
+			}
+		}
+	}); 
+}
+
+void LLFloaterCreateLandmark::folderCreatedCallback(LLUUID folder_id)
+{
+	populateFoldersList(folder_id);
+}
+
+void LLFloaterCreateLandmark::onSaveClicked()
+{
+	if (mItem.isNull())
+		return;
+
+	std::string current_title_value = mLandmarkTitleEditor->getText();
+	std::string item_title_value = mItem->getName();
+	std::string current_notes_value = mNotesEditor->getText();
+	std::string item_notes_value = mItem->getDescription();
+
+	LLStringUtil::trim(current_title_value);
+	LLStringUtil::trim(current_notes_value);
+
+	LLUUID item_id = mItem->getUUID();
+	LLUUID folder_id = mFolderCombo->getValue().asUUID();
+	bool change_parent = folder_id != mItem->getParentUUID();
+
+	LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem);
+
+	if (!current_title_value.empty() &&
+		(item_title_value != current_title_value || item_notes_value != current_notes_value))
+	{
+		new_item->rename(current_title_value);
+		new_item->setDescription(current_notes_value);
+		LLPointer<LLInventoryCallback> cb;
+		if (change_parent)
+		{
+			cb = new LLUpdateLandmarkParent(new_item, folder_id);
+		}
+		LLInventoryModel::LLCategoryUpdate up(mItem->getParentUUID(), 0);
+		gInventory.accountForUpdate(up);
+		update_inventory_item(new_item, cb);
+	}
+	else if (change_parent)
+	{
+		LLInventoryModel::update_list_t update;
+		LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1);
+		update.push_back(old_folder);
+		LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1);
+		update.push_back(new_folder);
+		gInventory.accountForUpdate(update);
+
+		new_item->setParent(folder_id);
+		new_item->updateParentOnServer(FALSE);
+	}
+
+	gInventory.updateItem(new_item);
+	gInventory.notifyObservers();
+
+	closeFloater();
+}
+
+void LLFloaterCreateLandmark::onCancelClicked()
+{
+	closeFloater();
+}
+
+
+void LLFloaterCreateLandmark::setItem(const uuid_set_t& items)
+{
+	for (uuid_set_t::const_iterator item_iter = items.begin();
+		item_iter != items.end();
+		++item_iter)
+	{
+		const LLUUID& item_id = (*item_iter);
+		if(!highlight_offered_object(item_id))
+		{
+			continue;
+		}
+
+		LLInventoryItem* item = gInventory.getItem(item_id);
+
+		llassert(item);
+		if (item && (LLAssetType::AT_LANDMARK == item->getType()) )
+		{
+			if(!getItem())
+			{
+				removeObserver();
+				mItem = item;
+				break;
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h
new file mode 100644
index 0000000000..d62ee01790
--- /dev/null
+++ b/indra/newview/llfloatercreatelandmark.h
@@ -0,0 +1,75 @@
+/** 
+ * @file llfloatercreatelandmark.h
+ * @brief LLFloaterCreateLandmark class definition
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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_LLFLOATERCREATELANDMARK_H
+#define LL_LLFLOATERCREATELANDMARK_H
+
+#include "llfloater.h"
+
+class LLComboBox;
+class LLInventoryItem;
+class LLLineEditor;
+class LLTextEditor;
+class LLLandmarksInventoryObserver;
+
+class LLFloaterCreateLandmark:
+	public LLFloater
+{
+	friend class LLFloaterReg;
+
+public:
+
+	LLFloaterCreateLandmark(const LLSD& key);
+	~LLFloaterCreateLandmark();
+
+	BOOL postBuild();
+	void onOpen(const LLSD& key);
+
+	void setItem(const uuid_set_t& items);
+
+	LLInventoryItem* getItem() { return mItem; }
+
+private:
+	void setLandmarkInfo(const LLUUID &folder_id);
+	void removeObserver();
+	void populateFoldersList(const LLUUID &folder_id = LLUUID::null);
+	void onCreateFolderClicked();
+	void onSaveClicked();
+	void onCancelClicked();
+
+	void folderCreatedCallback(LLUUID folder_id);
+
+	LLComboBox*		mFolderCombo;
+	LLLineEditor*	mLandmarkTitleEditor;
+	LLTextEditor*	mNotesEditor;
+	LLUUID			mLandmarksID;
+	LLUUID			mItemID;
+
+	LLLandmarksInventoryObserver*	mInventoryObserver;
+	LLPointer<LLInventoryItem>		mItem;
+};
+
+#endif
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 83195e9e3f..d6f3068610 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -44,6 +44,7 @@
 
 // newview includes
 #include "llagent.h"
+#include "llfloaterreg.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llinventoryobserver.h"
 #include "lllandmarkactions.h"
@@ -653,7 +654,7 @@ void LLLocationInputCtrl::onAddLandmarkButtonClicked()
 	}
 	else
 	{
-		LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
+		LLFloaterReg::showInstance("add_landmark");
 	}
 }
 
@@ -1126,7 +1127,7 @@ void LLLocationInputCtrl::onLocationContextMenuItemClicked(const LLSD& userdata)
 		
 		if(!landmark)
 		{
-			LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
+			LLFloaterReg::showInstance("add_landmark");
 		}
 		else
 		{
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index 069fb32a56..880323ce16 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -52,7 +52,6 @@
 typedef std::pair<LLUUID, std::string> folder_pair_t;
 
 static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
-static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
 
 static LLPanelInjector<LLPanelLandmarkInfo> t_landmark_info("panel_landmark_info");
 
@@ -516,7 +515,7 @@ static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
 	return left.second < right.second;
 }
 
-static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
+void LLPanelLandmarkInfo::collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
 {
 	LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
 
@@ -529,16 +528,20 @@ static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
 		items,
 		LLInventoryModel::EXCLUDE_TRASH,
 		is_category);
+}
 
-	// Add the "My Favorites" category.
-	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-	LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id);
-	if (!favorites_cat)
-	{
-		LL_WARNS() << "Cannot find the favorites folder" << LL_ENDL;
-	}
-	else
-	{
-		cats.push_back(favorites_cat);
-	}
+/* virtual */ void LLUpdateLandmarkParent::fire(const LLUUID& inv_item_id)
+{
+	LLInventoryModel::update_list_t update;
+	LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1);
+	update.push_back(old_folder);
+	LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1);
+	update.push_back(new_folder);
+	gInventory.accountForUpdate(update);
+
+	mItem->setParent(mNewParentId);
+	mItem->updateParentOnServer(FALSE);
+
+	gInventory.updateItem(mItem);
+	gInventory.notifyObservers();
 }
diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h
index 9a2e0c8f59..f727f286b5 100644
--- a/indra/newview/llpanellandmarkinfo.h
+++ b/indra/newview/llpanellandmarkinfo.h
@@ -28,6 +28,7 @@
 #define LL_LLPANELLANDMARKINFO_H
 
 #include "llpanelplaceinfo.h"
+#include "llinventorymodel.h"
 
 class LLComboBox;
 class LLLineEditor;
@@ -63,7 +64,9 @@ public:
 	// Select current landmark folder in combobox.
 	BOOL setLandmarkFolder(const LLUUID& id);
 
+	typedef std::vector<LLPointer<LLViewerInventoryCategory> > cat_array_t;
 	static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
+	static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
 
 private:
     // Create a landmark for the current location
@@ -85,4 +88,17 @@ private:
 	LLComboBox*			mFolderCombo;
 };
 
+class LLUpdateLandmarkParent : public LLInventoryCallback
+{
+public:
+	LLUpdateLandmarkParent(LLPointer<LLViewerInventoryItem> item, LLUUID new_parent) :
+		mItem(item),
+		mNewParentId(new_parent)
+	{};
+	/* virtual */ void fire(const LLUUID& inv_item_id);
+
+private:
+	LLPointer<LLViewerInventoryItem> mItem;
+	LLUUID mNewParentId;
+};
 #endif // LL_LLPANELLANDMARKINFO_H
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 1a10654a71..b5de28e469 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -500,7 +500,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
             {
                 args["dest_folder"] = view_model->getUUID();
             }
-			LLFloaterSidePanelContainer::showPanel("places", args);
+			LLFloaterReg::showInstance("add_landmark", args);
 		}
 	} 
 	else if ("category" == command_name)
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 7928896d96..90a70adea7 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -773,34 +773,6 @@ void LLPanelPlaces::onEditButtonClicked()
 	updateVerbs();
 }
 
-class LLUpdateLandmarkParent : public LLInventoryCallback
-{
-public:
-    LLUpdateLandmarkParent(LLPointer<LLViewerInventoryItem> item, LLUUID new_parent) :
-        mItem(item),
-        mNewParentId(new_parent)
-    {};
-    /* virtual */ void fire(const LLUUID& inv_item_id)
-    {
-        LLInventoryModel::update_list_t update;
-        LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1);
-        update.push_back(old_folder);
-        LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1);
-        update.push_back(new_folder);
-        gInventory.accountForUpdate(update);
-
-        mItem->setParent(mNewParentId);
-        mItem->updateParentOnServer(FALSE);
-
-        gInventory.updateItem(mItem);
-        gInventory.notifyObservers();
-    }
-
-private:
-    LLPointer<LLViewerInventoryItem> mItem;
-    LLUUID mNewParentId;
-};
-
 void LLPanelPlaces::onSaveButtonClicked()
 {
 	if (!mLandmarkInfo || mItem.isNull())
diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp
index 109013498e..0723a78704 100644
--- a/indra/newview/llpaneltopinfobar.cpp
+++ b/indra/newview/llpaneltopinfobar.cpp
@@ -31,6 +31,7 @@
 #include "llagent.h"
 #include "llagentui.h"
 #include "llclipboard.h"
+#include "llfloaterreg.h"
 #include "llfloatersidepanelcontainer.h"
 #include "lllandmarkactions.h"
 #include "lllocationinputctrl.h"
@@ -456,7 +457,7 @@ void LLPanelTopInfoBar::onContextMenuItemClicked(const LLSD::String& item)
 
 		if(landmark == NULL)
 		{
-			LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
+			LLFloaterReg::showInstance("add_landmark");
 		}
 		else
 		{
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 4f46d1c0a2..8baad30e8f 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -291,7 +291,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 			mLineEditor->setText(edit_text_contents);
 
 			std::string notif_name = mNotification->getName();
-			if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name))
+			if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name))
 			{
 				mLineEditor->setPrevalidate(&LLTextValidate::validateASCII);
 			}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 06587d6025..46ff441719 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -58,6 +58,7 @@
 #include "llfloaterchatvoicevolume.h"
 #include "llfloaterconversationlog.h"
 #include "llfloaterconversationpreview.h"
+#include "llfloatercreatelandmark.h"
 #include "llfloaterdeleteprefpreset.h"
 #include "llfloaterdestinations.h"
 #include "llfloatereditextdaycycle.h"
@@ -222,6 +223,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater);
 	LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
 	LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);
+	LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>);
 
 	LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeletePrefPreset>);
 	LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index c09654236c..41122a51b1 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6042,7 +6042,7 @@ class LLWorldCreateLandmark : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
+		LLFloaterReg::showInstance("add_landmark");
 
 		return true;
 	}
diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
new file mode 100644
index 0000000000..69b019c3a1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="false"
+ show_title="false"
+ can_minimize="false"
+ can_close="false"
+ height="305"
+ layout="topleft"
+ name="create_landmark"
+ width="330">
+  <string name="favorites_bar">
+    Favorites bar
+  </string>
+    <text
+     follows="left|top"
+     height="15"
+     layout="topleft"
+     left="20"
+     name="title_label"
+     top="5"
+     font="SansSerifLargeBold"
+     value="Landmark added"
+     width="290" />
+    <text
+     follows="left|top"
+     height="15"
+     layout="topleft"
+     left="20"
+     name="name_label"
+     top_pad="10"
+     value="Name"
+     width="290" />
+    <line_editor
+     follows="left|top"
+     height="22"
+     layout="topleft"
+     max_length_bytes="63"
+     name="title_editor"
+     prevalidate_callback="ascii"
+     text_readonly_color="white"
+     top_pad="5"
+     width="290" />
+    <text
+     follows="left|top"
+     height="15"
+     layout="topleft"
+     name="folder_label"
+     top_pad="10"
+     value="Landmark location:"
+     width="290" />
+    <combo_box
+     follows="bottom|left"
+     height="23"
+     layout="topleft"
+     name="folder_combo"
+     top_pad="2"
+     width="290" />
+    <text
+     follows="left|top"
+     layout="topleft"
+     top_pad="6"
+     left="20"
+     name="new_folder_textbox"
+     height="20"
+     parse_urls="true"
+     skip_link_underline="true"
+     wrap="true">
+        [secondlife:/// Create new folder]
+    </text>
+    <text
+     follows="left|top"
+     height="15"
+     layout="topleft"
+     name="notes_label"
+     top_pad="10"
+     value="My notes"
+     width="290" />
+    <text_editor
+     bg_readonly_color="DkGray0"
+     follows="all"
+     height="75"
+     layout="topleft"
+     max_length="127"
+     name="notes_editor"
+     spellcheck="true"
+     text_readonly_color="white"
+     text_type="ascii_with_newline"
+     top_pad="5"
+     width="290"
+     wrap="true" />
+    <button
+     follows="bottom|left|right"
+     height="23"
+     label="OK"
+     layout="topleft"
+     mouse_opaque="false"
+     name="ok_btn"
+     top_pad="10"
+     left="19"
+     width="140" />
+    <button
+     follows="bottom|left|right"
+     height="23"
+     label="Cancel"
+     layout="topleft"
+     left_pad="12"
+     mouse_opaque="false"
+     name="cancel_btn"
+     width="140" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index cdde9d2107..f1c8459b25 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2319,6 +2319,29 @@ You cannot create a landmark here because the owner of the land doesn&apos;t all
   <tag>fail</tag>
   </notification>
 
+  <notification
+ icon="alertmodal.tga"
+ label="Create folder"
+ name="CreateLandmarkFolder"
+ type="alertmodal">
+    <unique/>
+    Choose a name for the folder:
+    <tag>confirm</tag>
+    <form name="form">
+      <input name="message" type="text">
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="OK"
+       text="OK"/>
+      <button
+       index="1"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="CannotRecompileSelectObjectsNoScripts"
-- 
cgit v1.2.3


From fee2c14873dd47aaf805baa2e6e0c5b0de5870ca Mon Sep 17 00:00:00 2001
From: Mnikolenko ProductEngine <mnikolenko@productengine.com>
Date: Wed, 24 Mar 2021 13:09:29 +0200
Subject: mac build fix

---
 indra/newview/llpanellandmarks.cpp | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index b5de28e469..8bc4bca675 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -61,7 +61,6 @@
 
 // helper functions
 static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
-static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
 static void collapse_all_folders(LLFolderView* root_folder);
 static void expand_all_folders(LLFolderView* root_folder);
 static bool has_expanded_folders(LLFolderView* root_folder);
@@ -1102,17 +1101,6 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin
 	inventory_list->setFilterSubString(string);
 }
 
-static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
-{
-	LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getRootFolderID());
-	if (category)
-	{
-		return category->getDescendentCount() > 0;
-	}
-
-	return false;
-}
-
 static void collapse_all_folders(LLFolderView* root_folder)
 {
 	if (!root_folder)
-- 
cgit v1.2.3


From 33eadba6ef703c1fb0a8f4bffe49ccea224fb77f Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 25 Mar 2021 18:57:30 +0200
Subject: SL-15028 Guidebook floater

---
 indra/newview/app_settings/settings.xml               | 11 +++++++++++
 indra/newview/llviewermenu.cpp                        |  5 ++---
 indra/newview/skins/default/xui/en/floater_how_to.xml | 12 +++++-------
 indra/newview/skins/default/xui/en/menu_viewer.xml    |  9 +--------
 4 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c0166f158e..4610cd58af 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4725,6 +4725,17 @@
       <key>Value</key>
       <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
     </map>
+    <key>GuidebookURL</key>
+    <map>
+      <key>Comment</key>
+      <string>URL for Guidebook content</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>https://guidebooks.secondlife.io/welcome</string>
+    </map>
     <key>HighResSnapshot</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 41122a51b1..1aa67a30cd 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7730,12 +7730,11 @@ class LLToggleHowTo : public view_listener_t
 	bool handleEvent(const LLSD& userdata)
 	{
 		LLFloaterWebContent::Params p;
-		std::string url = gSavedSettings.getString("HowToHelpURL");
+		std::string url = gSavedSettings.getString("GuidebookURL");
 		p.url = LLWeb::expandURLSubstitutions(url, LLSD());
 		p.show_chrome = false;
-		p.target = "__help_how_to";
 		p.show_page_title = false;
-		p.preferred_media_size = LLRect(0, 460, 335, 0);
+		p.preferred_media_size = LLRect(0, 500, 300, 0);
 
 		LLFloaterReg::toggleInstanceOrBringToFront("how_to", p);
 		return true;
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index 8c0077a8cc..b79584c7b7 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -1,18 +1,16 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
   legacy_header_height="18"
-  can_resize="true"
-  can_minimize="true" 
+  can_resize="false"
+  can_minimize="false"
+  can_close="false" 
   height="775"
   layout="topleft"
-  min_height="360"
-  left="10000"
-  top="10" 
+  top="0" 
   min_width="335"
   name="floater_how_to"
-  help_topic="how_to"
   single_instance="true"
   save_rect="true"
-  title="HOW TO"
+  title="WELCOME ISLAND GUIDEBOOK"
   width="780"
   filename="floater_web_content.xml"/>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 0d456ffe5d..456d131d9c 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1596,20 +1596,13 @@ function="World.EnvPreset"
      name="Help"
      tear_off="true">
         <menu_item_call
-         label="How to..."
+         label="Guidebook"
          name="How To"
          shortcut="F1">
             <menu_item_call.on_click
              function="Help.ToggleHowTo"
              parameter="" />
         </menu_item_call>
-        <menu_item_call
-           label="Quickstart"
-           name="Quickstart">
-            <menu_item_call.on_click
-            function="Advanced.ShowURL"
-            parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Quickstart/ta-p/1087919"/>
-        </menu_item_call>
 <!--        <menu_item_call
          label="Tutorial"
          name="Tutorial">
-- 
cgit v1.2.3


From 100fa900c09110f215ab241cd2fd3d237dfb96fd Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 29 Mar 2021 18:32:02 +0300
Subject: SL-14900 remove created landmark when clicking Cancel button

---
 indra/newview/llfloatercreatelandmark.cpp                      | 4 +++-
 indra/newview/llfloatercreatelandmark.h                        | 1 -
 indra/newview/skins/default/xui/en/floater_create_landmark.xml | 3 +++
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index 95ddacbb6c..db84a2ac76 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -216,7 +216,7 @@ void LLFloaterCreateLandmark::onCreateFolderClicked()
 			if (!folder_name.empty())
 			{
 				inventory_func_type func = boost::bind(&LLFloaterCreateLandmark::folderCreatedCallback, this, _1);
-				LLUUID test = gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, func);
+				gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, func);
 				gInventory.notifyObservers();
 			}
 		}
@@ -282,6 +282,8 @@ void LLFloaterCreateLandmark::onSaveClicked()
 
 void LLFloaterCreateLandmark::onCancelClicked()
 {
+	LLUUID item_id = mItem->getUUID();
+	remove_inventory_item(item_id, NULL);
 	closeFloater();
 }
 
diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h
index d62ee01790..74ac5e651c 100644
--- a/indra/newview/llfloatercreatelandmark.h
+++ b/indra/newview/llfloatercreatelandmark.h
@@ -66,7 +66,6 @@ private:
 	LLLineEditor*	mLandmarkTitleEditor;
 	LLTextEditor*	mNotesEditor;
 	LLUUID			mLandmarksID;
-	LLUUID			mItemID;
 
 	LLLandmarksInventoryObserver*	mInventoryObserver;
 	LLPointer<LLInventoryItem>		mItem;
diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
index 69b019c3a1..dcedaceaeb 100644
--- a/indra/newview/skins/default/xui/en/floater_create_landmark.xml
+++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
@@ -4,6 +4,9 @@
  show_title="false"
  can_minimize="false"
  can_close="false"
+ header_height="10"
+ bg_opaque_image="Window_NoTitle_Foreground"
+ bg_alpha_image="Window_NoTitle_Background"
  height="305"
  layout="topleft"
  name="create_landmark"
-- 
cgit v1.2.3


From 569ad2d248cd1297b937e2c003399937114d06b9 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 29 Mar 2021 19:54:24 +0300
Subject: Separate "Save changes" and "Save as..." in Outfits floater

---
 indra/newview/llpaneloutfitedit.cpp                | 19 ++++++++---
 indra/newview/llpaneloutfitedit.h                  |  3 +-
 indra/newview/llpaneloutfitsinventory.cpp          | 23 ++++++++++---
 indra/newview/llpaneloutfitsinventory.h            |  3 +-
 .../skins/default/xui/en/panel_outfit_edit.xml     | 36 +++++++++++---------
 .../default/xui/en/panel_outfits_inventory.xml     | 39 ++++++++++++----------
 6 files changed, 77 insertions(+), 46 deletions(-)

diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 28a020870f..5be9ab6095 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -58,7 +58,6 @@
 #include "llmenubutton.h"
 #include "llpaneloutfitsinventory.h"
 #include "lluiconstants.h"
-#include "llsaveoutfitcombobtn.h"
 #include "llscrolllistctrl.h"
 #include "lltextbox.h"
 #include "lltoggleablemenu.h"
@@ -80,6 +79,8 @@ const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LL
 const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
 
 static const std::string REVERT_BTN("revert_btn");
+static const std::string SAVE_AS_BTN("save_as_btn");
+static const std::string SAVE_BTN("save_btn");
 
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -562,7 +563,8 @@ BOOL LLPanelOutfitEdit::postBuild()
 	mGearMenu = LLPanelOutfitEditGearMenu::create();
 	mGearMenuBtn->setMenu(mGearMenu);
 
-	mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));
+	getChild<LLButton>(SAVE_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));
+	getChild<LLButton>(SAVE_AS_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true));
 
 	onOutfitChanging(gAgentWearables.isCOFChangeInProgress());
 	return TRUE;
@@ -1239,11 +1241,9 @@ void LLPanelOutfitEdit::updateVerbs()
 	bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked();
 	bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull();
 
-	mSaveComboBtn->setSaveBtnEnabled(!outfit_locked && outfit_is_dirty);
+	getChildView(SAVE_BTN)->setEnabled(!outfit_locked && outfit_is_dirty);
 	getChildView(REVERT_BTN)->setEnabled(outfit_is_dirty && has_baseoutfit);
 
-	mSaveComboBtn->setMenuItemEnabled("save_outfit", !outfit_locked && outfit_is_dirty);
-
 	mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing"));
 
 	updateCurrentOutfitName();
@@ -1429,4 +1429,13 @@ void LLPanelOutfitEdit::saveListSelection()
 	}
 }
 
+void LLPanelOutfitEdit::saveOutfit(bool as_new)
+{
+	LLPanelOutfitsInventory* panel_outfits_inventory = LLPanelOutfitsInventory::findInstance();
+	if (panel_outfits_inventory)
+	{
+		panel_outfits_inventory->saveOutfit(as_new);
+	} 	
+}
+
 // EOF
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 3c6efac0e7..d0597fb72b 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -58,7 +58,6 @@ class LLMenuButton;
 class LLMenuGL;
 class LLFindNonLinksByMask;
 class LLFindWearablesOfType;
-class LLSaveOutfitComboBtn;
 class LLWearableItemTypeNameComparator;
 
 class LLPanelOutfitEdit : public LLPanel
@@ -195,6 +194,7 @@ private:
 	void getSelectedItemsUUID(uuid_vec_t& uuid_list);
 	void getCurrentItemUUID(LLUUID& selected_id);
 	void onCOFChanged();
+	void saveOutfit(bool as_new = false);
 
 	/**
 	 * Method preserves selection while switching between folder/list view modes
@@ -237,7 +237,6 @@ private:
 	LLToggleableMenu*	mGearMenu;
 	LLToggleableMenu*	mAddWearablesGearMenu;
 	bool				mInitialized;
-	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
 	LLMenuButton*		mWearablesGearMenuBtn;
 	LLMenuButton*		mGearMenuBtn;
 
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 8fff52ca4e..baacdd65b5 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -40,7 +40,6 @@
 #include "lloutfitgallery.h"
 #include "lloutfitslist.h"
 #include "llpanelwearing.h"
-#include "llsaveoutfitcombobtn.h"
 #include "llsidepanelappearance.h"
 #include "llviewercontrol.h"
 #include "llviewerfoldertype.h"
@@ -49,6 +48,9 @@ static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
 static const std::string OUTFIT_GALLERY_TAB_NAME = "outfit_gallery_tab";
 static const std::string COF_TAB_NAME = "cof_tab";
 
+static const std::string SAVE_AS_BTN("save_as_btn");
+static const std::string SAVE_BTN("save_btn");
+
 static LLPanelInjector<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
 
 LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
@@ -90,8 +92,9 @@ BOOL LLPanelOutfitsInventory::postBuild()
 	{
 		LLInventoryModelBackgroundFetch::instance().start(outfits_cat);
 	}
-	
-	mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this, true));
+
+	getChild<LLButton>(SAVE_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::saveOutfit, this, false));
+	getChild<LLButton>(SAVE_AS_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::saveOutfit, this, true));
 
 	return TRUE;
 }
@@ -269,7 +272,7 @@ void LLPanelOutfitsInventory::updateListCommands()
 	mOutfitGalleryPanel->childSetEnabled("trash_btn", trash_enabled);
 	wear_btn->setEnabled(wear_enabled);
 	wear_btn->setVisible(wear_visible);
-	mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled);
+	getChild<LLButton>(SAVE_BTN)->setEnabled(make_outfit_enabled);
 	wear_btn->setToolTip(getString((!isOutfitsGalleryPanelActive() && mMyOutfitsPanel->hasItemSelected()) ? "wear_items_tooltip" : "wear_outfit_tooltip"));
 }
 
@@ -368,3 +371,15 @@ LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP()
 		dynamic_cast<LLSidepanelAppearance*>(LLFloaterSidePanelContainer::getPanel("appearance"));
 	return panel_appearance;
 }
+
+void LLPanelOutfitsInventory::saveOutfit(bool as_new)
+{
+	if (!as_new && LLAppearanceMgr::getInstance()->updateBaseOutfit())
+	{
+		// we don't need to ask for an outfit name, and updateBaseOutfit() successfully saved.
+		// If updateBaseOutfit fails, ask for an outfit name anyways
+		return;
+	}
+
+	onSave();
+}
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index 6a0ea04fa6..e68f04e28d 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -38,7 +38,6 @@ class LLPanelWearing;
 class LLMenuGL;
 class LLSidepanelAppearance;
 class LLTabContainer;
-class LLSaveOutfitComboBtn;
 
 class LLPanelOutfitsInventory : public LLPanel
 {
@@ -52,6 +51,7 @@ public:
 	
 	void onSearchEdit(const std::string& string);
 	void onSave();
+	void saveOutfit(bool as_new = false);
 	
 	bool onSaveCommit(const LLSD& notification, const LLSD& response);
 
@@ -65,7 +65,6 @@ protected:
 private:
 	LLTabContainer*			mAppearanceTabs;
 	std::string 			mFilterSubString;
-	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
 
 	//////////////////////////////////////////////////////////////////////////////////
 	// tab panels                                                                   //
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index 6fd54d7c6a..c4c51afa82 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -510,27 +510,31 @@ It is calculated as border_size + 2*UIResizeBarOverlap
                 <button
                         follows="bottom|left|right"
                         height="23"
-                        label="Save"
+                        label="Save changes"
                         left="1"
                         layout="topleft"
                         name="save_btn"
                         top="0"
                         width="155" />
-                <button
-                        follows="bottom|right"
-                        height="23"
-                        name="save_flyout_btn"
-                        label=""
-                        layout="topleft"
-                        left_pad="-20"
-                        tab_stop="false"
-                        top="0"
-                        image_selected="SegmentedBtn_Right_Selected_Press"
-                        image_unselected="SegmentedBtn_Right_Off"
-                        image_pressed="SegmentedBtn_Right_Press"
-                        image_pressed_selected="SegmentedBtn_Right_Selected_Press"
-                        image_overlay="Arrow_Small_Up"
-                        width="20"/>
+            </layout_panel>
+            <layout_panel
+               follows="bottom|left|right"
+               height="23"
+               layout="bottomleft"
+               left_pad="3"
+               mouse_opaque="false"
+               name="save_as_btn_lp"
+               auto_resize="true"
+               width="156">
+              <button
+                   follows="bottom|left|right"
+                   height="23"
+                   label="Save as..."
+                   layout="topleft"
+                   name="save_as_btn"
+                   top="0"
+                   left="1"
+                   width="155" />
             </layout_panel>
             <layout_panel
                     follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index 6c8cc9d39a..7b898dbd7f 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -100,28 +100,33 @@
                     <button
                          follows="bottom|left|right"
                          height="23"
-                         label="Save As"
+                         label="Save changes"
                          left="1"
                          layout="topleft"
                          name="save_btn"
                          top="0"
                          width="155" />
-                    <button
-                         follows="bottom|right"
-                         height="23"
-                         name="save_flyout_btn"
-                         label=""
-                         layout="topleft"
-                         left_pad="-20"
-                         tab_stop="false"
-                         image_selected="SegmentedBtn_Right_Selected_Press"
-                         image_unselected="SegmentedBtn_Right_Off"
-                         image_pressed="SegmentedBtn_Right_Press"
-                         image_pressed_selected="SegmentedBtn_Right_Selected_Press"
-                         image_overlay="Arrow_Small_Up"
-                         width="20"/>
-			    </layout_panel>
-			    <layout_panel
+          </layout_panel>
+          <layout_panel
+               follows="bottom|left|right"
+               height="23"
+               layout="bottomleft"
+               left_pad="3"
+               mouse_opaque="false"
+               name="save_as_btn_lp"
+               auto_resize="true"
+               width="156">
+              <button
+                   follows="bottom|left|right"
+                   height="23"
+                   label="Save as..."
+                   layout="topleft"
+                   name="save_as_btn"
+                   top="0"
+                   left="1"
+                   width="155" />
+          </layout_panel>
+          <layout_panel
                      follows="bottom|left|right"
                      height="23"
                      layout="bottomleft"
-- 
cgit v1.2.3


From 309fb9e892beb724a442c85bcfd07d6f3f7c9c07 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 29 Mar 2021 23:36:55 +0300
Subject: SL-15034 Revisions to dedicated Avatar menus

---
 indra/newview/llpaneloutfitsinventory.cpp          |  6 +++
 indra/newview/llpaneloutfitsinventory.h            |  2 +
 indra/newview/llsidepanelappearance.cpp            | 60 ++++++++++++++--------
 indra/newview/llsidepanelappearance.h              |  5 +-
 indra/newview/llviewermenu.cpp                     |  6 +++
 .../skins/default/xui/en/menu_attachment_self.xml  | 38 ++++++++------
 .../skins/default/xui/en/menu_avatar_self.xml      | 46 ++++++++++-------
 indra/newview/skins/default/xui/en/menu_viewer.xml | 60 ++++++++++++----------
 .../skins/default/xui/en/panel_outfit_edit.xml     |  2 +-
 9 files changed, 141 insertions(+), 84 deletions(-)

diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index baacdd65b5..531073526b 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -249,6 +249,12 @@ LLPanelOutfitsInventory* LLPanelOutfitsInventory::findInstance()
 	return dynamic_cast<LLPanelOutfitsInventory*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfits_inventory"));
 }
 
+void LLPanelOutfitsInventory::openApearanceTab(const std::string& tab_name)
+{
+    if (!mAppearanceTabs) return;
+    mAppearanceTabs->selectTabByName(tab_name);
+}
+
 //////////////////////////////////////////////////////////////////////////////////
 // List Commands                                                                //
 
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index e68f04e28d..50d7074d4b 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -59,6 +59,8 @@ public:
 
 	static LLPanelOutfitsInventory* findInstance();
 
+	void openApearanceTab(const std::string& tab_name);
+
 protected:
 	void updateVerbs();
 
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 48151c17ea..6dfe40c29a 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -164,8 +164,12 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 		std::string type = key["type"].asString();
 		if (type == "my_outfits")
 		{
-			showOutfitsInventoryPanel();
+			showOutfitsInventoryPanel("outfitslist_tab");
 		}
+        else if (type == "now_wearing")
+        {
+            showOutfitsInventoryPanel("cof_tab");
+        }
 		else if (type == "edit_outfit")
 		{
 			showOutfitEditPanel();
@@ -287,7 +291,14 @@ void LLSidepanelAppearance::showOutfitsInventoryPanel()
 {
 	toggleWearableEditPanel(FALSE);
 	toggleOutfitEditPanel(FALSE);
-	toggleMyOutfitsPanel(TRUE);
+	toggleMyOutfitsPanel(TRUE, "");
+}
+
+void LLSidepanelAppearance::showOutfitsInventoryPanel(const std::string &tab_name)
+{
+    toggleWearableEditPanel(FALSE);
+    toggleOutfitEditPanel(FALSE);
+    toggleMyOutfitsPanel(TRUE, tab_name);
 }
 
 void LLSidepanelAppearance::showOutfitEditPanel()
@@ -312,37 +323,42 @@ void LLSidepanelAppearance::showOutfitEditPanel()
 		return;
 	}
 
-	toggleMyOutfitsPanel(FALSE);
+	toggleMyOutfitsPanel(FALSE, "");
 	toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode
 	toggleOutfitEditPanel(TRUE);
 }
 
 void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch)
 {
-	toggleMyOutfitsPanel(FALSE);
+	toggleMyOutfitsPanel(FALSE, "");
 	toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode
 	toggleWearableEditPanel(TRUE, wearable, disable_camera_switch);
 }
 
-void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible)
+void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible, const std::string& tab_name)
 {
-	if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible)
-	{
-		// visibility isn't changing, hence nothing to do
-		return;
-	}
-
-	mPanelOutfitsInventory->setVisible(visible);
-
-	// *TODO: Move these controls to panel_outfits_inventory.xml
-	// so that we don't need to toggle them explicitly.
-	mFilterEditor->setVisible(visible);
-	mCurrOutfitPanel->setVisible(visible);
-
-	if (visible)
-	{
-		mPanelOutfitsInventory->onOpen(LLSD());
-	}
+    if (!mPanelOutfitsInventory
+        || (mPanelOutfitsInventory->getVisible() == visible && tab_name.empty()))
+    {
+        // visibility isn't changing, hence nothing to do
+        return;
+    }
+
+    mPanelOutfitsInventory->setVisible(visible);
+
+    // *TODO: Move these controls to panel_outfits_inventory.xml
+    // so that we don't need to toggle them explicitly.
+    mFilterEditor->setVisible(visible);
+    mCurrOutfitPanel->setVisible(visible);
+
+    if (visible)
+    {
+        mPanelOutfitsInventory->onOpen(LLSD());
+        if (!tab_name.empty())
+        {
+            mPanelOutfitsInventory->openApearanceTab(tab_name);
+        }
+    }
 }
 
 void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch)
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 7817fd317c..bb9709a2b8 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -56,7 +56,8 @@ public:
 	void fetchInventory();
 	void inventoryFetched();
 
-	void showOutfitsInventoryPanel();
+    void showOutfitsInventoryPanel(); // last selected
+	void showOutfitsInventoryPanel(const std::string& tab_name);
 	void showOutfitEditPanel();
 	void showWearableEditPanel(LLViewerWearable *wearable = NULL, BOOL disable_camera_switch = FALSE);
 	void setWearablesLoading(bool val);
@@ -72,7 +73,7 @@ private:
 	void onOpenOutfitButtonClicked();
 	void onEditAppearanceButtonClicked();
 
-	void toggleMyOutfitsPanel(BOOL visible);
+	void toggleMyOutfitsPanel(BOOL visible, const std::string& tab_name);
 	void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE);
 	void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE);
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 1aa67a30cd..6104f72fc8 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6373,6 +6373,11 @@ void handle_edit_outfit()
 	LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
 }
 
+void handle_now_wearing()
+{
+    LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "now_wearing"));
+}
+
 void handle_edit_shape()
 {
 	LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape"));
@@ -8985,6 +8990,7 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight");
 	view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
 	commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
+    commit.add("NowWearing", boost::bind(&handle_now_wearing));
 	commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
 	commit.add("EditShape", boost::bind(&handle_edit_shape));
 	commit.add("HoverHeight", boost::bind(&handle_hover_height));
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 856bf4ce73..13e4b9ba7b 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -37,39 +37,47 @@
      layout="topleft" />
 
   <menu_item_call
-  label="Outfits..."
+  label="Now wearing..."
+  name="NowWearing">
+    <menu_item_call.on_click
+     function="NowWearing" />
+    <menu_item_call.on_enable
+     function="Edit.EnableCustomizeAvatar" />
+  </menu_item_call>
+  <menu_item_call
+  label="My Outfits..."
   name="Change Outfit">
     <menu_item_call.on_click
      function="CustomizeAvatar" />
     <menu_item_call.on_enable
      function="Edit.EnableCustomizeAvatar" />
   </menu_item_call>
-  <menu_item_call label="Current outfit..."
-layout="topleft"
-name="Edit Outfit">
+  <menu_item_call label="Hover height..."
+     layout="topleft"
+     name="Hover Height">
     <menu_item_call.on_click
-     function="EditOutfit" />
+     function="HoverHeight" />
     <menu_item_call.on_enable
-     function="Edit.EnableCustomizeAvatar" />
+     function="Edit.EnableHoverHeight" />
   </menu_item_call>
   <menu_item_call label="Shape..."
     layout="topleft"
-    name="Edit My Shape">
+    name="Edit Shape">
     <menu_item_call.on_click
      function="EditShape" />
     <menu_item_call.on_enable
      function="Edit.EnableEditShape" />
   </menu_item_call>
-  <menu_item_call label="Hover height..."
-     layout="topleft"
-     name="Hover Height">
-     <menu_item_call.on_click
-      function="HoverHeight" />
-     <menu_item_call.on_enable
-      function="Edit.EnableHoverHeight" />
+  <menu_item_call label="Edit outfit parts..."
+    layout="topleft"
+    name="Edit Outfit">
+    <menu_item_call.on_click
+     function="EditOutfit" />
+    <menu_item_call.on_enable
+     function="Edit.EnableCustomizeAvatar" />
   </menu_item_call>
   <context_menu
-  label="Take Off"
+  label="Take off"
   layout="topleft"
   name="Take Off &gt;">
     <context_menu
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index a46d9aed55..500b6fffc2 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -3,7 +3,16 @@
  layout="topleft"
  name="Self Pie">
     <menu_item_call
-     label="Outfits..."
+     label="Now wearing..."
+     layout="topleft"
+     name="NowWearing">
+        <menu_item_call.on_click
+         function="NowWearing" />
+        <menu_item_call.on_enable
+         function="Edit.EnableCustomizeAvatar" />
+    </menu_item_call>
+    <menu_item_call
+     label="My Outfits..."
      layout="topleft"
      name="Chenge Outfit">
         <menu_item_call.on_click
@@ -11,22 +20,6 @@
         <menu_item_call.on_enable
          function="Edit.EnableCustomizeAvatar" />
     </menu_item_call>
-    <menu_item_call label="Current outfit..." 
-    layout="topleft"
-    name="Edit Outfit">
-       <menu_item_call.on_click
-        function="EditOutfit" />
-       <menu_item_call.on_enable
-        function="Edit.EnableCustomizeAvatar" />
-   </menu_item_call>
-    <menu_item_call label="Shape..." 
-    layout="topleft"
-    name="Edit My Shape">
-       <menu_item_call.on_click
-        function="EditShape" />
-       <menu_item_call.on_enable
-        function="Edit.EnableEditShape" />
-   </menu_item_call>
    <menu_item_call label="Hover height..."
      layout="topleft"
      name="Hover Height">
@@ -35,8 +28,25 @@
      <menu_item_call.on_enable
       function="Edit.EnableHoverHeight" />
    </menu_item_call>
+   <menu_item_call label="Shape..." 
+    layout="topleft"
+    name="Edit Shape">
+       <menu_item_call.on_click
+        function="EditShape" />
+       <menu_item_call.on_enable
+        function="Edit.EnableEditShape" />
+   </menu_item_call>
+   <menu_item_call
+      label="Edit outfit parts..." 
+      layout="topleft"
+      name="Edit Outfit">
+       <menu_item_call.on_click
+        function="EditOutfit" />
+       <menu_item_call.on_enable
+        function="Edit.EnableCustomizeAvatar" />
+   </menu_item_call>
   <context_menu
-    label="Take Off"
+    label="Take off"
     layout="topleft"
     name="Take Off &gt;">
     <context_menu
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 456d131d9c..69d17e6547 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -165,50 +165,50 @@
      name="Avatar"
      tear_off="true">
        <menu_item_call
-         label="Complete avatars..."
-         name="Avatar Picker">
-            <menu_item_call.on_click
-             function="Floater.ToggleOrBringToFront"
-             parameter="avatar" />
-       </menu_item_call>
-       <menu_item_call
-         label="Outfits..."
-         name="ChangeOutfit"
+         label="Now wearing..."
+         name="NowWearing"
          shortcut="control|O">
             <menu_item_call.on_click
-             function="Floater.ToggleOrBringToFront"
-             parameter="appearance" />
+             function="NowWearing" />
             <menu_item_call.on_enable
              function="Edit.EnableCustomizeAvatar" />
        </menu_item_call>
-       <menu_item_call 
-         label="Current outfit..."
-         layout="topleft"
-         name="Edit Outfit">
+       <menu_item_call
+         label="My outfits..."
+         name="ChangeOutfit">
             <menu_item_call.on_click
-             function="EditOutfit" />
+             function="CustomizeAvatar" />
             <menu_item_call.on_enable
              function="Edit.EnableCustomizeAvatar" />
        </menu_item_call>
-       <menu_item_call 
-         label="Shape..."
+       <menu_item_call label="Hover height..."
          layout="topleft"
-         name="Edit My Shape">
+         name="Hover Height">
+            <menu_item_call.on_click
+             function="HoverHeight" />
+            <menu_item_call.on_enable
+             function="Edit.EnableHoverHeight" />
+      </menu_item_call>
+      <menu_item_call
+        label="Edit shape..."
+        layout="topleft"
+        name="Edit My Shape">
             <menu_item_call.on_click
              function="EditShape" />
             <menu_item_call.on_enable
              function="Edit.EnableEditShape" />
       </menu_item_call>
-       <menu_item_call label="Hover height..."
-         layout="topleft"
-         name="Hover Height">
+      <menu_item_call
+        label="Edit outfit parts..."
+        layout="topleft"
+        name="Edit Outfit">
             <menu_item_call.on_click
-             function="HoverHeight" />
+             function="EditOutfit" />
             <menu_item_call.on_enable
-             function="Edit.EnableHoverHeight" />
+             function="Edit.EnableCustomizeAvatar" />
       </menu_item_call>
       <menu
-        label="Take Off"
+        label="Take off"
         layout="topleft"
         name="Take Off &gt;">
         <menu
@@ -390,8 +390,16 @@
         </menu_item_call>
       </menu>
       <menu_item_separator/>
+      <menu_item_call
+        label="Complete avatars..."
+        name="Avatar Picker">
+        <menu_item_call.on_click
+         function="Floater.ToggleOrBringToFront"
+         parameter="avatar" />
+      </menu_item_call>
+      <menu_item_separator/>
 
-       <menu_item_call
+      <menu_item_call
          label="Sit / stand"
          layout="topleft"
          shortcut="alt|shift|S"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index c4c51afa82..d625f89f3b 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -81,7 +81,7 @@
             name="title"
             text_color="LtGray"
             top="0"
-            value="Current Outfit"
+            value="Edit outfit parts"
             use_ellipses="true"
             width="275" />
 
-- 
cgit v1.2.3


From 89b4611fc00a17d923c06d510da6842002113199 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 30 Mar 2021 15:53:22 +0300
Subject: SL-15036 Add actions to move landmarks between tabs in the Places
 floater

---
 indra/newview/llfavoritesbar.cpp                   |  4 ++
 indra/newview/llinventoryfunctions.cpp             | 20 ++++++++
 indra/newview/llinventoryfunctions.h               |  2 +
 indra/newview/llpanellandmarks.cpp                 | 56 +++++++++++++++++++++-
 .../skins/default/xui/en/menu_favorites.xml        |  8 ++++
 .../default/xui/en/menu_places_gear_landmark.xml   | 22 +++++++++
 6 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 8791f605e9..4a40a74dec 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1281,6 +1281,10 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
 
         LLNotificationsUtil::add("RenameLandmark", args, payload, boost::bind(onRenameCommit, _1, _2));
     }
+	else if (action == "move_to_landmarks")
+	{
+		change_item_parent(mSelectedItemID, gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
+	}
 
 	// Pop-up the overflow menu again (it gets hidden whenever the user clicks a context menu item).
 	// See EXT-4217 and STORM-207.
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f84bc68c82..f2e06d19f3 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -1847,6 +1847,26 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
     return result && !has_bad_items;
 }
 
+void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
+{
+	LLInventoryItem* inv_item = gInventory.getItem(item_id);
+	if (inv_item)
+	{
+		LLInventoryModel::update_list_t update;
+		LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
+		update.push_back(old_folder);
+		LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
+		update.push_back(new_folder);
+		gInventory.accountForUpdate(update);
+
+		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+		new_item->setParent(new_parent_id);
+		new_item->updateParentOnServer(FALSE);
+		gInventory.updateItem(new_item);
+		gInventory.notifyObservers();
+	}
+}
+
 ///----------------------------------------------------------------------------
 /// LLInventoryCollectFunctor implementations
 ///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 04eb962372..37c3c47336 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -92,6 +92,8 @@ S32  depth_nesting_in_marketplace(LLUUID cur_uuid);
 LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
 S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);
 
+void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id);
+
 /**                    Miscellaneous global functions
  **                                                                            **
  *******************************************************************************/
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 8bc4bca675..4b73412e60 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -615,6 +615,8 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 		? mCurrentSelectedList->getRootFolder() 
 		: NULL;
 
+	bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1;
+
 	if ("collapse_all" == command_name)
 	{
 		return has_expanded_folders(mCurrentSelectedList->getRootFolder());
@@ -669,7 +671,6 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 			)
 	{
 		// disable some commands for multi-selection. EXT-1757
-		bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1;
 		if (!is_single_selection)
 		{
 			return false;
@@ -718,7 +719,6 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 	}
     else if ("add_landmark" == command_name)
     {
-        bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1;
         if (!is_single_selection)
         {
             return false;
@@ -759,6 +759,36 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
         }
         return true;
     }
+	else if (command_name == "move_to_landmarks" || command_name == "move_to_favorites")
+	{
+		LLFolderViewModelItemInventory* cur_item_model = getCurSelectedViewModelItem();
+		if (cur_item_model)
+		{
+			LLFolderType::EType folder_type = command_name == "move_to_landmarks" ? LLFolderType::FT_FAVORITE : LLFolderType::FT_LANDMARK;
+			if (!gInventory.isObjectDescendentOf(cur_item_model->getUUID(), gInventory.findCategoryUUIDForType(folder_type)))
+			{
+				return false;
+			}
+
+			if (root_folder_view)
+			{
+				std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList();
+				for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter)
+				{
+					LLFolderViewItem* item = *iter;
+					if (!item) return false;
+
+					cur_item_model = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());
+					if (!cur_item_model || cur_item_model->getInventoryType() != LLInventoryType::IT_LANDMARK)
+					{
+						return false;
+					}
+				}
+				return true;
+			}
+		}
+		return false;
+	}
 	else
 	{
 		LL_WARNS() << "Unprocessed command has come: " << command_name << LL_ENDL;
@@ -798,6 +828,28 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
 	{
 		mCurrentSelectedList->doToSelected(userdata);
 	}
+	else if (command_name == "move_to_landmarks" || command_name == "move_to_favorites")
+	{
+		LLFolderView* root_folder_view = mCurrentSelectedList ? mCurrentSelectedList->getRootFolder() : NULL;
+		if (root_folder_view)
+		{
+			LLFolderType::EType folder_type = command_name == "move_to_landmarks" ? LLFolderType::FT_LANDMARK : LLFolderType::FT_FAVORITE;
+			std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList();
+			for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter)
+			{
+				LLFolderViewItem* item = *iter;
+				if (item)
+				{
+					LLFolderViewModelItemInventory* item_model = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());
+					if (item_model)
+					{
+						change_item_parent(item_model->getUUID(), gInventory.findCategoryUUIDForType(folder_type));
+					}
+				}
+			}
+		}
+
+	}
 }
 
 void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param)
diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml
index 6c28032e3f..0eab7c451b 100644
--- a/indra/newview/skins/default/xui/en/menu_favorites.xml
+++ b/indra/newview/skins/default/xui/en/menu_favorites.xml
@@ -20,6 +20,14 @@
          function="Favorites.DoToSelected"
          parameter="about" />
     </menu_item_call>
+    <menu_item_call
+     label="Move to Landmarks"
+     layout="topleft"
+     name="Move to Landmarks">
+        <menu_item_call.on_click
+         function="Favorites.DoToSelected"
+         parameter="move_to_landmarks" />
+    </menu_item_call>
     <menu_item_call
      label="Show on Map"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
index 7a7edc0ab7..c89b498ddf 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -39,6 +39,28 @@
          function="Places.LandmarksGear.Enable"
          parameter="more_info" />
     </menu_item_call>
+    <menu_item_call
+       label="Move to Landmarks"
+       layout="topleft"
+       name="Move to Landmarks">
+      <menu_item_call.on_click
+       function="Places.LandmarksGear.Custom.Action"
+       parameter="move_to_landmarks" />
+      <menu_item_call.on_visible
+       function="Places.LandmarksGear.Enable"
+       parameter="move_to_landmarks" />
+    </menu_item_call>
+    <menu_item_call
+       label="Move to Favorites"
+       layout="topleft"
+       name="Move to Favorites">
+      <menu_item_call.on_click
+       function="Places.LandmarksGear.Custom.Action"
+       parameter="move_to_favorites" />
+      <menu_item_call.on_visible
+       function="Places.LandmarksGear.Enable"
+       parameter="move_to_favorites" />
+    </menu_item_call>
     <menu_item_call
      label="Show on Map"
      layout="topleft"
-- 
cgit v1.2.3


From 6dbde938e2c72259e941b10fe0a96ba196c95de9 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 30 Mar 2021 18:34:50 +0300
Subject: SL-15050 Change name of toolbar button to "Guidebook"

---
 indra/newview/skins/default/xui/en/strings.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index d9d0b659cc..921f689732 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4126,7 +4126,7 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Environments_Label">My Environments</string>
   <string name="Command_Gestures_Label">Gestures</string>
   <string name="Command_Grid_Status_Label">Grid status</string>
-  <string name="Command_HowTo_Label">How to</string>
+  <string name="Command_HowTo_Label">Guidebook</string>
   <string name="Command_Inventory_Label">Inventory</string>
   <string name="Command_Map_Label">Map</string>
   <string name="Command_Marketplace_Label">Marketplace</string>
-- 
cgit v1.2.3


From e8d95d0a9db87b324a6a20a2f15f46b049b93534 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 1 Apr 2021 21:55:19 +0300
Subject: Merge conflict: restored lost part of SL-13479

---
 indra/newview/skins/default/xui/en/menu_viewer.xml | 117 +++------------------
 1 file changed, 17 insertions(+), 100 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index d7ffe72540..c550f69d26 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -65,107 +65,24 @@
          function="Floater.ToggleOrBringToFront"
          parameter="camera" />
       </menu_item_call>
-      <menu
-       create_jump_keys="true"
-       label="Movement"
-       name="Movement"
-       tear_off="true">
-        <menu_item_call
-         label="Sit Down"
-         layout="topleft"
-         shortcut="alt|shift|S"
-         name="Sit Down Here">
-          <menu_item_call.on_click
-           function="Self.SitDown"/>
-          <menu_item_call.on_visible
-           function="Self.ShowSitDown"/>
-          <menu_item_call.on_enable
-           function="Self.EnableSitDown" />
-        </menu_item_call>
-        <menu_item_call
-         label="Stand Up"
-         layout="topleft"
-         shortcut="alt|shift|S"
-         name="Stand up">
-          <menu_item_call.on_click
-           function="Self.StandUp"/>
-          <menu_item_call.on_visible
-           function="Self.EnableStandUp"/>
-          <menu_item_call.on_enable
-           function="Self.EnableStandUp" />
-        </menu_item_call>
-        <menu_item_check
-         label="Fly"
-         name="Fly"
-         shortcut="HOME">
-          <menu_item_check.on_check
-           function="Agent.getFlying" />
-          <menu_item_check.on_click
-           function="Agent.toggleFlying" />
-          <menu_item_check.on_enable
-           function="Agent.enableFlying" />
-        </menu_item_check>
-        <menu_item_call
-         label="Stop flying"
-         name="Stop flying"
-         shortcut="HOME">
-          <menu_item_call.on_click
-           function="Agent.toggleFlying" />
-          <menu_item_call.on_enable
-           function="Agent.getFlying" />
-        </menu_item_call>	
-        <menu_item_check
-         label="Always Run"
-         name="Always Run"
-         shortcut="control|R">
-          <menu_item_check.on_check
-           function="World.CheckAlwaysRun" />
-          <menu_item_check.on_click
-           function="World.AlwaysRun" />
-        </menu_item_check>
-        <menu_item_call
-         label="Stop Animating Me"
-         name="Stop Animating My Avatar"
-         allow_key_repeat="true"
-         shortcut="alt|shift|A">
-          <menu_item_call.on_click
-           function="Tools.StopAllAnimations" />
-        </menu_item_call>
-        <menu_item_check
-         label="Walk / run / fly..."
-         name="WalkRunFly">
-          <menu_item_check.on_check
-           function="Floater.Visible"
-           parameter="moveview" />
-          <menu_item_check.on_click
-           function="Floater.ToggleOrBringToFront"
-           parameter="moveview" />
-        </menu_item_check>
-      </menu>
 
-      <menu
-       create_jump_keys="true"
-       label="Status"
-       name="Status"
-       tear_off="true">
-        <menu_item_check
-         name="Away"
-         label="Away">
-          <menu_item_check.on_check
-           function="View.Status.CheckAway" />
-          <menu_item_check.on_click
-           function="World.SetAway" />
-        </menu_item_check>
-        <menu_item_check
-         name="Do Not Disturb"
-         label="Do Not Disturb">
-          <menu_item_check.on_check
-           function="View.Status.CheckDoNotDisturb" />
-          <menu_item_check.on_click
-           function="World.SetDoNotDisturb"/>
-        </menu_item_check>
-      
-    </menu>
+      <menu_item_separator/>
+      <menu_item_check
+       name="Away"
+       label="Away">
+        <menu_item_check.on_check
+         function="View.Status.CheckAway" />
+        <menu_item_check.on_click
+         function="World.SetAway" />
+      </menu_item_check>
+      <menu_item_check
+       name="Do Not Disturb"
+       label="Do Not Disturb">
+        <menu_item_check.on_check
+         function="View.Status.CheckDoNotDisturb" />
+        <menu_item_check.on_click
+         function="World.SetDoNotDisturb"/>
+      </menu_item_check>
 
       <menu_item_separator/>
 
-- 
cgit v1.2.3


From 26a0df8988d116ed0e2a9e3c559786ac5884feb9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 13 Apr 2021 11:35:09 +0300
Subject: SL-14654 Fixed transition time in fixed editor being different from
 day editor

---
 indra/newview/llfloaterfixedenvironment.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index cd8e0a48e7..e98cb16ca9 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -161,7 +161,7 @@ void LLFloaterFixedEnvironment::onOpen(const LLSD& key)
     updateEditEnvironment();
     syncronizeTabs();
     refresh();
-    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT);
 
 }
 
@@ -374,7 +374,7 @@ void LLFloaterFixedEnvironment::onAssetLoaded(LLUUID asset_id, LLSettingsBase::p
     updateEditEnvironment();
     syncronizeTabs();
     refresh();
-    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
 }
 
 void LLFloaterFixedEnvironment::onNameChanged(const std::string &name)
@@ -795,7 +795,7 @@ void LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile(const std::vector<
     setDirtyFlag();
     LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, legacywater);
     setEditSettings(legacywater);
-    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST, true);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT, true);
 }
 
 //=========================================================================
@@ -883,7 +883,7 @@ void LLFloaterFixedEnvironmentSky::loadSkySettingFromFile(const std::vector<std:
     setDirtyFlag();
     LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, legacysky);
     setEditSettings(legacysky);
-    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST, true);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT, true);
 }
 
 //=========================================================================
-- 
cgit v1.2.3


From 8772aed531ace9fda06649c1656c4cba98d270a9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 13 Apr 2021 22:44:27 +0300
Subject: SL-15013 Block List very often is empty when I log in

It looks like these messages were often getting lost.
These requests have higher, more visible impact if lost, so doubled retries.
As per Ansariel's suggestion moved request to a less busy stage.
---
 indra/newview/llmutelist.cpp  | 15 ++++++++++++++-
 indra/newview/llstartup.cpp   | 20 ++++++++++++--------
 indra/newview/llstatusbar.cpp | 15 ++++++++++++++-
 3 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 663a6071f7..4a8ef53a8b 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -726,7 +726,20 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id)
 	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 	msg->nextBlockFast(_PREHASH_MuteData);
 	msg->addU32Fast(_PREHASH_MuteCRC, crc.getCRC());
-	gAgent.sendReliableMessage();
+
+    if (gDisconnected)
+    {
+        LL_WARNS() << "Trying to request mute list when disconnected!" << LL_ENDL;
+        return;
+    }
+    if (!gAgent.getRegion())
+    {
+        LL_WARNS() << "No region for agent yet, skipping mute list request!" << LL_ENDL;
+        return;
+    }
+    // Double amount of retries due to this request happening during busy stage
+    // Ideally this should be turned into a capability
+    gMessageSystem->sendReliable(gAgent.getRegionHost(), LL_DEFAULT_RELIABLE_RETRIES * 2, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 85b578730e..ba39cf083d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1668,8 +1668,20 @@ bool idle_startup()
 	if (STATE_INVENTORY_SEND == LLStartUp::getStartupState())
 	{
 		display_startup();
+
+        // request mute list
+        LL_INFOS() << "Requesting Mute List" << LL_ENDL;
+        LLMuteList::getInstance()->requestFromServer(gAgent.getID());
+
+        // Get L$ and ownership credit information
+        LL_INFOS() << "Requesting Money Balance" << LL_ENDL;
+        LLStatusBar::sendMoneyBalanceRequest();
+
+        display_startup();
+
 		// Inform simulator of our language preference
 		LLAgentLanguage::update();
+
 		display_startup();
 		// unpack thin inventory
 		LLSD response = LLLoginInstance::getInstance()->getResponse();
@@ -1836,14 +1848,6 @@ bool idle_startup()
 		LLLandmark::registerCallbacks(msg);
 		display_startup();
 
-		// request mute list
-		LL_INFOS() << "Requesting Mute List" << LL_ENDL;
-		LLMuteList::getInstance()->requestFromServer(gAgent.getID());
-		display_startup();
-		// Get L$ and ownership credit information
-		LL_INFOS() << "Requesting Money Balance" << LL_ENDL;
-		LLStatusBar::sendMoneyBalanceRequest();
-		display_startup();
 		// request all group information
 		LL_INFOS() << "Requesting Agent Data" << LL_ENDL;
 		gAgent.sendAgentDataUpdateRequest();
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 4d55448d78..0a87b14e17 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -416,7 +416,20 @@ void LLStatusBar::sendMoneyBalanceRequest()
 	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 	msg->nextBlockFast(_PREHASH_MoneyData);
 	msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null );
-	gAgent.sendReliableMessage();
+
+    if (gDisconnected)
+    {
+        LL_DEBUGS() << "Trying to send message when disconnected, skipping balance request!" << LL_ENDL;
+        return;
+    }
+    if (!gAgent.getRegion())
+    {
+        LL_DEBUGS() << "LLAgent::sendReliableMessage No region for agent yet, skipping balance request!" << LL_ENDL;
+        return;
+    }
+    // Double amount of retries due to this request initially happening during busy stage
+    // Ideally this should be turned into a capability
+    gMessageSystem->sendReliable(gAgent.getRegionHost(), LL_DEFAULT_RELIABLE_RETRIES * 2, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
 }
 
 
-- 
cgit v1.2.3


From 2b8bf89ee9fbd536eab0d49c135f0bf32caa4555 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 2 Feb 2021 17:28:10 +0200
Subject: SL-14800 Clarify message when maturity level exceeded

---
 indra/newview/skins/default/xui/en/notifications.xml | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index bba6a5e9f2..87a702faab 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5084,7 +5084,9 @@ Do you wish to proceed?
    name="RegionEntryAccessBlocked"
    type="alertmodal">
    <tag>fail</tag>
-    The region you're trying to visit contains content exceeding your current preferences.  You can change your preferences using Me &gt; Preferences &gt; General.
+    The region you’re trying to visit has a maturity rating exceeding your maximum maturity preference. Change this preference using Me menu &gt; Preferences &gt; General.
+
+Complete information on maturity ratings can be found [https://community.secondlife.com/knowledgebase/english/maturity-ratings-r52/ here].
     <usetemplate
      name="okbutton"
      yestext="OK"/>
@@ -5171,7 +5173,9 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu
    name="TeleportEntryAccessBlocked"
    type="alertmodal">
     <tag>fail</tag>
-    The region you're trying to visit contains content exceeding your current preferences.  You can change your preferences using Me &gt; Preferences &gt; General.
+    The region you’re trying to visit has a maturity rating exceeding your maximum maturity preference. Change this preference using Me menu &gt; Preferences &gt; General.
+
+Complete information on maturity ratings can be found [https://community.secondlife.com/knowledgebase/english/maturity-ratings-r52/ here].
     <usetemplate
      name="okbutton"
      yestext="OK"/>
@@ -5320,6 +5324,8 @@ You won't receive any more notifications that you're about to visit a region wit
    name="LandClaimAccessBlocked"
    type="alertmodal">
     The land you're trying to claim has a maturity rating exceeding your current preferences.  You can change your preferences using Me &gt; Preferences &gt; General.
+
+Complete information on maturity ratings can be found [https://community.secondlife.com/knowledgebase/english/maturity-ratings-r52/ here].
     <tag>fail</tag>
     <usetemplate
      name="okbutton"
@@ -5389,6 +5395,8 @@ You won't receive any more notifications that you're about to visit a region wit
    name="LandBuyAccessBlocked"
    type="alertmodal">
     The land you're trying to buy has a maturity rating exceeding your current preferences.  You can change your preferences using Me &gt; Preferences &gt; General.
+
+Complete information on maturity ratings can be found [https://community.secondlife.com/knowledgebase/english/maturity-ratings-r52/ here].
     <tag>fail</tag>
     <usetemplate
      name="okbutton"
@@ -7257,8 +7265,10 @@ You can only claim public land in the Region you&apos;re in.
    name="RegionTPAccessBlocked"
    type="alertmodal">
    <tag>fail</tag>
-    The region you're trying to visit contains content exceeding your current preferences.  You can change your preferences using Me &gt; Preferences &gt; General.
-   <usetemplate
+    The region you’re trying to visit has a maturity rating exceeding your maximum maturity preference. Change this preference using Me menu &gt; Preferences &gt; General.
+
+Complete information on maturity ratings can be found [https://community.secondlife.com/knowledgebase/english/maturity-ratings-r52/ here].
+    <usetemplate
       name="okbutton"
       yestext="OK"/>
   </notification>
-- 
cgit v1.2.3


From 669dd6adbe29cdbd77d75e7d371a9733be785ea4 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 15 Apr 2021 01:23:04 +0300
Subject: SL-14906 Open Guidebook floater on first login

---
 indra/newview/llstartup.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index ba39cf083d..b7606f7f23 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1905,9 +1905,14 @@ bool idle_startup()
 			// on with this install.
 			gSavedSettings.setBOOL("ShowStartLocation", TRUE);
 
-			// Open Conversation floater on first login.
-			LLFloaterReg::toggleInstanceOrBringToFront("im_container");
-
+            LLFloaterWebContent::Params p;
+            std::string url = gSavedSettings.getString("GuidebookURL");
+            p.url = LLWeb::expandURLSubstitutions(url, LLSD());
+            p.show_chrome = false;
+            p.show_page_title = false;
+            p.preferred_media_size = LLRect(0, 500, 300, 0);
+
+            LLFloaterReg::toggleInstanceOrBringToFront("how_to", p);
 		}
 
 		display_startup();
-- 
cgit v1.2.3


From 96daac0ab458a3e1cd425ee4b580470e6b02416f Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 15 Apr 2021 17:34:21 +0300
Subject: SL-15118 Search link in People floater should open Search but not
 submit a search.

---
 indra/newview/skins/default/xui/en/panel_people.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 3c8a2fe4f4..50035fd0e3 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -36,7 +36,7 @@ Looking for places with more people?
 
 [secondlife:///app/floater/destinations Destination Guide] has locations chosen by Second Life staff.
 
-[secondlife:///app/search/people Search] lets you search all of Second Life for certain keywords.
+[secondlife:///app/search/ Search] lets you search all of Second Life for certain keywords.
     </string>
     <string
      name="no_filtered_friends_msg">
-- 
cgit v1.2.3


From 3780c86538ee667bb74f0a70bcf870ec554eda75 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 16 Apr 2021 00:01:57 +0300
Subject: SL-15028 Move guidebook code into own flaoter

To help with dispatcher and unify code
---
 indra/newview/CMakeLists.txt         |  2 ++
 indra/newview/llfloaterhowto.cpp     | 66 ++++++++++++++++++++++++++++++++++++
 indra/newview/llfloaterhowto.h       | 51 ++++++++++++++++++++++++++++
 indra/newview/llstartup.cpp          |  9 +----
 indra/newview/llviewerfloaterreg.cpp |  3 +-
 indra/newview/llviewermenu.cpp       |  9 +----
 6 files changed, 123 insertions(+), 17 deletions(-)
 create mode 100644 indra/newview/llfloaterhowto.cpp
 create mode 100644 indra/newview/llfloaterhowto.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 456fcdf574..405b4e09ba 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -255,6 +255,7 @@ set(viewer_SOURCE_FILES
     llfloaterhandler.cpp
     llfloaterhelpbrowser.cpp
     llfloaterhoverheight.cpp
+    llfloaterhowto.cpp
     llfloaterhud.cpp
     llfloaterimagepreview.cpp
     llfloaterimsessiontab.cpp
@@ -890,6 +891,7 @@ set(viewer_HEADER_FILES
     llfloaterhandler.h
     llfloaterhelpbrowser.h
     llfloaterhoverheight.h
+    llfloaterhowto.h
     llfloaterhud.h
     llfloaterimagepreview.h
     llfloaterimnearbychat.h
diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
new file mode 100644
index 0000000000..d6c4ed1b20
--- /dev/null
+++ b/indra/newview/llfloaterhowto.cpp
@@ -0,0 +1,66 @@
+/** 
+ * @file llfloaterhowto.cpp
+ * @brief A variant of web floater meant to open guidebook
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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 "llfloaterhowto.h"
+
+#include "llfloaterreg.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+
+
+LLFloaterHowTo::LLFloaterHowTo(const Params& key) :
+    LLFloaterWebContent(key)
+{
+    mShowPageTitle = false;
+}
+
+BOOL LLFloaterHowTo::postBuild()
+{
+    LLFloaterWebContent::postBuild();
+
+    return TRUE;
+}
+
+void LLFloaterHowTo::onOpen(const LLSD& key)
+{
+    LLFloaterWebContent::Params p(key);
+    if (!p.url.isProvided() || p.url.getValue().empty())
+    {
+        std::string url = gSavedSettings.getString("GuidebookURL");
+        p.url = LLWeb::expandURLSubstitutions(url, LLSD());
+        p.show_chrome = false;
+        p.preferred_media_size = LLRect(0, 500, 300, 0);
+    }
+
+    LLFloaterWebContent::onOpen(p);
+}
+
+LLFloaterHowTo* LLFloaterHowTo::getInstance()
+{
+    return LLFloaterReg::getTypedInstance<LLFloaterHowTo>("how_to");
+}
diff --git a/indra/newview/llfloaterhowto.h b/indra/newview/llfloaterhowto.h
new file mode 100644
index 0000000000..e08d102e2a
--- /dev/null
+++ b/indra/newview/llfloaterhowto.h
@@ -0,0 +1,51 @@
+/** 
+ * @file llfloaterhowto.h
+ * @brief A variant of web floater meant to open guidebook
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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_LLFLOATERHOWTO_H
+#define LL_LLFLOATERHOWTO_H
+
+#include "llfloaterwebcontent.h"
+
+class LLMediaCtrl;
+
+
+class LLFloaterHowTo :
+    public LLFloaterWebContent
+{
+public:
+
+    LLFloaterHowTo(const Params& key);
+
+    /*virtual*/ void onOpen(const LLSD& key);
+
+    static LLFloaterHowTo* getInstance();
+
+private:
+    /*virtual*/ BOOL postBuild();
+};
+
+#endif  // LL_LLFLOATERHOWTO_H
+
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index b7606f7f23..486c33cb43 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1905,14 +1905,7 @@ bool idle_startup()
 			// on with this install.
 			gSavedSettings.setBOOL("ShowStartLocation", TRUE);
 
-            LLFloaterWebContent::Params p;
-            std::string url = gSavedSettings.getString("GuidebookURL");
-            p.url = LLWeb::expandURLSubstitutions(url, LLSD());
-            p.show_chrome = false;
-            p.show_page_title = false;
-            p.preferred_media_size = LLRect(0, 500, 300, 0);
-
-            LLFloaterReg::toggleInstanceOrBringToFront("how_to", p);
+            LLFloaterReg::toggleInstanceOrBringToFront("how_to");
 		}
 
 		display_startup();
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 46ff441719..de184392f9 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -76,6 +76,7 @@
 #include "llfloatergroups.h"
 #include "llfloaterhelpbrowser.h"
 #include "llfloaterhoverheight.h"
+#include "llfloaterhowto.h"
 #include "llfloaterhud.h"
 #include "llfloaterimagepreview.h"
 #include "llfloaterimsession.h"
@@ -362,7 +363,7 @@ void LLViewerFloaterReg::registerFloaters()
     LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
 	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
 	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
-	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
+	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
 
 	LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
 	
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 78f6f23bc5..8ae245b924 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7746,14 +7746,7 @@ class LLToggleHowTo : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		LLFloaterWebContent::Params p;
-		std::string url = gSavedSettings.getString("GuidebookURL");
-		p.url = LLWeb::expandURLSubstitutions(url, LLSD());
-		p.show_chrome = false;
-		p.show_page_title = false;
-		p.preferred_media_size = LLRect(0, 500, 300, 0);
-
-		LLFloaterReg::toggleInstanceOrBringToFront("how_to", p);
+		LLFloaterReg::toggleInstanceOrBringToFront("how_to");
 		return true;
 	}
 };
-- 
cgit v1.2.3


From 8cd5d7c58a10a9d3c35af95048b3fbc994c72301 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Sat, 17 Apr 2021 00:36:10 +0300
Subject: SL-14906 More adjustments to guidebook

The Guidebook should remember it's open/closed state between sessions.
The Guidebook button should show as pressed while the Guidebook is open.
---
 indra/newview/app_settings/commands.xml               | 6 ++++--
 indra/newview/llviewermenu.cpp                        | 8 --------
 indra/newview/skins/default/xui/en/floater_how_to.xml | 1 +
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 9a4ab8b44b..91841b970d 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -88,8 +88,10 @@
            icon="Command_HowTo_Icon"
            label_ref="Command_HowTo_Label"
            tooltip_ref="Command_HowTo_Tooltip"
-           execute_function="Help.ToggleHowTo"
-           is_running_function="Help.HowToVisible"
+           execute_function="Floater.ToggleOrBringToFront"
+           execute_parameters="how_to"
+           is_running_function="Floater.IsOpen"
+           is_running_parameters="how_to"
            />
   <command name="inventory"
            available_in_toybox="true"
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 8ae245b924..918a469836 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -5000,13 +5000,6 @@ bool tools_visible_take_object()
 	return !is_selection_buy_not_take();
 }
 
-bool enable_how_to_visible(const LLSD& param)
-{
-	LLFloaterWebContent::Params p;
-	p.target = "__help_how_to";
-	return LLFloaterReg::instanceVisible("how_to", p);
-}
-
 class LLToolsEnableBuyOrTake : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -9103,7 +9096,6 @@ void initialize_menus()
 	// Help menu
 	// most items use the ShowFloater method
 	view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo");
-	enable.add("Help.HowToVisible", boost::bind(&enable_how_to_visible, _2));
 
 	// Advanced menu
 	view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index b79584c7b7..c06ff7be28 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -10,6 +10,7 @@
   min_width="335"
   name="floater_how_to"
   single_instance="true"
+  save_visibility="true"
   save_rect="true"
   title="WELCOME ISLAND GUIDEBOOK"
   width="780"
-- 
cgit v1.2.3


From 7b5dd3154b81f1cbd1f653db6ad76850dcb79d69 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 20 Apr 2021 14:48:13 +0300
Subject: SL-15028 Update menu items on the login screen

---
 indra/newview/skins/default/xui/en/menu_login.xml | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 07b3cc3bd8..96fac1c6e8 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -57,19 +57,12 @@
      tear_off="true"
      name="Help">
         <menu_item_call
-         label="How to..."
+         label="Guidebook"
          name="How To"
          shortcut="F1">
             <menu_item_call.on_click
              function="Help.ToggleHowTo"
              parameter="" />
-        </menu_item_call>
-        <menu_item_call
-           label="Quickstart"
-           name="Quickstart">
-            <menu_item_call.on_click
-            function="Advanced.ShowURL"
-            parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Quickstart/ta-p/1087919"/>
         </menu_item_call>
 		<menu_item_separator/>
         <menu_item_call
-- 
cgit v1.2.3


From d298c9983b9ffc9f212fd9325b1ff5f0e6e7aaab Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 20 Apr 2021 20:00:42 +0300
Subject: SL-14906 Fix LLFloaterHowTo overriding stored position

preferred_media_size was repositioning the floater
---
 indra/newview/llfloaterhowto.cpp                    | 21 ++++++++++++++-------
 .../newview/skins/default/xui/en/floater_how_to.xml |  6 ++----
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index d6c4ed1b20..665955c946 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -33,6 +33,9 @@
 #include "llweb.h"
 
 
+const S32 STACK_WIDTH = 300;
+const S32 STACK_HEIGHT = 505; // content will be 500
+
 LLFloaterHowTo::LLFloaterHowTo(const Params& key) :
     LLFloaterWebContent(key)
 {
@@ -49,15 +52,19 @@ BOOL LLFloaterHowTo::postBuild()
 void LLFloaterHowTo::onOpen(const LLSD& key)
 {
     LLFloaterWebContent::Params p(key);
-    if (!p.url.isProvided() || p.url.getValue().empty())
-    {
-        std::string url = gSavedSettings.getString("GuidebookURL");
-        p.url = LLWeb::expandURLSubstitutions(url, LLSD());
-        p.show_chrome = false;
-        p.preferred_media_size = LLRect(0, 500, 300, 0);
-    }
+    std::string url = gSavedSettings.getString("GuidebookURL");
+    p.url = LLWeb::expandURLSubstitutions(url, LLSD());
+    p.show_chrome = false;
 
     LLFloaterWebContent::onOpen(p);
+
+    // Elements from LLFloaterWebContent did not pick up restored size (save_rect) of LLFloaterHowTo
+    // set the stack size and position (alternative to preferred_media_size)
+    LLLayoutStack *stack = getChild<LLLayoutStack>("stack1");
+    LLRect stack_rect = stack->getRect();
+    stack->reshape(STACK_WIDTH, STACK_HEIGHT);
+    stack->setOrigin(stack_rect.mLeft, stack_rect.mTop - STACK_HEIGHT);
+    stack->updateLayout();
 }
 
 LLFloaterHowTo* LLFloaterHowTo::getInstance()
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index c06ff7be28..b4dd2e252f 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -4,14 +4,12 @@
   can_resize="false"
   can_minimize="false"
   can_close="false" 
-  height="775"
+  height="525"
   layout="topleft"
-  top="0" 
-  min_width="335"
   name="floater_how_to"
   single_instance="true"
   save_visibility="true"
   save_rect="true"
   title="WELCOME ISLAND GUIDEBOOK"
-  width="780"
+  width="310"
   filename="floater_web_content.xml"/>
\ No newline at end of file
-- 
cgit v1.2.3


From bf5ae51d2e4d0e998fd2dae023d893b8213e8549 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 21 Apr 2021 01:22:06 +0300
Subject: SL-14842 Clear history button was in wrong menu

---
 .../skins/default/xui/en/menu_teleport_history_gear.xml       | 11 -----------
 .../skins/default/xui/en/menu_teleport_history_item.xml       | 11 +++++++++++
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
index 0b75fd781a..c11d668698 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
@@ -28,15 +28,4 @@
          function="TeleportHistory.GearMenu.Enable"
          parameter="collapse_all" />
     </menu_item_call>
-    <menu_item_separator layout="topleft" />
-    <menu_item_call
-     label="Clear Teleport History"
-     name="Clear Teleport History">
-        <menu_item_call.on_click
-         function="TeleportHistory.GearMenu.Action"
-         parameter="clear_history" />
-        <on_enable
-         function="TeleportHistory.GearMenu.Enable"
-         parameter="clear_history" />
-    </menu_item_call>    
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index 153e5a70a9..f60f02f040 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -49,4 +49,15 @@
          function="TeleportHistory.GearMenu.Enable"
          parameter="copy_slurl" />
     </menu_item_call>
+    <menu_item_separator layout="topleft" />
+    <menu_item_call
+     label="Clear Teleport History"
+     name="Clear Teleport History">
+      <menu_item_call.on_click
+       function="TeleportHistory.GearMenu.Action"
+       parameter="clear_history" />
+      <on_enable
+       function="TeleportHistory.GearMenu.Enable"
+       parameter="clear_history" />
+    </menu_item_call>
 </toggleable_menu>
-- 
cgit v1.2.3


From b9fa5d55b50739238ff4cfa8ce0f581b519de13f Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 21 Apr 2021 12:07:31 +0300
Subject: Revert "SL-14632 FIXED The viewer is crashed after deleting the new
 favorite folder"

---
 indra/newview/llviewerinventory.cpp | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 2b200c17c1..bbed741a33 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1422,11 +1422,6 @@ void remove_inventory_category(
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
 			return;
 		}
-		const LLUUID fav_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-		if ((cat_id == fav_id) || gInventory.isObjectDescendentOf(fav_id, cat_id))
-		{
-			gSavedPerAccountSettings.setString("FavoritesFolder", "");
-		}
         AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
         AISAPI::RemoveCategory(cat_id, cr);
 	}
@@ -1466,12 +1461,6 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 	LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id);
 	if (cat.notNull())
 	{
-		const LLUUID fav_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-		if ((id == fav_id) || gInventory.isObjectDescendentOf(fav_id, id))
-		{
-			gSavedPerAccountSettings.setString("FavoritesFolder", "");
-		}
-
 		if (LLClipboard::instance().hasContents())
 		{
 			// Remove items from clipboard or it will remain active even if there is nothing to paste/copy
-- 
cgit v1.2.3


From b1fad32e8b50fc7bb09a45f3454c24d6efeb4b15 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 21 Apr 2021 12:08:24 +0300
Subject: Revert "SL-14633 FIXED The item from the favorite tab in the
 inventory floater can be purged"

---
 indra/newview/llinventorybridge.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index a0c3608107..d6c662557f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -987,7 +987,7 @@ void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items,
 		}
 	}
 	items.push_back(std::string("Purge Item"));
-	if (!isItemRemovable() || isPanelActive("Favorite Items"))
+	if (!isItemRemovable())
 	{
 		disabled_items.push_back(std::string("Purge Item"));
 	}
-- 
cgit v1.2.3


From 2c88c74276ffd67ef511e4c3dabbf8e7c676b641 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 21 Apr 2021 12:12:04 +0300
Subject: Revert "SL-12475 add Inventory Favorites tab"

---
 indra/llui/llfolderview.h                          |   2 -
 .../newview/app_settings/settings_per_account.xml  |  11 ---
 indra/newview/llinventorybridge.cpp                |  56 ++---------
 indra/newview/llinventorymodel.cpp                 |   5 -
 indra/newview/llinventorypanel.cpp                 | 102 ---------------------
 indra/newview/llinventorypanel.h                   |  23 -----
 indra/newview/llpanelmaininventory.cpp             |  12 +--
 indra/newview/llpanelmaininventory.h               |   2 -
 .../skins/default/xui/en/menu_inventory.xml        |  14 ---
 .../skins/default/xui/en/panel_main_inventory.xml  |  40 +++-----
 indra/newview/skins/default/xui/en/strings.xml     |   3 +-
 11 files changed, 25 insertions(+), 245 deletions(-)

diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index c175034d75..6bb5e6c02e 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -241,8 +241,6 @@ public:
 	void dumpSelectionInformation();
 
 	virtual S32	notify(const LLSD& info) ;
-
-	void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; }
 	
 	bool useLabelSuffix() { return mUseLabelSuffix; }
 	virtual void updateMenu();
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 3d77ac43e5..537744b44c 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -403,17 +403,6 @@
         <key>Value</key>
         <string></string>
       </map>
-      <key>FavoritesFolder</key>
-      <map>
-        <key>Comment</key>
-        <string>User's chosen folder which will be shown in the Favorites tab (UUID)</string>
-        <key>Persist</key>
-        <integer>1</integer>
-        <key>Type</key>
-        <string>String</string>
-        <key>Value</key>
-        <string></string>
-      </map>
       <key>SnapshotBaseDir</key>
       <map>
         <key>Comment</key>
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index d6c662557f..8b61e6c61a 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -138,35 +138,6 @@ bool isMarketplaceSendAction(const std::string& action)
 	return ("send_to_marketplace" == action);
 }
 
-bool isPanelActive(const std::string& panel_name)
-{
-    LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
-    return (active_panel && (active_panel->getName() == panel_name));
-}
-
-bool isParentSystemFolder(const LLInventoryModel* model, const LLUUID& folder_id)
-{
-    if (!model || folder_id.isNull()) return false;
-
-    LLViewerInventoryCategory* cat = model->getCategory(folder_id);
-    if (cat)
-    {
-        if (cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY)
-        {
-            return false;
-        }
-        if (LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
-        {
-            return true;
-        }
-        else
-        {
-            return isParentSystemFolder(model, cat->getParentUUID());
-        }
-    }
-    return false;
-}
-
 // Used by LLFolderBridge as callback for directory fetching recursion
 class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
 {
@@ -917,7 +888,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		disabled_items.push_back(std::string("Properties"));
 	}
 
-	if (!isPanelActive("All Items"))
+	LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+	if (active_panel && (active_panel->getName() != "All Items"))
 	{
 		items.push_back(std::string("Show in Main Panel"));
 	}
@@ -1008,7 +980,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
 
 	items.push_back(std::string("Delete"));
 
-	if (!isItemRemovable() || isPanelActive("Favorite Items"))
+	if (!isItemRemovable())
 	{
 		disabled_items.push_back(std::string("Delete"));
 	}
@@ -4021,7 +3993,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		disabled_items.push_back(std::string("New Clothes"));
 		disabled_items.push_back(std::string("New Body Parts"));
 		disabled_items.push_back(std::string("upload_def"));
-		disabled_items.push_back(std::string("Set Favorites folder"));
 	}
 	if (favorites == mUUID)
 	{
@@ -4049,7 +4020,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		disabled_items.push_back(std::string("New Clothes"));
 		disabled_items.push_back(std::string("New Body Parts"));
 		disabled_items.push_back(std::string("upload_def"));
-		disabled_items.push_back(std::string("Set Favorites folder"));
     }
     if (marketplace_listings_id == mUUID)
     {
@@ -4058,14 +4028,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
         disabled_items.push_back(std::string("Cut"));
         disabled_items.push_back(std::string("Delete"));
     }
-
-	if (isPanelActive("Favorite Items"))
-	{
-		disabled_items.push_back(std::string("Delete"));
-	}
 	if(trash_id == mUUID)
 	{
-		bool is_recent_panel = isPanelActive("Recent Items");
+		bool is_recent_panel = false;
+		LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+		if (active_panel && (active_panel->getName() == "Recent Items"))
+		{
+			is_recent_panel = true;
+		}
 
 		// This is the trash.
 		items.push_back(std::string("Empty Trash"));
@@ -4115,14 +4085,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
                     items.push_back(std::string("New Settings"));
                     items.push_back(std::string("upload_def"));
 
-                    if (model->findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE) == mUUID)
-                    {
-                        items.push_back(std::string("Reset Favorites folder"));
-                    }
-                    else if (!LLFolderType::lookupIsProtectedType(getPreferredType()) && !isParentSystemFolder(model, mUUID))
-                    {
-                        items.push_back(std::string("Set Favorites folder"));
-                    }
                     if (!LLEnvironment::instance().isInventoryEnabled())
                     {
                         disabled_items.push_back("New Settings");
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 48187c6179..28db6a5808 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -543,11 +543,6 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
         cat_id = LLUUID(gSavedPerAccountSettings.getString("AnimationUploadFolder"));
         break;
     }
-    case LLFolderType::FT_FAVORITE:
-    {
-        cat_id = LLUUID(gSavedPerAccountSettings.getString("FavoritesFolder"));
-        break;
-    }
     default:
         break;
     }
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index cda39c716b..3608f9e23f 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -181,8 +181,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
 	mCommitCallbackRegistrar.add("Inventory.Share",  boost::bind(&LLAvatarActions::shareWithAvatars, this));
 	mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryPanel::fileUploadLocation, this, _2));
-	mCommitCallbackRegistrar.add("Inventory.SetFavoritesFolder", boost::bind(&LLInventoryPanel::setFavoritesFolder, this, _2));
-    mCommitCallbackRegistrar.add("Inventory.ResetFavoritesFolder", boost::bind(&LLInventoryPanel::resetFavoritesFolder, this, _2));
 }
 
 LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
@@ -1473,16 +1471,6 @@ void LLInventoryPanel::fileUploadLocation(const LLSD& userdata)
     }
 }
 
-void LLInventoryPanel::setFavoritesFolder(const LLSD& userdata)
-{
-    gSavedPerAccountSettings.setString("FavoritesFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
-}
-
-void LLInventoryPanel::resetFavoritesFolder(const LLSD& userdata)
-{
-    gSavedPerAccountSettings.setString("FavoritesFolder", "");
-}
-
 void LLInventoryPanel::purgeSelectedItems()
 {
     if (!mFolderRoot.get()) return;
@@ -1864,96 +1852,6 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
 	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
 }
 
-static LLDefaultChildRegistry::Register<LLInventoryFavoriteItemsPanel> t_favorites_inventory_panel("favorites_inventory_panel");
-
-LLInventoryFavoriteItemsPanel::LLInventoryFavoriteItemsPanel(const Params& params)
-    : LLInventoryPanel(params)
-{
-    std::string ctrl_name = "FavoritesFolder";
-    if (gSavedPerAccountSettings.controlExists(ctrl_name))
-    {
-        LLPointer<LLControlVariable> cntrl_ptr = gSavedPerAccountSettings.getControl(ctrl_name);
-        if (cntrl_ptr.notNull())
-        {
-            mFolderChangedSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLInventoryFavoriteItemsPanel::updateFavoritesRootFolder, this));
-        }
-    }
-}
-
-void LLInventoryFavoriteItemsPanel::setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)
-{
-    if (mFolderRoot.get())
-    {
-        mFolderRoot.get()->setSelectCallback(cb);
-        mSelectionCallback = cb;
-    }
-}
-
-void LLInventoryFavoriteItemsPanel::initFromParams(const Params& p)
-{
-    Params fav_params(p);
-    fav_params.start_folder.id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-    LLInventoryPanel::initFromParams(fav_params);
-    updateFavoritesRootFolder();
-}
-
-void LLInventoryFavoriteItemsPanel::updateFavoritesRootFolder()
-{
-    const LLUUID& folder_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-
-    bool is_favorites_set = (folder_id != gInventory.findCategoryUUIDForTypeInRoot(LLFolderType::FT_FAVORITE, true, gInventory.getRootFolderID()));
-
-    if (!is_favorites_set || folder_id != getRootFolderID())
-    {
-        LLUUID root_id = folder_id;
-        if (mFolderRoot.get())
-        {
-            removeItemID(getRootFolderID());
-            mFolderRoot.get()->destroyView();
-        }
-
-        mCommitCallbackRegistrar.pushScope();
-        {
-            LLFolderView* folder_view = createFolderRoot(root_id);
-            mFolderRoot = folder_view->getHandle();
-
-            addItemID(root_id, mFolderRoot.get());
-
-
-            LLRect scroller_view_rect = getRect();
-            scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
-            LLScrollContainer::Params scroller_params(mParams.scroll());
-            scroller_params.rect(scroller_view_rect);
-
-            if (mScroller)
-            {
-                removeChild(mScroller);
-                delete mScroller;
-                mScroller = NULL;
-            }
-            mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
-            addChild(mScroller);
-            mScroller->addChild(mFolderRoot.get());
-            mFolderRoot.get()->setScrollContainer(mScroller);
-            mFolderRoot.get()->setFollowsAll();
-            mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox);
-
-            if (!mSelectionCallback.empty())
-            {
-                mFolderRoot.get()->setSelectCallback(mSelectionCallback);
-            }
-        }
-        mCommitCallbackRegistrar.popScope();
-        mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar);
-
-        if (is_favorites_set)
-        {
-            buildNewViews(folder_id);
-        }
-        mFolderRoot.get()->setShowEmptyMessage(!is_favorites_set);
-    }
-}
-
 /************************************************************************/
 /* Asset Pre-Filtered Inventory Panel related class                     */
 /************************************************************************/
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index e6d23eb649..a019fc2231 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -220,8 +220,6 @@ public:
 	void doCreate(const LLSD& userdata);
 	bool beginIMSession();
 	void fileUploadLocation(const LLSD& userdata);
-	void setFavoritesFolder(const LLSD& userdata);
-	void resetFavoritesFolder(const LLSD& userdata);
 	void purgeSelectedItems();
 	bool attachObject(const LLSD& userdata);
 	static void idle(void* user_data);
@@ -369,27 +367,6 @@ private:
     EViewsInitializationState	mViewsInitialized; // Whether views have been generated
 };
 
-
-class LLInventoryFavoriteItemsPanel : public LLInventoryPanel
-{
-public:
-    struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
-    {};
-
-    void initFromParams(const Params& p);
-    bool isSelectionRemovable() { return false; }
-    void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
-
-protected:
-    LLInventoryFavoriteItemsPanel(const Params& params);
-    ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); }
-    void updateFavoritesRootFolder();
-
-    boost::signals2::connection mFolderChangedSignal;
-    boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback;
-    friend class LLUICtrlFactory;
-};
-
 /************************************************************************/
 /* Asset Pre-Filtered Inventory Panel related class                     */
 /* Exchanges filter's flexibility for speed of generation and           */
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d9138091c6..e9c9c451a2 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -190,16 +190,6 @@ BOOL LLPanelMainInventory::postBuild()
 		worn_filter.markDefault();
 		mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2));
 	}
-
-	mFavoriteItemsPanel = getChild<LLInventoryFavoriteItemsPanel>("Favorite Items");
-	if (mFavoriteItemsPanel)
-	{
-		LLInventoryFilter& recent_filter = mFavoriteItemsPanel->getFilter();
-		recent_filter.setEmptyLookupMessage("InventoryFavoritItemsNotSelected");
-		recent_filter.markDefault();
-		mFavoriteItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mFavoriteItemsPanel, _1, _2));
-	}
-
 	mSearchTypeCombo  = getChild<LLComboBox>("search_type");
 	if(mSearchTypeCombo)
 	{
@@ -1449,7 +1439,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
 	}
 	if (command_name == "delete")
 	{
-		return getActivePanel()->isSelectionRemovable() && (getActivePanel() != mFavoriteItemsPanel);
+		return getActivePanel()->isSelectionRemovable();
 	}
 	if (command_name == "save_texture")
 	{
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 313e478bfe..dfb8db9d12 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -37,7 +37,6 @@
 class LLComboBox;
 class LLFolderViewItem;
 class LLInventoryPanel;
-class LLInventoryFavoriteItemsPanel;
 class LLSaveFolderState;
 class LLFilterEditor;
 class LLTabContainer;
@@ -138,7 +137,6 @@ private:
 	LLHandle<LLFloater>			mFinderHandle;
 	LLInventoryPanel*			mActivePanel;
 	LLInventoryPanel*			mWornItemsPanel;
-	LLInventoryFavoriteItemsPanel* mFavoriteItemsPanel;
 	bool						mResortActivePanel;
 	LLSaveFolderState*			mSavedFolderState;
 	std::string					mFilterText;
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index b5cde602bd..eda9739976 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -393,20 +393,6 @@
          parameter="model" />
       </menu_item_call>
     </menu>
-      <menu_item_call
-       label="Use as Favorites folder"
-       layout="topleft"
-       name="Set Favorites folder">
-        <menu_item_call.on_click
-         function="Inventory.SetFavoritesFolder"/>
-      </menu_item_call>
-      <menu_item_call
-       label="Reset Favorites folder"
-       layout="topleft"
-       name="Reset Favorites folder">
-          <menu_item_call.on_click
-           function="Inventory.ResetFavoritesFolder"/>
-      </menu_item_call>
     <menu
      label="Change Type"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index 7bd5c9b548..2ff58035ed 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -127,32 +127,20 @@
      name="Recent Items"
      show_item_link_overlays="true"
      width="290" />
-    <inventory_panel
-     name="Worn Items"
-     label="WORN"
-     show_empty_message="false"
-     follows="all"
-     layout="topleft"
-     width="290"
-     bg_opaque_color="DkGray2"
-     bg_alpha_color="DkGray2"
-     background_visible="true"
-     border="false"
-     bevel_style="none"
-     scroll.reserve_scroll_corner="false"/>
-    <favorites_inventory_panel
-     name="Favorite Items"
-     label="FAVORITES"
-     show_empty_message="false"
-     follows="all"
-     layout="topleft"
-     width="290"
-     bg_opaque_color="DkGray2"
-     bg_alpha_color="DkGray2"
-     background_visible="true"
-     border="false"
-     bevel_style="none"
-     scroll.reserve_scroll_corner="false"/>
+       <inventory_panel
+      name="Worn Items"
+      label="WORN"
+      show_empty_message="false"
+      follows="all"
+      layout="topleft"
+      width="290"
+      bg_opaque_color="DkGray2"
+      bg_alpha_color="DkGray2"
+      background_visible="true"
+      border="false"
+      bevel_style="none"
+      scroll.reserve_scroll_corner="false">
+  </inventory_panel>
   </tab_container>
   <layout_stack
    animate="false"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 4b022e7072..1f0d9c530f 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2296,8 +2296,7 @@ For AI Character: Get the closest navigable point to the point provided.
 
 	<!-- inventory -->
 	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
-	<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
-	<string name="InventoryFavoritItemsNotSelected">Click "Use as Favorites folder" on a folder of your choice. You can choose a different folder at any time. System folders and folders inside them cannot be used for Favorites.</string>
+	<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>	
 	<string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string>
 	<string name="FavoritesNoMatchingItems">To add a place to your favorites bar, click the star to the right of the location name.</string>
 	<string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string>
-- 
cgit v1.2.3


From 297b81b03ad1e01339735e612dbf17f131019403 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 21 Apr 2021 15:39:01 +0300
Subject: SL-15028 Update GuidebookURL setting

---
 indra/newview/app_settings/settings.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 25627e61ae..943062c127 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4734,7 +4734,7 @@
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>https://guidebooks.secondlife.io/welcome</string>
+      <string>http://guidebooks.secondlife.io/welcome/index.html</string>
     </map>
     <key>HighResSnapshot</key>
     <map>
-- 
cgit v1.2.3


From 0ed270a0569e205f837f84773f5e72ab3b46d01b Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 21 Apr 2021 01:37:28 +0300
Subject: SL-14842 Landmarks created by '+' menu always starting in favorites

---
 indra/newview/llpanellandmarks.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 4b73412e60..769b060d93 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -499,6 +499,12 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
             {
                 args["dest_folder"] = view_model->getUUID();
             }
+            if ("add_landmark_root" == command_name
+                && mCurrentSelectedList == mLandmarksInventoryPanel)
+            {
+                args["dest_folder"] = mLandmarksInventoryPanel->getRootFolderID();
+            }
+            // else will end up in favorites
 			LLFloaterReg::showInstance("add_landmark", args);
 		}
 	} 
-- 
cgit v1.2.3


From a391cf9cbc0a53463db6d628c86a3477e7d8a8b8 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 22 Apr 2021 20:10:10 +0300
Subject: SL-14842 Clear history should be it's own button

---
 indra/newview/llpanelplaces.cpp                               |  8 ++++++--
 indra/newview/llpanelteleporthistory.cpp                      | 10 ++++++----
 indra/newview/llpanelteleporthistory.h                        |  2 +-
 .../skins/default/xui/en/menu_teleport_history_item.xml       | 11 -----------
 indra/newview/skins/default/xui/en/notifications.xml          |  2 +-
 5 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 90a70adea7..ac7bc0fc32 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -656,7 +656,9 @@ void LLPanelPlaces::onTabSelected()
     // Hide menus
     bool supports_create = mActivePanel->getCreateMenu() != NULL;
     childSetVisible("add_btn_panel", supports_create);
-    childSetVisible("trash_btn_panel", supports_create);
+
+    // favorites and inventory can remove items, history can clear history
+    childSetVisible("trash_btn_panel", TRUE);
 }
 
 void LLPanelPlaces::onTeleportButtonClicked()
@@ -1224,7 +1226,9 @@ void LLPanelPlaces::createTabs()
         // Hide menus
         bool supports_create = mActivePanel->getCreateMenu() != NULL;
         childSetVisible("add_btn_panel", supports_create);
-        childSetVisible("trash_btn_panel", supports_create);
+
+        // favorites and inventory can remove items, history can clear history
+        childSetVisible("trash_btn_panel", TRUE);
     }
 
 	mTabsCreated = true;
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 48614e1e47..7a3d3525ac 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -534,6 +534,12 @@ void LLTeleportHistoryPanel::onTeleport()
 	confirmTeleport(itemp->getIndex());
 }
 
+// virtual
+void LLTeleportHistoryPanel::onRemoveSelected()
+{
+    LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
+}
+
 /*
 // virtual
 void LLTeleportHistoryPanel::onCopySLURL()
@@ -1032,10 +1038,6 @@ void LLTeleportHistoryPanel::onGearMenuAction(const LLSD& userdata)
             mLastSelectedFlatlList->resetSelection();
         }
     }
-    else if ("clear_history" == command_name)
-    {
-        LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
-    }
 
     S32 index = -1;
     if (mLastSelectedFlatlList)
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index f76dc139bd..058fee0170 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -54,7 +54,7 @@ public:
     void onShowProfile() override;
     void onTeleport() override;
     ///*virtual*/ void onCopySLURL();
-    void onRemoveSelected() override {};
+    void onRemoveSelected() override;
     void updateVerbs() override;
     bool isSingleItemSelected() override;
 
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index f60f02f040..153e5a70a9 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -49,15 +49,4 @@
          function="TeleportHistory.GearMenu.Enable"
          parameter="copy_slurl" />
     </menu_item_call>
-    <menu_item_separator layout="topleft" />
-    <menu_item_call
-     label="Clear Teleport History"
-     name="Clear Teleport History">
-      <menu_item_call.on_click
-       function="TeleportHistory.GearMenu.Action"
-       parameter="clear_history" />
-      <on_enable
-       function="TeleportHistory.GearMenu.Enable"
-       parameter="clear_history" />
-    </menu_item_call>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 87a702faab..0cf0376ef8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -8710,7 +8710,7 @@ This upload will cost L$[PRICE], do you wish to continue with the upload?
    icon="alertmodal.tga"
    name="ConfirmClearTeleportHistory"
    type="alertmodal">
-Are you sure you want to delete your teleport history?
+This will delete the entire list of places you have visited, and cannot be undone. Continue?
   <tag>confirm</tag>
     <usetemplate
      name="okcancelbuttons"
-- 
cgit v1.2.3


From 70bc98c4b0484a69ebb42717755b623bf9895e9f Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 23 Apr 2021 14:56:01 +0300
Subject: SL-15144 FIXED The "Remove" button is enabled with no selection

---
 indra/newview/llpanellandmarks.cpp       | 6 ++++++
 indra/newview/llpanelplaces.cpp          | 3 +++
 indra/newview/llpanelplacestab.cpp       | 1 +
 indra/newview/llpanelplacestab.h         | 3 +++
 indra/newview/llpanelteleporthistory.cpp | 4 ++--
 5 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 769b060d93..e698a61fef 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -285,6 +285,10 @@ LLToggleableMenu* LLLandmarksPanel::getCreateMenu()
 
 void LLLandmarksPanel::updateVerbs()
 {
+	if (sRemoveBtn)
+	{
+		sRemoveBtn->setEnabled(isActionEnabled("delete") && (isFolderSelected() || isLandmarkSelected()));
+	}
 }
 
 void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
@@ -425,6 +429,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list
 {
 	inventory_list->getFilter().setEmptyLookupMessage("PlacesNoMatchingItems");
 	inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
+	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::updateVerbs, this));
 
 	inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
 	bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
@@ -1032,6 +1037,7 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
 		break;
 	}
 
+	updateVerbs();
 	return true;
 }
 
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index ac7bc0fc32..1713370692 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -1229,6 +1229,9 @@ void LLPanelPlaces::createTabs()
 
         // favorites and inventory can remove items, history can clear history
         childSetVisible("trash_btn_panel", TRUE);
+
+        mActivePanel->setRemoveBtn(mRemoveSelectedBtn);
+		mActivePanel->updateVerbs();
     }
 
 	mTabsCreated = true;
diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp
index 9601ac54a4..748a917147 100644
--- a/indra/newview/llpanelplacestab.cpp
+++ b/indra/newview/llpanelplacestab.cpp
@@ -38,6 +38,7 @@
 #include "llworldmap.h"
 
 std::string LLPanelPlacesTab::sFilterSubString = LLStringUtil::null;
+LLButton* LLPanelPlacesTab::sRemoveBtn = NULL;
 
 bool LLPanelPlacesTab::isTabVisible()
 {
diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h
index 886f4ce9c0..aab1c130c1 100644
--- a/indra/newview/llpanelplacestab.h
+++ b/indra/newview/llpanelplacestab.h
@@ -67,9 +67,12 @@ public:
 	const std::string& getFilterSubString() { return sFilterSubString; }
 	void setFilterSubString(const std::string& string) { sFilterSubString = string; }
 
+	void setRemoveBtn(LLButton* trash_btn) { sRemoveBtn = trash_btn; }
+
 protected:
 	// Search string for filtering landmarks and teleport history locations
 	static std::string		sFilterSubString;
+	static LLButton*		sRemoveBtn;
 };
 
 #endif //LL_LLPANELPLACESTAB_H
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 7a3d3525ac..b938b30479 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -570,9 +570,9 @@ void LLTeleportHistoryPanel::updateVerbs()
 	if (!isTabVisible())
 		return;
 
-	if (!mLastSelectedFlatlList)
+	if (sRemoveBtn)
 	{
-		return;
+		sRemoveBtn->setEnabled(true);
 	}
 }
 
-- 
cgit v1.2.3


From db8a55c2e606b77cc4bf758dd7b4228e37269eab Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 23 Apr 2021 18:38:07 +0300
Subject: SL-14842 Tooltip for clear history

---
 indra/newview/llpanelplaces.cpp                     | 18 ++++++++++++++++++
 indra/newview/skins/default/xui/en/panel_places.xml |  7 ++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 1713370692..9c67ec40fe 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -659,6 +659,15 @@ void LLPanelPlaces::onTabSelected()
 
     // favorites and inventory can remove items, history can clear history
     childSetVisible("trash_btn_panel", TRUE);
+
+    if (supports_create)
+    {
+        mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_items"));
+    }
+    else
+    {
+        mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_history"));
+    }
 }
 
 void LLPanelPlaces::onTeleportButtonClicked()
@@ -1230,6 +1239,15 @@ void LLPanelPlaces::createTabs()
         // favorites and inventory can remove items, history can clear history
         childSetVisible("trash_btn_panel", TRUE);
 
+        if (supports_create)
+        {
+            mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_items"));
+        }
+        else
+        {
+            mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_history"));
+        }
+
         mActivePanel->setRemoveBtn(mRemoveSelectedBtn);
 		mActivePanel->updateVerbs();
     }
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index dd4cf7ab4e..58be4d4c5e 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -20,6 +20,12 @@ background_visible="true"
   <string
    name="favorites_tab_title"
    value="FAVORITES" />
+  <string
+   name="tooltip_trash_items"
+   value="Remove selected landmark or folder" />
+  <string
+   name="tooltip_trash_history"
+   value="Delete list of visited places" />
   <layout_stack
     animate="false"
     border_size="0"
@@ -146,7 +152,6 @@ background_visible="true"
           left="0"
           layout="topleft"
           name="trash_btn"
-          tool_tip="Remove selected landmark or folder"
           top="0"
           width="31"/>
       </layout_panel>
-- 
cgit v1.2.3


From a91e22731998230f9b41d6d86328b66bf7a122ae Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 28 Apr 2021 13:14:51 +0300
Subject: SL-15174 set Starting Guidebook location on-screen

---
 indra/llui/llfloater.cpp                              | 18 +++++++++++++++++-
 indra/llui/llfloater.h                                |  6 ++++++
 indra/newview/skins/default/xui/en/floater_how_to.xml |  2 ++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index c03b024dd5..3680e20f15 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -199,7 +199,9 @@ LLFloater::Params::Params()
 	help_pressed_image("help_pressed_image"),
 	open_callback("open_callback"),
 	close_callback("close_callback"),
-	follows("follows")
+	follows("follows"),
+	rel_x("rel_x", 0),
+	rel_y("rel_y", 0)
 {
 	changeDefault(visible, false);
 }
@@ -268,6 +270,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
 	mHasBeenDraggedWhileMinimized(FALSE),
 	mPreviousMinimizedBottom(0),
 	mPreviousMinimizedLeft(0),
+	mDefaultRelativeX(p.rel_x),
+	mDefaultRelativeY(p.rel_y),
 	mMinimizeSignal(NULL)
 //	mNotificationContext(NULL)
 {
@@ -935,6 +939,15 @@ bool LLFloater::applyRectControl()
 
 			saved_rect = true;
 		}
+		else if ((mDefaultRelativeX != 0) && (mDefaultRelativeY != 0))
+		{
+			mPosition.mX = mDefaultRelativeX;
+			mPosition.mY = mDefaultRelativeY;
+			mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
+			applyRelativePosition();
+
+			saved_rect = true;
+		}
 
 		// remember updated position
 		if (rect_specified)
@@ -3200,6 +3213,9 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
 	mSingleInstance = p.single_instance;
 	mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance;
 
+	mDefaultRelativeX = p.rel_x;
+	mDefaultRelativeY = p.rel_y;
+
 	mPositioning = p.positioning;
 
 	mSaveRect = p.save_rect;
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index f8c04e8a2f..2672d600c6 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -172,6 +172,9 @@ public:
 		Optional<S32>			header_height,
 								legacy_header_height; // HACK see initFromXML()
 
+		Optional<F32>			rel_x,
+								rel_y;
+
 		// Images for top-right controls
 		Optional<LLUIImage*>	close_image,
 								restore_image,
@@ -521,6 +524,9 @@ private:
 	BOOL			mHasBeenDraggedWhileMinimized;
 	S32				mPreviousMinimizedBottom;
 	S32				mPreviousMinimizedLeft;
+
+	F32				mDefaultRelativeX;
+	F32				mDefaultRelativeY;
 };
 
 
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index b4dd2e252f..acfa6a5152 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -12,4 +12,6 @@
   save_rect="true"
   title="WELCOME ISLAND GUIDEBOOK"
   width="310"
+  rel_x="-0.469309"
+  rel_y="-0.011166"
   filename="floater_web_content.xml"/>
\ No newline at end of file
-- 
cgit v1.2.3


From 9874d65e54c21db38efe65dfbb9c52f7c9971488 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Sat, 1 May 2021 02:17:35 +0300
Subject: Follow-up merge conflict fix

---
 indra/newview/llfloaterfixedenvironment.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 9978c837b2..4f2c36f45b 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -180,7 +180,7 @@ void LLFloaterFixedEnvironment::setEditSettingsAndUpdate(const LLSettingsBase::p
     updateEditEnvironment();
     syncronizeTabs();
     refresh();
-    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
 }
 
 void LLFloaterFixedEnvironment::syncronizeTabs()
-- 
cgit v1.2.3


From cfb6ca569b2c834520ce50564e857dfc06831675 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 6 May 2021 00:46:14 +0300
Subject: SL-15168 Viewer side functionality for guidebook window opening

---
 indra/newview/CMakeLists.txt                  |   2 +
 indra/newview/llappviewer.cpp                 |   2 +
 indra/newview/llenvironment.cpp               |   2 +-
 indra/newview/llfloaterhowto.cpp              |   7 +-
 indra/newview/llstartup.cpp                   |   2 -
 indra/newview/llurlfloaterdispatchhandler.cpp | 107 ++++++++++++++++++++++++++
 indra/newview/llurlfloaterdispatchhandler.h   |  46 +++++++++++
 7 files changed, 163 insertions(+), 5 deletions(-)
 create mode 100644 indra/newview/llurlfloaterdispatchhandler.cpp
 create mode 100644 indra/newview/llurlfloaterdispatchhandler.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 82dcd402be..e8e5b83957 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -638,6 +638,7 @@ set(viewer_SOURCE_FILES
     llurl.cpp
     llurldispatcher.cpp
     llurldispatcherlistener.cpp
+    llurlfloaterdispatchhandler.cpp
     llurlhistory.cpp
     llurllineeditorctrl.cpp
     llurlwhitelist.cpp
@@ -1269,6 +1270,7 @@ set(viewer_HEADER_FILES
     llurl.h
     llurldispatcher.h
     llurldispatcherlistener.h
+    llurlfloaterdispatchhandler.h
     llurlhistory.h
     llurllineeditorctrl.h
     llurlwhitelist.h
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0b2cdff36c..9d03edc060 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -59,6 +59,7 @@
 #include "llslurl.h"
 #include "llstartup.h"
 #include "llfocusmgr.h"
+#include "llurlfloaterdispatchhandler.h"
 #include "llviewerjoystick.h"
 #include "llallocator.h"
 #include "llcalc.h"
@@ -917,6 +918,7 @@ bool LLAppViewer::init()
 
 	// Load translations for tooltips
 	LLFloater::initClass();
+	LLUrlFloaterDispatchHandler::registerInDispatcher();
 
 	/////////////////////////////////////////////////
 
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 90d22c57b0..190051d763 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -327,7 +327,7 @@ namespace
                 std::istringstream llsdData(llsdRaw);
                 if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
                 {
-                    LL_WARNS() << "LLExperienceLogDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
+                    LL_WARNS() << "LLEnvironmentPushDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
                 }
             }
 
diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index 665955c946..9db733db25 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -52,8 +52,11 @@ BOOL LLFloaterHowTo::postBuild()
 void LLFloaterHowTo::onOpen(const LLSD& key)
 {
     LLFloaterWebContent::Params p(key);
-    std::string url = gSavedSettings.getString("GuidebookURL");
-    p.url = LLWeb::expandURLSubstitutions(url, LLSD());
+    if (!p.url.isProvided() || p.url.getValue().empty())
+    {
+        std::string url = gSavedSettings.getString("GuidebookURL");
+        p.url = LLWeb::expandURLSubstitutions(url, LLSD());
+    }
     p.show_chrome = false;
 
     LLFloaterWebContent::onOpen(p);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 0ea5de8d67..55048b03be 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1905,8 +1905,6 @@ bool idle_startup()
 			// Set the show start location to true, now that the user has logged
 			// on with this install.
 			gSavedSettings.setBOOL("ShowStartLocation", TRUE);
-
-            LLFloaterReg::toggleInstanceOrBringToFront("how_to");
 		}
 
 		display_startup();
diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
new file mode 100644
index 0000000000..7f9929041d
--- /dev/null
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -0,0 +1,107 @@
+/** 
+ * @file llurlfloaterdispatchhandler.cpp
+ * @brief Handles URLFloater generic message from server
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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 "llurlfloaterdispatchhandler.h"
+
+#include "llfloaterreg.h"
+#include "llfloaterwebcontent.h"
+#include "llsdserialize.h"
+#include "llviewercontrol.h"
+#include "llviewergenericmessage.h"
+#include "llweb.h"
+
+// values specified by server side's dispatcher
+const std::string MESSAGE_URL_FLOATER("URLFloater");
+const std::string KEY_ACTION("OpenURL");
+const std::string KEY_PARAMS("floater_params");
+const std::string KEY_FLOATER("floater_title");
+const std::string KEY_URL("floater_url");
+
+LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler;
+
+LLUrlFloaterDispatchHandler::LLUrlFloaterDispatchHandler()
+{
+}
+
+LLUrlFloaterDispatchHandler::~LLUrlFloaterDispatchHandler()
+{
+}
+
+void LLUrlFloaterDispatchHandler::registerInDispatcher()
+{
+    if (!gGenericDispatcher.isHandlerPresent(MESSAGE_URL_FLOATER))
+    {
+        gGenericDispatcher.addHandler(MESSAGE_URL_FLOATER, &sUrlDispatchhandler);
+    }
+}
+
+//virtual
+bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings)
+{
+    // invoice - transaction id
+
+    LLSD message;
+    sparam_t::const_iterator it = strings.begin();
+
+    if (it != strings.end())
+    {
+        const std::string& llsdRaw = *it++;
+        std::istringstream llsdData(llsdRaw);
+        if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
+        {
+            LL_WARNS("URLFloater") << "Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
+        }
+    }
+
+    std::string floater = message[KEY_FLOATER];
+    LLSD &command_params = message[KEY_PARAMS];
+
+    LLFloaterWebContent::Params params;
+    params.url = message[KEY_URL];
+
+    if (floater == "guidebook" || floater == "how_to")
+    {
+        if (command_params.isMap()) // by default is undefines
+        {
+            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false;
+        }
+        LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
+    }
+    else if (!params.url.getValue().empty())
+    {
+        if (command_params.isMap()) // by default is undefines
+        {
+            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false;
+            params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"] : true;
+            params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"] : true;
+        }
+        LLFloaterReg::showInstance("web_content", params);
+    }
+
+    return true;
+}
diff --git a/indra/newview/llurlfloaterdispatchhandler.h b/indra/newview/llurlfloaterdispatchhandler.h
new file mode 100644
index 0000000000..469f76b007
--- /dev/null
+++ b/indra/newview/llurlfloaterdispatchhandler.h
@@ -0,0 +1,46 @@
+/** 
+ * @file llurlfloaterdispatchhandler.h
+ * @brief Handles URLFloater generic message from server
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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_LLURLFLOATERDISPATCHHANDLER_H
+#define LL_LLURLFLOATERDISPATCHHANDLER_H
+
+#include "lldispatcher.h"
+
+class LLUrlFloaterDispatchHandler : public LLDispatchHandler
+{
+public:
+    LLUrlFloaterDispatchHandler();
+    virtual ~LLUrlFloaterDispatchHandler();
+    virtual bool operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override;
+
+    static void registerInDispatcher();
+
+private:
+    static LLUrlFloaterDispatchHandler sUrlDispatchhandler;
+};
+
+#endif  // LL_LLURLFLOATERDISPATCHHANDLER_H
+
-- 
cgit v1.2.3


From cb42bc2823931b84ce079423a471a332dc332b0c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 6 May 2021 21:57:46 +0300
Subject: SL-15168 Viewer side functionality for guidebook window opening #2

---
 indra/llui/llfloaterreg.cpp                   |  6 ++
 indra/llui/llfloaterreg.h                     |  1 +
 indra/newview/llfloaterhowto.cpp              | 17 +++---
 indra/newview/llfloaterhowto.h                |  3 +
 indra/newview/llurlfloaterdispatchhandler.cpp | 80 ++++++++++++++++++++++++---
 indra/newview/llurlfloaterdispatchhandler.h   |  3 +
 6 files changed, 96 insertions(+), 14 deletions(-)

diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 7c0933f554..36a0cb0fd0 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -57,6 +57,12 @@ void LLFloaterReg::add(const std::string& name, const std::string& filename, con
 	sGroupMap[groupname] = groupname; // for referencing directly by group name
 }
 
+//static
+bool LLFloaterReg::isRegistered(const std::string& name)
+{
+    return sBuildMap.find(name) != sBuildMap.end();
+}
+
 //static
 LLFloater* LLFloaterReg::getLastFloaterInGroup(const std::string& name)
 {
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index e3b17dcb4f..a457a15673 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -85,6 +85,7 @@ public:
 	
 	static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func,
 					const std::string& groupname = LLStringUtil::null);
+	static bool isRegistered(const std::string& name);
 
 	// Helpers
 	static LLFloater* getLastFloaterInGroup(const std::string& name);
diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index 9db733db25..ef40060807 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -61,13 +61,16 @@ void LLFloaterHowTo::onOpen(const LLSD& key)
 
     LLFloaterWebContent::onOpen(p);
 
-    // Elements from LLFloaterWebContent did not pick up restored size (save_rect) of LLFloaterHowTo
-    // set the stack size and position (alternative to preferred_media_size)
-    LLLayoutStack *stack = getChild<LLLayoutStack>("stack1");
-    LLRect stack_rect = stack->getRect();
-    stack->reshape(STACK_WIDTH, STACK_HEIGHT);
-    stack->setOrigin(stack_rect.mLeft, stack_rect.mTop - STACK_HEIGHT);
-    stack->updateLayout();
+    if (p.preferred_media_size().isEmpty())
+    {
+        // Elements from LLFloaterWebContent did not pick up restored size (save_rect) of LLFloaterHowTo
+        // set the stack size and position (alternative to preferred_media_size)
+        LLLayoutStack *stack = getChild<LLLayoutStack>("stack1");
+        LLRect stack_rect = stack->getRect();
+        stack->reshape(STACK_WIDTH, STACK_HEIGHT);
+        stack->setOrigin(stack_rect.mLeft, stack_rect.mTop - STACK_HEIGHT);
+        stack->updateLayout();
+    }
 }
 
 LLFloaterHowTo* LLFloaterHowTo::getInstance()
diff --git a/indra/newview/llfloaterhowto.h b/indra/newview/llfloaterhowto.h
index e08d102e2a..15fc43335a 100644
--- a/indra/newview/llfloaterhowto.h
+++ b/indra/newview/llfloaterhowto.h
@@ -36,6 +36,9 @@ class LLFloaterHowTo :
     public LLFloaterWebContent
 {
 public:
+    LOG_CLASS(LLFloaterHowTo);
+
+    typedef LLFloaterWebContent::Params Params;
 
     LLFloaterHowTo(const Params& key);
 
diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 7f9929041d..1a5da79a74 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -29,6 +29,7 @@
 #include "llurlfloaterdispatchhandler.h"
 
 #include "llfloaterreg.h"
+#include "llfloaterhowto.h"
 #include "llfloaterwebcontent.h"
 #include "llsdserialize.h"
 #include "llviewercontrol.h"
@@ -36,11 +37,14 @@
 #include "llweb.h"
 
 // values specified by server side's dispatcher
+// for llopenfloater
 const std::string MESSAGE_URL_FLOATER("URLFloater");
-const std::string KEY_ACTION("OpenURL");
-const std::string KEY_PARAMS("floater_params");
+const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL"
+const std::string VALUE_OPEN_URL("OpenURL");
+const std::string KEY_DATA("action_data");
 const std::string KEY_FLOATER("floater_title");
 const std::string KEY_URL("floater_url");
+const std::string KEY_PARAMS("floater_params");
 
 LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler;
 
@@ -75,26 +79,75 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
         {
             LL_WARNS("URLFloater") << "Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
+            return false;
+        }
+    }
+
+    std::string floater;
+    LLSD command_params;
+    std::string url;
+
+    if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL)
+    {
+        LLSD &action_data = message[KEY_DATA];
+        if (action_data.isMap())
+        {
+            floater = action_data[KEY_FLOATER];
+            command_params = action_data[KEY_PARAMS];
+            url = action_data[KEY_URL];
         }
     }
+    else if (message.has(KEY_FLOATER))
+    {
+        floater = message[KEY_FLOATER];
+        command_params = message[KEY_PARAMS];
+        url = message[KEY_URL];
+    }
+    else
+    {
+        LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with unexpected data format: " << message << LL_ENDL;
+        return false;
+    }
 
-    std::string floater = message[KEY_FLOATER];
-    LLSD &command_params = message[KEY_PARAMS];
+    if (url.find("://") == std::string::npos)
+    {
+        // try unescaping
+        url = LLURI::unescape(url);
+    }
 
     LLFloaterWebContent::Params params;
-    params.url = message[KEY_URL];
+    params.url = url;
 
     if (floater == "guidebook" || floater == "how_to")
     {
         if (command_params.isMap()) // by default is undefines
         {
             params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false;
+
+            // Script's side argument list can't include other lists, neither
+            // there is a LLRect type, so expect just width and height
+            if (command_params.has("width") && command_params.has("height"))
+            {
+                LLRect rect(0, command_params["height"].asInteger(), command_params["width"].asInteger(), 0);
+                params.preferred_media_size.setValue(rect);
+            }
         }
+
+        // Some locations will have customized guidebook, which this function easists for
+        // only one instance of guidebook can exist at a time, so if this command arrives,
+        // we need to close previous guidebook then reopen it.
+
+        LLFloater* instance = LLFloaterReg::findInstance("how_to");
+        if (instance)
+        {
+            instance->closeHostedFloater();
+        }
+
         LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
     }
-    else if (!params.url.getValue().empty())
+    else if (floater == "web_content")
     {
-        if (command_params.isMap()) // by default is undefines
+        if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
         {
             params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false;
             params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"] : true;
@@ -102,6 +155,19 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
         LLFloaterReg::showInstance("web_content", params);
     }
+    else
+    {
+        if (LLFloaterReg::isRegistered(floater))
+        {
+            // A valid floater
+            LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
+        }
+        else
+        {
+            // A valid message, but no such flaoter
+            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL;
+        }
+    }
 
     return true;
 }
diff --git a/indra/newview/llurlfloaterdispatchhandler.h b/indra/newview/llurlfloaterdispatchhandler.h
index 469f76b007..1dff52c66f 100644
--- a/indra/newview/llurlfloaterdispatchhandler.h
+++ b/indra/newview/llurlfloaterdispatchhandler.h
@@ -32,8 +32,11 @@
 class LLUrlFloaterDispatchHandler : public LLDispatchHandler
 {
 public:
+    LOG_CLASS(LLUrlFloaterDispatchHandler);
+
     LLUrlFloaterDispatchHandler();
     virtual ~LLUrlFloaterDispatchHandler();
+
     virtual bool operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override;
 
     static void registerInDispatcher();
-- 
cgit v1.2.3


From aac1fc4991338ef7c214e9b4e0dbc5d5bb554771 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 10 May 2021 21:15:12 +0300
Subject: SL-15168 Mac build fix

---
 indra/newview/llurlfloaterdispatchhandler.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 1a5da79a74..65fbfe9fa3 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -92,16 +92,16 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         LLSD &action_data = message[KEY_DATA];
         if (action_data.isMap())
         {
-            floater = action_data[KEY_FLOATER];
+            floater = action_data[KEY_FLOATER].asString();
             command_params = action_data[KEY_PARAMS];
-            url = action_data[KEY_URL];
+            url = action_data[KEY_URL].asString();
         }
     }
     else if (message.has(KEY_FLOATER))
     {
-        floater = message[KEY_FLOATER];
+        floater = message[KEY_FLOATER].asString();
         command_params = message[KEY_PARAMS];
-        url = message[KEY_URL];
+        url = message[KEY_URL].asString();
     }
     else
     {
@@ -122,7 +122,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
     {
         if (command_params.isMap()) // by default is undefines
         {
-            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false;
+            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false;
 
             // Script's side argument list can't include other lists, neither
             // there is a LLRect type, so expect just width and height
@@ -149,9 +149,9 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
     {
         if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
         {
-            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false;
-            params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"] : true;
-            params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"] : true;
+            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false;
+            params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"].asBoolean() : true;
+            params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"].asBoolean() : true;
         }
         LLFloaterReg::showInstance("web_content", params);
     }
-- 
cgit v1.2.3


From 48394bdc23015c8289ef97fa1af99ba3e024ef36 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 00:10:38 +0300
Subject: SL-15168 Reorginized contants

---
 indra/newview/llurlfloaterdispatchhandler.cpp | 40 +++++++++++++++++++++------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 65fbfe9fa3..40afafa4c0 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -46,6 +46,24 @@ const std::string KEY_FLOATER("floater_title");
 const std::string KEY_URL("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
+// Supported floaters
+const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to
+const std::string FLOATER_HOW_TO("how_to");
+const std::string FLOATER_WEB_CONTENT("web_content");
+
+// Web content universal argument
+const std::string KEY_TRUSTED_CONTENT("trusted_content");
+
+// Guidebook specific arguments
+const std::string KEY_WIDTH("width");
+const std::string KEY_HEGHT("height");
+const std::string KEY_CAN_CLOSE("can_close");
+
+// web_content specific arguments
+const std::string KEY_SHOW_PAGE_TITLE("show_page_title");
+const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed
+
+
 LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler;
 
 LLUrlFloaterDispatchHandler::LLUrlFloaterDispatchHandler()
@@ -118,17 +136,17 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
     LLFloaterWebContent::Params params;
     params.url = url;
 
-    if (floater == "guidebook" || floater == "how_to")
+    if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO)
     {
         if (command_params.isMap()) // by default is undefines
         {
-            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false;
+            params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
 
             // Script's side argument list can't include other lists, neither
             // there is a LLRect type, so expect just width and height
-            if (command_params.has("width") && command_params.has("height"))
+            if (command_params.has(KEY_WIDTH) && command_params.has(KEY_HEGHT))
             {
-                LLRect rect(0, command_params["height"].asInteger(), command_params["width"].asInteger(), 0);
+                LLRect rect(0, command_params[KEY_HEGHT].asInteger(), command_params[KEY_WIDTH].asInteger(), 0);
                 params.preferred_media_size.setValue(rect);
             }
         }
@@ -144,14 +162,20 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
 
         LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
+        
+        if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE))
+        {
+            LLFloater* instance = LLFloaterReg::findInstance("how_to");
+            instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
+        }
     }
-    else if (floater == "web_content")
+    else if (floater == FLOATER_WEB_CONTENT)
     {
         if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
         {
-            params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false;
-            params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"].asBoolean() : true;
-            params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"].asBoolean() : true;
+            params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
+            params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true;
+            params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true;
         }
         LLFloaterReg::showInstance("web_content", params);
     }
-- 
cgit v1.2.3


From 9dee16185a0b33177c6b7b3c60733682cebee66d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 01:23:28 +0300
Subject: SL-15168 Changed format

instead of an url function takes an uri
---
 indra/newview/llurlfloaterdispatchhandler.cpp | 97 ++++++++++++++++++---------
 1 file changed, 67 insertions(+), 30 deletions(-)

diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 40afafa4c0..f03caf43b8 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -36,25 +36,30 @@
 #include "llviewergenericmessage.h"
 #include "llweb.h"
 
+#include <boost/regex.hpp>
+
+// Example:
+// llOpenFloater("My Help Title", "secondlife://guidebook", []);
+
 // values specified by server side's dispatcher
 // for llopenfloater
 const std::string MESSAGE_URL_FLOATER("URLFloater");
 const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL"
 const std::string VALUE_OPEN_URL("OpenURL");
 const std::string KEY_DATA("action_data");
-const std::string KEY_FLOATER("floater_title");
-const std::string KEY_URL("floater_url");
+const std::string KEY_FLOATER_TITLE("floater_title");
+const std::string KEY_URI("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
-// Supported floaters
-const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to
-const std::string FLOATER_HOW_TO("how_to");
-const std::string FLOATER_WEB_CONTENT("web_content");
+// Supported floaters, for now it's exact matching, later it might get extended
+const std::string FLOATER_GUIDEBOOK("secondlife://guidebook"); // translates to "how_to"
+const std::string FLOATER_WEB_CONTENT("secondlife://browser"); // translates to "web_content"
 
-// Web content universal argument
+// Web content universal arguments
 const std::string KEY_TRUSTED_CONTENT("trusted_content");
+const std::string KEY_URL("url");
 
-// Guidebook specific arguments
+// Guidebook ("how_to") specific arguments
 const std::string KEY_WIDTH("width");
 const std::string KEY_HEGHT("height");
 const std::string KEY_CAN_CLOSE("can_close");
@@ -63,6 +68,10 @@ const std::string KEY_CAN_CLOSE("can_close");
 const std::string KEY_SHOW_PAGE_TITLE("show_page_title");
 const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed
 
+// expected format secondlife:///floater_alias
+// intended to be extended to: secondlife:///floater_alias/instance_id
+const boost::regex expression("secondlife:///[^ \n]{1,256}");
+
 
 LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler;
 
@@ -101,25 +110,25 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
     }
 
-    std::string floater;
+    std::string floater_title;
     LLSD command_params;
-    std::string url;
+    std::string floater_uri;
 
     if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL)
     {
         LLSD &action_data = message[KEY_DATA];
         if (action_data.isMap())
         {
-            floater = action_data[KEY_FLOATER].asString();
+            floater_title = action_data[KEY_FLOATER_TITLE].asString();
             command_params = action_data[KEY_PARAMS];
-            url = action_data[KEY_URL].asString();
+            floater_uri = action_data[KEY_URI].asString();
         }
     }
-    else if (message.has(KEY_FLOATER))
+    else if (message.has(KEY_FLOATER_TITLE))
     {
-        floater = message[KEY_FLOATER].asString();
+        floater_title = message[KEY_FLOATER_TITLE].asString();
         command_params = message[KEY_PARAMS];
-        url = message[KEY_URL].asString();
+        floater_uri = message[KEY_URI].asString();
     }
     else
     {
@@ -127,16 +136,33 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         return false;
     }
 
-    if (url.find("://") == std::string::npos)
+    if (floater_uri.find(":///") == std::string::npos)
     {
         // try unescaping
-        url = LLURI::unescape(url);
+        floater_uri = LLURI::unescape(floater_uri);
+    }
+
+    boost::cmatch what;
+    if (!boost::regex_match(floater_uri.c_str(), what, expression))
+    {
+        LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with invalid uri: " << floater_uri << LL_ENDL;
+        return false;
     }
 
     LLFloaterWebContent::Params params;
-    params.url = url;
+    if (command_params.isMap())
+    {
+        if (command_params.has(KEY_TRUSTED_CONTENT))
+        {
+            params.trusted_content = command_params[KEY_TRUSTED_CONTENT].asBoolean();
+        }
+        if (command_params.has(KEY_URL))
+        {
+            params.url = command_params[KEY_URL].asString();
+        }
+    }
 
-    if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO)
+    if (floater_uri == FLOATER_GUIDEBOOK)
     {
         if (command_params.isMap()) // by default is undefines
         {
@@ -162,34 +188,45 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
 
         LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
-        
+
+        instance = LLFloaterReg::findInstance("how_to");
+        instance->setTitle(floater_title);
         if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE))
         {
-            LLFloater* instance = LLFloaterReg::findInstance("how_to");
             instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
         }
     }
-    else if (floater == FLOATER_WEB_CONTENT)
+    else if (floater_uri == FLOATER_WEB_CONTENT)
     {
-        if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
+        if (command_params.has(KEY_URL))
         {
-            params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
-            params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true;
-            params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true;
+            if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
+            {
+                params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
+                params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true;
+                params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true;
+            }
+            LLFloater* instance = LLFloaterReg::showInstance("web_content", params);
+            instance->setTitle(floater_title);
         }
-        LLFloaterReg::showInstance("web_content", params);
     }
     else
     {
-        if (LLFloaterReg::isRegistered(floater))
+        LLSD path_array = LLURI(floater_uri).pathArray();
+        S32 path_parts = path_array.size();
+        if (path_parts == 0)
+        {
+            LL_INFOS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL;
+        }
+        else if (LLFloaterReg::isRegistered(path_array[0]))
         {
             // A valid floater
-            LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
+            LL_INFOS("URLFloater") << "Floater " << path_array[0] << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
         }
         else
         {
             // A valid message, but no such flaoter
-            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL;
+            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater_uri << LL_ENDL;
         }
     }
 
-- 
cgit v1.2.3


From e886a5e34320c6448293dc05ac89a41b2b4a7f69 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 01:48:21 +0300
Subject: SL-15168 Reset title of guidebook when opening

---
 indra/newview/llfloaterhowto.cpp                      | 6 ++++++
 indra/newview/skins/default/xui/en/floater_how_to.xml | 9 +++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index ef40060807..6e913b08ea 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -51,6 +51,12 @@ BOOL LLFloaterHowTo::postBuild()
 
 void LLFloaterHowTo::onOpen(const LLSD& key)
 {
+    // LLFloaterHowTo is intended to be opened as a location specific guidebook
+    // with custom titles, reset the title, LLUrlFloaterDispatchHandler will
+    // set needed one later
+    // todo: make title into general parameter for LLFloaterWebContent
+    setTitle(getString("default_tittle"));
+
     LLFloaterWebContent::Params p(key);
     if (!p.url.isProvided() || p.url.getValue().empty())
     {
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index acfa6a5152..95690219b8 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -3,7 +3,7 @@
   legacy_header_height="18"
   can_resize="false"
   can_minimize="false"
-  can_close="false" 
+  can_close="false"
   height="525"
   layout="topleft"
   name="floater_how_to"
@@ -14,4 +14,9 @@
   width="310"
   rel_x="-0.469309"
   rel_y="-0.011166"
-  filename="floater_web_content.xml"/>
\ No newline at end of file
+  filename="floater_web_content.xml">
+  <floater.string
+    name="default_tittle">
+WELCOME ISLAND GUIDEBOOK
+  </floater.string>
+</floater>
\ No newline at end of file
-- 
cgit v1.2.3


From 2ddbdeb165efc0c41866f1fba084fb365474e63c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 01:48:21 +0300
Subject: SL-15168 Reset title of guidebook when opening

---
 indra/newview/llfloaterhowto.cpp                      | 6 ++++++
 indra/newview/llurlfloaterdispatchhandler.cpp         | 4 ++--
 indra/newview/skins/default/xui/en/floater_how_to.xml | 9 +++++++--
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index ef40060807..6e913b08ea 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -51,6 +51,12 @@ BOOL LLFloaterHowTo::postBuild()
 
 void LLFloaterHowTo::onOpen(const LLSD& key)
 {
+    // LLFloaterHowTo is intended to be opened as a location specific guidebook
+    // with custom titles, reset the title, LLUrlFloaterDispatchHandler will
+    // set needed one later
+    // todo: make title into general parameter for LLFloaterWebContent
+    setTitle(getString("default_tittle"));
+
     LLFloaterWebContent::Params p(key);
     if (!p.url.isProvided() || p.url.getValue().empty())
     {
diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index f03caf43b8..519f81b72d 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -52,8 +52,8 @@ const std::string KEY_URI("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
 // Supported floaters, for now it's exact matching, later it might get extended
-const std::string FLOATER_GUIDEBOOK("secondlife://guidebook"); // translates to "how_to"
-const std::string FLOATER_WEB_CONTENT("secondlife://browser"); // translates to "web_content"
+const std::string FLOATER_GUIDEBOOK("secondlife:///guidebook"); // translates to "how_to"
+const std::string FLOATER_WEB_CONTENT("secondlife:///browser"); // translates to "web_content"
 
 // Web content universal arguments
 const std::string KEY_TRUSTED_CONTENT("trusted_content");
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index acfa6a5152..95690219b8 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -3,7 +3,7 @@
   legacy_header_height="18"
   can_resize="false"
   can_minimize="false"
-  can_close="false" 
+  can_close="false"
   height="525"
   layout="topleft"
   name="floater_how_to"
@@ -14,4 +14,9 @@
   width="310"
   rel_x="-0.469309"
   rel_y="-0.011166"
-  filename="floater_web_content.xml"/>
\ No newline at end of file
+  filename="floater_web_content.xml">
+  <floater.string
+    name="default_tittle">
+WELCOME ISLAND GUIDEBOOK
+  </floater.string>
+</floater>
\ No newline at end of file
-- 
cgit v1.2.3


From 80eb5ae1f21df34aa043d1aadd99abe042cfd3ba Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 13:18:29 +0300
Subject: SL-15168 Improved uri recognition

---
 indra/newview/llurlfloaterdispatchhandler.cpp | 56 +++++++++++++++------------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 519f81b72d..6de019d73c 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -52,8 +52,8 @@ const std::string KEY_URI("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
 // Supported floaters, for now it's exact matching, later it might get extended
-const std::string FLOATER_GUIDEBOOK("secondlife:///guidebook"); // translates to "how_to"
-const std::string FLOATER_WEB_CONTENT("secondlife:///browser"); // translates to "web_content"
+const std::string FLOATER_GUIDEBOOK("guidebook"); // translates to "how_to"
+const std::string FLOATER_WEB_CONTENT("browser"); // translates to "web_content"
 
 // Web content universal arguments
 const std::string KEY_TRUSTED_CONTENT("trusted_content");
@@ -68,10 +68,6 @@ const std::string KEY_CAN_CLOSE("can_close");
 const std::string KEY_SHOW_PAGE_TITLE("show_page_title");
 const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed
 
-// expected format secondlife:///floater_alias
-// intended to be extended to: secondlife:///floater_alias/instance_id
-const boost::regex expression("secondlife:///[^ \n]{1,256}");
-
 
 LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler;
 
@@ -112,7 +108,8 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
 
     std::string floater_title;
     LLSD command_params;
-    std::string floater_uri;
+    std::string raw_uri;
+    std::string floater_identifier;
 
     if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL)
     {
@@ -121,14 +118,14 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         {
             floater_title = action_data[KEY_FLOATER_TITLE].asString();
             command_params = action_data[KEY_PARAMS];
-            floater_uri = action_data[KEY_URI].asString();
+            raw_uri = action_data[KEY_URI].asString();
         }
     }
     else if (message.has(KEY_FLOATER_TITLE))
     {
         floater_title = message[KEY_FLOATER_TITLE].asString();
         command_params = message[KEY_PARAMS];
-        floater_uri = message[KEY_URI].asString();
+        raw_uri = message[KEY_URI].asString();
     }
     else
     {
@@ -136,16 +133,31 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         return false;
     }
 
-    if (floater_uri.find(":///") == std::string::npos)
+    if (raw_uri.find(":///") == std::string::npos)
     {
         // try unescaping
-        floater_uri = LLURI::unescape(floater_uri);
+        raw_uri = LLURI::unescape(raw_uri);
+    }
+
+    LLURI floater_uri(raw_uri);
+    if (floater_uri.scheme().empty() || floater_uri.scheme() != "secondlife")
+    {
+        LL_WARNS("URLFloater") << "Received " << raw_uri << " with unexpected scheme in uri: " << floater_uri << LL_ENDL;
+        return false;
     }
 
-    boost::cmatch what;
-    if (!boost::regex_match(floater_uri.c_str(), what, expression))
+    LLSD path_array = floater_uri.pathArray();
+    S32 path_parts = path_array.size();
+    if (path_parts == 0)
     {
-        LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with invalid uri: " << floater_uri << LL_ENDL;
+        LL_WARNS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL;
+        return false;
+    }
+
+    floater_identifier = path_array[0];
+    if (floater_identifier.size() < 3)
+    {
+        LL_WARNS("URLFloater") << "received invalid flaoter indentifier: " << floater_identifier << LL_ENDL;
         return false;
     }
 
@@ -162,7 +174,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
     }
 
-    if (floater_uri == FLOATER_GUIDEBOOK)
+    if (floater_identifier == FLOATER_GUIDEBOOK)
     {
         if (command_params.isMap()) // by default is undefines
         {
@@ -196,7 +208,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
             instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
         }
     }
-    else if (floater_uri == FLOATER_WEB_CONTENT)
+    else if (floater_identifier == FLOATER_WEB_CONTENT)
     {
         if (command_params.has(KEY_URL))
         {
@@ -212,21 +224,15 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
     }
     else
     {
-        LLSD path_array = LLURI(floater_uri).pathArray();
-        S32 path_parts = path_array.size();
-        if (path_parts == 0)
-        {
-            LL_INFOS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL;
-        }
-        else if (LLFloaterReg::isRegistered(path_array[0]))
+        if (LLFloaterReg::isRegistered(floater_identifier))
         {
             // A valid floater
-            LL_INFOS("URLFloater") << "Floater " << path_array[0] << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
+            LL_INFOS("URLFloater") << "Floater " << floater_identifier << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
         }
         else
         {
             // A valid message, but no such flaoter
-            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater_uri << LL_ENDL;
+            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << raw_uri << LL_ENDL;
         }
     }
 
-- 
cgit v1.2.3


From c8c06400a6627053897d69f127e8699f89e503f7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 13:23:04 +0300
Subject: SL-15245 Multiple guide books open, but cannot close them all

"how_to" floater is supposed to be single instance
---
 indra/newview/llfloaterhowto.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterhowto.h b/indra/newview/llfloaterhowto.h
index 15fc43335a..fa1d9cace0 100644
--- a/indra/newview/llfloaterhowto.h
+++ b/indra/newview/llfloaterhowto.h
@@ -42,12 +42,14 @@ public:
 
     LLFloaterHowTo(const Params& key);
 
-    /*virtual*/ void onOpen(const LLSD& key);
+    void onOpen(const LLSD& key) override;
 
     static LLFloaterHowTo* getInstance();
 
+    bool matchesKey(const LLSD& key) override { return true; /*single instance*/ };
+
 private:
-    /*virtual*/ BOOL postBuild();
+    BOOL postBuild() override;
 };
 
 #endif  // LL_LLFLOATERHOWTO_H
-- 
cgit v1.2.3


From e4dc39cf19a00ab148de6d1bd6c4cd229cf545f5 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 11 May 2021 13:25:57 +0300
Subject: SL-15249 FIXED The F1 key does not close the guidebook after clicking
 a link

---
 indra/newview/llfloaterhowto.cpp | 13 +++++++++++++
 indra/newview/llfloaterhowto.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index 6e913b08ea..2bd2c47dd7 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -83,3 +83,16 @@ LLFloaterHowTo* LLFloaterHowTo::getInstance()
 {
     return LLFloaterReg::getTypedInstance<LLFloaterHowTo>("how_to");
 }
+
+BOOL LLFloaterHowTo::handleKeyHere(KEY key, MASK mask)
+{
+	BOOL handled = FALSE;
+
+	if (KEY_F1 == key )
+	{
+		closeFloater();
+		handled = TRUE;
+	}
+
+	return handled;
+}
diff --git a/indra/newview/llfloaterhowto.h b/indra/newview/llfloaterhowto.h
index fa1d9cace0..c2703d815b 100644
--- a/indra/newview/llfloaterhowto.h
+++ b/indra/newview/llfloaterhowto.h
@@ -44,6 +44,8 @@ public:
 
     void onOpen(const LLSD& key) override;
 
+    virtual BOOL handleKeyHere(KEY key, MASK mask);
+
     static LLFloaterHowTo* getInstance();
 
     bool matchesKey(const LLSD& key) override { return true; /*single instance*/ };
-- 
cgit v1.2.3


From a7fada58acd778059e63d9b5a2af8c09cebcf7a2 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 17:12:27 +0300
Subject: SL-15249 Fix MAC build issue

---
 indra/newview/llfloaterhowto.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterhowto.h b/indra/newview/llfloaterhowto.h
index c2703d815b..d8da355600 100644
--- a/indra/newview/llfloaterhowto.h
+++ b/indra/newview/llfloaterhowto.h
@@ -44,7 +44,7 @@ public:
 
     void onOpen(const LLSD& key) override;
 
-    virtual BOOL handleKeyHere(KEY key, MASK mask);
+    BOOL handleKeyHere(KEY key, MASK mask) override;
 
     static LLFloaterHowTo* getInstance();
 
-- 
cgit v1.2.3


From 8eede89c0f3edb7eb6289dc023c3b8e67ae33fd9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 20:46:11 +0300
Subject: Revert "SL-15168 Changed format"

---
 indra/newview/llfloaterhowto.cpp                   |   6 --
 indra/newview/llurlfloaterdispatchhandler.cpp      | 103 ++++++---------------
 .../skins/default/xui/en/floater_how_to.xml        |   7 +-
 3 files changed, 31 insertions(+), 85 deletions(-)

diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index 2bd2c47dd7..ddb3ea04ba 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -51,12 +51,6 @@ BOOL LLFloaterHowTo::postBuild()
 
 void LLFloaterHowTo::onOpen(const LLSD& key)
 {
-    // LLFloaterHowTo is intended to be opened as a location specific guidebook
-    // with custom titles, reset the title, LLUrlFloaterDispatchHandler will
-    // set needed one later
-    // todo: make title into general parameter for LLFloaterWebContent
-    setTitle(getString("default_tittle"));
-
     LLFloaterWebContent::Params p(key);
     if (!p.url.isProvided() || p.url.getValue().empty())
     {
diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 6de019d73c..40afafa4c0 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -36,30 +36,25 @@
 #include "llviewergenericmessage.h"
 #include "llweb.h"
 
-#include <boost/regex.hpp>
-
-// Example:
-// llOpenFloater("My Help Title", "secondlife://guidebook", []);
-
 // values specified by server side's dispatcher
 // for llopenfloater
 const std::string MESSAGE_URL_FLOATER("URLFloater");
 const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL"
 const std::string VALUE_OPEN_URL("OpenURL");
 const std::string KEY_DATA("action_data");
-const std::string KEY_FLOATER_TITLE("floater_title");
-const std::string KEY_URI("floater_url");
+const std::string KEY_FLOATER("floater_title");
+const std::string KEY_URL("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
-// Supported floaters, for now it's exact matching, later it might get extended
-const std::string FLOATER_GUIDEBOOK("guidebook"); // translates to "how_to"
-const std::string FLOATER_WEB_CONTENT("browser"); // translates to "web_content"
+// Supported floaters
+const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to
+const std::string FLOATER_HOW_TO("how_to");
+const std::string FLOATER_WEB_CONTENT("web_content");
 
-// Web content universal arguments
+// Web content universal argument
 const std::string KEY_TRUSTED_CONTENT("trusted_content");
-const std::string KEY_URL("url");
 
-// Guidebook ("how_to") specific arguments
+// Guidebook specific arguments
 const std::string KEY_WIDTH("width");
 const std::string KEY_HEGHT("height");
 const std::string KEY_CAN_CLOSE("can_close");
@@ -106,26 +101,25 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
     }
 
-    std::string floater_title;
+    std::string floater;
     LLSD command_params;
-    std::string raw_uri;
-    std::string floater_identifier;
+    std::string url;
 
     if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL)
     {
         LLSD &action_data = message[KEY_DATA];
         if (action_data.isMap())
         {
-            floater_title = action_data[KEY_FLOATER_TITLE].asString();
+            floater = action_data[KEY_FLOATER].asString();
             command_params = action_data[KEY_PARAMS];
-            raw_uri = action_data[KEY_URI].asString();
+            url = action_data[KEY_URL].asString();
         }
     }
-    else if (message.has(KEY_FLOATER_TITLE))
+    else if (message.has(KEY_FLOATER))
     {
-        floater_title = message[KEY_FLOATER_TITLE].asString();
+        floater = message[KEY_FLOATER].asString();
         command_params = message[KEY_PARAMS];
-        raw_uri = message[KEY_URI].asString();
+        url = message[KEY_URL].asString();
     }
     else
     {
@@ -133,48 +127,16 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         return false;
     }
 
-    if (raw_uri.find(":///") == std::string::npos)
+    if (url.find("://") == std::string::npos)
     {
         // try unescaping
-        raw_uri = LLURI::unescape(raw_uri);
-    }
-
-    LLURI floater_uri(raw_uri);
-    if (floater_uri.scheme().empty() || floater_uri.scheme() != "secondlife")
-    {
-        LL_WARNS("URLFloater") << "Received " << raw_uri << " with unexpected scheme in uri: " << floater_uri << LL_ENDL;
-        return false;
-    }
-
-    LLSD path_array = floater_uri.pathArray();
-    S32 path_parts = path_array.size();
-    if (path_parts == 0)
-    {
-        LL_WARNS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL;
-        return false;
-    }
-
-    floater_identifier = path_array[0];
-    if (floater_identifier.size() < 3)
-    {
-        LL_WARNS("URLFloater") << "received invalid flaoter indentifier: " << floater_identifier << LL_ENDL;
-        return false;
+        url = LLURI::unescape(url);
     }
 
     LLFloaterWebContent::Params params;
-    if (command_params.isMap())
-    {
-        if (command_params.has(KEY_TRUSTED_CONTENT))
-        {
-            params.trusted_content = command_params[KEY_TRUSTED_CONTENT].asBoolean();
-        }
-        if (command_params.has(KEY_URL))
-        {
-            params.url = command_params[KEY_URL].asString();
-        }
-    }
+    params.url = url;
 
-    if (floater_identifier == FLOATER_GUIDEBOOK)
+    if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO)
     {
         if (command_params.isMap()) // by default is undefines
         {
@@ -200,39 +162,34 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
 
         LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
-
-        instance = LLFloaterReg::findInstance("how_to");
-        instance->setTitle(floater_title);
+        
         if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE))
         {
+            LLFloater* instance = LLFloaterReg::findInstance("how_to");
             instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
         }
     }
-    else if (floater_identifier == FLOATER_WEB_CONTENT)
+    else if (floater == FLOATER_WEB_CONTENT)
     {
-        if (command_params.has(KEY_URL))
+        if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
         {
-            if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
-            {
-                params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
-                params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true;
-                params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true;
-            }
-            LLFloater* instance = LLFloaterReg::showInstance("web_content", params);
-            instance->setTitle(floater_title);
+            params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
+            params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true;
+            params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true;
         }
+        LLFloaterReg::showInstance("web_content", params);
     }
     else
     {
-        if (LLFloaterReg::isRegistered(floater_identifier))
+        if (LLFloaterReg::isRegistered(floater))
         {
             // A valid floater
-            LL_INFOS("URLFloater") << "Floater " << floater_identifier << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
+            LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL;
         }
         else
         {
             // A valid message, but no such flaoter
-            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << raw_uri << LL_ENDL;
+            LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL;
         }
     }
 
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index 95690219b8..baff8e1bc0 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -14,9 +14,4 @@
   width="310"
   rel_x="-0.469309"
   rel_y="-0.011166"
-  filename="floater_web_content.xml">
-  <floater.string
-    name="default_tittle">
-WELCOME ISLAND GUIDEBOOK
-  </floater.string>
-</floater>
\ No newline at end of file
+  filename="floater_web_content.xml"/>
\ No newline at end of file
-- 
cgit v1.2.3


From 87f1d6071ee480c5dfcf15f6da3f9a9b9766d723 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 11 May 2021 20:55:12 +0300
Subject: SL-15168 Added 'Title' argument

---
 indra/newview/llurlfloaterdispatchhandler.cpp | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 40afafa4c0..ec2e423c64 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -36,13 +36,16 @@
 #include "llviewergenericmessage.h"
 #include "llweb.h"
 
+// Example:
+// llOpenFloater("guidebook", "http://page.com", []);
+
 // values specified by server side's dispatcher
 // for llopenfloater
 const std::string MESSAGE_URL_FLOATER("URLFloater");
 const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL"
 const std::string VALUE_OPEN_URL("OpenURL");
 const std::string KEY_DATA("action_data");
-const std::string KEY_FLOATER("floater_title");
+const std::string KEY_FLOATER("floater_title"); // name of the floater, not title
 const std::string KEY_URL("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
@@ -58,6 +61,7 @@ const std::string KEY_TRUSTED_CONTENT("trusted_content");
 const std::string KEY_WIDTH("width");
 const std::string KEY_HEGHT("height");
 const std::string KEY_CAN_CLOSE("can_close");
+const std::string KEY_TITLE("title");
 
 // web_content specific arguments
 const std::string KEY_SHOW_PAGE_TITLE("show_page_title");
@@ -163,10 +167,17 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
 
         LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
         
-        if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE))
+        if (command_params.isMap())
         {
             LLFloater* instance = LLFloaterReg::findInstance("how_to");
-            instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
+            if (command_params.has(KEY_CAN_CLOSE))
+            {
+                instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
+            }
+            if (command_params.has(KEY_TITLE))
+            {
+                instance->setTitle(command_params[KEY_TITLE].asString());
+            }
         }
     }
     else if (floater == FLOATER_WEB_CONTENT)
-- 
cgit v1.2.3


From 3917de54db0dacf2aaa4f8af083db632c6a51365 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 12 May 2021 14:25:46 +0300
Subject: SL-15245 Multiple guide books open, but cannot close them all

Opening and closing single-instance floaters rapidly and multiple times could result in cleaning instance from floaterreg twice, thus removing new isntance instead of current one
---
 indra/llui/llfloater.cpp                      | 7 ++++++-
 indra/newview/llurlfloaterdispatchhandler.cpp | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 3680e20f15..8ceb411ede 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -510,7 +510,12 @@ void LLFloater::destroy()
 // virtual
 LLFloater::~LLFloater()
 {
-	LLFloaterReg::removeInstance(mInstanceName, mKey);
+    if (!isDead())
+    {
+        // If it's dead, instance is supposed to be already removed, and
+        // in case of single instance we can remove new one by accident
+        LLFloaterReg::removeInstance(mInstanceName, mKey);
+    }
 	
 	if( gFocusMgr.childHasKeyboardFocus(this))
 	{
diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index ec2e423c64..0343485864 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -54,6 +54,7 @@ const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to
 const std::string FLOATER_HOW_TO("how_to");
 const std::string FLOATER_WEB_CONTENT("web_content");
 
+// All arguments are palceholders! Server side will need to add validation first.
 // Web content universal argument
 const std::string KEY_TRUSTED_CONTENT("trusted_content");
 
@@ -105,6 +106,8 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         }
     }
 
+    // At the moment command_params is a placeholder and code treats it as map
+    // Once server side adds argument validation this will be either a map or an array
     std::string floater;
     LLSD command_params;
     std::string url;
-- 
cgit v1.2.3


From 0aba47476f655afa1f259c3d8aa711eee43b3457 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 25 May 2021 00:27:32 +0300
Subject: SL-15298 Move Landmark's Edit button

---
 .../skins/default/xui/en/panel_landmark_info.xml   | 28 +++++++++++-----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index f00d25ff05..e82305ef17 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -289,7 +289,18 @@
                  name="title_value"
                  text_color="white"
                  top_pad="5"
-                 width="290" /> 
+                 width="200" /> 
+                <button
+                 follows="top|right"
+                 height="24"
+                 label="Edit"
+                 layout="topleft"
+                 left_pad="8"
+                 mouse_opaque="false"
+                 name="edit_btn"
+                 tool_tip="Edit landmark information"
+                 top_delta="-1"
+                 width="83" />
                 <line_editor
                  follows="left|top|right"
                  height="22"
@@ -299,8 +310,8 @@
                  name="title_editor"
                  prevalidate_callback="ascii"
                  text_readonly_color="white"
-                 top_delta="0"
-                 width="290" />
+                 top_delta="1"
+                 width="290"/>
                 <text
                  follows="left|top"
                  height="15"
@@ -342,17 +353,6 @@
                  name="folder_combo"
                  top_pad="5"
                  width="200" />
-                <button
-                 follows="bottom|left|right"
-                 height="23"
-                 label="Edit"
-                 layout="topleft"
-                 left="0"
-                 mouse_opaque="false"
-                 name="edit_btn"
-                 tool_tip="Edit landmark information"
-                 top_pad="-42"
-                 width="100" />
             </panel>
         </panel>
     </scroll_container>
-- 
cgit v1.2.3


From 242ae3e073273fcb6ccc3d02c187c799f20fed96 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 25 May 2021 21:56:07 +0300
Subject: SL-15285 Restore 'drop item' functionality in right click menu

---
 .../newview/skins/default/xui/en/menu_attachment_self.xml  | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 13e4b9ba7b..26b1c86c53 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -320,4 +320,18 @@
     <menu_item_call.on_visible
      function="EnableMuteParticle" />
   </menu_item_call>
+
+  <menu_item_separator
+   layout="topleft" />
+  
+  <menu_item_call
+   enabled="false"
+   label="Drop item"
+   layout="topleft"
+   name="Drop">
+    <menu_item_call.on_click
+     function="Attachment.Drop" />
+    <menu_item_call.on_enable
+     function="Attachment.EnableDrop" />
+  </menu_item_call>
 </context_menu>
-- 
cgit v1.2.3


From 7d726d1b4aa3e572c9a52788ad48f5807560be8d Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 27 May 2021 02:17:39 +0300
Subject: SL-15319 FIXED Crash in LLFloaterCreateLandmark::onCancelClicked

---
 indra/newview/llfloatercreatelandmark.cpp | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index db84a2ac76..eb93a6a75a 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -231,7 +231,11 @@ void LLFloaterCreateLandmark::folderCreatedCallback(LLUUID folder_id)
 void LLFloaterCreateLandmark::onSaveClicked()
 {
 	if (mItem.isNull())
+	{
+		closeFloater();
 		return;
+	}
+		
 
 	std::string current_title_value = mLandmarkTitleEditor->getText();
 	std::string item_title_value = mItem->getName();
@@ -282,8 +286,11 @@ void LLFloaterCreateLandmark::onSaveClicked()
 
 void LLFloaterCreateLandmark::onCancelClicked()
 {
-	LLUUID item_id = mItem->getUUID();
-	remove_inventory_item(item_id, NULL);
+	if (!mItem.isNull())
+	{
+		LLUUID item_id = mItem->getUUID();
+		remove_inventory_item(item_id, NULL);
+	}
 	closeFloater();
 }
 
-- 
cgit v1.2.3


From 34ef50f3b272cbf01e96a8356a1e67f2ec831452 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Fri, 4 Jun 2021 23:35:10 +0300
Subject: SL-15350 Update images for New User viewer log in page

---
 .../textures/windows/first_login_image_left.png    | Bin 384997 -> 271413 bytes
 .../textures/windows/first_login_image_right.png   | Bin 340188 -> 366068 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/indra/newview/skins/default/textures/windows/first_login_image_left.png b/indra/newview/skins/default/textures/windows/first_login_image_left.png
index 1fa10fde53..77904d7d12 100644
Binary files a/indra/newview/skins/default/textures/windows/first_login_image_left.png and b/indra/newview/skins/default/textures/windows/first_login_image_left.png differ
diff --git a/indra/newview/skins/default/textures/windows/first_login_image_right.png b/indra/newview/skins/default/textures/windows/first_login_image_right.png
index d764d846b7..35ecce9c07 100644
Binary files a/indra/newview/skins/default/textures/windows/first_login_image_right.png and b/indra/newview/skins/default/textures/windows/first_login_image_right.png differ
-- 
cgit v1.2.3


From 5b730160f662d0324ba01f498744a279d002a910 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 8 Jun 2021 00:49:14 +0300
Subject: SL-15168 A bit of debug logging

---
 indra/newview/llurlfloaterdispatchhandler.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 0343485864..2e595390cc 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -145,6 +145,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
 
     if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO)
     {
+        LL_DEBUGS("URLFloater") << "Opening how_to floater with parameters: " << message << LL_ENDL;
         if (command_params.isMap()) // by default is undefines
         {
             params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
@@ -185,6 +186,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
     }
     else if (floater == FLOATER_WEB_CONTENT)
     {
+        LL_DEBUGS("URLFloater") << "Opening web_content floater with parameters: " << message << LL_ENDL;
         if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params
         {
             params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false;
@@ -195,6 +197,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
     }
     else
     {
+        LL_DEBUGS("URLFloater") << "Unknow floater with parameters: " << message << LL_ENDL;
         if (LLFloaterReg::isRegistered(floater))
         {
             // A valid floater
-- 
cgit v1.2.3


From 79f8c024c34efad93ce55ebacf656e6fc9804198 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 9 Jun 2021 19:46:23 +0300
Subject: SL-15363 how_to on older viewers is forced to persist

Older how_to floater is not set to persist in between sessions and gets stuck, ranamed new how_to into guidebook to avoid the issue
---
 indra/newview/app_settings/commands.xml       |  4 ++--
 indra/newview/llfloaterhowto.cpp              |  2 +-
 indra/newview/llurlfloaterdispatchhandler.cpp | 10 +++++-----
 indra/newview/llviewerfloaterreg.cpp          |  2 +-
 indra/newview/llviewermenu.cpp                |  2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 91841b970d..d0480ca47e 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -89,9 +89,9 @@
            label_ref="Command_HowTo_Label"
            tooltip_ref="Command_HowTo_Tooltip"
            execute_function="Floater.ToggleOrBringToFront"
-           execute_parameters="how_to"
+           execute_parameters="guidebook"
            is_running_function="Floater.IsOpen"
-           is_running_parameters="how_to"
+           is_running_parameters="guidebook"
            />
   <command name="inventory"
            available_in_toybox="true"
diff --git a/indra/newview/llfloaterhowto.cpp b/indra/newview/llfloaterhowto.cpp
index ddb3ea04ba..a359fb7c7d 100644
--- a/indra/newview/llfloaterhowto.cpp
+++ b/indra/newview/llfloaterhowto.cpp
@@ -75,7 +75,7 @@ void LLFloaterHowTo::onOpen(const LLSD& key)
 
 LLFloaterHowTo* LLFloaterHowTo::getInstance()
 {
-    return LLFloaterReg::getTypedInstance<LLFloaterHowTo>("how_to");
+    return LLFloaterReg::getTypedInstance<LLFloaterHowTo>("guidebook");
 }
 
 BOOL LLFloaterHowTo::handleKeyHere(KEY key, MASK mask)
diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp
index 2e595390cc..6b1a373beb 100644
--- a/indra/newview/llurlfloaterdispatchhandler.cpp
+++ b/indra/newview/llurlfloaterdispatchhandler.cpp
@@ -50,8 +50,8 @@ const std::string KEY_URL("floater_url");
 const std::string KEY_PARAMS("floater_params");
 
 // Supported floaters
-const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to
-const std::string FLOATER_HOW_TO("how_to");
+const std::string FLOATER_GUIDEBOOK("guidebook");
+const std::string FLOATER_HOW_TO("how_to"); // alias for guidebook
 const std::string FLOATER_WEB_CONTENT("web_content");
 
 // All arguments are palceholders! Server side will need to add validation first.
@@ -163,17 +163,17 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st
         // only one instance of guidebook can exist at a time, so if this command arrives,
         // we need to close previous guidebook then reopen it.
 
-        LLFloater* instance = LLFloaterReg::findInstance("how_to");
+        LLFloater* instance = LLFloaterReg::findInstance("guidebook");
         if (instance)
         {
             instance->closeHostedFloater();
         }
 
-        LLFloaterReg::toggleInstanceOrBringToFront("how_to", params);
+        LLFloaterReg::toggleInstanceOrBringToFront("guidebook", params);
         
         if (command_params.isMap())
         {
-            LLFloater* instance = LLFloaterReg::findInstance("how_to");
+            LLFloater* instance = LLFloaterReg::findInstance("guidebook");
             if (command_params.has(KEY_CAN_CLOSE))
             {
                 instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean());
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index de184392f9..5a05f89758 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -363,7 +363,7 @@ void LLViewerFloaterReg::registerFloaters()
     LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
 	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
 	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
-	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
+	LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
 
 	LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
 	
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index d3d205d509..fbf057603e 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7739,7 +7739,7 @@ class LLToggleHowTo : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		LLFloaterReg::toggleInstanceOrBringToFront("how_to");
+		LLFloaterReg::toggleInstanceOrBringToFront("guidebook");
 		return true;
 	}
 };
-- 
cgit v1.2.3


From d1b52bd9d806e8ea2cc9ab37193d06521bbb0e87 Mon Sep 17 00:00:00 2001
From: Callum Prentice <callum@lindenlab.com>
Date: Thu, 10 Jun 2021 16:22:59 -0700
Subject: Fix for SL-15381 Import Vivox VAD voice fixes into 'Viewer UI
 changes' branch

---
 indra/newview/app_settings/settings.xml | 48 ++++++++++++++++-
 indra/newview/llvoicevivox.cpp          | 94 +++++++++++++++++++++++++++++++++
 indra/newview/llvoicevivox.h            |  6 +++
 3 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 1df3ed5346..a2933b85a5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14436,7 +14436,53 @@
       <key>Value</key>
       <integer>44125</integer>
     </map>
-    <key>VoiceCallsFriendsOnly</key>
+    
+  <key>VivoxVadAuto</key>
+  <map>
+    <key>Comment</key>
+    <string>A flag indicating if the automatic VAD is enabled (1) or disabled (0). The individual settings are ignored if the auto-mode is enabled</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>VivoxVadHangover</key>
+  <map>
+    <key>Comment</key>
+    <string>The time (in milliseconds) that it takes or the VAD to switch back to silence from speech mode after the last speech frame has been detected</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>2000</integer>
+  </map>
+  <key>VivoxVadNoiseFloor</key>
+  <map>
+    <key>Comment</key>
+    <string>A dimensionless value between 0 and 20000 (default 576) that controls the maximum level at which the noise floor may be set at by the VAD's noise tracking</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>576</integer>
+  </map>
+  <key>VivoxVadSensitivity</key>
+  <map>
+    <key>Comment</key>
+    <string>
+      A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>VoiceCallsFriendsOnly</key>
     <map>
       <key>Comment</key>
       <string>(Deprecated) Only accept voice calls from residents on your friends list</string>
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index b0f57beff8..7d8aa6fbbd 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -684,6 +684,21 @@ void LLVivoxVoiceClient::voiceControlCoro()
         bool success = startAndConnectSession();
         if (success)
         {
+			// enable/disable the automatic VAD and explicitly set the initial values of 
+			// the VAD variables ourselves when it is off - see SL-15072 for more details
+			// note: we set the other parameters too even if the auto VAD is on which is ok
+			unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
+			unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+			unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+			unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
+			setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
+			
+			// watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
+			gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+			gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+			gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+			gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+
             if (mTuningMode)
             {
                 performMicTuning();
@@ -3230,6 +3245,73 @@ void LLVivoxVoiceClient::sendLocalAudioUpdates()
 	}
 }
 
+/**
+ * Because of the recurring voice cutout issues (SL-15072) we are going to try
+ * to disable the automatic VAD (Voice Activity Detection) and set the associated
+ * parameters directly. We will expose them via Debug Settings and that should
+ * let us iterate on a collection of values that work for us. Hopefully! 
+ *
+ * From the VIVOX Docs:
+ *
+ * VadAuto: A flag indicating if the automatic VAD is enabled (1) or disabled (0)
+ *
+ * VadHangover: The time (in milliseconds) that it takes
+ * for the VAD to switch back to silence from speech mode after the last speech
+ * frame has been detected.
+ *
+ * VadNoiseFloor: A dimensionless value between 0 and 
+ * 20000 (default 576) that controls the maximum level at which the noise floor
+ * may be set at by the VAD's noise tracking. Too low of a value will make noise
+ * tracking ineffective (A value of 0 disables noise tracking and the VAD then 
+ * relies purely on the sensitivity property). Too high of a value will make 
+ * long speech classifiable as noise.
+ *
+ * VadSensitivity: A dimensionless value between 0 and 
+ * 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds
+ * to decreasing the sensitivity of the VAD (i.e. '0' is most sensitive, 
+ * while 100 is 'least sensitive')
+ */
+void LLVivoxVoiceClient::setupVADParams(unsigned int vad_auto,
+                                        unsigned int vad_hangover,
+                                        unsigned int vad_noise_floor,
+                                        unsigned int vad_sensitivity)
+{
+    std::ostringstream stream;
+
+    LL_INFOS("Voice") << "Setting the automatic VAD to "
+        << (vad_auto ? "True" : "False")
+		<< " and discrete values to"
+		<< " VadHangover = " << vad_hangover
+		<< ", VadSensitivity = " << vad_sensitivity
+		<< ", VadNoiseFloor = " << vad_noise_floor
+        << LL_ENDL;
+
+	// Create a request to set the VAD parameters:
+	stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
+               << "<VadAuto>" << vad_auto << "</VadAuto>"
+               << "<VadHangover>" << vad_hangover << "</VadHangover>"
+               << "<VadSensitivity>" << vad_sensitivity << "</VadSensitivity>"
+               << "<VadNoiseFloor>" << vad_noise_floor << "</VadNoiseFloor>"
+           << "</Request>\n\n\n";
+
+    if (!stream.str().empty())
+    {
+        writeString(stream.str());
+    }
+}
+
+void LLVivoxVoiceClient::onVADSettingsChange()
+{
+	// pick up the VAD variables (one of which was changed)
+	unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
+	unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+	unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+	unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
+
+	// build a VAD params change request and send it to SLVoice
+	setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
+}
+
 /////////////////////////////
 // Response/Event handlers
 
@@ -7582,6 +7664,18 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		{
 			LLVivoxVoiceClient::getInstance()->accountGetTemplateFontsResponse(statusCode, statusString);
 		}
+		else if (!stricmp(actionCstr, "Aux.SetVadProperties.1"))
+		{
+			// both values of statusCode (old and more recent) indicate valid requests
+			if (statusCode != 0 && statusCode != 200)
+			{
+				LL_WARNS("Voice") << "Aux.SetVadProperties.1 request failed: "
+					<< "statusCode: " << statusCode
+					<< " and "
+					<< "statusString: " << statusString
+					<< LL_ENDL;
+			}
+		}
 		/*
 		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
 		 {
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 699c85066b..746201af04 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -472,6 +472,12 @@ protected:
 	
 	void muteListChanged();
 		
+	/////////////////////////////
+	// VAD changes
+	// disable auto-VAD and configure VAD parameters explicitly
+	void setupVADParams(unsigned int vad_auto, unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
+	void onVADSettingsChange();
+
 	/////////////////////////////
 	// Sending updates of current state
 	void updatePosition(void);
-- 
cgit v1.2.3


From 467d8339c970c253dada2cf0e1eed45be66593ac Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 24 Jun 2021 15:52:37 -0400
Subject: Increment viewer version to 6.4.21 following promotion of DRTVWR-518

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index e786022da5..22beed373e 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.20
+6.4.21
-- 
cgit v1.2.3