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.cpp1148
1 files changed, 643 insertions, 505 deletions
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 63eedcdfea..e4032738a7 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -28,44 +28,44 @@
#include "llimfloater.h"
+#include "lldraghandle.h"
#include "llnotificationsutil.h"
#include "llagent.h"
#include "llappviewer.h"
+#include "llavataractions.h"
#include "llavatarnamecache.h"
#include "llbutton.h"
#include "llchannelmanager.h"
#include "llchiclet.h"
#include "llchicletbar.h"
#include "llfloaterreg.h"
+#include "llfloateravatarpicker.h"
#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container
#include "llinventoryfunctions.h"
-#include "lllayoutstack.h"
-#include "lllineeditor.h"
+//#include "lllayoutstack.h"
+#include "llchatentry.h"
#include "lllogchat.h"
-#include "llpanelimcontrolpanel.h"
#include "llscreenchannel.h"
#include "llsyswellwindow.h"
#include "lltrans.h"
#include "llchathistory.h"
#include "llnotifications.h"
#include "llviewerwindow.h"
-#include "llvoicechannel.h"
#include "lltransientfloatermgr.h"
#include "llinventorymodel.h"
#include "llrootview.h"
#include "llspeakers.h"
#include "llviewerchat.h"
+#include "llnotificationmanager.h"
#include "llautoreplace.h"
+floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal;
+
LLIMFloater::LLIMFloater(const LLUUID& session_id)
- : LLTransientDockableFloater(NULL, true, session_id),
- mControlPanel(NULL),
- mSessionID(session_id),
+ : LLIMConversation(session_id),
mLastMessageIndex(-1),
mDialog(IM_NOTHING_SPECIAL),
- mChatHistory(NULL),
- mInputEditor(NULL),
mSavedTitle(),
mTypingStart(),
mShouldSendTypingState(false),
@@ -74,38 +74,13 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mTypingTimer(),
mTypingTimeoutTimer(),
mPositioned(false),
- mSessionInitialized(false)
+ mSessionInitialized(false),
+ mStartConferenceInSameFloater(false)
{
- LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID);
- if (im_session)
- {
- mSessionInitialized = im_session->mSessionInitialized;
+ mIsNearbyChat = false;
+
+ initIMSession(session_id);
- mDialog = im_session->mType;
- switch(mDialog){
- case IM_NOTHING_SPECIAL:
- case IM_SESSION_P2P_INVITE:
- mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
- break;
- case IM_SESSION_CONFERENCE_START:
- mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
- break;
- case IM_SESSION_GROUP_START:
- mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
- break;
- case IM_SESSION_INVITE:
- if (gAgent.isInGroup(mSessionID))
- {
- mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
- }
- else
- {
- mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
- }
- break;
- default: break;
- }
- }
setOverlapsScreenChannel(true);
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
@@ -113,50 +88,61 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
setDocked(true);
}
-void LLIMFloater::onFocusLost()
+
+// virtual
+void LLIMFloater::refresh()
{
- LLIMModel::getInstance()->resetActiveSessionID();
-
- LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false);
+ if (mMeTyping)
+{
+ // Time out if user hasn't typed for a while.
+ if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS)
+ {
+ setTyping(false);
+ }
+ }
}
-void LLIMFloater::onFocusReceived()
+// virtual
+void LLIMFloater::onClickCloseBtn()
{
- LLIMModel::getInstance()->setActiveSessionID(mSessionID);
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID);
+
+ if (session != NULL)
+ {
+ bool is_call_with_chat = session->isGroupSessionType()
+ || session->isAdHocSessionType() || session->isP2PSessionType();
- LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true);
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
- if (getVisible())
+ if (is_call_with_chat && voice_channel != NULL
+ && voice_channel->isActive())
+ {
+ LLSD payload;
+ payload["session_id"] = mSessionID;
+ LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback);
+ return;
+ }
+ }
+ else
{
- LLIMModel::instance().sendNoUnreadMessages(mSessionID);
+ llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl;
+ return;
}
-}
-
-// virtual
-void LLIMFloater::onClose(bool app_quitting)
-{
- 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);
+ LLIMConversation::onClickCloseBtn();
}
/* static */
-void LLIMFloater::newIMCallback(const LLSD& data){
-
+void LLIMFloater::newIMCallback(const LLSD& data)
+{
if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())
{
LLUUID session_id = data["session_id"].asUUID();
LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
- if (floater == NULL) return;
// update if visible, otherwise will be updated when opened
- if (floater->getVisible())
+ if (floater && floater->getVisible())
{
floater->updateMessages();
}
@@ -183,113 +169,112 @@ void LLIMFloater::onVisibilityChange(const LLSD& new_visibility)
void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
{
LLIMFloater* self = (LLIMFloater*) userdata;
- self->sendMsg();
+ self->sendMsgFromInputEditor();
self->setTyping(false);
}
-void LLIMFloater::sendMsg()
+void LLIMFloater::sendMsgFromInputEditor()
{
- if (!gAgent.isGodlike()
- && (mDialog == IM_NOTHING_SPECIAL)
- && mOtherParticipantUUID.isNull())
- {
- llinfos << "Cannot send IM to everyone unless you're a god." << llendl;
- return;
- }
-
- if (mInputEditor)
+ if (gAgent.isGodlike()
+ || (mDialog != IM_NOTHING_SPECIAL)
+ || !mOtherParticipantUUID.isNull())
{
- LLWString text = mInputEditor->getConvertedText();
- if(!text.empty())
+ if (mInputEditor)
{
- // Truncate and convert to UTF8 for transport
- std::string utf8_text = wstring_to_utf8str(text);
- utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
-
- if (mSessionInitialized)
- {
- LLIMModel::sendMessage(utf8_text, mSessionID,
- mOtherParticipantUUID,mDialog);
- }
- else
+ LLWString text = mInputEditor->getWText();
+ LLWStringUtil::trim(text);
+ LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.
+ if(!text.empty())
{
- //queue up the message to send once the session is initialized
- mQueuedMsgsForInit.append(utf8_text);
- }
+ // Truncate and convert to UTF8 for transport
+ std::string utf8_text = wstring_to_utf8str(text);
- mInputEditor->setText(LLStringUtil::null);
+ sendMsg(utf8_text);
- updateMessages();
+ mInputEditor->setText(LLStringUtil::null);
+ }
}
}
+ else
+ {
+ llinfos << "Cannot send IM to everyone unless you're a god." << llendl;
+ }
}
+void LLIMFloater::sendMsg(const std::string& msg)
+{
+ const std::string utf8_text = utf8str_truncate(msg, MAX_MSG_BUF_SIZE - 1);
+ if (mSessionInitialized)
+ {
+ LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog);
+ }
+ else
+ {
+ //queue up the message to send once the session is initialized
+ mQueuedMsgsForInit.append(utf8_text);
+ }
-LLIMFloater::~LLIMFloater()
-{
- LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
+ updateMessages();
}
-//virtual
-BOOL LLIMFloater::postBuild()
+LLIMFloater::~LLIMFloater()
{
- const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
- if (other_party_id.notNull())
+ mParticipantsListRefreshConnection.disconnect();
+ mVoiceChannelStateChangeConnection.disconnect();
+ if(LLVoiceClient::instanceExists())
{
- mOtherParticipantUUID = other_party_id;
+ LLVoiceClient::getInstance()->removeObserver(this);
}
- mControlPanel->setSessionId(mSessionID);
- mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel"));
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
+}
- LLButton* slide_left = getChild<LLButton>("slide_left_btn");
- slide_left->setVisible(mControlPanel->getParent()->getVisible());
- slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
- LLButton* slide_right = getChild<LLButton>("slide_right_btn");
- slide_right->setVisible(!mControlPanel->getParent()->getVisible());
- slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+void LLIMFloater::initIMSession(const LLUUID& session_id)
+{
+ // Change the floater key to bind it to a new session.
+ setKey(session_id);
- mInputEditor = getChild<LLLineEditor>("chat_editor");
- mInputEditor->setMaxTextLength(1023);
- // enable line history support for instant message bar
- mInputEditor->setEnableLineHistory(TRUE);
- // *TODO Establish LineEditor with autoreplace callback
- mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2));
+ mSessionID = session_id;
+ mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
- 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->setCommitOnFocusLost( FALSE );
- mInputEditor->setRevertOnEsc( FALSE );
- mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
- mInputEditor->setPassDelete( TRUE );
+ if (mSession)
+ {
+ mIsP2PChat = mSession->isP2PSessionType();
+ mSessionInitialized = mSession->mSessionInitialized;
- childSetCommitCallback("chat_editor", onSendMsg, this);
-
- mChatHistory = getChild<LLChatHistory>("chat_history");
+ mDialog = mSession->mType;
+ }
+}
- setDocked(true);
+void LLIMFloater::initIMFloater()
+{
+ const LLUUID& other_party_id =
+ LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
+ if (other_party_id.notNull())
+ {
+ mOtherParticipantUUID = other_party_id;
+ }
+
+ boundVoiceChannel();
mTypingStart = LLTrans::getString("IM_typing_start_string");
+ // Show control panel in torn off floaters only.
+ mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel"));
+
// Disable input editor if session cannot accept text
- LLIMModel::LLIMSession* im_session =
- LLIMModel::instance().findIMSession(mSessionID);
- if( im_session && !im_session->mTextIMPossible )
+ if ( mSession && !mSession->mTextIMPossible )
{
mInputEditor->setEnabled(FALSE);
mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
}
- if ( im_session && im_session->isP2PSessionType())
+ if (mIsP2PChat)
{
// look up display name for window title
- LLAvatarNameCache::get(im_session->mOtherParticipantID,
+ LLAvatarNameCache::get(mSession->mOtherParticipantID,
boost::bind(&LLIMFloater::onAvatarNameCache,
this, _1, _2));
}
@@ -297,167 +282,418 @@ BOOL LLIMFloater::postBuild()
{
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));
+ }
}
+}
+
+//virtual
+BOOL LLIMFloater::postBuild()
+{
+ BOOL result = LLIMConversation::postBuild();
+
+ mInputEditor->setMaxTextLength(1023);
+ // enable line history support for instant message bar
+ // XXX stinson TODO : resolve merge by adding autoreplace to text editors
+#if 0
+ // *TODO Establish LineEditor with autoreplace callback
+ mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2));
+#endif
+
+ mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
+ mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) );
+ mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) );
+ mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this));
+
+ setDocked(true);
+
+ LLButton* add_btn = getChild<LLButton>("add_btn");
+
+ // Allow to add chat participants depending on the session type
+ add_btn->setEnabled(isInviteAllowed());
+ add_btn->setClickedCallback(boost::bind(&LLIMFloater::onAddButtonClicked, this));
+
+ childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this));
+
+ LLVoiceClient::getInstance()->addObserver(this);
//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
//see LLFloaterIMPanel for how it is done (IB)
- if(isChatMultiTab())
+ initIMFloater();
+
+ return result;
+}
+
+void LLIMFloater::onAddButtonClicked()
+{
+ LLView * button = findChild<LLView>("toolbar_panel")->findChild<LLButton>("add_btn");
+ LLFloater* root_floater = gFloaterView->getParentFloater(this);
+ LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button);
+ if (!picker)
{
- return LLFloater::postBuild();
+ return;
}
- else
+
+ // Need to disable 'ok' button when selected users are already in conversation.
+ picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1));
+
+ if (root_floater)
{
- return LLDockableFloater::postBuild();
+ root_floater->addDependentFloater(picker);
}
}
-void LLIMFloater::updateSessionName(const std::string& ui_title,
- const std::string& ui_label)
+bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids)
{
- mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label);
- setTitle(ui_title);
+ if (!mSession
+ || mDialog == IM_SESSION_GROUP_START
+ || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID))
+ {
+ return false;
+ }
+
+ if (mIsP2PChat)
+ {
+ // For a P2P session just check if we are not adding the other participant.
+
+ for (uuid_vec_t::const_iterator id = uuids.begin();
+ id != uuids.end(); ++id)
+ {
+ if (*id == mOtherParticipantUUID)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // For a conference session we need to check against the list from LLSpeakerMgr,
+ // because this list may change when participants join or leave the session.
+
+ LLSpeakerMgr::speaker_list_t speaker_list;
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if (speaker_mgr)
+ {
+ speaker_mgr->getSpeakerList(&speaker_list, true);
+ }
+
+ for (uuid_vec_t::const_iterator id = uuids.begin();
+ id != uuids.end(); ++id)
+ {
+ for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin();
+ it != speaker_list.end(); ++it)
+ {
+ const LLPointer<LLSpeaker>& speaker = *it;
+ if (*id == speaker->mID)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
}
-void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
- const LLAvatarName& av_name)
+void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids)
{
- // Use display name only for labels, as the extended name will be in the
- // floater title
- std::string ui_title = av_name.getCompleteName();
- updateSessionName(ui_title, av_name.mDisplayName);
- mTypingStart.setArg("[NAME]", ui_title);
+ if (mIsP2PChat)
+ {
+ LLSD payload;
+ LLSD args;
+
+ LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload,
+ boost::bind(&LLIMFloater::addP2PSessionParticipants, this, _1, _2, uuids));
+ }
+ else
+ {
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+
+ inviteToSession(uuids);
+ }
}
-// virtual
-void LLIMFloater::draw()
+void LLIMFloater::addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids)
{
- if ( mMeTyping )
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0)
{
- // Time out if user hasn't typed for a while.
- if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
- {
- setTyping(false);
- }
+ return;
}
- LLTransientDockableFloater::draw();
-}
+ mStartConferenceInSameFloater = true;
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
-// static
-void* LLIMFloater::createPanelIMControl(void* userdata)
+ // first check whether this is a voice session
+ bool is_voice_call = voice_channel != NULL && voice_channel->isActive();
+
+ uuid_vec_t temp_ids;
+
+ // Add the initial participant of a P2P session
+ temp_ids.push_back(mOtherParticipantUUID);
+ temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end());
+
+ // then we can close the current session
+ onClose(false);
+
+ // we start a new session so reset the initialization flag
+ mSessionInitialized = false;
+
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+
+ // Start a new ad hoc voice call if we invite new participants to a P2P call,
+ // or start a text chat otherwise.
+ if (is_voice_call)
+ {
+ LLAvatarActions::startAdhocCall(temp_ids, mSessionID);
+ }
+ else
+ {
+ LLAvatarActions::startConference(temp_ids, mSessionID);
+ }
+}
+
+void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids)
{
- LLIMFloater *self = (LLIMFloater*)userdata;
- self->mControlPanel = new LLPanelIMControlPanel();
- self->mControlPanel->setXMLFilename("panel_im_control_panel.xml");
- return self->mControlPanel;
+ std::string names_string;
+ LLAvatarActions::buildResidentsString(uuids, names_string);
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = names_string;
+
+ sendMsg(getString(uuids.size() > 1 ? "multiple_participants_added" : "participant_added", args));
}
+void LLIMFloater::boundVoiceChannel()
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+ if(voice_channel)
+ {
+ mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(
+ boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2));
-// static
-void* LLIMFloater::createPanelGroupControl(void* userdata)
+ //call (either p2p, group or ad-hoc) can be already in started state
+ bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED;
+ updateCallBtnState(callIsActive);
+ }
+}
+
+void LLIMFloater::onCallButtonClicked()
{
- LLIMFloater *self = (LLIMFloater*)userdata;
- self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID);
- self->mControlPanel->setXMLFilename("panel_group_control_panel.xml");
- return self->mControlPanel;
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+ if (voice_channel)
+ {
+ bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED;
+ if (is_call_active)
+ {
+ gIMMgr->endCall(mSessionID);
+ }
+ else
+ {
+ gIMMgr->startCall(mSessionID);
+ }
+ }
}
-// static
-void* LLIMFloater::createPanelAdHocControl(void* userdata)
+void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
- LLIMFloater *self = (LLIMFloater*)userdata;
- self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
- self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
- return self->mControlPanel;
+ if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL)
+ {
+ enableDisableCallBtn();
+ }
}
-void LLIMFloater::onSlide()
+void LLIMFloater::onVoiceChannelStateChanged(
+ const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
- mControlPanel->getParent()->setVisible(!mControlPanel->getParent()->getVisible());
+ bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED;
+ updateCallBtnState(callIsActive);
+}
- gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getParent()->getVisible());
+void LLIMFloater::updateSessionName(const std::string& ui_title,
+ const std::string& ui_label)
+{
+ mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label);
+ setTitle(ui_title);
+}
- getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible());
- getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible());
+void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ // Use display name only for labels, as the extended name will be in the
+ // floater title
+ std::string ui_title = av_name.getCompleteName();
+ updateSessionName(ui_title, av_name.mDisplayName);
+ mTypingStart.setArg("[NAME]", ui_title);
}
-//static
-LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
+void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)
{
- closeHiddenIMToasts();
+ LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl);
+ if (!avatar_list)
+ {
+ return;
+ }
- if (!gIMMgr->hasSession(session_id)) return NULL;
+ bool all_names_resolved = true;
+ std::vector<LLSD> participants_uuids;
+ uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string
- if(!isChatMultiTab())
+ 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)
{
- //hide all
- LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
- for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
- iter != inst_list.end(); ++iter)
- {
- LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter);
- if (floater && floater->isDocked())
- {
- floater->setVisible(false);
- }
- }
+ const LLUUID& id = it->asUUID();
+ temp_uuids.push_back(id);
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(id, &av_name))
+ {
+ 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;
+ }
}
+ if (all_names_resolved)
+ {
+ std::string ui_title;
+ LLAvatarActions::buildResidentsString(temp_uuids, ui_title);
+ updateSessionName(ui_title, ui_title);
+ }
+}
+
+void LLIMFloater::addToHost(const LLUUID& session_id, const bool force)
+{
+ if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id))
+ {
+ return;
+ }
+
+ // 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;
-
- if(isChatMultiTab())
+ if (floater)
{
+
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);
}
}
- floater->openFloater(floater->getKey());
- }
- else
- {
- // Docking may move chat window, hide it before moving, or user will see how window "jumps"
- floater->setVisible(false);
-
- if (floater->getDockControl() == NULL)
+ if (force)
{
- LLChiclet* chiclet =
- LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(
- session_id);
- if (chiclet == NULL)
+ if (floater_container && floater_container->getVisible())
{
- llerror("Dock chiclet for LLIMFloater doesn't exists", 0);
+ floater->openFloater(floater->getKey());
+ floater->setVisible(TRUE);
}
else
{
- LLChicletBar::getInstance()->getChicletPanel()->scrollToChiclet(chiclet);
+ floater->setVisible(FALSE);
}
-
- floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(),
- LLDockControl::BOTTOM));
}
+ }
+}
+
+
+//static
+LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
+{
+ closeHiddenIMToasts();
+
+ if (!gIMMgr->hasSession(session_id))
+ return NULL;
+
+ // 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;
+
+ LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance();
- // window is positioned, now we can show it.
+ // 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);
+ }
}
+
+ floater->openFloater(floater->getKey());
+
floater->setVisible(TRUE);
return floater;
}
+//static
+LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id)
+{
+ LLIMFloater* conversation =
+ LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+
+ return conversation;
+}
+
+LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id)
+{
+ LLIMFloater* conversation =
+ LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id);
+
+ return conversation;
+}
+
+void LLIMFloater::onClose(bool app_quitting)
+{
+ 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)
{
@@ -479,11 +715,25 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
}
}
+void LLIMFloater::setFocus(BOOL focusFlag)
+{
+ LLTransientDockableFloater::setFocus(focusFlag);
+
+ //Redirect focus to input editor
+ if (focusFlag)
+ {
+ updateMessages();
+ mInputEditor->setFocus(TRUE);
+ }
+
+}
+
void LLIMFloater::setVisible(BOOL visible)
{
LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
(LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+
LLTransientDockableFloater::setVisible(visible);
// update notification channel state
@@ -493,21 +743,6 @@ void LLIMFloater::setVisible(BOOL visible)
channel->redrawToasts();
}
- BOOL is_minimized = visible && isChatMultiTab()
- ? LLIMFloaterContainer::getInstance()->isMinimized()
- : !visible;
-
- if (!is_minimized && mChatHistory && mInputEditor)
- {
- //only if floater was construced and initialized from xml
- updateMessages();
- //prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781)
- if (!isChatMultiTab() || hasFocus())
- {
- mInputEditor->setFocus(TRUE);
- }
- }
-
if(!visible)
{
LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID);
@@ -516,13 +751,24 @@ void LLIMFloater::setVisible(BOOL visible)
chiclet->setToggleState(false);
}
}
+
+ if (visible && isInVisibleChain())
+ {
+ sIMFloaterShowedSignal(mSessionID);
+
+ }
+
+ setFocus(visible);
}
BOOL LLIMFloater::getVisible()
{
+ bool visible;
+
if(isChatMultiTab())
{
- LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance();
+ LLIMFloaterContainer* im_container =
+ LLIMFloaterContainer::getInstance();
// Treat inactive floater as invisible.
bool is_active = im_container->getActiveFloater() == this;
@@ -530,16 +776,21 @@ BOOL LLIMFloater::getVisible()
//torn off floater is always inactive
if (!is_active && getHost() != im_container)
{
- return LLTransientDockableFloater::getVisible();
+ visible = LLTransientDockableFloater::getVisible();
}
-
+ else
+ {
// getVisible() returns TRUE when Tabbed IM window is minimized.
- return is_active && !im_container->isMinimized() && im_container->getVisible();
+ visible = is_active && !im_container->isMinimized()
+ && im_container->getVisible();
+ }
}
else
{
- return LLTransientDockableFloater::getVisible();
+ visible = LLTransientDockableFloater::getVisible();
}
+
+ return visible;
}
//static
@@ -547,7 +798,8 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
{
if(!isChatMultiTab())
{
- LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+ LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>(
+ "impanel", session_id);
if (floater && floater->getVisible() && floater->hasFocus())
{
// clicking on chiclet to close floater just hides it to maintain existing
@@ -568,17 +820,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
return true;
}
-//static
-LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id)
-{
- return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
-}
-
-LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id)
-{
- return LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id);
-}
-
void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
{
mSessionInitialized = true;
@@ -586,53 +827,40 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
//will be different only for an ad-hoc im session
if (mSessionID != im_session_id)
{
- mSessionID = im_session_id;
- setKey(im_session_id);
- mControlPanel->setSessionId(im_session_id);
- }
+ initIMSession(im_session_id);
- // updating "Call" button from group control panel here to enable it without placing into draw() (EXT-4796)
- if(gAgent.isInGroup(im_session_id))
- {
- mControlPanel->updateCallButton();
+ buildParticipantList();
}
+
+ initIMFloater();
//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
-
- //need to send delayed messaged collected while waiting for session initialization
- if (!mQueuedMsgsForInit.size()) return;
- LLSD::array_iterator iter;
- for ( iter = mQueuedMsgsForInit.beginArray();
- iter != mQueuedMsgsForInit.endArray();
- ++iter)
+ //need to send delayed messages collected while waiting for session initialization
+ if (mQueuedMsgsForInit.size())
{
- LLIMModel::sendMessage(iter->asString(), mSessionID,
- mOtherParticipantUUID, mDialog);
+ LLSD::array_iterator iter;
+ for ( iter = mQueuedMsgsForInit.beginArray();
+ iter != mQueuedMsgsForInit.endArray(); ++iter)
+ {
+ LLIMModel::sendMessage(iter->asString(), mSessionID,
+ mOtherParticipantUUID, mDialog);
+ }
+
+ mQueuedMsgsForInit.clear();
}
}
void LLIMFloater::updateMessages()
{
- bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");
-
std::list<LLSD> messages;
// we shouldn't reset unread message counters if IM floater doesn't have focus
- if (hasFocus())
- {
- LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
- }
- else
- {
- LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1);
- }
+ LLIMModel::instance().getMessages(
+ mSessionID, messages, mLastMessageIndex + 1, hasFocus());
if (messages.size())
{
- LLSD chat_args;
- chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
-
std::ostringstream message;
std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
@@ -682,7 +910,8 @@ void LLIMFloater::updateMessages()
chat.mText = message;
}
- mChatHistory->appendMessage(chat, chat_args);
+ // Add the message to the chat log
+ appendMessage(chat);
mLastMessageIndex = msg["index"].asInteger();
// if it is a notification - next message is a notification history log, so skip it
@@ -706,6 +935,7 @@ void LLIMFloater::reloadMessages()
mChatHistory->clear();
mLastMessageIndex = -1;
updateMessages();
+ mInputEditor->setFont(LLViewerChat::getChatFont());
}
// static
@@ -732,19 +962,13 @@ 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();
- if (!text.empty())
- {
- self->setTyping(true);
- }
- else
- {
+
// Deleting all text counts as stopping typing.
- self->setTyping(false);
- }
+ self->setTyping(!text.empty());
}
void LLIMFloater::setTyping(bool typing)
@@ -769,27 +993,24 @@ void LLIMFloater::setTyping(bool typing)
// much network traffic. Only send in person-to-person IMs.
if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )
{
- if ( mMeTyping )
+ // Still typing, send 'start typing' notification or
+ // send 'stop typing' notification immediately
+ if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f)
{
- if ( mTypingTimer.getElapsedTimeF32() > 1.f )
- {
- // Still typing, send 'start typing' notification
- LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
- mShouldSendTypingState = false;
- }
+ LLIMModel::instance().sendTypingState(mSessionID,
+ mOtherParticipantUUID, mMeTyping);
+ mShouldSendTypingState = false;
}
- else
+ }
+
+ if (!mIsNearbyChat)
+ {
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if (speaker_mgr)
{
- // Send 'stop typing' notification immediately
- LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
- mShouldSendTypingState = false;
+ speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
}
}
-
- LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
- if (speaker_mgr)
- speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
-
}
void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
@@ -808,55 +1029,66 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
void LLIMFloater::processAgentListUpdates(const LLSD& body)
{
- if ( !body.isMap() ) return;
+ uuid_vec_t joined_uuids;
- if ( body.has("agent_updates") && body["agent_updates"].isMap() )
+ if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap())
{
- LLSD agent_data = body["agent_updates"].get(gAgentID.asString());
- if (agent_data.isMap() && agent_data.has("info"))
+ LLSD::map_const_iterator update_it;
+ for(update_it = body["agent_updates"].beginMap();
+ update_it != body["agent_updates"].endMap();
+ ++update_it)
{
- LLSD agent_info = agent_data["info"];
+ LLUUID agent_id(update_it->first);
+ LLSD agent_data = update_it->second;
- if (agent_info.has("mutes"))
+ if (agent_data.isMap())
{
- BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean();
- mInputEditor->setEnabled(!moderator_muted_text);
- std::string label;
- if (moderator_muted_text)
- label = LLTrans::getString("IM_muted_text_label");
- else
- label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID);
- mInputEditor->setLabel(label);
+ // store the new participants in joined_uuids
+ if (agent_data.has("transition") && agent_data["transition"].asString() == "ENTER")
+ {
+ joined_uuids.push_back(agent_id);
+ }
- if (moderator_muted_text)
- LLNotificationsUtil::add("TextChatIsMutedByModerator");
+ // process the moderator mutes
+ if (agent_id == gAgentID && agent_data.has("info") && agent_data["info"].has("mutes"))
+ {
+ BOOL moderator_muted_text = agent_data["info"]["mutes"]["text"].asBoolean();
+ mInputEditor->setEnabled(!moderator_muted_text);
+ std::string label;
+ if (moderator_muted_text)
+ label = LLTrans::getString("IM_muted_text_label");
+ else
+ label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID);
+ mInputEditor->setLabel(label);
+
+ if (moderator_muted_text)
+ LLNotificationsUtil::add("TextChatIsMutedByModerator");
+ }
}
}
}
-}
-void LLIMFloater::updateChatHistoryStyle()
-{
- mChatHistory->clear();
- mLastMessageIndex = -1;
- updateMessages();
-}
+ // the vectors need to be sorted for computing the intersection and difference
+ std::sort(mInvitedParticipants.begin(), mInvitedParticipants.end());
+ std::sort(joined_uuids.begin(), joined_uuids.end());
-void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue)
-{
- LLFontGL* font = LLViewerChat::getChatFont();
- LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
- for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
- iter != inst_list.end(); ++iter)
+ uuid_vec_t intersection; // uuids of invited residents who have joined the conversation
+ std::set_intersection(mInvitedParticipants.begin(), mInvitedParticipants.end(),
+ joined_uuids.begin(), joined_uuids.end(),
+ std::back_inserter(intersection));
+
+ if (intersection.size() > 0)
{
- LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter);
- if (floater)
- {
- floater->updateChatHistoryStyle();
- floater->mInputEditor->setFont(font);
- }
+ sendParticipantsAddedNotification(intersection);
}
+ // Remove all joined participants from invited array.
+ // The difference between the two vectors (the elements in mInvitedParticipants which are not in joined_uuids)
+ // is placed at the beginning of mInvitedParticipants, then all other elements are erased.
+ mInvitedParticipants.erase(std::set_difference(mInvitedParticipants.begin(), mInvitedParticipants.end(),
+ joined_uuids.begin(), joined_uuids.end(),
+ mInvitedParticipants.begin()),
+ mInvitedParticipants.end());
}
void LLIMFloater::processSessionUpdate(const LLSD& session_update)
@@ -870,7 +1102,8 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)
if (voice_moderated)
{
- setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
+ setTitle(session_label + std::string(" ")
+ + LLTrans::getString("IM_moderated_chat_label"));
}
else
{
@@ -883,98 +1116,56 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)
}
}
-BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop, EDragAndDropType cargo_type,
- void *cargo_data, EAcceptance *accept,
+// virtual
+BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
std::string& tooltip_msg)
{
-
- if (mDialog == IM_NOTHING_SPECIAL)
+ if (cargo_type == DAD_PERSON)
{
- LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop,
- cargo_type, cargo_data, accept);
- }
-
- // handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites
- else if (isInviteAllowed())
- {
- *accept = ACCEPT_NO;
-
- if (cargo_type == DAD_CALLINGCARD)
+ if (dropPerson(static_cast<LLUUID*>(cargo_data), drop))
{
- if (dropCallingCard((LLInventoryItem*)cargo_data, drop))
- {
- *accept = ACCEPT_YES_MULTI;
- }
+ *accept = ACCEPT_YES_MULTI;
}
- else if (cargo_type == DAD_CATEGORY)
+ else
{
- if (dropCategory((LLInventoryCategory*)cargo_data, drop))
- {
- *accept = ACCEPT_YES_MULTI;
- }
+ *accept = ACCEPT_NO;
}
}
+ else if (mDialog == IM_NOTHING_SPECIAL)
+ {
+ LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop,
+ cargo_type, cargo_data, accept);
+ }
+
return TRUE;
}
-BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop)
+bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop)
{
- BOOL rv = isInviteAllowed();
- if(rv && item && item->getCreatorUUID().notNull())
+ bool res = person_id && person_id->notNull();
+ if(res)
{
- if(drop)
- {
- uuid_vec_t ids;
- ids.push_back(item->getCreatorUUID());
- inviteToSession(ids);
- }
- }
- else
- {
- // set to false if creator uuid is null.
- rv = FALSE;
- }
- return rv;
-}
+ uuid_vec_t ids;
+ ids.push_back(*person_id);
-BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop)
-{
- BOOL rv = isInviteAllowed();
- if(rv && category)
- {
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- LLUniqueBuddyCollector buddies;
- gInventory.collectDescendentsIf(category->getUUID(),
- cats,
- items,
- LLInventoryModel::EXCLUDE_TRASH,
- buddies);
- S32 count = items.count();
- if(count == 0)
+ res = canAddSelectedToChat(ids);
+ if(res && drop)
{
- rv = FALSE;
- }
- else if(drop)
- {
- uuid_vec_t ids;
- ids.reserve(count);
- for(S32 i = 0; i < count; ++i)
- {
- ids.push_back(items.get(i)->getCreatorUUID());
- }
- inviteToSession(ids);
+ addSessionParticipants(ids);
}
}
- return rv;
+
+ return res;
}
BOOL LLIMFloater::isInviteAllowed() const
{
-
return ( (IM_SESSION_CONFERENCE_START == mDialog)
- || (IM_SESSION_INVITE == mDialog) );
+ || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID))
+ || mIsP2PChat);
}
class LLSessionInviteResponder : public LLHTTPClient::Responder
@@ -998,45 +1189,39 @@ private:
BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)
{
LLViewerRegion* region = gAgent.getRegion();
- if (!region)
- {
- return FALSE;
- }
-
- S32 count = ids.size();
+ bool is_region_exist = region != NULL;
- if( isInviteAllowed() && (count > 0) )
+ if (is_region_exist)
{
- llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl;
+ S32 count = ids.size();
- std::string url = region->getCapability("ChatSessionRequest");
+ if( isInviteAllowed() && (count > 0) )
+ {
+ llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl;
- LLSD data;
+ std::string url = region->getCapability("ChatSessionRequest");
- data["params"] = LLSD::emptyArray();
- for (int i = 0; i < count; i++)
+ LLSD data;
+ data["params"] = LLSD::emptyArray();
+ for (int i = 0; i < count; i++)
+ {
+ data["params"].append(ids[i]);
+ }
+ data["method"] = "invite";
+ data["session-id"] = mSessionID;
+ LLHTTPClient::post(url, data,new LLSessionInviteResponder(mSessionID));
+ }
+ else
{
- data["params"].append(ids[i]);
+ llinfos << "LLIMFloater::inviteToSession -"
+ << " no need to invite agents for "
+ << mDialog << llendl;
+ // successful add, because everyone that needed to get added
+ // was added.
}
-
- data["method"] = "invite";
- data["session-id"] = mSessionID;
- LLHTTPClient::post(
- url,
- data,
- new LLSessionInviteResponder(
- mSessionID));
- }
- else
- {
- llinfos << "LLIMFloater::inviteToSession -"
- << " no need to invite agents for "
- << mDialog << llendl;
- // successful add, because everyone that needed to get added
- // was added.
}
- return TRUE;
+ return is_region_exist;
}
void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
@@ -1077,7 +1262,6 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
}
}
-
}
}
@@ -1094,7 +1278,8 @@ void LLIMFloater::closeHiddenIMToasts()
}
};
- LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();
+ LLNotificationsUI::LLScreenChannel* channel =
+ LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();
if (channel != NULL)
{
channel->closeHiddenToasts(IMToastMatcher());
@@ -1107,7 +1292,7 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&
const LLSD& payload = notification["payload"];
LLUUID session_id = payload["session_id"];
- LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id);
+ LLFloater* im_floater = findInstance(session_id);
if (option == 0 && im_floater != NULL)
{
im_floater->closeFloater();
@@ -1117,79 +1302,32 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&
}
// static
-bool LLIMFloater::isChatMultiTab()
-{
- // Restart is required in order to change chat window type.
- static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1;
- return is_single_window;
-}
-
-// static
-void LLIMFloater::initIMFloater()
-{
- // This is called on viewer start up
- // init chat window type before user changed it in preferences
- isChatMultiTab();
-}
-
-//static
void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)
{
LLUUID session_id = data["session_id"];
- if (session_id.isNull()) return;
+ if (session_id.isNull())
+ return;
LLUUID from_id = data["from_id"];
- if (gAgentID == from_id || LLUUID::null == from_id) return;
+ if (gAgentID == from_id || LLUUID::null == from_id)
+ return;
LLIMFloater* floater = LLIMFloater::findInstance(session_id);
- if (!floater) return;
+ if (!floater)
+ return;
- if (IM_NOTHING_SPECIAL != floater->mDialog) return;
+ if (IM_NOTHING_SPECIAL != floater->mDialog)
+ return;
floater->removeTypingIndicator();
}
void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )
{
-
- if (isChatMultiTab())
- {
- LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance();
- if (!im_box) return;
-
- if (LLIMFloater::findInstance(session_id)) return;
-
- LLIMFloater* new_tab = LLIMFloater::getInstance(session_id);
-
- im_box->addFloater(new_tab, FALSE, LLTabContainer::END);
- }
-
+ LLIMFloater::addToHost(session_id);
}
-void LLIMFloater::onClickCloseBtn()
+boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb)
{
-
- 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;
- }
-
- LLFloater::onClickCloseBtn();
+ return LLIMFloater::sIMFloaterShowedSignal.connect(cb);
}