summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilbert Gonzales <gilbert@lindenlab.com>2012-09-11 17:45:45 -0700
committerGilbert Gonzales <gilbert@lindenlab.com>2012-09-11 17:45:45 -0700
commit7b78e72bf148d20a402eadb8629bf15dc2f100a3 (patch)
tree4209d49b18635a5c58317268965641ce89f69287
parentef39011f433d93ea72cf636d4c415b468f776a01 (diff)
parentcb8ce1141837cc450756764e03a4564f8ab0c9eb (diff)
merging in latest changes
-rw-r--r--indra/llui/llfloater.cpp7
-rw-r--r--indra/llui/llfloater.h1
-rw-r--r--indra/newview/app_settings/settings.xml2
-rwxr-xr-xindra/newview/llagent.cpp6
-rw-r--r--indra/newview/llchathistory.cpp5
-rw-r--r--indra/newview/llchathistory.h6
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp4
-rw-r--r--indra/newview/llconversationlog.cpp156
-rw-r--r--indra/newview/llconversationlog.h49
-rw-r--r--indra/newview/llconversationloglist.cpp57
-rw-r--r--indra/newview/llconversationloglist.h9
-rw-r--r--indra/newview/llconversationloglistitem.cpp10
-rw-r--r--indra/newview/llconversationloglistitem.h8
-rw-r--r--indra/newview/llconversationmodel.cpp56
-rwxr-xr-xindra/newview/llconversationmodel.h30
-rwxr-xr-xindra/newview/llconversationview.cpp51
-rwxr-xr-xindra/newview/llconversationview.h13
-rw-r--r--indra/newview/llfloaterconversationlog.cpp12
-rw-r--r--indra/newview/llfloaterconversationlog.h5
-rw-r--r--indra/newview/llfloaterconversationpreview.cpp13
-rw-r--r--indra/newview/llfloaterconversationpreview.h3
-rw-r--r--indra/newview/llfloatertranslationsettings.cpp3
-rw-r--r--indra/newview/llgesturemgr.cpp4
-rw-r--r--indra/newview/llimconversation.cpp87
-rw-r--r--indra/newview/llimconversation.h19
-rw-r--r--indra/newview/llimfloater.cpp58
-rw-r--r--indra/newview/llimfloater.h10
-rwxr-xr-xindra/newview/llimfloatercontainer.cpp118
-rw-r--r--indra/newview/llimfloatercontainer.h4
-rw-r--r--indra/newview/llimview.cpp6
-rw-r--r--indra/newview/llnearbychat.cpp88
-rw-r--r--indra/newview/llnearbychat.h13
-rw-r--r--indra/newview/llnearbychathandler.cpp6
-rw-r--r--indra/newview/llnotificationhandlerutil.cpp5
-rw-r--r--indra/newview/llnotificationtiphandler.cpp3
-rw-r--r--indra/newview/llparticipantlist.cpp7
-rw-r--r--indra/newview/llviewergesture.cpp4
-rw-r--r--indra/newview/llviewerkeyboard.cpp3
-rwxr-xr-xindra/newview/llviewermessage.cpp8
-rwxr-xr-xindra/newview/llviewerwindow.cpp12
-rw-r--r--indra/newview/skins/default/xui/en/floater_conversation_preview.xml65
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml4
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"