diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llui/llurlentry.cpp | 33 | ||||
| -rw-r--r-- | indra/llui/llurlentry.h | 13 | ||||
| -rw-r--r-- | indra/llui/llurlregistry.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llinventoryobserver.h | 2 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 32 | ||||
| -rw-r--r-- | indra/newview/llviewermessage.cpp | 196 | ||||
| -rw-r--r-- | indra/newview/llviewermessage.h | 5 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_url_inventory.xml | 28 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 32 | 
9 files changed, 239 insertions, 103 deletions
| diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 219fae84be..b51709e208 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -34,6 +34,7 @@  #include "linden_common.h"  #include "llurlentry.h"  #include "lluri.h" +  #include "llcachename.h"  #include "lltrans.h"  #include "lluicolortable.h" @@ -383,6 +384,38 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa  	}  } +// +// LLUrlEntryInventory Describes a Second Life inventory Url, e.g., +// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select +// +LLUrlEntryInventory::LLUrlEntryInventory() +{ +	mPattern = boost::regex("secondlife:///app/inventory/[\\da-f-]+/\\w+", +							boost::regex::perl|boost::regex::icase); +	mMenuName = "menu_url_inventory.xml"; +} + +std::string LLUrlEntryInventory::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ +	return unescapeUrl(url); +	// TODO: Figure out if we can somehow access the inventory from here to get the actual item name +	/*   +	std::string inventory_id_string = getIDStringFromUrl(url); +	if (inventory_id_string.empty()) +	{ +		// something went wrong, give raw url +		return unescapeUrl(url); +	} +	LLUUID inventory_id(inventory_id_string); +	LLInventoryItem* item = gInventory.getItem(inventory_id); +	if(!item) +	{ +		return unescapeUrl(url); +	} +	return item->getName(); */ +} + +  ///  /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,  /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 7970b48eb5..b3fb333fdd 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -174,6 +174,19 @@ private:  };  /// +/// LLUrlEntryInventory Describes a Second Life inventory Url, e.g., +/// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select +/// +class LLUrlEntryInventory : public LLUrlEntryBase +{ +public: +	LLUrlEntryInventory(); +	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); +private: +}; + + +///  /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,  /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about  /// diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index a6922b019b..b2f084e5ac 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -55,6 +55,7 @@ LLUrlRegistry::LLUrlRegistry()  	registerUrl(new LLUrlEntryPlace());  	registerUrl(new LLUrlEntrySL());  	registerUrl(new LLUrlEntrySLLabel()); +	registerUrl(new LLUrlEntryInventory());  }  LLUrlRegistry::~LLUrlRegistry() diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 384e6292e8..e908506b33 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -113,7 +113,7 @@ public:  	bool isEverythingComplete() const;  	void fetchItems(const item_ref_t& ids); -	virtual void done() = 0; +	virtual void done() {};  protected:  	item_ref_t mComplete; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 87d256b60a..c6ec25c1cb 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -56,11 +56,43 @@  #include "lltrans.h"  #include "llappearancemgr.h"  #include "llfloatercustomize.h" +#include "llcommandhandler.h" +#include "llviewermessage.h"  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs  ///---------------------------------------------------------------------------- +class LLInventoryHandler : public LLCommandHandler +{ +public: +	// requires trusted browser to trigger +	LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } +	 +	bool handle(const LLSD& params, const LLSD& query_map, +				LLMediaCtrl* web) +	{ +		if (params.size() < 2) return false; +		LLUUID inventory_id; +		if (!inventory_id.set(params[0], FALSE)) +		{ +			return false; +		} +		 +		const std::string verb = params[1].asString(); +		if (verb == "select") +		{ +			std::vector<LLUUID> items_to_open; +			items_to_open.push_back(inventory_id); +			open_inventory_offer(items_to_open, ""); +			return true; +		} +		 +		return false; +	} +}; +LLInventoryHandler gInventoryHandler; +  ///----------------------------------------------------------------------------  /// Class LLViewerInventoryItem  ///---------------------------------------------------------------------------- diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8db6d5917a..b2693c799c 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -726,7 +726,7 @@ public:  	LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {}  	/*virtual*/ void done()  	{ -		open_offer(mComplete, mFromName); +		open_inventory_offer(mComplete, mFromName);  		gInventory.removeObserver(this);  		delete this;  	} @@ -875,7 +875,7 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)  	}  } -void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) +void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& from_name)  {  	std::vector<LLUUID>::const_iterator it = items.begin();  	std::vector<LLUUID>::const_iterator end = items.end(); @@ -1065,22 +1065,8 @@ LLSD LLOfferInfo::asLLSD()  	return sd;  } -bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response) - { -	LLChat chat; -	std::string log_message; -	S32 button = LLNotification::getSelectedOption(notification, response); - -	// For muting, we need to add the mute, then decline the offer. -	// This must be done here because: -	// * callback may be called immediately, -	// * adding the mute sends a message, -	// * we can't build two messages at once. -	if (2 == button) -	{ -		gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); -	} - +void LLOfferInfo::send_auto_receive_response(void) +{	  	LLMessageSystem* msg = gMessageSystem;  	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);  	msg->nextBlockFast(_PREHASH_AgentData); @@ -1099,6 +1085,31 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	msg->addU32Fast(_PREHASH_ParentEstateID, 0);  	msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);  	msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); +	 +	// Auto Receive Message. The math for the dialog works, because the accept +	// for inventory_offered, task_inventory_offer or +	// group_notice_inventory is 1 greater than the offer integer value. +	// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,  +	// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED +	msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); +	msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData), +						   sizeof(mFolderID.mData)); +	// send the message +	msg->sendReliable(mHost); +	 +	if(IM_INVENTORY_OFFERED == mIM) +	{ +		// add buddy to recent people list +		LLRecentPeople::instance().add(mFromID); +	} +} + +bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response) +{ +	LLChat chat; +	std::string log_message; +	S32 button = LLNotification::getSelectedOption(notification, response); +	  	LLInventoryObserver* opener = NULL;  	LLViewerInventoryCategory* catp = NULL;  	catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID); @@ -1107,6 +1118,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	{  		itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);  	} +	  +	// For muting, we need to add the mute, then decline the offer. +	// This must be done here because: +	// * callback may be called immediately, +	// * adding the mute sends a message, +	// * we can't build two messages at once. +	if (2 == button) +	{ +		gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); +	}  	std::string from_string; // Used in the pop-up.  	std::string chatHistory_string;  // Used in chat history. @@ -1157,64 +1178,54 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	switch(button)  	{ -	case IOR_ACCEPT: -		// ACCEPT. The math for the dialog works, because the accept -		// for inventory_offered, task_inventory_offer or -		// group_notice_inventory is 1 greater than the offer integer value. -		// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,  -		// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED -		msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); -		msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData), -					 sizeof(mFolderID.mData)); -		// send the message -		msg->sendReliable(mHost); - -		//don't spam them if they are getting flooded -		if (check_offer_throttle(mFromName, true)) -		{ -			log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); - 			chat.mText = log_message; - 			LLFloaterChat::addChatHistory(chat); -		} - +	case IOR_SHOW:  		// we will want to open this item when it comes back.  		LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID  				 << LL_ENDL;  		switch (mIM)  		{  		case IM_INVENTORY_OFFERED: -		{ -			// This is an offer from an agent. In this case, the back -			// end has already copied the items into your inventory, -			// so we can fetch it out of our inventory. -			LLInventoryFetchObserver::item_ref_t items; -			items.push_back(mObjectID); -			LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); -			open_agent_offer->fetchItems(items); -			if(catp || (itemp && itemp->isComplete())) -			{ -				open_agent_offer->done(); -			} -			else  			{ -				opener = open_agent_offer; +				// This is an offer from an agent. In this case, the back +				// end has already copied the items into your inventory, +				// so we can fetch it out of our inventory. +				LLInventoryFetchObserver::item_ref_t items; +				items.push_back(mObjectID); +				LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); +				open_agent_offer->fetchItems(items); +				if(catp || (itemp && itemp->isComplete())) +				{ +					open_agent_offer->done(); +				} +				else +				{ +					opener = open_agent_offer; +				}  			} -		}  			break;  		case IM_TASK_INVENTORY_OFFERED:  		case IM_GROUP_NOTICE:  		case IM_GROUP_NOTICE_REQUESTED: -		{  			// This is an offer from a task or group.  			// We don't use a new instance of an opener  			// We instead use the singular observer gOpenTaskOffer  			// Since it already exists, we don't need to actually do anything -		} -		break; +			break;  		default:  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break;  		}	// end switch (mIM) +			 +		// Show falls through to accept. +			 +	case IOR_ACCEPT: +		//don't spam them if they are getting flooded +		if (check_offer_throttle(mFromName, true)) +		{ +			log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); +			chat.mText = log_message; +			LLFloaterChat::addChatHistory(chat); +		}  		break;  	case IOR_BUSY: @@ -1223,31 +1234,15 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	case IOR_MUTE:  		// MUTE falls through to decline  	case IOR_DECLINE: -		// DECLINE. The math for the dialog works, because the decline -		// for inventory_offered, task_inventory_offer or -		// group_notice_inventory is 2 greater than the offer integer value. -		// Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED, -		// or IM_GROUP_NOTICE_INVENTORY_DECLINED -	default: -		// close button probably (or any of the fall-throughs from above) -		msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2)); -		msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE); -		// send the message -		msg->sendReliable(mHost); - -		log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; -		chat.mText = log_message; -		if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) )  // muting for SL-42269 -		{ -			chat.mMuted = TRUE; -		} -		LLFloaterChat::addChatHistory(chat); - -		// If it's from an agent, we have to fetch the item to throw -		// it away. If it's from a task or group, just denying the  -		// request will suffice to discard the item. -		if(IM_INVENTORY_OFFERED == mIM)  		{ +			log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; +			chat.mText = log_message; +			if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) )  // muting for SL-42269 +			{ +				chat.mMuted = TRUE; +			} +			LLFloaterChat::addChatHistory(chat); +			  			LLInventoryFetchComboObserver::folder_ref_t folders;  			LLInventoryFetchComboObserver::item_ref_t items;  			items.push_back(mObjectID); @@ -1263,20 +1258,21 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  				opener = discard_agent_offer;  			} +			 +			if (busy &&	(!mFromGroup && !mFromObject)) +			{ +				busy_message(gMessageSystem, mFromID); +			} +			break;  		} -		if (busy &&	(!mFromGroup && !mFromObject)) -		{ -			busy_message(msg,mFromID); -		} +	default: +		// close button probably +		// The item has already been fetched and is in your inventory, we simply won't highlight it +		// OR delete it if the notification gets killed, since we don't want that to be a vector for  +		// losing inventory offers.  		break;  	} -	if(IM_INVENTORY_OFFERED == mIM) -	{ -		// add buddy to recent people list -		LLRecentPeople::instance().add(mFromID); -	} -  	if(opener)  	{  		gInventory.addObserver(opener); @@ -1388,7 +1384,25 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)  	{  		p.name = "UserGiveItem";  	} - +	 +	// Prefetch the item into your local inventory. +	LLInventoryFetchObserver::item_ref_t items; +	items.push_back(info->mObjectID); +	LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver(); +	fetch_item->fetchItems(items); +	if(fetch_item->isEverythingComplete()) +	{ +		fetch_item->done(); +	} +	else +	{ +		gInventory.addObserver(fetch_item); +	} +	 +	// In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages). +	info->send_auto_receive_response(); +	 +	// Pop up inv offer notification and let the user accept (keep), or reject (and silently delete) the inventory.  	LLNotifications::instance().add(p);  } diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index e24da2013d..2d8930d2fe 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -59,7 +59,8 @@ enum InventoryOfferResponse  	IOR_ACCEPT,  	IOR_DECLINE,  	IOR_MUTE, -	IOR_BUSY +	IOR_BUSY, +	IOR_SHOW  };  BOOL can_afford_transaction(S32 cost); @@ -197,6 +198,7 @@ void invalid_message_callback(LLMessageSystem*, void*, EMessageException);  void process_initiate_download(LLMessageSystem* msg, void**);  void start_new_inventory_observer(); +void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& from_name);  struct LLOfferInfo  { @@ -218,6 +220,7 @@ struct LLOfferInfo  	LLHost mHost;  	LLSD asLLSD(); +	void send_auto_receive_response(void);  	bool inventory_offer_callback(const LLSD& notification, const LLSD& response);  }; diff --git a/indra/newview/skins/default/xui/en/menu_url_inventory.xml b/indra/newview/skins/default/xui/en/menu_url_inventory.xml new file mode 100644 index 0000000000..cf9d1d5881 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_url_inventory.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Url Popup"> +    <menu_item_call +     label="Show Inventory Item" +     layout="topleft" +     name="show_item"> +        <menu_item_call.on_click +         function="Url.Execute" /> +    </menu_item_call> +    <menu_item_separator +     layout="topleft" /> +    <menu_item_call +     label="Copy Name to clipboard" +     layout="topleft" +     name="url_copy_label"> +        <menu_item_call.on_click +         function="Url.CopyLabel" /> +    </menu_item_call> +    <menu_item_call +     label="Copy SLurl to clipboard" +     layout="topleft" +     name="url_copy"> +        <menu_item_call.on_click +         function="Url.CopyUrl" /> +    </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 90e32cdd9c..eb0db2683f 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4494,7 +4494,7 @@ You don't have permission to copy this.     icon="notifytip.tga"     name="InventoryAccepted"     type="notifytip"> -[NAME] accepted your inventory offer. +[NAME] received your inventory offer.    </notification>    <notification @@ -4966,17 +4966,21 @@ No valid parcel could be found.     icon="notify.tga"     name="ObjectGiveItem"     type="offer"> -An object named [OBJECTFROMNAME] owned by [NAME_SLURL] has offered you [OBJECTTYPE]: +An object named [OBJECTFROMNAME] owned by [NAME_SLURL] has given you [OBJECTTYPE]:  [ITEM_SLURL]      <form name="form">        <button         index="0"         name="Keep" -       text="OK"/> +       text="Keep"/> +	  <button +       index="4" +       name="Show" +       text="Show"/>         <button         index="1"         name="Discard" -       text="Cancel"/> +       text="Discard"/>        <button         index="2"         name="Mute" @@ -4988,17 +4992,21 @@ An object named [OBJECTFROMNAME] owned by [NAME_SLURL] has offered you [OBJECTTY     icon="notify.tga"     name="ObjectGiveItemUnknownUser"     type="offer"> -An object named [OBJECTFROMNAME] owned by (an unknown Resident) has offered you [OBJECTTYPE]: +An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [OBJECTTYPE]:  [ITEM_SLURL]      <form name="form">        <button         index="0"         name="Keep" -       text="OK"/> +       text="Keep"/> +	  <button +       index="4" +       name="Show" +       text="Show"/>         <button         index="1"         name="Discard" -       text="Cancel"/> +       text="Discard"/>        <button         index="2"         name="Mute" @@ -5010,17 +5018,21 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has offered you     icon="notify.tga"     name="UserGiveItem"     type="offer"> -[NAME_SLURL] has offered you [OBJECTTYPE]: +[NAME_SLURL] has given you [OBJECTTYPE]:  [ITEM_SLURL]      <form name="form">        <button         index="0"         name="Keep" -       text="Accept"/> +       text="Keep"/> +      <button +       index="4" +       name="Show" +       text="Show"/>         <button         index="1"         name="Discard" -       text="No, thanks"/> +       text="Discard"/>      </form>    </notification> | 
