Make the right click avatar slurl menu as good as the list ones

This commit is contained in:
Liru Færs
2019-08-29 22:00:22 -04:00
parent 2e465ba04a
commit 4b97f76aa7
5 changed files with 325 additions and 23 deletions

View File

@@ -436,20 +436,67 @@ class ContextUrl : public LLMemberListener<LLView>
}
};
class ContextUrlCopy : public LLMemberListener<LLView>
class ContextIDUrl : public LLMemberListener<LLView>
{
bool handleEvent(LLPointer<LLOldEvents::LLEvent>, const LLSD& userdata) override
protected:
std::string getID(const std::string& type) const
{
const auto& url = get_focused_url();
const auto& type = userdata.asStringRef();
// Empty works like avatar and group, "object" is an object (you needed to be told this)
const auto& id = type.empty() ? LLUrlAction::getUserID(url) : LLUrlAction::getObjectId(url);
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(id));
return type.empty() ? LLUrlAction::getUserID(url) : LLUrlAction::getObjectId(url);
}
};
class ContextUrlCopy : public ContextIDUrl
{
bool handleEvent(LLPointer<LLOldEvents::LLEvent>, const LLSD& userdata) override
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(getID(userdata.asStringRef())));
return true;
}
};
class ContextUrlExt : public ContextIDUrl
{
bool handleEvent(LLPointer<LLOldEvents::LLEvent>, const LLSD& userdata) override
{
std::string cmd = userdata.asStringRef();
std::string type;
const auto sep = cmd.find(',');
if (sep != std::string::npos)
{
type = cmd.substr(sep);
cmd = cmd.substr(0, sep);
}
mExtCallback(cmd, LLUUID(getID(type)));
return true;
}
LLTextEditor::ext_slurl_cb mExtCallback;
public:
ContextUrlExt(LLTextEditor::ext_slurl_cb cb) : mExtCallback(cb) {}
};
class ContextUrlExtVisible : public ContextIDUrl
{
bool handleEvent(LLPointer<LLOldEvents::LLEvent>, const LLSD& userdata) override
{
std::string cmd = userdata["data"];
std::string type;
const auto sep = cmd.find(',');
if (sep != std::string::npos)
{
type = cmd.substr(sep);
cmd = cmd.substr(0, sep);
}
LLMenuGL::sMenuContainer->findControl(userdata["control"].asString())->setValue(mExtVCB(cmd, LLUUID(getID(type))));
return true;
}
LLTextEditor::ext_slurl_visible_cb mExtVCB;
public:
ContextUrlExtVisible(LLTextEditor::ext_slurl_visible_cb vcb) : mExtVCB(vcb) {}
};
void LLTextEditor::spell_correct(void* data)
{
@@ -528,11 +575,13 @@ void LLTextEditor::spell_add(void* data)
}
//static
void LLTextEditor::addMenuListeners()
void LLTextEditor::addMenuListeners(ext_slurl_cb cb, ext_slurl_visible_cb vcb)
{
(new ContextText)->registerListener(LLMenuGL::sMenuContainer, "Text");
(new ContextUrl)->registerListener(LLMenuGL::sMenuContainer, "Text.Url");
(new ContextUrlCopy)->registerListener(LLMenuGL::sMenuContainer, "Text.Url.CopyUUID");
(new ContextUrlExt(cb))->registerListener(LLMenuGL::sMenuContainer, "Text.Url.Ext");
(new ContextUrlExtVisible(vcb))->registerListener(LLMenuGL::sMenuContainer, "Text.Url.ExtVisible");
}
void LLTextEditor::setTrackColor( const LLColor4& color )
@@ -721,8 +770,8 @@ LLMenuGL* LLTextEditor::createUrlContextMenu(S32 x, S32 y, const std::string &in
if (addFriendButton && removeFriendButton)
{
addFriendButton->setEnabled(!isFriend);
removeFriendButton->setEnabled(isFriend);
addFriendButton->setVisible(!isFriend);
removeFriendButton->setVisible(isFriend);
}
}

View File

@@ -80,7 +80,11 @@ public:
static boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
static boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
static void addMenuListeners();
typedef std::function<void(const std::string&, const LLUUID&)> ext_slurl_cb;
typedef std::function<bool(const std::string&, const LLUUID&)> ext_slurl_visible_cb;
static void addMenuListeners(ext_slurl_cb cb, ext_slurl_visible_cb vcb);
void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback);
virtual LLXMLNodePtr getXML(bool save_children = true) const;

