summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llrender/llfontgl.cpp5
-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/lltextbase.cpp11
-rw-r--r--indra/llui/lltexteditor.cpp1
-rw-r--r--indra/llui/llurlaction.cpp31
-rw-r--r--indra/llui/llurlaction.h2
-rw-r--r--indra/newview/app_settings/settings.xml22
-rwxr-xr-xindra/newview/llavataractions.cpp2
-rw-r--r--indra/newview/llchathistory.cpp22
-rw-r--r--indra/newview/llconversationlog.cpp33
-rw-r--r--indra/newview/llconversationlog.h2
-rw-r--r--indra/newview/llconversationloglist.cpp69
-rwxr-xr-xindra/newview/llconversationview.cpp51
-rwxr-xr-xindra/newview/llconversationview.h2
-rw-r--r--indra/newview/llfloaterimcontainer.cpp88
-rw-r--r--indra/newview/llfloaterimcontainer.h7
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp11
-rw-r--r--indra/newview/llfloaterimnearbychat.h1
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp31
-rw-r--r--indra/newview/llfloaterimsessiontab.h1
-rwxr-xr-xindra/newview/llfloaterpreference.cpp5
-rw-r--r--indra/newview/llimview.cpp5
-rw-r--r--indra/newview/lllogchat.cpp22
-rw-r--r--indra/newview/lllogchat.h2
-rw-r--r--indra/newview/llspeakers.cpp28
-rw-r--r--indra/newview/llspeakers.h1
-rw-r--r--indra/newview/llvoavatar.cpp81
-rw-r--r--indra/newview/skins/default/xui/en/menu_object_icon.xml18
-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
36 files changed, 439 insertions, 171 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/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/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 4bb819a7f6..c4ec1edc73 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1086,7 +1086,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 +1919,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 +2338,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;
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/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..e216c7865d 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>
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/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 4be169e267..dd20ca15ae 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
@@ -380,6 +382,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 +607,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..b202cfc9d3 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;
@@ -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/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/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 413707baae..7437dd8cda 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -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();
@@ -667,7 +669,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 +678,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 +692,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 +702,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 +733,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 +767,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()
@@ -1400,6 +1405,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
@@ -1878,6 +1887,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 +1917,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 +1950,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;
}
}
@@ -1955,11 +1974,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..5139651d8d 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -72,7 +72,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 +129,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);
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index dfaf4bbdd6..cfee5001a6 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -257,6 +257,17 @@ 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()
{
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/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index d3fcfbbc56..9fd22b1537 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -61,6 +61,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
, mRefreshTimer(new LLTimer())
, mIsHostAttached(false)
, mHasVisibleBeenInitialized(false)
+ , mIsParticipantListExpanded(true)
{
setAutoFocus(FALSE);
mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
@@ -180,6 +181,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
@@ -253,6 +255,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
@@ -268,6 +271,12 @@ BOOL LLFloaterIMSessionTab::postBuild()
mRefreshTimer->setTimerExpirySec(0);
mRefreshTimer->start();
initBtns();
+
+ if (mIsParticipantListExpanded != (bool)gSavedSettings.getBOOL("IMShowControlPanel"))
+ {
+ LLFloaterIMSessionTab::onSlide(this);
+ }
+
return result;
}
@@ -324,13 +333,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,7 +646,7 @@ 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);
@@ -775,9 +777,8 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
// Expand/collapse the IM control panel
self->mParticipantListPanel->setVisible(expand);
-
- gSavedSettings.setBOOL("IMShowControlPanel", expand);
-
+ gSavedSettings.setBOOL("IMShowControlPanel", expand);
+ self->mIsParticipantListExpanded = expand;
self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon"));
}
}
@@ -801,10 +802,18 @@ void LLFloaterIMSessionTab::onTearOffClicked()
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);
+ }
refreshConversation();
updateGearBtn();
}
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index d55b021df7..e8ae557412 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -138,6 +138,7 @@ protected:
bool mIsNearbyChat;
bool mIsP2PChat;
+ bool mIsParticipantListExpanded;
LLIMModel::LLIMSession* mSession;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 3f8c23ba83..b308a820b2 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1667,7 +1667,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..37f5888e8c 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -285,6 +285,11 @@ void on_new_message(const LLSD& msg)
{
//Surface conversations floater
LLFloaterReg::showInstance("im_container");
+
+ if (session_floater && session_floater->isMinimized())
+ {
+ LLFloater::onClickMinimize(session_floater);
+ }
}
//If in DND mode, allow notification to be stored so upon DND exit
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/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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 157be08f45..c74d9f1292 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -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);
@@ -3303,6 +3303,7 @@ void LLVOAvatar::clearNameTag()
mNameText->setLabel("");
mNameText->setString( "" );
}
+ mTimeVisible.reset();
}
//static
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_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."