SL-13397 Reduce Viewer freeze when opening chat with a large group.
parent
3630beed07
commit
e1e25f9a0d
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue