diff options
Diffstat (limited to 'indra/newview/llfriendcard.cpp')
-rw-r--r-- | indra/newview/llfriendcard.cpp | 166 |
1 files changed, 161 insertions, 5 deletions
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 97b7f3e9ad..c956657825 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -91,8 +91,44 @@ const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollect return LLUUID::null; } + +// LLViewerInventoryCategory::fetchDescendents has it own period of fetching. +// for now it is FETCH_TIMER_EXPIRY = 10.0f; So made our period a bit more. +const F32 FETCH_FRIENDS_DESCENDENTS_PERIOD = 11.0f; + + +/** + * Intended to call passed callback after the specified period of time. + * + * Implemented to fix an issue when Inventory folders are in incomplete state. See EXT-2061, EXT-1935, EXT-813. + * For now it uses to periodically sync Inventory Friends/All folder with a Agent's Friends List + * until it is complete. + */ +class FriendListUpdater : public LLEventTimer +{ +public: + typedef boost::function<bool()> callback_t; + + FriendListUpdater(callback_t cb, F32 period) + : LLEventTimer(period) + , mCallback(cb) + { + mEventTimer.start(); + } + + virtual BOOL tick() // from LLEventTimer + { + return mCallback(); + } + +private: + callback_t mCallback; +}; + + // LLFriendCardsManager Constructor / Destructor LLFriendCardsManager::LLFriendCardsManager() +: mFriendsAllFolderCompleted(true) { LLAvatarTracker::instance().addObserver(this); } @@ -135,14 +171,14 @@ const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID) // and this method must be called before any actions with friend list void LLFriendCardsManager::ensureFriendFoldersExist() { - LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); if (friendFolderUUID.isNull()) { friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID, - LLAssetType::AT_CALLINGCARD, get_friend_folder_name()); + LLFolderType::FT_CALLINGCARD, get_friend_folder_name()); } LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl(); @@ -150,7 +186,7 @@ void LLFriendCardsManager::ensureFriendFoldersExist() if (friendAllSubfolderUUID.isNull()) { friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID, - LLAssetType::AT_CALLINGCARD, get_friend_all_subfolder_name()); + LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); } } @@ -166,6 +202,93 @@ bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* i return items.count() > 0; } + +bool LLFriendCardsManager::isObjDirectDescendentOfCategory(const LLInventoryObject* obj, + const LLViewerInventoryCategory* cat) const +{ + // we need both params to proceed. + if ( !obj || !cat ) + return false; + + // Need to check that target category is in the Calling Card/Friends folder. + // In other case function returns unpredictable result. + if ( !isCategoryInFriendFolder(cat) ) + return false; + + bool result = false; + + LLInventoryModel::item_array_t* items; + LLInventoryModel::cat_array_t* cats; + + gInventory.lockDirectDescendentArrays(cat->getUUID(), cats, items); + if ( items ) + { + if ( obj->getType() == LLAssetType::AT_CALLINGCARD ) + { + // For CALLINGCARD compare items by creator's id, if they are equal assume + // that it is same card and return true. Note: UUID's of compared items + // may be not equal. Also, we already know that obj should be type of LLInventoryItem, + // but in case inventory database is broken check what dynamic_cast returns. + const LLInventoryItem* item = dynamic_cast < const LLInventoryItem* > (obj); + if ( item ) + { + LLUUID creator_id = item->getCreatorUUID(); + LLViewerInventoryItem* cur_item = NULL; + for ( S32 i = items->count() - 1; i >= 0; --i ) + { + cur_item = items->get(i); + if ( creator_id == cur_item->getCreatorUUID() ) + { + result = true; + break; + } + } + } + } + else + { + // Else check that items have same type and name. + // Note: UUID's of compared items also may be not equal. + std::string obj_name = obj->getName(); + LLViewerInventoryItem* cur_item = NULL; + for ( S32 i = items->count() - 1; i >= 0; --i ) + { + cur_item = items->get(i); + if ( obj->getType() != cur_item->getType() ) + continue; + if ( obj_name == cur_item->getName() ) + { + result = true; + break; + } + } + } + } + if ( !result && cats ) + { + // There is no direct descendent in items, so check categories. + // If target obj and descendent category have same type and name + // then return true. Note: UUID's of compared items also may be not equal. + std::string obj_name = obj->getName(); + LLViewerInventoryCategory* cur_cat = NULL; + for ( S32 i = cats->count() - 1; i >= 0; --i ) + { + cur_cat = cats->get(i); + if ( obj->getType() != cur_cat->getType() ) + continue; + if ( obj_name == cur_cat->getName() ) + { + result = true; + break; + } + } + } + gInventory.unlockDirectDescendentArrays(cat->getUUID()); + + return result; +} + + bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const { if (NULL == cat) @@ -182,7 +305,7 @@ bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID); } -void LLFriendCardsManager::syncFriendsFolder() +bool LLFriendCardsManager::syncFriendsFolder() { //lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent LLFriendCardsManager::instance().ensureFriendFoldersExist(); @@ -210,11 +333,35 @@ void LLFriendCardsManager::syncFriendsFolder() // 2. Add missing Friend Cards for friends LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); llinfos << "try to build friends, count: " << all_buddies.size() << llendl; + mFriendsAllFolderCompleted = true; for(; buddy_it != all_buddies.end(); ++buddy_it) { const LLUUID& buddy_id = (*buddy_it).first; addFriendCardToInventory(buddy_id); } + + if (!mFriendsAllFolderCompleted) + { + forceFriendListIsLoaded(findFriendAllSubfolderUUIDImpl()); + + static bool timer_started = false; + if (!timer_started) + { + lldebugs << "Create and start timer to sync Inventory Friends All folder with Friends list" << llendl; + + // do not worry about destruction of the FriendListUpdater. + // It will be deleted by LLEventTimer::updateClass when FriendListUpdater::tick() returns true. + new FriendListUpdater(boost::bind(&LLFriendCardsManager::syncFriendsFolder, this), + FETCH_FRIENDS_DESCENDENTS_PERIOD); + } + timer_started = true; + } + else + { + lldebugs << "Friends/All Inventory folder is synchronized with the Agent's Friends List" << llendl; + } + + return mFriendsAllFolderCompleted; } void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const @@ -264,7 +411,7 @@ void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBud /************************************************************************/ const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const { - LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); std::string friendFolderName = get_friend_folder_name(); @@ -374,7 +521,9 @@ bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) LLUUID friendListFolderID = findFriendAllSubfolderUUIDImpl(); if (shouldBeAdded && !invModel->isCategoryComplete(friendListFolderID)) { + mFriendsAllFolderCompleted = false; shouldBeAdded = false; + lldebugs << "Friends/All category is not completed" << llendl; } if (shouldBeAdded) { @@ -433,4 +582,11 @@ void LLFriendCardsManager::onFriendListUpdate(U32 changed_mask) } } +void LLFriendCardsManager::forceFriendListIsLoaded(const LLUUID& folder_id) const +{ + bool fetching_inventory = gInventory.fetchDescendentsOf(folder_id); + lldebugs << "Trying to fetch descendants of Friends/All Inventory folder, fetched: " + << fetching_inventory << llendl; +} + // EOF |