summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindra/newview/llavataractions.cpp35
-rw-r--r--indra/newview/llavataractions.h9
-rw-r--r--indra/newview/llimconversation.cpp34
-rw-r--r--indra/newview/llimconversation.h10
-rw-r--r--indra/newview/llimfloater.cpp93
-rw-r--r--indra/newview/llimfloater.h9
-rw-r--r--indra/newview/llnearbychat.cpp36
-rw-r--r--indra/newview/llnearbychat.h6
-rw-r--r--indra/newview/llparticipantlist.cpp1
9 files changed, 151 insertions, 82 deletions
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index c9031dd26a..21367c224d 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -529,23 +529,6 @@ namespace action_give_inventory
return acceptable;
}
- static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string)
- {
- llassert(avatar_names.size() > 0);
-
- const std::string& separator = LLTrans::getString("words_separator");
- for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
- {
- LLAvatarName av_name = *it;
- residents_string.append(av_name.mDisplayName);
- if (++it == avatar_names.end())
- {
- break;
- }
- residents_string.append(separator);
- }
- }
-
static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
{
llassert(inventory_selected_uuids.size() > 0);
@@ -675,7 +658,7 @@ namespace action_give_inventory
}
std::string residents;
- build_residents_string(avatar_names, residents);
+ LLAvatarActions::buildResidentsString(avatar_names, residents);
std::string items;
build_items_string(inventory_selected_uuids, items);
@@ -706,7 +689,23 @@ namespace action_give_inventory
}
}
+// static
+void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string)
+{
+ llassert(avatar_names.size() > 0);
+ const std::string& separator = LLTrans::getString("words_separator");
+ for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
+ {
+ LLAvatarName av_name = *it;
+ residents_string.append(av_name.mDisplayName);
+ if (++it == avatar_names.end())
+ {
+ break;
+ }
+ residents_string.append(separator);
+ }
+}
//static
std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 0a69ad86a3..46830eb22c 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -34,6 +34,7 @@
#include <string>
#include <vector>
+class LLAvatarName;
class LLInventoryPanel;
class LLFloater;
@@ -208,6 +209,14 @@ public:
*/
static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
+ /**
+ * Builds a string of residents' display names separated by "words_separator" string.
+ *
+ * @param avatar_names - a vector of given avatar names from which resulting string is built
+ * @param residents_string - the resulting string
+ */
+ static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string);
+
static std::set<LLUUID> getInventorySelectedUUIDs();
private:
diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp
index d3f3e41a29..c734c3edd2 100644
--- a/indra/newview/llimconversation.cpp
+++ b/indra/newview/llimconversation.cpp
@@ -42,7 +42,6 @@ const F32 REFRESH_INTERVAL = 0.2f;
LLIMConversation::LLIMConversation(const LLUUID& session_id)
: LLTransientDockableFloater(NULL, true, session_id)
- , LLEventTimer(REFRESH_INTERVAL)
, mIsP2PChat(false)
, mExpandCollapseBtn(NULL)
, mTearOffBtn(NULL)
@@ -52,6 +51,7 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id)
, mChatHistory(NULL)
, mInputEditor(NULL)
, mInputEditorTopPad(0)
+ , mRefreshTimer(new LLTimer())
{
mCommitCallbackRegistrar.add("IMSession.Menu.Action",
boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2));
@@ -67,6 +67,10 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id)
boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck, this, _2));
mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable",
boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2));
+
+ // Zero expiry time is set only once to allow initial update.
+ mRefreshTimer->setTimerExpirySec(0);
+ mRefreshTimer->start();
}
LLIMConversation::~LLIMConversation()
@@ -76,6 +80,8 @@ LLIMConversation::~LLIMConversation()
delete mParticipantList;
mParticipantList = NULL;
}
+
+ delete mRefreshTimer;
}
BOOL LLIMConversation::postBuild()
@@ -120,19 +126,22 @@ BOOL LLIMConversation::postBuild()
}
-BOOL LLIMConversation::tick()
+void LLIMConversation::draw()
{
- // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater
- // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy().
- if (isDead()) return false;
+ LLTransientDockableFloater::draw();
- // Need to resort the participant list if it's in sort by recent speaker order.
- if (mParticipantList)
+ if (mRefreshTimer->hasExpired())
{
- mParticipantList->update();
- }
+ if (mParticipantList)
+ {
+ mParticipantList->update();
+ }
- return false;
+ refresh();
+
+ // Restart the refresh timer
+ mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);
+ }
}
void LLIMConversation::buildParticipantList()
@@ -144,10 +153,11 @@ void LLIMConversation::buildParticipantList()
}
else
{
+ LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
// for group and ad-hoc chat we need to include agent into list
- if(!mIsP2PChat && !mParticipantList && mSessionID.notNull())
+ if(!mIsP2PChat && mSessionID.notNull() && speaker_manager)
{
- LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ delete mParticipantList; // remove the old list and create a new one if the session id has changed
mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false);
}
}
diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h
index 47c98d6f8b..50663137ac 100644
--- a/indra/newview/llimconversation.h
+++ b/indra/newview/llimconversation.h
@@ -40,7 +40,6 @@ class LLChatHistory;
class LLIMConversation
: public LLTransientDockableFloater
- , public LLEventTimer
{
public:
@@ -65,6 +64,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
protected:
@@ -89,8 +89,6 @@ protected:
void buildParticipantList();
void onSortMenuItemClicked(const LLSD& userdata);
- /*virtual*/ BOOL tick();
-
bool mIsNearbyChat;
bool mIsP2PChat;
@@ -103,6 +101,9 @@ protected:
LLButton* mCloseBtn;
private:
+ /// Refreshes the floater at a constant rate.
+ virtual void refresh() = 0;
+
/// Update floater header and toolbar buttons when hosted/torn off state is toggled.
void updateHeaderAndToolbar();
@@ -113,10 +114,11 @@ private:
*/
void reshapeChatHistory();
-
LLChatHistory* mChatHistory;
LLChatEntry* mInputEditor;
int mInputEditorTopPad; // padding between input field and chat history
+
+ LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called.
};
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 9ea4bec069..6a5bf153d4 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -105,6 +105,18 @@ void LLIMFloater::onFocusReceived()
}
}
+// virtual
+void LLIMFloater::refresh()
+{
+ if (mMeTyping)
+ {
+ // Time out if user hasn't typed for a while.
+ if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS)
+ {
+ setTyping(false);
+ }
+ }
+}
/* static */
void LLIMFloater::newIMCallback(const LLSD& data)
@@ -188,6 +200,7 @@ void LLIMFloater::sendMsg()
LLIMFloater::~LLIMFloater()
{
+ mParticipantsListRefreshConnection.disconnect();
mVoiceChannelStateChangeConnection.disconnect();
if(LLVoiceClient::instanceExists())
{
@@ -225,6 +238,8 @@ void LLIMFloater::initIMFloater()
boundVoiceChannel();
+ mTypingStart = LLTrans::getString("IM_typing_start_string");
+
// Show control panel in torn off floaters only.
mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel"));
@@ -246,6 +261,20 @@ void LLIMFloater::initIMFloater()
{
std::string session_name(LLIMModel::instance().getName(mSessionID));
updateSessionName(session_name, session_name);
+
+ // For ad hoc conferences we should update the title with participants names.
+ if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID))
+ || mDialog == IM_SESSION_CONFERENCE_START)
+ {
+ if (mParticipantsListRefreshConnection.connected())
+ {
+ mParticipantsListRefreshConnection.disconnect();
+ }
+
+ LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list");
+ mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback(
+ boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1));
+ }
}
}
@@ -273,8 +302,6 @@ BOOL LLIMFloater::postBuild()
setDocked(true);
- mTypingStart = LLTrans::getString("IM_typing_start_string");
-
LLButton* add_btn = getChild<LLButton>("add_btn");
// Allow to add chat participants depending on the session type
@@ -341,7 +368,9 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids)
for (uuid_vec_t::const_iterator id = uuids.begin();
id != uuids.end(); ++id)
{
- if (*id == mOtherParticipantUUID)
+ // Skip this check for ad hoc conferences,
+ // conference participants should be listed in mSession->mInitialTargetIDs.
+ if (mIsP2PChat && *id == mOtherParticipantUUID)
{
return false;
}
@@ -411,11 +440,6 @@ void LLIMFloater::onCallButtonClicked()
}
}
-/*void LLIMFloater::onOpenVoiceControlsClicked()
-{
- LLFloaterReg::showInstance("voice_controls");
-}*/
-
void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL)
@@ -448,28 +472,55 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
mTypingStart.setArg("[NAME]", ui_title);
}
-// virtual
-BOOL LLIMFloater::tick()
+void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)
{
- // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater
- // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy().
- if (isDead())
+ LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl);
+ if (!avatar_list)
{
- return false;
+ return;
}
- BOOL parents_retcode = LLIMConversation::tick();
+ bool all_names_resolved = true;
+ std::vector<LLSD> participants_uuids;
- if ( mMeTyping )
+ avatar_list->getValues(participants_uuids);
+
+ // Check whether we have all participants names in LLAvatarNameCache
+ for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it)
{
- // Time out if user hasn't typed for a while.
- if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+ const LLUUID& id = it->asUUID();
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(id, &av_name))
{
- setTyping(false);
+ all_names_resolved = false;
+
+ // If a name is not found in cache, request it and continue the process recursively
+ // until all ids are resolved into names.
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list));
+ break;
}
}
- return parents_retcode;
+ if (all_names_resolved)
+ {
+ std::vector<LLAvatarName> avatar_names;
+ std::vector<LLSD>::const_iterator it = participants_uuids.begin();
+ for (; it != participants_uuids.end(); ++it)
+ {
+ const LLUUID& id = it->asUUID();
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(id, &av_name))
+ {
+ avatar_names.push_back(av_name);
+ }
+ }
+
+ std::string ui_title;
+ LLAvatarActions::buildResidentsString(avatar_names, ui_title);
+
+ updateSessionName(ui_title, ui_title);
+ }
}
//static
@@ -737,8 +788,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
{
initIMSession(im_session_id);
- boundVoiceChannel();
-
buildParticipantList();
}
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 6847efedf1..23f9e75e21 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -66,7 +66,6 @@ public:
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ BOOL getVisible();
// Check typing timeout timer.
- /*virtual*/ BOOL tick();
static LLIMFloater* findInstance(const LLUUID& session_id);
static LLIMFloater* getInstance(const LLUUID& session_id);
@@ -131,12 +130,18 @@ private:
/* virtual */ void onFocusLost();
/* virtual */ void onFocusReceived();
+ /*virtual*/ void refresh();
+
// Update the window title, input field help text, etc.
void updateSessionName(const std::string& ui_title, const std::string& ui_label);
// For display name lookups for IM window titles
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+ /// Updates the list of ad hoc conference participants
+ /// in an IM floater title.
+ void onParticipantsListChanged(LLUICtrl* ctrl);
+
bool dropPerson(LLUUID* person_id, bool drop);
BOOL isInviteAllowed() const;
@@ -193,6 +198,8 @@ private:
// connection to voice channel state change signal
boost::signals2::connection mVoiceChannelStateChangeConnection;
+
+ boost::signals2::connection mParticipantsListRefreshConnection;
};
#endif // LL_IMFLOATER_H
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 29ab4384cb..369ca699c5 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -186,6 +186,21 @@ BOOL LLNearbyChat::postBuild()
return LLIMConversation::postBuild();
}
+// virtual
+void LLNearbyChat::refresh()
+{
+ displaySpeakingIndicator();
+ updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState());
+
+ // *HACK: Update transparency type depending on whether our children have focus.
+ // This is needed because this floater is chrome and thus cannot accept focus, so
+ // the transparency type setting code from LLFloater::setFocus() isn't reached.
+ if (getTransparencyType() != TT_DEFAULT)
+ {
+ setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);
+ }
+}
+
void LLNearbyChat::onNearbySpeakers()
{
LLSD param;
@@ -389,27 +404,6 @@ void LLNearbyChat::showHistory()
storeRectControl();
}
-
-BOOL LLNearbyChat::tick()
-{
- // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater
- // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy().
- if (isDead()) return false;
-
- displaySpeakingIndicator();
- updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState());
-
- // *HACK: Update transparency type depending on whether our children have focus.
- // This is needed because this floater is chrome and thus cannot accept focus, so
- // the transparency type setting code from LLFloater::setFocus() isn't reached.
- if (getTransparencyType() != TT_DEFAULT)
- {
- setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);
- }
-
- return LLIMConversation::tick();
-}
-
std::string LLNearbyChat::getCurrentChat()
{
return mChatBox ? mChatBox->getText() : LLStringUtil::null;
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index c9aa69a912..db367f0b59 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -73,8 +73,6 @@ public:
LLChatEntry* getChatBox() { return mChatBox; }
- //virtual void draw();
-
std::string getCurrentChat();
virtual BOOL handleKeyHere( KEY key, MASK mask );
@@ -119,8 +117,6 @@ protected:
S32 mExpandedHeight;
- /*virtual*/ BOOL tick();
-
private:
void getAllowedRect (LLRect& rect);
@@ -128,6 +124,8 @@ private:
void appendMessage(const LLChat& chat, const LLSD &args = 0);
void onNearbySpeakers ();
+ /*virtual*/ void refresh();
+
LLHandle<LLView> mPopupMenuHandle;
std::vector<LLChat> mMessageArchive;
LLChatHistory* mChatHistory;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 59d26edff2..47518a365f 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -475,6 +475,7 @@ void LLParticipantList::update()
{
mSpeakerMgr->update(true);
+ // Need to resort the participant list if it's in sort by recent speaker order.
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered())
{
// Resort avatar list