summaryrefslogtreecommitdiff
path: root/indra/newview/llimfloater.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llimfloater.cpp')
-rw-r--r--indra/newview/llimfloater.cpp195
1 files changed, 132 insertions, 63 deletions
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 7c6de01c96..9d3c0f98ce 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -44,7 +44,7 @@
#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container
#include "llinventoryfunctions.h"
//#include "lllayoutstack.h"
-#include "lllineeditor.h"
+#include "llchatentry.h"
#include "lllogchat.h"
#include "llscreenchannel.h"
#include "llsyswellwindow.h"
@@ -106,39 +106,16 @@ void LLIMFloater::onFocusReceived()
}
// virtual
-void LLIMFloater::onClose(bool app_quitting)
+void LLIMFloater::refresh()
{
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
- mSessionID);
-
- if (session == NULL)
+ if (mMeTyping)
{
- llwarns << "Empty session." << llendl;
- return;
- }
-
- bool is_call_with_chat = session->isGroupSessionType()
- || session->isAdHocSessionType() || session->isP2PSessionType();
-
- LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
-
- if (is_call_with_chat && voice_channel != NULL
- && voice_channel->isActive())
- {
- LLSD payload;
- payload["session_id"] = mSessionID;
- LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback);
- return;
+ // Time out if user hasn't typed for a while.
+ if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS)
+ {
+ setTyping(false);
+ }
}
-
- setTyping(false);
-
- // The source of much argument and design thrashing
- // Should the window hide or the session close when the X is clicked?
- //
- // Last change:
- // EXT-3516 X Button should end IM session, _ button should hide
- gIMMgr->leaveSession(mSessionID);
}
/* static */
@@ -190,7 +167,9 @@ void LLIMFloater::sendMsg()
{
if (mInputEditor)
{
- LLWString text = mInputEditor->getConvertedText();
+ LLWString text = mInputEditor->getWText();
+ LLWStringUtil::trim(text);
+ LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.
if(!text.empty())
{
// Truncate and convert to UTF8 for transport
@@ -221,6 +200,7 @@ void LLIMFloater::sendMsg()
LLIMFloater::~LLIMFloater()
{
+ mParticipantsListRefreshConnection.disconnect();
mVoiceChannelStateChangeConnection.disconnect();
if(LLVoiceClient::instanceExists())
{
@@ -258,6 +238,8 @@ void LLIMFloater::initIMFloater()
boundVoiceChannel();
+ mTypingStart = LLTrans::getString("IM_typing_start_string");
+
// Show control panel in torn off floaters only.
mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel"));
@@ -279,6 +261,20 @@ void LLIMFloater::initIMFloater()
{
std::string session_name(LLIMModel::instance().getName(mSessionID));
updateSessionName(session_name, session_name);
+
+ // For ad hoc conferences we should update the title with participants names.
+ if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID))
+ || mDialog == IM_SESSION_CONFERENCE_START)
+ {
+ if (mParticipantsListRefreshConnection.connected())
+ {
+ mParticipantsListRefreshConnection.disconnect();
+ }
+
+ LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list");
+ mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback(
+ boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1));
+ }
}
}
@@ -287,30 +283,25 @@ BOOL LLIMFloater::postBuild()
{
LLIMConversation::postBuild();
- mInputEditor = getChild<LLLineEditor>("chat_editor");
+ mInputEditor = getChild<LLChatEntry>("chat_editor");
mInputEditor->setMaxTextLength(1023);
// enable line history support for instant message bar
- mInputEditor->setEnableLineHistory(TRUE);
LLFontGL* font = LLViewerChat::getChatFont();
mInputEditor->setFont(font);
mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) );
- mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this );
+ mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) );
mInputEditor->setCommitOnFocusLost( FALSE );
- mInputEditor->setRevertOnEsc( FALSE );
- mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
mInputEditor->setPassDelete( TRUE );
- childSetCommitCallback("chat_editor", onSendMsg, this);
+ mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this));
mChatHistory = getChild<LLChatHistory>("chat_history");
setDocked(true);
- mTypingStart = LLTrans::getString("IM_typing_start_string");
-
LLButton* add_btn = getChild<LLButton>("add_btn");
// Allow to add chat participants depending on the session type
@@ -377,7 +368,9 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids)
for (uuid_vec_t::const_iterator id = uuids.begin();
id != uuids.end(); ++id)
{
- if (*id == mOtherParticipantUUID)
+ // Skip this check for ad hoc conferences,
+ // conference participants should be listed in mSession->mInitialTargetIDs.
+ if (mIsP2PChat && *id == mOtherParticipantUUID)
{
return false;
}
@@ -447,11 +440,6 @@ void LLIMFloater::onCallButtonClicked()
}
}
-/*void LLIMFloater::onOpenVoiceControlsClicked()
-{
- LLFloaterReg::showInstance("voice_controls");
-}*/
-
void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL)
@@ -484,25 +472,59 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
mTypingStart.setArg("[NAME]", ui_title);
}
-// virtual
-BOOL LLIMFloater::tick()
+void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)
{
- // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater
- // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy().
- if (isDead()) return false;
+ LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl);
+ if (!avatar_list)
+ {
+ return;
+ }
- BOOL parents_retcode = LLIMConversation::tick();
+ bool all_names_resolved = true;
+ std::vector<LLSD> participants_uuids;
- if ( mMeTyping )
+ avatar_list->getValues(participants_uuids);
+
+ // Check whether we have all participants names in LLAvatarNameCache
+ for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it)
{
- // Time out if user hasn't typed for a while.
- if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+ const LLUUID& id = it->asUUID();
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(id, &av_name))
{
- setTyping(false);
+ all_names_resolved = false;
+
+ // If a name is not found in cache, request it and continue the process recursively
+ // until all ids are resolved into names.
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list));
+ break;
}
}
- return parents_retcode;
+ if (all_names_resolved)
+ {
+ std::vector<LLAvatarName> avatar_names;
+ std::vector<LLSD>::const_iterator it = participants_uuids.begin();
+ for (; it != participants_uuids.end(); ++it)
+ {
+ const LLUUID& id = it->asUUID();
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(id, &av_name))
+ {
+ avatar_names.push_back(av_name);
+ }
+ }
+
+ // We should check whether the vector is not empty to pass the assertion
+ // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString.
+ if (!avatar_names.empty())
+ {
+ std::string ui_title;
+ LLAvatarActions::buildResidentsString(avatar_names, ui_title);
+ updateSessionName(ui_title, ui_title);
+ }
+ }
}
//static
@@ -528,8 +550,10 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
}
}
+ // Test the existence of the floater before we try to create it
bool exist = findInstance(session_id);
+ // Get the floater: this will create the instance if it didn't exist
LLIMFloater* floater = getInstance(session_id);
if (!floater)
return NULL;
@@ -538,18 +562,21 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
{
LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance();
- // do not add existed floaters to avoid adding torn off instances
+ // Do not add again existing floaters
if (!exist)
{
// LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
// TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists
LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END;
-
if (floater_container)
{
floater_container->addFloater(floater, TRUE, i_pt);
}
}
+
+ // Add a conversation list item in the left pane: nothing will be done if already in there
+ // but relevant clean up will be done to ensure consistency of the conversation list
+ floater_container->addConversationListItem(floater->getTitle(), session_id, floater);
floater->openFloater(floater->getKey());
}
@@ -599,6 +626,44 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id)
return conversation;
}
+void LLIMFloater::onClose(bool app_quitting)
+{
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
+ mSessionID);
+
+ if (session == NULL)
+ {
+ llwarns << "Empty session." << llendl;
+ return;
+ }
+
+ bool is_call_with_chat = session->isGroupSessionType()
+ || session->isAdHocSessionType() || session->isP2PSessionType();
+
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+
+ if (is_call_with_chat && voice_channel != NULL
+ && voice_channel->isActive())
+ {
+ LLSD payload;
+ payload["session_id"] = mSessionID;
+ LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback);
+ return;
+ }
+
+ setTyping(false);
+
+ // The source of much argument and design thrashing
+ // Should the window hide or the session close when the X is clicked?
+ //
+ // Last change:
+ // EXT-3516 X Button should end IM session, _ button should hide
+ gIMMgr->leaveSession(mSessionID);
+
+ // Clean up the conversation *after* the session has been ended
+ LLIMConversation::onClose(app_quitting);
+}
+
void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
{
// update notification channel state
@@ -726,8 +791,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
{
initIMSession(im_session_id);
- boundVoiceChannel();
-
buildParticipantList();
}
@@ -877,7 +940,7 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd
}
// static
-void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
+void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata)
{
LLIMFloater* self = (LLIMFloater*) userdata;
std::string text = self->mInputEditor->getText();
@@ -1013,6 +1076,12 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
*accept = ACCEPT_NO;
}
}
+ else if (mDialog == IM_NOTHING_SPECIAL)
+ {
+ LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop,
+ cargo_type, cargo_data, accept);
+ }
+
return TRUE;
}
@@ -1074,7 +1143,7 @@ private:
BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)
{
LLViewerRegion* region = gAgent.getRegion();
- bool is_region_exist = !!region;
+ bool is_region_exist = region != NULL;
if (is_region_exist)
{