summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llrender/llfontgl.cpp5
-rw-r--r--indra/llrender/llgl.cpp9
-rw-r--r--indra/llui/llchatentry.cpp9
-rw-r--r--indra/llui/llfloater.cpp2
-rw-r--r--indra/llui/llfloater.h2
-rw-r--r--indra/llui/llfloaterreg.cpp10
-rw-r--r--indra/llui/lllineeditor.cpp8
-rw-r--r--indra/llui/llscrolllistctrl.cpp27
-rw-r--r--indra/llui/llscrolllistctrl.h3
-rw-r--r--indra/llui/lltabcontainer.cpp27
-rw-r--r--indra/llui/lltextbase.cpp30
-rw-r--r--indra/llui/lltexteditor.cpp1
-rw-r--r--indra/llui/lltoolbar.cpp5
-rw-r--r--indra/llui/llurlaction.cpp31
-rw-r--r--indra/llui/llurlaction.h2
-rw-r--r--indra/newview/app_settings/settings.xml44
-rw-r--r--indra/newview/app_settings/settings_per_account.xml22
-rwxr-xr-xindra/newview/llavataractions.cpp2
-rw-r--r--indra/newview/llchathistory.cpp22
-rw-r--r--indra/newview/llchiclet.cpp4
-rw-r--r--indra/newview/llconversationlog.cpp48
-rw-r--r--indra/newview/llconversationlog.h2
-rw-r--r--indra/newview/llconversationloglist.cpp71
-rw-r--r--indra/newview/llconversationmodel.cpp2
-rwxr-xr-xindra/newview/llconversationview.cpp51
-rwxr-xr-xindra/newview/llconversationview.h2
-rw-r--r--indra/newview/lldelayedgestureerror.cpp8
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.cpp29
-rw-r--r--indra/newview/llfloaterimcontainer.cpp132
-rw-r--r--indra/newview/llfloaterimcontainer.h9
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp62
-rw-r--r--indra/newview/llfloaterimnearbychat.h1
-rw-r--r--indra/newview/llfloaterimnearbychathandler.cpp19
-rw-r--r--indra/newview/llfloaterimsession.cpp9
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp198
-rw-r--r--indra/newview/llfloaterimsessiontab.h27
-rwxr-xr-xindra/newview/llfloaterpreference.cpp8
-rw-r--r--indra/newview/llimview.cpp217
-rw-r--r--indra/newview/lllogchat.cpp22
-rw-r--r--indra/newview/lllogchat.h2
-rw-r--r--indra/newview/llnotificationstorage.cpp4
-rw-r--r--indra/newview/llpanelpeople.cpp13
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp118
-rw-r--r--indra/newview/llpanelpeoplemenus.h20
-rw-r--r--indra/newview/llpersistentnotificationstorage.cpp4
-rw-r--r--indra/newview/llspeakers.cpp28
-rw-r--r--indra/newview/llspeakers.h1
-rw-r--r--indra/newview/llviewerdisplay.cpp1
-rwxr-xr-xindra/newview/llviewermessage.cpp113
-rwxr-xr-xindra/newview/llviewerwindow.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp92
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvoicevivox.cpp69
-rw-r--r--indra/newview/llvoicevivox.h1
-rw-r--r--indra/newview/llworldmapview.cpp3
-rw-r--r--indra/newview/skins/default/textures/icons/collapse_to_one_line.pngbin0 -> 538 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/expand_one_liner.pngbin0 -> 545 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml149
-rw-r--r--indra/newview/skins/default/xui/en/menu_conversation.xml9
-rw-r--r--indra/newview/skins/default/xui/en/menu_im_conversation.xml7
-rw-r--r--indra/newview/skins/default/xui/en/menu_object_icon.xml18
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby.xml40
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml14
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_agent.xml17
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_group.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_objectim.xml2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml1
70 files changed, 1364 insertions, 566 deletions
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 647512eb2e..8772779645 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -599,6 +599,11 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
+
+ if (NULL == fgi)
+ {
+ return 0;
+ }
}
// account for glyphs that run beyond the starting point for the next glyphs
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 09e451c62a..fd668f2d34 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -597,11 +597,6 @@ bool LLGLManager::initGL()
if (mGLVendor.substr(0,4) == "ATI ")
{
mGLVendorShort = "ATI";
- BOOL mobile = FALSE;
- if (mGLRenderer.find("MOBILITY") != std::string::npos)
- {
- mobile = TRUE;
- }
mIsATI = TRUE;
#if LL_WINDOWS && !LL_MESA_HEADLESS
@@ -1489,9 +1484,7 @@ void assert_glerror()
void clear_glerror()
{
- // Create or update texture to be used with this data
- GLenum error;
- error = glGetError();
+ glGetError();
}
///////////////////////////////////////////////////////////////
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index 8e9c6555c3..9e48dcde7e 100644
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -169,6 +169,15 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
BOOL handled = FALSE;
+ // In the case of a chat entry, pressing RETURN when something is selected
+ // should NOT erase the selection (unlike a notecard, for example)
+ if (key == KEY_RETURN)
+ {
+ endOfDoc();
+ startSelection();
+ endSelection();
+ }
+
LLTextEditor::handleSpecialKey(key, mask);
switch(key)
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 27dd7f5b32..09e27a264a 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1621,7 +1621,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
-void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
+void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLMultiFloater* hostp = getHost();
if (hostp)
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index cb5bf28db3..4dba1e645f 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -305,7 +305,7 @@ public:
/*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
void setFrontmost(BOOL take_focus = TRUE);
- virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE);
+ virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
// Defaults to false.
virtual BOOL canSaveAs() const { return FALSE; }
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index c20d863612..1cdddf0d5b 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -488,12 +488,12 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
{
host->setMinimized(FALSE);
instance->openFloater(key);
- instance->setVisibleAndFrontmost();
+ instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->getVisible())
{
instance->openFloater(key);
- instance->setVisibleAndFrontmost();
+ instance->setVisibleAndFrontmost(true, key);
instance->setFocus(TRUE);
}
else
@@ -506,16 +506,16 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
if (instance->isMinimized())
{
instance->setMinimized(FALSE);
- instance->setVisibleAndFrontmost();
+ instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->isShown())
{
instance->openFloater(key);
- instance->setVisibleAndFrontmost();
+ instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->isFrontmost())
{
- instance->setVisibleAndFrontmost();
+ instance->setVisibleAndFrontmost(true, key);
}
else
{
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 2e64be89fa..6976b06a92 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -202,6 +202,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
LLLineEditor::~LLLineEditor()
{
mCommitOnFocusLost = FALSE;
+
+ // Make sure no context menu linger around once the widget is deleted
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if (menu)
+ {
+ menu->hide();
+ }
+ setContextMenu(NULL);
// calls onCommit() while LLLineEditor still valid
gFocusMgr.releaseFocusIfNeeded( this );
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 8b9fb47d5c..7f04c92b27 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1801,6 +1801,9 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
// (N.B. callbacks don't take const refs as id is local scope)
bool is_group = (mContextMenuType == MENU_GROUP);
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Url.ShowProfile", boost::bind(&LLScrollListCtrl::showProfile, id, is_group));
+ registrar.add("Url.SendIM", boost::bind(&LLScrollListCtrl::sendIM, id));
+ registrar.add("Url.AddFriend", boost::bind(&LLScrollListCtrl::addFriend, id));
registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group));
registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group));
registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group));
@@ -1821,11 +1824,33 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
return FALSE;
}
-void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
+void LLScrollListCtrl::showProfile(std::string id, bool is_group)
{
// show the resident's profile or the group profile
std::string sltype = is_group ? "group" : "agent";
std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
+ LLUrlAction::showProfile(slurl);
+}
+
+void LLScrollListCtrl::sendIM(std::string id)
+{
+ // send im to the resident
+ std::string slurl = "secondlife:///app/agent/" + id + "/about";
+ LLUrlAction::sendIM(slurl);
+}
+
+void LLScrollListCtrl::addFriend(std::string id)
+{
+ // add resident to friends list
+ std::string slurl = "secondlife:///app/agent/" + id + "/about";
+ LLUrlAction::addFriend(slurl);
+}
+
+void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
+{
+ // open the resident's details or the group details
+ std::string sltype = is_group ? "group" : "agent";
+ std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
LLUrlAction::clickAction(slurl);
}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 38450b6313..8fa06cc499 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -430,6 +430,9 @@ private:
BOOL setSort(S32 column, BOOL ascending);
S32 getLinesPerPage();
+ static void showProfile(std::string id, bool is_group);
+ static void sendIM(std::string id);
+ static void addFriend(std::string id);
static void showNameDetails(std::string id, bool is_group);
static void copyNameToClipboard(std::string id, bool is_group);
static void copySLURLToClipboard(std::string id, bool is_group);
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 0c43a571b8..6f895ed939 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1483,16 +1483,22 @@ BOOL LLTabContainer::setTab(S32 which)
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
- if (!tuple)
- continue;
BOOL is_selected = ( tuple == selected_tuple );
- tuple->mButton->setUseEllipses(mUseTabEllipses);
- tuple->mButton->setHAlign(mFontHalign);
- tuple->mTabPanel->setVisible( is_selected );
-// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
- tuple->mButton->setToggleState( is_selected );
- // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
- tuple->mButton->setTabStop( is_selected );
+
+ // Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list
+ if (tuple->mButton)
+ {
+ tuple->mButton->setUseEllipses(mUseTabEllipses);
+ tuple->mButton->setHAlign(mFontHalign);
+ tuple->mButton->setToggleState( is_selected );
+ // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
+ tuple->mButton->setTabStop( is_selected );
+ }
+ if (tuple->mTabPanel)
+ {
+ tuple->mTabPanel->setVisible( is_selected );
+ //tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
+ }
if (is_selected)
{
@@ -1563,8 +1569,7 @@ BOOL LLTabContainer::selectTabByName(const std::string& name)
LLPanel* panel = getPanelByName(name);
if (!panel)
{
- llwarns << "LLTabContainer::selectTabByName("
- << name << ") failed" << llendl;
+ llwarns << "LLTabContainer::selectTabByName(" << name << ") failed" << llendl;
return FALSE;
}
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 4bb819a7f6..270d5294f9 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -359,7 +359,6 @@ void LLTextBase::drawSelectionBackground()
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
- LLRect selection_rect = mVisibleTextRect;
// Skip through the lines we aren't drawing.
LLRect content_display_rect = getVisibleDocumentRect();
@@ -1086,7 +1085,14 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
+ //Don't start triple click timer if user have clicked on scrollbar
+ mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
+ if (x >= mVisibleTextRect.mLeft && x <= mVisibleTextRect.mRight
+ && y >= mVisibleTextRect.mBottom && y <= mVisibleTextRect.mTop)
+ {
+ mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
+ }
+
LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
{
@@ -1912,6 +1918,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));
+ registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
@@ -2330,7 +2337,6 @@ const LLWString& LLTextBase::getWText() const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
{
// Figure out which line we're nearest to.
- LLRect visible_region = getVisibleDocumentRect();
LLRect doc_rect = mDocumentView->getRect();
S32 doc_y = local_y - doc_rect.mBottom;
@@ -3195,7 +3201,23 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0)
? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE
: LLFontGL::ONLY_WORD_BOUNDARIES;
- S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
+
+
+ LLWString offsetString(text.c_str() + segment_offset + mStart);
+
+ if(getLength() < segment_offset + mStart)
+ {
+ llerrs << "getLength() < segment_offset + mStart\t getLength()\t" << getLength() << "\tsegment_offset:\t"
+ << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << "\tmax_chars\t" << max_chars << llendl;
+ }
+
+ if(offsetString.length() + 1 < max_chars)
+ {
+ llerrs << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetString.length():\t" << offsetString.length()
+ << getLength() << "\tsegment_offset:\t" << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << llendl;
+ }
+
+ S32 num_chars = mStyle->getFont()->maxDrawableChars(offsetString.c_str(),
(F32)num_pixels,
max_chars,
word_wrap_style);
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 2f120479d9..d5e08fa29b 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2515,7 +2515,6 @@ void LLTextEditor::updateSegments()
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
clearSegments();
- segment_set_t::iterator insert_it = mSegments.begin();
for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
{
insertSegment(*list_it);
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index b9256dd890..1c74395c66 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -1059,10 +1059,9 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// Convert drag position into insert position and rank
if (!isReadOnly() && handled && !drop)
{
- LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
- LLAssetType::EType type = inv_item->getType();
- if (type == LLAssetType::AT_WIDGET)
+ if (cargo_type == DAD_WIDGET)
{
+ LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
LLCommandId dragged_command(inv_item->getUUID());
int orig_rank = getRankFromPosition(dragged_command);
mDragRank = getRankFromPosition(x, y);
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index fd872eca4b..f51aeaec13 100644
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -24,7 +24,6 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
#include "linden_common.h"
#include "llurlaction.h"
@@ -32,6 +31,7 @@
#include "llwindow.h"
#include "llurlregistry.h"
+
// global state for the callback functions
LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
@@ -158,16 +158,33 @@ void LLUrlAction::showProfile(std::string url)
}
}
-void LLUrlAction::sendIM(std::string url)
+std::string LLUrlAction::getUserID(std::string url)
{
LLURI uri(url);
LLSD path_array = uri.pathArray();
+ std::string id_str;
if (path_array.size() == 4)
{
- std::string id_str = path_array.get(2).asString();
- if (LLUUID::validate(id_str))
- {
- executeSLURL("secondlife:///app/agent/" + id_str + "/im");
- }
+ id_str = path_array.get(2).asString();
}
+ return id_str;
}
+
+void LLUrlAction::sendIM(std::string url)
+{
+ std::string id_str = getUserID(url);
+ if (LLUUID::validate(id_str))
+ {
+ executeSLURL("secondlife:///app/agent/" + id_str + "/im");
+ }
+}
+
+void LLUrlAction::addFriend(std::string url)
+{
+ std::string id_str = getUserID(url);
+ if (LLUUID::validate(id_str))
+ {
+ executeSLURL("secondlife:///app/agent/" + id_str + "/requestfriend");
+ }
+}
+
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index f5f2ceba72..e31cd71a20 100644
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -76,7 +76,9 @@ public:
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url);
+ static std::string getUserID(std::string url);
static void sendIM(std::string url);
+ static void addFriend(std::string url);
/// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t;
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 79376f7467..4c305e1d60 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1584,6 +1584,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>ChatLoadGroupMaxMembers</key>
+ <map>
+ <key>Comment</key>
+ <string>Max number of active members we'll show up for an unresponsive group</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <real>100</real>
+ </map>
+ <key>ChatLoadGroupTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Time we give the server to send group participants before we hit the server for group info (seconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
<key>ChatOnlineNotification</key>
<map>
<key>Comment</key>
@@ -1694,17 +1716,6 @@
<key>Value</key>
<integer>131073</integer>
</map>
- <key>NearbyChatIsNotTornOff</key>
- <map>
- <key>Comment</key>
- <string>saving torn-off state of the nearby chat between sessions</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>CloseChatOnReturn</key>
<map>
<key>Comment</key>
@@ -4260,6 +4271,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>IMShowContentPanel</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Toolbar and Body Panels</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>IgnoreAllNotifications</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 363713f2f4..590f41283b 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -281,6 +281,28 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>NearbyChatIsNotTornOff</key>
+ <map>
+ <key>Comment</key>
+ <string>saving torn-off state of the nearby chat between sessions</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>NearbyChatIsNotCollapsed</key>
+ <map>
+ <key>Comment</key>
+ <string>Saving expanded/collapsed state of the nearby chat between sessions</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ShowFavoritesOnLogin</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index ce063a9887..b513a52ff7 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -193,7 +193,7 @@ static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
// static
void LLAvatarActions::startIM(const LLUUID& id)
{
- if (id.isNull())
+ if (id.isNull() || gAgent.getID() == id)
return;
LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2));
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index c4f63d9256..53926c1fef 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -58,7 +58,7 @@
#include "llworld.h"
#include "lluiconstants.h"
#include "llstring.h"
-
+#include "llurlaction.h"
#include "llviewercontrol.h"
static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
@@ -156,6 +156,17 @@ public:
LLFloaterSidePanelContainer::showPanel("people", "panel_people",
LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));
}
+ else if (level == "map")
+ {
+ std::string url = "secondlife://" + mObjectData["slurl"].asString();
+ LLUrlAction::showLocationOnMap(url);
+ }
+ else if (level == "teleport")
+ {
+ std::string url = "secondlife://" + mObjectData["slurl"].asString();
+ LLUrlAction::teleportToLocation(url);
+ }
+
}
void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
@@ -820,6 +831,15 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
body_message_params.font.style = "ITALIC";
}
+ if(chat.mChatType == CHAT_TYPE_WHISPER)
+ {
+ body_message_params.font.style = "ITALIC";
+ }
+ else if(chat.mChatType == CHAT_TYPE_SHOUT)
+ {
+ body_message_params.font.style = "BOLD";
+ }
+
bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;
// We graying out chat history by graying out messages that contains full date in a time string
if (message_from_log)
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 3dbb43c657..43c6b558bc 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -174,6 +174,7 @@ void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
if("close all" == action)
{
LLNotificationWellWindow::getInstance()->closeAll();
+ LLIMWellWindow::getInstance()->closeAll();
}
}
@@ -427,6 +428,8 @@ LLChicletPanel::~LLChicletPanel()
void LLChicletPanel::onMessageCountChanged(const LLSD& data)
{
+ // *TODO : we either suppress this method or return a value. Right now, it servers no purpose.
+ /*
LLUUID session_id = data["session_id"].asUUID();
S32 unread = data["participant_unread"].asInteger();
@@ -435,6 +438,7 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data)
{
unread = 0;
}
+ */
}
void LLChicletPanel::objectChicletCallback(const LLSD& data)
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 4be169e267..7883e4cb89 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -28,9 +28,11 @@
#include "llagent.h"
#include "llavatarnamecache.h"
#include "llconversationlog.h"
+#include "lldiriterator.h"
#include "llnotificationsutil.h"
#include "lltrans.h"
+#include <boost/foreach.hpp>
#include "boost/lexical_cast.hpp"
const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec
@@ -192,14 +194,17 @@ LLConversationLog::LLConversationLog() :
mAvatarNameCacheConnection(),
mLoggingEnabled(false)
{
- LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get();
- S32 log_mode = keep_log_ctrlp->getValue();
- keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
- if (log_mode > 0)
+ if(gSavedPerAccountSettings.controlExists("KeepConversationLogTranscripts"))
{
- loadFromFile(getFileName());
+ LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get();
+ S32 log_mode = keep_log_ctrlp->getValue();
+ keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
+ if (log_mode > 0)
+ {
+ loadFromFile(getFileName());
- enableLogging(log_mode);
+ enableLogging(log_mode);
+ }
}
}
@@ -380,6 +385,36 @@ void LLConversationLog::cache()
}
}
+void LLConversationLog::getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs)
+{
+ // get Users log directory
+ std::string dirname = gDirUtilp->getPerAccountChatLogsDir();
+
+ // add final OS dependent delimiter
+ dirname += gDirUtilp->getDirDelimiter();
+
+ // create search pattern
+ std::string pattern = "conversation.log.backup*";
+
+ LLDirIterator iter(dirname, pattern);
+ std::string filename;
+ while (iter.next(filename))
+ {
+ list_of_backup_logs.push_back(gDirUtilp->add(dirname, filename));
+ }
+}
+
+void LLConversationLog::deleteBackupLogs()
+{
+ std::vector<std::string> backup_logs;
+ getListOfBackupLogs(backup_logs);
+
+ BOOST_FOREACH(const std::string& fullpath, backup_logs)
+ {
+ LLFile::remove(fullpath);
+ }
+}
+
bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory)
{
@@ -575,5 +610,6 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD&
mConversations.clear();
notifyObservers();
cache();
+ deleteBackupLogs();
}
}
diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h
index 58e698de25..265b1f0ef0 100644
--- a/indra/newview/llconversationlog.h
+++ b/indra/newview/llconversationlog.h
@@ -138,6 +138,8 @@ public:
*/
void cache();
bool moveLog(const std::string &originDirectory, const std::string &targetDirectory);
+ void getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs);
+ void deleteBackupLogs();
void onClearLog();
void onClearLogResponse(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp
index 96b225b841..5ab108b39f 100644
--- a/indra/newview/llconversationloglist.cpp
+++ b/indra/newview/llconversationloglist.cpp
@@ -198,6 +198,8 @@ void LLConversationLogList::refresh()
void LLConversationLogList::rebuildList()
{
+ const LLConversation * selected_conversationp = getSelectedConversation();
+
clear();
bool have_filter = !mNameFilter.empty();
@@ -214,7 +216,12 @@ void LLConversationLogList::rebuildList()
addNewItem(&*iter);
}
-
+
+ // try to restore selection of item
+ if (NULL != selected_conversationp)
+ {
+ selectItemByUUID(selected_conversationp->getSessionID());
+ }
bool logging_enabled = log_instance.getIsLoggingEnabled();
bool log_empty = log_instance.isLogEmpty();
@@ -238,8 +245,16 @@ void LLConversationLogList::rebuildList()
void LLConversationLogList::onCustomAction(const LLSD& userdata)
{
+ const LLConversation * selected_conversationp = getSelectedConversation();
+
+ if (NULL == selected_conversationp)
+ {
+ return;
+ }
+
const std::string command_name = userdata.asString();
- const LLUUID& selected_id = getSelectedConversation()->getParticipantID();
+ const LLUUID& selected_conversation_participant_id = selected_conversationp->getParticipantID();
+ const LLUUID& selected_conversation_session_id = selected_conversationp->getSessionID();
LLIMModel::LLIMSession::SType stype = getSelectedSessionType();
if ("im" == command_name)
@@ -247,11 +262,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype)
{
case LLIMModel::LLIMSession::P2P_SESSION:
- LLAvatarActions::startIM(selected_id);
+ LLAvatarActions::startIM(selected_conversation_participant_id);
break;
case LLIMModel::LLIMSession::GROUP_SESSION:
- LLGroupActions::startIM(getSelectedConversation()->getSessionID());
+ LLGroupActions::startIM(selected_conversation_session_id);
break;
default:
@@ -263,11 +278,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype)
{
case LLIMModel::LLIMSession::P2P_SESSION:
- LLAvatarActions::startCall(selected_id);
+ LLAvatarActions::startCall(selected_conversation_participant_id);
break;
case LLIMModel::LLIMSession::GROUP_SESSION:
- LLGroupActions::startCall(getSelectedConversation()->getSessionID());
+ LLGroupActions::startCall(selected_conversation_session_id);
break;
default:
@@ -279,11 +294,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype)
{
case LLIMModel::LLIMSession::P2P_SESSION:
- LLAvatarActions::showProfile(selected_id);
+ LLAvatarActions::showProfile(selected_conversation_participant_id);
break;
case LLIMModel::LLIMSession::GROUP_SESSION:
- LLGroupActions::show(getSelectedConversation()->getSessionID());
+ LLGroupActions::show(selected_conversation_session_id);
break;
default:
@@ -292,52 +307,53 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
}
else if ("chat_history" == command_name)
{
- const LLUUID& session_id = getSelectedConversation()->getSessionID();
- LLFloaterReg::showInstance("preview_conversation", session_id, true);
+ LLFloaterReg::showInstance("preview_conversation", selected_conversation_session_id, true);
}
else if ("offer_teleport" == command_name)
{
- LLAvatarActions::offerTeleport(selected_id);
+ LLAvatarActions::offerTeleport(selected_conversation_participant_id);
}
else if("add_friend" == command_name)
{
- if (!LLAvatarActions::isFriend(selected_id))
+ if (!LLAvatarActions::isFriend(selected_conversation_participant_id))
{
- LLAvatarActions::requestFriendshipDialog(selected_id);
+ LLAvatarActions::requestFriendshipDialog(selected_conversation_participant_id);
}
}
else if("remove_friend" == command_name)
{
- if (LLAvatarActions::isFriend(selected_id))
+ if (LLAvatarActions::isFriend(selected_conversation_participant_id))
{
- LLAvatarActions::removeFriendDialog(selected_id);
+ LLAvatarActions::removeFriendDialog(selected_conversation_participant_id);
}
}
else if ("invite_to_group" == command_name)
{
- LLAvatarActions::inviteToGroup(selected_id);
+ LLAvatarActions::inviteToGroup(selected_conversation_participant_id);
}
else if ("show_on_map" == command_name)
{
- LLAvatarActions::showOnMap(selected_id);
+ LLAvatarActions::showOnMap(selected_conversation_participant_id);
}
else if ("share" == command_name)
{
- LLAvatarActions::share(selected_id);
+ LLAvatarActions::share(selected_conversation_participant_id);
}
else if ("pay" == command_name)
{
- LLAvatarActions::pay(selected_id);
+ LLAvatarActions::pay(selected_conversation_participant_id);
}
else if ("block" == command_name)
{
- LLAvatarActions::toggleBlock(selected_id);
+ LLAvatarActions::toggleBlock(selected_conversation_participant_id);
}
}
bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
{
- if (numSelected() != 1)
+ const LLConversation * selected_conversationp = getSelectedConversation();
+
+ if (NULL == selected_conversationp || numSelected() > 1)
{
return false;
}
@@ -345,7 +361,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
const std::string command_name = userdata.asString();
LLIMModel::LLIMSession::SType stype = getSelectedSessionType();
- const LLUUID& selected_id = getSelectedConversation()->getParticipantID();
+ const LLUUID& selected_id = selected_conversationp->getParticipantID();
bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype;
bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype;
@@ -374,7 +390,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
{
return is_p2p && LLAvatarActions::canOfferTeleport(selected_id);
}
- else if ("can_show_on_map")
+ else if ("can_show_on_map" == command_name)
{
return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike());
}
@@ -384,9 +400,16 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
bool LLConversationLogList::isActionChecked(const LLSD& userdata)
{
+ const LLConversation * selected_conversationp = getSelectedConversation();
+
+ if (NULL == selected_conversationp)
+ {
+ return false;
+ }
+
const std::string command_name = userdata.asString();
- const LLUUID& selected_id = getSelectedConversation()->getParticipantID();
+ const LLUUID& selected_id = selected_conversationp->getParticipantID();
bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType();
if ("is_blocked" == command_name)
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 009fce0a92..c74ce24872 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -139,6 +139,8 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group"));
+ if (static_cast<LLConversationItem*>(mParent)->getType() == CONV_SESSION_NEARBY)
+ items.push_back(std::string("zoom_in"));
items.push_back(std::string("map"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 74b348cd81..956abcd586 100755
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -104,6 +104,15 @@ LLConversationViewSession::~LLConversationViewSession()
void LLConversationViewSession::setFlashState(bool flash_state)
{
+ if (flash_state && !mFlashStateOn)
+ {
+ // flash chat toolbar button if scrolled out of sight (because flashing will not be visible)
+ if (mContainer->isScrolledOutOfSight(this))
+ {
+ gToolBarView->flashCommand(LLCommandId("chat"), true);
+ }
+ }
+
mFlashStateOn = flash_state;
mFlashStarted = false;
mFlashTimer->stopFlashing();
@@ -115,12 +124,6 @@ void LLConversationViewSession::startFlashing()
{
mFlashStarted = true;
mFlashTimer->startFlashing();
-
- // flash chat toolbar button if scrolled out of sight (because flashing will not be visible)
- if (mContainer->isScrolledOutOfSight(this))
- {
- gToolBarView->flashCommand(LLCommandId("chat"), true);
- }
}
}
@@ -254,20 +257,38 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )
//This node (conversation) was selected and a child (participant) was not
if(result && getRoot())
{
- if(getRoot()->getCurSelectedItem() == this)
- {
- LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
- LLUUID session_id = item? item->getUUID() : LLUUID();
+ selectConversationItem();
+ }
- LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
- im_container->flashConversationItemWidget(session_id,false);
- im_container->selectConversationPair(session_id, false);
- im_container->collapseMessagesPane(false);
- }
+ return result;
+}
+
+BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask )
+{
+ BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask);
+
+ if(result)
+ {
+ selectConversationItem();
}
+
return result;
}
+void LLConversationViewSession::selectConversationItem()
+{
+ if(getRoot()->getCurSelectedItem() == this)
+ {
+ LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
+ LLUUID session_id = item? item->getUUID() : LLUUID();
+
+ LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+ im_container->flashConversationItemWidget(session_id,false);
+ im_container->selectConversationPair(session_id, false);
+ im_container->collapseMessagesPane(false);
+ }
+}
+
// virtual
S32 LLConversationViewSession::arrange(S32* width, S32* height)
{
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index 76d3d079ea..3eb2e63792 100755
--- a/indra/newview/llconversationview.h
+++ b/indra/newview/llconversationview.h
@@ -68,6 +68,7 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
+ /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ S32 arrange(S32* width, S32* height);
@@ -90,6 +91,7 @@ private:
void onCurrentVoiceSessionChanged(const LLUUID& session_id);
void startFlashing();
+ void selectConversationItem();
LLPanel* mItemPanel;
LLPanel* mCallIconLayoutPanel;
diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp
index 80e7c9f1b2..ef1b644ad4 100644
--- a/indra/newview/lldelayedgestureerror.cpp
+++ b/indra/newview/lldelayedgestureerror.cpp
@@ -113,9 +113,11 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
}
}
-
- LLNotificationsUtil::add(ent.mNotifyName, args);
-
+ if(!LLApp::isQuitting())
+ {
+ LLNotificationsUtil::add(ent.mNotifyName, args);
+ }
+
return true;
}
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 22f35752bd..82affcf068 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.cpp
+++ b/indra/newview/lldonotdisturbnotificationstorage.cpp
@@ -33,6 +33,7 @@
#include "lldir.h"
#include "llerror.h"
#include "llfloaterreg.h"
+#include "llimview.h"
#include "llnotifications.h"
#include "llnotificationhandler.h"
#include "llnotificationstorage.h"
@@ -131,6 +132,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
{
LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS);
+ LL_INFOS("LLDoNotDisturbNotificationStorage") << "start loading notifications" << LL_ENDL;
+
LLSD input;
if (!readNotifications(input) ||input.isUndefined())
{
@@ -145,6 +148,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
LLNotifications& instance = LLNotifications::instance();
bool imToastExists = false;
+ bool group_ad_hoc_toast_exists = false;
+ S32 toastSessionType;
bool offerExists = false;
for (LLSD::array_const_iterator notification_it = data.beginArray();
@@ -158,7 +163,20 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
if(notificationName == toastName)
{
- imToastExists = true;
+ toastSessionType = notification_params["payload"]["SESSION_TYPE"];
+ if(toastSessionType == LLIMModel::LLIMSession::P2P_SESSION)
+ {
+ imToastExists = true;
+ }
+ //Don't add group/ad-hoc messages to the notification system because
+ //this means the group/ad-hoc session has to be re-created
+ else if(toastSessionType == LLIMModel::LLIMSession::GROUP_SESSION
+ || toastSessionType == LLIMModel::LLIMSession::ADHOC_SESSION)
+ {
+ //Just allows opening the conversation log for group/ad-hoc messages upon startup
+ group_ad_hoc_toast_exists = true;
+ continue;
+ }
}
else if(notificationName == offerName)
{
@@ -197,13 +215,20 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
LLFloaterReg::showInstance("im_container");
}
- if(imToastExists || offerExists)
+ if(group_ad_hoc_toast_exists)
+ {
+ LLFloaterReg::showInstance("conversation");
+ }
+
+ if(imToastExists || group_ad_hoc_toast_exists || offerExists)
{
make_ui_sound_deferred("UISndNewIncomingIMSession");
}
//writes out empty .xml file (since LLCommunicationChannel::mHistory is empty)
saveNotifications();
+
+ LL_INFOS("LLDoNotDisturbNotificationStorage") << "finished loading notifications" << LL_ENDL;
}
void LLDoNotDisturbNotificationStorage::updateNotifications()
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 413707baae..7296ec3ced 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -53,6 +53,7 @@
#include "llcallbacklist.h"
#include "llworld.h"
#include "llsdserialize.h"
+#include "llviewerobjectlist.h"
//
// LLFloaterIMContainer
@@ -62,8 +63,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mExpandCollapseBtn(NULL),
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
- mInitialized(false),
- mIsFirstLaunch(false)
+ mInitialized(false)
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@@ -114,6 +114,7 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str
void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{
selectConversationPair(session_id, true);
+ collapseMessagesPane(false);
}
void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id)
@@ -225,10 +226,11 @@ BOOL LLFloaterIMContainer::postBuild()
childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this));
collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
- collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"));
+ collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"), false);
LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false));
mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this));
- if (! mMessagesPane->isCollapsed())
+
+ if (! mMessagesPane->isCollapsed() && ! mConversationsPane->isCollapsed())
{
S32 conversations_panel_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth");
LLRect conversations_panel_rect = mConversationsPane->getRect();
@@ -243,7 +245,6 @@ BOOL LLFloaterIMContainer::postBuild()
mGeneralTitle = getTitle();
mInitialized = true;
- mIsFirstLaunch = true;
// Add callbacks:
// We'll take care of view updates on idle
@@ -278,12 +279,6 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLUUID session_id = floaterp->getKey();
- // Make sure the message panel is open when adding a floater or it stays mysteriously hidden
- if (!mIsFirstLaunch)
- {
- collapseMessagesPane(false);
- }
-
// Add the floater
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
@@ -631,6 +626,12 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLMultiFloater::setVisible(visible);
}
+void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
+{
+ LLMultiFloater::setVisibleAndFrontmost(take_focus, key);
+ selectConversationPair(getSelectedSession(), false, take_focus);
+}
+
void LLFloaterIMContainer::updateResizeLimits()
{
LLMultiFloater::updateResizeLimits();
@@ -644,8 +645,6 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
return;
}
- mIsFirstLaunch = false;
-
// Save current width of panels before collapsing/expanding right pane.
S32 conv_pane_width = mConversationsPane->getRect().getWidth();
S32 msg_pane_width = mMessagesPane->getRect().getWidth();
@@ -667,7 +666,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
// Make sure layout is updated before resizing conversation pane.
mConversationsStack->updateLayout();
- updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth"));
+ reshapeFloaterAndSetResizeLimits(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth"));
if (!collapse)
{
@@ -676,7 +675,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
}
}
-void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
+void LLFloaterIMContainer::collapseConversationsPane(bool collapse, bool save_is_allowed /*=true*/)
{
if (mConversationsPane->isCollapsed() == collapse)
{
@@ -690,7 +689,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
// Save current width of Conversation panel before collapsing/expanding right pane.
S32 conv_pane_width = mConversationsPane->getRect().getWidth();
- if (collapse)
+ if (collapse && save_is_allowed)
{
// Save the conversations pane width before collapsing it.
gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width);
@@ -700,10 +699,18 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
}
mConversationsStack->collapsePanel(mConversationsPane, collapse);
+ if (!collapse)
+ {
+ // Make sure layout is updated before resizing conversation pane.
+ mConversationsStack->updateLayout();
+ // Restore conversation's pane previous width.
+ mConversationsPane->setTargetDim(gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"));
+ }
- S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim();
+ S32 delta_width =
+ gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim();
- updateState(collapse, delta_width);
+ reshapeFloaterAndSetResizeLimits(collapse, delta_width);
for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
widget_it != mConversationsWidgets.end(); ++widget_it)
@@ -723,21 +730,20 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
}
}
-void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width)
+void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width)
{
LLRect floater_rect = getRect();
floater_rect.mRight += ((collapse ? -1 : 1) * delta_width);
// Set by_user = true so that reshaped rect is saved in user_settings.
setShape(floater_rect, true);
-
updateResizeLimits();
- bool is_left_pane_expanded = !mConversationsPane->isCollapsed();
- bool is_right_pane_expanded = !mMessagesPane->isCollapsed();
+ bool at_least_one_panel_is_expanded =
+ ! (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed());
- setCanResize(is_left_pane_expanded || is_right_pane_expanded);
- setCanMinimize(is_left_pane_expanded || is_right_pane_expanded);
+ setCanResize(at_least_one_panel_is_expanded);
+ setCanMinimize(at_least_one_panel_is_expanded);
assignResizeLimits();
@@ -758,21 +764,17 @@ void LLFloaterIMContainer::assignResizeLimits()
// between the panels are merged into one
S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3);
S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH;
- S32 conv_pane_current_width = is_msg_pane_expanded
- ? (is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim())
- : (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim());
+ S32 conv_pane_target_width = is_conv_pane_expanded?
+ (is_msg_pane_expanded?
+ mConversationsPane->getRect().getWidth()
+ : mConversationsPane->getExpandedMinDim())
+ : mConversationsPane->getMinDim();
S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;
- S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders;
-
- if (is_conv_pane_expanded)
- {
- // Save the conversations pane width.
- gSavedPerAccountSettings.setS32(
- "ConversationsListPaneWidth",
- mConversationsPane->getRect().getWidth());
- }
+ S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders;
setResizeLimits(new_min_width, getMinHeight());
+
+ mConversationsStack->updateLayout();
}
void LLFloaterIMContainer::onAddButtonClicked()
@@ -1031,6 +1033,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
{
LLAvatarActions::inviteToGroup(userID);
}
+ else if ("zoom_in" == command)
+ {
+ handle_zoom_to_object(userID);
+ }
else if ("map" == command)
{
LLAvatarActions::showOnMap(userID);
@@ -1252,6 +1258,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return LLAvatarActions::canCall();
}
+ else if ("can_zoom_in" == item)
+ {
+ return is_single_select && gObjectList.findObject(single_id);
+ }
else if ("can_show_on_map" == item)
{
return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false);
@@ -1325,6 +1335,12 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id)
{
setVisibleAndFrontmost(false);
selectConversationPair(session_id, true);
+
+ LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
+ if (session_floater)
+ {
+ session_floater->restoreFloater();
+ }
}
void LLFloaterIMContainer::clearAllFlashStates()
@@ -1400,6 +1416,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
// Switch to the conversation floater that is being selected
selectFloater(session_floater);
}
+ else
+ {
+ showStub(true);
+ }
}
// Set the focus on the selected floater
@@ -1410,7 +1430,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
session_floater->setMinimized(is_minimized);
}
}
-
+ flashConversationItemWidget(session_id,false);
return handled;
}
@@ -1878,6 +1898,9 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve
{
llassert(conversation_item_widget != NULL);
+ // make sure the widget is actually in the right spot first
+ mConversationsRoot->arrange(NULL, NULL);
+
// check whether the widget is in the visible portion of the scroll container
LLRect widget_rect;
conversation_item_widget->localRectToOtherView(conversation_item_widget->getLocalRect(), &widget_rect, mConversationsRoot);
@@ -1905,7 +1928,19 @@ BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )
return TRUE;
}
-bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
+bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected)
+{
+ bool selectedAdjacentConversation = selectNextorPreviousConversation(true, focus_selected);
+
+ if(!selectedAdjacentConversation)
+ {
+ selectedAdjacentConversation = selectNextorPreviousConversation(false, focus_selected);
+ }
+
+ return selectedAdjacentConversation;
+}
+
+bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next, bool focus_selected)
{
if (mConversationsWidgets.size() > 1)
{
@@ -1926,12 +1961,7 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem());
if (vmi)
{
- selectConversationPair(vmi->getUUID(), true);
- LLFloater* floaterp = get_ptr_in_map(mSessions, getSelectedSession());
- if(floaterp && !floaterp->isTornOff())
- {
- setFocus(TRUE);
- }
+ selectConversationPair(vmi->getUUID(), true, focus_selected);
return true;
}
}
@@ -1942,10 +1972,13 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
void LLFloaterIMContainer::expandConversation()
{
- LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession()));
- if (widget)
+ if(!mConversationsPane->isCollapsed())
{
- widget->setOpen(!widget->isOpen());
+ LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession()));
+ if (widget)
+ {
+ widget->setOpen(!widget->isOpen());
+ }
}
}
@@ -1955,11 +1988,6 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
// Most of the time the user will never see this state.
setMinimized(FALSE);
- // Save the conversations pane width.
- gSavedPerAccountSettings.setS32(
- "ConversationsListPaneWidth",
- mConversationsPane->getRect().getWidth());
-
LLFloater::closeFloater(app_quitting);
}
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index c84d4978ec..52b672241f 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -60,6 +60,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void updateResizeLimits();
void onCloseFloater(LLUUID& id);
@@ -72,7 +73,8 @@ public:
void selectNextConversationByID(const LLUUID& session_id);
BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true);
void clearAllFlashStates();
- bool selectNextorPreviousConversation(bool select_next);
+ bool selectAdjacentConversation(bool focus_selected);
+ bool selectNextorPreviousConversation(bool select_next, bool focus_selected = true);
void expandConversation();
/*virtual*/ void tabClose();
@@ -128,9 +130,9 @@ private:
void processParticipantsStyleUpdate();
void onSpeakButtonClicked();
- void collapseConversationsPane(bool collapse);
+ void collapseConversationsPane(bool collapse, bool save_is_allowed=true);
- void updateState(bool collapse, S32 delta_width);
+ void reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width);
void onAddButtonClicked();
void onAvatarPicked(const uuid_vec_t& ids);
@@ -173,7 +175,6 @@ private:
LLLayoutStack* mConversationsStack;
bool mInitialized;
- bool mIsFirstLaunch;
LLUUID mSelectedSession;
std::string mGeneralTitle;
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index dfaf4bbdd6..d86e1b3fd7 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -257,14 +257,25 @@ void LLFloaterIMNearbyChat::setVisible(BOOL visible)
}
}
+
+void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
+{
+ LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key);
+
+ if(!isTornOff() && matchesKey(key))
+ {
+ LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, false);
+ }
+}
+
// virtual
void LLFloaterIMNearbyChat::onTearOffClicked()
{
LLFloaterIMSessionTab::onTearOffClicked();
// see CHUI-170: Save torn-off state of the nearby chat between sessions
- BOOL in_the_multifloater = !isTornOff();
- gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater);
+ BOOL in_the_multifloater = (BOOL)getHost();
+ gSavedPerAccountSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater);
}
@@ -272,6 +283,11 @@ void LLFloaterIMNearbyChat::onTearOffClicked()
void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
{
LLFloaterIMSessionTab::onOpen(key);
+ if(!isMessagePaneExpanded())
+ {
+ restoreFloater();
+ onCollapseToLine(this);
+ }
showTranslationCheckbox(LLTranslate::isTranslationConfigured());
}
@@ -279,6 +295,7 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
void LLFloaterIMNearbyChat::onClose(bool app_quitting)
{
// Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater
+ LLFloaterIMSessionTab::restoreFloater();
onClickCloseBtn();
}
@@ -286,8 +303,10 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting)
void LLFloaterIMNearbyChat::onClickCloseBtn()
{
if (!isTornOff())
+ {
return;
- onTearOffClicked();
+ }
+ LLFloaterIMSessionTab::onTearOffClicked();
LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance();
if (im_box)
@@ -308,11 +327,8 @@ void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp)
void LLFloaterIMNearbyChat::show()
{
- if (isChatMultiTab())
- {
openFloater(getKey());
}
-}
bool LLFloaterIMNearbyChat::isChatVisible() const
{
@@ -323,7 +339,7 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
if (im_box != NULL)
{
isVisible =
- isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")?
+ isChatMultiTab() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff")?
im_box->getVisible() && !im_box->isMinimized() :
getVisible() && !isMinimized();
}
@@ -334,6 +350,11 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
void LLFloaterIMNearbyChat::showHistory()
{
openFloater();
+ if(!isMessagePaneExpanded())
+ {
+ restoreFloater();
+ setFocus(true);
+ }
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
}
@@ -406,6 +427,12 @@ BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std:
void LLFloaterIMNearbyChat::onChatBoxKeystroke()
{
+ LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
+ if (im_box)
+ {
+ im_box->flashConversationItemWidget(mSessionID,false);
+ }
+
LLFirstUse::otherAvatarChatFirst(false);
LLWString raw_text = mInputEditor->getWText();
@@ -455,11 +482,14 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()
if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str))
{
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
- mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
+ if (!rest_of_match.empty())
+ {
+ mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
- // Select to end of line, starting from the character
- // after the last one the user typed.
- mInputEditor->selectNext(rest_of_match, false);
+ // Select to end of line, starting from the character
+ // after the last one the user typed.
+ mInputEditor->selectNext(rest_of_match, false);
+ }
}
else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
{
@@ -714,10 +744,16 @@ void LLFloaterIMNearbyChat::startChat(const char* line)
LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
if (nearby_chat)
{
+ if(!nearby_chat->isTornOff())
+ {
+ LLFloaterIMContainer::getInstance()->selectConversation(LLUUID(NULL));
+ }
+ if(nearby_chat->isMinimized())
+ {
+ nearby_chat->setMinimized(false);
+ }
nearby_chat->show();
- nearby_chat->setVisible(TRUE);
nearby_chat->setFocus(TRUE);
- nearby_chat->mInputEditor->setFocus(TRUE);
if (line)
{
diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h
index 4ad37eb0c7..05b48cccb0 100644
--- a/indra/newview/llfloaterimnearbychat.h
+++ b/indra/newview/llfloaterimnearbychat.h
@@ -54,6 +54,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void closeHostedFloater();
void loadHistory();
diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp
index 8870d54cd2..0824b26406 100644
--- a/indra/newview/llfloaterimnearbychathandler.cpp
+++ b/indra/newview/llfloaterimnearbychathandler.cpp
@@ -559,12 +559,12 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
- if( nearby_chat->hasFocus()
- || im_box->hasFocus()
- || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
+ if(( ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
&& gSavedSettings.getBOOL("UseChatBubbles") )
|| mChannel.isDead()
- || !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode
+ || !mChannel.get()->getShowToasts() )
+ && nearby_chat->isMessagePaneExpanded())
+ // to prevent toasts in Do Not Disturb mode
return;//no need in toast if chat is visible or if bubble chat is enabled
// arrange a channel on a screen
@@ -604,17 +604,16 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
toast_msg = chat_msg.mText;
}
- //Don't show nearby toast, if conversation is visible but not focused
- LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(LLUUID());
- if (session_floater
- && session_floater->isInVisibleChain() && !session_floater->isMinimized()
- && !(session_floater->getHost() && session_floater->getHost()->isMinimized()))
+ //Don't show nearby toast, if conversation is visible and selected
+ if (im_box->getSelectedSession().isNull() &&
+ ((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())
+ || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost())))
{
return;
}
//Will show toast when chat preference is set
- if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast")
+ if((gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") || !nearby_chat->isMessagePaneExpanded())
{
// Add a nearby chat toast.
LLUUID id;
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index 50b2ed8c51..6d5145f205 100644
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -618,7 +618,9 @@ void LLFloaterIMSession::onClose(bool app_quitting)
// Last change:
// EXT-3516 X Button should end IM session, _ button should hide
gIMMgr->leaveSession(mSessionID);
-
+ // *TODO: Study why we need to restore the floater before we close it.
+ // Might be because we want to save some state data in some clean open state.
+ LLFloaterIMSessionTab::restoreFloater();
// Clean up the conversation *after* the session has been ended
LLFloaterIMSessionTab::onClose(app_quitting);
}
@@ -892,6 +894,11 @@ void LLFloaterIMSession::onInputEditorFocusLost(LLFocusableElement* caller, void
void LLFloaterIMSession::onInputEditorKeystroke(LLTextEditor* caller, void* userdata)
{
LLFloaterIMSession* self = (LLFloaterIMSession*)userdata;
+ LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
+ if (im_box)
+ {
+ im_box->flashConversationItemWidget(self->mSessionID,false);
+ }
std::string text = self->mInputEditor->getText();
// Deleting all text counts as stopping typing.
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index d3fcfbbc56..5083331167 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -30,6 +30,7 @@
#include "llfloaterimsessiontab.h"
#include "llagent.h"
+#include "llagentcamera.h"
#include "llavataractions.h"
#include "llchatentry.h"
#include "llchathistory.h"
@@ -57,10 +58,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
, mSpeakingIndicator(NULL)
, mChatHistory(NULL)
, mInputEditor(NULL)
- , mInputEditorTopPad(0)
+ , mInputEditorPad(0)
, mRefreshTimer(new LLTimer())
, mIsHostAttached(false)
, mHasVisibleBeenInitialized(false)
+ , mIsParticipantListExpanded(true)
+ , mChatLayoutPanel(NULL)
{
setAutoFocus(FALSE);
mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
@@ -124,8 +127,18 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible)
if(visible && !mHasVisibleBeenInitialized)
{
mHasVisibleBeenInitialized = true;
- LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);
+ if(!gAgentCamera.cameraMouselook())
+ {
+ LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);
+ }
LLFloaterIMSessionTab::addToHost(mSessionID);
+ LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(mSessionID);
+
+ if (conversp && conversp->isNearbyChat() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotCollapsed"))
+ {
+ onCollapseToLine(this);
+ }
+ mInputButtonPanel->setVisible(isTornOff());
}
LLTransientDockableFloater::setVisible(visible);
@@ -169,7 +182,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
conversp->setHostAttached(true);
if (!conversp->isNearbyChat()
- || gSavedSettings.getBOOL("NearbyChatIsNotTornOff"))
+ || gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff"))
{
floater_container->addFloater(conversp, false, LLTabContainer::RIGHT_OF_CURRENT);
}
@@ -180,6 +193,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
// LLFloater::mLastHostHandle = floater_container (a "future" host)
conversp->setHost(floater_container);
conversp->setHost(NULL);
+
conversp->forceReshape();
}
// Added floaters share some state (like sort order) with their host
@@ -188,23 +202,51 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
}
}
+void LLFloaterIMSessionTab::assignResizeLimits()
+{
+ bool is_participants_pane_collapsed = mParticipantListPanel->isCollapsed();
+
+ // disable a layoutstack's functionality when participant list panel is collapsed
+ mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);
+
+ S32 participants_pane_target_width = is_participants_pane_collapsed?
+ 0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH);
+
+ S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
+
+ setResizeLimits(new_min_width, getMinHeight());
+
+ this->mParticipantListAndHistoryStack->updateLayout();
+}
+
BOOL LLFloaterIMSessionTab::postBuild()
{
BOOL result;
+ mBodyStack = getChild<LLLayoutStack>("main_stack");
+ mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels");
+
mCloseBtn = getChild<LLButton>("close_btn");
mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));
mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this));
+ mExpandCollapseLineBtn = getChild<LLButton>("minz_btn");
+ mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this));
+
mTearOffBtn = getChild<LLButton>("tear_off_btn");
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
mGearBtn = getChild<LLButton>("gear_btn");
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
-
+ mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
+
+ mToolbarPanel = getChild<LLLayoutPanel>("toolbar_panel");
+ mContentPanel = getChild<LLLayoutPanel>("body_panel");
+ mInputButtonPanel = getChild<LLLayoutPanel>("input_button_layout_panel");
+ mInputButtonPanel->setVisible(false);
// Add a scroller for the folder (participant) view
LLRect scroller_view_rect = mParticipantListPanel->getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
@@ -221,17 +263,20 @@ BOOL LLFloaterIMSessionTab::postBuild()
mChatHistory = getChild<LLChatHistory>("chat_history");
mInputEditor = getChild<LLChatEntry>("chat_editor");
- mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatHistory, this));
+
+ mChatLayoutPanel = getChild<LLLayoutPanel>("chat_layout_panel");
+
+ mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this));
mInputEditor->setCommitOnFocusLost( FALSE );
mInputEditor->setPassDelete(TRUE);
mInputEditor->setFont(LLViewerChat::getChatFont());
- mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop;
+ mInputEditorPad = mChatLayoutPanel->getRect().getHeight() - mInputEditor->getRect().getHeight();
setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);
mSaveRect = isNearbyChat()
- && !gSavedSettings.getBOOL("NearbyChatIsNotTornOff");
+ && !gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff");
initRectControl();
if (isChatMultiTab())
@@ -253,6 +298,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
p.root = NULL;
p.use_ellipses = true;
p.options_menu = "menu_conversation.xml";
+ p.name = "root";
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
// Attach that root to the scroller
@@ -261,6 +307,8 @@ BOOL LLFloaterIMSessionTab::postBuild()
mConversationsRoot->setFollowsAll();
mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox);
+ setMessagePaneExpanded(true);
+
buildConversationViewParticipant();
refreshConversation();
@@ -268,6 +316,21 @@ BOOL LLFloaterIMSessionTab::postBuild()
mRefreshTimer->setTimerExpirySec(0);
mRefreshTimer->start();
initBtns();
+
+ if (mIsParticipantListExpanded != (bool)gSavedSettings.getBOOL("IMShowControlPanel"))
+ {
+ LLFloaterIMSessionTab::onSlide(this);
+ }
+
+ // The resize limits for LLFloaterIMSessionTab should be updated, based on current values of width of conversation and message panels
+ mParticipantListPanel->getResizeBar()->setResizeListener(boost::bind(&LLFloaterIMSessionTab::assignResizeLimits, this));
+ mFloaterExtraWidth =
+ getRect().getWidth()
+ - mParticipantListAndHistoryStack->getRect().getWidth()
+ - (mParticipantListPanel->isCollapsed()? 0 : LLPANEL_BORDER_WIDTH);
+
+ assignResizeLimits();
+
return result;
}
@@ -299,7 +362,7 @@ void LLFloaterIMSessionTab::draw()
// Restart the refresh timer
mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);
}
-
+
LLTransientDockableFloater::draw();
}
@@ -324,13 +387,6 @@ void LLFloaterIMSessionTab::onFocusReceived()
}
LLTransientDockableFloater::onFocusReceived();
-
- LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
- if (container)
- {
- container->selectConversationPair(mSessionID, true);
- container->showStub(! getHost());
- }
}
void LLFloaterIMSessionTab::onFocusLost()
@@ -644,14 +700,16 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
// Participant list should be visible only in torn off floaters.
bool is_participant_list_visible =
!is_not_torn_off
- && gSavedSettings.getBOOL("IMShowControlPanel")
+ && mIsParticipantListExpanded
&& !mIsP2PChat;
- mParticipantListPanel->setVisible(is_participant_list_visible);
+ mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible);
+ mParticipantListPanel->setVisible(is_participant_list_visible);
// Display collapse image (<<) if the floater is hosted
// or if it is torn off but has an open control panel.
bool is_expanded = is_not_torn_off || is_participant_list_visible;
+
mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));
mExpandCollapseBtn->setToolTip(
is_not_torn_off?
@@ -672,6 +730,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon"));
mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window"));
+
mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat);
enableDisableCallBtn();
@@ -688,15 +747,11 @@ void LLFloaterIMSessionTab::forceReshape()
}
-void LLFloaterIMSessionTab::reshapeChatHistory()
+void LLFloaterIMSessionTab::reshapeChatLayoutPanel()
{
- LLRect chat_rect = mChatHistory->getRect();
+ LLRect chat_layout_panel_rect = mChatLayoutPanel->getRect();
LLRect input_rect = mInputEditor->getRect();
-
- int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad);
-
- chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height);
- mChatHistory->setShape(chat_rect);
+ mChatLayoutPanel->reshape(chat_layout_panel_rect.getWidth(), input_rect.getHeight() + mInputEditorPad, FALSE);
}
void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)
@@ -771,15 +826,76 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
{
if (!self->mIsP2PChat)
{
- bool expand = !self->mParticipantListPanel->getVisible();
+ // The state must toggle the collapsed state of the panel
+ bool should_be_expanded = self->mParticipantListPanel->isCollapsed();
+
+ // Update the expand/collapse flag of the participant list panel and save it
+ gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded);
+ self->mIsParticipantListExpanded = should_be_expanded;
+
+ // Refresh for immediate feedback
+ self->refreshConversation();
+ }
+ }
+
+ self->assignResizeLimits();
+}
+
+void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self)
+{
+ LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(self->getHost());
+ if (!host_floater)
+ {
+ bool expand = self->isMessagePaneExpanded();
+ self->mExpandCollapseLineBtn->setImageOverlay(self->getString(expand ? "collapseline_icon" : "expandline_icon"));
+ self->mContentPanel->setVisible(!expand);
+ self->mToolbarPanel->setVisible(!expand);
+ self->reshapeFloater(expand);
+ self->setMessagePaneExpanded(!expand);
+ }
+}
- // Expand/collapse the IM control panel
- self->mParticipantListPanel->setVisible(expand);
+void LLFloaterIMSessionTab::reshapeFloater(bool collapse)
+{
+ LLRect floater_rect = getRect();
- gSavedSettings.setBOOL("IMShowControlPanel", expand);
+ if(collapse)
+ {
+ mFloaterHeight = floater_rect.getHeight();
+ S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight();
+ floater_rect.mTop -= height;
+ enableResizeCtrls(true, true, false);
+ }
+ else
+ {
+ floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
+ enableResizeCtrls(true, true, true);
+
+ }
+ saveCollapsedState();
+ setShape(floater_rect, true);
+ mBodyStack->updateLayout();
- self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon"));
+}
+
+void LLFloaterIMSessionTab::restoreFloater()
+{
+ if(!isMessagePaneExpanded())
+ {
+ if(isMinimized())
+ {
+ setMinimized(false);
}
+ mContentPanel->setVisible(true);
+ mToolbarPanel->setVisible(true);
+ LLRect floater_rect = getRect();
+ floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
+ setShape(floater_rect, true);
+ mBodyStack->updateLayout();
+ mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
+ setMessagePaneExpanded(true);
+ saveCollapsedState();
+ enableResizeCtrls(true, true, true);
}
}
@@ -792,19 +908,33 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
// Show the messages pane when opening a floater hosted in the Conversations
host_floater->collapseMessagesPane(false);
}
+
+ mInputButtonPanel->setVisible(isTornOff());
}
void LLFloaterIMSessionTab::onTearOffClicked()
{
- setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE);
+ restoreFloater();
+ setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE);
mSaveRect = isTornOff();
initRectControl();
LLFloater::onClickTearOff(this);
+ LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
+
if (isTornOff())
{
+ container->selectAdjacentConversation(false);
forceReshape();
}
+ //Upon re-docking the torn off floater, select the corresponding conversation line item
+ else
+ {
+ container->selectConversation(mSessionID);
+
+ }
+ mInputButtonPanel->setVisible(isTornOff());
+
refreshConversation();
updateGearBtn();
}
@@ -940,6 +1070,14 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()
return conversationItem;
}
+void LLFloaterIMSessionTab::saveCollapsedState()
+{
+ LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(mSessionID);
+ if(conversp->isNearbyChat())
+ {
+ gSavedPerAccountSettings.setBOOL("NearbyChatIsNotCollapsed", isMessagePaneExpanded());
+ }
+}
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
{
if(mask == MASK_ALT)
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index d55b021df7..c7e73bd70d 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -98,6 +98,10 @@ public:
LLConversationItem* getCurSelectedViewModelItem();
void forceReshape();
virtual BOOL handleKeyHere( KEY key, MASK mask );
+ bool isMessagePaneExpanded(){return mMessagePaneExpanded;}
+ void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;}
+ void restoreFloater();
+ void saveCollapsedState();
protected:
@@ -111,6 +115,8 @@ protected:
bool onIMShowModesMenuItemCheck(const LLSD& userdata);
bool onIMShowModesMenuItemEnable(const LLSD& userdata);
static void onSlide(LLFloaterIMSessionTab *self);
+ static void onCollapseToLine(LLFloaterIMSessionTab *self);
+ void reshapeFloater(bool collapse);
// refresh a visual state of the Call button
void updateCallBtnState(bool callIsActive);
@@ -135,17 +141,30 @@ protected:
void appendMessage(const LLChat& chat, const LLSD &args = 0);
std::string appendTime();
+ void assignResizeLimits();
+
+ S32 mFloaterExtraWidth;
bool mIsNearbyChat;
bool mIsP2PChat;
+ bool mMessagePaneExpanded;
+ bool mIsParticipantListExpanded;
+
+
LLIMModel::LLIMSession* mSession;
// Participants list: model and view
LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
LLUUID mSessionID;
+ LLLayoutStack* mBodyStack;
+ LLLayoutStack* mParticipantListAndHistoryStack;
LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel
+ LLLayoutPanel* mRightPartPanel;
+ LLLayoutPanel* mContentPanel;
+ LLLayoutPanel* mToolbarPanel;
+ LLLayoutPanel* mInputButtonPanel;
LLParticipantList* getParticipantList();
conversations_widgets_map mConversationsWidgets;
LLConversationViewModel mConversationViewModel;
@@ -155,13 +174,17 @@ protected:
LLOutputMonitorCtrl* mSpeakingIndicator;
LLChatHistory* mChatHistory;
LLChatEntry* mInputEditor;
- int mInputEditorTopPad; // padding between input field and chat history
+ LLLayoutPanel * mChatLayoutPanel;
+ int mInputEditorPad; // padding between input field and chat history
+ LLButton* mExpandCollapseLineBtn;
LLButton* mExpandCollapseBtn;
LLButton* mTearOffBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
+ S32 mFloaterHeight;
+
private:
// Handling selection and contextual menu
@@ -179,7 +202,7 @@ private:
* and avoid overlapping, since input chat field can be vertically expanded.
* Implementation: chat history bottom "follows" top+top_pad of input chat field
*/
- void reshapeChatHistory();
+ void reshapeChatLayoutPanel();
bool checkIfTornOff();
bool mIsHostAttached;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 3f8c23ba83..a28af2101b 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -443,6 +443,8 @@ BOOL LLFloaterPreference::postBuild()
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location);
+ getChild<LLUICtrl>("log_path_string")->setEnabled(FALSE); // make it read-only but selectable
+
getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions"));
@@ -1572,7 +1574,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
getChildView("send_im_to_email")->setEnabled(TRUE);
getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email);
getChildView("favorites_on_login_check")->setEnabled(TRUE);
- getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case.
getChildView("log_path_button")->setEnabled(TRUE);
getChildView("chat_font_size")->setEnabled(TRUE);
}
@@ -1667,7 +1668,10 @@ void LLFloaterPreference::onClickActionChange()
void LLFloaterPreference::onDeleteTranscripts()
{
- LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2));
+ LLSD args;
+ args["FOLDER"] = gDirUtilp->getUserName();
+
+ LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", args, LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2));
}
void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response)
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 8f3f5145a9..76a314f807 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -154,149 +154,156 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
args["FROM"] = av_name.getCompleteName();
args["FROM_ID"] = msg["from_id"];
args["SESSION_ID"] = msg["session_id"];
+ args["SESSION_TYPE"] = msg["session_type"];
LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
}
void on_new_message(const LLSD& msg)
{
- std::string action;
+ std::string user_preferences;
LLUUID participant_id = msg["from_id"].asUUID();
LLUUID session_id = msg["session_id"].asUUID();
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
- // determine action for this session
+ // do not show notification which goes from agent
+ if (gAgent.getID() == participant_id)
+ {
+ return;
+ }
+
+ // determine state of conversations floater
+ enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
+
+ LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+ LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
+
+ if (!LLFloater::isVisible(im_box) || im_box->isMinimized())
+ {
+ conversations_floater_status = CLOSED;
+ }
+ else if ( !im_box->hasFocus() &&
+ (!session_floater || !LLFloater::isVisible(session_floater)
+ || session_floater->isMinimized() || !session_floater->hasFocus()))
+ {
+ conversations_floater_status = NOT_ON_TOP;
+ }
+ else if (im_box->getSelectedSession() != session_id)
+ {
+ conversations_floater_status = ON_TOP;
+ }
+ else
+ {
+ conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;
+ }
+ // determine user prefs for this session
if (session_id.isNull())
{
- action = gSavedSettings.getString("NotificationNearbyChatOptions");
+ user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
}
else if(session->isP2PSessionType())
{
if (LLAvatarTracker::instance().isBuddy(participant_id))
{
- action = gSavedSettings.getString("NotificationFriendIMOptions");
+ user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
}
else
{
- action = gSavedSettings.getString("NotificationNonFriendIMOptions");
+ user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
}
}
else if(session->isAdHocSessionType())
{
- action = gSavedSettings.getString("NotificationConferenceIMOptions");
+ user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
}
else if(session->isGroupSessionType())
{
- action = gSavedSettings.getString("NotificationGroupChatOptions");
+ user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
}
- // do not show notification which goes from agent
- if (gAgent.getID() == participant_id)
+ // actions:
+
+ // 0. nothing - exit
+ if (("none" == user_preferences ||
+ ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)
+ && session_floater->isMessagePaneExpanded())
{
- return;
+ return;
}
- // execution of the action
-
- LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
-
- if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id)
- {
- return;
- }
-
- LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
-
- //session floater not focused (visible or not)
- bool session_floater_not_focused = session_floater && !session_floater->hasFocus();
-
- //conv. floater is closed
- bool conversation_floater_is_closed =
- !( im_box
- && im_box->isInVisibleChain()
- && !im_box->isMinimized());
-
- //conversation floater not focused (visible or not)
- bool conversation_floater_not_focused =
- conversation_floater_is_closed || !im_box->hasFocus();
- // sess. floater is open
- bool session_floater_is_open =
- session_floater
- && session_floater->isInVisibleChain()
- && !session_floater->isMinimized()
- && !(session_floater->getHost() && session_floater->getHost()->isMinimized());
-
- if ("toast" == action && !session_floater_is_open)
+ // 1. open floater and [optional] surface it
+ if ("openconversations" == user_preferences &&
+ (CLOSED == conversations_floater_status
+ || NOT_ON_TOP == conversations_floater_status))
{
- //User is not focused on conversation containing the message
- if(session_floater_not_focused)
+ if(!gAgent.isDoNotDisturb())
{
- if(!LLMuteList::getInstance()->isMuted(participant_id))
- {
- im_box->flashConversationItemWidget(session_id, true);
- }
- //The conversation floater isn't focused/open
- if(conversation_floater_not_focused)
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id)
- && !gAgent.isDoNotDisturb())
- {
- gToolBarView->flashCommand(LLCommandId("chat"), true);
- }
-
- //Show IM toasts (upper right toasts)
- // Skip toasting for system messages and for nearby chat
- if(session_id.notNull() && participant_id.notNull())
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
+ // Open conversations floater
+ LLFloaterReg::showInstance("im_container");
+ im_box->collapseMessagesPane(false);
+ if (session_floater)
+ {
+ if (session_floater->getHost())
+ {
+ if (NULL != im_box && im_box->isMinimized())
+ {
+ LLFloater::onClickMinimize(im_box);
+ }
+ }
+ else
+ {
+ if (session_floater->isMinimized())
+ {
+ LLFloater::onClickMinimize(session_floater);
+ }
+ }
+ }
}
+ else
+ {
+ //If in DND mode, allow notification to be stored so upon DND exit
+ //useMostItrusiveIMNotification will be called to notify user a message exists
+ if(session_id.notNull()
+ && participant_id.notNull()
+ && !session_floater->isShown())
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
}
- else if ("flash" == action)
+ // 2. Flash line item
+ if ("openconversations" == user_preferences
+ || ON_TOP == conversations_floater_status)
{
- if (!gAgent.isDoNotDisturb())
+ if(!LLMuteList::getInstance()->isMuted(participant_id))
{
- im_box->flashConversationItemWidget(session_id, true);
- if(conversation_floater_not_focused)
- {
- //User is not focused on conversation containing the message
- gToolBarView->flashCommand(LLCommandId("chat"), true);
- }
- }
- else if(session_id.notNull() && participant_id.notNull())
- {
- //If a DND message, allow notification to be stored so upon DND exit
- //useMostItrusiveIMNotification will be called to notify user a message exists
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
+ im_box->flashConversationItemWidget(session_id, true);
+ }
}
- else if("openconversations" == action)
+ // 3. Flash FUI button
+ if (("toast" == user_preferences || "flash" == user_preferences) &&
+ (CLOSED == conversations_floater_status
+ || NOT_ON_TOP == conversations_floater_status))
{
- //User is not focused on conversation containing the message
- if(session_floater_not_focused)
- {
- //Flash line item
- im_box->flashConversationItemWidget(session_id, true);
-
- if(!gAgent.isDoNotDisturb())
- {
- //Surface conversations floater
- LLFloaterReg::showInstance("im_container");
- }
+ if(!LLMuteList::getInstance()->isMuted(participant_id)
+ && !gAgent.isDoNotDisturb())
+ {
+ gToolBarView->flashCommand(LLCommandId("chat"), true);
+ }
+ }
- //If in DND mode, allow notification to be stored so upon DND exit
- //useMostItrusiveIMNotification will be called to notify user a message exists
- if(session_id.notNull()
- && participant_id.notNull()
- && gAgent.isDoNotDisturb()
- && !session_floater_is_open)
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
+ // 4. Toast
+ if ("toast" == user_preferences
+ || !session_floater->isMessagePaneExpanded())
+ {
+ //Show IM toasts (upper right toasts)
+ // Skip toasting for system messages and for nearby chat
+ if(session_id.notNull() && participant_id.notNull())
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
}
}
@@ -636,8 +643,7 @@ void LLIMModel::LLIMSession::loadHistory()
LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
{
- return get_if_there(mId2SessionMap, session_id,
- (LLIMModel::LLIMSession*) NULL);
+ return get_if_there(mId2SessionMap, session_id, (LLIMModel::LLIMSession*) NULL);
}
//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code
@@ -990,6 +996,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co
arg["from"] = from;
arg["from_id"] = from_id;
arg["time"] = LLLogChat::timestamp(false);
+ arg["session_type"] = session->mSessionType;
mNewMsgSignal(arg);
return true;
@@ -2633,7 +2640,7 @@ void LLIMMgr::addMessage(
if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
{
// Evaluate if we need to skip this message when that setting is true (default is false)
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends...
skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself
@@ -2649,7 +2656,7 @@ void LLIMMgr::addMessage(
{
LLFloaterReg::showInstance("im_container");
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->
- flashConversationItemWidget(session_id, true);
+ flashConversationItemWidget(new_session_id, true);
}
}
@@ -2804,7 +2811,7 @@ LLUUID LLIMMgr::addSession(
}
}
- bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
+ bool new_session = (LLIMModel::getInstance()->findIMSession(session_id) == NULL);
//works only for outgoing ad-hoc sessions
if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size())
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 448100c5d6..2d7454b636 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -444,7 +444,7 @@ std::string LLLogChat::oldLogFileName(std::string filename)
}
// static
-void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions)
+void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions)
{
// get Users log directory
std::string dirname = gDirUtilp->getPerAccountChatLogsDir();
@@ -452,9 +452,6 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans
// add final OS dependent delimiter
dirname += gDirUtilp->getDirDelimiter();
- // create search pattern
- std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION;
-
LLDirIterator iter(dirname, pattern);
std::string filename;
while (iter.next(filename))
@@ -490,6 +487,22 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans
}
}
+// static
+void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions)
+{
+ // create search pattern
+ std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION;
+ findTranscriptFiles(pattern, list_of_transcriptions);
+}
+
+// static
+void LLLogChat::getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions)
+{
+ // create search pattern
+ std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION + ".backup*";
+ findTranscriptFiles(pattern, list_of_transcriptions);
+}
+
//static
boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb)
{
@@ -581,6 +594,7 @@ void LLLogChat::deleteTranscripts()
{
std::vector<std::string> list_of_transcriptions;
getListOfTranscriptFiles(list_of_transcriptions);
+ getListOfTranscriptBackupFiles(list_of_transcriptions);
BOOST_FOREACH(const std::string& fullpath, list_of_transcriptions)
{
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index 784786a565..e819f00dd9 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -49,7 +49,9 @@ public:
const std::string& from,
const LLUUID& from_id,
const std::string& line);
+ static void findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions);
static void getListOfTranscriptFiles(std::vector<std::string>& list);
+ static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp
index b6184f09bf..2923221c90 100644
--- a/indra/newview/llnotificationstorage.cpp
+++ b/indra/newview/llnotificationstorage.cpp
@@ -105,6 +105,8 @@ bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) co
bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
{
+ LL_INFOS("LLNotificationStorage") << "starting read '" << mFileName << "'" << LL_ENDL;
+
bool didFileRead;
pNotificationData.clear();
@@ -126,6 +128,8 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
}
}
+ LL_INFOS("LLNotificationStorage") << "ending read '" << mFileName << "'" << LL_ENDL;
+
return didFileRead;
}
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index c5283404f1..4138558bad 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -611,10 +611,10 @@ BOOL LLPanelPeople::postBuild()
mGroupList->setNoItemsMsg(getString("no_groups_msg"));
mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg"));
- mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
- mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
- mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
- mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
+ mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyPeopleContextMenu);
+ mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
+ mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
+ mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
@@ -1143,7 +1143,10 @@ void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn)
uuid_vec_t selected_uuids;
getCurrentItemIDs(selected_uuids);
// Spawn at bottom left corner of the button.
- LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0);
+ if (getActiveTabName() == NEARBY_TAB_NAME)
+ LLPanelPeopleMenus::gNearbyPeopleContextMenu.show(btn, selected_uuids, 0, 0);
+ else
+ LLPanelPeopleMenus::gPeopleContextMenu.show(btn, selected_uuids, 0, 0);
}
void LLPanelPeople::onImButtonClicked()
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index 47d6b49a50..49f7361c4a 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -39,15 +39,18 @@
#include "llcallingcard.h" // for LLAvatarTracker
#include "lllogchat.h"
#include "llviewermenu.h" // for gMenuHolder
+#include "llconversationmodel.h"
+#include "llviewerobjectlist.h"
namespace LLPanelPeopleMenus
{
-NearbyMenu gNearbyMenu;
+PeopleContextMenu gPeopleContextMenu;
+NearbyPeopleContextMenu gNearbyPeopleContextMenu;
-//== NearbyMenu ===============================================================
+//== PeopleContextMenu ===============================================================
-LLContextMenu* NearbyMenu::createMenu()
+LLContextMenu* PeopleContextMenu::createMenu()
{
// set up the callbacks for all of the avatar menu items
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -64,7 +67,8 @@ LLContextMenu* NearbyMenu::createMenu()
registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendDialog, id));
registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, id));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id));
- registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this));
+ registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this));
+ registrar.add("Avatar.ZoomIn", boost::bind(&handle_zoom_to_object, id));
registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::showOnMap, id));
registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id));
registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id));
@@ -72,33 +76,72 @@ LLContextMenu* NearbyMenu::createMenu()
registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id));
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
- enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
- enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2));
+ enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
+ enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2));
// create the context menu from the XUI
menu = createFromFile("menu_people_nearby.xml");
+ buildContextMenu(*menu, 0x0);
}
else
{
// Set up for multi-selected People
// registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented
- registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null));
- registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null));
- registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this));
- registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs));
+ registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null));
+ registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null));
+ registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this));
+ registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs));
// registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented
- // registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented
- enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
+ // registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented
+
+ enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
// create the context menu from the XUI
menu = createFromFile("menu_people_nearby_multiselect.xml");
+ buildContextMenu(*menu, ITEM_IN_MULTI_SELECTION);
}
return menu;
}
-bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
+void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
+{
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+
+ if (flags & ITEM_IN_MULTI_SELECTION)
+ {
+ items.push_back(std::string("add_friends"));
+ items.push_back(std::string("remove_friends"));
+ items.push_back(std::string("im"));
+ items.push_back(std::string("call"));
+ items.push_back(std::string("share"));
+ items.push_back(std::string("pay"));
+ items.push_back(std::string("offer_teleport"));
+ }
+ else
+ {
+ 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"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata)
{
if(gAgent.getID() == mUUIDs.front())
{
@@ -170,6 +213,12 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
{
return LLAvatarActions::canCall();
}
+ else if (item == std::string("can_zoom_in"))
+ {
+ const LLUUID& id = mUUIDs.front();
+
+ return gObjectList.findObject(id);
+ }
else if (item == std::string("can_show_on_map"))
{
const LLUUID& id = mUUIDs.front();
@@ -193,7 +242,7 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
return false;
}
-bool NearbyMenu::checkContextMenuItem(const LLSD& userdata)
+bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
{
std::string item = userdata.asString();
const LLUUID& id = mUUIDs.front();
@@ -206,11 +255,50 @@ bool NearbyMenu::checkContextMenuItem(const LLSD& userdata)
return false;
}
-void NearbyMenu::offerTeleport()
+void PeopleContextMenu::offerTeleport()
{
// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
// so we have to use a wrapper.
LLAvatarActions::offerTeleport(mUUIDs);
}
+//== NearbyPeopleContextMenu ===============================================================
+
+void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
+{
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+
+ if (flags & ITEM_IN_MULTI_SELECTION)
+ {
+ items.push_back(std::string("add_friends"));
+ items.push_back(std::string("remove_friends"));
+ items.push_back(std::string("im"));
+ items.push_back(std::string("call"));
+ items.push_back(std::string("share"));
+ items.push_back(std::string("pay"));
+ items.push_back(std::string("offer_teleport"));
+ }
+ else
+ {
+ 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("zoom_in"));
+ 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"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
} // namespace LLPanelPeopleMenus
diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h
index d51eaec716..0a1dcef303 100644
--- a/indra/newview/llpanelpeoplemenus.h
+++ b/indra/newview/llpanelpeoplemenus.h
@@ -33,19 +33,33 @@ namespace LLPanelPeopleMenus
{
/**
- * Menu used in the nearby people list.
+ * Menu used in the people lists.
*/
-class NearbyMenu : public LLListContextMenu
+class PeopleContextMenu : public LLListContextMenu
{
public:
/*virtual*/ LLContextMenu* createMenu();
+
+protected:
+ virtual void buildContextMenu(class LLMenuGL& menu, U32 flags);
+
private:
bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata);
void offerTeleport();
};
-extern NearbyMenu gNearbyMenu;
+/**
+ * Menu used in the nearby people list.
+ */
+class NearbyPeopleContextMenu : public PeopleContextMenu
+{
+protected:
+ /*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
+};
+
+extern PeopleContextMenu gPeopleContextMenu;
+extern NearbyPeopleContextMenu gNearbyPeopleContextMenu;
} // namespace LLPanelPeopleMenus
diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp
index 11c12e6c10..666f10df96 100644
--- a/indra/newview/llpersistentnotificationstorage.cpp
+++ b/indra/newview/llpersistentnotificationstorage.cpp
@@ -87,6 +87,8 @@ void LLPersistentNotificationStorage::loadNotifications()
{
LLFastTimer _(FTM_LOAD_NOTIFICATIONS);
+ LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL;
+
LLNotifications::instance().getChannel("Persistent")->
connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
@@ -129,6 +131,8 @@ void LLPersistentNotificationStorage::loadNotifications()
notification_channel->hideToast(notification->getID());
}
}
+
+ LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL;
}
bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 05df7261e1..8783d99b11 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -38,6 +38,8 @@
#include "llvoavatar.h"
#include "llworld.h"
+extern LLControlGroup gSavedSettings;
+
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
@@ -311,6 +313,7 @@ LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
mModerateModeHandledFirstTime(false),
mSpeakerListUpdated(false)
{
+ mGetListTime.reset();
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
@@ -409,12 +412,10 @@ void LLSpeakerMgr::update(BOOL resort_ok)
// update status of all current speakers
BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
- for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++)
{
LLUUID speaker_id = speaker_it->first;
LLSpeaker* speakerp = speaker_it->second;
-
- speaker_map_t::iterator cur_speaker_it = speaker_it++;
if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
{
@@ -539,30 +540,39 @@ void LLSpeakerMgr::updateSpeakerList()
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
if (session->isGroupSessionType() && (mSpeakers.size() <= 1))
{
+ const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout");
// For groups, we need to hit the group manager.
// Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id);
- if (!gdatap)
+ if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout))
{
// Request the data the first time around
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id);
}
- else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
+ else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
{
// Add group members when we get the complete list (note: can take a while before we get that list)
LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin();
+ const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers");
+ S32 updated = 0;
while (member_it != gdatap->mMembers.end())
{
LLGroupMemberData* member = member_it->second;
- // Add only the members who are online
- if (member->getOnlineStatus() == "Online")
+ LLUUID id = member_it->first;
+ // Add only members who are online and not already in the list
+ if ((member->getOnlineStatus() == "Online") && (mSpeakers.find(id) == mSpeakers.end()))
{
- LLPointer<LLSpeaker> speakerp = setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
+ LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR);
+ updated++;
}
++member_it;
+ // Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop
+ // *TODO : solve the perf issue of having several hundreds of widgets in the conversation list
+ if (updated >= load_group_max_members)
+ break;
}
- mSpeakerListUpdated = true;
+ mSpeakerListUpdated = true;
}
}
else if (mSpeakers.size() == 0)
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 5f5095097e..e953dd0e1a 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -264,6 +264,7 @@ protected:
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
speaker_map_t mSpeakers;
bool mSpeakerListUpdated;
+ LLTimer mGetListTime;
speaker_list_t mSpeakersSorted;
LLFrameTimer mSpeechTimer;
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index ffeea2f4df..40577118ba 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1038,7 +1038,6 @@ void render_hud_attachments()
if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
{
LLCamera hud_cam = *LLViewerCamera::getInstance();
- LLVector3 origin = hud_cam.getOrigin();
hud_cam.setOrigin(-1.f,0,0);
hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 2340436a01..a13c793899 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2382,7 +2382,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false);
break;
- case IM_NOTHING_SPECIAL:
+ case IM_NOTHING_SPECIAL: // p2p IM
// Don't show dialog, just do IM
if (!gAgent.isGodlike()
&& gAgent.getRegion()->isPrelude()
@@ -2783,47 +2783,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
break;
- case IM_SESSION_SEND:
- {
- if (is_do_not_disturb)
- {
- return;
- }
-
- // Only show messages if we have a session open (which
- // should happen after you get an "invitation"
- if ( !gIMMgr->hasSession(session_id) )
- {
- return;
- }
-
- // standard message, not from system
- std::string saved;
- if(offline == IM_OFFLINE)
- {
- saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
- }
- buffer = saved + message;
- BOOL is_this_agent = FALSE;
- if(from_id == gAgentID)
- {
- is_this_agent = TRUE;
- }
- gIMMgr->addMessage(
- session_id,
- from_id,
- name,
- buffer,
- IM_OFFLINE == offline,
- ll_safe_string((char*)binary_bucket),
- IM_SESSION_INVITE,
- parent_estate_id,
- region_id,
- position,
- true);
- }
- break;
-
case IM_FROM_TASK:
{
if (is_do_not_disturb && !is_owned_by_me)
@@ -2922,6 +2881,76 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group);
}
break;
+
+ case IM_SESSION_SEND: // ad-hoc or group IMs
+
+ // Only show messages if we have a session open (which
+ // should happen after you get an "invitation"
+ if ( !gIMMgr->hasSession(session_id) )
+ {
+ return;
+ }
+
+ else if (offline == IM_ONLINE && is_do_not_disturb)
+ {
+
+ // return a standard "do not disturb" message, but only do it to online IM
+ // (i.e. not other auto responses and not store-and-forward IM)
+ if (!gIMMgr->hasSession(session_id))
+ {
+ // if there is not a panel for this conversation (i.e. it is a new IM conversation
+ // initiated by the other party) then...
+ send_do_not_disturb_message(msg, from_id, session_id);
+ }
+
+ // now store incoming IM in chat history
+
+ buffer = message;
+
+ LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
+
+ // add to IM panel, but do not bother the user
+ gIMMgr->addMessage(
+ session_id,
+ from_id,
+ name,
+ buffer,
+ IM_OFFLINE == offline,
+ ll_safe_string((char*)binary_bucket),
+ IM_SESSION_INVITE,
+ parent_estate_id,
+ region_id,
+ position,
+ true);
+ }
+ else
+ {
+ // standard message, not from system
+ std::string saved;
+ if(offline == IM_OFFLINE)
+ {
+ saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
+ }
+
+ buffer = saved + message;
+
+ LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
+
+ gIMMgr->addMessage(
+ session_id,
+ from_id,
+ name,
+ buffer,
+ IM_OFFLINE == offline,
+ ll_safe_string((char*)binary_bucket),
+ IM_SESSION_INVITE,
+ parent_estate_id,
+ region_id,
+ position,
+ true);
+ }
+ break;
+
case IM_FROM_TASK_AS_ALERT:
if (is_do_not_disturb && !is_owned_by_me)
{
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index e44a2cc4df..4afd90b44c 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2827,7 +2827,6 @@ void LLViewerWindow::updateUI()
BOOL handled = FALSE;
- BOOL handled_by_top_ctrl = FALSE;
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
@@ -3012,7 +3011,6 @@ void LLViewerWindow::updateUI()
S32 local_x, local_y;
top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
- handled_by_top_ctrl = TRUE;
}
if ( !handled )
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 157be08f45..a3093f069d 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -675,7 +675,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mBelowWater(FALSE),
mLastAppearanceBlendTime(0.f),
mAppearanceAnimating(FALSE),
- mNameString(),
+ mNameIsSet(false),
mTitle(),
mNameAway(false),
mNameDoNotDisturb(false),
@@ -2994,43 +2994,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
- BOOL new_name = FALSE;
- if (visible_chat != mVisibleChat)
+ BOOL new_name = FALSE;
+ if (visible_chat != mVisibleChat)
+ {
+ mVisibleChat = visible_chat;
+ new_name = TRUE;
+ }
+
+ if (sRenderGroupTitles != mRenderGroupTitles)
+ {
+ mRenderGroupTitles = sRenderGroupTitles;
+ new_name = TRUE;
+ }
+
+ // First Calculate Alpha
+ // If alpha > 0, create mNameText if necessary, otherwise delete it
+ F32 alpha = 0.f;
+ if (mAppAngle > 5.f)
+ {
+ const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
+ if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
{
- mVisibleChat = visible_chat;
- new_name = TRUE;
+ alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
}
-
- if (sRenderGroupTitles != mRenderGroupTitles)
+ else
{
- mRenderGroupTitles = sRenderGroupTitles;
- new_name = TRUE;
+ // ...not fading, full alpha
+ alpha = 1.f;
}
-
- // First Calculate Alpha
- // If alpha > 0, create mNameText if necessary, otherwise delete it
- F32 alpha = 0.f;
- if (mAppAngle > 5.f)
- {
- const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
- if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
- {
- alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
- }
- else
- {
- // ...not fading, full alpha
- alpha = 1.f;
- }
- }
- else if (mAppAngle > 2.f)
- {
- // far away is faded out also
- alpha = (mAppAngle-2.f)/3.f;
- }
+ }
+ else if (mAppAngle > 2.f)
+ {
+ // far away is faded out also
+ alpha = (mAppAngle-2.f)/3.f;
+ }
if (alpha <= 0.f)
- {
+ {
if (mNameText)
{
mNameText->markDead();
@@ -3040,19 +3040,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
- if (!mNameText)
- {
+ if (!mNameText)
+ {
mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
LLHUDObject::LL_HUD_NAME_TAG) );
//mNameText->setMass(10.f);
- mNameText->setSourceObject(this);
+ mNameText->setSourceObject(this);
mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
- mNameText->setVisibleOffScreen(TRUE);
- mNameText->setMaxLines(11);
- mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
- sNumVisibleChatBubbles++;
- new_name = TRUE;
- }
+ mNameText->setVisibleOffScreen(TRUE);
+ mNameText->setMaxLines(11);
+ mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
+ sNumVisibleChatBubbles++;
+ new_name = TRUE;
+ }
idleUpdateNameTagPosition(root_pos_last);
idleUpdateNameTagText(new_name);
@@ -3096,7 +3096,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
}
// Rebuild name tag if state change detected
- if (mNameString.empty()
+ if (!mNameIsSet
|| new_name
|| (!title && !mTitle.empty())
|| (title && mTitle != title->getString())
@@ -3291,18 +3291,18 @@ void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color,
{
mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font);
}
- mNameString += line;
- mNameString += '\n';
+ mNameIsSet |= !line.empty();
}
void LLVOAvatar::clearNameTag()
{
- mNameString.clear();
+ mNameIsSet = false;
if (mNameText)
{
mNameText->setLabel("");
- mNameText->setString( "" );
+ mNameText->setString("");
}
+ mTimeVisible.reset();
}
//static
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index c59a3a150c..9f1f209920 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -939,7 +939,7 @@ protected:
static void getAnimLabels(LLDynamicArray<std::string>* labels);
static void getAnimNames(LLDynamicArray<std::string>* names);
private:
- std::string mNameString; // UTF-8 title + name + status
+ bool mNameIsSet;
std::string mTitle;
bool mNameAway;
bool mNameDoNotDisturb;
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index f3342b7ff1..c3cc90f040 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -1258,7 +1258,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateCreatingSessionGroup
case stateCreatingSessionGroup:
- if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized)
+ if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{
// *TODO: Question: is this the right way out of this state
setState(stateSessionTerminated);
@@ -1274,7 +1274,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateRetrievingParcelVoiceInfo
case stateRetrievingParcelVoiceInfo:
// wait until parcel voice info is received.
- if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized)
+ if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{
// if a terminate request has been received,
// bail and go to the stateSessionTerminated
@@ -1294,7 +1294,7 @@ void LLVivoxVoiceClient::stateMachine()
// Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
sendFriendsListUpdates();
- if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized)
+ if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{
// TODO: Question: Is this the right way out of this state?
setState(stateSessionTerminated);
@@ -1442,7 +1442,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateRunning
case stateRunning: // steady state
// Disabling voice or disconnect requested.
- if(!mVoiceEnabled && mIsInitialized || mSessionTerminateRequested)
+ if((!mVoiceEnabled && mIsInitialized) || mSessionTerminateRequested)
{
leaveAudioSession();
}
@@ -2671,33 +2671,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
{
buddyListEntry *buddy = findBuddy(id);
- // Make sure we don't add a name before it's been looked up.
+ // Make sure we don't add a name before it's been looked up in the avatar name cache
LLAvatarName av_name;
- if(LLAvatarNameCache::get(id, &av_name))
+ if (LLAvatarNameCache::get(id, &av_name))
{
- // *NOTE: For now, we feed legacy names to Vivox because I don't know
- // if their service can support a mix of new and old clients with
- // different sorts of names.
+ // *NOTE: We feed legacy names to Vivox because we don't know if their service
+ // can support a mix of new and old clients with different sorts of names.
std::string name = av_name.getAccountName();
-
- const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
- bool canSeeMeOnline = false;
- if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
- canSeeMeOnline = true;
-
- // When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary.
- if(buddy)
+ if (buddy)
{
- // This buddy is already in both lists.
-
- if(name != buddy->mDisplayName)
- {
- // The buddy is in the list with the wrong name. Update it with the correct name.
- LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
- buddy->mDisplayName = name;
- buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
- }
+ // This buddy is already in both lists (vivox buddies and avatar cache).
+ // Trust the avatar cache more for the display name (vivox display name are notoriously wrong)
+ buddy->mDisplayName = name;
}
else
{
@@ -2706,20 +2692,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
buddy->mUUID = id;
}
- // In all the above cases, the buddy is in the SL friends list (which is how we got here).
- buddy->mInSLFriends = true;
- buddy->mCanSeeMeOnline = canSeeMeOnline;
+ const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
+ buddy->mCanSeeMeOnline = (relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
+ // In all the above cases, the buddy is in the SL friends list and tha name has been resolved (which is how we got here).
buddy->mNameResolved = true;
-
+ buddy->mInSLFriends = true;
}
else
{
- // This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has.
- if(buddy)
+ // This name hasn't been looked up yet in the avatar cache. Don't do anything with this buddy list entry until it has.
+ if (buddy)
{
buddy->mNameResolved = false;
}
-
// Initiate a lookup.
// The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
lookupName(id);
@@ -2827,13 +2812,12 @@ void LLVivoxVoiceClient::sendFriendsListUpdates()
{
std::ostringstream stream;
- if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
+ if(buddy->mInSLFriends && !buddy->mInVivoxBuddies)
{
if(mNumberOfAliases > 0)
{
// Add (or update) this entry in the vivox buddy list
buddy->mInVivoxBuddies = true;
- buddy->mNeedsNameUpdate = false;
LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
@@ -5859,7 +5843,6 @@ LLVivoxVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
mNameResolved = false;
mInVivoxBuddies = false;
mInSLFriends = false;
- mNeedsNameUpdate = false;
}
void LLVivoxVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
@@ -5884,25 +5867,21 @@ LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::addBuddy(const std::stri
buddyListEntry *result = NULL;
buddyListMap::iterator iter = mBuddyListMap.find(uri);
- if(iter != mBuddyListMap.end())
+ if (iter != mBuddyListMap.end())
{
// Found a matching buddy already in the map.
LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
result = iter->second;
}
- if(!result)
+ if (!result)
{
// participant isn't already in one list or the other.
LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
result = new buddyListEntry(uri);
result->mDisplayName = displayName;
- if(IDFromName(uri, result->mUUID))
- {
- // Extracted UUID from name successfully.
- }
- else
+ if (!IDFromName(uri, result->mUUID))
{
LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
}
@@ -7272,7 +7251,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
void LLVivoxProtocolParser::EndTag(const char *tag)
{
const std::string& string = textBuffer;
-
+
responseDepth--;
if (ignoringTags)
@@ -7371,6 +7350,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
}
else if (!stricmp("Buddy", tag))
{
+ // NOTE : Vivox does *not* give reliable display name for Buddy tags
+ // We don't take those very seriously as a result...
LLVivoxVoiceClient::getInstance()->processBuddyListEntry(uriString, displayNameString);
}
else if (!stricmp("BlockRule", tag))
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 574027de42..a6f40eb3e9 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -584,7 +584,6 @@ protected:
bool mNameResolved;
bool mInSLFriends;
bool mInVivoxBuddies;
- bool mNeedsNameUpdate;
};
typedef std::map<std::string, buddyListEntry*> buddyListMap;
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index ccc513b80d..11b2770ec0 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -965,8 +965,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
S32 text_x = x;
S32 text_y = (S32)(y - sTrackCircleImage->getHeight()/2 - font->getLineHeight());
- BOOL is_in_window = true;
-
if( x < 0
|| y < 0
|| x >= getRect().getWidth()
@@ -979,7 +977,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
text_x = sTrackingArrowX;
text_y = sTrackingArrowY;
}
- is_in_window = false;
}
else if (LLTracker::getTrackingStatus() == LLTracker::TRACKING_LOCATION &&
LLTracker::getTrackedLocationType() != LLTracker::LOCATION_NOTHING)
diff --git a/indra/newview/skins/default/textures/icons/collapse_to_one_line.png b/indra/newview/skins/default/textures/icons/collapse_to_one_line.png
new file mode 100644
index 0000000000..d57144a645
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/collapse_to_one_line.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/expand_one_liner.png b/indra/newview/skins/default/textures/icons/expand_one_liner.png
new file mode 100644
index 0000000000..58b7d90131
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/expand_one_liner.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index a07d7e4855..93c9cb02cb 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -171,6 +171,8 @@ with the same filename but different name
<texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" />
<texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" />
<texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" />
+ <texture name="Conv_collapse_to_one_line" file_name="icons/collapse_to_one_line.png" preload="false" />
+ <texture name="Conv_expand_one_line" file_name="icons/expand_one_liner.png" preload="false" />
<texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" />
<texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" />
<texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 12c1676127..65f623a47e 100644
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -61,7 +61,7 @@
image_unselected="Toolbar_Middle_Off"
menu_filename="menu_participant_view.xml"
layout="topleft"
- left="10"
+ left="5"
name="sort_btn"
tool_tip="View/sort options"
top="5"
@@ -75,7 +75,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="4"
+ left_pad="2"
name="add_btn"
tool_tip="Start a new conversation"
width="31"/>
@@ -88,7 +88,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="4"
+ left_pad="2"
name="speak_btn"
tool_tip="Speak with people using your microphone"
width="31"/>
@@ -114,7 +114,7 @@
</layout_panel>
</layout_stack>
<panel
- bottom="-5"
+ bottom="-1"
follows="all"
layout="topleft"
name="conversations_list_panel"
@@ -129,7 +129,7 @@
name="messages_layout_panel"
expanded_min_dim="222">
<panel_container
- bottom="-5"
+ bottom="-1"
follows="all"
layout="topleft"
left="0"
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 8f0574177f..d8b085063f 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -14,12 +14,17 @@
width="394"
can_resize="true"
can_tear_off="false"
- min_width="340"
min_height="190"
positioning="relative">
<floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string>
<floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string>
<floater.string
+ name="collapseline_icon"
+ value="Conv_collapse_to_one_line"/>
+ <floater.string
+ name="expandline_icon"
+ value="Conv_expand_one_line"/>
+ <floater.string
name="collapse_icon"
value="Conv_toolbar_collapse"/>
<floater.string
@@ -65,14 +70,28 @@
top="0"
left="0"
height="355"
- width="394">
- <panel
+ width="394">
+ <layout_stack
+ animate="false"
+ default_tab_group="2"
+ follows="all"
+ height="355"
+ width="394"
+ layout="topleft"
+ orientation="vertical"
+ name="main_stack"
+ tab_group="1"
+ top="0"
+ left="0">
+
+ <layout_panel
follows="left|top|right"
layout="topleft"
name="toolbar_panel"
top="0"
left="0"
height="35"
+ min_height="35"
width="394">
<menu_button
menu_filename="menu_im_session_showmodes.xml"
@@ -98,7 +117,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="4"
+ left_pad="2"
name="gear_btn"
visible="false"
tool_tip="Actions on selected person"
@@ -113,7 +132,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="4"
+ left_pad="2"
name="add_btn"
tool_tip="Add someone to this conversation"
width="31"/>
@@ -126,7 +145,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="4"
+ left_pad="2"
name="voice_call_btn"
tool_tip="Open voice connection"
width="31"/>
@@ -151,7 +170,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left="283"
+ left="292"
name="close_btn"
tool_tip="End this conversation"
width="31" />
@@ -164,7 +183,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="5"
+ left_pad="2"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this pane"
width="31" />
@@ -177,15 +196,22 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
- left_pad="5"
+ left_pad="2"
name="tear_off_btn"
width="31" />
- </panel>
+ </layout_panel>
+ <layout_panel
+ name="body_panel"
+ follows="all"
+ width="394"
+ height="235"
+ user_resize="false"
+ auto_resize="true">
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
- height="310"
+ height="275"
width="394"
layout="topleft"
orientation="horizontal"
@@ -196,11 +222,12 @@
<layout_panel
name="speakers_list_panel"
follows="all"
- min_width="115"
+ expanded_min_dim="115"
+ min_dim="0"
width="150"
- height="310"
+ height="275"
user_resize="true"
- auto_resize="true">
+ auto_resize="false">
</layout_panel>
<layout_panel
default_tab_group="3"
@@ -208,26 +235,26 @@
tab_group="2"
follows="all"
top="0"
- height="310"
+ height="275"
width="244"
layout="topleft"
user_resize="true"
auto_resize="true"
visible="true"
- name="left_part_holder"
+ name="right_part_holder"
min_width="221">
<panel
name="trnsAndChat_panel"
follows="all"
layout="topleft"
visible="true"
- height="275"
+ height="240"
width="244">
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
- height="275"
+ height="240"
width="244"
layout="topleft"
visible="true"
@@ -239,6 +266,7 @@
left="0">
<layout_panel
auto_resize="false"
+ user_resize="false"
height="26"
layout="topleft"
left_delta="0"
@@ -258,7 +286,6 @@
width="230" />
</layout_panel>
<layout_panel
- height="248"
width="210"
layout="topleft"
follows="all"
@@ -266,43 +293,109 @@
top_delta="0"
bottom="0"
visible="true"
- user_resize="true"
+ user_resize="false"
auto_resize="true"
name="chat_holder">
<chat_history
font="SansSerifSmall"
follows="all"
visible="true"
- height="240"
name="chat_history"
parse_highlights="true"
parse_urls="true"
+ layout="topleft"
right="-5"
- left="5">
+ left="5"
+ top="0"
+ bottom="1">
</chat_history>
</layout_panel>
</layout_stack>
</panel>
- <chat_editor
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ <layout_panel
+ height="35"
+ layout="topleft"
+ follows="left|right|bottom"
+ left_delta="0"
+ right="0"
+ top_delta="0"
bottom="0"
+ visible="true"
+ user_resize="false"
+ auto_resize="false"
+ name="chat_layout_panel">
+ <layout_stack
+ animate="true"
+ default_tab_group="2"
+ follows="all"
+ height="35"
+ right="0"
+ layout="topleft"
+ orientation="horizontal"
+ name="input_panels"
+ top_pad="0"
+ left="0">
+ <layout_panel
+ height="35"
+ layout="topleft"
+ follows="left|right|bottom"
+ left_delta="0"
+ top_delta="0"
+ bottom="0"
+ visible="true"
+ user_resize="false"
+ auto_resize="true"
+ name="input_editor_layout_panel">
+ <chat_editor
expand_lines_count="5"
follows="left|right|bottom"
- font="SansSerifSmall"
+ font="SansSerifSmall"
visible="true"
height="20"
is_expandable="true"
label="To"
text_tentative_color="TextFgTentativeColor"
- layout="bottomleft"
+ layout="topleft"
name="chat_editor"
max_length="1023"
spellcheck="true"
tab_group="3"
- width="220"
- left="10"
+ width="160"
+ top="6"
+ left="5"
+ right="-5"
wrap="true">
</chat_editor>
- </layout_panel>
+ </layout_panel>
+ <layout_panel
+ height="35"
+ layout="topleft"
+ follows="left|right|bottom"
+ left_delta="0"
+ top_delta="0"
+ bottom="0"
+ width="35"
+ visible="true"
+ user_resize="false"
+ auto_resize="false"
+ name="input_button_layout_panel">
+ <button
+ follows="left|right|bottom"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Conv_expand_one_line"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ name="minz_btn"
+ tool_tip="Shows/hides message panel"
+ width="28"/>
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
</layout_stack>
</view>
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index fd5c86b3ca..5a13ef0a59 100644
--- a/indra/newview/skins/default/xui/en/menu_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -89,7 +89,14 @@
<on_click function="Avatar.DoToSelected" parameter="invite_to_group" />
<on_enable function="Avatar.EnableItem" parameter="can_invite" />
</menu_item_call>
- <menu_item_separator layout="topleft" name="separator_invite_to_group"/>
+ <menu_item_separator layout="topleft" name="separator_invite_to_group"/>
+ <menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ <on_click function="Avatar.DoToSelected" parameter="zoom_in" />
+ <on_enable function="Avatar.EnableItem" parameter="can_zoom_in" />
+ </menu_item_call>
<menu_item_call
label="Map"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_im_conversation.xml b/indra/newview/skins/default/xui/en/menu_im_conversation.xml
index 8882d0a7d8..43287c6ec3 100644
--- a/indra/newview/skins/default/xui/en/menu_im_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_im_conversation.xml
@@ -50,6 +50,13 @@
<menu_item_separator
layout="topleft"/>
<menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ <on_click function="Avatar.DoToSelected" parameter="zoom_in" />
+ <on_enable function="Avatar.EnableItem" parameter="can_zoom_in" />
+ </menu_item_call>
+ <menu_item_call
label="Map"
layout="topleft"
name="map">
diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml
index 0c8a2af002..2d4f1792c2 100644
--- a/indra/newview/skins/default/xui/en/menu_object_icon.xml
+++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml
@@ -24,4 +24,22 @@
function="ObjectIcon.Action"
parameter="block" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="map" />
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport to Object Location"
+ layout="topleft"
+ name="teleport_to_object">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="teleport" />
+ </menu_item_call>
</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
index 60a6c98514..3abb5f7bc8 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu
layout="topleft"
- name="Avatar Context Menu">
+ name="Nearby People Context Menu">
<menu_item_call
label="View Profile"
layout="topleft"
- name="View Profile">
+ name="view_profile">
<menu_item_call.on_click
function="Avatar.Profile" />
</menu_item_call>
<menu_item_call
label="IM"
layout="topleft"
- name="IM">
+ name="im">
<menu_item_call.on_click
function="Avatar.IM" />
<menu_item_call.on_enable
@@ -21,7 +21,7 @@
</menu_item_call>
<menu_item_call
label="Offer Teleport"
- name="teleport">
+ name="offer_teleport">
<menu_item_call.on_click
function="Avatar.OfferTeleport"/>
<menu_item_call.on_enable
@@ -31,7 +31,7 @@
<menu_item_call
label="Voice call"
layout="topleft"
- name="Call">
+ name="voice_call">
<menu_item_call.on_click
function="Avatar.Call" />
<menu_item_call.on_enable
@@ -42,18 +42,18 @@
<menu_item_call
label="View chat history..."
layout="topleft"
- name="Chat history">
+ name="chat_history">
<menu_item_call.on_click
function="Avatar.Calllog" />
<menu_item_call.on_enable
function="Avatar.EnableItem"
parameter="can_callog"/>
</menu_item_call>
- <menu_item_separator />
+ <menu_item_separator name="separator_chat_history"/>
<menu_item_call
label="Add Friend"
layout="topleft"
- name="Add Friend">
+ name="add_friend">
<menu_item_call.on_click
function="Avatar.AddFriend" />
<menu_item_call.on_visible
@@ -63,7 +63,7 @@
<menu_item_call
label="Remove Friend"
layout="topleft"
- name="Remove Friend">
+ name="remove_friend">
<menu_item_call.on_click
function="Avatar.RemoveFriend" />
<menu_item_call.on_enable
@@ -73,18 +73,28 @@
<menu_item_call
label="Invite to group..."
layout="topleft"
- name="Invite">
+ name="invite_to_group">
<menu_item_call.on_click
function="Avatar.InviteToGroup" />
<menu_item_call.on_enable
function="Avatar.EnableItem"
parameter="can_invite"/>
</menu_item_call>
- <menu_item_separator />
+ <menu_item_separator name="separator_invite_to_group"/>
+ <menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ <menu_item_call.on_click
+ function="Avatar.ZoomIn" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_zoom_in"/>
+ </menu_item_call>
<menu_item_call
label="Map"
layout="topleft"
- name="Map">
+ name="map">
<menu_item_call.on_click
function="Avatar.ShowOnMap" />
<menu_item_call.on_enable
@@ -94,7 +104,7 @@
<menu_item_call
label="Share"
layout="topleft"
- name="Share">
+ name="share">
<menu_item_call.on_click
function="Avatar.Share" />
<menu_item_call.on_enable
@@ -104,7 +114,7 @@
<menu_item_call
label="Pay"
layout="topleft"
- name="Pay">
+ name="pay">
<menu_item_call.on_click
function="Avatar.Pay" />
<menu_item_call.on_enable
@@ -114,7 +124,7 @@
<menu_item_check
label="Block/Unblock"
layout="topleft"
- name="Block/Unblock">
+ name="block_unblock">
<menu_item_check.on_click
function="Avatar.BlockUnblock" />
<menu_item_check.on_check
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
index 5d58a9d289..5f973088fd 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
@@ -6,7 +6,7 @@
enabled="false"
label="Add Friends"
layout="topleft"
- name="Add Friends">
+ name="add_friends">
<on_click
function="Avatar.AddFriends" />
<on_enable
@@ -16,7 +16,7 @@
<menu_item_call
label="Remove Friends"
layout="topleft"
- name="Remove Friend">
+ name="remove_friends">
<menu_item_call.on_click
function="Avatar.RemoveFriend" />
<menu_item_call.on_enable
@@ -26,7 +26,7 @@
<menu_item_call
label="IM"
layout="topleft"
- name="IM">
+ name="im">
<on_click
function="Avatar.IM" />
</menu_item_call>
@@ -34,7 +34,7 @@
enabled="false"
label="Call"
layout="topleft"
- name="Call">
+ name="call">
<on_click
function="Avatar.Call" />
<on_enable
@@ -45,7 +45,7 @@
enabled="false"
label="Share"
layout="topleft"
- name="Share">
+ name="share">
<on_click
function="Avatar.Share" />
</menu_item_call>
@@ -53,13 +53,13 @@
enabled="false"
label="Pay"
layout="topleft"
- name="Pay">
+ name="pay">
<on_click
function="Avatar.Pay" />
</menu_item_call>
<menu_item_call
label="Offer Teleport"
- name="teleport">
+ name="offer_teleport">
<menu_item_call.on_click
function="Avatar.OfferTeleport"/>
<menu_item_call.on_enable
diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml
index 88ae441bd3..7cd56f257a 100644
--- a/indra/newview/skins/default/xui/en/menu_url_agent.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml
@@ -1,20 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu
layout="topleft"
- name="Url Popup">
+ name="Url Popup">
<menu_item_call
- label="Send IM"
+ label="View Profile"
layout="topleft"
name="show_agent">
<menu_item_call.on_click
+ function="Url.ShowProfile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Send IM..."
+ layout="topleft"
+ name="send_im">
+ <menu_item_call.on_click
function="Url.SendIM" />
</menu_item_call>
<menu_item_call
- label="Show Resident Profile"
+ label="Add Friend..."
layout="topleft"
- name="show_agent">
+ name="add_friend">
<menu_item_call.on_click
- function="Url.ShowProfile" />
+ function="Url.AddFriend" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
diff --git a/indra/newview/skins/default/xui/en/menu_url_group.xml b/indra/newview/skins/default/xui/en/menu_url_group.xml
index c5eaf94d22..2cb125ce09 100644
--- a/indra/newview/skins/default/xui/en/menu_url_group.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_group.xml
@@ -7,7 +7,7 @@
layout="topleft"
name="show_group">
<menu_item_call.on_click
- function="Url.Execute" />
+ function="Url.ShowProfile" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
index 35c2269b0d..87ab58e622 100644
--- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
@@ -3,7 +3,7 @@
layout="topleft"
name="Url Popup">
<menu_item_call
- label="Show Object Information"
+ label="Object Profile..."
layout="topleft"
name="show_object">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 88c02fc84e..c681e39002 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -9998,7 +9998,7 @@ Cannot create large prims that intersect other players. Please re-try when othe
icon="alertmodal.tga"
name="PreferenceChatClearLog"
type="alertmodal">
- This will delete the log of previous conversations. Proceed?
+ This will delete the logs of previous conversations, and any backups of that file.
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before I delete the log of previous conversations."
@@ -10011,7 +10011,7 @@ Cannot create large prims that intersect other players. Please re-try when othe
icon="alertmodal.tga"
name="PreferenceChatDeleteTranscripts"
type="alertmodal">
- This will delete transcripts for all previous conversations. The list of conversations will not be affected. If you run scripts on your chat transcript files, you may want to proceed with caution. Proceed?
+ This will delete the transcripts for all previous conversations. The list of past conversations will not be affected. All files with the suffixes .txt and txt.backup in the folder [FOLDER] will be deleted.
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before I delete transcripts."
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index 9db3816c92..bd096ebb88 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -429,7 +429,6 @@
</text>
<line_editor
- enabled="false"
control_name="InstantMessageLogPath"
border_style="line"
border_thickness="1"