From 449f64caa2e1f62ab24e02465faadd0f02ac3023 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Mon, 13 Oct 2025 16:19:33 +0300 Subject: #2818 Creating a link to an empty notecard fails --- indra/newview/llinventorybridge.cpp | 26 ++++++++++++++++ indra/newview/llinventorygallery.cpp | 24 +++++++++++++++ indra/newview/llinventorygallerymenu.cpp | 35 ++++++++++++++++------ .../newview/skins/default/xui/en/notifications.xml | 16 ++++++++++ 4 files changed, 92 insertions(+), 9 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1e6c5cf04a..e322d3ae28 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4390,6 +4390,32 @@ void LLFolderBridge::pasteLinkFromClipboard() std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); + if (objects.size() == 0) + { + LLClipboard::instance().setCutMode(false); + return; + } + + LLUUID& first_id = objects[0]; + LLInventoryItem* item = model->getItem(first_id); + if (item && item->getAssetUUID().isNull()) + { + if (item->getActualType() == LLAssetType::AT_NOTECARD) + { + // otehrwise AIS will return 'Cannot link to items with a NULL asset_id.' + LLNotificationsUtil::add("CantLinkNotecard"); + LLClipboard::instance().setCutMode(false); + return; + } + else if (item->getActualType() == LLAssetType::AT_MATERIAL) + { + LLNotificationsUtil::add("CantLinkMaterial"); + LLClipboard::instance().setCutMode(false); + return; + } + } + + LLPointer cb = NULL; LLInventoryPanel* panel = mInventoryPanel.get(); if (panel->getRootFolder()->isSingleFolderMode()) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index a4cb6ea65d..c54af7d9f1 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2120,6 +2120,30 @@ void LLInventoryGallery::pasteAsLink() std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); + if (objects.size() == 0) + { + LLClipboard::instance().setCutMode(false); + return; + } + + LLUUID& first_id = objects[0]; + LLInventoryItem* item = gInventory.getItem(first_id); + if (item && item->getAssetUUID().isNull()) + { + if (item->getActualType() == LLAssetType::AT_NOTECARD) + { + LLNotificationsUtil::add("CantLinkNotecard"); + LLClipboard::instance().setCutMode(false); + return; + } + else if (item->getActualType() == LLAssetType::AT_MATERIAL) + { + LLNotificationsUtil::add("CantLinkMaterial"); + LLClipboard::instance().setCutMode(false); + return; + } + } + bool paste_into_root = mSelectedItemIDs.empty(); for (LLUUID& dest : mSelectedItemIDs) { diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index e129a1296a..eda93e3e79 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -603,20 +603,23 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men bool has_children = false; bool is_full_perm_item = false; bool is_copyable = false; - LLViewerInventoryItem* selected_item = gInventory.getItem(selected_id); + + LLViewerInventoryCategory* selected_category = nullptr; + LLViewerInventoryItem* selected_item = nullptr; if(is_folder) { - LLInventoryCategory* category = gInventory.getCategory(selected_id); - if (category) + selected_category = dynamic_cast(obj); + if (selected_category) { - folder_type = category->getPreferredType(); + folder_type = selected_category->getPreferredType(); is_system_folder = LLFolderType::lookupIsProtectedType(folder_type); has_children = (gInventory.categoryHasChildren(selected_id) != LLInventoryModel::CHILDREN_NO); } } else { + selected_item = dynamic_cast(obj); if (selected_item) { is_full_perm_item = selected_item->getIsFullPerm(); @@ -735,8 +738,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits && !is_in_outfits) { - LLViewerInventoryCategory* category = gInventory.getCategory(selected_id); - if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category)) + if (!selected_category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(selected_category)) { items.push_back(std::string("New Folder")); } @@ -764,6 +766,22 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if (inventory_linking) { items.push_back(std::string("Paste As Link")); + + if (selected_item) + { + if (!LLAssetType::lookupCanLink(selected_item->getActualType())) + { + disabled_items.push_back(std::string("Paste As Link")); + } + else if (gInventory.isObjectDescendentOf(selected_item->getUUID(), gInventory.getLibraryRootFolderID())) + { + disabled_items.push_back(std::string("Paste As Link")); + } + } + else if (selected_category && LLFolderType::lookupIsProtectedType(selected_category->getPreferredType())) + { + disabled_items.push_back(std::string("Paste As Link")); + } } } if (is_folder && is_agent_inventory) @@ -1020,9 +1038,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { if (is_folder) { - LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); - if (cat - && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) + if (selected_category + && !LLFolderType::lookupIsProtectedType(selected_category->getPreferredType()) && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID())) { can_list = true; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 69df05f6c2..b8c573221d 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6594,6 +6594,22 @@ Do you want to replace it with the selected object? fail + + You must save the notecard before creating a link to it. + fail + + + + You must save the material before creating a link to it. + fail + +