Add menu entries for copying mentions URIs and inserting mentions into chats from the participants list or avatar URIs, even when the avatar does not come up in the @mention chooser.

master
Zi Ree 2025-11-21 00:11:32 +01:00
parent 228d4a602f
commit 2a6b5cbde5
16 changed files with 196 additions and 0 deletions

View File

@ -278,3 +278,18 @@ void LLChatEntry::paste()
}
}
// </FS:Ansariel>
// <FS:Zi> Add menu items to copy and/or insert mention URIs into chat
void LLChatEntry::insertMentionAtCursor(const std::string& str)
{
S32 cursor_from_end = getLength() - getCursorPos();
insertText(str);
std::string new_text(wstring_to_utf8str(getConvertedText()));
clear();
appendTextImpl(new_text, LLStyle::Params(), true);
setCursorPos(getLength() - cursor_from_end);
}
// </FS:Zi>

View File

@ -71,6 +71,9 @@ public:
// <FS:Ansariel> Changed to public so we can update history when using modifier keys
void updateHistory();
// <FS:Zi> Add menu items to copy and/or insert mention URIs into chat
void insertMentionAtCursor(const std::string& str);
// <FS:Ansariel> Fix linefeed pasting
/*virtual*/ void paste();

View File

@ -2451,6 +2451,11 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
enable_registrar.add("FS.EnableViewLog", std::bind(&FSRegistrarUtils::checkIsEnabled, gFSRegistrarUtils, target_id, EFSRegistrarFunctionActionType::FS_RGSTR_ACT_VIEW_TRANSCRIPT));
// </FS:Ansariel>
// <FS:Zi> Add menu items to copy and/or insert mention URIs into chat
registrar.add("Mention.CopyURI", boost::bind(&LLUrlAction::copyURLToClipboard, "secondlife:///app/agent/" + target_id_str + "/mention"));
registrar.add("Mention.Chat", boost::bind(&LLTextBase::insertMentionAtCursor, this, "secondlife:///app/agent/" + target_id_str + "/mention"));
// </FS:Zi>
// <FS:Zi> FIRE-30725 - Add more group functions to group URL context menu
registrar.add("FS.JoinGroup", std::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupjoin", true));
registrar.add("FS.LeaveGroup", std::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupleave", true));
@ -2521,6 +2526,14 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
}
// </FS:Zi>
// <FS:Zi> Add menu items to copy and/or insert mention URIs into chat
if (!parent_floater || (parent_floater->getName() != "panel_im" && parent_floater->getName() != "nearby_chat"))
{
menu->getChild<LLView>("MentionURISeparator")->setVisible(false);
menu->getChild<LLView>("mention_in_chat")->setVisible(false);
}
// </FS:Zi>
menu->show(x, y);
LLMenuGL::showPopup(this, menu, x, y);
}
@ -4577,3 +4590,10 @@ void LLTextBase::setWordWrap(bool wrap)
{
mWordWrap = wrap;
}
// <FS:Zi> Add menu items to copy and/or insert mention URIs into chat
// virtual
void LLTextBase::insertMentionAtCursor(const std::string& str)
{
}
// </FS:Zi>

View File

@ -727,6 +727,9 @@ protected:
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link = e_underline::UNDERLINE_ALWAYS);
S32 normalizeUri(std::string& uri);
// <FS:Zi> Add menu items to copy and/or insert mention URIs into chat
virtual void insertMentionAtCursor(const std::string& str);
protected:
// virtual
std::string _getSearchText() const override

View File

