diff options
Diffstat (limited to 'indra/newview')
26 files changed, 375 insertions, 154 deletions
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." |