From 0cfea7b406c87bf593d2f7cf6040d92ef99b64cf Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 26 Jun 2012 01:38:59 +0300 Subject: CHUI-147 FIX Added updating conference participants in IM floater title - The title is updated with the data from participants list widget in IM floater. - Creating the participants list is fixed for the case of starting the ad hoc session when the session id changes upon initialization (see LLIMConversation::buildParticipantList()). - LLEventTimer replaced with simple LLTimer to avoid crashes in LLEventTimer::tick(). - Moved the build_residents_string() code to LLAvatarActions::buildResidentsString() to use it in LLIMFloater::onParticipantsListChanged(). --- indra/newview/llavataractions.cpp | 35 +++++++------- indra/newview/llavataractions.h | 9 ++++ indra/newview/llimconversation.cpp | 34 +++++++++----- indra/newview/llimconversation.h | 10 ++-- indra/newview/llimfloater.cpp | 93 ++++++++++++++++++++++++++++--------- indra/newview/llimfloater.h | 9 +++- indra/newview/llnearbychat.cpp | 36 ++++++-------- indra/newview/llnearbychat.h | 6 +-- indra/newview/llparticipantlist.cpp | 1 + 9 files changed, 151 insertions(+), 82 deletions(-) (limited to 'indra/newview') 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 avatar_names, std::string& residents_string) - { - llassert(avatar_names.size() > 0); - - const std::string& separator = LLTrans::getString("words_separator"); - for (std::vector::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& 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 avatar_names, std::string& residents_string) +{ + llassert(avatar_names.size() > 0); + const std::string& separator = LLTrans::getString("words_separator"); + for (std::vector::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 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 #include +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 avatar_names, std::string& residents_string); + static std::set 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("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("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("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(ctrl); + if (!avatar_list) { - return false; + return; } - BOOL parents_retcode = LLIMConversation::tick(); + bool all_names_resolved = true; + std::vector participants_uuids; - if ( mMeTyping ) + avatar_list->getValues(participants_uuids); + + // Check whether we have all participants names in LLAvatarNameCache + for (std::vector::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 avatar_names; + std::vector::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 mPopupMenuHandle; std::vector 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 -- cgit v1.2.3