diff options
| author | Gilbert Gonzales <gilbert@lindenlab.com> | 2012-09-11 17:45:45 -0700 | 
|---|---|---|
| committer | Gilbert Gonzales <gilbert@lindenlab.com> | 2012-09-11 17:45:45 -0700 | 
| commit | 7b78e72bf148d20a402eadb8629bf15dc2f100a3 (patch) | |
| tree | 4209d49b18635a5c58317268965641ce89f69287 | |
| parent | ef39011f433d93ea72cf636d4c415b468f776a01 (diff) | |
| parent | cb8ce1141837cc450756764e03a4564f8ab0c9eb (diff) | |
merging in latest changes
42 files changed, 656 insertions, 374 deletions
| diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 52812dc050..029c47c726 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -627,6 +627,13 @@ void LLFloater::setVisible( BOOL visible )  	storeVisibilityControl();  } + +void LLFloater::setIsSingleInstance(BOOL is_single_instance) +{ +	mSingleInstance = is_single_instance; +} + +  // virtual  void LLFloater::handleVisibilityChange ( BOOL new_visibility )  { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a1cac64a4a..4b738f88ea 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -217,6 +217,7 @@ public:  	/*virtual*/ void setFocus( BOOL b );  	/*virtual*/ void setIsChrome(BOOL is_chrome);  	/*virtual*/ void setRect(const LLRect &rect); +                void setIsSingleInstance(BOOL is_single_instance);  	void 			initFloater(const Params& p); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b98fea7032..593381cb29 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10105,7 +10105,7 @@        <key>Type</key>        <string>U32</string>        <key>Value</key> -      <integer>2</integer> +      <integer>1</integer>      </map>      <key>SortFriendsFirst</key>      <map> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index be6901c36a..bb0dbc7ff0 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1911,7 +1911,8 @@ void LLAgent::startTyping()  	{  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);  	} -	(LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_START, FALSE); +	(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> +			sendChatFromViewer("", CHAT_TYPE_START, FALSE);  }  //----------------------------------------------------------------------------- @@ -1923,7 +1924,8 @@ void LLAgent::stopTyping()  	{  		clearRenderState(AGENT_STATE_TYPING);  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); -		(LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); +		(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> +				sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);  	}  } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index e3d57ab7ae..3636f9e9d2 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -585,7 +585,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)  	mBottomSeparatorPad(p.bottom_separator_pad),  	mTopHeaderPad(p.top_header_pad),  	mBottomHeaderPad(p.bottom_header_pad), -	mIsLastMessageFromLog(false) +	mIsLastMessageFromLog(false), +	mNotifyAboutUnreadMsg(p.notify_unread_msg)  {  	LLTextEditor::Params editor_params(p);  	editor_params.rect = getLocalRect(); @@ -707,7 +708,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	bool from_me = chat.mFromID == gAgent.getID();  	mEditor->setPlainText(use_plain_text_chat_history); -	if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty()) +	if (mNotifyAboutUnreadMsg && !mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty())  	{  		mUnreadChatSources.insert(chat.mFromName);  		mMoreChatPanel->setVisible(TRUE); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 28344e6a10..990c52f31b 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -60,6 +60,8 @@ class LLChatHistory : public LLUICtrl  			Optional<LLTextBox::Params>	more_chat_text; +			Optional<bool>			notify_unread_msg; +  			Params()  			:	message_header("message_header"),  				message_separator("message_separator"), @@ -71,7 +73,8 @@ class LLChatHistory : public LLUICtrl  				bottom_separator_pad("bottom_separator_pad"),  				top_header_pad("top_header_pad"),  				bottom_header_pad("bottom_header_pad"), -				more_chat_text("more_chat_text") +				more_chat_text("more_chat_text"), +				notify_unread_msg("notify_unread_msg", true)  			{}  		}; @@ -122,6 +125,7 @@ class LLChatHistory : public LLUICtrl  		LLUUID mLastFromID;  		LLDate mLastMessageTime;  		bool mIsLastMessageFromLog; +		bool mNotifyAboutUnreadMsg;  		//std::string mLastMessageTimeStr;  		std::string mMessageHeaderFilename; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index e6340e0fa3..f1b5c42ef3 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -323,12 +323,12 @@ BOOL	LLNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)  			return TRUE;  		else  		{ -			LLNearbyChat::instance().showHistory(); +			(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->showHistory();  			return FALSE;  		}  	} -	LLNearbyChat::instance().showHistory(); +	(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->showHistory();  	return LLPanel::handleMouseUp(x,y,mask);  } diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 7db6a93709..239a89015f 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -26,15 +26,18 @@  #include "llviewerprecompiledheaders.h"  #include "llagent.h" +#include "llavatarnamecache.h"  #include "llconversationlog.h"  #include "lltrans.h" +const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec +  struct Conversation_params  {  	Conversation_params(time_t time)  	:	mTime(time),  		mTimestamp(LLConversation::createTimestamp(time)), -		mIsConversationPast(true) +		mIsVoice(false)  	{}  	time_t		mTime; @@ -45,7 +48,6 @@ struct Conversation_params  	LLUUID		mSessionID;  	LLUUID		mParticipantID;  	bool		mIsVoice; -	bool		mIsConversationPast;  	bool		mHasOfflineIMs;  }; @@ -62,7 +64,6 @@ LLConversation::LLConversation(const Conversation_params& params)  	mSessionID(params.mSessionID),  	mParticipantID(params.mParticipantID),  	mIsVoice(params.mIsVoice), -	mIsConversationPast(params.mIsConversationPast),  	mHasOfflineIMs(params.mHasOfflineIMs)  {  	setListenIMFloaterOpened(); @@ -77,7 +78,6 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session)  	mSessionID(session.mSessionID),  	mParticipantID(session.mOtherParticipantID),  	mIsVoice(session.mStartedAsIMCall), -	mIsConversationPast(false),  	mHasOfflineIMs(session.mHasOfflineMessage)  {  	setListenIMFloaterOpened(); @@ -93,7 +93,6 @@ LLConversation::LLConversation(const LLConversation& conversation)  	mSessionID			= conversation.getSessionID();  	mParticipantID		= conversation.getParticipantID();  	mIsVoice			= conversation.isVoice(); -	mIsConversationPast = conversation.isConversationPast();  	mHasOfflineIMs		= conversation.hasOfflineMessages();  	setListenIMFloaterOpened(); @@ -104,12 +103,10 @@ LLConversation::~LLConversation()  	mIMFloaterShowedConnection.disconnect();  } -void LLConversation::setIsVoice(bool is_voice) +void LLConversation::updateTimestamp()  { -	if (mIsConversationPast) -		return; - -	mIsVoice = is_voice; +	mTime = time_corrected(); +	mTimestamp = createTimestamp(mTime);  }  void LLConversation::onIMFloaterShown(const LLUUID& session_id) @@ -138,20 +135,33 @@ const std::string LLConversation::createTimestamp(const time_t& utc_time)  	return timeStr;  } +bool LLConversation::isOlderThan(U32 days) const +{ +	time_t now = time_corrected(); +	U32 age = (U32)((now - mTime) / SEC_PER_DAY); // age of conversation in days + +	return age > days; +} +  void LLConversation::setListenIMFloaterOpened()  {  	LLIMFloater* floater = LLIMFloater::findInstance(mSessionID);  	bool has_offline_ims = !mIsVoice && mHasOfflineIMs; -	bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); +	bool offline_ims_visible = LLIMFloater::isVisible(floater) && floater->hasFocus();  	// we don't need to listen for im floater with this conversation is opened  	// if floater is already opened or this conversation doesn't have unread offline messages -	if (has_offline_ims && !ims_are_read) +	if (has_offline_ims && !offline_ims_visible)  	{  		mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1));  	} +	else +	{ +		mHasOfflineIMs = false; +	}  } +  /************************************************************************/  /*             LLConversationLogFriendObserver implementation           */  /************************************************************************/ @@ -193,6 +203,7 @@ LLConversationLog::LLConversationLog()  		if (ctrl->getValue().asBoolean())  		{  			LLIMMgr::instance().addSessionObserver(this); +			newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1));  		}  	} @@ -206,17 +217,80 @@ void LLConversationLog::observeIMSession()  	if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))  	{  		LLIMMgr::instance().addSessionObserver(this); +		LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1));  	}  	else  	{  		LLIMMgr::instance().removeSessionObserver(this); +		newMessageSignalConnection.disconnect();  	}  } -void LLConversationLog::logConversation(const LLConversation& conversation) +void LLConversationLog::logConversation(const LLUUID& session_id)  { -	mConversations.push_back(conversation); -	notifyObservers(); +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); +	LLConversation* conversation = findConversation(session_id); + +	if (session && conversation) +	{ +		updateConversationTimestamp(conversation); +	} +	else if (session && !conversation) +	{ +		createConversation(session_id); +	} +} + +void LLConversationLog::createConversation(const LLUUID& session_id) +{ +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + +	if (session) +	{ +		LLConversation conversation(*session); +		mConversations.push_back(conversation); + +		if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) +		{ +			LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); +		} + +		notifyObservers(); +	} +} + +void LLConversationLog::updateConversationName(const LLUUID& session_id, const std::string& name) +{ +	LLConversation* conversation = findConversation(session_id); + +	if (conversation) +	{ +		conversation->setConverstionName(name); +		notifyPrticularConversationObservers(session_id, LLConversationLogObserver::CHANGED_NAME); +	} +} + +void LLConversationLog::updateConversationTimestamp(LLConversation* conversation) +{ +	if (conversation) +	{ +		conversation->updateTimestamp(); +		notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); +	} +} + +LLConversation* LLConversationLog::findConversation(const LLUUID& session_id) +{ +	conversations_vec_t::iterator conv_it = mConversations.begin(); +	for(; conv_it != mConversations.end(); ++conv_it) +	{ +		if (conv_it->getSessionID() == session_id) +		{ +			return &*conv_it; +		} +	} + +	return NULL;  }  void LLConversationLog::removeConversation(const LLConversation& conversation) @@ -259,27 +333,7 @@ void LLConversationLog::removeObserver(LLConversationLogObserver* observer)  void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)  { -	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); -	if (session) -	{ -		LLConversation conversation(*session); -		LLConversationLog::instance().logConversation(conversation); -		session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); -	} -} - -void LLConversationLog::sessionRemoved(const LLUUID& session_id) -{ -	conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); - -	for (; rev_iter != mConversations.rend(); ++rev_iter) -	{ -		if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast()) -		{ -			rev_iter->setIsPast(true); -			return; // return here because only one session with session_id may be active -		} -	} +	logConversation(session_id);  }  void LLConversationLog::cache() @@ -385,10 +439,22 @@ bool LLConversationLog::loadFromFile(const std::string& filename)  		params.mHistoryFileName = std::string(history_file_name);  		LLConversation conversation(params); + +		// CHUI-325 +		// The conversation log should be capped to the last 30 days. Conversations with the last utterance +		// being over 30 days old should be purged from the conversation log text file on login. +		if (conversation.isOlderThan(CONVERSATION_LIFETIME)) +		{ +			continue; +		} +  		mConversations.push_back(conversation);  	}  	fclose(fp); +	LLFile::remove(filename); +	cache(); +  	notifyObservers();  	return true;  } @@ -411,17 +477,13 @@ void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& sessi  	}  } -void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state) +void LLConversationLog::onNewMessageReceived(const LLSD& data)  { -	conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); +	const LLUUID session_id = data["session_id"].asUUID(); +	logConversation(session_id); +} -	for (; rev_iter != mConversations.rend(); ++rev_iter) -	{ -		if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast() && LLVoiceChannel::STATE_CALL_STARTED == state) -		{ -			rev_iter->setIsVoice(true); -			notifyPrticularConversationObservers(session_id, LLConversationLogObserver::VOICE_STATE); -			return; // return here because only one session with session_id may be active -		} -	} +void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session) +{ +	updateConversationName(session->mSessionID, av_name.getCompleteName());  } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 9fd54c61c9..ffd27f7e20 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -57,11 +57,17 @@ public:  	const std::string&	getTimestamp()			const	{ return mTimestamp; }  	const time_t&		getTime()				const	{ return mTime; }  	bool				isVoice()				const	{ return mIsVoice; } -	bool				isConversationPast()	const	{ return mIsConversationPast; }  	bool				hasOfflineMessages()	const	{ return mHasOfflineIMs; }  	void	setIsVoice(bool is_voice); -	void	setIsPast (bool is_past) { mIsConversationPast = is_past; } +	void	setConverstionName(std::string conv_name) { mConversationName = conv_name; } + +	bool isOlderThan(U32 days) const; + +	/* +	 * updates last interaction time +	 */ +	void updateTimestamp();  	/*  	 * Resets flag of unread offline message to false when im floater with this conversation is opened. @@ -83,7 +89,7 @@ private:  	boost::signals2::connection mIMFloaterShowedConnection; -	time_t			mTime; // start time of conversation +	time_t			mTime; // last interaction time  	SessionType		mConversationType;  	std::string		mConversationName;  	std::string		mHistoryFileName; @@ -91,8 +97,7 @@ private:  	LLUUID			mParticipantID;  	bool			mIsVoice;  	bool			mHasOfflineIMs; -	bool			mIsConversationPast; // once session is finished conversation became past forever -	std::string		mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm +	std::string		mTimestamp; // last interaction time in form of: mm/dd/yyyy hh:mm  };  /** @@ -109,32 +114,26 @@ class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObse  	friend class LLSingleton<LLConversationLog>;  public: -	/** -	 * adds conversation to the conversation list and notifies observers -	 */ -	void logConversation(const LLConversation& conversation);  	void removeConversation(const LLConversation& conversation);  	/**  	 * Returns first conversation with matched session_id  	 */ -	const LLConversation* getConversation(const LLUUID& session_id); +	const LLConversation*				getConversation(const LLUUID& session_id); +	const std::vector<LLConversation>&	getConversations() { return mConversations; }  	void addObserver(LLConversationLogObserver* observer);  	void removeObserver(LLConversationLogObserver* observer); -	const std::vector<LLConversation>& getConversations() { return mConversations; } -  	// LLIMSessionObserver triggers  	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); -	virtual void sessionRemoved(const LLUUID& session_id); +	virtual void sessionRemoved(const LLUUID& session_id){}											// Stub  	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){};								// Stub  	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){};	// Stub  	void notifyObservers(); -	void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); -	void onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state); +	void onNewMessageReceived(const LLSD& data);  	/**  	 * public method which is called on viewer exit to save conversation log @@ -145,6 +144,13 @@ private:  	LLConversationLog(); +	/** +	 * adds conversation to the conversation list and notifies observers +	 */ +	void logConversation(const LLUUID& session_id); + +	void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); +  	void observeIMSession();  	/** @@ -156,11 +162,21 @@ private:  	bool saveToFile(const std::string& filename);  	bool loadFromFile(const std::string& filename); +	void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session); + +	void createConversation(const LLUUID& session_id); +	void updateConversationTimestamp(LLConversation* conversation); +	void updateConversationName(const LLUUID& session_id, const std::string& name); + +	LLConversation* findConversation(const LLUUID& session_id); +  	typedef std::vector<LLConversation> conversations_vec_t;  	std::vector<LLConversation>				mConversations;  	std::set<LLConversationLogObserver*>	mObservers;  	LLFriendObserver* mFriendObserver;		// Observer of the LLAvatarTracker instance + +	boost::signals2::connection newMessageSignalConnection;  };  class LLConversationLogObserver @@ -169,7 +185,8 @@ public:  	enum EConversationChange  		{ -			VOICE_STATE = 1 +			CHANGED_TIME = 1, // last interaction time changed +			CHANGED_NAME = 2  // conversation name changed  		};  	virtual ~LLConversationLogObserver(){} diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index d39e090c22..429e99f7ad 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -143,22 +143,32 @@ void LLConversationLogList::changed()  void LLConversationLogList::changed(const LLUUID& session_id, U32 mask)  { -	if (mask & LLConversationLogObserver::VOICE_STATE) +	LLConversationLogListItem* item = getConversationLogListItem(session_id); + +	if (!item)  	{ -		std::vector<LLPanel*> panels; -		LLFlatListViewEx::getItems(panels); +		return; +	} -		std::vector<LLPanel*>::iterator iter = panels.begin(); +	if (mask & LLConversationLogObserver::CHANGED_TIME) +	{ +		item->updateTimestamp(); -		for (; iter != panels.end(); ++iter) +		// if list is sorted by date and a date of some item has changed, +		// than the whole list should be rebuilt +		if (E_SORT_BY_DATE == getSortOrder())  		{ -			LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter); - -			if (item && session_id == item->getConversation()->getSessionID() && !item->getConversation()->isConversationPast()) -			{ -				item->initIcons(); -				return; -			} +			mIsDirty = true; +		} +	} +	else if (mask & LLConversationLogObserver::CHANGED_NAME) +	{ +		item->updateName(); +		// if list is sorted by name and a name of some item has changed, +		// than the whole list should be rebuilt +		if (E_SORT_BY_DATE == getSortOrder()) +		{ +			mIsDirty = true;  		}  	}  } @@ -401,6 +411,29 @@ const LLConversation* LLConversationLogList::getSelectedConversation()  	return NULL;  } +LLConversationLogListItem* LLConversationLogList::getConversationLogListItem(const LLUUID& session_id) +{ +	std::vector<LLPanel*> panels; +	LLFlatListViewEx::getItems(panels); +	std::vector<LLPanel*>::iterator iter = panels.begin(); + +	for (; iter != panels.end(); ++iter) +	{ +		LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter); +		if (item && session_id == item->getConversation()->getSessionID()) +		{ +			return item; +		} +	} + +	return NULL; +} + +LLConversationLogList::ESortOrder LLConversationLogList::getSortOrder() +{ +	return static_cast<ESortOrder>(gSavedSettings.getU32("CallLogSortOrder")); +} +  bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const  {  	const LLConversationLogListItem* conversation_item1 = dynamic_cast<const LLConversationLogListItem*>(item1); diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h index 5e7fc0a9fb..62ec57e09e 100644 --- a/indra/newview/llconversationloglist.h +++ b/indra/newview/llconversationloglist.h @@ -43,6 +43,12 @@ class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogOb  {  	LOG_CLASS(LLConversationLogList);  public: + +	typedef enum e_sort_oder{ +		E_SORT_BY_NAME = 0, +		E_SORT_BY_DATE = 1, +	} ESortOrder; +  	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params>  	{  		Params(){}; @@ -90,6 +96,9 @@ private:  	LLIMModel::LLIMSession::SType getSelectedSessionType();  	const LLConversationLogListItem* getSelectedConversationPanel();  	const LLConversation* getSelectedConversation(); +	LLConversationLogListItem* getConversationLogListItem(const LLUUID& session_id); + +	ESortOrder getSortOrder();  	LLHandle<LLToggleableMenu>	mContextMenu;  	bool mIsDirty; diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index dddf216592..fac6130371 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -117,6 +117,16 @@ void LLConversationLogListItem::initIcons()  	}  } +void LLConversationLogListItem::updateTimestamp() +{ +	mConversationDate->setValue(mConversation->getTimestamp()); +} + +void LLConversationLogListItem::updateName() +{ +	mConversationName->setValue(mConversation->getConversationName()); +} +  void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask)  {  	getChildView("hovered_icon")->setVisible(true); diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 2aaafa0fba..1bf7a0ed93 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -64,10 +64,16 @@ public:  	void onDoubleClick(); -	void initIcons(); +	/** +	 * updates string value of last interaction time from conversation +	 */ +	void updateTimestamp(); +	void updateName();  private: +	void initIcons(); +  	const LLConversation* mConversation;  	LLTextBox*		mConversationName; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d7f9093a4a..e810bac1d9 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -36,21 +36,24 @@  LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) :  	LLFolderViewModelItemCommon(root_view_model),  	mName(display_name), -	mUUID(uuid) +	mUUID(uuid), +	mNeedsRefresh(true)  {  }  LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) :  	LLFolderViewModelItemCommon(root_view_model),  	mName(""), -	mUUID(uuid) +	mUUID(uuid), +	mNeedsRefresh(true)  {  }  LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) :  	LLFolderViewModelItemCommon(root_view_model),  	mName(""), -	mUUID() +	mUUID(), +	mNeedsRefresh(true)  {  } @@ -75,14 +78,6 @@ void LLConversationItem::showProperties(void)  {  } -bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const -{ -	// We compare only by name for the moment -	// *TODO : Implement the sorting by date -	S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); -	return (compare < 0); -} -  //  // LLConversationItemSession  //  @@ -102,11 +97,13 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa  {  	addChild(participant);  	mIsLoaded = true; +	mNeedsRefresh = true;  }  void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant)  {  	removeChild(participant); +	mNeedsRefresh = true;  }  void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -122,6 +119,7 @@ void LLConversationItemSession::clearParticipants()  {  	clearChildren();  	mIsLoaded = false; +	mNeedsRefresh = true;  }  LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id) @@ -187,8 +185,42 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid,  {  } +void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) +{ +	mName = av_name.mDisplayName; +	// *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername +	mNeedsRefresh = true; +	if (mParent) +	{ +		mParent->requestSort(); +	} +} +  void LLConversationItemParticipant::dumpDebugData()  {  	llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; -}	 +} + +// +// LLConversationSort +//  + +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ +	// For the moment, we sort only by name +	// *TODO : Implement the sorting by date as well (most recent first) +	// *TODO : Check the type of item (session/participants) as order should be different for both (eventually) +	S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); +	return (compare < 0);	 +} + +// +// LLConversationViewModel +// + +void LLConversationViewModel::sort(LLFolderViewFolder* folder)  +{ +	base_t::sort(folder); +} +  // EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 7baabf7f76..4f13d3d3a1 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -29,6 +29,7 @@  #include "llfolderviewitem.h"  #include "llfolderviewmodel.h" +#include "llavatarname.h"  #include "llviewerfoldertype.h"  // Implementation of conversations list @@ -61,7 +62,7 @@ public:  	virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }  	virtual std::string getLabelSuffix() const { return LLStringUtil::null; }  	virtual BOOL isItemRenameable() const { return TRUE; } -	virtual BOOL renameItem(const std::string& new_name) { mName = new_name; return TRUE; } +	virtual BOOL renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return TRUE; }  	virtual BOOL isItemMovable( void ) const { return FALSE; }  	virtual BOOL isItemRemovable( void ) const { return FALSE; }  	virtual BOOL isItemInTrash( void) const { return FALSE; } @@ -104,9 +105,13 @@ public:  //	bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); }  	bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } +	void resetRefresh() { mNeedsRefresh = false; } +	bool needsRefresh() { return mNeedsRefresh; } +	  protected:  	std::string mName;	// Name of the session or the participant  	LLUUID mUUID;		// UUID of the session or the participant +	bool mNeedsRefresh;	// Flag signaling to the view that something changed for this item  };  class LLConversationItemSession : public LLConversationItem @@ -117,7 +122,7 @@ public:  	virtual ~LLConversationItemSession() {}      LLPointer<LLUIImage> getIcon() const { return NULL; } -	void setSessionID(const LLUUID& session_id) { mUUID = session_id; } +	void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; }  	void addParticipant(LLConversationItemParticipant* participant);  	void removeParticipant(LLConversationItemParticipant* participant);  	void removeParticipant(const LLUUID& participant_id); @@ -144,8 +149,10 @@ public:  	bool isMuted() { return mIsMuted; }  	bool isModerator() {return mIsModerator; } -	void setIsMuted(bool is_muted) { mIsMuted = is_muted; } -	void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } +	void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } +	void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } +	 +	void onAvatarNameCache(const LLAvatarName& av_name);  	void dumpDebugData(); @@ -203,23 +210,14 @@ private:  class LLConversationSort  {  public: -	LLConversationSort(U32 order = 0) -	:	mSortOrder(order), -	mByDate(false), -	mByName(false) -	{ -		mByDate = (order & LLConversationFilter::SO_DATE); -		mByName = (order & LLConversationFilter::SO_NAME); -	} +	LLConversationSort(U32 order = 0) : mSortOrder(order) { } -	bool isByDate() const { return mByDate; } +	bool isByDate() const { return (mSortOrder & LLConversationFilter::SO_DATE); }  	U32 getSortOrder() const { return mSortOrder; }  	bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const;  private:  	U32  mSortOrder; -	bool mByDate; -	bool mByName;  };  class LLConversationViewModel @@ -228,7 +226,7 @@ class LLConversationViewModel  public:  	typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; -	void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort +	void sort(LLFolderViewFolder* folder);  	bool contentsReady() { return true; }	// *TODO : we need to check that participants names are available somewhat  	bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 9c1c9aa225..1d1c774874 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -39,7 +39,7 @@  //  // Implementation of conversations list session widgets  // -  +  LLConversationViewSession::Params::Params() :	 @@ -85,6 +85,36 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)  	}  } +LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id) +{ +	// This is *not* a general tree parsing algorithm. We search only in the mItems list +	// assuming there is no mFolders which makes sense for sessions (sessions don't contain +	// sessions). +	LLConversationViewParticipant* participant = NULL; +	items_t::const_iterator iter; +	for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) +	{ +		participant = dynamic_cast<LLConversationViewParticipant*>(*iter); +		if (participant->hasSameValue(participant_id)) +		{ +			break; +		} +	} +	return (iter == getItemsEnd() ? NULL : participant); +} + +void LLConversationViewSession::refresh() +{ +	// Refresh the session view from its model data +	LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); +	vmi->resetRefresh(); +	 +	// Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() +	 +	// Do the regular upstream refresh +	LLFolderViewFolder::refresh(); +} +  //  // Implementation of conversations list participant (avatar) widgets  // @@ -93,13 +123,15 @@ static LLDefaultChildRegistry::Register<LLConversationViewParticipant> r("conver  LLConversationViewParticipant::Params::Params() :	  container(), +participant_id(),  info_button("info_button"),  output_monitor("output_monitor")  {}  LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): -	LLFolderViewItem(p) -{	 +	LLFolderViewItem(p), +    mUUID(p.participant_id) +{  } @@ -124,6 +156,18 @@ BOOL LLConversationViewParticipant::postBuild()  	return TRUE;  } +void LLConversationViewParticipant::refresh() +{ +	// Refresh the participant view from its model data +	LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); +	vmi->resetRefresh(); +	 +	// Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() +	 +	// Do the regular upstream refresh +	LLFolderViewItem::refresh(); +} +  void LLConversationViewParticipant::onInfoBtnClick()  { @@ -189,3 +233,4 @@ void LLConversationViewParticipant::draw()  }  // EOF + diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 98eb32d44e..a7946f4d06 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -39,6 +39,8 @@  #include "lloutputmonitorctrl.h"  class LLIMFloaterContainer; +class LLConversationViewSession; +class LLConversationViewParticipant;  // Implementation of conversations list session widgets @@ -62,6 +64,9 @@ public:  	virtual ~LLConversationViewSession( void ) { }  	virtual void selectItem();	  	void setVisibleIfDetached(BOOL visible); +	LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); + +	virtual void refresh();  };  // Implementation of conversations list participant (avatar) widgets @@ -76,6 +81,7 @@ public:      struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params>      {          Optional<LLIMFloaterContainer*>			container; +        Optional<LLUUID>	participant_id;  		Optional<LLButton::Params>				info_button;          Optional<LLOutputMonitorCtrl::Params>   output_monitor; @@ -84,9 +90,11 @@ public:      virtual ~LLConversationViewParticipant( void ) { }      virtual void draw(); +    bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } +    virtual void refresh();  protected: -    friend class LLUICtrlFactory; +	friend class LLUICtrlFactory;      LLConversationViewParticipant( const Params& p );  	void initFromParams(const Params& params);  	BOOL postBuild(); @@ -96,8 +104,7 @@ protected:  private:  	LLButton* createProfileButton();  	LLButton * mInfoBtn; -	 - +    LLUUID mUUID;		// UUID of the participant	  };  #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 4375ce5726..7b4c999e52 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -45,11 +45,11 @@ BOOL LLFloaterConversationLog::postBuild()  	switch (gSavedSettings.getU32("CallLogSortOrder"))  	{ -	case E_SORT_BY_NAME: +	case LLConversationLogList::E_SORT_BY_NAME:  		mConversationLogList->sortByName();  		break; -	case E_SORT_BY_DATE: +	case LLConversationLogList::E_SORT_BY_DATE:  		mConversationLogList->sortByDate();  		break;  	} @@ -87,12 +87,12 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata)  	if ("sort_by_name" == command_name)  	{  		mConversationLogList->sortByName(); -		gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); +		gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_NAME);  	}  	else if ("sort_by_date" == command_name)  	{  		mConversationLogList->sortByDate(); -		gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); +		gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_DATE);  	}  	else if ("sort_friends_on_top" == command_name)  	{ @@ -117,11 +117,11 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata)  	if ("sort_by_name" == command_name)  	{ -		return sort_order == E_SORT_BY_NAME; +		return sort_order == LLConversationLogList::E_SORT_BY_NAME;  	}  	else if ("sort_by_date" == command_name)  	{ -		return sort_order == E_SORT_BY_DATE; +		return sort_order == LLConversationLogList::E_SORT_BY_DATE;  	}  	else if ("sort_friends_on_top" == command_name)  	{ diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 7d788c0290..e971330f3d 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -34,11 +34,6 @@ class LLFloaterConversationLog : public LLFloater  {  public: -	typedef enum e_sort_oder{ -		E_SORT_BY_NAME = 0, -		E_SORT_BY_DATE = 1, -	} ESortOrder; -  	LLFloaterConversationLog(const LLSD& key);  	virtual ~LLFloaterConversationLog(){}; diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 7083fb987d..dbcf154ef2 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@  #include "llfloaterconversationpreview.h"  #include "llimview.h"  #include "lllineeditor.h" +#include "llspinctrl.h"  #include "lltrans.h"  LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) @@ -64,11 +65,18 @@ BOOL LLFloaterConversationPreview::postBuild()  	std::string title = getString("Title", args);  	setTitle(title); -	getChild<LLLineEditor>("description")->setValue(name); -  	LLLogChat::loadChatHistory(file, mMessages, true);  	mCurrentPage = mMessages.size() / mPageSize; +	mPageSpinner = getChild<LLSpinCtrl>("history_page_spin"); +	mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); +	mPageSpinner->setMinValue(1); +	mPageSpinner->setMaxValue(mCurrentPage + 1); +	mPageSpinner->set(mCurrentPage + 1); + +	std::string total_page_num = llformat("/ %d", mCurrentPage + 1); +	getChild<LLTextBox>("page_num_label")->setValue(total_page_num); +  	return LLFloater::postBuild();  } @@ -128,6 +136,7 @@ void LLFloaterConversationPreview::showHistory()  void LLFloaterConversationPreview::onMoreHistoryBtnClick()  { +	mCurrentPage = (int)(mPageSpinner->getValueF32());  	if (--mCurrentPage < 0)  	{  		return; diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 2246a44761..0341e5d2a0 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -29,6 +29,8 @@  #include "llchathistory.h"  #include "llfloater.h" +class LLSpinCtrl; +  class LLFloaterConversationPreview : public LLFloater  {  public: @@ -45,6 +47,7 @@ private:  	void onMoreHistoryBtnClick();  	void showHistory(); +	LLSpinCtrl*		mPageSpinner;  	LLChatHistory*	mChatHistory;  	LLUUID			mSessionID;  	int				mCurrentPage; diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index b5b86dadc2..29d7732a68 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -293,6 +293,7 @@ void LLFloaterTranslationSettings::onBtnOK()  	gSavedSettings.setString("TranslationService", getSelectedService());  	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());  	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); -	LLNearbyChat::instance().showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +	(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> +			showTranslationCheckbox(LLTranslate::isTranslationConfigured());  	closeFloater(false);  } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 0377337af6..0996af6125 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -35,6 +35,7 @@  // library  #include "llaudioengine.h"  #include "lldatapacker.h" +#include "llfloaterreg.h"  #include "llinventory.h"  #include "llkeyframemotion.h"  #include "llmultigesture.h" @@ -997,7 +998,8 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)  			const BOOL animate = FALSE; -			LLNearbyChat::instance().sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); +			(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> +					sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);  			gesture->mCurrentStep++;  			break; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 7bb29be27b..216c5bbd70 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -31,6 +31,8 @@  #include "llchatentry.h"  #include "llchathistory.h" +#include "llchiclet.h" +#include "llchicletbar.h"  #include "lldraghandle.h"  #include "llfloaterreg.h"  #include "llimfloater.h" @@ -53,6 +55,8 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id)    , mInputEditorTopPad(0)    , mRefreshTimer(new LLTimer())  { +	mSession = LLIMModel::getInstance()->findIMSession(mSessionID); +  	mCommitCallbackRegistrar.add("IMSession.Menu.Action",  			boost::bind(&LLIMConversation::onIMSessionMenuItemClicked,  this, _2));  	mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", @@ -182,6 +186,84 @@ void LLIMConversation::draw()  	}  } +void LLIMConversation::enableDisableCallBtn() +{ +    getChildView("voice_call_btn")->setEnabled( +    		mSessionID.notNull() +    		&& mSession +    		&& mSession->mSessionInitialized +    		&& LLVoiceClient::getInstance()->voiceEnabled() +    		&& LLVoiceClient::getInstance()->isVoiceWorking() +    		&& mSession->mCallBackEnabled); +} + + +void LLIMConversation::onFocusReceived() +{ +	setBackgroundOpaque(true); + +	if (mSessionID.notNull()) +	{ +		LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); + +		if (getVisible()) +		{ +			// suppress corresponding toast only if this floater is visible and have focus +			LLIMModel::getInstance()->setActiveSessionID(mSessionID); +			LLIMModel::instance().sendNoUnreadMessages(mSessionID); +		} +	} + +	LLTransientDockableFloater::onFocusReceived(); +} + +void LLIMConversation::onFocusLost() +{ +	setBackgroundOpaque(false); +	LLTransientDockableFloater::onFocusLost(); +} + +std::string LLIMConversation::appendTime() +{ +	time_t utc_time; +	utc_time = time_corrected(); +	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" +		+LLTrans::getString("TimeMin")+"]"; + +	LLSD substitution; + +	substitution["datetime"] = (S32) utc_time; +	LLStringUtil::format (timeStr, substitution); + +	return timeStr; +} + +void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) +{ +	LLChat& tmp_chat = const_cast<LLChat&>(chat); + +	if(tmp_chat.mTimeStr.empty()) +		tmp_chat.mTimeStr = appendTime(); + +	if (!chat.mMuted) +	{ +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = +				!mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + +		if (mChatHistory) +		{ +			mChatHistory->appendMessage(chat, chat_args); +		} +	} +} + +  void LLIMConversation::buildParticipantList()  {  	if (mIsNearbyChat) @@ -358,9 +440,10 @@ void LLIMConversation::processChatHistoryStyleUpdate()  		}  	} -	if (LLNearbyChat::instanceExists()) +	LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); +	if (nearby_chat)  	{ -		LLNearbyChat::instance().reloadMessages(); +             nearby_chat->reloadMessages();  	}  } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 26151ad1be..41a76c206e 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -33,6 +33,7 @@  #include "lltransientdockablefloater.h"  #include "llviewercontrol.h"  #include "lleventtimer.h" +#include "llimview.h"  #include "llconversationmodel.h"  class LLPanelChatControlPanel; @@ -87,9 +88,6 @@ protected:  	// refresh a visual state of the Call button  	void updateCallBtnState(bool callIsActive); -	// set the enable/disable state for the Call button -	virtual void enableDisableCallBtn() = 0; -  	void buildParticipantList();  	void onSortMenuItemClicked(const LLSD& userdata); @@ -99,9 +97,23 @@ protected:  	/// Update floater header and toolbar buttons when hosted/torn off state is toggled.  	void updateHeaderAndToolbar(); +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	// process focus events to set a currently active session +	/* virtual */ void onFocusLost(); +	/* virtual */ void onFocusReceived(); + +	// prepare chat's params and out one message to chatHistory +	void appendMessage(const LLChat& chat, const LLSD &args = 0); + +	std::string appendTime(); +  	bool mIsNearbyChat;  	bool mIsP2PChat; +	LLIMModel::LLIMSession* mSession; +  	LLLayoutPanel* mParticipantListPanel;  	LLParticipantList* mParticipantList;  	LLUUID mSessionID; @@ -119,7 +131,6 @@ private:  	/// Refreshes the floater at a constant rate.  	virtual void refresh() = 0; -  	/**  	 * Adjusts chat history height to fit vertically with input chat field  	 * and avoid overlapping, since input chat field can be vertically expanded. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a601561c62..2474fe0891 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -92,24 +92,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  	setDocked(true);  } -void LLIMFloater::onFocusLost() -{ -	LLIMModel::getInstance()->resetActiveSessionID(); -	 -	LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); -} - -void LLIMFloater::onFocusReceived() -{ -	LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); - -	if (getVisible()) -	{ -		// suppress corresponding toast only if this floater is visible and have focus -		LLIMModel::getInstance()->setActiveSessionID(mSessionID); -		LLIMModel::instance().sendNoUnreadMessages(mSessionID); -	} -}  // virtual  void LLIMFloater::refresh() @@ -513,27 +495,6 @@ void LLIMFloater::boundVoiceChannel()  	}  } -void LLIMFloater::enableDisableCallBtn() -{ -	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() -			&& LLVoiceClient::getInstance()->isVoiceWorking(); - -	if (mSession) -	{ -		bool session_initialized = mSession->mSessionInitialized; -		bool callback_enabled = mSession->mCallBackEnabled; - -		BOOL enable_connect = -				session_initialized && voice_enabled && callback_enabled; -		getChildView("voice_call_btn")->setEnabled(enable_connect); -	} -	else -	{ -		getChildView("voice_call_btn")->setEnabled(false); -	} -} - -  void LLIMFloater::onCallButtonClicked()  {  	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); @@ -887,25 +848,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  	}  } -void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) -{ -	LLChat& tmp_chat = const_cast<LLChat&>(chat); - -	if (!chat.mMuted) -	{ -		tmp_chat.mFromName = chat.mFromName; -		LLSD chat_args; -		if (args) chat_args = args; -		chat_args["use_plain_text_chat_history"] = -				gSavedSettings.getBOOL("PlainTextChatHistory"); -		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); -		chat_args["show_names_for_p2p_conv"] = !mIsP2PChat -				|| gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - -		mChatHistory->appendMessage(chat, chat_args); -	} -} -  void LLIMFloater::updateMessages()  {  	std::list<LLSD> messages; diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 24a8f17feb..e4a67a3d56 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -134,10 +134,6 @@ public:  private: -	// process focus events to set a currently active session -	/* virtual */ void onFocusLost(); -	/* virtual */ void onFocusReceived(); -  	/*virtual*/ void refresh();  	/*virtual*/ void onClickCloseBtn(); @@ -156,7 +152,6 @@ private:  	BOOL isInviteAllowed() const;  	BOOL inviteToSession(const uuid_vec_t& agent_ids); -	void appendMessage(const LLChat& chat, const LLSD &args = 0);  	static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata );  	static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);  	static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); @@ -169,9 +164,6 @@ private:  	void onCallButtonClicked(); -	// set the enable/disable state for the Call button -	virtual void enableDisableCallBtn(); -  	void boundVoiceChannel();  	// Add the "User is typing..." indicator. @@ -184,8 +176,6 @@ private:  	static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); - -	LLIMModel::LLIMSession* mSession;  	S32 mLastMessageIndex;  	EInstantMessage mDialog; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9758f5a93e..faca92e662 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -45,6 +45,7 @@  #include "lltransientfloatermgr.h"  #include "llviewercontrol.h"  #include "llconversationview.h" +#include "llcallbacklist.h"  //  // LLIMFloaterContainer @@ -52,7 +53,8 @@  LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)  :	LLMultiFloater(seed),  	mExpandCollapseBtn(NULL), -	mConversationsRoot(NULL) +	mConversationsRoot(NULL), +	mInitialized(false)  {  	mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction,  this, _2)); @@ -65,6 +67,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)  LLIMFloaterContainer::~LLIMFloaterContainer()  { +	gIdleCallbacks.deleteFunction(idle, this); +  	mNewMessageConnection.disconnect();  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); @@ -139,6 +143,20 @@ BOOL LLIMFloaterContainer::postBuild()  	LLAvatarNameCache::addUseDisplayNamesCallback(  			boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); +	if (! mMessagesPane->isCollapsed()) +	{ +		S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); +		LLRect list_size = mConversationsPane->getRect(); +        S32 left_pad = mConversationsListPanel->getRect().mLeft; +		list_size.mRight = list_size.mLeft + list_width - left_pad; + +        mConversationsPane->handleReshape(list_size, TRUE); +	} +	mInitialized = true; + +	// Add callback: we'll take care of view updates on idle +	gIdleCallbacks.addFunction(idle, this); +  	return TRUE;  } @@ -290,8 +308,70 @@ void LLIMFloaterContainer::setMinimized(BOOL b)  	}  } +//static +void LLIMFloaterContainer::idle(void* user_data) +{ +	LLIMFloaterContainer* panel = (LLIMFloaterContainer*)user_data; +	panel->mConversationsRoot->update(); +} +  void LLIMFloaterContainer::draw()  { +	// CHUI Notes +	// Currently, the model is not responsible for creating the view which is a good thing. This means that +	// the model could change substantially and the view could decide to echo only a portion of this model. +	// Consequently, the participant views need to be created either by the session view or by the container panel. +	// For the moment, we create them here (which makes for complicated code...) to conform to the pattern +	// implemented in llinventorypanel.cpp (see LLInventoryPanel::buildNewViews()). +	// The best however would be to have an observer on the model so that we would not pool on each draw to know +	// if the view needs refresh. The current implementation (testing for change on draw) is less +	// efficient perf wise than a listener/observer scheme. We will implement that shortly. +	 +	// On each session in mConversationsItems +	for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) +	{ +		// Get the current session descriptors +		LLConversationItem* session_model = it_session->second; +		LLUUID session_id = it_session->first; +		LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); +		// If the session model has been changed, refresh the corresponding view +		if (session_model->needsRefresh()) +		{ +			session_view->refresh(); +		} +		// Iterate through each model participant child +		LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); +		LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); +		while (current_participant_model != end_participant_model) +		{ +			LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); +			LLUUID participant_id = participant_model->getUUID(); +			LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); +			// Is there a corresponding view? If not create it +			if (!participant_view) +			{ +				participant_view = createConversationViewParticipant(participant_model); +				participant_view->addToFolder(session_view); +				mConversationsListPanel->addChild(participant_view); +				participant_view->setVisible(TRUE); +			} +			else +			// Else, see if it needs refresh +			{ +				if (participant_model->needsRefresh()) +				{ +					participant_view->refresh(); +				} +			} +			// Reset the need for refresh +			session_model->resetRefresh(); +			// Next participant +			current_participant_model++; +		} +	} +	 +	repositioningWidgets(); +  	if (mTabContainer->getTabCount() == 0)  	{  		// Do not close the container when every conversation is torn off because the user @@ -299,8 +379,6 @@ void LLIMFloaterContainer::draw()  		collapseMessagesPane(true);  	}  	LLFloater::draw(); - -	repositioningWidgets();  }  void LLIMFloaterContainer::tabClose() @@ -461,6 +539,16 @@ void LLIMFloaterContainer::onCustomAction(const LLSD& userdata)  void LLIMFloaterContainer::repositioningWidgets()  { +	if (!mInitialized) +	{ +		return; +	} + +	if (!mConversationsPane->isCollapsed()) +	{ +		S32 list_width = (mConversationsPane->getRect()).getWidth(); +		gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", list_width); +	}  	LLRect panel_rect = mConversationsListPanel->getRect();  	S32 item_height = 16;  	int index = 0; @@ -499,7 +587,6 @@ void LLIMFloaterContainer::repositioningWidgets()  	}  } -// CHUI-137 : Temporary implementation of conversations list  void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)  {  	bool is_nearby_chat = uuid.isNull(); @@ -527,7 +614,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)  	}  	if (!item)  	{ -		llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; +		llwarns << "Couldn't create conversation session item : " << display_name << llendl;  		return;  	}  	// *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat? @@ -550,7 +637,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)  	// Note: usually, we do not get an updated avatar list at that point  	LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin();  	LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); -	llinfos << "Merov debug : create participant, children size = " << item->getChildrenCount() << llendl;  	while (current_participant_model != end_participant_model)  	{  		LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); @@ -560,24 +646,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)  		participant_view->setVisible(TRUE);  		current_participant_model++;  	} -	// Debugging hack : uncomment to force the creation of a dummy participant  -	// This hack is to be eventually deleted -	if (item->getChildrenCount() == 0) -	{ -		llinfos << "Merov debug : create dummy participant" << llendl; -		// Create a dummy participant : we let that leak but that's just for debugging... -		std::string name("Debug Test : "); -		name += display_name; -		LLUUID test_id; -		test_id.generate(name); -		LLConversationItemParticipant* participant_model = new LLConversationItemParticipant(name, test_id, getRootViewModel()); -		// Create the dummy widget -		LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); -		participant_view->addToFolder(widget); -		mConversationsListPanel->addChild(participant_view); -		participant_view->setVisible(TRUE); -	} -	// End debugging hack  	repositioningWidgets(); @@ -644,7 +712,7 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti  	params.listener = item;  	params.rect = LLRect (0, 0, 0, 0);  	params.tool_tip = params.name; -	params.container = this; +	params.participant_id = item->getUUID();  	return LLUICtrlFactory::create<LLConversationViewParticipant>(params);  } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a72a3e2221..324adfcc11 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -75,6 +75,8 @@ public:  	void collapseMessagesPane(bool collapse); +	// Callbacks +	static void idle(void* user_data);  	// LLIMSessionObserver observe triggers  	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); @@ -110,6 +112,8 @@ private:  	LLLayoutPanel* mConversationsPane;  	LLLayoutStack* mConversationsStack; +	bool mInitialized; +  	// Conversation list implementation  public:  	void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index effcc9a826..f5392b442a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2486,9 +2486,11 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  		LLChat chat(message);  		chat.mSourceType = CHAT_SOURCE_SYSTEM; -		if (LLNearbyChat::instanceExists()) + +		LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); +		if (nearby_chat)  		{ -			LLNearbyChat::instance().addMessage(chat); +			nearby_chat->addMessage(chat);  		}  	}  	else // going to IM session diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index f1518fe825..ddd271e23f 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -69,7 +69,7 @@  S32 LLNearbyChat::sLastSpecialChatChannel = 0; -// --- 2 functions in the global namespace :( --- +// --- function in the global namespace :( ---  bool isWordsName(const std::string& name)  {  	// checking to see if it's display name plus username in parentheses @@ -89,22 +89,6 @@ bool isWordsName(const std::string& name)  	}  } -std::string appendTime() -{ -	time_t utc_time; -	utc_time = time_corrected(); -	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" -		+LLTrans::getString("TimeMin")+"]"; - -	LLSD substitution; - -	substitution["datetime"] = (S32) utc_time; -	LLStringUtil::format (timeStr, substitution); - -	return timeStr; -} - -  const S32 EXPANDED_HEIGHT = 266;  const S32 COLLAPSED_HEIGHT = 60;  const S32 EXPANDED_MIN_HEIGHT = 150; @@ -129,11 +113,14 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd)  	mSpeakerMgr(NULL),  	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)  { +    mIsP2PChat = false;  	mIsNearbyChat = true;  	setIsChrome(TRUE);  	mKey = LLSD();  	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); +	mSessionID = LLUUID();  	setName("nearby_chat"); +	setIsSingleInstance(TRUE);  }  //virtual @@ -215,21 +202,6 @@ bool	LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)  	return false;  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() -{ -	setBackgroundOpaque(true); -	LLIMConversation::onFocusReceived(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() -{ -	setBackgroundOpaque(false); -	LLIMConversation::onFocusLost(); -}  BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)  { @@ -325,13 +297,6 @@ void	LLNearbyChat::setVisible(BOOL visible)  } -void LLNearbyChat::enableDisableCallBtn() -{ -	// bool btn_enabled = LLAgent::isActionAllowed("speak"); - -	getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); -} -  void LLNearbyChat::onTearOffClicked()  {  	LLIMConversation::onTearOffClicked(); @@ -624,31 +589,6 @@ void LLNearbyChat::sendChat( EChatType type )  	}  } - -void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) -{ -	LLChat& tmp_chat = const_cast<LLChat&>(chat); - -	if(tmp_chat.mTimeStr.empty()) -		tmp_chat.mTimeStr = appendTime(); - -	if (!chat.mMuted) -	{ -		tmp_chat.mFromName = chat.mFromName; -		LLSD chat_args; -		if (args) chat_args = args; -		chat_args["use_plain_text_chat_history"] = -				gSavedSettings.getBOOL("PlainTextChatHistory"); -		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); -		chat_args["show_names_for_p2p_conv"] = true; - -		if (mChatHistory) -		{ -			mChatHistory->appendMessage(chat, chat_args); -		} -	} -} -  void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)  {  	appendMessage(chat, args); @@ -780,20 +720,21 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO  // static   void LLNearbyChat::startChat(const char* line)  { -	if (LLNearbyChat::instanceExists()) +	LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); +	if (nearby_chat)  	{ -		(LLNearbyChat::instance()).show(); -		(LLNearbyChat::instance()).setVisible(TRUE); -		(LLNearbyChat::instance()).setFocus(TRUE); -		(LLNearbyChat::instance().mInputEditor)->setFocus(TRUE); +		nearby_chat->show(); +		nearby_chat->setVisible(TRUE); +		nearby_chat->setFocus(TRUE); +		nearby_chat->mInputEditor->setFocus(TRUE);  		if (line)  		{  			std::string line_string(line); -			(LLNearbyChat::instance().mInputEditor)->setText(line_string); +			nearby_chat->mInputEditor->setText(line_string);  		} -		(LLNearbyChat::instance().mInputEditor)->endOfDoc(); +		nearby_chat->mInputEditor->endOfDoc();  	}  } @@ -801,9 +742,10 @@ void LLNearbyChat::startChat(const char* line)  // static  void LLNearbyChat::stopChat()  { -	if (LLNearbyChat::instanceExists()) +	LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); +	if (nearby_chat)  	{ -		(LLNearbyChat::instance().mInputEditor)->setFocus(FALSE); +		nearby_chat->mInputEditor->setFocus(FALSE);  	    gAgent.stopTyping();  	}  } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 379bfbee4b..2cbafbfa62 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -35,15 +35,13 @@  #include "lloutputmonitorctrl.h"  #include "llspeakers.h"  #include "llscrollbar.h" -#include "llsingleton.h"  #include "llviewerchat.h"  #include "llpanel.h"  class LLResizeBar;  class LLNearbyChat -	:	public LLIMConversation, -	 	public LLSingleton<LLNearbyChat> +	:	public LLIMConversation  {  public:  	// constructor for inline chat-bars (e.g. hosted in chat history window) @@ -53,10 +51,6 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); -	// focus overrides -	/*virtual*/ void	onFocusLost(); -	/*virtual*/ void	onFocusReceived(); -  	/*virtual*/ void	setVisible(BOOL visible);  	void loadHistory(); @@ -104,9 +98,6 @@ protected:  	void displaySpeakingIndicator(); -	// set the enable/disable state for the Call button -	virtual void enableDisableCallBtn(); -  	// Which non-zero channel did we last chat on?  	static S32 sLastSpecialChatChannel; @@ -117,8 +108,6 @@ protected:  private: -	// prepare chat's params and out one message to chatHistory -	void appendMessage(const LLChat& chat, const LLSD &args = 0);  	void	onNearbySpeakers	();  	/*virtual*/ void refresh(); diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 37f4cc4c19..f3e17ea61b 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -487,6 +487,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	if(chat_msg.mText.empty())  		return;//don't process empty messages +	LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); +  	// Build notification data   	LLSD chat;  	chat["message"] = chat_msg.mText; @@ -537,7 +539,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  		}  	} -	LLNearbyChat::instance().addMessage(chat_msg, true, args); +	nearby_chat->addMessage(chat_msg, true, args);  	if(chat_msg.mSourceType == CHAT_SOURCE_AGENT   		&& chat_msg.mFromID.notNull()  @@ -553,7 +555,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	// Send event on to LLEventStream  	sChatWatcher->post(chat); -	if( LLNearbyChat::instance().isInVisibleChain() +	if( nearby_chat->isInVisibleChain()  		|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT  			&& gSavedSettings.getBOOL("UseChatBubbles") )  		|| mChannel.isDead() diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index db8e917435..9fd73746e8 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -181,13 +181,14 @@ void LLHandlerUtil::logGroupNoticeToIMGroup(  // static  void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type)  { -	if (LLNearbyChat::instanceExists()) +    LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); +	if (nearby_chat)  	{  		LLChat chat_msg(notification->getMessage());  		chat_msg.mSourceType = type;  		chat_msg.mFromName = SYSTEM_FROM;  		chat_msg.mFromID = LLUUID::null; -		LLNearbyChat::instance().addMessage(chat_msg); +		nearby_chat->addMessage(chat_msg);  	}  } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 67fc9b27dc..a293e6acb6 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -85,7 +85,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)  		LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM);  		// don't show toast if Nearby Chat is opened -		if (LLNearbyChat::instance().isChatVisible()) +		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); +		if (nearby_chat->isChatVisible())  		{  			return false;  		} diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index fa3432fc89..0d1a37c835 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -652,6 +652,8 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)  		LLAvatarName avatar_name;  		bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name);  		participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); +		// Binds avatar's name update callback +		LLAvatarNameCache::get(avatar_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant, _2));  		if (mAvatarList)  		{  			mAvatarList->getIDs().push_back(avatar_id); @@ -670,14 +672,9 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)  		mAvalineUpdater->watchAvalineCaller(avatar_id);  	} -	// *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. -	// For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) -  	// *TODO : Merov : need to update the online/offline status of the participant.  	// Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) -	llinfos << "Merov debug : added participant, name = " << participant->getName() << llendl; -	  	// Add the participant model to the session's children list  	addParticipant(participant); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a2dea31d9b..71608b5280 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -33,6 +33,7 @@  #include "llviewerinventory.h"  #include "sound_ids.h"		// for testing +#include "llfloaterreg.h"  #include "llkeyboard.h"		// for key shortcuts for testing  #include "llinventorymodel.h"  #include "llvoavatar.h" @@ -130,7 +131,8 @@ void LLViewerGesture::doTrigger( BOOL send_chat )  	{  		// Don't play nodding animation, since that might not blend  		// with the gesture animation. -		LLNearbyChat::instance().sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); +		(LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> +				sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);  	}  } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 7105720eb4..f8e988bc0c 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -27,6 +27,7 @@  #include "llviewerprecompiledheaders.h"  #include "llappviewer.h" +#include "llfloaterreg.h"  #include "llviewerkeyboard.h"  #include "llmath.h"  #include "llagent.h" @@ -543,7 +544,7 @@ void start_gesture( EKeystate s )  	if (KEYSTATE_UP == s &&  		! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))  	{ - 		if (LLNearbyChat::instance().getCurrentChat().empty()) + 		if ((LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->getCurrentChat().empty())   		{   			// No existing chat in chat editor, insert '/'   			LLNearbyChat::startChat("/"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9abd269f0f..81cbc3b6c3 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2297,9 +2297,10 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m  	// Treat like a system message and put in chat history.  	chat.mText = av_name.getCompleteName() + ": " + message; -	if (LLNearbyChat::instanceExists()) +	LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); +	if (nearby_chat)  	{ -		LLNearbyChat::instance().addMessage(chat); +		nearby_chat->addMessage(chat);  	}  } @@ -2895,7 +2896,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			// Note: lie to Nearby Chat, pretending that this is NOT an IM, because  			// IMs from obejcts don't open IM sessions. -			if(!chat_from_system && LLNearbyChat::instanceExists()) +			LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); +			if(!chat_from_system && nearby_chat)  			{  				chat.mOwnerID = from_id;  				LLSD args; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 23d2b1633d..403288b2fd 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2493,12 +2493,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		return TRUE;  	} +	LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); +  	// Traverses up the hierarchy  	if( keyboard_focus )  	{ -		if (LLNearbyChat::instanceExists()) +		if (nearby_chat)  		{ -			LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); +			LLChatEntry* chat_editor = nearby_chat->getChatBox();  			// arrow keys move avatar while chatting hack  			if (chat_editor && chat_editor->hasFocus()) @@ -2559,14 +2561,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook,   	// no view has keyboard focus, this is a printable character key (and no modifier key is   	// pressed except shift), then give focus to nearby chat (STORM-560) -	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&  +	if ( nearby_chat && gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&  		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )  	{ -		LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); +		LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")->getChatBox();  		if (chat_editor)  		{  			// passing NULL here, character will be added later when it is handled by character handler. -			LLNearbyChat::instance().startChat(NULL); +			nearby_chat->startChat(NULL);  			return TRUE;  		}  	} diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index c837a0ee57..825a88e4e1 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -14,50 +14,49 @@       name="Title">          CONVERSATION: [NAME]      </floater.string> -    <text -     type="string" -     length="1" -     follows="left|top" -     font="SansSerif" -     height="19" -     layout="topleft" -     left="10" -     name="desc txt" -     top="22" -     width="90"> -        Description: -    </text> -    <line_editor -     border_style="line" -     border_thickness="1" -     enabled="false" -     follows="left|top|right" -     font="SansSerif" -     height="22" -     layout="topleft" -     left_pad="0" -     max_length_bytes="127" -     name="description" -     width="296" />      <chat_history       font="SansSerifSmall"       follows="all"       visible="true" -     height="310" +     height="330"       name="chat_history" +     notify_unread_msg="false"       parse_highlights="true"       parse_urls="true"       left="5" +     top_pad="25"       width="390">      </chat_history> -    <button +    <text       follows="bottom|right" +     font="SansSerif"       height="22"       layout="topleft" -     name="more_history" -     label="More history..." -     right="-15" -     top_pad="5" -     width="100"> -    </button> +     name="page_label" +     right="-110" +     top_pad="7" +     value="Page" +     width="35"> +    </text> +    <spinner +     decimal_digits="0" +     follows="bottom|right" +     height="23" +     increment="1" +     label_width="40" +     layout="topleft" +     left_pad="0" +     name="history_page_spin" +     top_delta="-3" +     width="50"/> +    <text +     follows="bottom|right" +     font="SandSerif" +     height="22" +     layout="topleft" +     name="page_num_label" +     left_pad="5" +     top_delta="4" +     width="40"> +    </text>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e439fc9005..1583add857 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -36,7 +36,7 @@           name="conversations_layout_panel"           min_dim="38"           width="268" -         expanded_min_dim="120"> +         expanded_min_dim="165">              <layout_stack               animate="false"                follows="left|top|right" @@ -113,7 +113,7 @@           height="430"           name="messages_layout_panel"           width="412" -         expanded_min_dim="205"> +         expanded_min_dim="225">              <panel_container               follows="all"               height="430" | 
