From 706d8f17273f4718a2adf5a43c1de5a1dc08abad Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 18 May 2023 22:22:07 +0300 Subject: [PATCH 01/16] SL-19732 Fix folder's thumbnail from sticking over folder's content --- indra/llui/llfolderview.cpp | 2 +- indra/llui/llfolderview.h | 2 +- indra/llui/llfolderviewitem.cpp | 2 +- indra/llui/llfolderviewitem.h | 8 ++++---- indra/newview/llinventorypanel.cpp | 12 ++++++++++-- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 9fa8a84fa4..bf6f2436b1 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -2064,7 +2064,7 @@ LLFolderViewItem* LLFolderView::getNextUnselectedItem() return new_selection; } -S32 LLFolderView::getItemHeight() +S32 LLFolderView::getItemHeight() const { if(!hasVisibleChildren()) { diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 22b8c475ec..73028f31b1 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -136,7 +136,7 @@ public: // Find width and height of this object and its children. Also // makes sure that this view and its children are the right size. virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); + virtual S32 getItemHeight() const; void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index bc7a2cc3f0..4fbfa7ed79 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -416,7 +416,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) return *height; } -S32 LLFolderViewItem::getItemHeight() +S32 LLFolderViewItem::getItemHeight() const { return mItemHeight; } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index c8d44de474..5c2a1ecff0 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -178,7 +178,7 @@ public: // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); + virtual S32 getItemHeight() const; virtual S32 getLabelXPos(); S32 getIconPad(); S32 getTextPad(); @@ -217,9 +217,9 @@ public: void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - BOOL getIsCurSelection() { return mIsCurSelection; } + BOOL getIsCurSelection() const { return mIsCurSelection; } - BOOL hasVisibleChildren() { return mHasVisibleChildren; } + BOOL hasVisibleChildren() const { return mHasVisibleChildren; } // true if object can't have children virtual bool isFolderComplete() { return true; } @@ -268,7 +268,7 @@ public: virtual LLFolderView* getRoot(); virtual const LLFolderView* getRoot() const; BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); - S32 getIndentation() { return mIndentation; } + S32 getIndentation() const { return mIndentation; } virtual BOOL passedFilter(S32 filter_generation = -1); virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index edcd45db79..c5d3fa3f7a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1311,10 +1311,18 @@ BOOL LLInventoryPanel::handleToolTip(S32 x, S32 y, MASK mask) params["inv_type"] = vm_item_p->getInventoryType(); params["thumbnail_id"] = vm_item_p->getThumbnailUUID(); params["item_id"] = vm_item_p->getUUID(); - + + // tooltip should only show over folder, but screen + // rect includes items under folder as well + LLRect actionable_rect = hover_item_p->calcScreenRect(); + if (hover_item_p->isOpen() && hover_item_p->hasVisibleChildren()) + { + actionable_rect.mBottom = actionable_rect.mTop - hover_item_p->getItemHeight(); + } + LLToolTipMgr::instance().show(LLToolTip::Params() .message(hover_item_p->getToolTip()) - .sticky_rect(hover_item_p->calcScreenRect()) + .sticky_rect(actionable_rect) .delay_time(LLView::getTooltipTimeout()) .create_callback(boost::bind(&LLInspectTextureUtil::createInventoryToolTip, _1)) .create_params(params)); From 100ace48f1cd64a364179c06900465209aac4945 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 18 May 2023 23:22:58 +0300 Subject: [PATCH 02/16] SL-19686 don't build gallery items without thumbnails in combination view --- indra/newview/llinventorygallery.cpp | 65 ++++++++++++++++++++++++++-- indra/newview/llinventorygallery.h | 4 ++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f97cb9dbf4..18a7068b66 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -200,6 +200,14 @@ void LLInventoryGallery::updateRootFolder() delete mCategoriesObserver; mCategoriesObserver = new LLInventoryCategoriesObserver(); + + if (gInventory.containsObserver(mThumbnailsObserver)) + { + gInventory.removeObserver(mThumbnailsObserver); + } + delete mThumbnailsObserver; + mThumbnailsObserver = new LLThumbnailsObserver(); + gInventory.addObserver(mThumbnailsObserver); } { mRootChangedSignal(); @@ -699,7 +707,11 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LL_WARNS("InventoryGallery") << "Failed to find item: " << item_id << LL_ENDL; return; } - + if(!mFilter->checkAgainstFilterThumbnails(item_id)) + { + mThumbnailsObserver->addSkippedItem(item_id, boost::bind(&LLInventoryGallery::onThumbnailAdded, this, item_id)); + return; + } std::string name = obj->getName(); LLUUID thumbnail_id = obj->getThumbnailUUID();; LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); @@ -816,6 +828,15 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) } } +void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) +{ + if((mItemMap.count(item_id) == 0) && mFilter->checkAgainstFilterThumbnails(item_id)) + { + updateAddedItem(item_id); + reArrangeRows(); + } +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) @@ -1525,9 +1546,33 @@ void LLInventoryGalleryItem::updateNameText() void LLThumbnailsObserver::changed(U32 mask) { - if (!mItemMap.size()) - return; std::vector deleted_ids; + for (item_map_t::iterator iter = mSkippedItems.begin(); + iter != mSkippedItems.end(); + ++iter) + { + const LLUUID& obj_id = (*iter).first; + LLItemData& data = (*iter).second; + + LLInventoryObject* obj = gInventory.getObject(obj_id); + if (!obj) + { + deleted_ids.push_back(obj_id); + continue; + } + + const LLUUID thumbnail_id = obj->getThumbnailUUID(); + if (data.mThumbnailID != thumbnail_id) + { + data.mThumbnailID = thumbnail_id; + data.mCallback(); + } + } + for (std::vector::iterator deleted_id = deleted_ids.begin(); deleted_id != deleted_ids.end(); ++deleted_id) + { + removeSkippedItem(*deleted_id); + } + deleted_ids.clear(); for (item_map_t::iterator iter = mItemMap.begin(); iter != mItemMap.end(); @@ -1569,11 +1614,25 @@ bool LLThumbnailsObserver::addItem(const LLUUID& obj_id, callback_t cb) return false; } +void LLThumbnailsObserver::addSkippedItem(const LLUUID& obj_id, callback_t cb) +{ + LLInventoryObject* obj = gInventory.getObject(obj_id); + if (obj) + { + mSkippedItems.insert(item_map_value_t(obj_id, LLItemData(obj_id, obj->getThumbnailUUID(), cb))); + } +} + void LLThumbnailsObserver::removeItem(const LLUUID& obj_id) { mItemMap.erase(obj_id); } +void LLThumbnailsObserver::removeSkippedItem(const LLUUID& obj_id) +{ + mSkippedItems.erase(obj_id); +} + //----------------------------- // Helper drag&drop functions //----------------------------- diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index f7065afdae..473d1a1db4 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -89,6 +89,7 @@ public: void updateRemovedItem(LLUUID item_id); void updateChangedItemName(LLUUID item_id, std::string name); void updateItemThumbnail(LLUUID item_id); + void onThumbnailAdded(LLUUID item_id); void updateWornItem(LLUUID item_id, bool is_worn); void updateMessageVisibility(); @@ -308,7 +309,9 @@ public: virtual void changed(U32 mask); bool addItem(const LLUUID& obj_id, callback_t cb); + void addSkippedItem(const LLUUID& obj_id, callback_t cb); void removeItem(const LLUUID& obj_id); + void removeSkippedItem(const LLUUID& obj_id); protected: @@ -328,6 +331,7 @@ protected: typedef std::map item_map_t; typedef item_map_t::value_type item_map_value_t; item_map_t mItemMap; + item_map_t mSkippedItems; }; class LLGalleryGestureObserver : public LLGestureManagerObserver From d53c8a7d65cabaab303c21db7bb6d2ce4370c331 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 19 May 2023 18:09:35 +0300 Subject: [PATCH 03/16] SL-19738 don't switch the view when creating an item --- indra/newview/llinventorypanel.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index c5d3fa3f7a..604bffb96e 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1834,7 +1834,13 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L if (main_inventory && main_inventory->isSingleFolderMode() && use_main_panel) { - main_inventory->toggleViewMode(); + const LLInventoryObject *obj = gInventory.getObject(obj_id); + if (obj) + { + main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false); + main_inventory->setGallerySelection(obj_id); + return; + } } LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open); From f83ed218327213ae809535f4739d9f9eff6374a3 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 22 May 2023 20:47:17 +0300 Subject: [PATCH 04/16] SL-19752 don't try to scroll after opening the new folder in single-folder view to avoid crash --- indra/llui/llfolderview.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index bf6f2436b1..7831aa92fb 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -833,9 +833,12 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) mAutoOpenItems.push(item); item->setOpen(TRUE); + if(!item->isSingleFolderMode()) + { LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); scrollToShowItem(item, constraint_rect); + } } void LLFolderView::closeAutoOpenedFolders() From 8c0ad5425f4f7497fcb3973623d8620d7088e28a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 22 May 2023 22:14:58 +0300 Subject: [PATCH 05/16] SL-19748 Fix thumbnail not applying if floater was closed too fast --- .../newview/llfloaterchangeitemthumbnail.cpp | 64 +++++++++++++------ indra/newview/llfloaterchangeitemthumbnail.h | 2 + 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp index 3070c437bd..1ac6ee72bf 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.cpp +++ b/indra/newview/llfloaterchangeitemthumbnail.cpp @@ -336,9 +336,6 @@ void LLFloaterChangeItemThumbnail::refreshFromObject(LLInventoryObject* obj) if (item) { setTitle(getString("title_item_thumbnail")); - // This floater probably shouldn't be possible to open - // for imcomplete items - llassert(item->isFinished()); icon_img = LLInventoryIcon::getIcon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE); mRemoveImageBtn->setEnabled(thumbnail_id.notNull() && ((item->getActualType() != LLAssetType::AT_TEXTURE) || (item->getAssetUUID() != thumbnail_id))); @@ -543,6 +540,13 @@ void LLFloaterChangeItemThumbnail::onRemovalConfirmation(const LLSD& notificatio } } +struct ImageLoadedData +{ + LLUUID mThumbnailId; + LLUUID mObjectId; + LLHandle mFloaterHandle; +}; + void LLFloaterChangeItemThumbnail::assignAndValidateAsset(const LLUUID &asset_id, bool silent) { LLPointer texturep = LLViewerTextureManager::getFetchedTexture(asset_id); @@ -557,11 +561,16 @@ void LLFloaterChangeItemThumbnail::assignAndValidateAsset(const LLUUID &asset_id // don't warn user multiple times if some textures took their time mExpectingAssetId = asset_id; } + ImageLoadedData *data = new ImageLoadedData(); + data->mObjectId = mItemId; + data->mThumbnailId = asset_id; + data->mFloaterHandle = getHandle(); + texturep->setLoadedCallback(onImageLoaded, MAX_DISCARD_LEVEL, // don't actually need max one, 3 or 4 should be enough FALSE, FALSE, - new LLHandle(getHandle()), + (void*)data, NULL, FALSE); } @@ -629,19 +638,21 @@ void LLFloaterChangeItemThumbnail::onImageLoaded( if (!final && success) return; //not done yet - LLHandle* handle = (LLHandle*)userdata; + ImageLoadedData* data = (ImageLoadedData*)userdata; - if (success && !handle->isDead()) + if (success) { - LLFloaterChangeItemThumbnail* self = static_cast(handle->get()); - if (self) + // Update the item, set it even if floater is dead + if (validateAsset(data->mThumbnailId)) { - LLUUID asset_id = src_vi->getID(); - if (validateAsset(asset_id)) - { - self->setThumbnailId(asset_id); - } - else if (self->mExpectingAssetId == asset_id) + setThumbnailId(data->mThumbnailId, data->mObjectId); + } + + // Update floater + if (!data->mFloaterHandle.isDead()) + { + LLFloaterChangeItemThumbnail* self = static_cast(data->mFloaterHandle.get()); + if (self && self->mExpectingAssetId == data->mThumbnailId) { LLNotificationsUtil::add("ThumbnailDimentionsLimit"); self->mExpectingAssetId = LLUUID::null; @@ -649,7 +660,7 @@ void LLFloaterChangeItemThumbnail::onImageLoaded( } } - delete handle; + delete data; } void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id) @@ -738,8 +749,25 @@ void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID &new_thumbnail_id if (mTaskId.notNull()) { LL_ERRS() << "Not implemented yet" << LL_ENDL; + return; } - else if (obj->getThumbnailUUID() != new_thumbnail_id) + + setThumbnailId(new_thumbnail_id, mItemId, obj); +} + +void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id) +{ + LLInventoryObject* obj = gInventory.getObject(object_id); + if (!obj) + { + return; + } + + setThumbnailId(new_thumbnail_id, object_id, obj); +} +void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id, LLInventoryObject* obj) +{ + if (obj->getThumbnailUUID() != new_thumbnail_id) { LLSD updates; // At the moment server expects id as a string @@ -747,12 +775,12 @@ void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID &new_thumbnail_id LLViewerInventoryCategory* view_folder = dynamic_cast(obj); if (view_folder) { - update_inventory_category(mItemId, updates, NULL); + update_inventory_category(object_id, updates, NULL); } LLViewerInventoryItem* view_item = dynamic_cast(obj); if (view_item) { - update_inventory_item(mItemId, updates, NULL); + update_inventory_item(object_id, updates, NULL); } } } diff --git a/indra/newview/llfloaterchangeitemthumbnail.h b/indra/newview/llfloaterchangeitemthumbnail.h index 33bf2ecab5..de2a20bf2a 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.h +++ b/indra/newview/llfloaterchangeitemthumbnail.h @@ -95,6 +95,8 @@ private: void onTexturePickerCommit(LLUUID id); void setThumbnailId(const LLUUID &new_thumbnail_id); + static void setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id); + static void setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id, LLInventoryObject* obj); enum EToolTipState { From 505c15cf47c04e45f4a68790b5c63237a7bfcc9b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 23 May 2023 16:13:10 +0300 Subject: [PATCH 06/16] SL-19759 FIXED Adding New Folders in Single Folder view can cause all folders to open and shift out of view --- indra/llui/llfolderviewitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 4fbfa7ed79..7090156b4e 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1344,7 +1344,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem child_selected = TRUE; } } - if(openitem && child_selected) + if(openitem && child_selected && !mSingleFolderMode) { setOpenArrangeRecursively(TRUE); } From 572e8269bcd5320daa66f4074e927c79869bf7de Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 24 May 2023 22:51:02 +0300 Subject: [PATCH 07/16] SL-19604 Creating new folders in combination views does not highlight created item --- indra/llui/llfolderview.cpp | 15 +++++++++++---- indra/newview/llinventorypanel.cpp | 14 +++++++++++++- indra/newview/llinventorypanel.h | 2 ++ indra/newview/llpanelmaininventory.cpp | 22 ++++++++++------------ indra/newview/llpanelmaininventory.h | 13 +++++++------ 5 files changed, 43 insertions(+), 23 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 7831aa92fb..798c00d0ca 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -694,11 +694,18 @@ void LLFolderView::draw() } } - if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().overlaps(mRenamer->getRect())) + if (mRenameItem + && mRenamer + && mRenamer->getVisible()) { - // renamer is not connected to the item we are renaming in any form so manage it manually - // TODO: consider stopping on any scroll action instead of when out of visible area - finishRenamingItem(); + LLRect renamer_rect; + localRectToOtherView(mRenamer->getRect(), &renamer_rect, mScrollContainer); + if (!mScrollContainer->getRect().overlaps(renamer_rect)) + { + // renamer is not connected to the item we are renaming in any form so manage it manually + // TODO: consider stopping on any scroll action instead of when out of visible area + finishRenamingItem(); + } } // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 604bffb96e..2226384ba2 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2107,6 +2107,7 @@ static LLDefaultChildRegistry::Register t_single_f LLInventorySingleFolderPanel::LLInventorySingleFolderPanel(const Params& params) : LLInventoryPanel(params) + , mExternalScroller(NULL) { mBuildChildrenViews = false; getFilter().setSingleFolderMode(true); @@ -2235,7 +2236,18 @@ void LLInventorySingleFolderPanel::updateSingleFolderRoot() mScroller = LLUICtrlFactory::create(scroller_params); addChild(mScroller); mScroller->addChild(mFolderRoot.get()); - mFolderRoot.get()->setScrollContainer(mScroller); + if (!mExternalScroller) + { + mFolderRoot.get()->setScrollContainer(mScroller); + } + else + { + // Hack to use exteranl scroll in combination view + // Todo: find a way to avoid this + // ideally combination view should be own inventory panel + // instead of piggy backing on two different ones + mFolderRoot.get()->setScrollContainer(mExternalScroller); + } mFolderRoot.get()->setFollowsAll(); mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index f323a6c6d7..7b54a5bbf2 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -421,6 +421,7 @@ public: std::list getNavForwardList() { return mForwardFolders; } void setSelectCallback(const boost::function& items, BOOL user_action)>& cb); + void setScroller(LLScrollContainer* scroller) { mExternalScroller = scroller; } typedef boost::function root_changed_callback_t; boost::signals2::connection setRootChangedCallback(root_changed_callback_t cb); @@ -436,6 +437,7 @@ protected: LLUUID mFolderID; std::list mBackwardFolders; std::list mForwardFolders; + LLScrollContainer* mExternalScroller; boost::signals2::signal mRootChangedSignal; }; diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 5a8565b5aa..998a211795 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -256,7 +256,7 @@ BOOL LLPanelMainInventory::postBuild() mInventoryGalleryPanel = getChild("gallery_view_inv"); mGalleryRootUpdatedConnection = mInventoryGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this)); - mCombinationScrollPanel = getChild("combination_view_inventory"); + mCombinationScrollPanel = getChild("combination_view_inventory"); mCombinationInventoryPanel = getChild("comb_single_folder_inv"); LLInventoryFilter& comb_inv_filter = mCombinationInventoryPanel->getFilter(); @@ -264,6 +264,7 @@ BOOL LLPanelMainInventory::postBuild() comb_inv_filter.markDefault(); mCombinationInventoryPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onCombinationInventorySelectionChanged, this, _1, _2)); mCombinationInventoryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, false)); + mCombinationInventoryPanel->setScroller(mCombinationScrollPanel); mCombinationGalleryPanel = getChild("comb_gallery_view_inv"); LLInventoryFilter& comb_gallery_filter = mCombinationGalleryPanel->getFilter(); @@ -2326,6 +2327,11 @@ void LLPanelMainInventory::updateCombinationVisibility() { mCombinationShapeDirty = false; mCombinationInventoryPanel->reshape(1,1); // HACK: force reduce visible area + LLFolderView* root_folder = mCombinationInventoryPanel->getRootFolder(); + if (root_folder) + { + root_folder->arrangeAll(); + } } if (!mCombinationGalleryPanel->hasVisibleItems()) { @@ -2335,13 +2341,11 @@ void LLPanelMainInventory::updateCombinationVisibility() LLRect inv_inner_rect = mCombinationInventoryPanel->getScrollableContainer()->getScrolledViewRect(); LLRect galery_rect = mCombinationGalleryPanel->getRect(); LLRect inner_galery_rect = mCombinationGalleryPanel->getScrollableContainer()->getScrolledViewRect(); - LLScrollContainer* scroll = static_cast(mCombinationScrollPanel); - LLRect scroller_window_rect = scroll->getContentWindowRect(); + LLRect scroller_window_rect = mCombinationScrollPanel->getContentWindowRect(); const S32 BORDER_PAD = 2; // two sides - S32 desired_width = llmax(inv_inner_rect.getWidth(), scroller_window_rect.getWidth() - BORDER_PAD); inv_rect.mBottom = 0; - inv_rect.mRight = inv_rect.mLeft + desired_width; + inv_rect.mRight = inv_rect.mLeft + inv_inner_rect.getWidth(); if (!mCombinationGalleryPanel->hasVisibleItems() || mCombinationInventoryPanel->hasVisibleItems()) { inv_rect.mTop = inv_rect.mBottom + inv_inner_rect.getHeight() + BORDER_PAD; @@ -2364,7 +2368,7 @@ void LLPanelMainInventory::updateCombinationVisibility() galery_rect.mTop = galery_rect.mBottom; } - mCombinationScroller->reshape(desired_width, inv_rect.getHeight() + galery_rect.getHeight(), true); + mCombinationScroller->reshape(scroller_window_rect.getWidth(), inv_rect.getHeight() + galery_rect.getHeight(), true); mCombinationGalleryPanel->setShape(galery_rect, false); mCombinationInventoryPanel->setShape(inv_rect, false); @@ -2376,12 +2380,6 @@ void LLPanelMainInventory::updateCombinationVisibility() { scrollToInvPanelSelection(); } - - LLFolderView* root_folder = mCombinationInventoryPanel->getRootFolder(); - if (root_folder) - { - root_folder->updateRenamerPosition(); - } } } diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index bc010ff37f..2c3379996f 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -36,19 +36,20 @@ #include "llfolderview.h" class LLComboBox; -class LLFolderViewItem; class LLInventoryPanel; class LLInventoryGallery; -class LLSaveFolderState; class LLFilterEditor; -class LLTabContainer; +class LLFloater; class LLFloaterInventoryFinder; +class LLFloaterSidePanelContainer; +class LLFolderViewItem; class LLMenuButton; class LLMenuGL; +class LLSaveFolderState; +class LLScrollContainer; class LLSidepanelInventory; +class LLTabContainer; class LLToggleableMenu; -class LLFloater; -class LLFloaterSidePanelContainer; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLPanelMainInventory @@ -196,7 +197,7 @@ private: LLInventorySingleFolderPanel* mSingleFolderPanelInventory; LLInventoryGallery* mInventoryGalleryPanel; - LLUICtrl* mCombinationScrollPanel; + LLScrollContainer* mCombinationScrollPanel; LLInventorySingleFolderPanel* mCombinationInventoryPanel; LLInventoryGallery* mCombinationGalleryPanel; LLView* mCombinationScroller; From 67e17bd822f146f333b91d353df6f55174ce4db6 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 26 May 2023 19:45:46 +0300 Subject: [PATCH 08/16] SL-19774 add context menu for root folder (without any selection); show paste menu when right clicking any item --- indra/newview/llinventorygallery.cpp | 24 +++++++++++ indra/newview/llinventorygallery.h | 2 + indra/newview/llinventorygallerymenu.cpp | 54 ++++++++++++++---------- indra/newview/llinventorygallerymenu.h | 7 ++- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 18a7068b66..c6fee42297 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -126,12 +126,15 @@ BOOL LLInventoryGallery::postBuild() mGalleryPanel = LLUICtrlFactory::create(params); mMessageTextBox = getChild("empty_txt"); mInventoryGalleryMenu = new LLInventoryGalleryContextMenu(this); + mRootGalleryMenu = new LLInventoryGalleryContextMenu(this); + mRootGalleryMenu->setRootFolder(true); return TRUE; } LLInventoryGallery::~LLInventoryGallery() { delete mInventoryGalleryMenu; + delete mRootGalleryMenu; delete mFilter; while (!mUnusedRowPanels.empty()) @@ -837,6 +840,27 @@ void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) } } +BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if(mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setFocus(false); + } + clearSelection(); + BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (mSelectedItemID.isNull()) + { + if (mInventoryGalleryMenu && mFolderID.notNull()) + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(mFolderID); + mRootGalleryMenu->show(this, selected_uuids, x, y); + return TRUE; + } + } + return res; +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 473d1a1db4..7e4ed9725b 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -78,6 +78,7 @@ public: void draw(); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); void setFilterSubString(const std::string& string); std::string getFilterSubString() { return mFilterSubString; } @@ -204,6 +205,7 @@ private: int mGalleryWidthFactor; LLInventoryGalleryContextMenu* mInventoryGalleryMenu; + LLInventoryGalleryContextMenu* mRootGalleryMenu; std::string mFilterSubString; LLInventoryFilter* mFilter; diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 43ddf4da63..8a99b79e2b 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -159,6 +159,8 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU bool is_cut_mode = (LLClipboard::instance().isCutMode()); { + LLUUID dest = is_folder ? selected_id : obj->getParentUUID(); + std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) @@ -174,11 +176,11 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { if(is_cut_mode) { - gInventory.changeCategoryParent(cat, selected_id, false); + gInventory.changeCategoryParent(cat, dest, false); } else { - copy_inventory_category(&gInventory, cat, selected_id); + copy_inventory_category(&gInventory, cat, dest); } } else @@ -188,13 +190,13 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { if(is_cut_mode) { - gInventory.changeItemParent(item, selected_id, false); + gInventory.changeItemParent(item, dest, false); } else { if (item->getIsLinkType()) { - link_inventory_object(selected_id, item_id, + link_inventory_object(dest, item_id, LLPointer(NULL)); } else @@ -203,7 +205,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(), - selected_id, + dest, std::string(), LLPointer(NULL)); } @@ -264,7 +266,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { return; } - + LLUUID dest = is_folder ? selected_id : obj->getParentUUID(); std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); for (std::vector::const_iterator iter = objects.begin(); @@ -274,7 +276,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU const LLUUID &object_id = (*iter); if (LLConstPointer link_obj = gInventory.getObject(object_id)) { - link_inventory_object(selected_id, link_obj, LLPointer(NULL)); + link_inventory_object(dest, link_obj, LLPointer(NULL)); } } @@ -463,11 +465,14 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if (is_folder) { - items.push_back(std::string("Copy Separator")); + if(!isRootFolder()) + { + items.push_back(std::string("Copy Separator")); - items.push_back(std::string("open_in_current_window")); - items.push_back(std::string("open_in_new_window")); - items.push_back(std::string("Open Folder Separator")); + items.push_back(std::string("open_in_current_window")); + items.push_back(std::string("open_in_new_window")); + items.push_back(std::string("Open Folder Separator")); + } } else { @@ -512,18 +517,28 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { items.push_back(std::string("Share")); } + if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id)) + { + items.push_back(std::string("Paste")); + + static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); + if (inventory_linking) + { + items.push_back(std::string("Paste As Link")); + } + } if (is_folder && is_agent_inventory) { if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id)) { - if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD))) + if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD)) && !isRootFolder()) { items.push_back(std::string("New Folder")); } items.push_back(std::string("upload_def")); } - if(is_outfits) + if(is_outfits && !isRootFolder()) { items.push_back(std::string("New Outfit")); } @@ -531,6 +546,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("Subfolder Separator")); if (!is_system_folder) { + if(!isRootFolder()) + { if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) { items.push_back(std::string("Ungroup folder items")); @@ -542,21 +559,12 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } + } if(!is_inbox) { items.push_back(std::string("Rename")); } } - if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id)) - { - items.push_back(std::string("Paste")); - - static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); - if (inventory_linking) - { - items.push_back(std::string("Paste As Link")); - } - } if(!is_system_folder) { items.push_back(std::string("Copy")); diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h index 1768c07e6e..fd542e7d79 100644 --- a/indra/newview/llinventorygallerymenu.h +++ b/indra/newview/llinventorygallerymenu.h @@ -33,9 +33,13 @@ class LLInventoryGalleryContextMenu : public LLListContextMenu public: LLInventoryGalleryContextMenu(LLInventoryGallery* gallery) : LLListContextMenu(), - mGallery(gallery){} + mGallery(gallery), + mRootFolder(false){} /*virtual*/ LLContextMenu* createMenu(); + bool isRootFolder() { return mRootFolder; } + void setRootFolder(bool is_root) { mRootFolder = is_root; } + protected: //virtual void buildContextMenu(class LLMenuGL& menu, U32 flags); void updateMenuItemsVisibility(LLContextMenu* menu); @@ -50,6 +54,7 @@ private: bool checkContextMenuItem(const LLSD& userdata); LLInventoryGallery* mGallery; + bool mRootFolder; }; #endif From 8c9edebde752d69cfc120a1ddaf5dd7d6f6c27c4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 26 May 2023 23:02:54 +0300 Subject: [PATCH 09/16] SL-19604 Properly account for borders --- indra/newview/llpanelmaininventory.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 998a211795..39add4ee1c 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -2342,17 +2342,16 @@ void LLPanelMainInventory::updateCombinationVisibility() LLRect galery_rect = mCombinationGalleryPanel->getRect(); LLRect inner_galery_rect = mCombinationGalleryPanel->getScrollableContainer()->getScrolledViewRect(); LLRect scroller_window_rect = mCombinationScrollPanel->getContentWindowRect(); - const S32 BORDER_PAD = 2; // two sides inv_rect.mBottom = 0; - inv_rect.mRight = inv_rect.mLeft + inv_inner_rect.getWidth(); + inv_rect.mRight = inv_rect.mLeft + inv_inner_rect.getWidth() + mCombinationInventoryPanel->getScrollableContainer()->getBorderWidth(); if (!mCombinationGalleryPanel->hasVisibleItems() || mCombinationInventoryPanel->hasVisibleItems()) { - inv_rect.mTop = inv_rect.mBottom + inv_inner_rect.getHeight() + BORDER_PAD; + inv_rect.mTop = inv_rect.mBottom + inv_inner_rect.getHeight() + mCombinationInventoryPanel->getScrollableContainer()->getBorderWidth(); } else { - inv_rect.mTop = inv_rect.mBottom; + inv_rect.mTop = inv_rect.mBottom + mCombinationInventoryPanel->getScrollableContainer()->getBorderWidth(); } galery_rect.mBottom = inv_rect.mTop; @@ -2360,12 +2359,12 @@ void LLPanelMainInventory::updateCombinationVisibility() if (mCombinationGalleryPanel->hasVisibleItems()) { mCombinationGalleryPanel->setVisible(true); - galery_rect.mTop = galery_rect.mBottom + inner_galery_rect.getHeight() + BORDER_PAD; + galery_rect.mTop = galery_rect.mBottom + inner_galery_rect.getHeight() + mCombinationGalleryPanel->getScrollableContainer()->getBorderWidth(); } else { mCombinationGalleryPanel->setVisible(false); - galery_rect.mTop = galery_rect.mBottom; + galery_rect.mTop = galery_rect.mBottom + mCombinationGalleryPanel->getScrollableContainer()->getBorderWidth(); } mCombinationScroller->reshape(scroller_window_rect.getWidth(), inv_rect.getHeight() + galery_rect.getHeight(), true); From 352ca2f881b02bd455d0f191d93737d3dc3dd52d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 22:47:31 +0300 Subject: [PATCH 10/16] SL-19652 Folder fetch dupplicate protection and over limit handling --- .../llinventorymodelbackgroundfetch.cpp | 73 +++++++++++++++---- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 8f1012868f..b0ebe83f57 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -945,6 +945,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() // *TODO: Think I'd like to get a shared pointer to this and share it // among all the folder requests. uuid_vec_t recursive_cats; + uuid_vec_t all_cats; // dupplicate avoidance LLSD folder_request_body; LLSD folder_request_body_lib; @@ -976,22 +977,25 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) { - LLSD folder_sd; - folder_sd["folder_id"] = cat->getUUID(); - folder_sd["owner_id"] = cat->getOwnerID(); - folder_sd["sort_order"] = LLSD::Integer(sort_order); - folder_sd["fetch_folders"] = LLSD::Boolean(true); //(LLSD::Boolean)sFullFetchStarted; - folder_sd["fetch_items"] = LLSD::Boolean(true); + if (std::find(all_cats.begin(), all_cats.end(), cat_id) == all_cats.end()) + { + LLSD folder_sd; + folder_sd["folder_id"] = cat->getUUID(); + folder_sd["owner_id"] = cat->getOwnerID(); + folder_sd["sort_order"] = LLSD::Integer(sort_order); + folder_sd["fetch_folders"] = LLSD::Boolean(TRUE); //(LLSD::Boolean)sFullFetchStarted; + folder_sd["fetch_items"] = LLSD::Boolean(TRUE); - if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) - { - folder_request_body_lib["folders"].append(folder_sd); + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + { + folder_request_body_lib["folders"].append(folder_sd); + } + else + { + folder_request_body["folders"].append(folder_sd); + } + folder_count++; } - else - { - folder_request_body["folders"].append(folder_sd); - } - folder_count++; } else { @@ -1015,6 +1019,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { recursive_cats.push_back(cat_id); } + all_cats.push_back(cat_id); } mFetchFolderQueue.pop_front(); @@ -1349,6 +1354,46 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; // Could use a 404 test here to try to detect revoked caps... + + if(status == LLCore::HttpStatus(HTTP_FORBIDDEN)) + { + // too large, split into two, assume that this isn't the library + const std::string url(gAgent.getRegionCapability("FetchInventoryDescendents2")); + S32 size = mRequestSD["folders"].size(); + + if (!gDisconnected && !LLApp::isExiting() && !url.empty() && size > 1) + { + LLSD folders; + uuid_vec_t recursive_cats; + LLSD::array_iterator iter = mRequestSD["folders"].beginArray(); + LLSD::array_iterator end = mRequestSD["folders"].endArray(); + while (iter != end) + { + folders.append(*iter); + LLUUID fodler_id = iter->get("folder_id").asUUID(); + if (std::find(mRecursiveCatUUIDs.begin(), mRecursiveCatUUIDs.end(), fodler_id) != mRecursiveCatUUIDs.end()) + { + recursive_cats.push_back(fodler_id); + } + if (folders.size() == (S32)(size / 2)) + { + LLSD request_body; + request_body["folders"] = folders; + LLCore::HttpHandler::ptr_t handler(new BGFolderHttpHandler(request_body, recursive_cats)); + gInventory.requestPost(false, url, request_body, handler, "Inventory Folder"); + recursive_cats.clear(); + folders.clear(); + } + iter++; + } + + LLSD request_body; + request_body["folders"] = folders; + LLCore::HttpHandler::ptr_t handler(new BGFolderHttpHandler(request_body, recursive_cats)); + gInventory.requestPost(false, url, request_body, handler, "Inventory Folder"); + return; + } + } // This was originally the request retry logic for the inventory // request which tested on HTTP_INTERNAL_ERROR status. This From b9fad316a356fd223dcf29ed000de1b86e6a93d3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 29 May 2023 23:37:58 +0300 Subject: [PATCH 11/16] SL-17429 Message user when their inventory hits AIS2 limits --- .../llinventorymodelbackgroundfetch.cpp | 22 +++++++++++++++++-- .../skins/default/xui/en/notifications.xml | 8 +++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index b0ebe83f57..0eb07523ae 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -34,6 +34,7 @@ #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" +#include "llnotificationsutil.h" #include "llstartup.h" #include "llviewercontrol.h" #include "llviewerinventory.h" @@ -1357,12 +1358,24 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http if(status == LLCore::HttpStatus(HTTP_FORBIDDEN)) { - // too large, split into two, assume that this isn't the library + // Too large, split into two if possible + if (gDisconnected || LLApp::isExiting()) + { + return; + } + const std::string url(gAgent.getRegionCapability("FetchInventoryDescendents2")); + if (url.empty()) + { + LL_WARNS(LOG_INV) << "Failed to get AIS2 cap" << LL_ENDL; + return; + } + S32 size = mRequestSD["folders"].size(); - if (!gDisconnected && !LLApp::isExiting() && !url.empty() && size > 1) + if (size > 1) { + // Can split, assume that this isn't the library LLSD folders; uuid_vec_t recursive_cats; LLSD::array_iterator iter = mRequestSD["folders"].beginArray(); @@ -1393,6 +1406,11 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http gInventory.requestPost(false, url, request_body, handler, "Inventory Folder"); return; } + else + { + // Can't split + LLNotificationsUtil::add("InventoryLimitReachedAIS"); + } } // This was originally the request retry logic for the inventory diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e8fdc84fae..4c8d7fbd83 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6440,6 +6440,14 @@ Your trash is overflowing. This may cause problems logging in. yestext="Check trash folder"/> + +Your inventory is experiencing issues. Please, contact support. + fail + + Date: Tue, 30 May 2023 00:01:58 +0300 Subject: [PATCH 12/16] SL-17429 Message user when their inventory hits AIS3 limits --- indra/newview/llaisapi.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index b09b8ec517..fcee3a3e91 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -32,11 +32,12 @@ #include "llappviewer.h" #include "llcallbacklist.h" #include "llinventorymodel.h" +#include "llinventoryobserver.h" +#include "llnotificationsutil.h" #include "llsdutil.h" #include "llviewerregion.h" #include "llvoavatar.h" #include "llvoavatarself.h" -#include "llinventoryobserver.h" #include "llviewercontrol.h" ///---------------------------------------------------------------------------- @@ -893,11 +894,21 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } } } - else if (status.getType() == 403) + else if (status == LLCore::HttpStatus(HTTP_FORBIDDEN) /*403*/) { if (type == FETCHCATEGORYCHILDREN) { - LL_DEBUGS("Inventory") << "Fetch failed, content is over imit" << LL_ENDL; + if (body.has("depth") && body["depth"].asInteger() == 0) + { + // Can't fetch a single folder with depth 0, folder is too big. + LLNotificationsUtil::add("InventoryLimitReachedAIS"); + LL_WARNS("Inventory") << "Fetch failed, content is over limit, url: " << url << LL_ENDL; + } + else + { + // Result was too big, but situation is recoverable by requesting with lower depth + LL_DEBUGS("Inventory") << "Fetch failed, content is over limit, url: " << url << LL_ENDL; + } } } LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL; From 5c55adae47cab93a12793528373f639ea9e8efcf Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 30 May 2023 13:10:36 +0300 Subject: [PATCH 13/16] SL-19773 add context menu for root folder in single folder mode --- indra/llui/llfolderview.cpp | 12 +++++++++--- indra/llui/llfolderview.h | 6 +++++- indra/newview/llinventorybridge.cpp | 20 ++++++++++++++++---- indra/newview/llinventoryfunctions.cpp | 8 ++++++++ indra/newview/llinventorygallerymenu.cpp | 6 ++---- indra/newview/llinventorypanel.cpp | 17 ++++++++++++++++- indra/newview/llinventorypanel.h | 1 + 7 files changed, 57 insertions(+), 13 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 798c00d0ca..f0106e345c 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -190,7 +190,8 @@ LLFolderView::LLFolderView(const Params& p) mShowItemLinkOverlays(p.show_item_link_overlays), mViewModel(p.view_model), mGroupedItemModel(p.grouped_item_model), - mForceArrange(false) + mForceArrange(false), + mSingleFolderMode(false) { LLPanel* panel = p.parent_panel; mParentPanel = panel->getHandle(); @@ -1475,8 +1476,8 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) } } bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if (menu && (handled - && ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible + if (menu && (mSingleFolderMode || (handled + && ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible !hide_folder_menu) { if (mCallbackRegistrar) @@ -1918,6 +1919,11 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + if(mSingleFolderMode && (mSelectedItems.size() == 0)) + { + buildContextMenu(*menu, flags); + } + // This adds a check for restrictions based on the entire // selection set - for example, any one wearable may not push you // over the limit, but all wearables together still might. diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 73028f31b1..ed84b29fd9 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -127,6 +127,9 @@ public: bool getAllowMultiSelect() { return mAllowMultiSelect; } bool getAllowDrag() { return mAllowDrag; } + void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; } + bool isSingleFolderMode() { return mSingleFolderMode; } + // Close all folders in the view void closeAllFolders(); void openTopLevelFolders(); @@ -300,7 +303,8 @@ protected: mShowItemLinkOverlays, mShowSelectionContext, mShowSingleSelection, - mSuppressFolderMenu; + mSuppressFolderMenu, + mSingleFolderMode; // Renaming variables and methods LLFolderViewItem* mRenameItem; // The item currently being renamed diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1c8342cdda..3c1e58205a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -791,6 +791,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, menuentry_vec_t &disabled_items, U32 flags) { const LLInventoryObject *obj = getInventoryObject(); + bool single_folder_root = (mRoot == NULL); if (obj) { @@ -802,7 +803,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } - if (isAgentInventory()) + if (isAgentInventory() && !single_folder_root) { items.push_back(std::string("New folder from selected")); items.push_back(std::string("Subfolder Separator")); @@ -836,7 +837,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, items.push_back(std::string("Find Links")); } - if (!isInboxFolder()) + if (!isInboxFolder() && !single_folder_root) { items.push_back(std::string("Rename")); if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) @@ -870,6 +871,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } + if(!single_folder_root) + { items.push_back(std::string("Cut")); if (!isItemMovable() || !isItemRemovable()) { @@ -891,6 +894,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } } + } } } @@ -916,7 +920,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, items.push_back(std::string("Paste Separator")); - addDeleteContextMenuOptions(items, disabled_items); + if(!single_folder_root) + { + addDeleteContextMenuOptions(items, disabled_items); + } if (!isPanelActive("All Items") && !isPanelActive("single_folder_inv") && !isPanelActive("comb_single_folder_inv")) { @@ -4382,7 +4389,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& const bool is_agent_inventory = isAgentInventory(); // Only enable calling-card related options for non-system folders. - if (!is_system_folder && is_agent_inventory) + if (!is_system_folder && is_agent_inventory && (mRoot != NULL)) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) @@ -4402,6 +4409,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& disabled_items.push_back(std::string("New folder from selected")); } + //skip the rest options in single-folder mode + if (mRoot == NULL) + { + return; + } if ((flags & ITEM_IN_MULTI_SELECTION) == 0) { diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index b934ccd22b..a259dad08a 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -3194,6 +3194,14 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if(!bridge) continue; bridge->performAction(model, action); } + if(root->isSingleFolderMode() && selected_items.empty()) + { + LLInvFVBridge* bridge = (LLInvFVBridge*)root->getViewModelItem(); + if(bridge) + { + bridge->performAction(model, action); + } + } } // Update the marketplace listings that have been affected by the operation diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 8a99b79e2b..6dc749fab6 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -544,10 +544,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } items.push_back(std::string("Subfolder Separator")); - if (!is_system_folder) + if (!is_system_folder && !isRootFolder()) { - if(!isRootFolder()) - { if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) { items.push_back(std::string("Ungroup folder items")); @@ -559,7 +557,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } - } + if(!is_inbox) { items.push_back(std::string("Rename")); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 2226384ba2..bd15e55b9a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2116,6 +2116,7 @@ LLInventorySingleFolderPanel::LLInventorySingleFolderPanel(const Params& params) mCommitCallbackRegistrar.add("Inventory.OpenSelectedFolder", boost::bind(&LLInventorySingleFolderPanel::openInCurrentWindow, this, _2)); mCommitCallbackRegistrar.replace("Inventory.DoCreate", boost::bind(&LLInventorySingleFolderPanel::doCreate, this, _2)); + mCommitCallbackRegistrar.replace("Inventory.Share", boost::bind(&LLInventorySingleFolderPanel::doShare, this)); } LLInventorySingleFolderPanel::~LLInventorySingleFolderPanel() @@ -2138,6 +2139,7 @@ void LLInventorySingleFolderPanel::initFromParams(const Params& p) pane_params.open_first_folder = false; pane_params.start_folder.id = mFolderID; LLInventoryPanel::initFromParams(pane_params); + mFolderRoot.get()->setSingleFolderMode(true); } void LLInventorySingleFolderPanel::openInCurrentWindow(const LLSD& userdata) @@ -2219,7 +2221,7 @@ void LLInventorySingleFolderPanel::updateSingleFolderRoot() LLFolderView* folder_view = createFolderRoot(root_id); folder_view->setChildrenInited(false); mFolderRoot = folder_view->getHandle(); - + mFolderRoot.get()->setSingleFolderMode(true); addItemID(root_id, mFolderRoot.get()); LLRect scroller_view_rect = getRect(); @@ -2285,6 +2287,19 @@ void LLInventorySingleFolderPanel::doCreate(const LLSD& userdata) reset_inventory_filter(); menu_create_inventory_item(this, dest_id, userdata); } + +void LLInventorySingleFolderPanel::doShare() +{ + if(mFolderRoot.get()->getCurSelectedItem() == NULL) + { + std::set uuids{mFolderID}; + LLAvatarActions::shareWithAvatars(uuids, gFloaterView->getParentFloater(this)); + } + else + { + LLAvatarActions::shareWithAvatars(this); + } +} /************************************************************************/ /* Asset Pre-Filtered Inventory Panel related class */ /************************************************************************/ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 7b54a5bbf2..2754d79fbe 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -409,6 +409,7 @@ public: LLUUID getSingleFolderRoot() { return mFolderID; } void doCreate(const LLSD& userdata); + void doShare(); bool isBackwardAvailable(); bool isForwardAvailable(); From caa21f9054c51eea6557c9f0d080d91e43e44018 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 30 May 2023 22:08:51 +0300 Subject: [PATCH 14/16] SL-19748 Thumbnail to clipboard not working --- indra/newview/llfloaterchangeitemthumbnail.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp index 1ac6ee72bf..c3392889fb 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.cpp +++ b/indra/newview/llfloaterchangeitemthumbnail.cpp @@ -468,6 +468,7 @@ void LLFloaterChangeItemThumbnail::onCopyToClipboard(void *userdata) LLInventoryObject* obj = self->getInventoryObject(); if (obj) { + LLClipboard::instance().reset(); LLClipboard::instance().addToClipboard(obj->getThumbnailUUID(), LLAssetType::AT_NONE); self->mPasteFromClipboardBtn->setEnabled(true); } From 1834cc1a8be0b4519d774ca52202677ccaf40933 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 31 May 2023 00:17:36 +0300 Subject: [PATCH 15/16] SL-19795 Creating folders in combination mode does not scroll to new folder --- indra/newview/llinventorypanel.cpp | 9 +++++++++ indra/newview/llinventorypanel.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index bd15e55b9a..9827fa8c5c 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2132,6 +2132,15 @@ void LLInventorySingleFolderPanel::setSelectCallback(const boost::functionsetScrollContainer(mExternalScroller); + } +} + void LLInventorySingleFolderPanel::initFromParams(const Params& p) { mFolderID = gInventory.getRootFolderID(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 2754d79fbe..8d3edebcb4 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -422,7 +422,7 @@ public: std::list getNavForwardList() { return mForwardFolders; } void setSelectCallback(const boost::function& items, BOOL user_action)>& cb); - void setScroller(LLScrollContainer* scroller) { mExternalScroller = scroller; } + void setScroller(LLScrollContainer* scroller); typedef boost::function root_changed_callback_t; boost::signals2::connection setRootChangedCallback(root_changed_callback_t cb); From a6efb920e8e0d9add76ec86c3ed158c691685727 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 31 May 2023 01:09:57 +0300 Subject: [PATCH 16/16] SL-19795 Creating folders in combination mode does not scroll to new folder #2 --- indra/newview/llinventorygallery.cpp | 3 ++- indra/newview/llpanelmaininventory.cpp | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c6fee42297..2f9f594790 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -183,7 +183,8 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) void LLInventoryGallery::updateRootFolder() { - if (mIsInitialized) + llassert(mFolderID.notNull()); + if (mIsInitialized && mFolderID.notNull()) { S32 count = mItemsAddedCount; for (S32 i = count - 1; i >= 0; i--) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 39add4ee1c..381506c2a6 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1011,9 +1011,12 @@ void LLPanelMainInventory::updateItemcountText() gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items); - string_args["[ITEM_COUNT]"] = llformat("%d", items->size()); - string_args["[CATEGORY_COUNT]"] = llformat("%d", cats->size()); - text = getString("ItemcountCompleted", string_args); + if (items && cats) + { + string_args["[ITEM_COUNT]"] = llformat("%d", items->size()); + string_args["[CATEGORY_COUNT]"] = llformat("%d", cats->size()); + text = getString("ItemcountCompleted", string_args); + } } mCounterCtrl->setValue(text); @@ -1532,6 +1535,13 @@ void LLPanelMainInventory::toggleViewMode() } mSingleFolderMode = !mSingleFolderMode; + mCombinationShapeDirty = true; + + if (mCombinationGalleryPanel->getRootFolder().isNull()) + { + mCombinationGalleryPanel->setRootFolder(mCombinationInventoryPanel->getSingleFolderRoot()); + mCombinationGalleryPanel->updateRootFolder(); + } getChild("default_inventory_panel")->setVisible(!mSingleFolderMode); getChild("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode());