diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index b41f962ffadc4644919694d306d6c865d992e337..1b929eca0e7ac0de5bf81952b98db47f030420df 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -35,6 +35,7 @@ #include "llcallfloater.h" +#include "llagentdata.h" // for gAgentID #include "llavatarlist.h" #include "llbottomtray.h" #include "llparticipantlist.h" @@ -46,6 +47,7 @@ LLCallFloater::LLCallFloater(const LLSD& key) , mSpeakerManager(NULL) , mPaticipants(NULL) , mAvatarList(NULL) +, mVoiceType(VC_LOCAL_CHAT) { } @@ -69,6 +71,8 @@ BOOL LLCallFloater::postBuild() anchor_panel, this, getDockTongue(), LLDockControl::TOP)); + initAgentData(); + // update list for current session updateSession(); @@ -110,6 +114,19 @@ void LLCallFloater::updateSession() if (im_session) { mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id); + switch (im_session->mType) + { + case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: + mVoiceType = VC_PEER_TO_PEER; + break; + case IM_SESSION_CONFERENCE_START: + mVoiceType = VC_AD_HOC_CHAT; + break; + default: + mVoiceType = VC_GROUP_CHAT; + break; + } } if (NULL == mSpeakerManager) @@ -117,8 +134,10 @@ void LLCallFloater::updateSession() // by default let show nearby chat participants mSpeakerManager = LLLocalSpeakerMgr::getInstance(); lldebugs << "Set DEFAULT speaker manager" << llendl; + mVoiceType = VC_LOCAL_CHAT; } + updateTitle(); refreshPartisipantList(); } @@ -129,10 +148,52 @@ void LLCallFloater::refreshPartisipantList() bool do_not_use_context_menu_in_local_chat = LLLocalSpeakerMgr::getInstance() != mSpeakerManager; mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, do_not_use_context_menu_in_local_chat); + + if (!do_not_use_context_menu_in_local_chat) + { + mAvatarList->setNoItemsCommentText(getString("no_one_near")); + } } void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) { updateSession(); } + +void LLCallFloater::updateTitle() +{ + LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); + std::string title; + switch (mVoiceType) + { + case VC_LOCAL_CHAT: + title = getString("title_nearby"); + break; + case VC_PEER_TO_PEER: + title = voice_channel->getSessionName(); + break; + case VC_AD_HOC_CHAT: + title = getString("title_adhoc"); + break; + case VC_GROUP_CHAT: + LLStringUtil::format_map_t args; + args["[GROUP]"] = voice_channel->getSessionName(); + title = getString("title_group", args); + break; + } + + setTitle(title); +} + +void LLCallFloater::initAgentData() +{ + childSetValue("user_icon", gAgentID); + + std::string name; + gCacheName->getFullName(gAgentID, name); + childSetValue("user_text", name); + + LLOutputMonitorCtrl* speaking_indicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); + speaking_indicator->setSpeakerId(gAgentID); +} //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index bfaa1075c47c554e50143631bae9798e3918cd33..8a440873ff1a070c61d2ca8af4385334d5d41ebc 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -61,6 +61,14 @@ class LLCallFloater : public LLDockableFloater /*virtual*/ void onOpen(const LLSD& key); private: + typedef enum e_voice_controls_type + { + VC_LOCAL_CHAT, + VC_GROUP_CHAT, + VC_AD_HOC_CHAT, + VC_PEER_TO_PEER + }EVoiceControls; + /** * Updates mSpeakerManager and list according to current Voice Channel * @@ -74,11 +82,14 @@ class LLCallFloater : public LLDockableFloater */ void refreshPartisipantList(); void onCurrentChannelChanged(const LLUUID& session_id); + void updateTitle(); + void initAgentData(); private: LLSpeakerMgr* mSpeakerManager; LLParticipantList* mPaticipants; LLAvatarList* mAvatarList; + EVoiceControls mVoiceType; }; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index caf9c080574315fb342c6904cb54f6eae017a5ea..078c2518c6f76c5e56e196e37629a0bd6df43d1a 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -267,20 +267,20 @@ class LLChatHistoryHeader: public LLPanel } private: - std::string appendTime(const LLChat& chat) - { - 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; - } + std::string appendTime(const LLChat& chat) + { + 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 setTimeField(const LLChat& chat) { @@ -302,7 +302,7 @@ class LLChatHistoryHeader: public LLPanel time_box->translate(delta_pos_x, delta_pos_y); //... & change width of the name control - LLTextBox* user_name = getChild<LLTextBox>("user_name"); + LLView* user_name = getChild<LLView>("user_name"); const LLRect& user_rect = user_name->getRect(); user_name->reshape(user_rect.getWidth() + delta_pos_x, user_rect.getHeight()); } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 310eaaec27cd8eb45ac24d9d878e85a2b1ee78c3..5e9ffdf4100b4e529b3807e6271bf15b5874e03a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -34,6 +34,8 @@ #include "llimfloater.h" +#include "llnotificationsutil.h" + #include "llagent.h" #include "llappviewer.h" #include "llbutton.h" @@ -634,6 +636,9 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) else label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); mInputEditor->setLabel(label); + + if (moderator_muted_text) + LLNotificationsUtil::add("TextChatIsMutedByModerator"); } } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2f885787391201dbbed24bc51209297b257dea29..be719c0a7839f85a9f149e3ad914da515780a053 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -233,6 +233,12 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES break; } } + + // Update speakers list when connected + if (LLVoiceChannel::STATE_CONNECTED == new_state) + { + mSpeakers->update(true); + } } else // group || ad-hoc calls { @@ -445,6 +451,19 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, return true; } +bool LLIMModel::logToFile(const std::string& session_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) +{ + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + LLLogChat::saveHistory(session_name, from, from_id, utf8_text); + return true; + } + else + { + return false; + } +} + bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) @@ -476,8 +495,7 @@ bool LLIMModel::proccessOnlineOfflineNotification( } bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, - const std::string& utf8_text, bool log2file /* = true */) -{ + const std::string& utf8_text, bool log2file /* = true */) { LLIMSession* session = findIMSession(session_id); if (!session) @@ -486,7 +504,10 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co return false; } - addMessageSilently(*session, from, from_id, utf8_text, log2file); + addToHistory(session_id, from, from_id, utf8_text); + if (log2file) logToFile(session_id, from, from_id, utf8_text); + + session->mNumUnread++; // notify listeners LLSD arg; @@ -501,15 +522,6 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co return true; } -void LLIMModel::addMessageSilently(LLIMSession& session, const std::string& from, const LLUUID& from_id, - const std::string& utf8_text, bool log2file /* = true */) -{ - addToHistory(session.mSessionID, from, from_id, utf8_text); - if (log2file) logToFile(session.mSessionID, from, from_id, utf8_text); - - session.mNumUnread++; -} - const std::string& LLIMModel::getName(const LLUUID& session_id) const { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 72fd006222db412462fc0d04277a847d6e863d4b..40e3a8fb692ce6d8aaa870d91a97f395bfe623b6 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -145,11 +145,6 @@ class LLIMModel : public LLSingleton<LLIMModel> */ bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true); - /** - * Adds message without new message notification. - */ - void addMessageSilently(LLIMSession& session, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true); - /** * Add a system message to an IM Model */ @@ -205,6 +200,11 @@ class LLIMModel : public LLSingleton<LLIMModel> void testMessages(); + /** + * Saves an IM message into a file + */ + bool logToFile(const std::string& session_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); + private: /** diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 2e7f95660a48e966c3fcb8929607635d79abb825..68899319563eac76edc3a7a47e5868ecb3f675c4 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -88,6 +88,8 @@ bool LLGroupHandler::processNotification(const LLSD& notify) if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { + LLHandlerUtil::logGroupNoticeToIMGroup(notification); + LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); LLToast::Params p; p.notif_id = notification->getID(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index d42b0148d6196f539249daef98efd246e8670bb5..da8928321aba50b3daa5cc9e06040f6372a48496 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -268,7 +268,20 @@ class LLHandlerUtil /** * Writes notification message to IM session. */ - static void logToIM(const LLNotificationPtr& notification); + static void logToIM(const EInstantMessage& session_type, + const std::string& session_name, const std::string& from_name, + const std::string& message, const LLUUID& session_owner_id, + const LLUUID& from_id); + + /** + * Writes notification message to IM p2p session. + */ + static void logToIMP2P(const LLNotificationPtr& notification); + + /** + * Writes group notice notification message to IM group session. + */ + static void logGroupNoticeToIMGroup(const LLNotificationPtr& notification); }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index e1236b935ee79bcaf5bef531101ae3fbe19bdce8..05da33851382f9bfa3d8556faa9d96facb5f65ad 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -36,6 +36,7 @@ #include "llnotificationhandler.h" #include "llnotifications.h" #include "llimview.h" +#include "llagent.h" using namespace LLNotificationsUI; @@ -52,37 +53,77 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) } // static -void LLHandlerUtil::logToIM(const LLNotificationPtr& notification) +void LLHandlerUtil::logToIM(const EInstantMessage& session_type, + const std::string& session_name, const std::string& from_name, + const std::string& message, const LLUUID& session_owner_id, + const LLUUID& from_id) +{ + LLUUID session_id = LLIMMgr::computeSessionID(session_type, + session_owner_id); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + session_id); + if (session == NULL) + { + LLIMModel::instance().logToFile(session_name, from_name, from_id, message); + } + else + { + // store active session id + const LLUUID & active_session_id = + LLIMModel::instance().getActiveSessionID(); + + // set searched session as active to avoid IM toast popup + LLIMModel::instance().setActiveSessionID(session_id); + + LLIMModel::instance().addMessage(session_id, from_name, from_id, + message); + + // restore active session id + LLIMModel::instance().setActiveSessionID(active_session_id); + } +} + +// static +void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) { - // add message to IM const std::string name = notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"] : notification->getSubstitutions()["[NAME]"]; - // don't create IM session with objects, it's necessary condition to log + // don't create IM p2p session with objects, it's necessary condition to log if (notification->getName() != OBJECT_GIVE_ITEM && notification->getName() != OBJECT_GIVE_ITEM_UNKNOWN_USER) { LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, - from_id); - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - if (session == NULL) - { - session_id = LLIMMgr::instance().addSession(name, - IM_NOTHING_SPECIAL, from_id); - session = LLIMModel::instance().findIMSession(session_id); - } - - if (session == NULL) - { - llerrs << "session " << session_id << "does not exist " << llendl; - return; - } - - LLIMModel::instance().addMessageSilently(*session, name, from_id, - notification->getMessage()); + + logToIM(IM_NOTHING_SPECIAL, name, name, notification->getMessage(), + from_id, from_id); } } + +// static +void LLHandlerUtil::logGroupNoticeToIMGroup( + const LLNotificationPtr& notification) +{ + + const LLSD& payload = notification->getPayload(); + LLGroupData groupData; + if (!gAgent.getGroupData(payload["group_id"].asUUID(), groupData)) + { + llwarns + << "Group notice for unkown group: " + << payload["group_id"].asUUID() << llendl; + } + + const std::string group_name = groupData.mName; + const std::string sender_name = payload["sender_name"].asString(); + + // we can't retrieve sender id from group notice system message, so try to lookup it from cache + LLUUID sender_id; + gCacheName->getUUID(sender_name, sender_id); + + logToIM(IM_SESSION_GROUP_START, group_name, sender_name, payload["message"], + payload["group_id"], sender_id); +} + diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index cfe7fd09ac1abe6e1aee61e859ae69c93544b54d..c179a2cf90a881f5fc086b0dc6d4d81f60594ba5 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -90,7 +90,7 @@ bool LLOfferHandler::processNotification(const LLSD& notify) if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { - LLHandlerUtil::logToIM(notification); + LLHandlerUtil::logToIMP2P(notification); LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 6f91b6e58b4dc18dca6552d2bb1d9e69e36a9367..c7261199e3cee2268d570d5be410f16ba059a32f 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -98,7 +98,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify) { if (LLHandlerUtil::canLogToIM(notification)) { - LLHandlerUtil::logToIM(notification); + LLHandlerUtil::logToIMP2P(notification); } if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 68dc1b511f64f76e753276be1dd2c9100729ce0d..07a1214b4f412cd8dbe74c5dab38bb5726c412fa 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -87,7 +87,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) { const LLPointer<LLSpeaker>& speakerp = *it; - group_members.push_back(speakerp->mID); + addAvatarIDExceptAgent(group_members, speakerp->mID); if ( speakerp->mIsModerator ) { mModeratorList.insert(speakerp->mID); @@ -192,7 +192,7 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co return true; } - group_members.push_back(uu_id); + addAvatarIDExceptAgent(group_members, uu_id); // Mark AvatarList as dirty one mAvatarList->setDirty(); sort(); @@ -260,6 +260,15 @@ void LLParticipantList::sort() } } +// static +void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id) +{ + if (gAgent.getID() != avatar_id) + { + existing_list.push_back(avatar_id); + } +} + // // LLParticipantList::SpeakerAddListener // diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index ce61dd9b96423b366fcc7f043e1874ad9fa6027e..460cf4b9efe938dca764899577bfe0c29f04a89b 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -132,6 +132,11 @@ class LLParticipantList void onAvatarListDoubleClicked(LLAvatarList* list); void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); + /** + * Adds specified avatar ID to the existing list if it is not Agent's ID + */ + static void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); + LLSpeakerMgr* mSpeakerMgr; LLAvatarList* mAvatarList; diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 4434fe7403212c388a77248272769c27adbe7a72..04696ca2e7b6e0e4c30a22a0a234708918c347d8 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -8,32 +8,49 @@ save_visibility="true" single_instance="true" width="282"> + <string + name="title_nearby"> + NEARBY VOICE + </string> + <string + name="title_group"> + Group Call with [GROUP] + </string> + <string + name="title_adhoc"> + Conference Call + </string> + <string + name="no_one_near"> + No one near + </string> <panel bevel_style="in" follows="left|right|top" - height="73" + height="62" layout="topleft" left="0" name="control_panel" - width="285"> + width="282"> <panel - height="20" + height="18" + follows="top|left|right" layout="topleft" left="10" name="my_panel" - width="262"> + width="263"> <avatar_icon enabled="false" follows="left|top" height="18" - image_name="Generic_Person" + default_icon_name="Generic_Person" layout="topleft" left="0" name="user_icon" top="0" width="18" /> <text - follows="top|left" + follows="top|left|right" font="SansSerifSmallBold" height="16" layout="topleft" @@ -41,8 +58,20 @@ name="user_text" text_color="white" top="4" + use_ellipses="true" value="Mya Avatar:" - width="80" /> + width="210" /> + <output_monitor + auto_update="true" + draw_border="false" + follows="right" + height="16" + layout="topleft" + name="speaking_indicator" + right="-1" + top="2" + visible="true" + width="20" /> </panel> <layout_stack bottom="10" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 49276172d57365e6469583f71880c4f7cc975dac..cb0614797a8c9cbe43668c4f0af421e8fafa7420 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5783,6 +5783,26 @@ Server Error: Media update or get failed. yestext="OK"/> </notification> + <notification + icon="alertmodal.tga" + name="TextChatIsMutedByModerator" + type="alertmodal"> +Your text chat has been muted by moderator. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="VoiceIsMutedByModerator" + type="alertmodal"> +Your voice has been muted by moderator. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + <notification icon="alertmodal.tga" name="ConfirmClearTeleportHistory" diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml index 0a5812882da60e16afcf4d1d7cfc84647d46d428..0a3fd1699f7635af78cf729b6b37a39aa7bc92fd 100644 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -76,7 +76,6 @@ visible="false" width="100" /> <button - enabled="false" bottom="10" height="20" label="Voice Controls"