merge
commit
95adfa4cac
|
|
@ -512,50 +512,6 @@ std::string LLUrlEntryTeleport::getLocation(const std::string &url) const
|
|||
return ::getStringAfterToken(url, "app/teleport/");
|
||||
}
|
||||
|
||||
///
|
||||
/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g.,
|
||||
/// secondlife:///app/objectim/<sessionid>
|
||||
///
|
||||
LLUrlEntryObjectIM::LLUrlEntryObjectIM()
|
||||
{
|
||||
mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\\??\\S*",
|
||||
boost::regex::perl|boost::regex::icase);
|
||||
mMenuName = "menu_url_objectim.xml";
|
||||
mTooltip = LLTrans::getString("TooltipObjectIMUrl");
|
||||
}
|
||||
|
||||
std::string LLUrlEntryObjectIM::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
|
||||
{
|
||||
LLURI uri(url);
|
||||
LLSD params = uri.queryMap();
|
||||
if (params.has("name"))
|
||||
{
|
||||
// look for a ?name=<obj-name> param in the url
|
||||
// and use that as the label if present.
|
||||
std::string name = params.get("name");
|
||||
LLStringUtil::trim(name);
|
||||
if (name.empty())
|
||||
{
|
||||
name = LLTrans::getString("Unnamed");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
return unescapeUrl(url);
|
||||
}
|
||||
|
||||
std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
|
||||
{
|
||||
LLURI uri(url);
|
||||
LLSD params = uri.queryMap();
|
||||
if (params.has("slurl"))
|
||||
{
|
||||
return params.get("slurl");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//
|
||||
// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
|
||||
// with secondlife:// (used as a catch-all for cases not matched above)
|
||||
|
|
|
|||
|
|
@ -208,18 +208,6 @@ public:
|
|||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g.,
|
||||
/// secondlife:///app/objectim/<sessionid>?name=Foo
|
||||
///
|
||||
class LLUrlEntryObjectIM : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryObjectIM();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
|
||||
/// with secondlife:// (used as a catch-all for cases not matched above)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ LLUrlRegistry::LLUrlRegistry()
|
|||
registerUrl(new LLUrlEntryParcel());
|
||||
registerUrl(new LLUrlEntryTeleport());
|
||||
registerUrl(new LLUrlEntryWorldMap());
|
||||
registerUrl(new LLUrlEntryObjectIM());
|
||||
registerUrl(new LLUrlEntryPlace());
|
||||
registerUrl(new LLUrlEntrySL());
|
||||
registerUrl(new LLUrlEntrySLLabel());
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES
|
|||
llinspectavatar.cpp
|
||||
llinspectgroup.cpp
|
||||
llinspectobject.cpp
|
||||
llinspectremoteobject.cpp
|
||||
llinventorybridge.cpp
|
||||
llinventoryclipboard.cpp
|
||||
llinventoryfilter.cpp
|
||||
|
|
@ -741,6 +742,7 @@ set(viewer_HEADER_FILES
|
|||
llinspectavatar.h
|
||||
llinspectgroup.h
|
||||
llinspectobject.h
|
||||
llinspectremoteobject.h
|
||||
llinventorybridge.h
|
||||
llinventoryclipboard.h
|
||||
llinventoryfilter.h
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
|||
params.append(event_data["y"]);
|
||||
params.append(event_data["z"]);
|
||||
LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true);
|
||||
// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "objectim", "parcel", "login", login_refresh", "balance", "chat"
|
||||
// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
|
||||
// should we just compose LLCommandHandler and LLDispatchListener?
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -124,9 +124,19 @@ void LLFloaterSearch::search(const LLSD &key)
|
|||
url += "&p=" + search_token.asString();
|
||||
|
||||
// also append the user's preferred maturity (can be changed via prefs)
|
||||
std::string maturity = "pg";
|
||||
if (gAgent.prefersMature()) maturity += ",mature";
|
||||
if (gAgent.prefersAdult()) maturity += ",adult";
|
||||
std::string maturity;
|
||||
if (gAgent.prefersAdult())
|
||||
{
|
||||
maturity = "42"; // PG,Mature,Adult
|
||||
}
|
||||
else if (gAgent.prefersMature())
|
||||
{
|
||||
maturity = "21"; // PG,Mature
|
||||
}
|
||||
else
|
||||
{
|
||||
maturity = "13"; // PG
|
||||
}
|
||||
url += "&r=" + maturity;
|
||||
|
||||
// and load the URL in the web view
|
||||
|
|
|
|||
|
|
@ -0,0 +1,200 @@
|
|||
/**
|
||||
* @file llinspectremoteobject.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llinspectremoteobject.h"
|
||||
#include "llinspect.h"
|
||||
#include "llslurl.h"
|
||||
#include "llmutelist.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llpanelblockedlist.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llui.h"
|
||||
#include "lluictrl.h"
|
||||
|
||||
class LLViewerObject;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// LLInspectRemoteObject
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Remote Object Inspector, a small information window used to
|
||||
// display information about potentially-remote objects. Used
|
||||
// to display details about objects sending messages to the user.
|
||||
class LLInspectRemoteObject : public LLInspect
|
||||
{
|
||||
friend class LLFloaterReg;
|
||||
|
||||
public:
|
||||
LLInspectRemoteObject(const LLSD& object_id);
|
||||
virtual ~LLInspectRemoteObject() {};
|
||||
|
||||
/*virtual*/ BOOL postBuild(void);
|
||||
/*virtual*/ void onOpen(const LLSD& avatar_id);
|
||||
|
||||
void onClickMap();
|
||||
void onClickBlock();
|
||||
void onClickClose();
|
||||
|
||||
private:
|
||||
void update();
|
||||
static void nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data);
|
||||
|
||||
private:
|
||||
LLUUID mObjectID;
|
||||
LLUUID mOwnerID;
|
||||
std::string mOwner;
|
||||
std::string mSLurl;
|
||||
std::string mName;
|
||||
bool mGroupOwned;
|
||||
};
|
||||
|
||||
LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :
|
||||
LLInspect(LLSD()),
|
||||
mObjectID(NULL),
|
||||
mOwnerID(NULL),
|
||||
mOwner(""),
|
||||
mSLurl(""),
|
||||
mName(""),
|
||||
mGroupOwned(false)
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
BOOL LLInspectRemoteObject::postBuild(void)
|
||||
{
|
||||
// hook up the inspector's buttons
|
||||
getChild<LLUICtrl>("map_btn")->setCommitCallback(
|
||||
boost::bind(&LLInspectRemoteObject::onClickMap, this));
|
||||
getChild<LLUICtrl>("block_btn")->setCommitCallback(
|
||||
boost::bind(&LLInspectRemoteObject::onClickBlock, this));
|
||||
getChild<LLUICtrl>("close_btn")->setCommitCallback(
|
||||
boost::bind(&LLInspectRemoteObject::onClickClose, this));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLInspectRemoteObject::onOpen(const LLSD& data)
|
||||
{
|
||||
// Start animation
|
||||
LLInspect::onOpen(data);
|
||||
|
||||
// Extract appropriate object information from input LLSD
|
||||
// (Eventually, it might be nice to query server for details
|
||||
// rather than require caller to pass in the information.)
|
||||
mObjectID = data["object_id"].asUUID();
|
||||
mName = data["name"].asString();
|
||||
mOwnerID = data["owner_id"].asUUID();
|
||||
mGroupOwned = data["group_owned"].asBoolean();
|
||||
mSLurl = data["slurl"].asString();
|
||||
|
||||
// work out the owner's name
|
||||
mOwner = "";
|
||||
if (gCacheName)
|
||||
{
|
||||
gCacheName->get(mOwnerID, mGroupOwned, nameCallback, this);
|
||||
}
|
||||
|
||||
// update the inspector with the current object state
|
||||
update();
|
||||
|
||||
// Position the inspector relative to the mouse cursor
|
||||
LLUI::positionViewNearMouse(this);
|
||||
}
|
||||
|
||||
void LLInspectRemoteObject::onClickMap()
|
||||
{
|
||||
std::string url = "secondlife://" + mSLurl;
|
||||
LLUrlAction::showLocationOnMap(url);
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
void LLInspectRemoteObject::onClickBlock()
|
||||
{
|
||||
LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT;
|
||||
LLMute mute(mOwnerID, mOwner, mute_type);
|
||||
LLMuteList::getInstance()->add(mute);
|
||||
LLPanelBlockedList::showPanelAndSelect(mute.mID);
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
void LLInspectRemoteObject::onClickClose()
|
||||
{
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLInspectRemoteObject::nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
|
||||
{
|
||||
LLInspectRemoteObject *self = (LLInspectRemoteObject*)data;
|
||||
self->mOwner = first;
|
||||
if (!last.empty())
|
||||
{
|
||||
self->mOwner += " " + last;
|
||||
}
|
||||
self->update();
|
||||
}
|
||||
|
||||
void LLInspectRemoteObject::update()
|
||||
{
|
||||
// show the object name as the inspector's title
|
||||
getChild<LLUICtrl>("object_name")->setValue(mName);
|
||||
|
||||
// show the object's owner - click it to show profile
|
||||
std::string owner = mOwner;
|
||||
if (! mOwnerID.isNull())
|
||||
{
|
||||
if (mGroupOwned)
|
||||
{
|
||||
owner = LLSLURL::buildCommand("group", mOwnerID, "about");
|
||||
}
|
||||
else
|
||||
{
|
||||
owner = LLSLURL::buildCommand("agent", mOwnerID, "about");
|
||||
}
|
||||
}
|
||||
getChild<LLUICtrl>("object_owner")->setValue(owner);
|
||||
|
||||
// display the object's SLurl - click it to teleport
|
||||
std::string url = "secondlife:///app/teleport/" + mSLurl;
|
||||
getChild<LLUICtrl>("object_slurl")->setValue(url);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// LLInspectRemoteObjectUtil
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void LLInspectRemoteObjectUtil::registerFloater()
|
||||
{
|
||||
LLFloaterReg::add("inspect_remote_object", "inspect_remote_object.xml",
|
||||
&LLFloaterReg::build<LLInspectRemoteObject>);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* @file llinspectremoteobject.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLINSPECTREMOTEOBJECT_H
|
||||
#define LLINSPECTREMOTEOBJECT_H
|
||||
|
||||
namespace LLInspectRemoteObjectUtil
|
||||
{
|
||||
void registerFloater();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -364,9 +364,9 @@ bool LLURLDispatcher::dispatchRightClick(const std::string& url)
|
|||
bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url)
|
||||
{
|
||||
// *NOTE: Text editors are considered sources of trusted URLs
|
||||
// in order to make objectim and avatar profile links in chat
|
||||
// history work. While a malicious resident could chat an app
|
||||
// SLURL, the receiving resident will see it and must affirmatively
|
||||
// in order to make avatar profile links in chat history work.
|
||||
// While a malicious resident could chat an app SLURL, the
|
||||
// receiving resident will see it and must affirmatively
|
||||
// click on it.
|
||||
// *TODO: Make this trust model more refined. JC
|
||||
const bool trusted_browser = true;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@
|
|||
#include "llinspectavatar.h"
|
||||
#include "llinspectgroup.h"
|
||||
#include "llinspectobject.h"
|
||||
#include "llinspectremoteobject.h"
|
||||
#include "llmediaremotectrl.h"
|
||||
#include "llmoveview.h"
|
||||
#include "llnearbychat.h"
|
||||
|
|
@ -176,6 +177,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLInspectAvatarUtil::registerFloater();
|
||||
LLInspectGroupUtil::registerFloater();
|
||||
LLInspectObjectUtil::registerFloater();
|
||||
LLInspectRemoteObjectUtil::registerFloater();
|
||||
|
||||
LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
|
||||
LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
|
||||
|
|
|
|||
|
|
@ -1431,6 +1431,17 @@ bool goto_url_callback(const LLSD& notification, const LLSD& response)
|
|||
}
|
||||
static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback);
|
||||
|
||||
bool inspect_remote_object_callback(const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 option = LLNotification::getSelectedOption(notification, response);
|
||||
if (0 == option)
|
||||
{
|
||||
LLFloaterReg::showInstance("inspect_remote_object", notification["payload"]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static LLNotificationFunctorRegistration inspect_remote_object_callback_reg("ServerObjectMessage", inspect_remote_object_callback);
|
||||
|
||||
void process_improved_im(LLMessageSystem *msg, void **user_data)
|
||||
{
|
||||
if (gNoRender)
|
||||
|
|
@ -1943,9 +1954,23 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
|
|||
return;
|
||||
}
|
||||
|
||||
// Build a link to open the object IM info window.
|
||||
std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1);
|
||||
|
||||
LLSD substitutions;
|
||||
substitutions["NAME"] = name;
|
||||
substitutions["MSG"] = message;
|
||||
LLNotifications::instance().add("ServerObjectMessage", substitutions);
|
||||
|
||||
LLSD payload;
|
||||
payload["object_id"] = session_id;
|
||||
payload["owner_id"] = from_id;
|
||||
payload["slurl"] = location;
|
||||
payload["name"] = name;
|
||||
if (from_group)
|
||||
{
|
||||
payload["groupowned"] = "true";
|
||||
}
|
||||
LLNotifications::instance().add("ServerObjectMessage", substitutions, payload);
|
||||
}
|
||||
break;
|
||||
case IM_FROM_TASK_AS_ALERT:
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
Done
|
||||
</floater.string>
|
||||
<layout_stack
|
||||
bottom="400"
|
||||
bottom="512"
|
||||
follows="left|right|top|bottom"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="status_text"
|
||||
top_pad="4"
|
||||
top_pad="5"
|
||||
width="150" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<!--
|
||||
Not can_close / no title to avoid window chrome
|
||||
Single instance - only have one at a time, recycle it each spawn
|
||||
-->
|
||||
<floater
|
||||
legacy_header_height="18"
|
||||
bevel_style="in"
|
||||
bg_opaque_image="Inspector_Background"
|
||||
can_close="false"
|
||||
can_minimize="false"
|
||||
height="145"
|
||||
layout="topleft"
|
||||
name="inspect_remote_object"
|
||||
single_instance="true"
|
||||
sound_flags="0"
|
||||
visible="true"
|
||||
width="300">
|
||||
<text
|
||||
follows="all"
|
||||
font="SansSerifLargeBold"
|
||||
height="16"
|
||||
left="8"
|
||||
name="object_name"
|
||||
text_color="White"
|
||||
top="5"
|
||||
use_ellipses="true"
|
||||
width="290">
|
||||
Test Object Name That Is Really Long
|
||||
</text>
|
||||
<text
|
||||
follows="all"
|
||||
font="SansSerif"
|
||||
height="20"
|
||||
left="8"
|
||||
name="object_owner_label"
|
||||
width="55"
|
||||
top_pad="20">
|
||||
Owner:
|
||||
</text>
|
||||
<text
|
||||
follows="top|left"
|
||||
font="SansSerif"
|
||||
height="20"
|
||||
left_pad="10"
|
||||
name="object_owner"
|
||||
use_ellipses="true"
|
||||
width="200"
|
||||
word_wrap="false">
|
||||
Longavatarname Johnsonlongstonnammer
|
||||
</text>
|
||||
<text
|
||||
follows="top|left"
|
||||
font="SansSerif"
|
||||
height="20"
|
||||
left="8"
|
||||
name="object_slurl_label"
|
||||
top_pad="10"
|
||||
width="55">
|
||||
Location:
|
||||
</text>
|
||||
<text
|
||||
follows="top|left"
|
||||
height="20"
|
||||
left_pad="10"
|
||||
name="object_slurl"
|
||||
width="240"
|
||||
use_ellipses="true"
|
||||
word_wrap="false">
|
||||
http://slurl.com/Ahern/50/50/50
|
||||
</text>
|
||||
<button
|
||||
follows="top|left"
|
||||
font="SansSerif"
|
||||
height="20"
|
||||
label="Map"
|
||||
left="10"
|
||||
name="map_btn"
|
||||
top="114"
|
||||
width="75" />
|
||||
<button
|
||||
follows="top|left"
|
||||
font="SansSerif"
|
||||
height="20"
|
||||
label="Block"
|
||||
left_pad="5"
|
||||
name="block_btn"
|
||||
top_delta="0"
|
||||
width="75" />
|
||||
<button
|
||||
follows="top|left"
|
||||
font="SansSerif"
|
||||
height="20"
|
||||
label="Close"
|
||||
right="-10"
|
||||
name="close_btn"
|
||||
top_delta="0"
|
||||
width="75" />
|
||||
</floater>
|
||||
|
|
@ -4696,7 +4696,12 @@ The objects on the selected parcel that are NOT owned by you have been returned
|
|||
icon="notify.tga"
|
||||
name="ServerObjectMessage"
|
||||
type="notify">
|
||||
Message from [NAME]:
|
||||
[MSG]
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="OK"
|
||||
yestext="Inspect"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
|
|
|
|||
Loading…
Reference in New Issue