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.cpp248
1 files changed, 193 insertions, 55 deletions
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index a20b5ea66c..b21df87093 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -42,7 +42,6 @@
#include "llchiclet.h"
#include "llfloaterchat.h"
#include "llfloaterreg.h"
-#include "llimview.h"
#include "lllineeditor.h"
#include "lllogchat.h"
#include "llpanelimcontrolpanel.h"
@@ -50,6 +49,7 @@
#include "lltrans.h"
#include "llchathistory.h"
#include "llviewerwindow.h"
+#include "llvoicechannel.h"
#include "lltransientfloatermgr.h"
@@ -61,7 +61,14 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mLastMessageIndex(-1),
mDialog(IM_NOTHING_SPECIAL),
mChatHistory(NULL),
- mInputEditor(NULL),
+ mInputEditor(NULL),
+ mSavedTitle(),
+ mTypingStart(),
+ mShouldSendTypingState(false),
+ mMeTyping(false),
+ mOtherTyping(false),
+ mTypingTimer(),
+ mTypingTimeoutTimer(),
mPositioned(false),
mSessionInitialized(false)
{
@@ -71,12 +78,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mSessionInitialized = im_session->mSessionInitialized;
mDialog = im_session->mType;
- if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
- {
+ switch(mDialog){
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
- }
- else
- {
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+ break;
+ default:
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
}
}
@@ -95,6 +105,7 @@ void LLIMFloater::onFocusReceived()
// virtual
void LLIMFloater::onClose(bool app_quitting)
{
+ setTyping(false);
gIMMgr->leaveSession(mSessionID);
}
@@ -141,6 +152,7 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
{
LLIMFloater* self = (LLIMFloater*) userdata;
self->sendMsg();
+ self->setTyping(false);
}
void LLIMFloater::sendMsg()
@@ -193,9 +205,10 @@ BOOL LLIMFloater::postBuild()
if (other_party_id.notNull())
{
mOtherParticipantUUID = other_party_id;
- mControlPanel->setID(mOtherParticipantUUID);
}
+ mControlPanel->setSessionId(mSessionID);
+
LLButton* slide_left = getChild<LLButton>("slide_left_btn");
slide_left->setVisible(mControlPanel->getVisible());
slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
@@ -222,10 +235,16 @@ BOOL LLIMFloater::postBuild()
setTitle(LLIMModel::instance().getName(mSessionID));
setDocked(true);
-
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+
+ mTypingStart = LLTrans::getString("IM_typing_start_string");
+
+ // Disable input editor if session cannot accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(mSessionID);
+ if( im_session && !im_session->mTextIMPossible )
{
- LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
+ mInputEditor->setEnabled(FALSE);
+ mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
}
//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
@@ -234,6 +253,20 @@ BOOL LLIMFloater::postBuild()
return LLDockableFloater::postBuild();
}
+// virtual
+void LLIMFloater::draw()
+{
+ if ( mMeTyping )
+ {
+ // Time out if user hasn't typed for a while.
+ if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+ {
+ setTyping(false);
+ }
+ }
+
+ LLFloater::draw();
+}
// static
@@ -255,11 +288,22 @@ void* LLIMFloater::createPanelGroupControl(void* userdata)
return self->mControlPanel;
}
+// static
+void* LLIMFloater::createPanelAdHocControl(void* userdata)
+{
+ LLIMFloater *self = (LLIMFloater*)userdata;
+ self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
+ self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
+ return self->mControlPanel;
+}
+
void LLIMFloater::onSlide()
{
LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
im_control_panel->setVisible(!im_control_panel->getVisible());
+ gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible());
+
getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible());
getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible());
}
@@ -302,6 +346,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1)));
}
+ floater->childSetVisible("panel_im_control_panel", gSavedSettings.getBOOL("IMShowControlPanel"));
+
return floater;
}
@@ -363,8 +409,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
{
// ensure the list of messages is updated when floater is made visible
show(session_id);
- // update number of unread notifications in the SysWell
- LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
return true;
}
}
@@ -379,10 +423,12 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
{
mSessionInitialized = true;
+ //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);
}
//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
@@ -402,10 +448,8 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
void LLIMFloater::updateMessages()
{
- std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
- std::string agent_name;
-
- gCacheName->getFullName(gAgentID, agent_name);
+ std::list<LLSD> messages;
+ LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
if (messages.size())
{
@@ -414,21 +458,22 @@ void LLIMFloater::updateMessages()
std::ostringstream message;
std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
- for (; iter != iter_end; ++iter)
+ for (; iter != iter_end; ++iter)
{
LLSD msg = *iter;
- std::string from = msg["from"].asString();
std::string time = msg["time"].asString();
LLUUID from_id = msg["from_id"].asUUID();
+ std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You");
std::string message = msg["message"].asString();
LLStyle::Params style_params;
style_params.color(chat_color);
- if (from == agent_name)
- from = LLTrans::getString("You");
+ LLChat chat(message);
+ chat.mFromID = from_id;
+ chat.mFromName = from;
- mChatHistory->appendWidgetMessage(from_id, from, time, message, style_params);
+ mChatHistory->appendWidgetMessage(chat, style_params);
mLastMessageIndex = msg["index"].asInteger();
}
@@ -440,9 +485,14 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
{
LLIMFloater* self= (LLIMFloater*) userdata;
- //in disconnected state IM input editor should be disabled
- self->mInputEditor->setEnabled(!gDisconnected);
-
+ // Allow enabling the LLIMFloater input editor only if session can accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(self->mSessionID);
+ if( im_session && im_session->mTextIMPossible )
+ {
+ //in disconnected state IM input editor should be disabled
+ self->mInputEditor->setEnabled(!gDisconnected);
+ }
self->mChatHistory->setCursorAndScrollToEnd();
}
@@ -450,7 +500,7 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
{
LLIMFloater* self = (LLIMFloater*) userdata;
- self->setTyping(FALSE);
+ self->setTyping(false);
}
// static
@@ -460,53 +510,141 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
std::string text = self->mInputEditor->getText();
if (!text.empty())
{
- self->setTyping(TRUE);
+ self->setTyping(true);
}
else
{
// Deleting all text counts as stopping typing.
- self->setTyping(FALSE);
+ self->setTyping(false);
}
}
-
-//just a stub for now
-void LLIMFloater::setTyping(BOOL typing)
+void LLIMFloater::setTyping(bool typing)
{
+ if ( typing )
+ {
+ // Started or proceeded typing, reset the typing timeout timer
+ mTypingTimeoutTimer.reset();
+ }
+
+ if ( mMeTyping != typing )
+ {
+ // Typing state is changed
+ mMeTyping = typing;
+ // So, should send current state
+ mShouldSendTypingState = true;
+ // In case typing is started, send state after some delay
+ mTypingTimer.reset();
+ }
+
+ // Don't want to send typing indicators to multiple people, potentially too
+ // much network traffic. Only send in person-to-person IMs.
+ if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )
+ {
+ if ( mMeTyping )
+ {
+ if ( mTypingTimer.getElapsedTimeF32() > 1.f )
+ {
+ // Still typing, send 'start typing' notification
+ LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
+ mShouldSendTypingState = false;
+ }
+ }
+ else
+ {
+ // Send 'stop typing' notification immediately
+ LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
+ mShouldSendTypingState = false;
+ }
+ }
+
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if (speaker_mgr)
+ speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
+
}
-void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
+void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
{
- if (!userdata) return;
+ if ( typing )
+ {
+ // other user started typing
+ addTypingIndicator(im_info);
+ }
+ else
+ {
+ // other user stopped typing
+ removeTypingIndicator(im_info);
+ }
+}
- LLIMFloater* self = (LLIMFloater*) userdata;
- std::string message = line;
- S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
- switch (type)
+void LLIMFloater::processSessionUpdate(const LLSD& session_update)
+{
+ // *TODO : verify following code when moderated mode will be implemented
+ if ( false && session_update.has("moderated_mode") &&
+ session_update["moderated_mode"].has("voice") )
{
- case LLLogChat::LOG_EMPTY:
- // add warning log enabled message
- if (im_log_option!=LOG_CHAT)
+ BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+ const std::string session_label = LLIMModel::instance().getName(mSessionID);
+
+ if (voice_moderated)
{
- message = LLTrans::getString("IM_logging_string");
+ setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
}
- break;
- case LLLogChat::LOG_END:
- // add log end message
- if (im_log_option!=LOG_CHAT)
+ else
{
- message = LLTrans::getString("IM_logging_string");
+ setTitle(session_label);
}
- break;
- case LLLogChat::LOG_LINE:
- // just add normal lines from file
- break;
- default:
- // nothing
- break;
+
+ // *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added
+ //update the speakers dropdown too
+ //mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
}
+}
- self->mChatHistory->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
- self->mChatHistory->blockUndo();
+void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
+{
+ // We may have lost a "stop-typing" packet, don't add it twice
+ if ( im_info && !mOtherTyping )
+ {
+ mOtherTyping = true;
+
+ // Create typing is started title string
+ LLUIString typing_start(mTypingStart);
+ typing_start.setArg("[NAME]", im_info->mName);
+
+ // Save and set new title
+ mSavedTitle = getTitle();
+ setTitle (typing_start);
+
+ // Update speaker
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if ( speaker_mgr )
+ {
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);
+ }
+ }
+}
+
+void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
+{
+ if ( mOtherTyping )
+ {
+ mOtherTyping = false;
+
+ // Revert the title to saved one
+ setTitle(mSavedTitle);
+
+ if ( im_info )
+ {
+ // Update speaker
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if ( speaker_mgr )
+ {
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
+ }
+ }
+
+ }
}