From 87b333f9cfb4cd7efc3aa38bcd94cc62ecbec1e8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 20 May 2026 00:19:20 +0300 Subject: #5809 Add 'mute' based filter for conversation history - Don't add blocked conversations - Menus and global setting to control this mechanics - Refresh on changes Decided just not to add blocked conversation to the list, an alternate way is to alter visibility logic or filter logic --- indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llconversationloglist.cpp | 65 ++++++++++++++++++++-- indra/newview/llconversationloglist.h | 10 +++- indra/newview/llfloaterconversationlog.cpp | 8 +++ .../default/xui/en/menu_conversation_log_view.xml | 10 ++++ 5 files changed, 99 insertions(+), 5 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6946ffa396..ec78603cfe 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11119,6 +11119,17 @@ Value 1 + ShowBlockedConvHistory + + Comment + Specifies whether blocked agents will be shown in Call Log + Persist + 1 + Type + Boolean + Value + 0 + ShowMatureEvents Comment diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 65863f0a5e..e9c6df3ed8 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -45,6 +45,7 @@ LLConversationLogList::LLConversationLogList(const Params& p) mIsDirty(true) { LLConversationLog::instance().addObserver(this); + LLMuteList::instance().addObserver(this); // Set up context menu. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -65,6 +66,15 @@ LLConversationLogList::LLConversationLogList(const Params& p) } mIsFriendsOnTop = gSavedSettings.getBOOL("SortFriendsFirst"); + LLControlVariable* cntrl_ptr = gSavedSettings.getControl("ShowBlockedConvHistory"); + if (cntrl_ptr) + { + mShowBlockedSignal = cntrl_ptr->getCommitSignal()->connect( + [this](LLControlVariable* control, const LLSD& value, const LLSD& previous) + { + setDirty(true); + }); + } } LLConversationLogList::~LLConversationLogList() @@ -74,6 +84,7 @@ LLConversationLogList::~LLConversationLogList() mContextMenu.get()->die(); } + LLMuteList::getInstance()->removeObserver(this); LLConversationLog::instance().removeObserver(this); } @@ -178,6 +189,44 @@ void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) } } +// inherited from LLMuteListObserver +void LLConversationLogList::onChange() +{ +} + +// inherited from LLMuteListObserver +void LLConversationLogList::onChangeDetailed(const LLMute& mute) +{ + if (isDirty()) + { + // Going to refresh either way. + return; + } + + static LLCachedControl show_blocked(gSavedSettings, "ShowBlockedConvHistory", false); + if (!show_blocked()) + { + // Check if any conversation in the log has this participant + const std::vector& conversations = LLConversationLog::instance().getConversations(); + + // Note sure if actually need this update. List can be rather large + // and rebuilding it on every event can be expensive. + // But 'mute' events are also rare, so maybe not a problem. + // There also might be a way to react only to relevant changes, + // instead of reacting to everything, like ignoring voice only mutes, + // which are not relevant for this log by themselves. + for (const LLConversation& conversation : conversations) + { + if (conversation.getParticipantID() == mute.mID) + { + setDirty(true); + break; + } + } + } + // else don't need to hide anything +} + void LLConversationLogList::addNewItem(const LLConversation* conversation) { LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); @@ -207,6 +256,9 @@ void LLConversationLogList::rebuildList() const std::vector& conversations = log_instance.getConversations(); std::vector::const_iterator iter = conversations.begin(); + LLMuteList* mutes = LLMuteList::getInstance(); + + static LLCachedControl show_blocked(gSavedSettings, "ShowBlockedConvHistory", false); for (; iter != conversations.end(); ++iter) { @@ -214,6 +266,11 @@ void LLConversationLogList::rebuildList() if (not_found) continue; + if (!show_blocked() && mutes->isMuted(iter->getParticipantID())) + { + continue; + } + addNewItem(&*iter); } @@ -517,8 +574,8 @@ bool LLConversationLogListNameComparator::doCompare(const LLConversationLogListI LLStringUtil::toUpper(name1); LLStringUtil::toUpper(name2); - bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); - if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) + static LLCachedControl sort_friends_first(gSavedSettings, "SortFriendsFirst", true); + if (sort_friends_first() && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) { return LLAvatarActions::isFriend(id1); } @@ -533,8 +590,8 @@ bool LLConversationLogListDateComparator::doCompare(const LLConversationLogListI const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); - bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); - if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) + static LLCachedControl sort_friends_first(gSavedSettings, "SortFriendsFirst", true); + if (sort_friends_first() && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) { return LLAvatarActions::isFriend(id1); } diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h index 6372f6c9a3..39f129c9f1 100644 --- a/indra/newview/llconversationloglist.h +++ b/indra/newview/llconversationloglist.h @@ -39,7 +39,7 @@ class LLConversationLogListItem; * it's always in actual state. */ -class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver +class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver, public LLMuteListObserver { LOG_CLASS(LLConversationLogList); public: @@ -76,6 +76,12 @@ public: virtual void changed(); virtual void changed(const LLUUID& session_id, U32 mask); + /** + * Changes from LLMuteListObserver + */ + virtual void onChange(); + virtual void onChangeDetailed(const LLMute& mute); + private: void setDirty(bool dirty = true) { mIsDirty = dirty; } @@ -104,6 +110,8 @@ private: bool mIsDirty; bool mIsFriendsOnTop; std::string mNameFilter; + + boost::signals2::scoped_connection mShowBlockedSignal; }; /** diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 97399c9cf7..40e2d2bf1e 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -100,6 +100,10 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) { mConversationLogList->toggleSortFriendsOnTop(); } + else if ("show_blocked" == command_name) + { + gSavedSettings.setBOOL("ShowBlockedConvHistory", !gSavedSettings.getBOOL("ShowBlockedConvHistory")); + } else if ("view_nearby_chat_history" == command_name) { LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); @@ -129,6 +133,10 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) { return gSavedSettings.getBOOL("SortFriendsFirst"); } + else if ("show_blocked" == command_name) + { + return gSavedSettings.getBOOL("ShowBlockedConvHistory"); + } return false; } diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml index 864bec5d9a..1e10a984da 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml @@ -34,6 +34,16 @@ function="CallLog.Check" parameter="sort_friends_on_top" /> + + + +