Inventory Offer changes and clickable inventory slurls
parent
521820ad8d
commit
a3930c7ff7
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -173,6 +173,19 @@ private:
|
|||
const std::string& last, BOOL is_group);
|
||||
};
|
||||
|
||||
///
|
||||
/// 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
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ LLUrlRegistry::LLUrlRegistry()
|
|||
registerUrl(new LLUrlEntryPlace());
|
||||
registerUrl(new LLUrlEntrySL());
|
||||
registerUrl(new LLUrlEntrySLLabel());
|
||||
registerUrl(new LLUrlEntryInventory());
|
||||
}
|
||||
|
||||
LLUrlRegistry::~LLUrlRegistry()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -1060,22 +1060,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);
|
||||
|
|
@ -1094,6 +1080,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);
|
||||
|
|
@ -1102,6 +1113,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.
|
||||
|
|
@ -1152,64 +1173,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();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
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:
|
||||
|
|
@ -1218,31 +1229,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);
|
||||
|
|
@ -1258,20 +1253,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);
|
||||
|
|
@ -1382,7 +1378,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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -4487,7 +4487,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
|
||||
|
|
@ -4959,17 +4959,21 @@ No valid parcel could be found.
|
|||
icon="notify.tga"
|
||||
name="ObjectGiveItem"
|
||||
type="offer">
|
||||
An object named [OBJECTFROMNAME] owned by [NAME] has offered you [OBJECTTYPE]:
|
||||
An object named [OBJECTFROMNAME] owned by [NAME] 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"
|
||||
|
|
@ -4986,11 +4990,15 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
|
|||
<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"
|
||||
|
|
@ -5002,17 +5010,21 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
|
|||
icon="notify.tga"
|
||||
name="UserGiveItem"
|
||||
type="offer">
|
||||
[NAME] has offered you [OBJECTTYPE]:
|
||||
[NAME] 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>
|
||||
|
||||
|
|
@ -5747,7 +5759,7 @@ Are you sure you want to delete your teleport history?
|
|||
name="BottomTrayButtonCanNotBeShown"
|
||||
type="alert">
|
||||
Selected button can not be shown right now.
|
||||
The button will be shown when there is enough space for it.
|
||||
The button will be shown when there is enough space for it.
|
||||
</notification>
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue