summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llavataractions.cpp11
-rw-r--r--indra/newview/llavatariconctrl.cpp7
-rw-r--r--indra/newview/llgroupactions.cpp7
-rw-r--r--indra/newview/llgrouplist.cpp5
-rw-r--r--indra/newview/llimfloater.cpp33
-rw-r--r--indra/newview/llimfloater.h1
-rw-r--r--indra/newview/llimpanel.cpp14
-rw-r--r--indra/newview/llimview.cpp65
-rw-r--r--indra/newview/llimview.h4
-rw-r--r--indra/newview/llinventorybridge.cpp7
-rw-r--r--indra/newview/llinventorypanel.cpp7
-rw-r--r--indra/newview/llnotificationofferhandler.cpp4
-rw-r--r--indra/newview/llpanellandmarks.cpp6
-rw-r--r--indra/newview/llpanelpeople.cpp6
-rw-r--r--indra/newview/llpanelteleporthistory.cpp13
-rw-r--r--indra/newview/llparticipantlist.cpp98
-rw-r--r--indra/newview/llparticipantlist.h20
-rw-r--r--indra/newview/llspeakers.cpp23
-rw-r--r--indra/newview/llspeakers.h10
-rw-r--r--indra/newview/llviewerfloaterreg.cpp1
-rw-r--r--indra/newview/llviewermenu.cpp7
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_notes.xml11
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
25 files changed, 314 insertions, 54 deletions
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 67ffe54b7e..3fc37aa3d5 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -178,7 +178,10 @@ void LLAvatarActions::startIM(const LLUUID& id)
std::string name;
gCacheName->getFullName(id, name);
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
- LLIMFloater::show(session_id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
make_ui_sound("UISndStartIM");
}
@@ -191,7 +194,11 @@ void LLAvatarActions::startConference(const std::vector<LLUUID>& ids)
{
id_array.push_back(*it);
}
- gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array);
+ LLUUID session_id = gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
make_ui_sound("UISndStartIM");
}
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index b56e8d1ec2..0ee3e78409 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -44,6 +44,7 @@
#include "llcachename.h"
#include "llagentdata.h"
+#include "llimfloater.h"
#define MENU_ITEM_VIEW_PROFILE 0
#define MENU_ITEM_SEND_IM 1
@@ -354,7 +355,11 @@ void LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked(const LLSD& userdata)
name.append(" ");
name.append(getLastName());
- gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+ LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
}
else if (level == "add")
{
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index c46eedbef2..e60bde9fd8 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -43,6 +43,7 @@
#include "llimview.h" // for gIMMgr
#include "llsidetray.h"
#include "llstatusbar.h" // can_afford_transaction()
+#include "llimfloater.h"
//
// Globals
@@ -279,10 +280,14 @@ void LLGroupActions::startChat(const LLUUID& group_id)
LLGroupData group_data;
if (gAgent.getGroupData(group_id, group_data))
{
- gIMMgr->addSession(
+ LLUUID session_id = gIMMgr->addSession(
group_data.mName,
IM_SESSION_GROUP_START,
group_id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
make_ui_sound("UISndStartIM");
}
else
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 2e2b2d5101..010ed23918 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -183,6 +183,11 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL
item->childSetVisible("info_btn", false);
item->setGroupIconVisible(mShowIcons);
+ if (id.isNull())
+ {
+ item->childSetVisible("profile_btn", false);
+ }
+
addItem(item, id, pos);
// setCommentVisible(false);
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 85863ed85b..a634a1b0fd 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -115,7 +115,7 @@ void LLIMFloater::onClose(bool app_quitting)
/* static */
void LLIMFloater::newIMCallback(const LLSD& data){
- if (data["num_unread"].asInteger() > 0)
+ if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())
{
LLUUID session_id = data["session_id"].asUUID();
@@ -235,7 +235,7 @@ BOOL LLIMFloater::postBuild()
std::string session_name(LLIMModel::instance().getName(mSessionID));
- mInputEditor->setLabel(mInputEditor->getLabel() + " " + session_name);
+ mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name);
LLStringUtil::toUpper(session_name);
setTitle(session_name);
@@ -498,7 +498,8 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
// Allow enabling the LLIMFloater input editor only if session can accept text
LLIMModel::LLIMSession* im_session =
LLIMModel::instance().findIMSession(self->mSessionID);
- if( im_session && im_session->mTextIMPossible )
+ //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK)
+ if( im_session && im_session->mTextIMPossible && !self->mInputEditor->getEnabled())
{
//in disconnected state IM input editor should be disabled
self->mInputEditor->setEnabled(!gDisconnected);
@@ -588,6 +589,32 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
}
}
+void LLIMFloater::processAgentListUpdates(const LLSD& body)
+{
+ if ( !body.isMap() ) return;
+
+ if ( body.has("agent_updates") && body["agent_updates"].isMap() )
+ {
+ LLSD agent_data = body["agent_updates"].get(gAgentID.asString());
+ if (agent_data.isMap() && agent_data.has("info"))
+ {
+ LLSD agent_info = agent_data["info"];
+
+ if (agent_info.has("mutes"))
+ {
+ BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean();
+ mInputEditor->setEnabled(!moderator_muted_text);
+ std::string label;
+ if (moderator_muted_text)
+ label = LLTrans::getString("IM_muted_text_label");
+ else
+ label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID);
+ mInputEditor->setLabel(label);
+ }
+ }
+ }
+}
+
void LLIMFloater::processSessionUpdate(const LLSD& session_update)
{
// *TODO : verify following code when moderated mode will be implemented
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index f5edb3188a..065441b188 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -90,6 +90,7 @@ public:
void onVisibilityChange(const LLSD& new_visibility);
void processIMTyping(const LLIMInfo* im_info, BOOL typing);
+ void processAgentListUpdates(const LLSD& body);
void processSessionUpdate(const LLSD& session_update);
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 7399f1e1b3..0b8b5935f8 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -321,6 +321,9 @@ void LLFloaterIMPanel::draw()
// hide/show start call and end call buttons
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID);
+ if (!voice_channel)
+ return;
+
childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
childSetEnabled("start_call_btn", enable_connect);
@@ -770,10 +773,13 @@ void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility)
}
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID);
- if (new_visibility.asBoolean() && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED)
- LLFloaterReg::showInstance("voice_call", mSessionUUID);
- else
- LLFloaterReg::hideInstance("voice_call", mSessionUUID);
+ if (voice_channel && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED)
+ {
+ if (new_visibility.asBoolean())
+ LLFloaterReg::showInstance("voice_call", mSessionUUID);
+ else
+ LLFloaterReg::hideInstance("voice_call", mSessionUUID);
+ }
}
void LLFloaterIMPanel::sendMsg()
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 7e8701bf21..fdf119fbee 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -134,7 +134,6 @@ void LLIMModel::setActiveSessionID(const LLUUID& session_id)
LLIMModel::LLIMModel()
{
addNewMsgCallback(LLIMFloater::newIMCallback);
- addNoUnreadMsgsCallback(LLIMFloater::newIMCallback);
addNewMsgCallback(toast_callback);
}
@@ -440,7 +439,8 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co
addToHistory(session_id, from, from_id, utf8_text);
if (log2file) logToFile(session_id, from, from_id, utf8_text);
- session->mNumUnread++;
+ //we do not count system messages
+ if (from_id.notNull()) session->mNumUnread++;
// notify listeners
LLSD arg;
@@ -1192,10 +1192,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
}
else
{
- gIMMgr->addSession(
+ LLUUID session_id = gIMMgr->addSession(
mPayload["session_name"].asString(),
type,
session_id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
@@ -1279,10 +1283,14 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
}
else
{
- gIMMgr->addSession(
+ LLUUID session_id = gIMMgr->addSession(
payload["session_name"].asString(),
type,
session_id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
@@ -1350,13 +1358,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
LLIMMgr::LLIMMgr() :
mIMReceived(FALSE)
{
- static bool registered_dialog = false;
- if (!registered_dialog)
- {
- LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
- registered_dialog = true;
- }
-
mPendingInvitations = LLSD::emptyMap();
mPendingAgentListUpdates = LLSD::emptyMap();
}
@@ -1555,6 +1556,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
const std::string& caller_uri)
{
LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
if (speaker_mgr)
@@ -1848,6 +1853,29 @@ void LLIMMgr::clearPendingInvitation(const LLUUID& session_id)
}
}
+void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body)
+{
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ im_floater->processAgentListUpdates(body);
+ }
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ if (speaker_mgr)
+ {
+ speaker_mgr->updateSpeakers(body);
+ }
+ else
+ {
+ //we don't have a speaker manager yet..something went wrong
+ //we are probably receiving an update here before
+ //a start or an acceptance of an invitation. Race condition.
+ gIMMgr->addPendingAgentListUpdates(
+ session_id,
+ body);
+ }
+}
+
LLSD LLIMMgr::getPendingAgentListUpdates(const LLUUID& session_id)
{
if ( mPendingAgentListUpdates.has(session_id.asString()) )
@@ -2232,20 +2260,7 @@ public:
const LLSD& input) const
{
const LLUUID& session_id = input["body"]["session_id"].asUUID();
- LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
- if (speaker_mgr)
- {
- speaker_mgr->updateSpeakers(input["body"]);
- }
- else
- {
- //we don't have a speaker manager yet..something went wrong
- //we are probably receiving an update here before
- //a start or an acceptance of an invitation. Race condition.
- gIMMgr->addPendingAgentListUpdates(
- input["body"]["session_id"].asUUID(),
- input["body"]);
- }
+ gIMMgr->processAgentListUpdates(session_id, input["body"]);
}
};
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index f986d9dcdb..bd55bd2c30 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -66,7 +66,10 @@ public:
EInstantMessage mType;
LLUUID mOtherParticipantID;
std::vector<LLUUID> mInitialTargetIDs;
+
+ //does NOT include system messages
S32 mNumUnread;
+
std::list<LLSD> mMsgs;
LLVoiceChannel* mVoiceChannel;
@@ -315,6 +318,7 @@ public:
void clearPendingInvitation(const LLUUID& session_id);
+ void processAgentListUpdates(const LLUUID& session_id, const LLSD& body);
LLSD getPendingAgentListUpdates(const LLUUID& session_id);
void addPendingAgentListUpdates(
const LLUUID& sessioN_id,
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index dbc12f0617..90e48d22ec 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -97,6 +97,7 @@
#include "llfloateropenobject.h"
#include "lltrans.h"
#include "llappearancemgr.h"
+#include "llimfloater.h"
using namespace LLOldEvents;
@@ -3390,7 +3391,11 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel*
{
std::string callingcard_name;
gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
- gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
}
}
else if ("lure" == action)
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 0a13d819a5..7f69ce9641 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -86,6 +86,7 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llwearablelist.h"
+#include "llimfloater.h"
static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
@@ -800,7 +801,11 @@ bool LLInventoryPanel::beginIMSession()
name = llformat("Session %d", session_num++);
}
- gIMMgr->addSession(name, type, members[0], members);
+ LLUUID session_id = gIMMgr->addSession(name, type, members[0], members);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
return true;
}
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 8e3a44682c..75ef5208e7 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -99,6 +99,10 @@ bool LLOfferHandler::processNotification(const LLSD& notify)
session_id = LLIMMgr::instance().addSession(
notification->getSubstitutions()["NAME"], IM_NOTHING_SPECIAL,
notification->getPayload()["from_id"]);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
}
LLIMMgr::instance().addMessage(session_id, LLUUID(),
notification->getSubstitutions()["NAME"],
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index dc0a49b6e2..ce1a7f98df 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -499,6 +499,7 @@ void LLLandmarksPanel::updateListCommands()
// keep Options & Add Landmark buttons always enabled
mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled);
mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled);
+ mListCommands->childSetEnabled(OPTIONS_BUTTON_NAME,getCurSelectedItem() != NULL);
}
void LLLandmarksPanel::onActionsButtonClick()
@@ -829,17 +830,18 @@ bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) co
// then ask LLFolderView permissions
if (can_be_modified)
{
+ LLFolderViewItem* selected = getCurSelectedItem();
if ("cut" == command_name)
{
can_be_modified = mCurrentSelectedList->getRootFolder()->canCut();
}
else if ("rename" == command_name)
{
- can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable();
+ can_be_modified = selected? selected->getListener()->isItemRenameable() : false;
}
else if ("delete" == command_name)
{
- can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable();
+ can_be_modified = selected? selected->getListener()->isItemRemovable(): false;
}
else if("paste" == command_name)
{
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 65a7b5322b..bb6cdd2f78 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -667,8 +667,10 @@ void LLPanelPeople::updateButtons()
buttonSetEnabled("im_btn", (selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection
buttonSetEnabled("call_btn", item_selected && false); // not implemented yet
buttonSetEnabled("share_btn", item_selected && false); // not implemented yet
- buttonSetEnabled("group_info_btn", item_selected);
- buttonSetEnabled("chat_btn", item_selected);
+
+ bool none_group_selected = item_selected && selected_id.isNull();
+ buttonSetEnabled("group_info_btn", !none_group_selected);
+ buttonSetEnabled("chat_btn", !none_group_selected);
}
std::string LLPanelPeople::getActiveTabName() const
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 28e89fd619..72856d5b82 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -406,6 +406,7 @@ void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, L
if (tab_idx <= tabs_cnt - 4)
{
+ // All tabs, except last three, are tabs for one day, so just push tab_date back by one day
tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
}
else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
@@ -442,6 +443,7 @@ void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, L
}
}
+// Called to add items, no more, than ADD_LIMIT at time
void LLTeleportHistoryPanel::refresh()
{
if (!mHistoryAccordion)
@@ -452,12 +454,16 @@ void LLTeleportHistoryPanel::refresh()
const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
+ // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary.
+ // That leads to call to getNextTab to get right tab_idx in first pass
LLDate tab_boundary_date = LLDate::now();
+
LLFlatListView* curr_flat_view = NULL;
U32 added_items = 0;
while (mCurrentItem >= 0)
{
+ // Filtering
std::string landmark_title = items[mCurrentItem].mTitle;
LLStringUtil::toUpper(landmark_title);
@@ -470,10 +476,14 @@ void LLTeleportHistoryPanel::refresh()
continue;
}
+ // Checking whether date of item is earlier, than tab_boundary_date.
+ // In that case, item should be added to another tab
const LLDate &date = items[mCurrentItem].mDate;
if (date < tab_boundary_date)
{
+ // Getting apropriate tab_idx for this and subsequent items,
+ // tab_boundary_date would be earliest possible date for this tab
S32 tab_idx = 0;
getNextTab(date, tab_idx, tab_boundary_date);
@@ -580,6 +590,9 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
void LLTeleportHistoryPanel::showTeleportHistory()
{
mDirty = true;
+
+ // Starting to add items from last one, in reverse order,
+ // since TeleportHistory keeps most recent item at the end
mCurrentItem = mTeleportHistory->getItems().size() - 1;
for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 32223e314e..2be0781487 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -53,13 +53,16 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
mSpeakerAddListener = new SpeakerAddListener(*this);
mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
mSpeakerClearListener = new SpeakerClearListener(*this);
+ mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this);
mSpeakerMgr->addListener(mSpeakerAddListener, "add");
mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
+ mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));
+ mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2));
//Lets fill avatarList with existing speakers
LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
@@ -68,7 +71,12 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
mSpeakerMgr->getSpeakerList(&speaker_list, true);
for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
{
- group_members.push_back((*it)->mID);
+ const LLPointer<LLSpeaker>& speakerp = *it;
+ group_members.push_back(speakerp->mID);
+ if ( speakerp->mIsModerator )
+ {
+ mModeratorList.insert(speakerp->mID);
+ }
}
sort();
}
@@ -87,6 +95,56 @@ void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list)
LLAvatarActions::startIM(clicked_id);
}
+void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
+{
+ LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl);
+ if (list)
+ {
+ const std::string moderator_indicator(LLTrans::getString("IM_moderator_label"));
+ const std::size_t moderator_indicator_len = moderator_indicator.length();
+
+ // Firstly remove moderators indicator
+ std::set<LLUUID>::const_iterator
+ moderator_list_it = mModeratorToRemoveList.begin(),
+ moderator_list_end = mModeratorToRemoveList.end();
+ for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
+ {
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it));
+ if ( item )
+ {
+ std::string name = item->getAvatarName();
+ size_t found = name.find(moderator_indicator);
+ if (found == std::string::npos)
+ {
+ name.erase(found, moderator_indicator_len);
+ item->setName(name);
+ }
+ }
+ }
+
+ mModeratorToRemoveList.clear();
+
+ // Add moderators indicator
+ moderator_list_it = mModeratorList.begin();
+ moderator_list_end = mModeratorList.end();
+ for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
+ {
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it));
+ if ( item )
+ {
+ std::string name = item->getAvatarName();
+ size_t found = name.find(moderator_indicator);
+ if (found == std::string::npos)
+ {
+ name += " ";
+ name += moderator_indicator;
+ item->setName(name);
+ }
+ }
+ }
+ }
+}
+
void LLParticipantList::setSortOrder(EParticipantSortOrder order)
{
if ( mSortOrder != order )
@@ -109,6 +167,8 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co
}
group_members.push_back(uu_id);
+ // Mark AvatarList as dirty one
+ mAvatarList->setDirty();
sort();
return true;
}
@@ -133,14 +193,36 @@ bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event,
return true;
}
+bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ const LLSD& evt_data = event->getValue();
+ if ( evt_data.has("id") && evt_data.has("is_moderator") )
+ {
+ LLUUID id = evt_data["id"];
+ bool is_moderator = evt_data["is_moderator"];
+ if ( id.notNull() )
+ {
+ if ( is_moderator )
+ mModeratorList.insert(id);
+ else
+ {
+ std::set<LLUUID>::iterator it = mModeratorList.find (id);
+ if ( it != mModeratorList.end () )
+ {
+ mModeratorToRemoveList.insert(id);
+ mModeratorList.erase(id);
+ }
+ }
+ }
+ }
+ return true;
+}
+
void LLParticipantList::sort()
{
if ( !mAvatarList )
return;
- // Mark AvatarList as dirty one
- mAvatarList->setDirty();
-
// TODO: Implement more sorting orders after specs updating (EM)
switch ( mSortOrder ) {
case E_SORT_BY_NAME :
@@ -175,3 +257,11 @@ bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents:
{
return mParent.onClearListEvent(event, userdata);
}
+
+//
+// LLParticipantList::SpeakerModeratorListener
+//
+bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ return mParent.onModeratorUpdateEvent(event, userdata);
+}
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index 8c209c0b20..fc34dd308b 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -35,6 +35,7 @@
class LLSpeakerMgr;
class LLAvatarList;
+class LLUICtrl;
class LLParticipantList
{
@@ -59,6 +60,7 @@ class LLParticipantList
bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
/**
* Sorts the Avatarlist by stored order
@@ -97,15 +99,27 @@ class LLParticipantList
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
};
+ class SpeakerModeratorUpdateListener : public BaseSpeakerListner
+ {
+ public:
+ SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
private:
void onAvatarListDoubleClicked(LLAvatarList* list);
+ void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
LLSpeakerMgr* mSpeakerMgr;
LLAvatarList* mAvatarList;
- LLPointer<SpeakerAddListener> mSpeakerAddListener;
- LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
- LLPointer<SpeakerClearListener> mSpeakerClearListener;
+ std::set<LLUUID> mModeratorList;
+ std::set<LLUUID> mModeratorToRemoveList;
+
+ LLPointer<SpeakerAddListener> mSpeakerAddListener;
+ LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
+ LLPointer<SpeakerClearListener> mSpeakerClearListener;
+ LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
EParticipantSortOrder mSortOrder;
};
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 2341fcfc6d..2ed82b7d62 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -87,6 +87,21 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, c
mDisplayName = first + " " + last;
}
+LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker add moderator event"),
+ mSpeakerID (source->mID),
+ mIsModerator (source->mIsModerator)
+{
+}
+
+LLSD LLSpeakerUpdateModeratorEvent::getValue()
+{
+ LLSD ret;
+ ret["id"] = mSpeakerID;
+ ret["is_moderator"] = mIsModerator;
+ return ret;
+}
+
LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
: LLEvent(source, "Speaker text moderation event")
{
@@ -437,9 +452,13 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
if ( speaker_it->second.isMap() )
{
+ BOOL is_moderator = speakerp->mIsModerator;
speakerp->mIsModerator = speaker_it->second["is_moderator"];
speakerp->mModeratorMutedText =
speaker_it->second["mutes"]["text"];
+ // Fire event only if moderator changed
+ if ( is_moderator != speakerp->mIsModerator )
+ fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
}
}
}
@@ -507,7 +526,11 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
if (agent_info.has("is_moderator"))
{
+ BOOL is_moderator = speakerp->mIsModerator;
speakerp->mIsModerator = agent_info["is_moderator"];
+ // Fire event only if moderator changed
+ if ( is_moderator != speakerp->mIsModerator )
+ fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
}
if (agent_info.has("mutes"))
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index e0f22bff4f..04046a8587 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -84,6 +84,16 @@ public:
BOOL mModeratorMutedText;
};
+class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerUpdateModeratorEvent(LLSpeaker* source);
+ /*virtual*/ LLSD getValue();
+private:
+ const LLUUID& mSpeakerID;
+ BOOL mIsModerator;
+};
+
class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent
{
public:
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 9ca2d3f61d..edbac69e1b 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -170,6 +170,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);
+ LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>);
LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>);
LLInspectAvatarUtil::registerFloater();
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a3b119456b..07d073c3a9 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -210,6 +210,7 @@
#include "lltexlayer.h"
#include "llappearancemgr.h"
+#include "llimfloater.h"
using namespace LLVOAvatarDefines;
@@ -6260,9 +6261,13 @@ class LLAvatarSendIM : public view_listener_t
//EInstantMessage type = have_agent_callingcard(gLastHitObjectID)
// ? IM_SESSION_ADD : IM_SESSION_CARDLESS_START;
- gIMMgr->addSession(name,
+ LLUUID session_id = gIMMgr->addSession(name,
IM_NOTHING_SPECIAL,
avatar->getID());
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
}
return true;
}
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 70af2f63b6..452d28d4ea 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -15,7 +15,7 @@
width="520"
can_resize="true"
min_width="350"
- min_height="350">
+ min_height="369">
<layout_stack follows="left|top|right|bottom"
height="354"
width="520"
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 c8b134cdf0..e81532ec3e 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
@@ -14,7 +14,7 @@
width="125"/>
<text
- follows="left|right"
+ follows="top|left|right"
font="SansSerifBig"
height="16"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml
index 5333dfa2f5..b9c9100ebc 100644
--- a/indra/newview/skins/default/xui/en/panel_notes.xml
+++ b/indra/newview/skins/default/xui/en/panel_notes.xml
@@ -17,13 +17,16 @@
left="0"
top="0"
height="517"
+ width="313"
border_size="0">
<panel
name="notes_stack"
follows="all"
layout="topleft"
top="0"
- left="0">
+ left="0"
+ height="475"
+ width="313">
<scroll_container
color="DkGray2"
follows="all"
@@ -31,8 +34,11 @@
left="0"
name="profile_scroll"
opaque="true"
+ height="475"
+ width="313"
top="0">
<panel
+ height="450"
layout="topleft"
name="profile_scroll_panel"
top="0"
@@ -104,7 +110,8 @@
layout="topleft"
left="0"
name="notes_buttons_panel"
- auto_resize="false">
+ auto_resize="false"
+ width="313">
<button
follows="bottom|left"
height="19"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ec2673644f..c850dce141 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2845,6 +2845,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Unnamed">(Unnamed)</string>
<string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string>
<string name="IM_unavailable_text_label">Text chat is not available for this call.</string>
+ <string name="IM_muted_text_label">Your text chat has been disabled by a Group Moderator.</string>
+ <string name="IM_default_text_label">Click here to instant message.</string>
+ <string name="IM_to_label">To</string>
+ <string name="IM_moderator_label">(Moderator)</string>
<string name="ringing-im">