diff options
| author | Sergei Litovchuk <slitovchuk@productengine.com> | 2009-11-13 15:08:41 +0200 | 
|---|---|---|
| committer | Sergei Litovchuk <slitovchuk@productengine.com> | 2009-11-13 15:08:41 +0200 | 
| commit | 61556f1acf36a1a8fc459fd17a8c0a4a74cc6eeb (patch) | |
| tree | 618c8c77a7c061d891dead94af1cc96dce1f83c8 /indra | |
| parent | 03a0b86335216ec22192c353b7bd4d9ee58dc732 (diff) | |
Fixed EXT-2320 "Viewer creates empty Friends folders every startup".
- Added check for "Friends" folder and all its contents to be fetched from server. Only after fetch is complete friends cards are synchronized with agent's buddies list.
--HG--
branch : product-engine
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/newview/llfriendcard.cpp | 265 | ||||
| -rw-r--r-- | indra/newview/llfriendcard.h | 47 | ||||
| -rw-r--r-- | indra/newview/llstartup.cpp | 7 | 
3 files changed, 172 insertions, 147 deletions
| diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 1ff2566dca..481b75cf73 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -91,44 +91,39 @@ 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. + * Class for fetching initial friend cards data   * - * 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 + * Implemented to fix an issue when Inventory folders are in incomplete state. + * See EXT-2320, EXT-2061, EXT-1935, EXT-813. + * Uses a callback to sync Inventory Friends/All folder with agent's Friends List. + */ +class LLInitialFriendCardsFetch : public LLInventoryFetchDescendentsObserver  {  public: -	typedef boost::function<bool()> callback_t; +	typedef boost::function<void()> callback_t; -	FriendListUpdater(callback_t cb, F32 period) -		:	LLEventTimer(period) -		,	mCallback(cb) -	{ -		mEventTimer.start(); -	} +	LLInitialFriendCardsFetch(callback_t cb) +		:	mCheckFolderCallback(cb)	{} -	virtual BOOL tick() // from LLEventTimer -	{ -		return mCallback(); -	} +	/* virtual */ void done();  private: -	callback_t		mCallback; +	callback_t		mCheckFolderCallback;  }; +void LLInitialFriendCardsFetch::done() +{ +	// This observer is no longer needed. +	gInventory.removeObserver(this); + +	mCheckFolderCallback(); + +	delete this; +}  // LLFriendCardsManager Constructor / Destructor  LLFriendCardsManager::LLFriendCardsManager() -: mFriendsAllFolderCompleted(true)  {  	LLAvatarTracker::instance().addObserver(this);  } @@ -167,30 +162,6 @@ const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID)  	return rv;  } -// be sure LLInventoryModel::buildParentChildMap() has been called before it. -// and this method must be called before any actions with friend list -void LLFriendCardsManager::ensureFriendFoldersExist() -{ -	const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); - -	LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); - -	if (friendFolderUUID.isNull()) -	{ -		friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID, -			LLFolderType::FT_CALLINGCARD, get_friend_folder_name()); -	} - -	LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl(); - -	if (friendAllSubfolderUUID.isNull()) -	{ -		friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID, -			LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); -	} -} - -  bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* item)  {  	if (item->getType() != LLAssetType::AT_CALLINGCARD) @@ -305,63 +276,12 @@ bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const  	return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID);  } -bool LLFriendCardsManager::syncFriendsFolder() +void LLFriendCardsManager::syncFriendCardsFolders()  { -	//lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent -	LLFriendCardsManager::instance().ensureFriendFoldersExist(); - -	LLAvatarTracker::buddy_map_t all_buddies; -	LLAvatarTracker::instance().copyBuddyList(all_buddies); - -	// 1. Remove Friend Cards for non-friends -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; - -	gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH); -	 -	LLInventoryModel::item_array_t::const_iterator it; -	for (it = items.begin(); it != items.end(); ++it) -	{ -		lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl; -		if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID())) -		{ -			lldebugs << "NONEXISTS, so remove it" << llendl; -			removeFriendCardFromInventory((*it)->getCreatorUUID()); -		} -	} - -	// 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; -	} +	const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); -	return mFriendsAllFolderCompleted; +	fetchAndCheckFolderDescendents(callingCardsFolderID, +			boost::bind(&LLFriendCardsManager::ensureFriendsFolderExists, this));  }  void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const @@ -482,6 +402,122 @@ void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInve  	}  } +void LLFriendCardsManager::fetchAndCheckFolderDescendents(const LLUUID& folder_id,  callback_t cb) +{ +	// This instance will be deleted in LLInitialFriendCardsFetch::done(). +	LLInitialFriendCardsFetch* fetch = new LLInitialFriendCardsFetch(cb); + +	LLInventoryFetchDescendentsObserver::folder_ref_t folders; +	folders.push_back(folder_id); + +	fetch->fetchDescendents(folders); +	if(fetch->isEverythingComplete()) +	{ +		// everything is already here - call done. +		fetch->done(); +	} +	else +	{ +		// it's all on it's way - add an observer, and the inventory +		// will call done for us when everything is here. +		gInventory.addObserver(fetch); +	} +} + +// Make sure LLInventoryModel::buildParentChildMap() has been called before it. +// This method must be called before any actions with friends list. +void LLFriendCardsManager::ensureFriendsFolderExists() +{ +	const LLUUID calling_cards_folder_ID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + +	// If "Friends" folder exists in "Calling Cards" we should check if "All" sub-folder +	// exists in "Friends", otherwise we create it. +	LLUUID friends_folder_ID = findFriendFolderUUIDImpl(); +	if (friends_folder_ID.notNull()) +	{ +		fetchAndCheckFolderDescendents(friends_folder_ID, +				boost::bind(&LLFriendCardsManager::ensureFriendsAllFolderExists, this)); +	} +	else +	{ +		if (!gInventory.isCategoryComplete(calling_cards_folder_ID)) +		{ +			LLViewerInventoryCategory* cat = gInventory.getCategory(calling_cards_folder_ID); +			std::string cat_name = cat ? cat->getName() : "unknown"; +			llwarns << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << llendl; +		} + +		friends_folder_ID = gInventory.createNewCategory(calling_cards_folder_ID, +			LLFolderType::FT_CALLINGCARD, get_friend_folder_name()); + +		gInventory.createNewCategory(friends_folder_ID, +			LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); + +		// Now when we have all needed folders we can sync their contents with buddies list. +		syncFriendsFolder(); +	} +} + +// Make sure LLFriendCardsManager::ensureFriendsFolderExists() has been called before it. +void LLFriendCardsManager::ensureFriendsAllFolderExists() +{ +	LLUUID friends_all_folder_ID = findFriendAllSubfolderUUIDImpl(); +	if (friends_all_folder_ID.notNull()) +	{ +		fetchAndCheckFolderDescendents(friends_all_folder_ID, +				boost::bind(&LLFriendCardsManager::syncFriendsFolder, this)); +	} +	else +	{ +		LLUUID friends_folder_ID = findFriendFolderUUIDImpl(); + +		if (!gInventory.isCategoryComplete(friends_folder_ID)) +		{ +			LLViewerInventoryCategory* cat = gInventory.getCategory(friends_folder_ID); +			std::string cat_name = cat ? cat->getName() : "unknown"; +			llwarns << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << llendl; +		} + +		friends_all_folder_ID = gInventory.createNewCategory(friends_folder_ID, +			LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); + +		// Now when we have all needed folders we can sync their contents with buddies list. +		syncFriendsFolder(); +	} +} + +void LLFriendCardsManager::syncFriendsFolder() +{ +	LLAvatarTracker::buddy_map_t all_buddies; +	LLAvatarTracker::instance().copyBuddyList(all_buddies); + +	// 1. Remove Friend Cards for non-friends +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; + +	gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	LLInventoryModel::item_array_t::const_iterator it; +	for (it = items.begin(); it != items.end(); ++it) +	{ +		lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl; +		if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID())) +		{ +			lldebugs << "NONEXISTS, so remove it" << llendl; +			removeFriendCardFromInventory((*it)->getCreatorUUID()); +		} +	} + +	// 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; +	for(; buddy_it != all_buddies.end(); ++buddy_it) +	{ +		const LLUUID& buddy_id = (*buddy_it).first; +		addFriendCardToInventory(buddy_id); +	} +} +  class CreateFriendCardCallback : public LLInventoryCallback  {  public: @@ -494,9 +530,8 @@ public:  	}  }; -bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) +void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)  { -	LLInventoryModel* invModel = &gInventory;  	bool shouldBeAdded = true;  	std::string name; @@ -518,13 +553,6 @@ bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)  		lldebugs << "is found in sentRequests: " << name << llendl;   	} -	LLUUID friendListFolderID = findFriendAllSubfolderUUIDImpl(); -	if (friendListFolderID.notNull() && shouldBeAdded && !invModel->isCategoryComplete(friendListFolderID)) -	{ -		mFriendsAllFolderCompleted = false; -		shouldBeAdded = false; -		lldebugs << "Friends/All category is not completed" << llendl;  -	}  	if (shouldBeAdded)  	{  		putAvatarData(avatarID); @@ -533,10 +561,8 @@ bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)  		// TODO: mantipov: Is CreateFriendCardCallback really needed? Probably not  		LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback(); -		create_inventory_callingcard(avatarID, friendListFolderID, cb); +		create_inventory_callingcard(avatarID, findFriendAllSubfolderUUIDImpl(), cb);  	} - -	return shouldBeAdded;  }  void LLFriendCardsManager::removeFriendCardFromInventory(const LLUUID& avatarID) @@ -582,11 +608,4 @@ 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 diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index feea05bc1d..98dc3153d0 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -58,14 +58,6 @@ public:  	}  	/** -	 *	Ensures that all necessary folders are created in Inventory. -	 *  -	 *	For now it processes Calling Card, Calling Card/Friends & Calling Card/Friends/All folders -	 */ -	void ensureFriendFoldersExist(); - - -	/**  	 *	Determines if specified Inventory Calling Card exists in any of lists   	 *	in the Calling Card/Friends/ folder (Default, or Custom)  	 */ @@ -88,11 +80,10 @@ public:  	bool isAnyFriendCategory(const LLUUID& catID) const;  	/** -	 *	Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List -	 * -	 *	@return true - if folder is already synchronized, false otherwise. +	 *	Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" category +	 *	(creates them otherwise) and fetches their contents to synchronize with Agent's Friends List.  	 */ -	bool syncFriendsFolder(); +	void syncFriendCardsFolders();  	/*!  	 * \brief @@ -108,6 +99,8 @@ public:  	void collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const;  private: +	typedef boost::function<void()> callback_t; +  	LLFriendCardsManager();  	~LLFriendCardsManager(); @@ -133,10 +126,29 @@ private:  	const LLUUID& findFriendCardInventoryUUIDImpl(const LLUUID& avatarID);  	void findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const; +	void fetchAndCheckFolderDescendents(const LLUUID& folder_id, callback_t cb); + +	/** +	 *	Checks whether "Calling Cards/Friends" folder exists. If not, creates it with "All" +	 *	sub-folder and synchronizes its contents with buddies list. +	 */ +	void ensureFriendsFolderExists(); + +	/** +	 *	Checks whether "Calling Cards/Friends/All" folder exists. If not, creates it and +	 *	synchronizes its contents with buddies list. +	 */ +	void ensureFriendsAllFolderExists(); + +	/** +	 *	Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List +	 */ +	void syncFriendsFolder(); +  	/**  	 *	Adds avatar specified by its UUID into the Calling Card/Friends/All Global Inventory folder  	 */ -	bool addFriendCardToInventory(const LLUUID& avatarID); +	void addFriendCardToInventory(const LLUUID& avatarID);  	/**  	 *	Removes an avatar specified by its UUID from the Calling Card/Friends/All Global Inventory folder @@ -146,20 +158,11 @@ private:  	void onFriendListUpdate(U32 changed_mask); -	/** -	 * Force fetching of the Inventory folder specified by passed folder's LLUUID. -	 * -	 * It only sends request to server, server reply should be processed in other place. -	 * Because request can be sent via UDP we need to periodically check if request was completed with success. -	 */ -	void forceFriendListIsLoaded(const LLUUID& folder_id) const; -  private:  	typedef std::set<LLUUID> avatar_uuid_set_t;  	avatar_uuid_set_t mBuddyIDSet; -	bool mFriendsAllFolderCompleted;  };  #endif // LL_LLFRIENDCARD_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 64dcd7b97f..9be80c3add 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1688,8 +1688,11 @@ bool idle_startup()  		//all categories loaded. lets create "My Favorites" category  		gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true); -		// lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies -		LLFriendCardsManager::instance().syncFriendsFolder(); +		// Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" folder, +		// fetches their contents if needed and synchronizes it with buddies list. +		// If the folders are not found they are created. +		LLFriendCardsManager::instance().syncFriendCardsFolders(); +  		// set up callbacks  		llinfos << "Registering Callbacks" << llendl; | 
