summaryrefslogtreecommitdiff
path: root/indra/newview/llfloaterimcontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfloaterimcontainer.cpp')
-rw-r--r--indra/newview/llfloaterimcontainer.cpp171
1 files changed, 126 insertions, 45 deletions
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 21420b122b..9c84fa1991 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -54,9 +54,15 @@
#include "llcallbacklist.h"
#include "llworld.h"
#include "llsdserialize.h"
+#include "llviewermenu.h" // is_agent_mappable
#include "llviewerobjectlist.h"
#include "boost/foreach.hpp"
+
+const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80;
+const S32 EVENTS_PER_IDLE_LOOP_BACKGROUND = 40;
+const F32 EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE = 0.01f; // process a minimum of 1% of total events per frame
+
//
// LLFloaterIMContainer
//
@@ -66,7 +72,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));
@@ -304,12 +311,15 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLIconCtrl* icon = 0;
+ bool is_in_group = gAgent.isInGroup(session_id, TRUE);
+ LLUUID icon_id;
- if(gAgent.isInGroup(session_id, TRUE))
+ if (is_in_group)
{
LLGroupIconCtrl::Params icon_params;
icon_params.group_id = session_id;
icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
+ icon_id = session_id;
mSessions[session_id] = floaterp;
floaterp->mCloseSignal.connect(boost::bind(&LLFloaterIMContainer::onCloseFloater, this, session_id));
@@ -321,11 +331,18 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLAvatarIconCtrl::Params icon_params;
icon_params.avatar_id = avatar_id;
icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
+ icon_id = avatar_id;
mSessions[session_id] = floaterp;
floaterp->mCloseSignal.connect(boost::bind(&LLFloaterIMContainer::onCloseFloater, this, session_id));
}
+ LLFloaterIMSessionTab* floater = LLFloaterIMSessionTab::getConversation(session_id);
+ if (floater)
+ {
+ floater->updateChatIcon(icon_id);
+ }
+
// forced resize of the floater
LLRect wrapper_rect = this->mTabContainer->getLocalRect();
floaterp->setRect(wrapper_rect);
@@ -411,8 +428,11 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate()
while (current_participant_model != end_participant_model)
{
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
- // Get the avatar name for this participant id from the cache and update the model
- participant_model->updateName();
+ if (participant_model)
+ {
+ // Get the avatar name for this participant id from the cache and update the model
+ participant_model->updateName();
+ }
// Next participant
current_participant_model++;
}
@@ -424,7 +444,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;
}
@@ -447,19 +469,26 @@ void LLFloaterIMContainer::idleUpdate()
const LLConversationItem *current_session = getCurSelectedViewModelItem();
if (current_session)
{
- // Update moderator options visibility
- LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
- LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
- bool is_moderator = isGroupModerator();
- bool can_ban = haveAbilityToBan();
- while (current_participant_model != end_participant_model)
+ if (current_session->getType() == LLConversationItem::CONV_SESSION_GROUP)
{
- LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
- participant_model->setModeratorOptionsVisible(is_moderator && participant_model->getUUID() != gAgentID);
- participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
-
- current_participant_model++;
+ // Update moderator options visibility
+ LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
+ LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
+ bool is_moderator = isGroupModerator();
+ bool can_ban = haveAbilityToBan();
+ while (current_participant_model != end_participant_model)
+ {
+ LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
+ if (participant_model)
+ {
+ participant_model->setModeratorOptionsVisible(is_moderator);
+ participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
+ }
+
+ current_participant_model++;
+ }
}
+
// Update floater's title as required by the currently selected session or use the default title
LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID());
setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle);
@@ -485,13 +514,57 @@ void LLFloaterIMContainer::idleUpdate()
}
}
+void LLFloaterIMContainer::idleProcessEvents()
+{
+ LLUUID current_session_id = getSelectedSession();
+ conversations_items_deque::iterator iter = mConversationEventQueue.begin();
+ conversations_items_deque::iterator end = mConversationEventQueue.end();
+ while (iter != end)
+ {
+ std::deque<LLSD> &events = iter->second;
+ if (!events.empty())
+ {
+ S32 events_to_handle;
+ S32 query_size = (S32)events.size();
+ if (current_session_id == iter->first)
+ {
+ events_to_handle = EVENTS_PER_IDLE_LOOP_CURRENT_SESSION;
+ }
+ else
+ {
+ events_to_handle = EVENTS_PER_IDLE_LOOP_BACKGROUND;
+ }
+
+ if (events_to_handle <= query_size)
+ {
+ // Some groups can be very large and can generate huge amount of updates, scale processing up to keep up
+ events_to_handle = llmax(events_to_handle, (S32)(query_size * EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE));
+ }
+ else
+ {
+ events_to_handle = query_size;
+ }
+
+ for (S32 i = 0; i < events_to_handle; i++)
+ {
+ handleConversationModelEvent(events.back());
+ events.pop_back();
+ }
+ }
+ iter++;
+ }
+}
+
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
+ LLUUID id = event.get("session_uuid").asUUID();
+ mConversationEventQueue[id].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 +581,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 +608,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 +621,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 +645,6 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
mConversationViewModel.requestSortAll();
mConversationsRoot->arrangeAll();
- if (conversation_floater)
- {
- conversation_floater->refreshConversation();
- }
-
- return false;
}
void LLFloaterIMContainer::draw()
@@ -1409,12 +1477,21 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return is_single_select;
}
-
- // Beyond that point, if only the user agent is selected, everything is disabled
- if (is_single_select && (single_id == gAgentID))
- {
- return false;
- }
+
+ bool is_moderator_option = ("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item);
+
+ // Beyond that point, if only the user agent is selected, everything is disabled
+ if (is_single_select && (single_id == gAgentID))
+ {
+ if (is_moderator_option)
+ {
+ return enableModerateContextMenuItem(item, true);
+ }
+ else
+ {
+ return false;
+ }
+ }
// If the user agent is selected with others, everything is disabled
for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id)
@@ -1480,11 +1557,11 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return canBanSelectedMember(single_id);
}
- else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item))
- {
- // *TODO : get that out of here...
- return enableModerateContextMenuItem(item);
- }
+ else if (is_moderator_option)
+ {
+ // *TODO : get that out of here...
+ return enableModerateContextMenuItem(item);
+ }
// By default, options that not explicitely disabled are enabled
return true;
@@ -1786,12 +1863,16 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
{
new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE);
}
+
+ // Will destroy views and delete models that are not assigned to any views
widget->destroyView();
}
// Suppress the conversation items and widgets from their respective maps
mConversationsItems.erase(uuid);
mConversationsWidgets.erase(uuid);
+ // Clear event query (otherwise reopening session in some way can bombard session with stale data)
+ mConversationEventQueue.erase(uuid);
// Don't let the focus fall IW, select and refocus on the first conversation in the list
if (change_focus)
@@ -1854,7 +1935,7 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti
return LLUICtrlFactory::create<LLConversationViewParticipant>(params);
}
-bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata)
+bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self)
{
// only group moderators can perform actions related to this "enable callback"
if (!isGroupModerator())
@@ -1874,7 +1955,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user
{
return voice_channel;
}
- else if ("can_mute" == userdata)
+ else if (("can_mute" == userdata) && !is_self)
{
return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID());
}
@@ -1884,7 +1965,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user
}
// The last invoke is used to check whether the "can_allow_text_chat" will enabled
- return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID());
+ return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()) && !is_self;
}
bool LLFloaterIMContainer::isGroupModerator()