diff options
Diffstat (limited to 'indra/newview/llimfloater.cpp')
-rw-r--r-- | indra/newview/llimfloater.cpp | 195 |
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) { |