@ -128,6 +128,8 @@ LLObjectIMHandler gObjectIMHandler;
class FSChatHistoryHeader: public LLPanel
{
public:
typedef boost::function<void (const std::string& speaker_id)> insert_mention_callback_t;
FSChatHistoryHeader()
: LLPanel(),
mInfoCtrl(NULL),
@ -150,6 +152,7 @@ public:
mTimeBoxTextBox(NULL),
mHeaderLayoutStack(NULL),
mAvatarNameCacheConnection(),
mInsertMentionCallback(NULL),
mTime(0)
{}
@ -180,6 +183,24 @@ public:
}
}
void setInsertMentionCallback(insert_mention_callback_t cb)
{
mInsertMentionCallback = cb;
}
void copyURLToClipboard()
{
LLUrlAction::copyURLToClipboard("secondlife:///app/agent/" + mAvatarID.asString() + "/mention");
}
void insertMentionAtCursor()
{
if (mInsertMentionCallback)
{
mInsertMentionCallback("secondlife:///app/agent/" + mAvatarID.asString() + "/mention");
}
}
bool handleMouseUp(S32 x, S32 y, MASK mask)
{
return LLPanel::handleMouseUp(x,y,mask);
@ -1069,6 +1090,9 @@ protected:
registrar_enable.add("AvatarIcon.Enable", boost::bind(&FSChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
registrar_enable.add("AvatarIcon.Visible", boost::bind(&FSChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
registrar.add("Mention.CopyURI", boost::bind(&FSChatHistoryHeader::copyURLToClipboard, this));
registrar.add("Mention.Chat", boost::bind(&FSChatHistoryHeader::insertMentionAtCursor, this));
menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if (menu)
{
@ -1256,6 +1280,8 @@ protected:
private:
boost::signals2::connection mAvatarNameCacheConnection;
insert_mention_callback_t mInsertMentionCallback;
};
FSChatHistory::FSChatHistory(const FSChatHistory::Params& p)
@ -1353,6 +1379,17 @@ void FSChatHistory::initFromParams(const FSChatHistory::Params& p)
setShowContextMenu(true);
}
// virtual
void FSChatHistory::insertMentionAtCursor(const std::string& str)
{
updateChatInputLine();
if (mChatInputLine)
{
mChatInputLine->insertMentionAtCursor(str);
mChatInputLine->setFocus(true);
}
}
LLView* FSChatHistory::getSeparator()
{
LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageSeparatorFilename, NULL, LLPanel::child_registry_t::instance());
@ -1365,6 +1402,7 @@ LLView* FSChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style
if (header)
{
header->setup(chat, style_params, args);
header->setInsertMentionCallback(boost::bind(&FSChatHistory::insertMentionAtCursor, this, _1));
}
return header;
}

View File

@ -110,6 +110,8 @@ class FSChatHistory : public LLTextEditor // <FS:Zi> FIRE-8600: TAB out of cha
LLSD getValue() const;
void initFromParams(const Params&);
virtual void insertMentionAtCursor(const std::string& str);
/**
* Appends a widget message.
* If last user appended message, concurs with current user,

View File

@ -61,6 +61,7 @@ LLContextMenu* FSContactsFriendsMenu::createMenu()
registrar.add("Contacts.Friends.CopyLabel", boost::bind(&FSContactsFriendsMenu::copyNameToClipboard, this, id));
registrar.add("Contacts.Friends.CopyUrl", boost::bind(&FSContactsFriendsMenu::copySLURLToClipboard, this, id));
registrar.add("Contacts.Friends.SelectOption", boost::bind(&FSContactsFriendsMenu::selectOption, this, _2));
registrar.add("Mention.CopyURI", boost::bind(&FSContactsFriendsMenu::copyURLToClipboard, this));
enable_registrar.add("Contacts.Friends.EnableItem", boost::bind(&FSContactsFriendsMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Contacts.Friends.EnableZoomIn", boost::bind(&LLAvatarActions::canZoomIn, id));
@ -237,3 +238,8 @@ bool FSContactsFriendsMenu::checkOption(const LLSD& userdata)
return false;
}
void FSContactsFriendsMenu::copyURLToClipboard()
{
LLUrlAction::copyURLToClipboard("secondlife:///app/agent/" + mUUIDs.front().asString() + "/mention");
}

View File

@ -44,6 +44,7 @@ private:
void copySLURLToClipboard(const LLUUID& id);
void selectOption(const LLSD& userdata);
bool checkOption(const LLSD& userdata);
void copyURLToClipboard();
};
extern FSContactsFriendsMenu gFSContactsFriendsMenu;

View File

@ -32,6 +32,8 @@
#include "fsparticipantlist.h"
#include "llagent.h"
#include "llchatentry.h"
#include "fsfloaterim.h"
#include "llimview.h"
#include "llspeakers.h"
@ -88,7 +90,16 @@ void FSPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
return;
mParticipantList = new FSParticipantList(speaker_manager, getChild<LLAvatarList>("grp_speakers_list"), true,false);
if (mParticipantList)
{
mParticipantList->setInsertMentionCallback(boost::bind(&FSPanelGroupControlPanel::insertMentionAtCursor, this, _1));
}
}
}
void FSPanelGroupControlPanel::insertMentionAtCursor(const LLUUID& avatar_id)
{
FSFloaterIM::getInstance(getSessionId())->findChild<LLChatEntry>("chat_editor")->insertMentionAtCursor("secondlife:///app/agent/" + avatar_id.asString() + "/mention");
}
uuid_vec_t FSPanelGroupControlPanel::getParticipants() const

View File

@ -69,6 +69,7 @@ public:
void draw() override;
uuid_vec_t getParticipants() const override;
void insertMentionAtCursor(const LLUUID& url);
protected:
LLUUID mGroupID;

View File

@ -39,6 +39,7 @@
#include "llnotificationsutil.h"
#include "lloutputmonitorctrl.h"
#include "llspeakers.h"
#include "llurlaction.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
#include "llvoiceclient.h"
@ -69,6 +70,7 @@ FSParticipantList::FSParticipantList(LLSpeakerMgr* data_source,
mParticipantListMenu(NULL),
mExcludeAgent(exclude_agent),
mValidateSpeakerCallback(NULL),
mInsertMentionCallback(NULL),
mConvType(CONV_UNKNOWN)
{
mSpeakerAddListener = new SpeakerAddListener(*this);
@ -301,6 +303,11 @@ void FSParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t c
mValidateSpeakerCallback = cb;
}
void FSParticipantList::setInsertMentionCallback(insert_mention_callback_t cb)
{
mInsertMentionCallback = cb;
}
void FSParticipantList::update()
{
mSpeakerMgr->update(true);
@ -530,6 +537,9 @@ LLContextMenu* FSParticipantList::FSParticipantListMenu::createMenu()
registrar.add("ParticipantList.ModerateVoice", boost::bind(&FSParticipantList::FSParticipantListMenu::moderateVoice, this, _2));
registrar.add("Mention.CopyURI", boost::bind(&FSParticipantList::FSParticipantListMenu::copyURLToClipboard, this, mUUIDs.front()));
registrar.add("Mention.Chat", boost::bind(&FSParticipantList::FSParticipantListMenu::insertMentionAtCursor, this, mUUIDs.front()));
enable_registrar.add("ParticipantList.EnableItem", boost::bind(&FSParticipantList::FSParticipantListMenu::enableContextMenuItem, this, _2));
enable_registrar.add("ParticipantList.EnableItem.Moderate", boost::bind(&FSParticipantList::FSParticipantListMenu::enableModerateContextMenuItem, this, _2));
enable_registrar.add("ParticipantList.CheckItem", boost::bind(&FSParticipantList::FSParticipantListMenu::checkContextMenuItem, this, _2));
@ -556,6 +566,19 @@ LLContextMenu* FSParticipantList::FSParticipantListMenu::createMenu()
return main_menu;
}
void FSParticipantList::FSParticipantListMenu::copyURLToClipboard(const LLUUID& avatar_id)
{
LLUrlAction::copyURLToClipboard("secondlife:///app/agent/" + mUUIDs.front().asString() + "/mention");
}
void FSParticipantList::FSParticipantListMenu::insertMentionAtCursor(const LLUUID& avatar_id)
{
if (mParent.mInsertMentionCallback)
{
mParent.mInsertMentionCallback(avatar_id);
}
}
void FSParticipantList::FSParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y)
{
if (uuids.size() == 0) return;

View File

@ -53,6 +53,7 @@ public:
};
typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
typedef boost::function<void (const LLUUID& speaker_id)> insert_mention_callback_t;
FSParticipantList(LLSpeakerMgr* data_source,
LLAvatarList* avatar_list,
@ -94,6 +95,7 @@ public:
* @see onAddItemEvent()
*/
void setValidateSpeakerCallback(validate_speaker_callback_t cb);
void setInsertMentionCallback(insert_mention_callback_t cb);
EConversationType const getType() const { return mConvType; }
@ -240,6 +242,10 @@ protected:
static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response);
void handleAddToContactSet();
// mentions support
void copyURLToClipboard(const LLUUID& avatar_id);
void insertMentionAtCursor(const LLUUID& avatar_id);
};
/**
@ -300,6 +306,8 @@ private:
LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
validate_speaker_callback_t mValidateSpeakerCallback;
insert_mention_callback_t mInsertMentionCallback;
EConversationType mConvType;
};

View File

@ -129,6 +129,14 @@
name="copy url">
<on_click function="AvatarIcon.Action" parameter="copy_url" />
</menu_item_call>
<!-- <FS:Zi> Add menu items to copy and/or insert mention URIs into chat -->
<menu_item_call
label="Copy Mention URI to clipboard"
layout="topleft"
name="mention_copy_label">
<on_click function="Mention.CopyURI" />
</menu_item_call>
<!-- </FS:Zi> -->
<menu_item_separator layout="topleft" name="separator_block"/>
<menu_item_call
label="Report Abuse"
@ -195,4 +203,16 @@
<on_click function="AvatarIcon.Action" parameter="ban_member" />
<on_enable function="AvatarIcon.Enable" parameter="can_ban_member" />
</menu_item_call>
<!-- <FS:Zi> Add menu items to copy and/or insert mention URIs into chat -->
<menu_item_separator
name="MentionURISeparator"
layout="topleft" />
<menu_item_call
label="Mention User in Chat"
layout="topleft"
name="mention_in_chat">
<menu_item_call.on_click
function="Mention.Chat" />
</menu_item_call>
<!-- </FS:Zi> -->
</toggleable_menu>

View File

@ -115,6 +115,15 @@
<menu_item_call.on_click
function="Contacts.Friends.CopyUrl"/>
</menu_item_call>
<!-- <FS:Zi> Add menu items to copy and/or insert mention URIs into chat -->
<menu_item_call
label="Copy Mention URI to clipboard"
layout="topleft"
name="mention_copy_label">
<menu_item_call.on_click
function="Mention.CopyURI" />
</menu_item_call>
<!-- </FS:Zi> -->
<menu_item_separator/>
<menu name="options" label="Options...">
<menu_item_check

View File

@ -241,4 +241,21 @@
<on_click function="Avatar.BanMember" parameter="ban_member" />
<on_enable function="ParticipantList.EnableItem" parameter="can_ban_member" />
</menu_item_call>
<!-- <FS:Zi> Add menu items to copy and/or insert mention URIs into chat -->
<menu_item_separator layout="topleft" name="MentionURISeparator"/>
<menu_item_call
label="Copy Mention URI to clipboard"
layout="topleft"
name="mention_copy_label">
<menu_item_call.on_click
function="Mention.CopyURI" />
</menu_item_call>
<menu_item_call
label="Mention User in Chat"
layout="topleft"
name="mention_in_chat">
<menu_item_call.on_click
function="Mention.Chat" />
</menu_item_call>
<!-- </FS:Zi> -->
</context_menu>

View File

@ -177,4 +177,23 @@
<menu_item_call.on_click
function="Url.CopyUrl" />
</menu_item_call>
<!-- <FS:Zi> Add menu items to copy and/or insert mention URIs into chat -->
<menu_item_call
label="Copy Mention URI to clipboard"
layout="topleft"
name="mention_copy_label">
<menu_item_call.on_click
function="Mention.CopyURI" />
</menu_item_call>
<menu_item_separator
name="MentionURISeparator"
layout="topleft" />
<menu_item_call
label="Mention User in Chat"
layout="topleft"
name="mention_in_chat">
<menu_item_call.on_click
function="Mention.Chat" />
</menu_item_call>
<!-- </FS:Zi> -->
</context_menu>