summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llurlentry.cpp33
-rw-r--r--indra/llui/llurlentry.h13
-rw-r--r--indra/llui/llurlregistry.cpp1
-rw-r--r--indra/newview/llinventoryobserver.h2
-rw-r--r--indra/newview/llviewerinventory.cpp32
-rw-r--r--indra/newview/llviewermessage.cpp416
-rw-r--r--indra/newview/llviewermessage.h6
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_inventory.xml28
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml24
9 files changed, 412 insertions, 143 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 4d7d3ee8ac..adad06dc6f 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -170,7 +170,6 @@ static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds
extern BOOL gDebugClicks;
// function prototypes
-void open_offer(const std::vector<LLUUID>& items, const std::string& from_name);
bool check_offer_throttle(const std::string& from_name, bool check_only);
//inventory offer throttle globals
@@ -727,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;
}
@@ -745,7 +744,7 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
protected:
/*virtual*/ void done()
{
- open_offer(mAdded, "");
+ open_inventory_offer(mAdded, "");
mAdded.clear();
}
};
@@ -876,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();
@@ -1066,12 +1065,60 @@ LLSD LLOfferInfo::asLLSD()
return sd;
}
+void LLOfferInfo::send_auto_receive_response(void)
+{
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_MessageBlock);
+ msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
+ msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
+ msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
+ msg->addUUIDFast(_PREHASH_ID, mTransactionID);
+ msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
+ std::string name;
+ LLAgentUI::buildFullname(name);
+ msg->addStringFast(_PREHASH_FromAgentName, name);
+ msg->addStringFast(_PREHASH_Message, "");
+ 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);
+ LLViewerInventoryItem* itemp = NULL;
+ if(!catp)
+ {
+ 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,
@@ -1082,6 +1129,136 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
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.
+
+ // TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
+ from_string = chatHistory_string = mFromName;
+
+ bool busy=FALSE;
+
+ switch(button)
+ {
+ 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;
+ }
+ }
+ 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;
+ 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:
+ //Busy falls through to decline. Says to make busy message.
+ busy=TRUE;
+ case IOR_MUTE:
+ // MUTE falls through to decline
+ case IOR_DECLINE:
+ {
+ 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);
+ LLDiscardAgentOffer* discard_agent_offer;
+ discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
+ discard_agent_offer->fetch(folders, items);
+ if(catp || (itemp && itemp->isComplete()))
+ {
+ discard_agent_offer->done();
+ }
+ else
+ {
+ opener = discard_agent_offer;
+ }
+
+
+ if (busy && (!mFromGroup && !mFromObject))
+ {
+ busy_message(gMessageSystem, mFromID);
+ }
+ break;
+ }
+ 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(opener)
+ {
+ gInventory.addObserver(opener);
+ }
+
+ delete this;
+ return false;
+}
+
+bool LLOfferInfo::inventory_task_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);
+ }
+
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -1108,7 +1285,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
{
itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
}
-
+
std::string from_string; // Used in the pop-up.
std::string chatHistory_string; // Used in chat history.
if (mFromObject == TRUE)
@@ -1119,16 +1296,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
if (gCacheName->getGroupName(mFromID, group_name))
{
from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
- + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup")
- + " "+ "'" + group_name + "'";
+ + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup")
+ + " "+ "'" + group_name + "'";
chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup")
- + " " + group_name + "'";
+ + " " + group_name + "'";
}
else
{
from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
- + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
+ + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
}
}
@@ -1138,13 +1315,13 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
if (gCacheName->getName(mFromID, first_name, last_name))
{
from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName
- + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name;
+ + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name;
chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name;
}
else
{
from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+LLTrans::getString("'")
- + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser");
+ + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser");
chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser");
}
}
@@ -1158,137 +1335,90 @@ 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);
- }
-
- // 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()))
+ 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))
{
- open_agent_offer->done();
+ log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
+ chat.mText = log_message;
+ LLFloaterChat::addChatHistory(chat);
}
- else
+
+ // 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_TASK_INVENTORY_OFFERED:
+ case IM_GROUP_NOTICE:
+ case IM_GROUP_NOTICE_REQUESTED:
{
- opener = open_agent_offer;
+ // 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;
+ default:
+ LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
+ break;
+ } // end switch (mIM)
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;
+
+ case IOR_BUSY:
+ //Busy falls through to decline. Says to make busy message.
+ busy=TRUE;
+ 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:
- LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
- break;
- } // end switch (mIM)
- break;
-
- case IOR_BUSY:
- //Busy falls through to decline. Says to make busy message.
- busy=TRUE;
- 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)
- {
- LLInventoryFetchComboObserver::folder_ref_t folders;
- LLInventoryFetchComboObserver::item_ref_t items;
- items.push_back(mObjectID);
- LLDiscardAgentOffer* discard_agent_offer;
- discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
- discard_agent_offer->fetch(folders, items);
- if(catp || (itemp && itemp->isComplete()))
+ // 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
{
- discard_agent_offer->done();
+ chat.mMuted = TRUE;
}
- else
+ LLFloaterChat::addChatHistory(chat);
+
+ if (busy && (!mFromGroup && !mFromObject))
{
- opener = discard_agent_offer;
+ busy_message(msg,mFromID);
}
-
- }
- if (busy && (!mFromGroup && !mFromObject))
- {
- busy_message(msg,mFromID);
- }
- break;
- }
-
- if(IM_INVENTORY_OFFERED == mIM)
- {
- // add buddy to recent people list
- LLRecentPeople::instance().add(mFromID);
+ break;
}
-
+
if(opener)
{
gInventory.addObserver(opener);
}
-
+
delete this;
return false;
}
-
-void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
+void inventory_offer_handler(LLOfferInfo* info)
{
//Until throttling is implmented, busy mode should reject inventory instead of silently
//accepting it. SEE SL-39554
@@ -1375,21 +1505,45 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
args["OBJECTFROMNAME"] = info->mFromName;
args["NAME"] = info->mFromName;
args["NAME_SLURL"] = LLSLURL::buildCommand("agent", info->mFromID, "about");
- std::string verb = "highlight?name=" + msg;
+ std::string verb = "select?name=" + msg;
args["ITEM_SLURL"] = LLSLURL::buildCommand("inventory", info->mObjectID, verb.c_str());
LLNotification::Params p("ObjectGiveItem");
- p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));
- if (from_task)
+ // Object -> Agent Inventory Offer
+ if (info->mFromObject)
{
+ // Inventory Slurls don't currently work for non agent transfers, so only display the object name.
+ args["ITEM_SLURL"] = msg;
+ // Note: sets inventory_task_offer_callback as the callback
+ p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_task_offer_callback, info, _1, _2));
p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser";
}
- else
+ else // Agent -> Agent Inventory Offer
{
+ // Note: sets inventory_offer_callback as the callback
+ p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));
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);
}
@@ -1885,7 +2039,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
else
{
- inventory_offer_handler(info, dialog == IM_TASK_INVENTORY_OFFERED);
+ inventory_offer_handler(info);
}
}
break;
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index e24da2013d..1a98828010 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,7 +220,9 @@ struct LLOfferInfo
LLHost mHost;
LLSD asLLSD();
+ void send_auto_receive_response(void);
bool inventory_offer_callback(const LLSD& notification, const LLSD& response);
+ bool inventory_task_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 9d1bcb8f60..a87f05cbcc 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&apos;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,17 @@ 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="1"
name="Discard"
- text="Cancel"/>
+ text="Discard"/>
<button
index="2"
name="Mute"
@@ -4988,17 +4988,17 @@ 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="1"
name="Discard"
- text="Cancel"/>
+ text="Discard"/>
<button
index="2"
name="Mute"
@@ -5010,17 +5010,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>