From 811da7dbb1bdbf04a2dceb02ad4d296db4274076 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 7 Mar 2023 22:39:36 +0200 Subject: SL-18629 WIP Replacing UDP creation messages with callback based AIS #2 findCategory and move_item_to_marketplacelistings --- indra/newview/llstartup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6883ead5ee..776b9f8279 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2768,7 +2768,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, // Not going through the processAgentInitialWearables path, so need to set this here. LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); // Initiate creation of COF, since we're also bypassing that. - gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); ESex gender; if (gender_name == "male") -- cgit v1.3 From ac145cb21f382b8eab9f770cecfa23ea9d58aac6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 14 Mar 2023 23:21:26 +0200 Subject: SL-18629 WIP Fetch Inventory using AIS caps --- indra/newview/llaisapi.cpp | 42 ++++- indra/newview/llaisapi.h | 4 +- indra/newview/llinventoryfilter.cpp | 2 +- indra/newview/llinventorymodel.cpp | 13 -- indra/newview/llinventorymodel.h | 3 - indra/newview/llinventorymodelbackgroundfetch.cpp | 214 ++++++++++++++++++---- indra/newview/llinventorymodelbackgroundfetch.h | 47 ++--- indra/newview/llstartup.cpp | 1 + indra/newview/llviewerinventory.cpp | 2 +- 9 files changed, 242 insertions(+), 86 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index afc307278c..87811e9c0b 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -33,6 +33,8 @@ #include "llinventorymodel.h" #include "llsdutil.h" #include "llviewerregion.h" +#include "llvoavatar.h" +#include "llvoavatarself.h" #include "llinventoryobserver.h" #include "llviewercontrol.h" @@ -409,6 +411,7 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + callback(LLUUID::null); return; } std::string url = cap + std::string("/category/") + catId.asString() + "/children"; @@ -565,6 +568,24 @@ void AISAPI::onIdle(void *userdata) } } +/*static*/ +void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type) +{ + LLTimer timer; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); + } + bool is_fetch = (type == FETCHITEM) + || (type == FETCHCATEGORYCHILDREN) + || (type == FETCHCATEGORYCATEGORIES) + || (type == FETCHCOF); + // parse update llsd into stuff to do or parse received items. + AISUpdate ais_update(update, is_fetch); + ais_update.doUpdate(); // execute the updates in the appropriate order. + LL_INFOS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; +} + /*static*/ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter, invokationFn_t invoke, std::string url, @@ -659,7 +680,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } LL_DEBUGS("Inventory") << result << LL_ENDL; - gInventory.onAISUpdateReceived("AISCommand", result); + onUpdateReceived("AISCommand", result, type); if (callback && !callback.empty()) { @@ -708,7 +729,8 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } //------------------------------------------------------------------------- -AISUpdate::AISUpdate(const LLSD& update) +AISUpdate::AISUpdate(const LLSD& update, bool fetch) +: mFetch(fetch) { parseUpdate(update); } @@ -849,7 +871,7 @@ void AISUpdate::parseItem(const LLSD& item_map) BOOL rv = new_item->unpackMessage(item_map); if (rv) { - if (curr_item) + if (!mFetch && curr_item) { mItemsUpdated[item_id] = new_item; // This statement is here to cause a new entry with 0 @@ -884,7 +906,7 @@ void AISUpdate::parseLink(const LLSD& link_map) if (rv) { const LLUUID& parent_id = new_link->getParentUUID(); - if (curr_link) + if (!mFetch && curr_link) { mItemsUpdated[item_id] = new_link; // This statement is here to cause a new entry with 0 @@ -951,7 +973,7 @@ void AISUpdate::parseCategory(const LLSD& category_map) //} if (rv) { - if (curr_cat) + if (curr_cat && !mFetch) { mCategoriesUpdated[category_id] = new_cat; // This statement is here to cause a new entry with 0 @@ -1054,7 +1076,7 @@ void AISUpdate::parseEmbeddedLinks(const LLSD& links) { const LLUUID link_id((*linkit).first); const LLSD& link_map = (*linkit).second; - if (mItemIds.end() == mItemIds.find(link_id)) + if (!mFetch && mItemIds.end() == mItemIds.find(link_id)) { LL_DEBUGS("Inventory") << "Ignoring link not in items list " << link_id << LL_ENDL; } @@ -1070,7 +1092,7 @@ void AISUpdate::parseEmbeddedItem(const LLSD& item) // a single item (_embedded in a link) if (item.has("item_id")) { - if (mItemIds.end() != mItemIds.find(item["item_id"].asUUID())) + if (mFetch || mItemIds.end() != mItemIds.find(item["item_id"].asUUID())) { parseItem(item); } @@ -1086,7 +1108,7 @@ void AISUpdate::parseEmbeddedItems(const LLSD& items) { const LLUUID item_id((*itemit).first); const LLSD& item_map = (*itemit).second; - if (mItemIds.end() == mItemIds.find(item_id)) + if (!mFetch && mItemIds.end() == mItemIds.find(item_id)) { LL_DEBUGS("Inventory") << "Ignoring item not in items list " << item_id << LL_ENDL; } @@ -1102,7 +1124,7 @@ void AISUpdate::parseEmbeddedCategory(const LLSD& category) // a single category (_embedded in a link) if (category.has("category_id")) { - if (mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID())) + if (mFetch || mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID())) { parseCategory(category); } @@ -1118,7 +1140,7 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories) { const LLUUID category_id((*categoryit).first); const LLSD& category_map = (*categoryit).second; - if (mCategoryIds.end() == mCategoryIds.find(category_id)) + if (!mFetch && mCategoryIds.end() == mCategoryIds.find(category_id)) { LL_DEBUGS("Inventory") << "Ignoring category not in categories list " << category_id << LL_ENDL; } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index b21edb9f33..3de3366a0e 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -86,6 +86,7 @@ private: static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc); static void onIdle(void *userdata); // launches postponed AIS commands + static void onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type); static std::string getInvCap(); static std::string getLibCap(); @@ -101,7 +102,7 @@ private: class AISUpdate { public: - AISUpdate(const LLSD& update); + AISUpdate(const LLSD& update, bool fetch); void parseUpdate(const LLSD& update); void parseMeta(const LLSD& update); void parseContent(const LLSD& update); @@ -137,6 +138,7 @@ private: uuid_list_t mObjectsDeletedIds; uuid_list_t mItemIds; uuid_list_t mCategoryIds; + bool mFetch; }; #endif diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index d6110b3cd5..6e09161473 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -202,7 +202,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { // At the moment background fetch only cares about VERSION_UNKNOWN, // so do not check isCategoryComplete that compares descendant count - LLInventoryModelBackgroundFetch::instance().start(folder_id); + LLInventoryModelBackgroundFetch::instance().start(folder_id, false); } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ee0dd2422a..65690228e7 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1754,19 +1754,6 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } -void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) -{ - LLTimer timer; - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); - } - - AISUpdate ais_update(update); // parse update llsd into stuff to do. - ais_update.doUpdate(); // execute the updates in the appropriate order. - LL_INFOS(LOG_INV) << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; -} - // Does not appear to be used currently. void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 3fbf8924b5..5e4319bb12 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -411,9 +411,6 @@ public: // Delete //-------------------------------------------------------------------- public: - - // Update model after an AISv3 update received for any operation. - void onAISUpdateReceived(const std::string& context, const LLSD& update); // Update model after an item is confirmed as removed from // server. Works for categories or items. diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 406c8b89d0..1905a9c9a4 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llinventorymodelbackgroundfetch.h" +#include "llaisapi.h" #include "llagent.h" #include "llappviewer.h" #include "llcallbacklist.h" @@ -184,12 +185,12 @@ const char * const LOG_INV("Inventory"); ///---------------------------------------------------------------------------- LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch(): - mBackgroundFetchActive(FALSE), + mBackgroundFetchActive(false), mFolderFetchActive(false), mFetchCount(0), - mAllFoldersFetched(FALSE), - mRecursiveInventoryFetchStarted(FALSE), - mRecursiveLibraryFetchStarted(FALSE), + mAllFoldersFetched(false), + mRecursiveInventoryFetchStarted(false), + mRecursiveLibraryFetchStarted(false), mMinTimeBetweenFetches(0.3f) {} @@ -241,17 +242,17 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const return mFolderFetchActive; } -void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category) +void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, bool recursive, bool is_category) { mFetchQueue.push_front(FetchQueueInfo(id, recursive, is_category)); } -void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category) +void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, bool recursive, bool is_category) { mFetchQueue.push_back(FetchQueueInfo(id, recursive, is_category)); } -void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) +void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) { LLViewerInventoryCategory * cat(gInventory.getCategory(id)); @@ -260,31 +261,57 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) // it's a folder, do a bulk fetch LL_DEBUGS(LOG_INV) << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; - mBackgroundFetchActive = TRUE; + mBackgroundFetchActive = true; mFolderFetchActive = true; if (id.isNull()) { if (! mRecursiveInventoryFetchStarted) { mRecursiveInventoryFetchStarted |= recursive; - mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + if (recursive && AISAPI::isAvailable()) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + } + else + { + mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + } gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } if (! mRecursiveLibraryFetchStarted) { mRecursiveLibraryFetchStarted |= recursive; - mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + if (recursive && AISAPI::isAvailable()) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + } + else + { + mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + } gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } else { - // Specific folder requests go to front of queue. - if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) - { - mFetchQueue.push_front(FetchQueueInfo(id, recursive)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); - } + if (recursive && AISAPI::isAvailable()) + { + // AIS does depth requests, recursive requests will need to be prioritizes + if (mRecursiveFetchQueue.empty() || mRecursiveFetchQueue.back().mUUID != id) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo(id, recursive)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + } + else + { + // Specific folder requests go to front of queue. + if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) + { + mFetchQueue.push_front(FetchQueueInfo(id, recursive)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + } if (id == gInventory.getLibraryRootFolderID()) { mRecursiveLibraryFetchStarted |= recursive; @@ -299,7 +326,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { if (! itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)) { - mBackgroundFetchActive = TRUE; + mBackgroundFetchActive = true; mFetchQueue.push_front(FetchQueueInfo(id, false, false)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); @@ -309,9 +336,9 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) void LLInventoryModelBackgroundFetch::findLostItems() { - mBackgroundFetchActive = TRUE; + mBackgroundFetchActive = true; mFolderFetchActive = true; - mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE)); + mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, true)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } @@ -320,7 +347,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() if (mRecursiveInventoryFetchStarted && mRecursiveLibraryFetchStarted) { - mAllFoldersFetched = TRUE; + mAllFoldersFetched = true; //LL_INFOS(LOG_INV) << "All folders fetched, validating" << LL_ENDL; //gInventory.validate(); } @@ -338,8 +365,15 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() { if (mBackgroundFetchActive && gAgent.getRegion() && gAgent.getRegion()->capabilitiesReceived()) { - // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. - bulkFetch(); + if (AISAPI::isAvailable()) + { + bulkFetchViaAis(); + } + else + { + // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. + bulkFetch(); + } } } @@ -352,9 +386,118 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching) mFetchCount = 0; } } +void ais_callback(const LLUUID& inv_id) +{ + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); +} static LLTrace::BlockTimerStatHandle FTM_BULK_FETCH("Bulk Fetch"); +void LLInventoryModelBackgroundFetch::bulkFetchViaAis() +{ + LL_RECORD_BLOCK_TIME(FTM_BULK_FETCH); + //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. + if (gDisconnected) + { + return; + } + + static const S32 max_concurrent_fetches(12); + + if (mFetchCount >= max_concurrent_fetches) + { + return; + } + + // Start with recursive queue since it can get multiple categories + // in a single request and might contain what other requests want + while (!mRecursiveFetchQueue.empty() && mFetchCount < max_concurrent_fetches) + { + const FetchQueueInfo & fetch_info(mRecursiveFetchQueue.front()); + bulkFetchViaAis(fetch_info); + mRecursiveFetchQueue.pop_front(); + } + + while (!mFetchQueue.empty() && mFetchCount < max_concurrent_fetches) + { + const FetchQueueInfo & fetch_info(mFetchQueue.front()); + bulkFetchViaAis(fetch_info); + mFetchQueue.pop_front(); + } + + if (isBulkFetchProcessingComplete()) + { + setAllFoldersFetched(); + } +} + +void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetch_info) +{ + if (fetch_info.mIsCategory) + { + const LLUUID & cat_id(fetch_info.mUUID); + if (cat_id.isNull()) // Lost and found + { + AISAPI::FetchCategoryChildren(LLUUID::null, AISAPI::INVENTORY, false, ais_callback); + mFetchCount++; + } + else + { + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); + + if (cat) + { + if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) + { + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + { + AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mRecursive, ais_callback); + } + else + { + AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::INVENTORY, fetch_info.mRecursive, ais_callback); + } + mFetchCount++; + } + else + { + // Already fetched, check if anything inside needs fetching + if (fetch_info.mRecursive) + { + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); + gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + } + } + } + } + // else??? + } + } + else + { + LLViewerInventoryItem * itemp(gInventory.getItem(fetch_info.mUUID)); + + if (itemp) + { + if (itemp->getPermissions().getOwner() == gAgent.getID()) + { + AISAPI::FetchItem(itemp->getUUID(), AISAPI::INVENTORY, ais_callback); + } + else + { + AISAPI::FetchItem(itemp->getUUID(), AISAPI::LIBRARY, ais_callback); + } + mFetchCount++; + } + } +} + // Bundle up a bunch of requests to send all at once. void LLInventoryModelBackgroundFetch::bulkFetch() { @@ -374,13 +517,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch() // inventory more quickly. static const U32 max_batch_size(10); static const S32 max_concurrent_fetches(12); // Outstanding requests, not connections - static const F32 new_min_time(0.05f); // *HACK: Clean this up when old code goes away entirely. - - mMinTimeBetweenFetches = new_min_time; - if (mMinTimeBetweenFetches < new_min_time) - { - mMinTimeBetweenFetches = new_min_time; // *HACK: See above. - } if (mFetchCount) { @@ -394,8 +530,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() gInventory.notifyObservers(); } - if ((mFetchCount > max_concurrent_fetches) || - (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) + if (mFetchCount > max_concurrent_fetches) { return; } @@ -414,6 +549,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLSD item_request_body; LLSD item_request_body_lib; + if (!mRecursiveFetchQueue.empty()) + { + LL_DEBUGS(LOG_INV) << "Request was sheduled for AIS, using legacy" << LL_ENDL; + mFetchQueue.insert(mFetchQueue.begin(), mRecursiveFetchQueue.begin(), mRecursiveFetchQueue.end()); + mRecursiveFetchQueue.clear(); + } + while (! mFetchQueue.empty() && (item_count + folder_count) < max_batch_size) { @@ -421,14 +563,14 @@ void LLInventoryModelBackgroundFetch::bulkFetch() if (fetch_info.mIsCategory) { const LLUUID & cat_id(fetch_info.mUUID); - if (cat_id.isNull()) //DEV-17797 + if (cat_id.isNull()) //DEV-17797 Lost and found { LLSD folder_sd; folder_sd["folder_id"] = LLUUID::null.asString(); folder_sd["owner_id"] = gAgent.getID(); folder_sd["sort_order"] = LLSD::Integer(sort_order); - folder_sd["fetch_folders"] = LLSD::Boolean(FALSE); - folder_sd["fetch_items"] = LLSD::Boolean(TRUE); + folder_sd["fetch_folders"] = LLSD::Boolean(false); + folder_sd["fetch_items"] = LLSD::Boolean(true); folder_request_body["folders"].append(folder_sd); folder_count++; } @@ -444,8 +586,8 @@ void LLInventoryModelBackgroundFetch::bulkFetch() 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); + folder_sd["fetch_folders"] = LLSD::Boolean(true); //(LLSD::Boolean)sFullFetchStarted; + folder_sd["fetch_items"] = LLSD::Boolean(true); if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) { diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 00d2908c1b..ac1c42e0d7 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -49,7 +49,7 @@ public: // Start and stop background breadth-first fetching of inventory contents. // This gets triggered when performing a filter-search. - void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE); + void start(const LLUUID& cat_id = LLUUID::null, bool recursive = true); BOOL folderFetchActive() const; bool isEverythingFetched() const; // completing the fetch once per session should be sufficient @@ -68,10 +68,27 @@ public: bool isBulkFetchProcessingComplete() const; void setAllFoldersFetched(); - void addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category); - void addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category); + void addRequestAtFront(const LLUUID & id, bool recursive, bool is_category); + void addRequestAtBack(const LLUUID & id, bool recursive, bool is_category); protected: + + struct FetchQueueInfo + { + FetchQueueInfo(const LLUUID& id, bool recursive, bool is_category = true) + : mUUID(id), + mIsCategory(is_category), + mRecursive(recursive) + {} + + LLUUID mUUID; + bool mIsCategory; + bool mRecursive; + }; + typedef std::deque fetch_queue_t; + + void bulkFetchViaAis(); + void bulkFetchViaAis(const FetchQueueInfo& fetch_info); void bulkFetch(); void backgroundFetch(); @@ -80,31 +97,19 @@ protected: bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const; private: - BOOL mRecursiveInventoryFetchStarted; - BOOL mRecursiveLibraryFetchStarted; - BOOL mAllFoldersFetched; + bool mRecursiveInventoryFetchStarted; + bool mRecursiveLibraryFetchStarted; + bool mAllFoldersFetched; - BOOL mBackgroundFetchActive; + bool mBackgroundFetchActive; bool mFolderFetchActive; S32 mFetchCount; LLFrameTimer mFetchTimer; F32 mMinTimeBetweenFetches; - - struct FetchQueueInfo - { - FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) - : mUUID(id), - mIsCategory(is_category), - mRecursive(recursive) - {} - - LLUUID mUUID; - bool mIsCategory; - BOOL mRecursive; - }; - typedef std::deque fetch_queue_t; fetch_queue_t mFetchQueue; + fetch_queue_t mRecursiveFetchQueue; + }; #endif // LL_LLINVENTORYMODELBACKGROUNDFETCH_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 776b9f8279..842192a62b 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1897,6 +1897,7 @@ bool idle_startup() LLNotificationsUtil::add("InventoryUnusable"); } + LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 6f7c5d96f5..61123e65d7 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -667,7 +667,7 @@ bool LLViewerInventoryCategory::fetch() { LL_WARNS(LOG_INV) << "agent region is null" << LL_ENDL; } - if (!url.empty()) //Capability found. Build up LLSD and use it. + if (!url.empty() || AISAPI::isAvailable()) { LLInventoryModelBackgroundFetch::instance().start(mUUID, false); } -- cgit v1.3 From 3a5c41a20e6044c8cfa71dfd1583fea0809d6a68 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 17 Mar 2023 03:23:15 +0200 Subject: SL-18629 Fetch Inventory using AIS caps #4 --- indra/newview/llinventorymodelbackgroundfetch.cpp | 28 +++++++++++++---------- indra/newview/llstartup.cpp | 5 ++++ 2 files changed, 21 insertions(+), 12 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 098ced4ec9..282d234cf3 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -293,23 +293,20 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) } else { - if (AISAPI::isAvailable() && !recursive) + if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) { - // Specific folder requests go to front of queue. - if (mFetchQueue.empty() || mFetchQueue.back().mUUID != id) + if (AISAPI::isAvailable()) { + // On AIS make sure root goes to the top and follow up recursive + // fetches, not individual requests mFetchQueue.push_back(FetchQueueInfo(id, recursion_type)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } - } - else - { - // Specific folder requests go to front of queue. - if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) + else { + // Specific folder requests go to front of queue. mFetchQueue.push_front(FetchQueueInfo(id, recursion_type)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } if (id == gInventory.getLibraryRootFolderID()) @@ -419,7 +416,7 @@ void LLInventoryModelBackgroundFetch::onAISCalback(const LLUUID &request_id, con it != categories->end(); ++it) { - mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE)); + mFetchQueue.push_front(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE)); } if (!mFetchQueue.empty()) { @@ -449,11 +446,17 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() return; } - while (!mFetchQueue.empty() && mFetchCount < max_concurrent_fetches) + // Don't loop for too long (in case of large, fully loaded inventory) + F64 curent_time = LLTimer::getTotalSeconds(); + const F64 max_time = 0.006f; // 6 ms + const F64 end_time = curent_time + max_time; + + while (!mFetchQueue.empty() && mFetchCount < max_concurrent_fetches && curent_time < end_time) { const FetchQueueInfo & fetch_info(mFetchQueue.front()); bulkFetchViaAis(fetch_info); mFetchQueue.pop_front(); + curent_time = LLTimer::getTotalSeconds(); } if (isBulkFetchProcessingComplete()) @@ -513,6 +516,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc it != categories->end(); ++it) { + // not push_front to not cause an infinite loop mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); } } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 842192a62b..a1f2753ada 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2930,6 +2930,11 @@ void reset_login() LLFloaterReg::hideVisibleInstances(); LLStartUp::setStartupState( STATE_BROWSER_INIT ); + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->terminate(); + } + // Clear any verified certs and verify them again on next login // to ensure cert matches server instead of just getting reused LLPointer store = gSecAPIHandler->getCertificateStore(""); -- cgit v1.3 From 9c2b0c709b3d1cf1a9243853a8df7089e2494057 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 01:34:35 +0300 Subject: SL-19533 Special COF handling --- indra/newview/llaisapi.cpp | 40 +++++++++++++++++++++++ indra/newview/llaisapi.h | 2 ++ indra/newview/llinventorymodelbackgroundfetch.cpp | 6 ++++ indra/newview/llinventorymodelbackgroundfetch.h | 1 + indra/newview/llstartup.cpp | 1 + 5 files changed, 50 insertions(+) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d39bb57304..117a596cd2 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -592,6 +592,40 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r EnqueueAISCommand("FetchCategoryCategories", proc); } +/*static*/ +// Will get COF folder, links in it and items those links point to +void AISAPI::FetchCOF(completion_t callback) +{ + std::string cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } + return; + } + std::string url = cap + std::string("/category/current/links"); + + invokationFn_t getFn = boost::bind( + // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. + static_cast + //---- + // _1 -> httpAdapter + // _2 -> httpRequest + // _3 -> url + // _4 -> body + // _5 -> httpOptions + // _6 -> httpHeaders + (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6); + + LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, + _1, getFn, url, LLUUID::null, LLSD(), callback, FETCHCOF)); + + EnqueueAISCommand("FetchCOF", proc); +} + /*static*/ void AISAPI::FetchOrphans(completion_t callback) { @@ -687,6 +721,7 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO bool is_fetch = (type == FETCHITEM) || (type == FETCHCATEGORYCHILDREN) || (type == FETCHCATEGORYCATEGORIES) + || (type == FETCHCOF) || (type == FETCHORPHANS); // parse update llsd into stuff to do or parse received items. S32 depth = 0; @@ -1095,6 +1130,11 @@ void AISUpdate::parseLink(const LLSD& link_map) mCatDescendentDeltas[parent_id]++; new_link->setComplete(true); } + + if (link_map.has("_embedded")) + { + parseEmbedded(link_map["_embedded"], S32_MAX); + } } else { diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 4e1c6e5a7d..0ca0144d7b 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -59,6 +59,7 @@ public: static void FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCategoryChildren(const std::string &identifier, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); + static void FetchCOF(completion_t callback = completion_t()); static void FetchOrphans(completion_t callback = completion_t() ); static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); @@ -76,6 +77,7 @@ private: FETCHITEM, FETCHCATEGORYCHILDREN, FETCHCATEGORYCATEGORIES, + FETCHCOF, FETCHORPHANS, } COMMAND_TYPE; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index bfb5ad9d12..f56532ff8c 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -391,6 +391,12 @@ void LLInventoryModelBackgroundFetch::findLostItems() gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } +void LLInventoryModelBackgroundFetch::fetchCOF() +{ + // Will get COF folder, links in it and items those links point to + AISAPI::FetchCOF(); +} + void LLInventoryModelBackgroundFetch::setAllFoldersFetched() { if (mRecursiveInventoryFetchStarted && diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 1881322e7a..db2d6db323 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -65,6 +65,7 @@ public: bool inventoryFetchInProgress() const; void findLostItems(); + void fetchCOF(); void incrFetchCount(S32 fetching); void incrFetchFolderCount(S32 fetching); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a1f2753ada..161beaff19 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1898,6 +1898,7 @@ bool idle_startup() } LLInventoryModelBackgroundFetch::instance().start(); + LLInventoryModelBackgroundFetch::instance().fetchCOF(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all -- cgit v1.3 From 154ab03bf8a5dacc3128718d1f15160f0cbe2b33 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 03:38:26 +0300 Subject: SL-19533 Special COF handling #2 --- indra/newview/llappearancemgr.cpp | 33 ++++++++++++++++------- indra/newview/llappearancemgr.h | 1 + indra/newview/llinventorymodelbackgroundfetch.cpp | 18 +------------ indra/newview/llinventorymodelbackgroundfetch.h | 5 ++-- indra/newview/llstartup.cpp | 3 +-- 5 files changed, 28 insertions(+), 32 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 9115d7e5c2..297403fc6c 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4561,18 +4561,31 @@ protected: nullary_func_t mCallable; }; +void callAfterCOFFetch(nullary_func_t cb) +{ + if (AISAPI::isAvailable()) + { + AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); }); + } + else + { + LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); + callAfterCategoryFetch(cat_id, cb); + } +} + void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) { - CallAfterCategoryFetchStage1 *stage1 = new CallAfterCategoryFetchStage1(cat_id, cb); - stage1->startFetch(); - if (stage1->isFinished()) - { - stage1->done(); - } - else - { - gInventory.addObserver(stage1); - } + CallAfterCategoryFetchStage1* stage1 = new CallAfterCategoryFetchStage1(cat_id, cb); + stage1->startFetch(); + if (stage1->isFinished()) + { + stage1->done(); + } + else + { + gInventory.addObserver(stage1); + } } void add_wearable_type_counts(const uuid_vec_t& ids, diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index cf953d21ac..f6aa30d865 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -338,6 +338,7 @@ public: LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name); // Invoke a given callable after category contents are fully fetched. +void callAfterCOFFetch(nullary_func_t cb); void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb); // Wear all items in a uuid vector. diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index f56532ff8c..277ddb16ba 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -354,17 +354,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) void LLInventoryModelBackgroundFetch::scheduleFolderFetch(const LLUUID& cat_id, bool forced) { - if (AISAPI::isAvailable()) - { - if (mFetchFolderQueue.empty() || mFetchFolderQueue.back().mUUID != cat_id) - { - // On AIS make sure root goes to the top and follow up recursive - // fetches, not individual requests - mFetchFolderQueue.push_back(FetchQueueInfo(cat_id, forced ? FT_FORCED : FT_DEFAULT)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); - } - } - else if (mFetchFolderQueue.empty() || mFetchFolderQueue.front().mUUID != cat_id) + if (mFetchFolderQueue.empty() || mFetchFolderQueue.front().mUUID != cat_id) { // Specific folder requests go to front of queue. mFetchFolderQueue.push_front(FetchQueueInfo(cat_id, forced ? FT_FORCED : FT_DEFAULT)); @@ -391,12 +381,6 @@ void LLInventoryModelBackgroundFetch::findLostItems() gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } -void LLInventoryModelBackgroundFetch::fetchCOF() -{ - // Will get COF folder, links in it and items those links point to - AISAPI::FetchCOF(); -} - void LLInventoryModelBackgroundFetch::setAllFoldersFetched() { if (mRecursiveInventoryFetchStarted && diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index db2d6db323..363d04486d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -64,9 +64,8 @@ public: bool inventoryFetchCompleted() const; bool inventoryFetchInProgress() const; - void findLostItems(); - void fetchCOF(); - void incrFetchCount(S32 fetching); + void findLostItems(); + void incrFetchCount(S32 fetching); void incrFetchFolderCount(S32 fetching); bool isBulkFetchProcessingComplete() const; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 161beaff19..3a96a7bced 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1898,7 +1898,6 @@ bool idle_startup() } LLInventoryModelBackgroundFetch::instance().start(); - LLInventoryModelBackgroundFetch::instance().fetchCOF(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all @@ -2161,7 +2160,7 @@ bool idle_startup() gAgentWearables.notifyLoadingStarted(); gAgent.setOutfitChosen(TRUE); gAgentWearables.sendDummyAgentWearablesUpdate(); - callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance); + callAfterCOFFetch(set_flags_and_update_appearance); } display_startup(); -- cgit v1.3 From 98681ef73ff33e0c0ff321e839a8e79b2cb334de Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 5 May 2023 15:56:21 +0300 Subject: SL-19533 Prevent COF dupplicate request --- indra/newview/llappearancemgr.cpp | 20 +++++++++++++++----- indra/newview/llinventorymodel.cpp | 13 +++++++++++-- indra/newview/llstartup.cpp | 14 +++++++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4133470973..454ac5d88c 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4565,10 +4565,14 @@ void callAfterCOFFetch(nullary_func_t cb) { LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN && AISAPI::isAvailable()) + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) { - // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. - AISAPI::FetchCOF([cb](const LLUUID& id) + if (AISAPI::isAvailable()) + { + // Mark cof (update timer) so that background fetch won't request it + cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. + AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); @@ -4578,8 +4582,14 @@ void callAfterCOFFetch(nullary_func_t cb) cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); } }); - // Mark it so that background fetch won't request it if it didn't already - cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + } + else + { + LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL; + // startup should have marked folder as fetching, remove that + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + callAfterCategoryFetch(cat_id, cb); + } } else { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 48539f4748..c65901a754 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -853,8 +853,17 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred LLStringUtil::null, [preferred_type](const LLUUID &new_cat_id) { - LL_DEBUGS("Inventory") << "Created category: " << new_cat_id - << " for type: " << preferred_type << LL_ENDL; + if (new_cat_id.isNull()) + { + LL_WARNS("Inventory") + << "Failed to create folder of type " << preferred_type + << LL_ENDL; + } + else + { + LL_DEBUGS("Inventory") << "Created category: " << new_cat_id + << " for type: " << preferred_type << LL_ENDL; + } } ); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5d1df21c9b..10ddd59f34 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1900,9 +1900,21 @@ bool idle_startup() LLNotificationsUtil::add("InventoryUnusable"); } - LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); + LLInventoryModelBackgroundFetch::instance().start(); + LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); + if (cof + && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // Special case, dupplicate request prevention. + // Cof folder will be requested via FetchCOF + // in appearance manager, prevent recursive fetch + cof->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + } + + // It's debatable whether this flag is a good idea - sets all // bits, and in general it isn't true that inventory // initialization generates all types of changes. Maybe add an -- cgit v1.3 From f149b87fcc152a7e6232d1a2eb81bb2ac72697da Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 29 Jun 2023 23:53:22 +0300 Subject: SL-19929 New inventory feature notification --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llagent.cpp | 33 ++++++++++-- indra/newview/llagent.h | 12 +++-- indra/newview/llfloaternewfeaturenotification.cpp | 63 ++++++++++++++++++++++ indra/newview/llfloaternewfeaturenotification.h | 49 +++++++++++++++++ indra/newview/llsidepanelinventory.cpp | 2 + indra/newview/llstartup.cpp | 4 +- indra/newview/llviewerfloaterreg.cpp | 4 ++ .../xui/en/floater_new_feature_notification.xml | 54 +++++++++++++++++++ 10 files changed, 224 insertions(+), 10 deletions(-) create mode 100644 indra/newview/llfloaternewfeaturenotification.cpp create mode 100644 indra/newview/llfloaternewfeaturenotification.h create mode 100644 indra/newview/skins/default/xui/en/floater_new_feature_notification.xml (limited to 'indra/newview/llstartup.cpp') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index eedc24f973..c37d03221c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES llfloatermyscripts.cpp llfloatermyenvironment.cpp llfloaternamedesc.cpp + llfloaternewfeaturenotification.cpp llfloaternotificationsconsole.cpp llfloaternotificationstabbed.cpp llfloaterobjectweights.cpp @@ -894,6 +895,7 @@ set(viewer_HEADER_FILES llfloatermyscripts.h llfloatermyenvironment.h llfloaternamedesc.h + llfloaternewfeaturenotification.h llfloaternotificationsconsole.h llfloaternotificationstabbed.h llfloaterobjectweights.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dd87f827df..df3dd65a0e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5497,6 +5497,17 @@ Value 0 + LastUIFeatureVersion + + Comment + UI Feature Version number for tracking feature notification between viewer builds + Persist + 1 + Type + S32 + Value + 0 + LastFindPanel Comment diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 8cc9be7244..2430ca5f83 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -120,6 +120,8 @@ const F64 CHAT_AGE_FAST_RATE = 3.0; const F32 MIN_FIDGET_TIME = 8.f; // seconds const F32 MAX_FIDGET_TIME = 20.f; // seconds +const S32 UI_FEATURE_VERSION = 1; + // The agent instance. LLAgent gAgent; @@ -372,7 +374,7 @@ LLAgent::LLAgent() : mHideGroupTitle(FALSE), mGroupID(), - mInitialized(FALSE), + mInitialized(false), mListener(), mDoubleTapRunTimer(), @@ -447,7 +449,7 @@ LLAgent::LLAgent() : mNextFidgetTime(0.f), mCurrentFidget(0), - mFirstLogin(FALSE), + mFirstLogin(false), mOutfitChosen(FALSE), mVoiceConnected(false), @@ -504,7 +506,7 @@ void LLAgent::init() mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT); - mInitialized = TRUE; + mInitialized = true; } //----------------------------------------------------------------------------- @@ -559,6 +561,31 @@ void LLAgent::onAppFocusGained() } } +void LLAgent::setFirstLogin(bool b) +{ + mFirstLogin = b; + + if (mFirstLogin) + { + // Don't notify new users about new features + S32 feature_version = gSavedSettings.getS32("LastUIFeatureVersion"); + if (feature_version < UI_FEATURE_VERSION) + { + gSavedSettings.setS32("LastUIFeatureVersion", UI_FEATURE_VERSION); + } + } +} + +void LLAgent::showLatestFeatureNotification() +{ + // Notify user about new thumbnail support + S32 feature_version = gSavedSettings.getS32("LastUIFeatureVersion"); + if (feature_version < UI_FEATURE_VERSION) + { + LLFloaterReg::showInstance("new_feature_notification"); + gSavedSettings.setS32("LastUIFeatureVersion", UI_FEATURE_VERSION); + } +} void LLAgent::ageChat() { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 498bea3c07..fb9ac402e1 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -117,15 +117,17 @@ private: //-------------------------------------------------------------------- public: void onAppFocusGained(); - void setFirstLogin(BOOL b) { mFirstLogin = b; } + void setFirstLogin(bool b); // Return TRUE if the database reported this login as the first for this particular user. - BOOL isFirstLogin() const { return mFirstLogin; } - BOOL isInitialized() const { return mInitialized; } + bool isFirstLogin() const { return mFirstLogin; } + bool isInitialized() const { return mInitialized; } + + void showLatestFeatureNotification(); public: std::string mMOTD; // Message of the day private: - BOOL mInitialized; - BOOL mFirstLogin; + bool mInitialized; + bool mFirstLogin; boost::shared_ptr mListener; //-------------------------------------------------------------------- diff --git a/indra/newview/llfloaternewfeaturenotification.cpp b/indra/newview/llfloaternewfeaturenotification.cpp new file mode 100644 index 0000000000..e04b1a5da5 --- /dev/null +++ b/indra/newview/llfloaternewfeaturenotification.cpp @@ -0,0 +1,63 @@ +/** + * @file llfloaternewfeaturenotification.cpp + * @brief LLFloaterNewFeatureNotification class implementation + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaternewfeaturenotification.h" + + +LLFloaterNewFeatureNotification::LLFloaterNewFeatureNotification(const LLSD& key) + : LLFloater(key) +{ +} + +LLFloaterNewFeatureNotification::~LLFloaterNewFeatureNotification() +{ +} + +BOOL LLFloaterNewFeatureNotification::postBuild() +{ + setCanDrag(FALSE); + getChild("close_btn")->setCommitCallback(boost::bind(&LLFloaterNewFeatureNotification::onCloseBtn, this)); + return TRUE; +} + +void LLFloaterNewFeatureNotification::onOpen(const LLSD& key) +{ + centerOnScreen(); +} + +void LLFloaterNewFeatureNotification::onCloseBtn() +{ + closeFloater(); +} + +void LLFloaterNewFeatureNotification::centerOnScreen() +{ + LLVector2 window_size = LLUI::getInstance()->getWindowSize(); + centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY]))); +} + diff --git a/indra/newview/llfloaternewfeaturenotification.h b/indra/newview/llfloaternewfeaturenotification.h new file mode 100644 index 0000000000..86e9683def --- /dev/null +++ b/indra/newview/llfloaternewfeaturenotification.h @@ -0,0 +1,49 @@ +/** + * @file llfloaternewfeaturenotification.h + * @brief LLFloaterNewFeatureNotification class definition + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLOATER_NEW_FEATURE_NOTOFICATION_H +#define LL_FLOATER_NEW_FEATURE_NOTOFICATION_H + +#include "llfloater.h" + +class LLFloaterNewFeatureNotification: + public LLFloater +{ + friend class LLFloaterReg; +public: + BOOL postBuild() override; + void onOpen(const LLSD& key) override; + +private: + LLFloaterNewFeatureNotification(const LLSD& key); + /*virtual*/ ~LLFloaterNewFeatureNotification(); + + void centerOnScreen(); + + void onCloseBtn(); +}; + +#endif diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 5eb853f44c..dde260eb7f 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -400,6 +400,8 @@ void LLSidepanelInventory::onOpen(const LLSD& key) gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } #endif + + gAgent.showLatestFeatureNotification(); } void LLSidepanelInventory::performActionOnSelection(const std::string &action) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a37bde6eb8..edd46f7423 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3627,7 +3627,7 @@ bool process_login_success_response() std::string flag = login_flags["ever_logged_in"]; if(!flag.empty()) { - gAgent.setFirstLogin((flag == "N") ? TRUE : FALSE); + gAgent.setFirstLogin(flag == "N"); } /* Flag is currently ignored by the viewer. @@ -3718,7 +3718,7 @@ bool process_login_success_response() std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName"); if (!fake_initial_outfit_name.empty()) { - gAgent.setFirstLogin(TRUE); + gAgent.setFirstLogin(true); sInitialOutfit = fake_initial_outfit_name; if (sInitialOutfitGender.empty()) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 0c6e2de3ed..060bdb6995 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -100,6 +100,7 @@ #include "llfloatermyscripts.h" #include "llfloatermyenvironment.h" #include "llfloaternamedesc.h" +#include "llfloaternewfeaturenotification.h" #include "llfloaternotificationsconsole.h" #include "llfloaternotificationstabbed.h" #include "llfloaterobjectweights.h" @@ -229,6 +230,7 @@ public: "avatar_picker", "camera", "camera_presets", + "change_item_thumbnail" "classified", "add_landmark", "delete_pref_preset", @@ -247,6 +249,7 @@ public: "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant "message_tos", // Modal!!! Login specific. "mute_object_by_name", + "new_feature_notification", "publish_classified", "save_pref_preset", "save_camera_preset", @@ -402,6 +405,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("new_feature_notification", "floater_new_feature_notification.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml new file mode 100644 index 0000000000..370a08f16a --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_new_feature_notification.xml @@ -0,0 +1,54 @@ + + + +New inventory features + + +You can now add preview images to inventory items and view a folder in its own window. +Learn more in this [https://community.secondlife.com/blogs/entry/13637-new-features-inventory-item-preview-and-single-folder-view/ blogpost] + +