summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2012-10-03 16:57:48 -0700
committerMerov Linden <merov@lindenlab.com>2012-10-03 16:57:48 -0700
commitba5760a4d9d110890aab26a394479b36e60915d7 (patch)
treeacad21a7c576de056bfa21a37027a673feab8fad /indra/newview
parentbd64c483639ae33518609398fce7c51ddc73dae7 (diff)
parentf2510ca0d629a2cd6cd85588698672f5a0c4e64a (diff)
Pull merge from richard/viewer-chui
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/commands.xml10
-rw-r--r--indra/newview/llappviewer.cpp3
-rwxr-xr-xindra/newview/llavataractions.cpp13
-rw-r--r--indra/newview/llcallfloater.cpp3
-rw-r--r--indra/newview/llcallfloater.h4
-rw-r--r--indra/newview/llconversationmodel.cpp74
-rwxr-xr-xindra/newview/llconversationmodel.h20
-rw-r--r--indra/newview/llimfloater.cpp28
-rw-r--r--indra/newview/llimfloater.h1
-rw-r--r--indra/newview/llimfloatercontainer.cpp302
-rw-r--r--indra/newview/llimfloatercontainer.h14
-rw-r--r--indra/newview/llinventorybridge.cpp9
-rw-r--r--indra/newview/llinventorybridge.h1
-rw-r--r--indra/newview/llinventorypanel.cpp1
-rw-r--r--indra/newview/llnearbychat.cpp16
-rw-r--r--indra/newview/llnearbychat.h5
-rw-r--r--indra/newview/llnearbychathandler.cpp1
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp16
-rw-r--r--indra/newview/skins/default/xui/en/floater_conversation_log.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_conversation.xml127
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml13
-rw-r--r--indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml3
23 files changed, 605 insertions, 63 deletions
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 51211a8ce5..d4bbd84d0f 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -239,14 +239,4 @@
is_running_function="Floater.IsOpen"
is_running_parameters="camera"
/>
- <command name="voice"
- available_in_toybox="true"
- icon="Command_Voice_Icon"
- label_ref="Command_Voice_Label"
- tooltip_ref="Command_Voice_Tooltip"
- execute_function="Floater.ToggleOrBringToFront"
- execute_parameters="voice_controls"
- is_running_function="Floater.IsOpen"
- is_running_parameters="voice_controls"
- />
</commands>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 08a1a237f5..6b15e4b21a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -42,6 +42,7 @@
#include "llagentcamera.h"
#include "llagentlanguage.h"
#include "llagentwearables.h"
+#include "llimfloatercontainer.h"
#include "llwindow.h"
#include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
@@ -1204,7 +1205,7 @@ bool LLAppViewer::mainLoop()
LLVoiceChannel::initClass();
LLVoiceClient::getInstance()->init(gServicePump);
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLIMFloaterContainer::onCurrentChannelChanged, _1), true);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index a76dbcac53..248685b964 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -42,6 +42,7 @@
#include "llappviewer.h" // for gLastVersionChannel
#include "llcachename.h"
#include "llcallingcard.h" // for LLAvatarTracker
+#include "llconversationlog.h"
#include "llfloateravatarpicker.h" // for LLFloaterAvatarPicker
#include "llfloatergroupinvite.h"
#include "llfloatergroups.h"
@@ -900,7 +901,17 @@ void LLAvatarActions::inviteToGroup(const LLUUID& id)
// static
void LLAvatarActions::viewChatHistory(const LLUUID& id)
{
- LLFloaterReg::showInstance("preview_conversation", id, true);
+ const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations();
+ std::vector<LLConversation>::const_iterator iter = conversations.begin();
+
+ for (; iter != conversations.end(); ++iter)
+ {
+ if (iter->getParticipantID() == id)
+ {
+ LLFloaterReg::showInstance("preview_conversation", iter->getSessionID(), true);
+ break;
+ }
+ }
}
//== private methods ========================================================================================
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 38b755004c..e767609d74 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -364,7 +364,8 @@ void LLCallFloater::onAvatarListRefreshed()
}
// static
-void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
+// This entry point now disable, but left for later use.
+void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/)
{
LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel();
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 181c92276d..e1c7b3f43a 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -74,7 +74,7 @@ public:
*/
/*virtual*/ void onParticipantsChanged();
- static void sOnCurrentChannelChanged(const LLUUID& session_id);
+ static void onCurrentChannelChanged(const LLUUID& session_id);
private:
typedef enum e_voice_controls_type
@@ -260,7 +260,7 @@ private:
*
* Is used to ignore voice channel changed callback for the same channel.
*
- * @see sOnCurrentChannelChanged()
+ * @see onCurrentChannelChanged()
*/
static LLVoiceChannel* sCurrentVoiceChannel;
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 7ddb725fb1..0f29ffe77f 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -29,6 +29,7 @@
#include "llevents.h"
#include "llconversationmodel.h"
+#include "llimview.h" //For LLIMModel
//
// Conversation items : common behaviors
@@ -95,6 +96,24 @@ void LLConversationItem::showProperties(void)
{
}
+void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items)
+{
+ items.push_back(std::string("view_profile"));
+ items.push_back(std::string("im"));
+ items.push_back(std::string("offer_teleport"));
+ items.push_back(std::string("voice_call"));
+ items.push_back(std::string("chat_history"));
+ items.push_back(std::string("separator_chat_history"));
+ items.push_back(std::string("add_friend"));
+ items.push_back(std::string("remove_friend"));
+ items.push_back(std::string("invite_to_group"));
+ items.push_back(std::string("separator_invite_to_group"));
+ items.push_back(std::string("map"));
+ items.push_back(std::string("share"));
+ items.push_back(std::string("pay"));
+ items.push_back(std::string("block_unblock"));
+}
+
//
// LLConversationItemSession
//
@@ -204,6 +223,52 @@ void LLConversationItemSession::setDistance(const LLUUID& participant_id, F64 di
}
}
+void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+
+ if(this->getType() == CONV_SESSION_1_ON_1)
+ {
+ items.push_back(std::string("close_conversation"));
+ items.push_back(std::string("separator_disconnect_from_voice"));
+ buildParticipantMenuOptions(items);
+ }
+ else if(this->getType() == CONV_SESSION_GROUP)
+ {
+ items.push_back(std::string("close_conversation"));
+ addVoiceOptions(items);
+ items.push_back(std::string("chat_history"));
+ items.push_back(std::string("separator_chat_history"));
+ items.push_back(std::string("group_profile"));
+ items.push_back(std::string("activate_group"));
+ items.push_back(std::string("leave_group"));
+ }
+ else if(this->getType() == CONV_SESSION_AD_HOC)
+ {
+ items.push_back(std::string("close_conversation"));
+ addVoiceOptions(items);
+ items.push_back(std::string("chat_history"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+void LLConversationItemSession::addVoiceOptions(menuentry_vec_t& items)
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance() ? LLIMModel::getInstance()->getVoiceChannel(this->getUUID()) : NULL;
+
+ if(voice_channel != LLVoiceChannel::getCurrentVoiceChannel())
+ {
+ items.push_back(std::string("open_voice_conversation"));
+ }
+ else
+ {
+ items.push_back(std::string("disconnect_from_voice"));
+ }
+}
+
// The time of activity of a session is the time of the most recent activity, session and participants included
const bool LLConversationItemSession::getTime(F64& time) const
{
@@ -262,6 +327,15 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid,
mConvType = CONV_PARTICIPANT;
}
+void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+
+ buildParticipantMenuOptions(items);
+ hide_context_entries(menu, items, disabled_items);
+}
+
void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name)
{
mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername);
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 32280f3293..7218cdf25a 100755
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -41,6 +41,8 @@ class LLConversationItemParticipant;
typedef std::map<LLUUID, LLConversationItem*> conversations_items_map;
typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map;
+typedef std::vector<std::string> menuentry_vec_t;
+
// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each
// that we tuck into the mConversationsListPanel.
class LLConversationItem : public LLFolderViewModelItemCommon
@@ -126,6 +128,8 @@ public:
void postEvent(const std::string& event_type, LLConversationItemParticipant* participant);
+ void buildParticipantMenuOptions(menuentry_vec_t& items);
+
protected:
std::string mName; // Name of the session or the participant
LLUUID mUUID; // UUID of the session or the participant
@@ -157,6 +161,8 @@ public:
bool isLoaded() { return mIsLoaded; }
+ void buildContextMenu(LLMenuGL& menu, U32 flags);
+ void addVoiceOptions(menuentry_vec_t& items);
virtual const bool getTime(F64& time) const;
void dumpDebugData();
@@ -180,7 +186,8 @@ public:
void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; }
void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; }
void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; }
-
+
+ void buildContextMenu(LLMenuGL& menu, U32 flags);
void onAvatarNameCache(const LLAvatarName& av_name);
virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); }
@@ -275,4 +282,15 @@ public:
private:
};
+// Utility function to hide all entries except those in the list
+// Can be called multiple times on the same menu (e.g. if multiple items
+// are selected). If "append" is false, then only common enabled items
+// are set as enabled.
+
+//(defined in inventorybridge.cpp)
+//TODO: Gilbert Linden - Refactor to make this function non-global
+void hide_context_entries(LLMenuGL& menu,
+ const menuentry_vec_t &entries_to_show,
+ const menuentry_vec_t &disabled_entries);
+
#endif // LL_LLCONVERSATIONMODEL_H
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index d11504d312..99337bd5f3 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -111,23 +111,25 @@ void LLIMFloater::onClickCloseBtn()
{
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID);
- if (session == NULL)
+ if (session != NULL)
{
- llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl;
- return;
- }
+ bool is_call_with_chat = session->isGroupSessionType()
+ || session->isAdHocSessionType() || session->isP2PSessionType();
- bool is_call_with_chat = session->isGroupSessionType()
- || session->isAdHocSessionType() || session->isP2PSessionType();
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
- LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
-
- if (is_call_with_chat && voice_channel != NULL
- && voice_channel->isActive())
+ if (is_call_with_chat && voice_channel != NULL
+ && voice_channel->isActive())
+ {
+ LLSD payload;
+ payload["session_id"] = mSessionID;
+ LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback);
+ return;
+ }
+ }
+ else
{
- LLSD payload;
- payload["session_id"] = mSessionID;
- LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback);
+ llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl;
return;
}
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index d444270716..5ed1d1ab35 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -127,6 +127,7 @@ public:
static void onIMChicletCreated(const LLUUID& session_id);
bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; }
+ const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;}
static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb);
static floater_showed_signal_t sIMFloaterShowedSignal;
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index e58154b2a2..da4d1afb2b 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -39,6 +39,7 @@
#include "llavatariconctrl.h"
#include "llavatarnamecache.h"
#include "llcallbacklist.h"
+#include "llgroupactions.h"
#include "llgroupiconctrl.h"
#include "llfloateravatarpicker.h"
#include "llfloaterpreference.h"
@@ -60,8 +61,14 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
mStream("ConversationsEvents"),
mInitialized(false)
{
+ mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2));
- mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2));
+
+ mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLIMFloaterContainer::checkContextMenuItem, this, _2));
+ mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem, this, _2));
+ mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2));
+
+ mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelectedGroup, this, _2));
// Firstly add our self to IMSession observers, so we catch session events
LLIMMgr::getInstance()->addSessionObserver(this);
@@ -109,6 +116,16 @@ void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id)
removeConversationListItem(session_id);
}
+// static
+void LLIMFloaterContainer::onCurrentChannelChanged(const LLUUID& session_id)
+{
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+}
+
+
BOOL LLIMFloaterContainer::postBuild()
{
mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1));
@@ -136,7 +153,9 @@ BOOL LLIMFloaterContainer::postBuild()
p.view_model = &mConversationViewModel;
p.root = NULL;
p.use_ellipses = true;
+ p.options_menu = "menu_conversation.xml";
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
+ mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
// Add listener to conversation model events
mStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1));
@@ -494,21 +513,26 @@ void LLIMFloaterContainer::tabClose()
}
void LLIMFloaterContainer::setVisible(BOOL visible)
-{
+{ LLNearbyChat* nearby_chat;
if (visible)
{
// Make sure we have the Nearby Chat present when showing the conversation container
- LLIMConversation* nearby_chat = LLFloaterReg::findTypedInstance<LLIMConversation>("nearby_chat");
+ nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat");
if (nearby_chat == NULL)
{
// If not found, force the creation of the nearby chat conversation panel
// *TODO: find a way to move this to XML as a default panel or something like that
LLSD name("nearby_chat");
LLFloaterReg::toggleInstanceOrBringToFront(name);
- LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat")->addToHost();
}
}
+ nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat");
+ if (nearby_chat && !nearby_chat->isHostSet())
+ {
+ nearby_chat->addToHost();
+ }
+
// We need to show/hide all the associated conversations that have been torn off
// (and therefore, are not longer managed by the multifloater),
// so that they show/hide with the conversations manager.
@@ -587,7 +611,7 @@ void LLIMFloaterContainer::collapseConversationsPane(bool collapse)
{
widget->setOpen(false);
}
- }
+}
}
}
@@ -751,6 +775,274 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order)
gSavedSettings.setU32("ConversationSortOrder", (U32)order);
}
+void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids)
+{
+ const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList();
+
+ std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin();
+ const std::set<LLFolderViewItem*>::const_iterator it_end = selectedItems.end();
+ LLConversationItem * conversationItem;
+
+ for (; it != it_end; ++it)
+ {
+ conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem());
+ selected_uuids.push_back(conversationItem->getUUID());
+ }
+}
+
+const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem()
+{
+ LLConversationItem * conversationItem = NULL;
+
+ if(mConversationsRoot &&
+ mConversationsRoot->getCurSelectedItem() &&
+ mConversationsRoot->getCurSelectedItem()->getViewModelItem())
+ {
+ conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem());
+ }
+
+ return conversationItem;
+}
+
+void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t selectedIDS)
+{
+ LLUUID userID;
+ userID = selectedIDS.front();
+
+ if ("view_profile" == command)
+ {
+ LLAvatarActions::showProfile(userID);
+ }
+ else if("im" == command)
+ {
+ LLAvatarActions::startIM(userID);
+ }
+ else if("offer_teleport" == command)
+ {
+ LLAvatarActions::offerTeleport(selectedIDS);
+ }
+ else if("voice_call" == command)
+ {
+ LLAvatarActions::startCall(userID);
+ }
+ else if("chat_history" == command)
+ {
+ LLAvatarActions::viewChatHistory(userID);
+ }
+ else if("add_friend" == command)
+ {
+ LLAvatarActions::requestFriendshipDialog(userID);
+ }
+ else if("remove_friend" == command)
+ {
+ LLAvatarActions::removeFriendDialog(userID);
+ }
+ else if("invite_to_group" == command)
+ {
+ LLAvatarActions::inviteToGroup(userID);
+ }
+ else if("map" == command)
+ {
+ LLAvatarActions::showOnMap(userID);
+ }
+ else if("share" == command)
+ {
+ LLAvatarActions::share(userID);
+ }
+ else if("pay" == command)
+ {
+ LLAvatarActions::pay(userID);
+ }
+ else if("block_unblock" == command)
+ {
+ LLAvatarActions::toggleBlock(userID);
+ }
+}
+
+void LLIMFloaterContainer::doToSelectedParticipant(const std::string& command)
+{
+ uuid_vec_t selected_uuids;
+ getSelectedUUIDs(selected_uuids);
+
+ doToUsers(command, selected_uuids);
+}
+
+void LLIMFloaterContainer::doToSelectedConversation(const std::string& command)
+{
+ LLUUID participantID;
+
+ //Find the conversation floater associated with the selected id
+ const LLConversationItem * conversationItem = getCurSelectedViewModelItem();
+ LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID());
+
+ if(conversationFloater)
+ {
+ //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c
+ //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with.
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1)
+ {
+ participantID = conversationFloater->getOtherParticipantUUID();
+ }
+
+ //Close the selected conversation
+ if("close_conversation" == command)
+ {
+ LLFloater::onClickClose(conversationFloater);
+ }
+ else if("open_voice_conversation" == command)
+ {
+ gIMMgr->startCall(conversationItem->getUUID());
+ }
+ else if("disconnect_from_voice" == command)
+ {
+ gIMMgr->endCall(conversationItem->getUUID());
+ }
+ else if("chat_history" == command)
+ {
+ LLAvatarActions::viewChatHistory(conversationItem->getUUID());
+ }
+ else
+ {
+ uuid_vec_t selected_uuids;
+ selected_uuids.push_back(participantID);
+ doToUsers(command, selected_uuids);
+ }
+ }
+}
+
+void LLIMFloaterContainer::doToSelected(const LLSD& userdata)
+{
+ std::string command = userdata.asString();
+ const LLConversationItem * conversationItem = getCurSelectedViewModelItem();
+
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 ||
+ conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP ||
+ conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC)
+ {
+ doToSelectedConversation(command);
+ }
+ else
+ {
+ doToSelectedParticipant(command);
+ }
+}
+
+void LLIMFloaterContainer::doToSelectedGroup(const LLSD& userdata)
+{
+ std::string action = userdata.asString();
+ LLUUID selected_group = getCurSelectedViewModelItem()->getUUID();
+
+ if (action == "group_profile")
+ {
+ LLGroupActions::show(selected_group);
+ }
+ else if (action == "activate_group")
+ {
+ LLGroupActions::activate(selected_group);
+ }
+ else if (action == "leave_group")
+ {
+ LLGroupActions::leave(selected_group);
+ }
+}
+
+bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ uuid_vec_t mUUIDs;
+ getSelectedUUIDs(mUUIDs);
+
+ // Note: can_block and can_delete is used only for one person selected menu
+ // so we don't need to go over all uuids.
+
+ if (item == std::string("can_block"))
+ {
+ const LLUUID& id = mUUIDs.front();
+ return LLAvatarActions::canBlock(id);
+ }
+ else if (item == std::string("can_add"))
+ {
+ // We can add friends if:
+ // - there are selected people
+ // - and there are no friends among selection yet.
+
+ //EXT-7389 - disable for more than 1
+ if(mUUIDs.size() > 1)
+ {
+ return false;
+ }
+
+ bool result = (mUUIDs.size() > 0);
+
+ uuid_vec_t::const_iterator
+ id = mUUIDs.begin(),
+ uuids_end = mUUIDs.end();
+
+ for (;id != uuids_end; ++id)
+ {
+ if ( LLAvatarActions::isFriend(*id) )
+ {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
+ else if (item == std::string("can_delete"))
+ {
+ // We can remove friends if:
+ // - there are selected people
+ // - and there are only friends among selection.
+
+ bool result = (mUUIDs.size() > 0);
+
+ uuid_vec_t::const_iterator
+ id = mUUIDs.begin(),
+ uuids_end = mUUIDs.end();
+
+ for (;id != uuids_end; ++id)
+ {
+ if ( !LLAvatarActions::isFriend(*id) )
+ {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
+ else if (item == std::string("can_call"))
+ {
+ return LLAvatarActions::canCall();
+ }
+ else if (item == std::string("can_show_on_map"))
+ {
+ const LLUUID& id = mUUIDs.front();
+
+ return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id))
+ || gAgent.isGodlike();
+ }
+ else if(item == std::string("can_offer_teleport"))
+ {
+ return LLAvatarActions::canOfferTeleport(mUUIDs);
+ }
+ return false;
+}
+
+bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ const LLUUID& id = getCurSelectedViewModelItem()->getUUID();
+
+ if (item == std::string("is_blocked"))
+ {
+ return LLAvatarActions::isBlocked(id);
+ }
+
+ return false;
+}
+
void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id)
{
LLFolderViewItem* widget = mConversationsWidgets[session_id];
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
index 8e953025bc..5702b88a48 100644
--- a/indra/newview/llimfloatercontainer.h
+++ b/indra/newview/llimfloatercontainer.h
@@ -67,11 +67,11 @@ public:
/*virtual*/ void tabClose();
static LLFloater* getCurrentVoiceFloater();
-
static LLIMFloaterContainer* findInstance();
-
static LLIMFloaterContainer* getInstance();
+ static void onCurrentChannelChanged(const LLUUID& session_id);
+
virtual void setMinimized(BOOL b);
void collapseMessagesPane(bool collapse);
@@ -112,6 +112,16 @@ private:
void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order);
void setSortOrder(const LLConversationSort& order);
+ void getSelectedUUIDs(uuid_vec_t& selected_uuids);
+ const LLConversationItem * getCurSelectedViewModelItem();
+ void doToSelected(const LLSD& userdata);
+ void doToSelectedConversation(const std::string& command);
+ void doToSelectedParticipant(const std::string& command);
+ void doToUsers(const std::string& command, uuid_vec_t selectedIDS);
+ void doToSelectedGroup(const LLSD& userdata);
+ bool checkContextMenuItem(const LLSD& userdata);
+ bool enableContextMenuItem(const LLSD& userdata);
+
LLButton* mExpandCollapseBtn;
LLLayoutPanel* mMessagesPane;
LLLayoutPanel* mConversationsPane;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 72c54e5ce2..139713b96e 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1531,6 +1531,15 @@ LLUIImagePtr LLItemBridge::getIcon() const
return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT);
}
+LLUIImagePtr LLItemBridge::getIconOverlay() const
+{
+ if (getItem() && getItem()->getIsLinkType())
+ {
+ return LLUI::getUIImage("Inv_Link");
+ }
+ return NULL;
+}
+
PermissionMask LLItemBridge::getPermissionMask() const
{
LLViewerInventoryItem* item = getItem();
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 6beccf19ae..b33972167c 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -228,6 +228,7 @@ public:
virtual BOOL isItemCopyable() const;
virtual bool hasChildren() const { return FALSE; }
virtual BOOL isUpToDate() const { return TRUE; }
+ virtual LLUIImagePtr getIconOverlay() const;
LLViewerInventoryItem* getItem() const;
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index a77b57638f..a8d99ad7de 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -172,6 +172,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
p.show_empty_message = mShowEmptyMessage;
p.show_item_link_overlays = mShowItemLinkOverlays;
p.root = NULL;
+ p.options_menu = "menu_inventory.xml";
return LLUICtrlFactory::create<LLFolderView>(p);
}
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 4b35092f2d..b96b486868 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -91,7 +91,8 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd)
: LLIMConversation(llsd),
//mOutputMonitor(NULL),
mSpeakerMgr(NULL),
- mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)
+ mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT),
+ mIsHostSet(false)
{
mIsP2PChat = false;
mIsNearbyChat = true;
@@ -100,6 +101,12 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd)
mSessionID = LLUUID();
}
+//static
+LLNearbyChat* LLNearbyChat::buildFloater(const LLSD& key)
+{
+ LLFloaterReg::getInstance("im_container");
+ return new LLNearbyChat(key);
+}
//virtual
BOOL LLNearbyChat::postBuild()
@@ -304,9 +311,16 @@ void LLNearbyChat::addToHost()
setHost(NULL);
}
}
+
+ mIsHostSet = true;
}
}
+bool LLNearbyChat::isHostSet()
+{
+ return mIsHostSet;
+}
+
// virtual
void LLNearbyChat::onOpen(const LLSD& key)
{
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index 3987212e4c..93168ba96a 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -48,6 +48,8 @@ public:
LLNearbyChat(const LLSD& key = LLSD(LLUUID()));
~LLNearbyChat() {}
+ static LLNearbyChat* buildFloater(const LLSD& key);
+
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
@@ -76,6 +78,8 @@ public:
static void startChat(const char* line);
static void stopChat();
+ bool isHostSet();
+
static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate);
static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);
@@ -117,6 +121,7 @@ private:
LLHandle<LLView> mPopupMenuHandle;
std::vector<LLChat> mMessageArchive;
+ bool mIsHostSet;
};
#endif
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index f3e17ea61b..7834f6d320 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -487,6 +487,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,
if(chat_msg.mText.empty())
return;//don't process empty messages
+ LLFloaterReg::getInstance("im_container");
LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat");
// Build notification data
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 4cd5ecc754..c751550523 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -194,7 +194,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);
- LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);
+ LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLNearbyChat::buildFloater);
LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a993d195b5..6da9296ea3 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3466,7 +3466,8 @@ class LLTogglePanelPeopleTab : public view_listener_t
if ( panel_name == "friends_panel"
|| panel_name == "groups_panel"
- || panel_name == "nearby_panel")
+ || panel_name == "nearby_panel"
+ || panel_name == "blocked_panel")
{
return togglePeoplePanel(panel_name, param);
}
@@ -5490,16 +5491,6 @@ void toggle_debug_menus(void*)
// gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects...");
// }
//
-
-class LLCommunicateBlockList : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD());
- return true;
- }
-};
-
class LLWorldSetHomeLocation : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -8290,9 +8281,6 @@ void initialize_menus()
// Me > Movement
view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
- // Communicate
- view_listener_t::addMenu(new LLCommunicateBlockList(), "Communicate.BlockList");
-
// World menu
view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml
index 12d17e6b37..c9c52e5ce5 100644
--- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml
+++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml
@@ -49,6 +49,7 @@
menu_filename="menu_conversation_log_view.xml"
menu_position="bottomleft"
name="conversation_view_btn"
+ tool_tip="View/sort options"
top="3"
width="31" />
<menu_button
@@ -61,6 +62,7 @@
layout="topleft"
left_pad="2"
name="conversations_gear_btn"
+ tool_tip="Actions on selected person or group"
top="3"
width="31" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
new file mode 100644
index 0000000000..912ff811d9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_conversation_participant"
+ visible="false">
+ <menu_item_call
+ label="Close conversation"
+ layout="topleft"
+ name="close_conversation">
+ <on_click function="Avatar.DoToSelected" parameter="close_conversation"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Open voice conversation"
+ layout="topleft"
+ name="open_voice_conversation">
+ <on_click function="Avatar.DoToSelected" parameter="open_voice_conversation"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Disconnect from voice"
+ layout="topleft"
+ name="disconnect_from_voice">
+ <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/>
+ </menu_item_call>
+ <menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/>
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ name="view_profile">
+ <on_click function="Avatar.DoToSelected" parameter="view_profile"/>
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ layout="topleft"
+ name="im">
+ <on_click function="Avatar.DoToSelected" parameter="im"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Offer teleport"
+ layout="topleft"
+ name="offer_teleport">
+ <on_click function="Avatar.DoToSelected" parameter="offer_teleport"/>
+ <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Voice call"
+ layout="topleft"
+ name="voice_call">
+ <on_click function="Avatar.DoToSelected" parameter="voice_call"/>
+ <on_enable function="Avatar.EnableItem" parameter="can_call" />
+ </menu_item_call>
+ <menu_item_call
+ label="Chat history..."
+ layout="topleft"
+ name="chat_history">
+ <on_click function="Avatar.DoToSelected" parameter="chat_history"/>
+ </menu_item_call>
+ <menu_item_separator layout="topleft" name="separator_chat_history"/>
+ <menu_item_call
+ label="Add friend"
+ layout="topleft"
+ name="add_friend">
+ <on_click function="Avatar.DoToSelected" parameter="add_friend"/>
+ <on_enable function="Avatar.EnableItem" parameter="can_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove friend"
+ layout="topleft"
+ name="remove_friend">
+ <on_click function="Avatar.DoToSelected" parameter="remove_friend" />
+ <on_enable function="Avatar.EnableItem" parameter="can_delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Invite to group..."
+ layout="topleft"
+ name="invite_to_group">
+ <on_click function="Avatar.DoToSelected" parameter="invite_to_group" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" name="separator_invite_to_group"/>
+ <menu_item_call
+ label="Map"
+ layout="topleft"
+ name="map">
+ <on_click function="Avatar.DoToSelected" parameter="map" />
+ <on_enable function="Avatar.EnableItem" parameter="can_show_on_map" />
+ </menu_item_call>
+ <menu_item_call
+ label="Share"
+ layout="topleft"
+ name="share">
+ <on_click function="Avatar.DoToSelected" parameter="share" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="pay">
+ <on_click function="Avatar.DoToSelected" parameter="pay" />
+ </menu_item_call>
+ <menu_item_check
+ label="Block / unblock"
+ layout="topleft"
+ name="block_unblock">
+ <on_click function="Avatar.DoToSelected" parameter="block_unblock" />
+ <on_check function="Avatar.CheckItem" parameter="is_blocked" />
+ <on_enable function="Avatar.EnableItem" parameter="can_block" />
+ </menu_item_check>
+ <menu_item_call
+ label="Group Profile"
+ layout="topleft"
+ name="group_profile">
+ <on_click function="Group.DoToSelected" parameter="group_profile"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Activate Group"
+ layout="topleft"
+ name="activate_group">
+ <on_click function="Group.DoToSelected" parameter="activate_group"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Leave Group"
+ layout="topleft"
+ name="leave_group">
+ <on_click function="Group.DoToSelected" parameter="leave_group"/>
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index aa131035ed..88b30c8272 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -244,16 +244,6 @@
parameter="speak" />
</menu_item_check>
<menu_item_check
- label="Voice settings..."
- name="Nearby Voice">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="voice_controls" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="voice_controls" />
- </menu_item_check>
- <menu_item_check
label="Voice morphing..."
name="ShowVoice"
visibility_control="VoiceMorphingEnabled">
@@ -304,7 +294,8 @@
label="Block List"
name="Block List">
<menu_item_call.on_click
- function="Communicate.BlockList" />
+ function="SideTray.PanelPeopleTab"
+ parameter="blocked_panel" />
</menu_item_call>
</menu>
<menu
diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml
index 8a58eb1ca6..78d4c174d2 100644
--- a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml
@@ -35,6 +35,7 @@
image_name="Conv_toolbar_open_call"
mouse_opaque="true"
name="voice_session_icon"
+ tool_tip="Included a voice conversation"
top="2"
visible="false"
width="20" />
@@ -46,6 +47,7 @@
image_name="Conv_log_inbox"
mouse_opaque="false"
name="unread_ims_icon"
+ tool_tip="Messages arrived while you were logged out"
top="2"
visible="false"
width="20" />
@@ -92,6 +94,7 @@
width="110"/>
<button
name="delete_btn"
+ tool_tip="Remove this entry"
layout="topleft"
follows="top|right"
image_unselected="Conv_toolbar_close"