SL-13397 Reduce Viewer freeze when opening chat with a large group.

meow-7.2.2
Mnikolenko Productengine 2020-06-26 15:10:46 +03:00 committed by Dave Houlton
parent 3630beed07
commit e1e25f9a0d
4 changed files with 42 additions and 21 deletions

View File

@ -57,6 +57,9 @@
#include "llviewerobjectlist.h"
#include "boost/foreach.hpp"
const S32 EVENTS_PER_IDLE_LOOP = 100;
//
// LLFloaterIMContainer
//
@ -66,7 +69,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
mInitialized(false),
mIsFirstLaunch(true)
mIsFirstLaunch(true),
mConversationEventQueue()
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@ -424,7 +428,9 @@ void LLFloaterIMContainer::idle(void* user_data)
{
LLFloaterIMContainer* self = static_cast<LLFloaterIMContainer*>(user_data);
if (!self->getVisible() || self->isMinimized())
self->idleProcessEvents();
if (!self->getVisible() || self->isMinimized())
{
return;
}
@ -485,13 +491,28 @@ void LLFloaterIMContainer::idleUpdate()
}
}
void LLFloaterIMContainer::idleProcessEvents()
{
if (!mConversationEventQueue.empty())
{
S32 events_to_handle = llmin((S32)mConversationEventQueue.size(), EVENTS_PER_IDLE_LOOP);
for (S32 i = 0; i < events_to_handle; i++)
{
handleConversationModelEvent(mConversationEventQueue.back());
mConversationEventQueue.pop_back();
}
}
}
bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
{
// For debug only
//std::ostringstream llsd_value;
//llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl;
//LL_INFOS() << "LLFloaterIMContainer::onConversationModelEvent, event = " << llsd_value.str() << LL_ENDL;
// end debug
mConversationEventQueue.push_front(event);
return true;
}
void LLFloaterIMContainer::handleConversationModelEvent(const LLSD& event)
{
// Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that
// the model could change substantially and the view could echo only a portion of this model (though currently the
@ -508,7 +529,7 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
if (!session_view)
{
// We skip events that are not associated with a session
return false;
return;
}
LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id);
LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ?
@ -535,9 +556,9 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
{
LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]);
LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL);
LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
if (!participant_view && session_model && participant_model)
{
LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
{
if (session_id.isNull() || (im_sessionp && !im_sessionp->isP2PSessionType()))
{
participant_view = createConversationViewParticipant(participant_model);
@ -548,7 +569,8 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
// Add a participant view to the conversation floater
if (conversation_floater && participant_model)
{
conversation_floater->addConversationViewParticipant(participant_model);
bool skip_updating = im_sessionp && im_sessionp->isGroupChat();
conversation_floater->addConversationViewParticipant(participant_model, !skip_updating);
}
}
else if (type == "update_participant")
@ -571,12 +593,6 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
mConversationViewModel.requestSortAll();
mConversationsRoot->arrangeAll();
if (conversation_floater)
{
conversation_floater->refreshConversation();
}
return false;
}
void LLFloaterIMContainer::draw()

View File

@ -181,6 +181,7 @@ private:
bool isParticipantListExpanded();
void idleUpdate(); // for convenience (self) from static idle
void idleProcessEvents();
LLButton* mExpandCollapseBtn;
LLButton* mStubCollapseBtn;
@ -220,6 +221,7 @@ private:
LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
bool onConversationModelEvent(const LLSD& event);
void handleConversationModelEvent(const LLSD& event);
// Conversation list data
LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to
@ -229,6 +231,8 @@ private:
LLFolderView* mConversationsRoot;
LLEventStream mConversationsEventStream;
std::deque<LLSD> mConversationEventQueue;
LLTimer mParticipantRefreshTimer;
};

View File

@ -465,9 +465,10 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args)
}
}
static LLTrace::BlockTimerStatHandle FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT("Build Conversation View");
void LLFloaterIMSessionTab::buildConversationViewParticipant()
{
LL_RECORD_BLOCK_TIME(FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT);
// Clear the widget list since we are rebuilding afresh from the model
conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
while (widget_it != mConversationsWidgets.end())
@ -496,14 +497,14 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
}
}
void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model)
void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model, bool update_view)
{
// Check if the model already has an associated view
LLUUID uuid = participant_model->getUUID();
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
// If not already present, create the participant view and attach it to the root, otherwise, just refresh it
if (widget)
if (widget && update_view)
{
updateConversationViewParticipant(uuid); // overkill?
}

View File

@ -84,7 +84,7 @@ public:
/*virtual*/ void setFocus(BOOL focus);
// Handle the left hand participant list widgets
void addConversationViewParticipant(LLConversationItem* item);
void addConversationViewParticipant(LLConversationItem* item, bool update_view = true);
void removeConversationViewParticipant(const LLUUID& participant_id);
void updateConversationViewParticipant(const LLUUID& participant_id);
void refreshConversation();