From 90c7684112714fd5ca2c8d73d8ca9bef3fc1e5d6 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 10 Apr 2025 17:57:16 +0300 Subject: #3758 add support for highlighted segments --- indra/llui/llurlregistry.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/llui/llurlregistry.cpp') diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index cec1ddfc57..6e6e3be9b4 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -233,12 +233,13 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL match_entry->getQuery(url), match_entry->getTooltip(url), match_entry->getIcon(url), - match_entry->getStyle(), + match_entry->getStyle(url), match_entry->getMenuName(), match_entry->getLocation(url), match_entry->getID(url), - match_entry->underlineOnHoverOnly(url), - match_entry->isTrusted()); + match_entry->getUnderline(url), + match_entry->isTrusted(), + match_entry->getSkipProfileIcon(url)); return true; } @@ -274,7 +275,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr match.getMenuName(), match.getLocation(), match.getID(), - match.underlineOnHoverOnly()); + match.getUnderline(), + false, + match.getSkipProfileIcon()); return true; } return false; -- cgit v1.3 From 17561e2ad13ec5c32e49f26e70b4ee291433db04 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 23 Apr 2025 21:01:46 +0300 Subject: #3758 show mention name in bubble chat --- indra/llui/lltextbase.cpp | 2 +- indra/llui/llurlentry.cpp | 49 ++++++++++++++++++++++++++---------------- indra/llui/llurlentry.h | 14 +++++++++++- indra/llui/llurlregistry.cpp | 9 +++++++- indra/llui/llurlregistry.h | 3 ++- indra/newview/llviewerchat.cpp | 8 +++++++ 6 files changed, 62 insertions(+), 23 deletions(-) (limited to 'indra/llui/llurlregistry.cpp') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 5f62763683..677dc63b25 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2335,7 +2335,7 @@ void LLTextBase::appendTextImpl(const std::string& new_text, const LLStyle::Para LLUrlMatch match; std::string text = new_text; while (LLUrlRegistry::instance().findUrl(text, match, - boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3), isContentTrusted() || mAlwaysShowIcons)) + boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3), isContentTrusted() || mAlwaysShowIcons, force_slurl)) { start = match.getStart(); end = match.getEnd()+1; diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 9657dc9527..a2062d077e 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -580,7 +580,7 @@ LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL() // LLUrlEntryAgent::LLUrlEntryAgent() { - mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/(mention|(?!mention)\\w+)", + mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/\\w+", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_agent.xml"; mIcon = "Generic_Person"; @@ -673,19 +673,9 @@ LLUrlMatch::EUnderlineLink LLUrlEntryAgent::getUnderline(const std::string& stri { return LLUrlMatch::EUnderlineLink::UNDERLINE_ON_HOVER; } - else if (LLStringUtil::endsWith(url, "/mention")) - { - return LLUrlMatch::EUnderlineLink::UNDERLINE_NEVER; - } return LLUrlMatch::EUnderlineLink::UNDERLINE_ALWAYS; } -bool LLUrlEntryAgent::getSkipProfileIcon(const std::string& string) const -{ - std::string url = getUrl(string); - return (LLStringUtil::endsWith(url, "/mention")) ? true : false; -} - std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb) { if (!gCacheName) @@ -730,14 +720,7 @@ LLStyle::Params LLUrlEntryAgent::getStyle(const std::string &url) const LLStyle::Params style_params = LLUrlEntryBase::getStyle(url); style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); - if (LLStringUtil::endsWith(url, "/mention")) - { - style_params.font.style = "NORMAL"; - style_params.draw_highlight_bg = true; - LLUUID agent_id(getIDStringFromUrl(url)); - style_params.highlight_bg_color = LLUIColorTable::instance().getColor((agent_id == sAgentID) ? "ChatSelfMentionHighlight" : "ChatMentionHighlight"); - } return style_params; } @@ -784,7 +767,35 @@ std::string LLUrlEntryAgent::getIcon(const std::string &url) { // *NOTE: Could look up a badge here by calling getIDStringFromUrl() // and looking up the badge for the agent. - return LLStringUtil::endsWith(url, "/mention") ? std::string() : mIcon; + return mIcon; +} + +/// +/// LLUrlEntryAgentMention Describes a chat mention Url, e.g., +/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/mention +/// +LLUrlEntryAgentMention::LLUrlEntryAgentMention() +{ + mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/mention", boost::regex::perl | boost::regex::icase); + mMenuName = "menu_url_agent.xml"; + mIcon = std::string(); +} + +LLUrlMatch::EUnderlineLink LLUrlEntryAgentMention::getUnderline(const std::string& string) const +{ + return LLUrlMatch::EUnderlineLink::UNDERLINE_NEVER; +} + +LLStyle::Params LLUrlEntryAgentMention::getStyle(const std::string& url) const +{ + LLStyle::Params style_params = LLUrlEntryAgent::getStyle(url); + style_params.font.style = "NORMAL"; + style_params.draw_highlight_bg = true; + + LLUUID agent_id(getIDStringFromUrl(url)); + style_params.highlight_bg_color = LLUIColorTable::instance().getColor((agent_id == sAgentID) ? "ChatSelfMentionHighlight" : "ChatMentionHighlight"); + + return style_params; } // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index af5b8f5d83..df3932b2a0 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -234,7 +234,6 @@ public: /*virtual*/ LLUUID getID(const std::string &string) const; LLUrlMatch::EUnderlineLink getUnderline(const std::string& string) const; - bool getSkipProfileIcon(const std::string& string) const; protected: /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon); @@ -245,6 +244,19 @@ private: avatar_name_cache_connection_map_t mAvatarNameCacheConnections; }; +/// +/// LLUrlEntryAgentMention Describes a chat mention Url, e.g., +/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/mention +class LLUrlEntryAgentMention : public LLUrlEntryAgent +{ +public: + LLUrlEntryAgentMention(); + + LLStyle::Params getStyle(const std::string& url) const; + LLUrlMatch::EUnderlineLink getUnderline(const std::string& string) const; + bool getSkipProfileIcon(const std::string& string) const { return true; }; +}; + /// /// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g., /// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 6e6e3be9b4..02d88c83fb 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -62,6 +62,8 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryAgentUserName()); // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since // LLUrlEntryAgent is a less specific (catchall for agent urls) + mUrlEntryAgentMention = new LLUrlEntryAgentMention(); + registerUrl(mUrlEntryAgentMention); registerUrl(new LLUrlEntryAgent()); registerUrl(new LLUrlEntryChat()); registerUrl(new LLUrlEntryGroup()); @@ -155,7 +157,7 @@ static bool stringHasUrl(const std::string &text) text.find("@") != std::string::npos); } -bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted) +bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted, bool skip_non_mentions) { // avoid costly regexes if there is clearly no URL in the text if (! stringHasUrl(text)) @@ -176,6 +178,11 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL continue; } + if (skip_non_mentions && (mUrlEntryAgentMention != *it)) + { + continue; + } + LLUrlEntryBase *url_entry = *it; U32 start = 0, end = 0; diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 64cfec3960..35c6c0d84f 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -76,7 +76,7 @@ public: /// your callback is invoked if the matched Url's label changes in the future bool findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback, - bool is_content_trusted = false); + bool is_content_trusted = false, bool skip_non_mentions = false); /// a slightly less efficient version of findUrl for wide strings bool findUrl(const LLWString &text, LLUrlMatch &match, @@ -102,6 +102,7 @@ private: LLUrlEntryBase* mUrlEntrySLLabel; LLUrlEntryBase* mUrlEntryNoLink; LLUrlEntryBase* mUrlEntryKeybinding; + LLUrlEntryBase* mUrlEntryAgentMention; }; #endif diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp index 8b01c4ef88..2ca2c5c07d 100644 --- a/indra/newview/llviewerchat.cpp +++ b/indra/newview/llviewerchat.cpp @@ -36,6 +36,7 @@ #include "llviewerregion.h" #include "llworld.h" #include "llinstantmessage.h" //SYSTEM_FROM +#include "llurlregistry.h" // LLViewerChat LLViewerChat::font_change_signal_t LLViewerChat::sChatFontChangedSignal; @@ -222,6 +223,13 @@ void LLViewerChat::formatChatMsg(const LLChat& chat, std::string& formated_msg) { std::string tmpmsg = chat.mText; + // show @name instead of slurl for chat mentions + LLUrlMatch match; + while (LLUrlRegistry::instance().findUrl(tmpmsg, match, LLUrlRegistryNullCallback, false, true)) + { + tmpmsg.replace(match.getStart(), match.getEnd() - match.getStart() + 1, match.getLabel()); + } + if(chat.mChatStyle == CHAT_STYLE_IRC) { formated_msg = chat.mFromName + tmpmsg.substr(3); -- cgit v1.3 From 50108bf0b7953e1f44a13b0790fe8dd8e9f7d2ca Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 7 May 2025 18:59:00 +0300 Subject: #4011 Add conversation list highlight for chat mention --- indra/llui/llfolderviewitem.h | 2 +- indra/llui/llurlentry.cpp | 5 +++++ indra/llui/llurlentry.h | 3 +++ indra/llui/llurlregistry.cpp | 27 +++++++++++++++++++++++++++ indra/llui/llurlregistry.h | 2 ++ indra/newview/llconversationview.cpp | 9 ++++++--- indra/newview/llconversationview.h | 3 ++- indra/newview/llfloaterimcontainer.cpp | 4 ++-- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llimview.cpp | 8 +++++--- indra/newview/llviewermessage.cpp | 2 ++ indra/newview/skins/default/colors.xml | 3 +++ 12 files changed, 59 insertions(+), 11 deletions(-) (limited to 'indra/llui/llurlregistry.cpp') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 234d0dc7f9..2ee018a90a 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -154,7 +154,7 @@ protected: virtual bool isHighlightActive(); virtual bool isFadeItem(); virtual bool isFlashing() { return false; } - virtual void setFlashState(bool) { } + virtual void setFlashState(bool, bool) { } static LLFontGL* getLabelFontForStyle(U8 style); const LLFontGL* getLabelFont(); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 7218211a44..bcd13b7f0b 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -630,6 +630,11 @@ LLUUID LLUrlEntryAgent::getID(const std::string &string) const return LLUUID(getIDStringFromUrl(string)); } +bool LLUrlEntryAgent::isAgentID(const std::string& url) const +{ + return sAgentID == getID(url); +} + std::string LLUrlEntryAgent::getTooltip(const std::string &string) const { // return a tooltip corresponding to the URL type instead of the generic one diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 740e99acfd..6e7d2fc80f 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -103,6 +103,7 @@ public: virtual bool getSkipProfileIcon(const std::string& string) const { return false; } virtual LLUUID getID(const std::string &string) const { return LLUUID::null; } + virtual bool isAgentID(const std::string& url) const { return false; } bool isLinkDisabled() const; @@ -232,6 +233,8 @@ public: /*virtual*/ LLStyle::Params getStyle(const std::string &url) const; /*virtual*/ LLUUID getID(const std::string &string) const; + bool isAgentID(const std::string& url) const; + LLStyle::EUnderlineLink getUnderline(const std::string& string) const; protected: diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 02d88c83fb..cb101d325d 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -327,3 +327,30 @@ void LLUrlRegistry::setKeybindingHandler(LLKeyBindingToStringHandler* handler) LLUrlEntryKeybinding *entry = (LLUrlEntryKeybinding*)mUrlEntryKeybinding; entry->setHandler(handler); } + +bool LLUrlRegistry::containsAgentMention(const std::string& text) +{ + // avoid costly regexes if there is clearly no URL in the text + if (!stringHasUrl(text)) + { + return false; + } + + try + { + boost::sregex_iterator it(text.begin(), text.end(), mUrlEntryAgentMention->getPattern()); + boost::sregex_iterator end; + for (; it != end; ++it) + { + if (mUrlEntryAgentMention->isAgentID(it->str())) + { + return true; + } + } + } + catch (boost::regex_error&) + { + LL_INFOS() << "Regex error for: " << text << LL_ENDL; + } + return false; +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index b9502f4592..592e422487 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -92,6 +92,8 @@ public: // Set handler for url registry to be capable of parsing and populating keybindings void setKeybindingHandler(LLKeyBindingToStringHandler* handler); + bool containsAgentMention(const std::string& text); + private: std::vector mUrlEntry; LLUrlEntryBase* mUrlEntryTrusted; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index a1f627c8cc..0e0ab236d6 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -86,7 +86,8 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mHasArrow(true), mIsInActiveVoiceChannel(false), mFlashStateOn(false), - mFlashStarted(false) + mFlashStarted(false), + mIsAltFlashColor(false) { mFlashTimer = new LLFlashTimer(); mAreChildrenInited = true; // inventory only @@ -157,7 +158,7 @@ void LLConversationViewSession::destroyView() LLFolderViewFolder::destroyView(); } -void LLConversationViewSession::setFlashState(bool flash_state) +void LLConversationViewSession::setFlashState(bool flash_state, bool alternate_color) { if (flash_state && !mFlashStateOn) { @@ -170,6 +171,7 @@ void LLConversationViewSession::setFlashState(bool flash_state) mFlashStateOn = flash_state; mFlashStarted = false; + mIsAltFlashColor = mFlashStateOn && (alternate_color || mIsAltFlashColor); mFlashTimer->stopFlashing(); } @@ -288,7 +290,8 @@ void LLConversationViewSession::draw() startFlashing(); // draw highlight for selected items - drawHighlight(show_context, true, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); + static LLUIColor alt_color = LLUIColorTable::instance().getColor("MentionFlashBgColor", DEFAULT_WHITE); + drawHighlight(show_context, true, sHighlightBgColor, mIsAltFlashColor ? alt_color : sFlashBgColor, sFocusOutlineColor, sMouseOverColor); // Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap. bool draw_children = getRoot() == static_cast(this) || isOpen(); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 8eb6392121..a6d240ed84 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -90,7 +90,7 @@ public: virtual void refresh(); - /*virtual*/ void setFlashState(bool flash_state); + /*virtual*/ void setFlashState(bool flash_state, bool alternate_color = false); void setHighlightState(bool hihglight_state); LLFloater* getSessionFloater(); @@ -111,6 +111,7 @@ private: LLFlashTimer* mFlashTimer; bool mFlashStateOn; bool mFlashStarted; + bool mIsAltFlashColor; bool mCollapsedMode; bool mHasArrow; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index e4b14d8df6..72d4d30dcf 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -2302,14 +2302,14 @@ bool LLFloaterIMContainer::isConversationLoggingAllowed() return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0; } -void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) +void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes, bool alternate_color) { //Finds the conversation line item to flash using the session_id LLConversationViewSession * widget = dynamic_cast(get_ptr_in_map(mConversationsWidgets,session_id)); if (widget) { - widget->setFlashState(is_flashes); + widget->setFlashState(is_flashes, alternate_color); } } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index e5486e67da..30eed8be36 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -208,7 +208,7 @@ public: void reSelectConversation(); void updateSpeakBtnState(); static bool isConversationLoggingAllowed(); - void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); + void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes, bool alternate_color = false); void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted); bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget); boost::signals2::connection mMicroChangedSignal; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 474b7b66d7..23bba99ed6 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -71,6 +71,7 @@ #include "llviewerregion.h" #include "llcorehttputil.h" #include "lluiusage.h" +#include "llurlregistry.h" #include @@ -197,6 +198,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg) LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); bool store_dnd_message = false; // flag storage of a dnd message bool is_session_focused = session_floater->isTornOff() && session_floater->hasFocus(); + bool contains_mention = LLUrlRegistry::getInstance()->containsAgentMention(msg["message"].asString()); if (!LLFloater::isVisible(im_box) || im_box->isMinimized()) { conversations_floater_status = CLOSED; @@ -323,7 +325,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg) if ("openconversations" == user_preferences || ON_TOP == conversations_floater_status || ("toast" == user_preferences && ON_TOP != conversations_floater_status) - || ("flash" == user_preferences && (CLOSED == conversations_floater_status + || (("flash" == user_preferences || contains_mention) && (CLOSED == conversations_floater_status || NOT_ON_TOP == conversations_floater_status)) || is_dnd_msg) { @@ -343,7 +345,7 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg) } else { - im_box->flashConversationItemWidget(session_id, true); + im_box->flashConversationItemWidget(session_id, true, contains_mention); } } } @@ -3269,7 +3271,7 @@ void LLIMMgr::addMessage( { LLFloaterReg::showInstance("im_container"); LLFloaterReg::getTypedInstance("im_container")-> - flashConversationItemWidget(new_session_id, true); + flashConversationItemWidget(new_session_id, true, LLUrlRegistry::getInstance()->containsAgentMention(msg)); } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index bdcfec34f6..1501ba41c2 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2583,6 +2583,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) msg_notify["session_id"] = LLUUID(); msg_notify["from_id"] = chat.mFromID; msg_notify["source_type"] = chat.mSourceType; + // used to check if there is agent mention in the message + msg_notify["message"] = mesg; on_new_message(msg_notify); } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index f0ada22d66..0c34a3a5fb 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -1009,4 +1009,7 @@ + -- cgit v1.3