Merge branch 'DRTVWR-567' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/app_settings/settings.xml # indra/newview/llaisapi.cpp # indra/newview/llaisapi.h # indra/newview/llappviewer.cpp # indra/newview/llinventorymodel.cpp # indra/newview/llpanelmaininventory.h # indra/newview/llstartup.cpp # indra/newview/llviewerinventory.cpp # indra/newview/skins/default/xui/en/panel_main_inventory.xmlmaster
commit
f156461048
|
|
@ -1198,11 +1198,7 @@ LLSD LLInventoryCategory::asAISLLSD() const
|
|||
S8 type = static_cast<S8>(mPreferredType);
|
||||
sd[INV_ASSET_TYPE_LABEL_WS] = type;
|
||||
sd[INV_NAME_LABEL] = mName;
|
||||
|
||||
if (mThumbnailUUID.notNull())
|
||||
{
|
||||
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
|
||||
}
|
||||
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
|
@ -1427,16 +1423,16 @@ bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
|
|||
{
|
||||
setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
|
||||
}
|
||||
LLUUID thumbnail_uuid;
|
||||
if (cat_data.has(INV_THUMBNAIL_LABEL))
|
||||
{
|
||||
LLUUID thumbnail_uuid;
|
||||
const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
|
||||
if (thumbnail_data.has(INV_ASSET_ID_LABEL))
|
||||
{
|
||||
thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
|
||||
}
|
||||
setThumbnailUUID(thumbnail_uuid);
|
||||
}
|
||||
setThumbnailUUID(thumbnail_uuid);
|
||||
if (cat_data.has(INV_NAME_LABEL))
|
||||
{
|
||||
mName = cat_data[INV_NAME_LABEL].asString();
|
||||
|
|
|
|||
|
|
@ -19051,6 +19051,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>BatchSizeAIS3</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Amount of folder ais packs into category subset request</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>20</integer>
|
||||
</map>
|
||||
<key>PoolSizeAIS</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1443,8 +1443,9 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array
|
|||
}
|
||||
|
||||
// Build up list of objects to be removed and items currently attached.
|
||||
for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
|
||||
iter != gAgentAvatarp->mAttachmentPoints.end();)
|
||||
LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
|
||||
LLVOAvatar::attachment_map_t::iterator end = gAgentAvatarp->mAttachmentPoints.end();
|
||||
while (iter != end)
|
||||
{
|
||||
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
|
|
|
|||
|
|
@ -48,11 +48,16 @@
|
|||
//=========================================================================
|
||||
const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3");
|
||||
const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3");
|
||||
const S32 AISAPI::HTTP_TIMEOUT = 180;
|
||||
|
||||
std::list<AISAPI::ais_query_item_t> AISAPI::sPostponedQuery;
|
||||
|
||||
const S32 MAX_SIMULTANEOUS_COROUTINES = 2048;
|
||||
|
||||
// AIS3 allows '*' requests, but in reality those will be cut at some point
|
||||
// Specify own depth to be able to anticipate it and mark folders as incomplete
|
||||
const S32 MAX_FOLDER_DEPTH_REQUEST = 50;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*static*/
|
||||
bool AISAPI::isAvailable()
|
||||
|
|
@ -463,11 +468,11 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec
|
|||
{
|
||||
// can specify depth=*, but server side is going to cap requests
|
||||
// and reject everything 'over the top',.
|
||||
depth = 50;
|
||||
depth = MAX_FOLDER_DEPTH_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = llmax(depth, 50);
|
||||
depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST);
|
||||
}
|
||||
|
||||
url += "?depth=" + std::to_string(depth);
|
||||
|
|
@ -516,11 +521,11 @@ void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive
|
|||
{
|
||||
// can specify depth=*, but server side is going to cap requests
|
||||
// and reject everything 'over the top',.
|
||||
depth = 50;
|
||||
depth = MAX_FOLDER_DEPTH_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = llmax(depth, 50);
|
||||
depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST);
|
||||
}
|
||||
|
||||
url += "?depth=" + std::to_string(depth);
|
||||
|
|
@ -567,11 +572,11 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r
|
|||
{
|
||||
// can specify depth=*, but server side is going to cap requests
|
||||
// and reject everything 'over the top',.
|
||||
depth = 50;
|
||||
depth = MAX_FOLDER_DEPTH_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = llmax(depth, 50);
|
||||
depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST);
|
||||
}
|
||||
|
||||
url += "?depth=" + std::to_string(depth);
|
||||
|
|
@ -597,6 +602,117 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r
|
|||
EnqueueAISCommand("FetchCategoryCategories", proc);
|
||||
}
|
||||
|
||||
void AISAPI::FetchCategorySubset(const LLUUID& catId,
|
||||
const uuid_vec_t specificChildren,
|
||||
ITEM_TYPE type,
|
||||
bool recursive,
|
||||
completion_t callback,
|
||||
S32 depth)
|
||||
{
|
||||
std::string cap = (type == INVENTORY) ? getInvCap() : getLibCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (specificChildren.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Empty request!" << LL_ENDL;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// category/any_folder_id/children?depth=*&children=child_id1,child_id2,child_id3
|
||||
std::string url = cap + std::string("/category/") + catId.asString() + "/children";
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
depth = MAX_FOLDER_DEPTH_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST);
|
||||
}
|
||||
|
||||
uuid_vec_t::const_iterator iter = specificChildren.begin();
|
||||
uuid_vec_t::const_iterator end = specificChildren.end();
|
||||
|
||||
url += "?depth=" + std::to_string(depth) + "&children=" + iter->asString();
|
||||
iter++;
|
||||
|
||||
while (iter != end)
|
||||
{
|
||||
url += "," + iter->asString();
|
||||
iter++;
|
||||
}
|
||||
|
||||
const S32 MAX_URL_LENGH = 2000; // RFC documentation specifies a maximum length of 2048
|
||||
if (url.length() > MAX_URL_LENGH)
|
||||
{
|
||||
LL_WARNS("Inventory") << "Request url is too long, url: " << url << LL_ENDL;
|
||||
}
|
||||
|
||||
invokationFn_t getFn = boost::bind(
|
||||
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
|
||||
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string&, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
||||
//----
|
||||
// _1 -> httpAdapter
|
||||
// _2 -> httpRequest
|
||||
// _3 -> url
|
||||
// _4 -> body
|
||||
// _5 -> httpOptions
|
||||
// _6 -> httpHeaders
|
||||
(&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6);
|
||||
|
||||
// get doesn't use body, can pass additional data
|
||||
LLSD body;
|
||||
body["depth"] = depth;
|
||||
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
|
||||
_1, getFn, url, catId, body, callback, FETCHCATEGORYSUBSET));
|
||||
|
||||
EnqueueAISCommand("FetchCategorySubset", 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<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string&, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
||||
//----
|
||||
// _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)
|
||||
{
|
||||
|
|
@ -681,7 +797,7 @@ void AISAPI::onIdle(void *userdata)
|
|||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body)
|
||||
void AISAPI::onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD& request_body)
|
||||
{
|
||||
LLTimer timer;
|
||||
if ( (type == UPDATECATEGORY || type == UPDATEITEM)
|
||||
|
|
@ -689,17 +805,8 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO
|
|||
{
|
||||
dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
|
||||
}
|
||||
bool is_fetch = (type == FETCHITEM)
|
||||
|| (type == FETCHCATEGORYCHILDREN)
|
||||
|| (type == FETCHCATEGORYCATEGORIES)
|
||||
|| (type == FETCHORPHANS);
|
||||
// parse update llsd into stuff to do or parse received items.
|
||||
S32 depth = 0;
|
||||
if (is_fetch && request_body.has("depth"))
|
||||
{
|
||||
depth = request_body["depth"].asInteger();
|
||||
}
|
||||
AISUpdate ais_update(update, is_fetch, depth);
|
||||
|
||||
AISUpdate ais_update(update, type, request_body);
|
||||
ais_update.doUpdate(); // execute the updates in the appropriate order.
|
||||
LL_DEBUGS("Inventory", "AIS3") << "Elapsed processing: " << timer.getElapsedTimeF32() << LL_ENDL;
|
||||
}
|
||||
|
|
@ -722,7 +829,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
|
||||
LLCore::HttpHeaders::ptr_t httpHeaders;
|
||||
|
||||
httpOptions->setTimeout(180);
|
||||
httpOptions->setTimeout(HTTP_TIMEOUT);
|
||||
|
||||
LL_DEBUGS("Inventory") << "Request url: " << url << LL_ENDL;
|
||||
|
||||
|
|
@ -741,7 +848,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
|
||||
LL_DEBUGS("Inventory") << "Request type: " << (S32)type
|
||||
<< " \nRequest target: " << targetId
|
||||
<< " \nElapsed time ince request: " << elapsed_time
|
||||
<< " \nElapsed time since request: " << elapsed_time
|
||||
<< " \nstatus: " << status.toULong() << LL_ENDL;
|
||||
}
|
||||
else
|
||||
|
|
@ -803,7 +910,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
}
|
||||
|
||||
LL_DEBUGS("Inventory", "AIS3") << "Result: " << result << LL_ENDL;
|
||||
onUpdateReceived("AISCommand", result, type, body);
|
||||
onUpdateReceived(result, type, body);
|
||||
|
||||
if (callback && !callback.empty())
|
||||
{
|
||||
|
|
@ -814,6 +921,8 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
case COPYLIBRARYCATEGORY:
|
||||
case FETCHCATEGORYCATEGORIES:
|
||||
case FETCHCATEGORYCHILDREN:
|
||||
case FETCHCATEGORYSUBSET:
|
||||
case FETCHCOF:
|
||||
if (result.has("category_id"))
|
||||
{
|
||||
ids.emplace(result["category_id"]);
|
||||
|
|
@ -865,6 +974,8 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
//case COPYLIBRARYCATEGORY:
|
||||
//case FETCHCATEGORYCATEGORIES:
|
||||
//case FETCHCATEGORYCHILDREN:
|
||||
//case FETCHCATEGORYSUBSET:
|
||||
//case FETCHCOF:
|
||||
// if (result.has("category_id"))
|
||||
// {
|
||||
// id = result["category_id"];
|
||||
|
|
@ -920,10 +1031,24 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
AISUpdate::AISUpdate(const LLSD& update, bool fetch, S32 depth)
|
||||
: mFetch(fetch)
|
||||
, mFetchDepth(depth)
|
||||
AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body)
|
||||
: mType(type)
|
||||
{
|
||||
mFetch = (type == AISAPI::FETCHITEM)
|
||||
|| (type == AISAPI::FETCHCATEGORYCHILDREN)
|
||||
|| (type == AISAPI::FETCHCATEGORYCATEGORIES)
|
||||
|| (type == AISAPI::FETCHCATEGORYSUBSET)
|
||||
|| (type == AISAPI::FETCHCOF)
|
||||
|| (type == AISAPI::FETCHORPHANS);
|
||||
// parse update llsd into stuff to do or parse received items.
|
||||
mFetchDepth = MAX_FOLDER_DEPTH_REQUEST;
|
||||
if (mFetch && request_body.has("depth"))
|
||||
{
|
||||
mFetchDepth = request_body["depth"].asInteger();
|
||||
}
|
||||
|
||||
mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE);
|
||||
mTimer.start();
|
||||
parseUpdate(update);
|
||||
}
|
||||
|
||||
|
|
@ -942,6 +1067,16 @@ void AISUpdate::clearParseResults()
|
|||
mCategoryIds.clear();
|
||||
}
|
||||
|
||||
void AISUpdate::checkTimeout()
|
||||
{
|
||||
if (mTimer.hasExpired())
|
||||
{
|
||||
llcoro::suspend();
|
||||
LLCoros::checkStop();
|
||||
mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void AISUpdate::parseUpdate(const LLSD& update)
|
||||
{
|
||||
clearParseResults();
|
||||
|
|
@ -1031,17 +1166,26 @@ void AISUpdate::parseContent(const LLSD& update)
|
|||
{
|
||||
if (update.has("linked_id"))
|
||||
{
|
||||
parseLink(update);
|
||||
parseLink(update, mFetchDepth);
|
||||
}
|
||||
else if (update.has("item_id"))
|
||||
{
|
||||
parseItem(update);
|
||||
}
|
||||
|
||||
if (update.has("category_id"))
|
||||
{
|
||||
parseCategory(update, mFetchDepth);
|
||||
}
|
||||
if (mType == AISAPI::FETCHCATEGORYSUBSET)
|
||||
{
|
||||
// initial category is incomplete, don't process it,
|
||||
// go for content instead
|
||||
if (update.has("_embedded"))
|
||||
{
|
||||
parseEmbedded(update["_embedded"], mFetchDepth - 1);
|
||||
}
|
||||
}
|
||||
else if (update.has("category_id"))
|
||||
{
|
||||
parseCategory(update, mFetchDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update.has("_embedded"))
|
||||
|
|
@ -1097,7 +1241,7 @@ void AISUpdate::parseItem(const LLSD& item_map)
|
|||
}
|
||||
}
|
||||
|
||||
void AISUpdate::parseLink(const LLSD& link_map)
|
||||
void AISUpdate::parseLink(const LLSD& link_map, S32 depth)
|
||||
{
|
||||
LLUUID item_id = link_map["item_id"].asUUID();
|
||||
LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
|
||||
|
|
@ -1150,6 +1294,11 @@ void AISUpdate::parseLink(const LLSD& link_map)
|
|||
mCatDescendentDeltas[parent_id]++;
|
||||
new_link->setComplete(true);
|
||||
}
|
||||
|
||||
if (link_map.has("_embedded"))
|
||||
{
|
||||
parseEmbedded(link_map["_embedded"], depth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1294,9 +1443,11 @@ void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embe
|
|||
|
||||
void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth)
|
||||
{
|
||||
checkTimeout();
|
||||
|
||||
if (embedded.has("links")) // _embedded in a category
|
||||
{
|
||||
parseEmbeddedLinks(embedded["links"]);
|
||||
parseEmbeddedLinks(embedded["links"], depth);
|
||||
}
|
||||
if (embedded.has("items")) // _embedded in a category
|
||||
{
|
||||
|
|
@ -1329,7 +1480,7 @@ void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uui
|
|||
}
|
||||
}
|
||||
|
||||
void AISUpdate::parseEmbeddedLinks(const LLSD& links)
|
||||
void AISUpdate::parseEmbeddedLinks(const LLSD& links, S32 depth)
|
||||
{
|
||||
for(LLSD::map_const_iterator linkit = links.beginMap(),
|
||||
linkend = links.endMap();
|
||||
|
|
@ -1343,7 +1494,7 @@ void AISUpdate::parseEmbeddedLinks(const LLSD& links)
|
|||
}
|
||||
else
|
||||
{
|
||||
parseLink(link_map);
|
||||
parseLink(link_map, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1414,6 +1565,8 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories, S32 depth)
|
|||
|
||||
void AISUpdate::doUpdate()
|
||||
{
|
||||
checkTimeout();
|
||||
|
||||
// Do version/descendant accounting.
|
||||
for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
|
||||
catit != mCatDescendentDeltas.end(); ++catit)
|
||||
|
|
@ -1455,6 +1608,7 @@ void AISUpdate::doUpdate()
|
|||
}
|
||||
|
||||
// CREATE CATEGORIES
|
||||
const S32 MAX_UPDATE_BACKLOG = 50; // stall prevention
|
||||
for (deferred_category_map_t::const_iterator create_it = mCategoriesCreated.begin();
|
||||
create_it != mCategoriesCreated.end(); ++create_it)
|
||||
{
|
||||
|
|
@ -1463,6 +1617,13 @@ void AISUpdate::doUpdate()
|
|||
|
||||
gInventory.updateCategory(new_category, LLInventoryObserver::CREATE);
|
||||
LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL;
|
||||
|
||||
// fetching can receive massive amount of items and fodlers
|
||||
if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
checkTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATE CATEGORIES
|
||||
|
|
@ -1517,6 +1678,13 @@ void AISUpdate::doUpdate()
|
|||
// case this is create.
|
||||
LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL;
|
||||
gInventory.updateItem(new_item, LLInventoryObserver::CREATE);
|
||||
|
||||
// fetching can receive massive amount of items and fodlers
|
||||
if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
checkTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATE ITEMS
|
||||
|
|
@ -1577,6 +1745,8 @@ void AISUpdate::doUpdate()
|
|||
}
|
||||
}
|
||||
|
||||
checkTimeout();
|
||||
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
class AISAPI
|
||||
{
|
||||
public:
|
||||
static const S32 HTTP_TIMEOUT;
|
||||
typedef enum {
|
||||
INVENTORY,
|
||||
LIBRARY
|
||||
|
|
@ -59,10 +60,11 @@ 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 FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, 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());
|
||||
|
||||
private:
|
||||
typedef enum {
|
||||
COPYINVENTORY,
|
||||
SLAMFOLDER,
|
||||
|
|
@ -76,9 +78,12 @@ private:
|
|||
FETCHITEM,
|
||||
FETCHCATEGORYCHILDREN,
|
||||
FETCHCATEGORYCATEGORIES,
|
||||
FETCHCATEGORYSUBSET,
|
||||
FETCHCOF,
|
||||
FETCHORPHANS,
|
||||
} COMMAND_TYPE;
|
||||
|
||||
private:
|
||||
static const std::string INVENTORY_CAP_NAME;
|
||||
static const std::string LIBRARY_CAP_NAME;
|
||||
|
||||
|
|
@ -87,7 +92,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, const LLSD& request_body);
|
||||
static void onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD& request_body);
|
||||
|
||||
static std::string getInvCap();
|
||||
static std::string getLibCap();
|
||||
|
|
@ -103,7 +108,7 @@ private:
|
|||
class AISUpdate
|
||||
{
|
||||
public:
|
||||
AISUpdate(const LLSD& update, bool fetch, S32 depth);
|
||||
AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body);
|
||||
void parseUpdate(const LLSD& update);
|
||||
void parseMeta(const LLSD& update);
|
||||
void parseContent(const LLSD& update);
|
||||
|
|
@ -111,12 +116,12 @@ public:
|
|||
static void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
// [/SL:KB]
|
||||
// void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
void parseLink(const LLSD& link_map);
|
||||
void parseLink(const LLSD& link_map, S32 depth);
|
||||
void parseItem(const LLSD& link_map);
|
||||
void parseCategory(const LLSD& link_map, S32 depth);
|
||||
void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
|
||||
void parseEmbedded(const LLSD& embedded, S32 depth);
|
||||
void parseEmbeddedLinks(const LLSD& links);
|
||||
void parseEmbeddedLinks(const LLSD& links, S32 depth);
|
||||
void parseEmbeddedItems(const LLSD& items);
|
||||
void parseEmbeddedCategories(const LLSD& categories, S32 depth);
|
||||
void parseEmbeddedItem(const LLSD& item);
|
||||
|
|
@ -124,6 +129,12 @@ public:
|
|||
void doUpdate();
|
||||
private:
|
||||
void clearParseResults();
|
||||
void checkTimeout();
|
||||
|
||||
// Debug is very log-heavy, give it more time or it will take forever to process
|
||||
// Todo: find a way to make throttle static isntead of per-request
|
||||
const F32 EXPIRY_SECONDS_DEBUG = 1.f;
|
||||
const F32 EXPIRY_SECONDS_LIVE = 0.008f;
|
||||
|
||||
typedef std::map<LLUUID,S32> uuid_int_map_t;
|
||||
uuid_int_map_t mCatDescendentDeltas;
|
||||
|
|
@ -145,6 +156,8 @@ private:
|
|||
uuid_list_t mCategoryIds;
|
||||
bool mFetch;
|
||||
S32 mFetchDepth;
|
||||
LLTimer mTimer;
|
||||
AISAPI::COMMAND_TYPE mType;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5131,18 +5131,45 @@ protected:
|
|||
nullary_func_t mCallable;
|
||||
};
|
||||
|
||||
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())
|
||||
{
|
||||
// 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();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
if (cat)
|
||||
{
|
||||
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
|
||||
{
|
||||
// Assume that cache is present. Process like a normal folder.
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -367,6 +367,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.
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
|
|||
&& !LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress())
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id);
|
||||
if (!cat || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN))
|
||||
if ((!cat && folder_id.notNull()) || (cat && cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN))
|
||||
{
|
||||
// At the moment background fetch only cares about VERSION_UNKNOWN,
|
||||
// so do not check isCategoryComplete that compares descendant count
|
||||
|
|
@ -229,6 +229,11 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
|
|||
}
|
||||
}
|
||||
|
||||
if (!checkAgainstFilterThumbnails(folder_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Marketplace folder filtering
|
||||
const U32 filterTypes = mFilterOps.mFilterTypes;
|
||||
const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE |
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ public:
|
|||
bool hasDescendents(const LLUUID& cat_id);
|
||||
bool hasVisibleItems();
|
||||
void handleModifiedFilter();
|
||||
LLScrollContainer* getScrollableContainer() { return mScrollPanel; }
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -334,6 +334,10 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU
|
|||
gInventory.updateItem(item);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
else if ("replace_links" == action)
|
||||
{
|
||||
LLFloaterReg::showInstance("linkreplace", LLSD(selected_id));
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response)
|
||||
|
|
@ -451,8 +455,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
if(!is_link)
|
||||
{
|
||||
items.push_back(std::string("thumbnail"));
|
||||
LLViewerInventoryItem* inv_item = gInventory.getItem(selected_id);
|
||||
if (inv_item && !inv_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
|
||||
if (!is_agent_inventory)
|
||||
{
|
||||
disabled_items.push_back(std::string("thumbnail"));
|
||||
}
|
||||
|
|
@ -466,6 +469,13 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
items.push_back(std::string("open_in_new_window"));
|
||||
items.push_back(std::string("Open Folder Separator"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_agent_inventory && (obj->getType() != LLAssetType::AT_LINK_FOLDER))
|
||||
{
|
||||
items.push_back(std::string("Replace Links"));
|
||||
}
|
||||
}
|
||||
|
||||
if(is_trash)
|
||||
{
|
||||
|
|
@ -490,7 +500,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
}
|
||||
}
|
||||
items.push_back(std::string("Purge Item"));
|
||||
if (!get_is_category_removable(&gInventory, selected_id))
|
||||
if (is_folder && !get_is_category_removable(&gInventory, selected_id))
|
||||
{
|
||||
disabled_items.push_back(std::string("Purge Item"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2878,12 +2878,6 @@ bool LLInventoryModel::loadSkeleton(
|
|||
cat->setUUID(folder_id.asUUID());
|
||||
cat->setParent(parent_id.asUUID());
|
||||
|
||||
LLSD thumbnail = (*it)["thumbnail"];
|
||||
if (thumbnail.isMap())
|
||||
{
|
||||
cat->setThumbnailUUID(thumbnail["asset_id"].asUUID());
|
||||
}
|
||||
|
||||
LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
|
||||
LLSD type_default = (*it)["type_default"];
|
||||
if(type_default.isDefined())
|
||||
|
|
@ -2975,6 +2969,10 @@ bool LLInventoryModel::loadSkeleton(
|
|||
else
|
||||
{
|
||||
cached_ids.insert(tcat->getUUID());
|
||||
|
||||
// At the moment download does not provide a thumbnail
|
||||
// uuid, use the one from cache
|
||||
tcat->setThumbnailUUID(cat->getThumbnailUUID());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5257,7 +5255,6 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
|
|||
}
|
||||
else if (count_under_root > 1)
|
||||
{
|
||||
// LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; // <FS:Beq/> FIRE-31634 [OPENSIM] Better inventory validation logging
|
||||
validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
|
||||
if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS)
|
||||
{
|
||||
|
|
@ -5273,6 +5270,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
|
|||
// outfits, trash and other non-automatic folders.
|
||||
validation_info->mFatalSystemDuplicate++;
|
||||
fatal_errs++;
|
||||
// <FS:Beq> FIRE-31634 [OPENSIM] Better inventory validation logging
|
||||
//LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5282,6 +5281,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
|
|||
// Exception: FT_SETTINGS is not automatic, but only deserves a warning.
|
||||
validation_info->mWarnings["non_fatal_system_duplicate_under_root"]++;
|
||||
warning_count++;
|
||||
// <FS:Beq> FIRE-31634 [OPENSIM] Better inventory validation logging
|
||||
//LL_WARNS("Inventory") << "System folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (count_elsewhere > 0)
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive)
|
|||
// Not only root folder can be massive, but
|
||||
// most system folders will be requested independently
|
||||
// so request root folder and content separately
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_CONTENT_RECURSIVE));
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_FOLDER_AND_CONTENT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -358,17 +358,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));
|
||||
|
|
@ -630,10 +620,67 @@ void ais_simple_item_callback(const LLUUID& inv_id)
|
|||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion)
|
||||
void LLInventoryModelBackgroundFetch::onAISContentCalback(
|
||||
const LLUUID& request_id,
|
||||
const uuid_vec_t& content_ids,
|
||||
const LLUUID& response_id,
|
||||
EFetchType fetch_type)
|
||||
{
|
||||
// Don't push_front on failure - there is a chance it was fired from inside bulkFetchViaAis
|
||||
incrFetchFolderCount(-1);
|
||||
std::list<LLUUID>::const_iterator found = std::find(mExpectedFolderIds.begin() , mExpectedFolderIds.end(), request_id);
|
||||
|
||||
uuid_vec_t::const_iterator folder_iter = content_ids.begin();
|
||||
uuid_vec_t::const_iterator folder_end = content_ids.end();
|
||||
while (folder_iter != folder_end)
|
||||
{
|
||||
std::list<LLUUID>::const_iterator found = std::find(mExpectedFolderIds.begin(), mExpectedFolderIds.end(), *folder_iter);
|
||||
if (found != mExpectedFolderIds.end())
|
||||
{
|
||||
mExpectedFolderIds.erase(found);
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* cat(gInventory.getCategory(*folder_iter));
|
||||
if (cat)
|
||||
{
|
||||
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
|
||||
}
|
||||
if (response_id.isNull())
|
||||
{
|
||||
// Failed to fetch, get it individually
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(*folder_iter, FT_RECURSIVE));
|
||||
}
|
||||
else
|
||||
{
|
||||
// push descendant back to verify they are fetched fully (ex: didn't encounter depth limit)
|
||||
LLInventoryModel::cat_array_t* categories(NULL);
|
||||
LLInventoryModel::item_array_t* items(NULL);
|
||||
gInventory.getDirectDescendentsOf(*folder_iter, categories, items);
|
||||
if (categories)
|
||||
{
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
folder_iter++;
|
||||
}
|
||||
|
||||
if (!mFetchFolderQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType fetch_type)
|
||||
{
|
||||
// Don't push_front on failure - there is a chance it was fired from inside bulkFetchViaAis
|
||||
incrFetchFolderCount(-1);
|
||||
std::list<LLUUID>::const_iterator found = std::find(mExpectedFolderIds.begin(), mExpectedFolderIds.end(), request_id);
|
||||
if (found != mExpectedFolderIds.end())
|
||||
{
|
||||
mExpectedFolderIds.erase(found);
|
||||
|
|
@ -655,32 +702,34 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i
|
|||
if (response_id.isNull()) // Failure
|
||||
{
|
||||
LL_DEBUGS(LOG_INV , "AIS3") << "Failure response for folder " << request_id << LL_ENDL;
|
||||
if (recursion == FT_RECURSIVE)
|
||||
if (fetch_type == FT_RECURSIVE)
|
||||
{
|
||||
// A full recursive request failed.
|
||||
// Try requesting folder and nested content separately
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(request_id, FT_FOLDER_AND_CONTENT));
|
||||
}
|
||||
else if (recursion == FT_CONTENT_RECURSIVE)
|
||||
else if (fetch_type == FT_FOLDER_AND_CONTENT)
|
||||
{
|
||||
LL_WARNS() << "Failed to download folder: " << request_id << " Requesting known content separately" << LL_ENDL;
|
||||
request_descendants = true;
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (recursion == FT_CONTENT_RECURSIVE || recursion == FT_RECURSIVE)
|
||||
if (fetch_type == FT_RECURSIVE)
|
||||
{
|
||||
// Got the folder, now recursively request content
|
||||
// Got the folder and content, now verify content
|
||||
// Request content even for FT_RECURSIVE in case of changes, failures
|
||||
// or if depth limit gets imlemented.
|
||||
// This shouldn't redownload folders if they already have version
|
||||
request_descendants = true;
|
||||
LL_DEBUGS(LOG_INV, "AIS3") << "Got folder " << request_id << ". Requesting content" << LL_ENDL;
|
||||
}
|
||||
else if (fetch_type == FT_FOLDER_AND_CONTENT)
|
||||
{
|
||||
// readd folder for content request
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS(LOG_INV, "AIS3") << "Got folder " << request_id << "." << LL_ENDL;
|
||||
|
|
@ -699,17 +748,18 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i
|
|||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
if (!mFetchFolderQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mFetchFolderQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
|
||||
// done
|
||||
LLViewerInventoryCategory * cat(gInventory.getCategory(request_id));
|
||||
if (cat)
|
||||
|
|
@ -730,7 +780,9 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis()
|
|||
}
|
||||
|
||||
static LLCachedControl<U32> ais_pool(gSavedSettings, "PoolSizeAIS", 20);
|
||||
const U32 max_concurrent_fetches = llmax(1, ais_pool - 1);
|
||||
// Don't have too many requests at once, AIS throttles
|
||||
// Reserve one request for actions outside of fetch (like renames)
|
||||
const U32 max_concurrent_fetches = llclamp(ais_pool - 1, 1, 50);
|
||||
|
||||
if (mFetchCount >= max_concurrent_fetches)
|
||||
{
|
||||
|
|
@ -833,10 +885,111 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc
|
|||
LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id));
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion() || fetch_info.mFetchType == FT_FORCED)
|
||||
if (fetch_info.mFetchType == FT_CONTENT_RECURSIVE)
|
||||
{
|
||||
// fetch content only, ignore cat itself
|
||||
uuid_vec_t children;
|
||||
LLInventoryModel::cat_array_t* categories(NULL);
|
||||
LLInventoryModel::item_array_t* items(NULL);
|
||||
gInventory.getDirectDescendentsOf(cat_id, categories, items);
|
||||
|
||||
LLViewerInventoryCategory::EFetchType target_state = LLViewerInventoryCategory::FETCH_RECURSIVE;
|
||||
bool content_done = true;
|
||||
|
||||
// Top limit is 'as many as you can put into url'
|
||||
static LLCachedControl<S32> ais_batch(gSavedSettings, "BatchSizeAIS3", 20);
|
||||
S32 batch_limit = llclamp(ais_batch(), 1, 40);
|
||||
|
||||
for (LLInventoryModel::cat_array_t::iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
LLViewerInventoryCategory* child_cat = (*it);
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN != child_cat->getVersion()
|
||||
|| child_cat->getFetching() >= target_state)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_LISTINGS)
|
||||
{
|
||||
// special case
|
||||
content_done = false;
|
||||
if (children.empty())
|
||||
{
|
||||
// fetch marketplace alone
|
||||
// Should it actually be fetched as FT_FOLDER_AND_CONTENT?
|
||||
children.push_back(child_cat->getUUID());
|
||||
mExpectedFolderIds.push_back(child_cat->getUUID());
|
||||
child_cat->setFetching(target_state);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fetch marketplace alone next run
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
children.push_back(child_cat->getUUID());
|
||||
mExpectedFolderIds.push_back(child_cat->getUUID());
|
||||
child_cat->setFetching(target_state);
|
||||
|
||||
if (children.size() >= batch_limit)
|
||||
{
|
||||
content_done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!children.empty())
|
||||
{
|
||||
// increment before call in case of immediate callback
|
||||
incrFetchFolderCount(1);
|
||||
|
||||
EFetchType type = fetch_info.mFetchType;
|
||||
LLUUID cat_id = cat->getUUID(); // need a copy for lambda
|
||||
AISAPI::completion_t cb = [cat_id, children, type](const LLUUID& response_id)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().onAISContentCalback(cat_id, children, response_id, type);
|
||||
};
|
||||
|
||||
AISAPI::ITEM_TYPE item_type = AISAPI::INVENTORY;
|
||||
if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
{
|
||||
item_type = AISAPI::LIBRARY;
|
||||
}
|
||||
|
||||
AISAPI::FetchCategorySubset(cat_id, children, item_type, true, cb, 0);
|
||||
}
|
||||
|
||||
if (content_done)
|
||||
{
|
||||
// This will have a bit of overlap with onAISContentCalback,
|
||||
// but something else might have dowloaded folders, so verify
|
||||
// every child that is complete has it's children done as well
|
||||
for (LLInventoryModel::cat_array_t::iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
LLViewerInventoryCategory* child_cat = (*it);
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN != child_cat->getVersion())
|
||||
{
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(child_cat->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// send it back to get the rest
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(cat_id, FT_CONTENT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
else if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()
|
||||
|| fetch_info.mFetchType == FT_FORCED)
|
||||
{
|
||||
LLViewerInventoryCategory::EFetchType target_state =
|
||||
fetch_info.mFetchType >= FT_CONTENT_RECURSIVE
|
||||
fetch_info.mFetchType > FT_CONTENT_RECURSIVE
|
||||
? LLViewerInventoryCategory::FETCH_RECURSIVE
|
||||
: LLViewerInventoryCategory::FETCH_NORMAL;
|
||||
// start again if we did a non-recursive fetch before
|
||||
|
|
@ -867,7 +1020,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc
|
|||
else
|
||||
{
|
||||
// Already fetched, check if anything inside needs fetching
|
||||
if (fetch_info.mFetchType >= FT_CONTENT_RECURSIVE)
|
||||
if (fetch_info.mFetchType == FT_RECURSIVE)
|
||||
{
|
||||
LLInventoryModel::cat_array_t * categories(NULL);
|
||||
LLInventoryModel::item_array_t * items(NULL);
|
||||
|
|
@ -881,7 +1034,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc
|
|||
}
|
||||
}
|
||||
}
|
||||
} // else?
|
||||
} // else try to fetch folder either way?
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ public:
|
|||
bool inventoryFetchCompleted() const;
|
||||
bool inventoryFetchInProgress() const;
|
||||
|
||||
void findLostItems();
|
||||
void incrFetchCount(S32 fetching);
|
||||
void findLostItems();
|
||||
void incrFetchCount(S32 fetching);
|
||||
void incrFetchFolderCount(S32 fetching);
|
||||
|
||||
bool isBulkFetchProcessingComplete() const;
|
||||
|
|
@ -82,8 +82,9 @@ protected:
|
|||
|
||||
typedef enum {
|
||||
FT_DEFAULT = 0,
|
||||
FT_FORCED, // request even if already loaded
|
||||
FT_FORCED, // request non-recursively even if already loaded
|
||||
FT_CONTENT_RECURSIVE, // request content recursively
|
||||
FT_FOLDER_AND_CONTENT, // request folder, then content recursively
|
||||
FT_RECURSIVE, // request everything recursively
|
||||
} EFetchType;
|
||||
struct FetchQueueInfo
|
||||
|
|
@ -100,7 +101,8 @@ protected:
|
|||
};
|
||||
typedef std::deque<FetchQueueInfo> fetch_queue_t;
|
||||
|
||||
void onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion);
|
||||
void onAISContentCalback(const LLUUID& request_id, const uuid_vec_t &content_ids, const LLUUID& response_id, EFetchType fetch_type);
|
||||
void onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType fetch_type);
|
||||
void bulkFetchViaAis();
|
||||
void bulkFetchViaAis(const FetchQueueInfo& fetch_info);
|
||||
void bulkFetch();
|
||||
|
|
|
|||
|
|
@ -979,7 +979,10 @@ void LLInventoryPanel::initializeViews(F64 max_time)
|
|||
|
||||
gIdleCallbacks.addFunction(idle, this);
|
||||
|
||||
openStartFolderOrMyInventory();
|
||||
if(mParams.open_first_folder)
|
||||
{
|
||||
openStartFolderOrMyInventory();
|
||||
}
|
||||
|
||||
// Special case for new user login
|
||||
if (gAgent.isFirstLogin())
|
||||
|
|
@ -2349,10 +2352,11 @@ void LLInventorySingleFolderPanel::setSelectCallback(const boost::function<void(
|
|||
|
||||
void LLInventorySingleFolderPanel::initFromParams(const Params& p)
|
||||
{
|
||||
Params fav_params(p);
|
||||
fav_params.start_folder.id = gInventory.getRootFolderID();
|
||||
LLInventoryPanel::initFromParams(p);
|
||||
changeFolderRoot(gInventory.getRootFolderID());
|
||||
mFolderID = gInventory.getRootFolderID();
|
||||
Params pane_params(p);
|
||||
pane_params.open_first_folder = false;
|
||||
pane_params.start_folder.id = mFolderID;
|
||||
LLInventoryPanel::initFromParams(pane_params);
|
||||
}
|
||||
|
||||
void LLInventorySingleFolderPanel::openInCurrentWindow(const LLSD& userdata)
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ public:
|
|||
Optional<LLFolderView::Params> folder_view;
|
||||
Optional<LLFolderViewFolder::Params> folder;
|
||||
Optional<LLFolderViewItem::Params> item;
|
||||
Optional<bool> open_first_folder;
|
||||
|
||||
// All item and folder views will be initialized on init if true (default)
|
||||
// Will initialize on visibility change otherwise.
|
||||
|
|
@ -126,6 +127,7 @@ public:
|
|||
show_root_folder("show_root_folder", false),
|
||||
allow_drop_on_root("allow_drop_on_root", true),
|
||||
use_marketplace_folders("use_marketplace_folders", false),
|
||||
open_first_folder("open_first_folder", true),
|
||||
scroll("scroll"),
|
||||
accepts_drag_and_drop("accepts_drag_and_drop"),
|
||||
folder_view("folder_view"),
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
|
|||
mSingleFolderMode(false),
|
||||
mForceShowInvLayout(false),
|
||||
mViewMode(MODE_COMBINATION),
|
||||
mCombinationShapeDirty(true),
|
||||
mListViewRootUpdatedConnection(),
|
||||
mGalleryRootUpdatedConnection(),
|
||||
mViewMenuButton(nullptr), // <FS:Ansariel> Keep better inventory layout
|
||||
|
|
@ -374,6 +375,8 @@ BOOL LLPanelMainInventory::postBuild()
|
|||
mInventoryGalleryPanel = getChild<LLInventoryGallery>("gallery_view_inv");
|
||||
mGalleryRootUpdatedConnection = mInventoryGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this));
|
||||
|
||||
mCombinationScrollPanel = getChild<LLUICtrl>("combination_view_inventory");
|
||||
|
||||
mCombinationInventoryPanel = getChild<LLInventorySingleFolderPanel>("comb_single_folder_inv");
|
||||
LLInventoryFilter& comb_inv_filter = mCombinationInventoryPanel->getFilter();
|
||||
comb_inv_filter.setFilterThumbnails(LLInventoryFilter::FILTER_EXCLUDE_THUMBNAILS);
|
||||
|
|
@ -387,6 +390,8 @@ BOOL LLPanelMainInventory::postBuild()
|
|||
comb_gallery_filter.markDefault();
|
||||
mCombinationGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, true));
|
||||
|
||||
mCombinationScroller = getChild<LLView>("combination_scroller");
|
||||
|
||||
initListCommandsHandlers();
|
||||
const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
|
||||
const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
|
||||
|
|
@ -402,6 +407,7 @@ BOOL LLPanelMainInventory::postBuild()
|
|||
|
||||
// Trigger callback for focus received so we can deselect items in inbox/outbox
|
||||
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
|
||||
mCombinationShapeDirty = true;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -590,7 +596,7 @@ void LLPanelMainInventory::newFolderWindow(LLUUID folder_id, LLUUID item_to_sele
|
|||
{
|
||||
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
|
||||
if (main_inventory && main_inventory->isSingleFolderMode()
|
||||
&& (main_inventory->getSingleFolderViewRoot() == folder_id))
|
||||
&& (main_inventory->getCurrentSFVRoot() == folder_id))
|
||||
{
|
||||
main_inventory->setFocus(true);
|
||||
if(item_to_select.notNull())
|
||||
|
|
@ -1251,9 +1257,18 @@ BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
|||
}
|
||||
|
||||
// virtual
|
||||
void LLPanelMainInventory::changed(U32)
|
||||
void LLPanelMainInventory::changed(U32 mask)
|
||||
{
|
||||
updateItemcountText();
|
||||
if ((mask & LLInventoryObserver::REBUILD)
|
||||
|| (mask & LLInventoryObserver::STRUCTURE)
|
||||
|| (mask & LLInventoryObserver::REMOVE)
|
||||
|| (mask & LLInventoryObserver::ADD)
|
||||
|| (mask & LLInventoryObserver::LABEL))
|
||||
{
|
||||
// todo: can be limited to just observed folder
|
||||
mCombinationShapeDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::setFocusFilterEditor()
|
||||
|
|
@ -1264,6 +1279,13 @@ void LLPanelMainInventory::setFocusFilterEditor()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLPanelMainInventory::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
mCombinationShapeDirty = true;
|
||||
LLPanel::reshape(width, height, called_from_parent);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLPanelMainInventory::draw()
|
||||
{
|
||||
|
|
@ -1293,6 +1315,7 @@ void LLPanelMainInventory::draw()
|
|||
mActivePanel->setSortOrder(order);
|
||||
mResortActivePanel = false;
|
||||
}
|
||||
|
||||
LLPanel::draw();
|
||||
updateItemcountText();
|
||||
updateCombinationVisibility();
|
||||
|
|
@ -1982,9 +2005,9 @@ void LLPanelMainInventory::toggleViewMode()
|
|||
getChild<LLPanel>("default_inventory_panel")->setVisible(!mSingleFolderMode);
|
||||
getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode());
|
||||
getChild<LLPanel>("gallery_view_inventory")->setVisible(mSingleFolderMode && isGalleryViewMode());
|
||||
getChild<LLPanel>("combination_view_inventory")->setVisible(mSingleFolderMode && isCombinationViewMode());
|
||||
getChild<LLLayoutPanel>("nav_buttons")->setVisible(mSingleFolderMode);
|
||||
getChild<LLButton>("view_mode_btn")->setImageOverlay(mSingleFolderMode ? getString("default_mode_btn") : getString("single_folder_mode_btn"));
|
||||
mCombinationScrollPanel->setVisible(mSingleFolderMode && isCombinationViewMode());
|
||||
|
||||
// <FS:Ansariel> Disable Expand/Collapse buttons in single folder mode
|
||||
getChild<LLLayoutPanel>("collapse_expand_buttons")->setVisible(!mSingleFolderMode);
|
||||
|
|
@ -2446,6 +2469,7 @@ void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
|
|||
}
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
mCombinationShapeDirty = true;
|
||||
}
|
||||
|
||||
bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)
|
||||
|
|
@ -2911,27 +2935,57 @@ void LLPanelMainInventory::onCombinationRootChanged(bool gallery_clicked)
|
|||
}
|
||||
mForceShowInvLayout = false;
|
||||
updateTitle();
|
||||
|
||||
//force update scroll container
|
||||
mCombinationShapeDirty = true;
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::updateCombinationVisibility()
|
||||
{
|
||||
if(mSingleFolderMode && isCombinationViewMode())
|
||||
if(mSingleFolderMode && isCombinationViewMode() && mCombinationShapeDirty)
|
||||
{
|
||||
bool is_gallery_empty = !mCombinationGalleryPanel->hasVisibleItems();
|
||||
bool show_inv_pane = mCombinationInventoryPanel->hasVisibleItems() || is_gallery_empty || mForceShowInvLayout;
|
||||
getChild<LLLayoutPanel>("comb_gallery_layout")->setVisible(!is_gallery_empty);
|
||||
getChild<LLLayoutPanel>("comb_inventory_layout")->setVisible(show_inv_pane);
|
||||
mCombinationInventoryPanel->getRootFolder()->setForceArrange(!show_inv_pane);
|
||||
if(mCombinationInventoryPanel->hasVisibleItems())
|
||||
{
|
||||
mForceShowInvLayout = false;
|
||||
}
|
||||
if(is_gallery_empty)
|
||||
mCombinationShapeDirty = false;
|
||||
mCombinationInventoryPanel->reshape(1,1); // HACK: force reduce visible area
|
||||
if (!mCombinationGalleryPanel->hasVisibleItems())
|
||||
{
|
||||
mCombinationGalleryPanel->handleModifiedFilter();
|
||||
}
|
||||
|
||||
getActivePanel()->getRootFolder();
|
||||
LLRect inv_rect = mCombinationInventoryPanel->getRect();
|
||||
LLRect inv_inner_rect = mCombinationInventoryPanel->getScrollableContainer()->getScrolledViewRect();
|
||||
LLRect galery_rect = mCombinationGalleryPanel->getRect();
|
||||
LLRect inner_galery_rect = mCombinationGalleryPanel->getScrollableContainer()->getScrolledViewRect();
|
||||
LLScrollContainer* scroll = static_cast<LLScrollContainer*>(mCombinationScrollPanel);
|
||||
LLRect scroller_window_rect = scroll->getContentWindowRect();
|
||||
S32 desired_width = llmax(inv_inner_rect.getWidth(), scroller_window_rect.getWidth());
|
||||
const S32 BORDER_PAD = 2; // two sides
|
||||
|
||||
inv_rect.mBottom = 0;
|
||||
inv_rect.mRight = inv_rect.mLeft + desired_width;
|
||||
if (!mCombinationGalleryPanel->hasVisibleItems() || mCombinationInventoryPanel->hasVisibleItems())
|
||||
{
|
||||
inv_rect.mTop = inv_rect.mBottom + inv_inner_rect.getHeight() + BORDER_PAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
inv_rect.mTop = inv_rect.mBottom;
|
||||
}
|
||||
|
||||
galery_rect.mBottom = inv_rect.mTop;
|
||||
galery_rect.mRight = galery_rect.mLeft + scroller_window_rect.getWidth();
|
||||
if (mCombinationGalleryPanel->hasVisibleItems())
|
||||
{
|
||||
mCombinationGalleryPanel->setVisible(true);
|
||||
galery_rect.mTop = galery_rect.mBottom + inner_galery_rect.getHeight() + BORDER_PAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCombinationGalleryPanel->setVisible(false);
|
||||
galery_rect.mTop = galery_rect.mBottom;
|
||||
}
|
||||
|
||||
mCombinationScroller->reshape(desired_width, inv_rect.getHeight() + galery_rect.getHeight(), true);
|
||||
mCombinationGalleryPanel->setShape(galery_rect, false);
|
||||
mCombinationInventoryPanel->setShape(inv_rect, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2996,7 +3050,7 @@ void LLPanelMainInventory::setViewMode(EViewModeType mode)
|
|||
|
||||
getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode());
|
||||
getChild<LLPanel>("gallery_view_inventory")->setVisible(mSingleFolderMode && isGalleryViewMode());
|
||||
getChild<LLPanel>("combination_view_inventory")->setVisible(mSingleFolderMode && isCombinationViewMode());
|
||||
mCombinationScrollPanel->setVisible(mSingleFolderMode && isCombinationViewMode());
|
||||
|
||||
if(isListViewMode())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -85,8 +85,9 @@ public:
|
|||
EAcceptance* accept,
|
||||
std::string& tooltip_msg);
|
||||
/*virtual*/ void changed(U32);
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void onVisibilityChange ( BOOL new_visibility );
|
||||
/*virtual*/ void onVisibilityChange ( BOOL new_visibility );
|
||||
// <FS:Ansariel> CTRL-F focusses local search editor
|
||||
/*virtual*/ bool hasAccelerators() const { return true; }
|
||||
|
||||
|
|
@ -160,8 +161,6 @@ protected:
|
|||
|
||||
static BOOL filtersVisible(void* user_data);
|
||||
void onClearSearch();
|
||||
static void onFoldersByName(void *user_data);
|
||||
static BOOL checkFoldersByName(void *user_data);
|
||||
|
||||
static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward);
|
||||
void onFilterSelected();
|
||||
|
|
@ -220,8 +219,10 @@ private:
|
|||
LLInventorySingleFolderPanel* mSingleFolderPanelInventory;
|
||||
LLInventoryGallery* mInventoryGalleryPanel;
|
||||
|
||||
LLUICtrl* mCombinationScrollPanel;
|
||||
LLInventorySingleFolderPanel* mCombinationInventoryPanel;
|
||||
LLInventoryGallery* mCombinationGalleryPanel;
|
||||
LLView* mCombinationScroller;
|
||||
|
||||
// <FS:Zi> Filter dropdown
|
||||
LLComboBox* mFilterComboBox;
|
||||
|
|
@ -295,6 +296,7 @@ private:
|
|||
bool mNeedUploadCost;
|
||||
|
||||
bool mForceShowInvLayout;
|
||||
bool mCombinationShapeDirty;
|
||||
// List Commands //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,10 +64,13 @@ LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params
|
|||
: LLInventoryPanel(p)
|
||||
{
|
||||
LLInboxNewItemsStorage::getInstance()->load();
|
||||
LLInboxNewItemsStorage::getInstance()->addInboxPanel(this);
|
||||
}
|
||||
|
||||
LLInboxInventoryPanel::~LLInboxInventoryPanel()
|
||||
{}
|
||||
{
|
||||
LLInboxNewItemsStorage::getInstance()->removeInboxPanel(this);
|
||||
}
|
||||
|
||||
void LLInboxInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
|
||||
{
|
||||
|
|
@ -128,6 +131,21 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b
|
|||
return LLUICtrlFactory::create<LLInboxFolderViewItem>(params);
|
||||
}
|
||||
|
||||
void LLInboxInventoryPanel::onRemoveItemFreshness(const LLUUID& item_id)
|
||||
{
|
||||
LLInboxFolderViewFolder* inbox_folder_view = dynamic_cast<LLInboxFolderViewFolder*>(getFolderByID(item_id));
|
||||
if(inbox_folder_view)
|
||||
{
|
||||
inbox_folder_view->setFresh(false);
|
||||
}
|
||||
|
||||
LLInboxFolderViewItem* inbox_item_view = dynamic_cast<LLInboxFolderViewItem*>(getItemByID(item_id));
|
||||
if(inbox_item_view)
|
||||
{
|
||||
inbox_item_view->setFresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLInboxFolderViewFolder Implementation
|
||||
//
|
||||
|
|
@ -364,4 +382,18 @@ void LLInboxNewItemsStorage::load()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLInboxNewItemsStorage::removeItem(const LLUUID& id)
|
||||
{
|
||||
mNewItemsIDs.erase(id);
|
||||
|
||||
//notify inbox panels
|
||||
for (auto inbox : mInboxPanels)
|
||||
{
|
||||
if(inbox)
|
||||
{
|
||||
inbox->onRemoveItemFreshness(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// eof
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ public:
|
|||
void initFromParams(const LLInventoryPanel::Params&);
|
||||
LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop);
|
||||
LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge);
|
||||
|
||||
void onRemoveItemFreshness(const LLUUID& item_id);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -77,6 +79,7 @@ public:
|
|||
void deFreshify();
|
||||
|
||||
bool isFresh() const { return mFresh; }
|
||||
void setFresh(bool is_fresh) { mFresh = is_fresh; }
|
||||
|
||||
protected:
|
||||
bool mFresh;
|
||||
|
|
@ -108,6 +111,7 @@ public:
|
|||
void deFreshify();
|
||||
|
||||
bool isFresh() const { return mFresh; }
|
||||
void setFresh(bool is_fresh) { mFresh = is_fresh; }
|
||||
|
||||
protected:
|
||||
bool mFresh;
|
||||
|
|
@ -125,11 +129,16 @@ public:
|
|||
void load();
|
||||
|
||||
void addFreshItem(const LLUUID& id) { mNewItemsIDs.insert(id); }
|
||||
void removeItem(const LLUUID& id) { mNewItemsIDs.erase(id); }
|
||||
void removeItem(const LLUUID& id);
|
||||
bool isItemFresh(const LLUUID& id) { return (mNewItemsIDs.find(id) != mNewItemsIDs.end()); }
|
||||
|
||||
void addInboxPanel(LLInboxInventoryPanel* inbox) { mInboxPanels.insert(inbox); }
|
||||
void removeInboxPanel(LLInboxInventoryPanel* inbox) { mInboxPanels.erase(inbox); }
|
||||
|
||||
private:
|
||||
std::set<LLUUID> mNewItemsIDs;
|
||||
|
||||
std::set<LLInboxInventoryPanel*> mInboxPanels;
|
||||
};
|
||||
|
||||
#endif //LL_INBOXINVENTORYPANEL_H
|
||||
|
|
|
|||
|
|
@ -2985,7 +2985,7 @@ bool idle_startup()
|
|||
gAgentWearables.sendDummyAgentWearablesUpdate();
|
||||
}
|
||||
// </FS:Ansariel> [Legacy Bake]
|
||||
callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance);
|
||||
callAfterCOFFetch(set_flags_and_update_appearance);
|
||||
}
|
||||
|
||||
display_startup();
|
||||
|
|
|
|||
|
|
@ -385,9 +385,9 @@ bool LLToolBarView::loadToolbars(bool force_default)
|
|||
}
|
||||
|
||||
// SL-18581: Don't show the starter avatar toolbar button for NUX users
|
||||
LLViewerInventoryCategory* my_outfits_cat = gInventory.getCategory(gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
|
||||
if (gAgent.isFirstLogin())
|
||||
{
|
||||
LLViewerInventoryCategory* my_outfits_cat = gInventory.getCategory(gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
|
||||
LL_WARNS() << "First login: checking for NUX user." << LL_ENDL;
|
||||
if (my_outfits_cat != NULL && my_outfits_cat->getDescendentCount() > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -780,9 +780,16 @@ void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchTyp
|
|||
{
|
||||
if (mDescendentsRequested.hasExpired() || (mFetching == FETCH_NONE))
|
||||
{
|
||||
const F32 FETCH_TIMER_EXPIRY = 30.0f;
|
||||
mDescendentsRequested.reset();
|
||||
mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY);
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
mDescendentsRequested.setTimerExpirySec(AISAPI::HTTP_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
const F32 FETCH_TIMER_EXPIRY = 30.0f;
|
||||
mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY);
|
||||
}
|
||||
}
|
||||
mFetching = fetching;
|
||||
}
|
||||
|
|
@ -1600,19 +1607,18 @@ void update_inventory_category(
|
|||
return;
|
||||
}
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
|
||||
new_cat->fromLLSD(updates);
|
||||
// <FS:Ansariel> [UDP-Msg]
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
// </FS:Ansariel> [UDP-Msg]
|
||||
LLSD new_llsd = new_cat->asLLSD();
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::UpdateCategory(cat_id, new_llsd, cr);
|
||||
AISAPI::UpdateCategory(cat_id, updates, cr);
|
||||
// <FS:Ansariel> [UDP-Msg]
|
||||
}
|
||||
else
|
||||
{
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
|
||||
new_cat->fromLLSD(updates);
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
|
|
|
|||
|
|
@ -900,7 +900,7 @@
|
|||
follows="all"
|
||||
layout="topleft" />
|
||||
</panel>
|
||||
<panel
|
||||
<scroll_container
|
||||
follows="all"
|
||||
halign="center"
|
||||
height="319"
|
||||
|
|
@ -910,74 +910,48 @@
|
|||
top_delta="0"
|
||||
visible="false"
|
||||
width="326">
|
||||
<layout_stack
|
||||
follows="all"
|
||||
height="319"
|
||||
width="326"
|
||||
animate="false"
|
||||
drag_handle_gap="13"
|
||||
drag_handle_thickness="6"
|
||||
drag_handle_first_indent="18"
|
||||
drag_handle_second_indent="18"
|
||||
drag_handle_color="PanelGray"
|
||||
drag_handle_shift="5"
|
||||
show_drag_handle="true"
|
||||
top="0"
|
||||
left="0"
|
||||
orientation="vertical">
|
||||
<layout_panel
|
||||
border="false"
|
||||
bevel_style="in"
|
||||
user_resize="true"
|
||||
auto_resize="true"
|
||||
height="209"
|
||||
width="326"
|
||||
min_width="150"
|
||||
name="comb_gallery_layout">
|
||||
<panel
|
||||
class="inventory_gallery"
|
||||
filename="panel_inventory_gallery.xml"
|
||||
left="0"
|
||||
top_pad="0"
|
||||
height="209"
|
||||
width="326"
|
||||
name="comb_gallery_view_inv"
|
||||
background_visible="true"
|
||||
follows="all"
|
||||
layout="topleft">
|
||||
<panel
|
||||
name="combination_scroller"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="0"
|
||||
height="20"
|
||||
width="304">
|
||||
<panel
|
||||
class="inventory_gallery"
|
||||
filename="panel_inventory_gallery.xml"
|
||||
follows="left|right"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="0"
|
||||
height="10"
|
||||
width="303"
|
||||
name="comb_gallery_view_inv"
|
||||
background_visible="true">
|
||||
</panel>
|
||||
<single_folder_inventory_panel
|
||||
name="comb_single_folder_inv"
|
||||
follows="left|right"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="200"
|
||||
height="10"
|
||||
width="303"
|
||||
show_item_link_overlays="true"
|
||||
background_visible="true"
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<item
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
<folder
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
</single_folder_inventory_panel>
|
||||
</panel>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
border="false"
|
||||
bevel_style="in"
|
||||
user_resize="true"
|
||||
auto_resize="true"
|
||||
height="110"
|
||||
width="326"
|
||||
name="comb_inventory_layout">
|
||||
<single_folder_inventory_panel
|
||||
name="comb_single_folder_inv"
|
||||
follows="all"
|
||||
left="0"
|
||||
top="1"
|
||||
height="110"
|
||||
width="326"
|
||||
layout="topleft"
|
||||
show_item_link_overlays="true"
|
||||
background_visible="true"
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<item
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
<folder
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
</single_folder_inventory_panel>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
</scroll_container>
|
||||
<panel
|
||||
follows="left|right|bottom"
|
||||
height="25"
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@
|
|||
follows="all"
|
||||
layout="topleft" />
|
||||
</panel>
|
||||
<panel
|
||||
<scroll_container
|
||||
follows="all"
|
||||
halign="center"
|
||||
height="338"
|
||||
|
|
@ -334,74 +334,48 @@
|
|||
top_delta="0"
|
||||
visible="false"
|
||||
width="322">
|
||||
<layout_stack
|
||||
follows="all"
|
||||
height="338"
|
||||
width="322"
|
||||
animate="false"
|
||||
drag_handle_gap="13"
|
||||
drag_handle_thickness="6"
|
||||
drag_handle_first_indent="18"
|
||||
drag_handle_second_indent="18"
|
||||
drag_handle_color="PanelGray"
|
||||
drag_handle_shift="5"
|
||||
show_drag_handle="true"
|
||||
top="0"
|
||||
left="0"
|
||||
orientation="vertical">
|
||||
<layout_panel
|
||||
border="false"
|
||||
bevel_style="in"
|
||||
user_resize="true"
|
||||
auto_resize="true"
|
||||
height="228"
|
||||
width="322"
|
||||
min_width="150"
|
||||
name="comb_gallery_layout">
|
||||
<panel
|
||||
class="inventory_gallery"
|
||||
filename="panel_inventory_gallery.xml"
|
||||
left="0"
|
||||
top_pad="0"
|
||||
height="228"
|
||||
width="322"
|
||||
name="comb_gallery_view_inv"
|
||||
background_visible="true"
|
||||
follows="all"
|
||||
layout="topleft">
|
||||
<panel
|
||||
name="combination_scroller"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="0"
|
||||
height="20"
|
||||
width="300">
|
||||
<panel
|
||||
class="inventory_gallery"
|
||||
filename="panel_inventory_gallery.xml"
|
||||
follows="left|right"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="0"
|
||||
height="10"
|
||||
width="299"
|
||||
name="comb_gallery_view_inv"
|
||||
background_visible="true">
|
||||
</panel>
|
||||
<single_folder_inventory_panel
|
||||
name="comb_single_folder_inv"
|
||||
follows="left|right"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
top="200"
|
||||
height="10"
|
||||
width="299"
|
||||
show_item_link_overlays="true"
|
||||
background_visible="true"
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<item
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
<folder
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
</single_folder_inventory_panel>
|
||||
</panel>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
border="false"
|
||||
bevel_style="in"
|
||||
user_resize="true"
|
||||
auto_resize="true"
|
||||
height="110"
|
||||
width="322"
|
||||
name="comb_inventory_layout">
|
||||
<single_folder_inventory_panel
|
||||
name="comb_single_folder_inv"
|
||||
follows="all"
|
||||
left="0"
|
||||
top="1"
|
||||
height="110"
|
||||
width="322"
|
||||
layout="topleft"
|
||||
show_item_link_overlays="true"
|
||||
background_visible="true"
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<item
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
<folder
|
||||
single_folder_mode="true"
|
||||
folder_indentation="-8"/>
|
||||
</single_folder_inventory_panel>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
</scroll_container>
|
||||
<panel
|
||||
follows="left|right|bottom"
|
||||
height="25"
|
||||
|
|
|
|||
Loading…
Reference in New Issue