diff options
| -rw-r--r-- | indra/newview/llimfloater.cpp | 135 | ||||
| -rw-r--r-- | indra/newview/llimfloater.h | 18 | ||||
| -rw-r--r-- | indra/newview/llimview.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 10 | 
4 files changed, 157 insertions, 12 deletions
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a20b5ea66c..97af96847c 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -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)  { @@ -95,6 +102,7 @@ void LLIMFloater::onFocusReceived()  // virtual  void LLIMFloater::onClose(bool app_quitting)  { +	setTyping(false);  	gIMMgr->leaveSession(mSessionID);  } @@ -141,6 +149,7 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )  {  	LLIMFloater* self = (LLIMFloater*) userdata;  	self->sendMsg(); +	self->setTyping(false);  }  void LLIMFloater::sendMsg() @@ -228,12 +237,27 @@ BOOL LLIMFloater::postBuild()  		LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);  	} +	mTypingStart = LLTrans::getString("IM_typing_start_string"); +  	//*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)  	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 @@ -450,7 +474,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,19 +484,118 @@ 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); +	} +} + +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::processIMTyping(const LLIMInfo* im_info, BOOL typing) +{ +	if ( typing ) +	{ +		// other user started typing +		addTypingIndicator(im_info); +	} +	else +	{ +		// other user stopped typing +		removeTypingIndicator(im_info);  	}  } +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; -//just a stub for now -void LLIMFloater::setTyping(BOOL typing) +		// 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); +			} +		} + +	}  }  void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 99810b6d6d..3559e14c89 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -55,6 +55,8 @@ public:  	// LLView overrides  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible); +	// Check typing timeout timer. +	/*virtual*/ void draw();  	// LLFloater overrides  	/*virtual*/ void onClose(bool app_quitting); @@ -85,6 +87,7 @@ public:  	void setPositioned(bool b) { mPositioned = b; };  	void onVisibilityChange(const LLSD& new_visibility); +	void processIMTyping(const LLIMInfo* im_info, BOOL typing);  private:  	// process focus events to set a currently active session @@ -94,7 +97,7 @@ private:  	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );  	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);  	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata); -	void			setTyping(BOOL typing); +	void			setTyping(bool typing);  	void			onSlide();  	static void*	createPanelIMControl(void* userdata);  	static void*	createPanelGroupControl(void* userdata); @@ -103,6 +106,11 @@ private:  	static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata); +	// Add the "User is typing..." indicator. +	void addTypingIndicator(const LLIMInfo* im_info); + +	// Remove the "User is typing..." indicator. +	void removeTypingIndicator(const LLIMInfo* im_info = NULL);  	LLPanelChatControlPanel* mControlPanel;  	LLUUID mSessionID; @@ -114,6 +122,14 @@ private:  	LLLineEditor* mInputEditor;  	bool mPositioned; +	std::string mSavedTitle; +	LLUIString mTypingStart; +	bool mMeTyping; +	bool mOtherTyping; +	bool mShouldSendTypingState; +	LLFrameTimer mTypingTimer; +	LLFrameTimer mTypingTimeoutTimer; +  	bool mSessionInitialized;  	LLSD mQueuedMsgsForInit;  }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index fa7e1170be..f8d794e967 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1991,6 +1991,12 @@ void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)  	{  		floater->processIMTyping(im_info, typing);  	} + +	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); +	if ( im_floater ) +	{ +		im_floater->processIMTyping(im_info, typing); +	}  }  class LLViewerChatterBoxSessionStartReply : public LLHTTPNode diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4c19b22ac5..7efda2b882 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -264,10 +264,6 @@  	<string name="TrackYourCamera">Track your camera</string>  	<string name="ControlYourCamera">Control your camera</string> -	<!-- IM --> -	<string name="IM_logging_string">-- Instant message logging enabled --</string> -	<string name="Unnamed">(Unnamed)</string> -	  	<!-- Sim Access labels -->  	<string name="SIM_ACCESS_PG">PG</string>  	<string name="SIM_ACCESS_MATURE">Mature</string> @@ -2884,7 +2880,11 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	  Failed to start viewer  	</string> -  <!-- IM system messages --> +	<!-- IM system messages --> +	<string name="IM_logging_string">-- Instant message logging enabled --</string> +	<string name="IM_typing_start_string">[NAME] is typing...</string> +	<string name="Unnamed">(Unnamed)</string> +    <string name="ringing-im">      Joining Voice Chat...    </string>  | 
