From bbc850997cd095188127d971f6cb90052615849a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Mon, 4 May 2026 23:31:14 +0300 Subject: #5756 Improve LLUICtrlFactory's performance --- indra/llui/lluictrlfactory.cpp | 2 +- indra/llui/lluictrlfactory.h | 11 ++++++++--- indra/newview/llappviewer.cpp | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 33ffc3dfc6..740f187ed8 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -67,7 +67,7 @@ public: static LLDefaultChildRegistry::Register r1("locate"); // Build time optimization, generate this once in .cpp file -template class LLUICtrlFactory* LLSingleton::getInstance(); +template class LLUICtrlFactory* LLSimpleton::getInstance(); //----------------------------------------------------------------------------- // LLUICtrlFactory() diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index f44b4ba4dc..75cee5f004 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -81,12 +81,13 @@ class LLWidgetNameRegistry // Build time optimization, generate this once in .cpp file #ifndef LLUICTRLFACTORY_CPP -extern template class LLUICtrlFactory* LLSingleton::getInstance(); +extern template class LLUICtrlFactory* LLSimpleton::getInstance(); #endif -class LLUICtrlFactory : public LLSingleton +class LLUICtrlFactory : public LLSimpleton { - LLSINGLETON(LLUICtrlFactory); +public: + LLUICtrlFactory(); ~LLUICtrlFactory(); // only partial specialization allowed in inner classes, so use extra dummy parameter @@ -313,6 +314,10 @@ template LLChildRegistry::Register::Register(const char* tag, LLWidgetCreatorFunc func) : LLChildRegistry::StaticRegistrar(tag, func == nullptr ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder : func) { + if (!LLUICtrlFactory::instanceExists()) + { + LLUICtrlFactory::createInstance(); + } // add this widget to various registries LLUICtrlFactory::instance().registerWidget(typeid(T), typeid(typename T::Params), tag); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index bae9749772..8343cc3218 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2183,6 +2183,8 @@ bool LLAppViewer::cleanup() // deleteSingleton() methods. LLSingletonBase::deleteAll(); + LLUICtrlFactory::deleteSingleton(); + LLSplashScreen::hide(); LL_INFOS() << "Goodbye!" << LL_ENDL; -- cgit v1.3 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" /> + + + + Date: Fri, 15 May 2026 19:11:26 +0300 Subject: #5804 Prevent focus steal when removing unselected conversation widget --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a0f2dbe197..e80133f93c 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1948,7 +1948,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c mConversationEventQueue.erase(uuid); // Don't let the focus fall IW, select and refocus on the first conversation in the list - if (change_focus && isInVisibleChain()) + if (change_focus && is_widget_selected && isInVisibleChain()) { setFocus(true); if (new_selection) -- cgit v1.3