View File

@@ -63,6 +63,7 @@
#include "lldebugview.h"
#include "llenvmanager.h"
#include "llfirstuse.h"
#include "llfloateravatarlist.h"
#include "llfloateravatartextures.h"
#include "llfloaterbuy.h"
#include "llfloaterbuycontents.h"
@@ -9255,11 +9256,16 @@ class ListShare : public view_listener_t
}
};
bool can_show_web_profile()
{
return !gSavedSettings.getString("WebProfileURL").empty();
}
void show_log_browser(const LLUUID& id);
class ListShowLog : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
void show_log_browser(const LLUUID& id);
for (const LLUUID& id : get_focused_list_ids_selected())
show_log_browser(id);
return true;
@@ -9368,23 +9374,29 @@ class ListTrack : public view_listener_t
};
void send_eject(const LLUUID& avatar_id, bool ban);
void confirm_eject(const uuid_vec_t& ids)
{
LLNotificationsUtil::add("EjectAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_eject));
}
class ListEject : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
const uuid_vec_t& ids = get_focused_list_ids_selected();
LLNotificationsUtil::add("EjectAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_eject));
confirm_eject(get_focused_list_ids_selected());
return true;
}
};
void send_freeze(const LLUUID& avatar_id, bool freeze);
void confirm_freeze(const uuid_vec_t& ids)
{
LLNotificationsUtil::add("FreezeAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_freeze));
}
class ListFreeze : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
const uuid_vec_t& ids = get_focused_list_ids_selected();
LLNotificationsUtil::add("FreezeAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_freeze));
confirm_freeze(get_focused_list_ids_selected());
return true;
}
};
@@ -9415,22 +9427,28 @@ void estate_bulk_eject(const uuid_vec_t& ids, bool ban, S32 option)
if (!tphome) send_estate_message("kickestate", strings);
}
void confirm_estate_ban(const uuid_vec_t& ids)
{
LLNotificationsUtil::add("EstateBanUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, true, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
}
class ListEstateBan : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
const uuid_vec_t& ids = get_focused_list_ids_selected();
LLNotificationsUtil::add("EstateBanUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, true, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
confirm_estate_ban(get_focused_list_ids_selected());
return true;
}
};
void confirm_estate_kick(const uuid_vec_t& ids)
{
LLNotificationsUtil::add("EstateKickUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, false, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
}
class ListEstateEject : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
const uuid_vec_t& ids = get_focused_list_ids_selected();
LLNotificationsUtil::add("EstateKickUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, false, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
confirm_estate_kick(get_focused_list_ids_selected());
return true;
}
};
@@ -9446,6 +9464,59 @@ class ListToggleMute : public view_listener_t
}
};
struct MenuSLURLDict : public LLSingleton<MenuSLURLDict>
{
typedef std::function<void (const LLUUID&)> cb;
typedef std::function<bool (const LLUUID&)> vcb;
typedef std::map<std::string, std::pair<cb, vcb>> slurl_menu_map;
slurl_menu_map mEntries;
MenuSLURLDict()
{
// Text Editor menus
LLTextEditor::setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
LLTextEditor::setIsFriendCallback(LLAvatarActions::isFriend);
LLTextEditor::addMenuListeners(boost::bind(&MenuSLURLDict::action, this, _1, _2), boost::bind(&MenuSLURLDict::visible, this, _1, _2));
// Add the entries
insert("ShowWebProfile", boost::bind(LLAvatarActions::showProfile, _1, true), boost::bind(can_show_web_profile));
insert("Pay", LLAvatarActions::pay);
insert("Call", LLAvatarActions::startCall);
insert("Share", LLAvatarActions::share);
insert("AbuseReport", LLFloaterReporter::showFromObject);
insert("InviteToGroup", [](const LLUUID& id) { LLAvatarActions::inviteToGroup(id); });
insert("BanFromGroup", [](const LLUUID& id) { ban_from_group(uuid_vec_t(1, id)); });
insert("ShowLog", [](const LLUUID& id) { show_log_browser(id); });
insert("OfferTeleport", [](const LLUUID& id) { LLAvatarActions::offerTeleport(id); }, [](const LLUUID& id) { return LLAvatarActions::canOfferTeleport(id); });
insert("RequestTeleport", LLAvatarActions::teleportRequest);
void teleport_to(const LLUUID& id);
insert("TeleportTo", teleport_to, is_nearby);
insert("Focus", LLFloaterAvatarList::setFocusAvatar, is_nearby);
insert("ParcelEject", [](const LLUUID& id) { confirm_eject(uuid_vec_t(1, id)); }, is_nearby);
insert("Freeze", [](const LLUUID& id) { confirm_freeze(uuid_vec_t(1, id)); }, is_nearby);
insert("EstateBan", [](const LLUUID& id) { confirm_estate_ban(uuid_vec_t(1, id)); }, is_nearby);
insert("EstateEject", [](const LLUUID & id) { confirm_estate_kick(uuid_vec_t(1, id)); }, is_nearby);
insert("Mute", LLAvatarActions::toggleBlock, [](const LLUUID& id) { return LLAvatarActions::canBlock(id) && !LLAvatarActions::isBlocked(id); });
insert("Unmute", LLAvatarActions::toggleBlock, LLAvatarActions::isBlocked);
}
void insert(const std::string& key, cb callback, vcb vcallback = nullptr)
{
mEntries[key] = std::make_pair(callback, vcallback);
}
void action(const std::string& cmd, LLUUID id) const
{
auto it = mEntries.find(cmd);
if (it != mEntries.end())
(*it).second.first(id);
}
bool visible(const std::string& cmd, LLUUID id) const
{
auto it = mEntries.find(cmd);
return it == mEntries.end() || !(*it).second.second || (*it).second.second(id);
}
};
LLMediaCtrl* get_focused_media_ctrl()
{
auto media_ctrl = dynamic_cast<LLMediaCtrl*>(gFocusMgr.getKeyboardFocus());
@@ -9837,10 +9908,7 @@ void initialize_menus()
add_radar_listeners();
// Text Editor menus
LLTextEditor::setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
LLTextEditor::setIsFriendCallback(LLAvatarActions::isFriend);
LLTextEditor::addMenuListeners();
MenuSLURLDict::getInstance();
// Media Ctrl menus
addMenu(new MediaCtrlCopyURL(), "Copy.PageURL");

View File

@@ -10,6 +10,14 @@
<menu_item_call.on_click
function="Text.Url" userdata="ShowProfile" />
</menu_item_call>
<menu_item_call label="Web Profile" name="Web Profile">
<on_click function="Text.Url.Ext" userdata="ShowWebProfile"/>
<on_visible function="Text.Url.ExtVisible" userdata="ShowWebProfile"/>
</menu_item_call>
<menu_item_call label="Pay" name="Pay">
<on_click function="Text.Url.Ext" userdata="Pay"/>
<on_visible function="Text.Url.ExtVisible" userdata="Pay"/>
</menu_item_call>
<menu_item_call
label="Send IM..."
layout="topleft"
@@ -17,6 +25,10 @@
<menu_item_call.on_click
function="Text.Url" userdata="SendIM" />
</menu_item_call>
<menu_item_call label="Call" name="Call">
<on_click function="Text.Url.Ext" userdata="Call"/>
<on_visible function="Text.Url.ExtVisible" userdata="Call"/>
</menu_item_call>
<menu_item_call
label="Add Friend..."
layout="topleft"
@@ -31,6 +43,34 @@
<menu_item_call.on_click
function="Text.Url" userdata="RemoveFriend" />
</menu_item_call>
<menu_item_call label="Invite To Group" name="Invite To Group">
<on_click function="Text.Url.Ext" userdata="InviteToGroup"/>
<on_visible function="Text.Url.ExtVisible" userdata="InviteToGroup"/>
</menu_item_call>
<menu_item_call label="Offer Teleport" name="Offer Teleport">
<on_click function="Text.Url.Ext" userdata="OfferTeleport"/>
<on_visible function="Text.Url.ExtVisible" userdata="OfferTeleport"/>
</menu_item_call>
<menu_item_call label="Teleport To" name="Teleport To">
<on_click function="Text.Url.Ext" userdata="TeleportTo"/>
<on_visible function="Text.Url.ExtVisible" userdata="TeleportTo"/>
</menu_item_call>
<menu_item_call label="Request Teleport" name="Request Teleport">
<on_click function="Text.Url.Ext" userdata="RequestTeleport"/>
<on_visible function="Text.Url.ExtVisible" userdata="RequestTeleport"/>
</menu_item_call>
<menu_item_call label="Share" name="Share">
<on_click function="Text.Url.Ext" userdata="Share"/>
<on_visible function="Text.Url.ExtVisible" userdata="Share"/>
</menu_item_call>
<menu_item_call label="Chat History" name="Chat History">
<on_click function="Text.Url.Ext" userdata="ShowLog"/>
<on_visible function="Text.Url.ExtVisible" userdata="ShowLog"/>
</menu_item_call>
<menu_item_call label="Track/Untrack" name="Track/Untrack">
<on_click function="Text.Url.Ext" userdata="Track"/>
<on_visible function="Text.Url.ExtVisible" userdata="Track"/>
</menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
@@ -53,4 +93,43 @@
<menu_item_call label="Select All" name="Select All">
<on_click function="Text" userdata="SelectAll"/>
</menu_item_call>
<menu_item_call label="Focus" name="Focus">
<on_click function="Text.Url.Ext" userdata="Focus"/>
<on_visible function="Text.Url.ExtVisible" userdata="Focus"/>
</menu_item_call>
<menu label="Moderation" name="Moderation" create_jump_keys="true">
<menu_item_call label="Mute" name="Mute">
<on_click function="Text.Url.Ext" userdata="Mute"/>
<on_visible function="Text.Url.ExtVisible" userdata="Mute"/>
</menu_item_call>
<menu_item_call label="Unmute" name="Unmute">
<on_click function="Text.Url.Ext" userdata="Unmute"/>
<on_visible function="Text.Url.ExtVisible" userdata="Unmute"/>
</menu_item_call>
<menu_item_call label="Ban From Group" name="Ban From Group">
<on_click function="Text.Url.Ext" userdata="BanFromGroup"/>
<on_visible function="Text.Url.ExtVisible" userdata="BanFromGroup"/>
</menu_item_call>
<menu_item_call label="Report Abuse" name="Report Abuse">
<on_click function="Text.Url.Ext" userdata="AbuseReport"/>
<on_visible function="Text.Url.ExtVisible" userdata="AbuseReport"/>
</menu_item_call>
<menu_item_separator/>
<menu_item_call label="Freeze" name="Freeze">
<on_click function="Text.Url.Ext" userdata="Freeze"/>
<on_visible function="Text.Url.ExtVisible" userdata="Freeze"/>
</menu_item_call>
<menu_item_call label="Eject/Ban from Parcel" name="Eject/Ban from Parcel">
<on_click function="Text.Url.Ext" userdata="ParcelEject"/>
<on_visible function="Text.Url.ExtVisible" userdata="ParcelEject"/>
</menu_item_call>
<menu_item_call label="Eject from estate" name="Eject from estate">
<on_click function="Text.Url.Ext" userdata="EstateEject"/>
<on_visible function="Text.Url.ExtVisible" userdata="EstateEject"/>
</menu_item_call>
<menu_item_call label="Eject and ban from estate" name="Eject and ban from estate">
<on_click function="Text.Url.Ext" userdata="EstateBan"/>
<on_visible function="Text.Url.ExtVisible" userdata="EstateBan"/>
</menu_item_call>
</menu>
</context_menu>

View File

@@ -10,6 +10,73 @@
<menu_item_call.on_click
function="Text.Url" userdata="ShowProfile" />
</menu_item_call>
<menu name="Avatar" label="Avatar">
<menu_item_call label="Web Profile" name="Web Profile">
<on_click function="Text.Url.Ext" userdata="ShowWebProfile"/>
<on_visible function="Text.Url.ExtVisible" userdata="ShowWebProfile"/>
</menu_item_call>
<menu_item_call label="Pay" name="Pay">
<on_click function="Text.Url.Ext" userdata="Pay"/>
<on_visible function="Text.Url.ExtVisible" userdata="Pay"/>
</menu_item_call>
<menu_item_call
label="Send IM..."
layout="topleft"
name="send_im">
<menu_item_call.on_click
function="Text.Url" userdata="SendIM" />
</menu_item_call>
<menu_item_call label="Call" name="Call">
<on_click function="Text.Url.Ext" userdata="Call"/>
<on_visible function="Text.Url.ExtVisible" userdata="Call"/>
</menu_item_call>
<menu_item_call
label="Add Friend..."
layout="topleft"
name="add_friend">
<menu_item_call.on_click
function="Text.Url" userdata="AddFriend" />
</menu_item_call>
<menu_item_call
label="Remove Friend..."
layout="topleft"
name="remove_friend">
<menu_item_call.on_click
function="Text.Url" userdata="RemoveFriend" />
</menu_item_call>
<menu_item_call label="Invite To Group" name="Invite To Group">
<on_click function="Text.Url.Ext" userdata="InviteToGroup"/>
<on_visible function="Text.Url.ExtVisible" userdata="InviteToGroup"/>
</menu_item_call>
<menu_item_call label="Offer Teleport" name="Offer Teleport">
<on_click function="Text.Url.Ext" userdata="OfferTeleport"/>
<on_visible function="Text.Url.ExtVisible" userdata="OfferTeleport"/>
</menu_item_call>
<menu_item_call label="Teleport To" name="Teleport To">
<on_click function="Text.Url.Ext" userdata="TeleportTo"/>
<on_visible function="Text.Url.ExtVisible" userdata="TeleportTo"/>
</menu_item_call>
<menu_item_call label="Request Teleport" name="Request Teleport">
<on_click function="Text.Url.Ext" userdata="RequestTeleport"/>
<on_visible function="Text.Url.ExtVisible" userdata="RequestTeleport"/>
</menu_item_call>
<menu_item_call label="Share" name="Share">
<on_click function="Text.Url.Ext" userdata="Share"/>
<on_visible function="Text.Url.ExtVisible" userdata="Share"/>
</menu_item_call>
<menu_item_call label="Chat History" name="Chat History">
<on_click function="Text.Url.Ext" userdata="ShowLog"/>
<on_visible function="Text.Url.ExtVisible" userdata="ShowLog"/>
</menu_item_call>
<menu_item_call label="Track/Untrack" name="Track/Untrack">
<on_click function="Text.Url.Ext" userdata="Track"/>
<on_visible function="Text.Url.ExtVisible" userdata="Track"/>
</menu_item_call>
<menu_item_call label="Focus" name="Focus">
<on_click function="Text.Url.Ext" userdata="Focus"/>
<on_visible function="Text.Url.ExtVisible" userdata="Focus"/>
</menu_item_call>
</menu>
<menu_item_separator
layout="topleft" />
<menu_item_call
@@ -32,4 +99,39 @@
<menu_item_call label="Select All" name="Select All">
<on_click function="Text" userdata="SelectAll"/>
</menu_item_call>
<menu label="Moderation" name="Moderation" create_jump_keys="true">
<menu_item_call label="Mute" name="Mute">
<on_click function="Text.Url.Ext" userdata="Mute"/>
<on_visible function="Text.Url.ExtVisible" userdata="Mute"/>
</menu_item_call>
<menu_item_call label="Unmute" name="Unmute">
<on_click function="Text.Url.Ext" userdata="Unmute"/>
<on_visible function="Text.Url.ExtVisible" userdata="Unmute"/>
</menu_item_call>
<menu_item_call label="Ban From Group" name="Ban From Group">
<on_click function="Text.Url.Ext" userdata="BanFromGroup"/>
<on_visible function="Text.Url.ExtVisible" userdata="BanFromGroup"/>
</menu_item_call>
<menu_item_call label="Report Abuse" name="Report Abuse">
<on_click function="Text.Url.Ext" userdata="AbuseReport"/>
<on_visible function="Text.Url.ExtVisible" userdata="AbuseReport"/>
</menu_item_call>
<menu_item_separator/>
<menu_item_call label="Freeze" name="Freeze">
<on_click function="Text.Url.Ext" userdata="Freeze"/>
<on_visible function="Text.Url.ExtVisible" userdata="Freeze"/>
</menu_item_call>
<menu_item_call label="Eject/Ban from Parcel" name="Eject/Ban from Parcel">
<on_click function="Text.Url.Ext" userdata="ParcelEject"/>
<on_visible function="Text.Url.ExtVisible" userdata="ParcelEject"/>
</menu_item_call>
<menu_item_call label="Eject from estate" name="Eject from estate">
<on_click function="Text.Url.Ext" userdata="EstateEject"/>
<on_visible function="Text.Url.ExtVisible" userdata="EstateEject"/>
</menu_item_call>
<menu_item_call label="Eject and ban from estate" name="Eject and ban from estate">
<on_click function="Text.Url.Ext" userdata="EstateBan"/>
<on_visible function="Text.Url.ExtVisible" userdata="EstateBan"/>
</menu_item_call>
</menu>
</context_menu>