From 0ee0a5eff41a3763b1fc3fc45a36f87fc6eedac5 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 27 Jul 2012 22:25:17 +0300 Subject: CHUI-151 FIXED (Implement conversation log) A brief explanation of what have been implemented. More information can be found in comments. 1. Created conversation history viewer (llfloaterconversationpreview) 2. Created LLConversation and LLConversationLog classes which represent and hold data of conversations (llconversationlog) 3. Created LLConversationLogList and LLConversationLogListItem which are the visual representation of LLConversationLog and LLConversation respectively 4. Created LLFloaterConversationLog - which holds and displays LLConversationLogList --- indra/newview/llfloaterconversationlog.cpp | 127 +++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 indra/newview/llfloaterconversationlog.cpp (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp new file mode 100644 index 0000000000..569ba12ed6 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.cpp @@ -0,0 +1,127 @@ +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +: LLFloater(key), + mConversationLogList(NULL) +{ + mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ + mConversationLogList = getChild("conversation_log_list"); + + switch (gSavedSettings.getU32("CallLogSortOrder")) + { + case E_SORT_BY_NAME: + mConversationLogList->sortByName(); + break; + + case E_SORT_BY_DATE: + mConversationLogList->sortByDate(); + break; + } + + // Use the context menu of the Conversation list for the Conversation tab gear menu. + LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); + if (conversations_gear_menu) + { + getChild("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + + getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + + return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ + std::string filter = search_string; + LLStringUtil::trimHead(filter); + + mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + if ("sort_by_name" == command_name) + { + mConversationLogList->sortByName(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + } + else if ("sort_by_date" == command_name) + { + mConversationLogList->sortByDate(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + } + else if ("sort_friends_on_top" == command_name) + { + mConversationLogList->toggleSortFriendsOnTop(); + } +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ + return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + + if ("sort_by_name" == command_name) + { + return sort_order == E_SORT_BY_NAME; + } + else if ("sort_by_date" == command_name) + { + return sort_order == E_SORT_BY_DATE; + } + else if ("sort_friends_on_top" == command_name) + { + return gSavedSettings.getBOOL("SortFriendsFirst"); + } + + return false; +} -- cgit v1.3 From f9ccd6bc9d9a1da849ac21913ff870e2db8ad6a1 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Fri, 27 Jul 2012 23:46:25 +0300 Subject: Fixed line endings in files added in CHUI-151. --- indra/newview/llfloaterconversationlog.cpp | 254 ++++++++++++++--------------- indra/newview/llfloaterconversationlog.h | 122 +++++++------- 2 files changed, 188 insertions(+), 188 deletions(-) (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 569ba12ed6..c77a9e74bb 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -1,127 +1,127 @@ -/** - * @file llfloaterconversationlog.cpp - * @brief Functionality of the "conversation log" floater - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#include "llviewerprecompiledheaders.h" - -#include "llconversationloglist.h" -#include "llfiltereditor.h" -#include "llfloaterconversationlog.h" -#include "llmenubutton.h" - -LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) -: LLFloater(key), - mConversationLogList(NULL) -{ - mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); - mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); -} - -BOOL LLFloaterConversationLog::postBuild() -{ - mConversationLogList = getChild("conversation_log_list"); - - switch (gSavedSettings.getU32("CallLogSortOrder")) - { - case E_SORT_BY_NAME: - mConversationLogList->sortByName(); - break; - - case E_SORT_BY_DATE: - mConversationLogList->sortByDate(); - break; - } - - // Use the context menu of the Conversation list for the Conversation tab gear menu. - LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); - if (conversations_gear_menu) - { - getChild("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); - } - - getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); - - return LLFloater::postBuild(); -} - -void LLFloaterConversationLog::draw() -{ - LLFloater::draw(); -} - -void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) -{ - std::string filter = search_string; - LLStringUtil::trimHead(filter); - - mConversationLogList->setNameFilter(filter); -} - - -void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) -{ - const std::string command_name = userdata.asString(); - - if ("sort_by_name" == command_name) - { - mConversationLogList->sortByName(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); - } - else if ("sort_by_date" == command_name) - { - mConversationLogList->sortByDate(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); - } - else if ("sort_friends_on_top" == command_name) - { - mConversationLogList->toggleSortFriendsOnTop(); - } -} - -bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) -{ - return true; -} - -bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) -{ - const std::string command_name = userdata.asString(); - - U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); - - if ("sort_by_name" == command_name) - { - return sort_order == E_SORT_BY_NAME; - } - else if ("sort_by_date" == command_name) - { - return sort_order == E_SORT_BY_DATE; - } - else if ("sort_friends_on_top" == command_name) - { - return gSavedSettings.getBOOL("SortFriendsFirst"); - } - - return false; -} +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +: LLFloater(key), + mConversationLogList(NULL) +{ + mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ + mConversationLogList = getChild("conversation_log_list"); + + switch (gSavedSettings.getU32("CallLogSortOrder")) + { + case E_SORT_BY_NAME: + mConversationLogList->sortByName(); + break; + + case E_SORT_BY_DATE: + mConversationLogList->sortByDate(); + break; + } + + // Use the context menu of the Conversation list for the Conversation tab gear menu. + LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); + if (conversations_gear_menu) + { + getChild("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + + getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + + return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ + std::string filter = search_string; + LLStringUtil::trimHead(filter); + + mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + if ("sort_by_name" == command_name) + { + mConversationLogList->sortByName(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + } + else if ("sort_by_date" == command_name) + { + mConversationLogList->sortByDate(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + } + else if ("sort_friends_on_top" == command_name) + { + mConversationLogList->toggleSortFriendsOnTop(); + } +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ + return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + + if ("sort_by_name" == command_name) + { + return sort_order == E_SORT_BY_NAME; + } + else if ("sort_by_date" == command_name) + { + return sort_order == E_SORT_BY_DATE; + } + else if ("sort_friends_on_top" == command_name) + { + return gSavedSettings.getBOOL("SortFriendsFirst"); + } + + return false; +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 40dd266663..7d788c0290 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -1,61 +1,61 @@ -/** - * @file llfloaterconversationlog.h - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ -#define LL_LLFLOATERCONVERSATIONLOG_H_ - -#include "llfloater.h" - -class LLConversationLogList; - -class LLFloaterConversationLog : public LLFloater -{ -public: - - typedef enum e_sort_oder{ - E_SORT_BY_NAME = 0, - E_SORT_BY_DATE = 1, - } ESortOrder; - - LLFloaterConversationLog(const LLSD& key); - virtual ~LLFloaterConversationLog(){}; - - virtual BOOL postBuild(); - - virtual void draw(); - - void onFilterEdit(const std::string& search_string); - -private: - - void onCustomAction (const LLSD& userdata); - bool isActionEnabled(const LLSD& userdata); - bool isActionChecked(const LLSD& userdata); - - LLConversationLogList* mConversationLogList; -}; - - -#endif /* LLFLOATERCONVERSATIONLOG_H_ */ +/** + * @file llfloaterconversationlog.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ +#define LL_LLFLOATERCONVERSATIONLOG_H_ + +#include "llfloater.h" + +class LLConversationLogList; + +class LLFloaterConversationLog : public LLFloater +{ +public: + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_DATE = 1, + } ESortOrder; + + LLFloaterConversationLog(const LLSD& key); + virtual ~LLFloaterConversationLog(){}; + + virtual BOOL postBuild(); + + virtual void draw(); + + void onFilterEdit(const std::string& search_string); + +private: + + void onCustomAction (const LLSD& userdata); + bool isActionEnabled(const LLSD& userdata); + bool isActionChecked(const LLSD& userdata); + + LLConversationLogList* mConversationLogList; +}; + + +#endif /* LLFLOATERCONVERSATIONLOG_H_ */ -- cgit v1.3 From dab6788c42260135d298b619ff92a71838bba2b8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 31 Aug 2012 11:57:36 +0300 Subject: CHUI-157 FIXED (Implement menu bar for conversation floater) - Added View Nearby chat history option - Also replaced menu item "Add Friend / Remove" with two separate menus: Add Friend and Remove Friend. So if user is a Friend the Remove Friend option would be shown there. If the user is not a friend, the Add Friend option would be shown. --- indra/newview/llconversationloglist.cpp | 17 ++++++--- indra/newview/llfloaterconversationlog.cpp | 5 +++ indra/newview/llfloaterconversationpreview.cpp | 40 ++++++++++++---------- indra/newview/llfloaterconversationpreview.h | 2 +- .../default/xui/en/menu_conversation_log_gear.xml | 28 +++++++++------ .../default/xui/en/menu_conversation_log_view.xml | 8 +++++ 6 files changed, 66 insertions(+), 34 deletions(-) (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 257ec082a5..94be9055bd 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -241,15 +241,18 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) { LLAvatarActions::offerTeleport(selected_id); } - else if("add_rem_friend" == command_name) + else if("add_friend" == command_name) { - if (LLAvatarActions::isFriend(selected_id)) + if (!LLAvatarActions::isFriend(selected_id)) { - LLAvatarActions::removeFriendDialog(selected_id); + LLAvatarActions::requestFriendshipDialog(selected_id); } - else + } + else if("remove_friend" == command_name) + { + if (LLAvatarActions::isFriend(selected_id)) { - LLAvatarActions::requestFriendshipDialog(selected_id); + LLAvatarActions::removeFriendDialog(selected_id); } } else if ("invite_to_group" == command_name) @@ -336,6 +339,10 @@ bool LLConversationLogList::isActionChecked(const LLSD& userdata) { return is_p2p && LLAvatarActions::isFriend(selected_id); } + else if ("is_not_friend" == command_name) + { + return is_p2p && !LLAvatarActions::isFriend(selected_id); + } return false; } diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index c77a9e74bb..4375ce5726 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -28,6 +28,7 @@ #include "llconversationloglist.h" #include "llfiltereditor.h" #include "llfloaterconversationlog.h" +#include "llfloaterreg.h" #include "llmenubutton.h" LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) @@ -97,6 +98,10 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) { mConversationLogList->toggleSortFriendsOnTop(); } + else if ("view_nearby_chat_history" == command_name) + { + LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); + } } bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index ae6f1441eb..7083fb987d 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" +#include "lltrans.h" LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) : LLFloater(session_id), @@ -44,20 +45,28 @@ BOOL LLFloaterConversationPreview::postBuild() getChild("more_history")->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); - if (conv) - { - std::string name = conv->getConversationName(); - LLStringUtil::format_map_t args; - args["[NAME]"] = name; - std::string title = getString("Title", args); - setTitle(title); + std::string name; + std::string file; - getChild("description")->setValue(name); + if (mSessionID != LLUUID::null && conv) + { + name = conv->getConversationName(); + file = conv->getHistoryFileName(); + } + else + { + name = LLTrans::getString("NearbyChatTitle"); + file = "chat"; } - std::string file = conv->getHistoryFileName(); - LLLogChat::loadChatHistory(file, mMessages, true); + LLStringUtil::format_map_t args; + args["[NAME]"] = name; + std::string title = getString("Title", args); + setTitle(title); + + getChild("description")->setValue(name); + LLLogChat::loadChatHistory(file, mMessages, true); mCurrentPage = mMessages.size() / mPageSize; return LLFloater::postBuild(); @@ -68,7 +77,7 @@ void LLFloaterConversationPreview::draw() LLFloater::draw(); } -void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +void LLFloaterConversationPreview::onOpen(const LLSD& key) { showHistory(); } @@ -88,13 +97,8 @@ void LLFloaterConversationPreview::showHistory() int delta = 0; if (mCurrentPage) { - // stinson 08/28/2012 : This operation could be simplified using integer math with the mod (%) operator. - // e.g. The following code should give the same output. - // int remainder = mMessages.size() % mPageSize; - // delta = (remainder == 0) ? 0 : (mPageSize - remainder); - // Though without examining further, the remainder might be a more appropriate value. - double num_of_pages = static_cast(mMessages.size()) / static_cast(mPageSize); - delta = static_cast((ceil(num_of_pages) - num_of_pages) * static_cast(mPageSize)); + int remainder = mMessages.size() % mPageSize; + delta = (remainder == 0) ? 0 : (mPageSize - remainder); } std::advance(iter, (mCurrentPage * mPageSize) - delta); diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 5105ef3702..2246a44761 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -39,7 +39,7 @@ public: virtual BOOL postBuild(); virtual void draw(); - virtual void onOpen(const LLSD& session_id); + virtual void onOpen(const LLSD& key); private: void onMoreHistoryBtnClick(); diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml index b8d0eef956..8796b87955 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -57,20 +57,28 @@ parameter="can_offer_teleport"/> - - + - + + + + + - - + + + + + -- cgit v1.3 From 1e2dcbfb3fbc8717ea594365ff165115b29df83a Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Tue, 11 Sep 2012 17:45:49 +0300 Subject: CHUI-326 FIXED (One entry per conversation with a user in conversation log timestamped with most recent utterance/activity.) - Modified LLConversationLog to show only one entry per conversation with user. I.e. there can't be two conversations with the same session_id in LLConversationLog. - Got rid of processing voice sessions - Refactored creation of conversation in LLConversationLog - Refactored a little bit LLConversation and LLConversationLog: function names and made some functions private --- indra/newview/llconversationlog.cpp | 141 ++++++++++++++++------------ indra/newview/llconversationlog.h | 44 +++++---- indra/newview/llconversationloglist.cpp | 57 ++++++++--- indra/newview/llconversationloglist.h | 9 ++ indra/newview/llconversationloglistitem.cpp | 10 ++ indra/newview/llconversationloglistitem.h | 8 +- indra/newview/llfloaterconversationlog.cpp | 12 +-- indra/newview/llfloaterconversationlog.h | 5 - 8 files changed, 187 insertions(+), 99 deletions(-) (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index cc02e18698..239a89015f 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -37,7 +37,7 @@ struct Conversation_params Conversation_params(time_t time) : mTime(time), mTimestamp(LLConversation::createTimestamp(time)), - mIsConversationPast(true) + mIsVoice(false) {} time_t mTime; @@ -48,7 +48,6 @@ struct Conversation_params LLUUID mSessionID; LLUUID mParticipantID; bool mIsVoice; - bool mIsConversationPast; bool mHasOfflineIMs; }; @@ -65,7 +64,6 @@ LLConversation::LLConversation(const Conversation_params& params) mSessionID(params.mSessionID), mParticipantID(params.mParticipantID), mIsVoice(params.mIsVoice), - mIsConversationPast(params.mIsConversationPast), mHasOfflineIMs(params.mHasOfflineIMs) { setListenIMFloaterOpened(); @@ -80,7 +78,6 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session) mSessionID(session.mSessionID), mParticipantID(session.mOtherParticipantID), mIsVoice(session.mStartedAsIMCall), - mIsConversationPast(false), mHasOfflineIMs(session.mHasOfflineMessage) { setListenIMFloaterOpened(); @@ -96,7 +93,6 @@ LLConversation::LLConversation(const LLConversation& conversation) mSessionID = conversation.getSessionID(); mParticipantID = conversation.getParticipantID(); mIsVoice = conversation.isVoice(); - mIsConversationPast = conversation.isConversationPast(); mHasOfflineIMs = conversation.hasOfflineMessages(); setListenIMFloaterOpened(); @@ -107,12 +103,10 @@ LLConversation::~LLConversation() mIMFloaterShowedConnection.disconnect(); } -void LLConversation::setIsVoice(bool is_voice) +void LLConversation::updateTimestamp() { - if (mIsConversationPast) - return; - - mIsVoice = is_voice; + mTime = time_corrected(); + mTimestamp = createTimestamp(mTime); } void LLConversation::onIMFloaterShown(const LLUUID& session_id) @@ -154,14 +148,18 @@ void LLConversation::setListenIMFloaterOpened() LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); bool has_offline_ims = !mIsVoice && mHasOfflineIMs; - bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + bool offline_ims_visible = LLIMFloater::isVisible(floater) && floater->hasFocus(); // we don't need to listen for im floater with this conversation is opened // if floater is already opened or this conversation doesn't have unread offline messages - if (has_offline_ims && !ims_are_read) + if (has_offline_ims && !offline_ims_visible) { mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } + else + { + mHasOfflineIMs = false; + } } /************************************************************************/ @@ -205,6 +203,7 @@ LLConversationLog::LLConversationLog() if (ctrl->getValue().asBoolean()) { LLIMMgr::instance().addSessionObserver(this); + newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); } } @@ -218,17 +217,80 @@ void LLConversationLog::observeIMSession() if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) { LLIMMgr::instance().addSessionObserver(this); + LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); } else { LLIMMgr::instance().removeSessionObserver(this); + newMessageSignalConnection.disconnect(); } } -void LLConversationLog::logConversation(const LLConversation& conversation) +void LLConversationLog::logConversation(const LLUUID& session_id) { - mConversations.push_back(conversation); - notifyObservers(); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + LLConversation* conversation = findConversation(session_id); + + if (session && conversation) + { + updateConversationTimestamp(conversation); + } + else if (session && !conversation) + { + createConversation(session_id); + } +} + +void LLConversationLog::createConversation(const LLUUID& session_id) +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + + if (session) + { + LLConversation conversation(*session); + mConversations.push_back(conversation); + + if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) + { + LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); + } + + notifyObservers(); + } +} + +void LLConversationLog::updateConversationName(const LLUUID& session_id, const std::string& name) +{ + LLConversation* conversation = findConversation(session_id); + + if (conversation) + { + conversation->setConverstionName(name); + notifyPrticularConversationObservers(session_id, LLConversationLogObserver::CHANGED_NAME); + } +} + +void LLConversationLog::updateConversationTimestamp(LLConversation* conversation) +{ + if (conversation) + { + conversation->updateTimestamp(); + notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); + } +} + +LLConversation* LLConversationLog::findConversation(const LLUUID& session_id) +{ + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } + } + + return NULL; } void LLConversationLog::removeConversation(const LLConversation& conversation) @@ -271,34 +333,7 @@ void LLConversationLog::removeObserver(LLConversationLogObserver* observer) void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - if (session) - { - if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) - { - LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); - } - else - { - LLConversation conversation(*session); - LLConversationLog::instance().logConversation(conversation); - session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); - } - } -} - -void LLConversationLog::sessionRemoved(const LLUUID& session_id) -{ - conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); - - for (; rev_iter != mConversations.rend(); ++rev_iter) - { - if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast()) - { - rev_iter->setIsPast(true); - return; // return here because only one session with session_id may be active - } - } + logConversation(session_id); } void LLConversationLog::cache() @@ -442,25 +477,13 @@ void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& sessi } } -void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state) +void LLConversationLog::onNewMessageReceived(const LLSD& data) { - conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); - - for (; rev_iter != mConversations.rend(); ++rev_iter) - { - if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast() && LLVoiceChannel::STATE_CALL_STARTED == state) - { - rev_iter->setIsVoice(true); - notifyPrticularConversationObservers(session_id, LLConversationLogObserver::VOICE_STATE); - return; // return here because only one session with session_id may be active - } - } + const LLUUID session_id = data["session_id"].asUUID(); + logConversation(session_id); } void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session) { - LLConversation conversation(*session); - conversation.setConverstionName(av_name.getCompleteName()); - LLConversationLog::instance().logConversation(conversation); - session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + updateConversationName(session->mSessionID, av_name.getCompleteName()); } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 16be37d67a..ffd27f7e20 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -57,15 +57,18 @@ public: const std::string& getTimestamp() const { return mTimestamp; } const time_t& getTime() const { return mTime; } bool isVoice() const { return mIsVoice; } - bool isConversationPast() const { return mIsConversationPast; } bool hasOfflineMessages() const { return mHasOfflineIMs; } void setIsVoice(bool is_voice); - void setIsPast (bool is_past) { mIsConversationPast = is_past; } void setConverstionName(std::string conv_name) { mConversationName = conv_name; } bool isOlderThan(U32 days) const; + /* + * updates last interaction time + */ + void updateTimestamp(); + /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ @@ -86,7 +89,7 @@ private: boost::signals2::connection mIMFloaterShowedConnection; - time_t mTime; // start time of conversation + time_t mTime; // last interaction time SessionType mConversationType; std::string mConversationName; std::string mHistoryFileName; @@ -94,8 +97,7 @@ private: LLUUID mParticipantID; bool mIsVoice; bool mHasOfflineIMs; - bool mIsConversationPast; // once session is finished conversation became past forever - std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm + std::string mTimestamp; // last interaction time in form of: mm/dd/yyyy hh:mm }; /** @@ -112,32 +114,26 @@ class LLConversationLog : public LLSingleton, LLIMSessionObse friend class LLSingleton; public: - /** - * adds conversation to the conversation list and notifies observers - */ - void logConversation(const LLConversation& conversation); void removeConversation(const LLConversation& conversation); /** * Returns first conversation with matched session_id */ - const LLConversation* getConversation(const LLUUID& session_id); + const LLConversation* getConversation(const LLUUID& session_id); + const std::vector& getConversations() { return mConversations; } void addObserver(LLConversationLogObserver* observer); void removeObserver(LLConversationLogObserver* observer); - const std::vector& getConversations() { return mConversations; } - // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - virtual void sessionRemoved(const LLUUID& session_id); + virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub void notifyObservers(); - void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); - void onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state); + void onNewMessageReceived(const LLSD& data); /** * public method which is called on viewer exit to save conversation log @@ -148,6 +144,13 @@ private: LLConversationLog(); + /** + * adds conversation to the conversation list and notifies observers + */ + void logConversation(const LLUUID& session_id); + + void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); + void observeIMSession(); /** @@ -161,11 +164,19 @@ private: void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session); + void createConversation(const LLUUID& session_id); + void updateConversationTimestamp(LLConversation* conversation); + void updateConversationName(const LLUUID& session_id, const std::string& name); + + LLConversation* findConversation(const LLUUID& session_id); + typedef std::vector conversations_vec_t; std::vector mConversations; std::set mObservers; LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance + + boost::signals2::connection newMessageSignalConnection; }; class LLConversationLogObserver @@ -174,7 +185,8 @@ public: enum EConversationChange { - VOICE_STATE = 1 + CHANGED_TIME = 1, // last interaction time changed + CHANGED_NAME = 2 // conversation name changed }; virtual ~LLConversationLogObserver(){} diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index d39e090c22..429e99f7ad 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -143,22 +143,32 @@ void LLConversationLogList::changed() void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) { - if (mask & LLConversationLogObserver::VOICE_STATE) + LLConversationLogListItem* item = getConversationLogListItem(session_id); + + if (!item) { - std::vector panels; - LLFlatListViewEx::getItems(panels); + return; + } - std::vector::iterator iter = panels.begin(); + if (mask & LLConversationLogObserver::CHANGED_TIME) + { + item->updateTimestamp(); - for (; iter != panels.end(); ++iter) + // if list is sorted by date and a date of some item has changed, + // than the whole list should be rebuilt + if (E_SORT_BY_DATE == getSortOrder()) { - LLConversationLogListItem* item = dynamic_cast(*iter); - - if (item && session_id == item->getConversation()->getSessionID() && !item->getConversation()->isConversationPast()) - { - item->initIcons(); - return; - } + mIsDirty = true; + } + } + else if (mask & LLConversationLogObserver::CHANGED_NAME) + { + item->updateName(); + // if list is sorted by name and a name of some item has changed, + // than the whole list should be rebuilt + if (E_SORT_BY_DATE == getSortOrder()) + { + mIsDirty = true; } } } @@ -401,6 +411,29 @@ const LLConversation* LLConversationLogList::getSelectedConversation() return NULL; } +LLConversationLogListItem* LLConversationLogList::getConversationLogListItem(const LLUUID& session_id) +{ + std::vector panels; + LLFlatListViewEx::getItems(panels); + std::vector::iterator iter = panels.begin(); + + for (; iter != panels.end(); ++iter) + { + LLConversationLogListItem* item = dynamic_cast(*iter); + if (item && session_id == item->getConversation()->getSessionID()) + { + return item; + } + } + + return NULL; +} + +LLConversationLogList::ESortOrder LLConversationLogList::getSortOrder() +{ + return static_cast(gSavedSettings.getU32("CallLogSortOrder")); +} + bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const { const LLConversationLogListItem* conversation_item1 = dynamic_cast(item1); diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h index 5e7fc0a9fb..62ec57e09e 100644 --- a/indra/newview/llconversationloglist.h +++ b/indra/newview/llconversationloglist.h @@ -43,6 +43,12 @@ class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogOb { LOG_CLASS(LLConversationLogList); public: + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_DATE = 1, + } ESortOrder; + struct Params : public LLInitParam::Block { Params(){}; @@ -90,6 +96,9 @@ private: LLIMModel::LLIMSession::SType getSelectedSessionType(); const LLConversationLogListItem* getSelectedConversationPanel(); const LLConversation* getSelectedConversation(); + LLConversationLogListItem* getConversationLogListItem(const LLUUID& session_id); + + ESortOrder getSortOrder(); LLHandle mContextMenu; bool mIsDirty; diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index dddf216592..fac6130371 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -117,6 +117,16 @@ void LLConversationLogListItem::initIcons() } } +void LLConversationLogListItem::updateTimestamp() +{ + mConversationDate->setValue(mConversation->getTimestamp()); +} + +void LLConversationLogListItem::updateName() +{ + mConversationName->setValue(mConversation->getConversationName()); +} + void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) { getChildView("hovered_icon")->setVisible(true); diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 2aaafa0fba..1bf7a0ed93 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -64,10 +64,16 @@ public: void onDoubleClick(); - void initIcons(); + /** + * updates string value of last interaction time from conversation + */ + void updateTimestamp(); + void updateName(); private: + void initIcons(); + const LLConversation* mConversation; LLTextBox* mConversationName; diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 4375ce5726..7b4c999e52 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -45,11 +45,11 @@ BOOL LLFloaterConversationLog::postBuild() switch (gSavedSettings.getU32("CallLogSortOrder")) { - case E_SORT_BY_NAME: + case LLConversationLogList::E_SORT_BY_NAME: mConversationLogList->sortByName(); break; - case E_SORT_BY_DATE: + case LLConversationLogList::E_SORT_BY_DATE: mConversationLogList->sortByDate(); break; } @@ -87,12 +87,12 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) if ("sort_by_name" == command_name) { mConversationLogList->sortByName(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_NAME); } else if ("sort_by_date" == command_name) { mConversationLogList->sortByDate(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_DATE); } else if ("sort_friends_on_top" == command_name) { @@ -117,11 +117,11 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) if ("sort_by_name" == command_name) { - return sort_order == E_SORT_BY_NAME; + return sort_order == LLConversationLogList::E_SORT_BY_NAME; } else if ("sort_by_date" == command_name) { - return sort_order == E_SORT_BY_DATE; + return sort_order == LLConversationLogList::E_SORT_BY_DATE; } else if ("sort_friends_on_top" == command_name) { diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 7d788c0290..e971330f3d 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -34,11 +34,6 @@ class LLFloaterConversationLog : public LLFloater { public: - typedef enum e_sort_oder{ - E_SORT_BY_NAME = 0, - E_SORT_BY_DATE = 1, - } ESortOrder; - LLFloaterConversationLog(const LLSD& key); virtual ~LLFloaterConversationLog(){}; -- cgit v1.3 From 8c0fcf0e391ff5db78f95f031562eedec998f164 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Thu, 13 Sep 2012 16:12:53 +0300 Subject: CHUI-321 FIXED (Indicate within the Call Log why there's nothing in it) I. On "LogInstantMessages" variable set to false: 1. save call log to file 2. clear call log 3. show message: "Conversations are not being logged. To log conversations in the future, select "Save IM logs in my computer" under Preferences > Privacy." On "LogInstantMessages" set to true: 1. clear message 2. reload all saved call log entries II. Refactored the way LLConversationLog reacts on "LogInstantMessages" value change --- indra/newview/llappviewer.cpp | 5 +-- indra/newview/llconversationlog.cpp | 36 +++++++++++++--------- indra/newview/llconversationlog.h | 4 +-- indra/newview/llfloaterconversationlog.cpp | 13 ++++++++ indra/newview/llfloaterconversationlog.h | 2 ++ .../default/xui/en/floater_conversation_log.xml | 5 +++ 6 files changed, 44 insertions(+), 21 deletions(-) (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4dacde4792..08a1a237f5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1834,10 +1834,7 @@ bool LLAppViewer::cleanup() LLMuteList::getInstance()->cache(gAgent.getID()); //save call log list - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) - { - LLConversationLog::instance().cache(); - } + LLConversationLog::instance().cache(); if (mPurgeOnExit) { diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 239a89015f..27be2bc5ae 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -193,37 +193,40 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() { - loadFromFile(getFileName()); - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); if (ctrl) { - ctrl->getSignal()->connect(boost::bind(&LLConversationLog::observeIMSession, this)); - + ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); if (ctrl->getValue().asBoolean()) { - LLIMMgr::instance().addSessionObserver(this); - newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + enableLogging(true); } } - - mFriendObserver = new LLConversationLogFriendObserver; - LLAvatarTracker::instance().addObserver(mFriendObserver); - } -void LLConversationLog::observeIMSession() +void LLConversationLog::enableLogging(bool enable) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (enable) { + loadFromFile(getFileName()); + LLIMMgr::instance().addSessionObserver(this); - LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + + mFriendObserver = new LLConversationLogFriendObserver; + LLAvatarTracker::instance().addObserver(mFriendObserver); } else { + saveToFile(getFileName()); + LLIMMgr::instance().removeSessionObserver(this); newMessageSignalConnection.disconnect(); + LLAvatarTracker::instance().removeObserver(mFriendObserver); + mConversations.clear(); } + + notifyObservers(); } void LLConversationLog::logConversation(const LLUUID& session_id) @@ -338,7 +341,10 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string void LLConversationLog::cache() { - saveToFile(getFileName()); + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + saveToFile(getFileName()); + } } std::string LLConversationLog::getFileName() @@ -349,7 +355,7 @@ std::string LLConversationLog::getFileName() bool LLConversationLog::saveToFile(const std::string& filename) { - if(!filename.size()) + if (!filename.size()) { llwarns << "Call log list filename is empty!" << llendl; return false; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index ffd27f7e20..a458e975bb 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -144,6 +144,8 @@ private: LLConversationLog(); + void enableLogging(bool enable); + /** * adds conversation to the conversation list and notifies observers */ @@ -151,8 +153,6 @@ private: void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); - void observeIMSession(); - /** * constructs file name in which conversations log will be saved * file name is conversation.log diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 7b4c999e52..089aec1905 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -63,6 +63,13 @@ BOOL LLFloaterConversationLog::postBuild() getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); + onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean()); + } + return LLFloater::postBuild(); } @@ -130,3 +137,9 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) return false; } + +void LLFloaterConversationLog::onCallLoggingEnabledDisabled(bool enabled) +{ + std::string no_items_msg = enabled ? "" : getString("logging_calls_disabled"); + mConversationLogList->setNoItemsCommentText(no_items_msg); +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index e971330f3d..9e79cbd7d8 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -49,6 +49,8 @@ private: bool isActionEnabled(const LLSD& userdata); bool isActionChecked(const LLSD& userdata); + void onCallLoggingEnabledDisabled(bool enabled); + LLConversationLogList* mConversationLogList; }; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 9cdeb0d788..df78bbccec 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -13,6 +13,11 @@ reuse_instance="true" title="CONVERSATION LOG" width="450"> + + + Conversations are not being logged. To log conversations in the future, select "Save IM logs in my computer" under Preferences > Privacy. + + Date: Sat, 15 Dec 2012 20:37:18 +0200 Subject: CHUI-598 : Fixed : Conversation log file created even when keep conversation log preference is off : Checked the status of the another ("KeepConversationLogTranscripts") setting too. --- indra/newview/llconversationlog.cpp | 3 ++- indra/newview/llfloaterconversationlog.cpp | 3 ++- indra/newview/llimview.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index a0765f5e16..1171b3db41 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -191,7 +191,8 @@ LLConversationLog::LLConversationLog() if (ctrl) { ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - if (ctrl->getValue().asBoolean()) + if (ctrl->getValue().asBoolean() + && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { enableLogging(true); } diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 089aec1905..a40a000bab 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -67,7 +67,8 @@ BOOL LLFloaterConversationLog::postBuild() if (ctrl) { ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); - onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean()); + onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean() + && gSavedSettings.getBOOL("KeepConversationLogTranscripts")); } return LLFloater::postBuild(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4e2ac09dd8..cdd08ededf 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -857,7 +857,8 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages") + && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { std::string from_name = from; -- cgit v1.3 From 2ac99f55f9e562e4ff8ebde4cba8270f1048c28d Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Thu, 24 Jan 2013 19:56:13 +0200 Subject: CHUI-578 FIXED Move preferences for conversation logs/transcripts to chat tab --- indra/llvfs/lldir.cpp | 13 +- indra/llvfs/lldir.h | 2 + indra/newview/app_settings/settings.xml | 4 +- indra/newview/llconversationlog.cpp | 60 +++-- indra/newview/llconversationlog.h | 11 +- indra/newview/llfloaterconversationlog.cpp | 14 +- indra/newview/llfloaterconversationlog.h | 2 +- indra/newview/llfloaterimcontainer.cpp | 6 +- indra/newview/llfloaterimnearbychat.cpp | 27 +- indra/newview/llfloaterimnearbychat.h | 2 +- indra/newview/llfloaterimsession.cpp | 12 +- indra/newview/llfloaterimsession.h | 2 +- indra/newview/llfloaterimsessiontab.cpp | 6 +- indra/newview/llfloaterimsessiontab.h | 2 +- indra/newview/llfloaterpreference.cpp | 109 +++++--- indra/newview/llfloaterpreference.h | 19 +- indra/newview/llimview.cpp | 37 +-- indra/newview/llimview.h | 2 + indra/newview/lllogchat.cpp | 235 ++++++++++------- indra/newview/lllogchat.h | 15 +- indra/newview/llviewermessage.cpp | 2 +- .../newview/skins/default/xui/en/notifications.xml | 26 ++ .../default/xui/en/panel_preferences_chat.xml | 284 ++++++++++++++------- .../default/xui/en/panel_preferences_privacy.xml | 226 +++++----------- 24 files changed, 641 insertions(+), 477 deletions(-) (limited to 'indra/newview/llfloaterconversationlog.cpp') diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 5e5aeefba1..f7bc19574a 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -90,7 +90,8 @@ LLDir::LLDir() mCAFile(""), mTempDir(""), mDirDelimiter("/"), // fallback to forward slash if not overridden - mLanguage("en") + mLanguage("en"), + mUserName("undefined") { } @@ -814,6 +815,11 @@ void LLDir::setChatLogsDir(const std::string &path) } } +void LLDir::updatePerAccountChatLogsDir() +{ + mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName); +} + void LLDir::setPerAccountChatLogsDir(const std::string &username) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -824,13 +830,14 @@ void LLDir::setPerAccountChatLogsDir(const std::string &username) std::string userlower(username); LLStringUtil::toLower(userlower); LLStringUtil::replaceChar(userlower, ' ', '_'); - mPerAccountChatLogsDir = add(getChatLogsDir(), userlower); + + mUserName = userlower; + updatePerAccountChatLogsDir(); } else { llerrs << "NULL name for LLDir::setPerAccountChatLogsDir" << llendl; } - } void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 300ff1eef6..95cab65149 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -186,6 +186,7 @@ class LLDir virtual std::string getSkinFolder() const; virtual std::string getLanguage() const; virtual bool setCacheDir(const std::string &path); + virtual void updatePerAccountChatLogsDir(); virtual void dumpCurrentDirectories(); @@ -243,6 +244,7 @@ protected: std::vector mSearchSkinDirs; std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell + std::string mUserName; // Current user name }; void dir_exists_or_crash(const std::string &dir_name); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fd4d1df894..dd9a0100c0 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4674,9 +4674,9 @@ Persist 1 Type - Boolean + S32 Value - 1 + 2 LandBrushSize diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index ff1f819d7d..8de041f983 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -28,13 +28,14 @@ #include "llagent.h" #include "llavatarnamecache.h" #include "llconversationlog.h" +#include "llnotificationsutil.h" #include "lltrans.h" const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec -struct Conversation_params +struct ConversationParams { - Conversation_params(time_t time) + ConversationParams(time_t time) : mTime(time), mTimestamp(LLConversation::createTimestamp(time)) {} @@ -53,7 +54,7 @@ struct Conversation_params /* LLConversation implementation */ /************************************************************************/ -LLConversation::LLConversation(const Conversation_params& params) +LLConversation::LLConversation(const ConversationParams& params) : mTime(params.mTime), mTimestamp(params.mTimestamp), mConversationType(params.mConversationType), @@ -188,33 +189,24 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() : mAvatarNameCacheConnection() { - LLControlVariable* log_instant_message = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - LLControlVariable* keep_convers_log = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); - bool is_log_message = false; - bool is_keep_log = false; + LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + S32 log_mode = keep_log_ctrlp->getValue(); - if (log_instant_message) + if (log_mode > 0) { - log_instant_message->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - is_log_message = log_instant_message->getValue().asBoolean(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + enableLogging(log_mode); } - if (keep_convers_log) - { - keep_convers_log->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - is_keep_log = keep_convers_log->getValue().asBoolean(); - } - - enableLogging(is_log_message && is_keep_log); } -void LLConversationLog::enableLogging(bool enable) +void LLConversationLog::enableLogging(S32 log_mode) { - if (enable) + if (log_mode > 0) { loadFromFile(getFileName()); LLIMMgr::instance().addSessionObserver(this); - newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + mNewMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); mFriendObserver = new LLConversationLogFriendObserver; LLAvatarTracker::instance().addObserver(mFriendObserver); @@ -224,7 +216,7 @@ void LLConversationLog::enableLogging(bool enable) saveToFile(getFileName()); LLIMMgr::instance().removeSessionObserver(this); - newMessageSignalConnection.disconnect(); + mNewMessageSignalConnection.disconnect(); LLAvatarTracker::instance().removeObserver(mFriendObserver); mConversations.clear(); } @@ -377,7 +369,7 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string void LLConversationLog::cache() { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 0) { saveToFile(getFileName()); } @@ -450,9 +442,9 @@ bool LLConversationLog::loadFromFile(const std::string& filename) char part_id_buffer[MAX_STRING]; char conv_id_buffer[MAX_STRING]; char history_file_name[MAX_STRING]; - int has_offline_ims; - int stype; - time_t time; + S32 has_offline_ims; + S32 stype; + S64 time; // before CHUI-348 it was a flag of conversation voice state int prereserved_unused; @@ -462,7 +454,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) part_id_buffer[0] = '\0'; conv_id_buffer[0] = '\0'; - sscanf(buffer, "[%ld] %d %d %d %[^|]| %s %s %[^|]|", + sscanf(buffer, "[%lld] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, &prereserved_unused, @@ -472,7 +464,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) conv_id_buffer, history_file_name); - Conversation_params params(time); + ConversationParams params((time_t)time); params.mConversationType = (SessionType)stype; params.mHasOfflineIMs = has_offline_ims; params.mConversationName = std::string(conv_name_buffer); @@ -530,3 +522,17 @@ void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LL mAvatarNameCacheConnection.disconnect(); updateConversationName(session, av_name.getCompleteName()); } + +void LLConversationLog::onClearLog() +{ + LLNotificationsUtil::add("PreferenceChatClearLog", LLSD(), LLSD(), boost::bind(&LLConversationLog::onClearLogResponse, this, _1, _2)); +} + +void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& response) +{ + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + { + mConversations.clear(); + notifyObservers(); + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 35462ec3a4..65a18c02e5 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -31,7 +31,7 @@ #include "llimview.h" class LLConversationLogObserver; -struct Conversation_params; +struct ConversationParams; typedef LLIMModel::LLIMSession::SType SessionType; @@ -43,7 +43,7 @@ class LLConversation { public: - LLConversation(const Conversation_params& params); + LLConversation(const ConversationParams& params); LLConversation(const LLIMModel::LLIMSession& session); LLConversation(const LLConversation& conversation); @@ -138,6 +138,9 @@ public: */ void cache(); + void onClearLog(); + void onClearLogResponse(const LLSD& notification, const LLSD& response); + private: LLConversationLog(); @@ -149,7 +152,7 @@ private: } } - void enableLogging(bool enable); + void enableLogging(S32 log_mode); /** * adds conversation to the conversation list and notifies observers @@ -182,7 +185,7 @@ private: LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance - boost::signals2::connection newMessageSignalConnection; + boost::signals2::connection mNewMessageSignalConnection; boost::signals2::connection mAvatarNameCacheConnection; }; diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index a40a000bab..a44ebcf6ab 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -63,13 +63,9 @@ BOOL LLFloaterConversationLog::postBuild() getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); - onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean() - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")); - } + LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); + onCallLoggingEnabledDisabled(keep_log_ctrlp->getValue()); return LLFloater::postBuild(); } @@ -139,8 +135,8 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) return false; } -void LLFloaterConversationLog::onCallLoggingEnabledDisabled(bool enabled) +void LLFloaterConversationLog::onCallLoggingEnabledDisabled(S32 log_mode) { - std::string no_items_msg = enabled ? "" : getString("logging_calls_disabled"); + std::string no_items_msg = log_mode > 0 ? "" : getString("logging_calls_disabled"); mConversationLogList->setNoItemsCommentText(no_items_msg); } diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 9e79cbd7d8..aa0f480aae 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -49,7 +49,7 @@ private: bool isActionEnabled(const LLSD& userdata); bool isActionChecked(const LLSD& userdata); - void onCallLoggingEnabledDisabled(bool enabled); + void onCallLoggingEnabledDisabled(S32 log_mode); LLConversationLogList* mConversationLogList; }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c272e5e391..54e5085490 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -224,7 +224,7 @@ BOOL LLFloaterIMContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed()) { @@ -1142,7 +1142,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) if ("conversation_log" == item) { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; } //Enable Chat history item for ad-hoc and group conversations @@ -1793,7 +1793,7 @@ void LLFloaterIMContainer::updateSpeakBtnState() bool LLFloaterIMContainer::isConversationLoggingAllowed() { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; } void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 797d590e1f..17d2341b3c 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -148,8 +148,14 @@ void LLFloaterIMNearbyChat::refresh() } } -void LLFloaterIMNearbyChat::reloadMessages() +void LLFloaterIMNearbyChat::reloadMessages(bool clean_messages/* = false*/) { + if (clean_messages) + { + mMessageArchive.clear(); + loadHistory(); + } + mChatHistory->clear(); LLSD do_not_log; @@ -174,11 +180,11 @@ void LLFloaterIMNearbyChat::loadHistory() { const LLSD& msg = *it; - std::string from = msg[IM_FROM]; + std::string from = msg[LL_IM_FROM]; LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) + if (msg[LL_IM_FROM_ID].isDefined()) { - from_id = msg[IM_FROM_ID].asUUID(); + from_id = msg[LL_IM_FROM_ID].asUUID(); } else { @@ -189,8 +195,8 @@ void LLFloaterIMNearbyChat::loadHistory() LLChat chat; chat.mFromName = from; chat.mFromID = from_id; - chat.mText = msg[IM_TEXT].asString(); - chat.mTimeStr = msg[IM_TIME].asString(); + chat.mText = msg[LL_IM_TEXT].asString(); + chat.mTimeStr = msg[LL_IM_TIME].asString(); chat.mChatStyle = CHAT_STYLE_HISTORY; chat.mSourceType = CHAT_SOURCE_AGENT; @@ -519,20 +525,21 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type ) } } -void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) { appendMessage(chat, args); if(archive) { mMessageArchive.push_back(chat); - if(mMessageArchive.size()>200) + if(mMessageArchive.size() > 200) + { mMessageArchive.erase(mMessageArchive.begin()); + } } // logging - if (!args["do_not_log"].asBoolean() - && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + if (!args["do_not_log"].asBoolean() && gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = chat.mFromName; diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index f4213eda5a..14c7d01ecd 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -56,7 +56,7 @@ public: /*virtual*/ void setVisible(BOOL visible); void loadHistory(); - void reloadMessages(); + void reloadMessages(bool clean_messages = false); void removeScreenChat(); void show(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a09dc1914f..07f5515582 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -853,8 +853,18 @@ void LLFloaterIMSession::updateMessages() } } -void LLFloaterIMSession::reloadMessages() +void LLFloaterIMSession::reloadMessages(bool clean_messages/* = false*/) { + if (clean_messages) + { + LLIMModel::LLIMSession * sessionp = LLIMModel::instance().findIMSession(mSessionID); + + if (NULL != sessionp) + { + sessionp->loadHistory(); + } + } + mChatHistory->clear(); mLastMessageIndex = -1; updateMessages(); diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 2049cedfd7..e7fd6f9ff3 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -86,7 +86,7 @@ public: // get new messages from LLIMModel /*virtual*/ void updateMessages(); - void reloadMessages(); + void reloadMessages(bool clean_messages = false); static void onSendMsg(LLUICtrl*, void*); void sendMsgFromInputEditor(); void sendMsg(const std::string& msg); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 37404ab716..f7c6f19450 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -680,7 +680,7 @@ void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) } // static -void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() +void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* = false*/) { LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); @@ -689,14 +689,14 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() LLFloaterIMSession* floater = dynamic_cast(*iter); if (floater) { - floater->reloadMessages(); + floater->reloadMessages(clean_messages); } } LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); if (nearby_chat) { - nearby_chat->reloadMessages(); + nearby_chat->reloadMessages(clean_messages); } } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index beaffc14a6..e90fcbb806 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -53,7 +53,7 @@ public: ~LLFloaterIMSessionTab(); // reload all message with new settings of visual modes - static void processChatHistoryStyleUpdate(); + static void processChatHistoryStyleUpdate(bool clean_messages = false); /** * Returns true if chat is displayed in multi tabbed floater diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d4a1c44d8..7742e5b3c3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -306,7 +306,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mAvatarDataInitialized(false), mClickActionDirty(false) { - + LLConversationLog::instance().addObserver(this); + //Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); static bool registered_dialog = false; @@ -329,8 +330,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this)); mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this)); mCommitCallbackRegistrar.add("Pref.SetSounds", boost::bind(&LLFloaterPreference::onClickSetSounds, this)); -// mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this)); -// mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this)); mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this)); mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this)); mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this)); @@ -351,13 +350,16 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) sSkin = gSavedSettings.getString("SkinCurrent"); - mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); + mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); + + mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); + mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) @@ -425,7 +427,7 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -455,9 +457,24 @@ BOOL LLFloaterPreference::postBuild() gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } + // set 'enable' property for 'Clear log...' button + changed(); + + // set 'enable' property for 'Delete transcripts...' button + updateDeleteTranscriptsButton(); + + LLLogChat::setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this)); + return TRUE; } +void LLFloaterPreference::updateDeleteTranscriptsButton() +{ + std::vector list_of_transcriptions_file_names; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); + getChild("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); +} + void LLFloaterPreference::onDoNotDisturbResponseChanged() { // set "DoNotDisturbResponseChanged" TRUE if user edited message differs from default, FALSE otherwise @@ -476,6 +493,8 @@ LLFloaterPreference::~LLFloaterPreference() { ctrl_window_size->setCurrentByIndex(i); } + + LLConversationLog::instance().removeObserver(this); } void LLFloaterPreference::draw() @@ -833,12 +852,12 @@ void LLFloaterPreference::onBtnCancel() } // static -void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance("preferences"); if (instance) { - instance->setPersonalInfo(visibility, im_via_email, email); + instance->setPersonalInfo(visibility, im_via_email); } } @@ -1425,10 +1444,21 @@ void LLFloaterPreference::onClickLogPath() return; //Canceled! } - gSavedPerAccountSettings.setString("InstantMessageLogPath", picker.getDirName()); + std::string dir_name = picker.getDirName(); + gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); + + gDirUtilp->setChatLogsDir(dir_name); + gDirUtilp->updatePerAccountChatLogsDir(); + LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + + // refresh IM floaters with new logs from files from new selected directory + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); } -void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) { mGotPersonalInfo = true; mOriginalIMViaEmail = im_via_email; @@ -1450,32 +1480,14 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im } getChild("online_searchresults")->setEnabled(TRUE); - - getChildView("include_im_in_chat_history")->setEnabled(TRUE); - getChildView("show_timestamps_check_im")->setEnabled(TRUE); getChildView("friends_online_notify_checkbox")->setEnabled(TRUE); - getChild("online_visibility")->setValue(mOriginalHideOnlineStatus); getChild("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility); getChildView("send_im_to_email")->setEnabled(TRUE); getChild("send_im_to_email")->setValue(im_via_email); - getChildView("log_instant_messages")->setEnabled(TRUE); -// getChildView("log_chat")->setEnabled(TRUE); -// getChildView("log_instant_messages_timestamp")->setEnabled(TRUE); -// getChildView("log_chat_timestamp")->setEnabled(TRUE); - getChildView("log_chat_IM")->setEnabled(TRUE); - getChildView("log_date_timestamp")->setEnabled(TRUE); - getChildView("favorites_on_login_check")->setEnabled(TRUE); - getChildView("log_nearby_chat")->setEnabled(TRUE); - getChildView("log_instant_messages")->setEnabled(TRUE); - getChildView("show_timestamps_check_im")->setEnabled(TRUE); getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case. getChildView("log_path_button")->setEnabled(TRUE); - childEnable("logfile_name_datestamp"); - std::string display_email(email); - getChild("email_address")->setValue(display_email); - } void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) @@ -1566,6 +1578,35 @@ void LLFloaterPreference::onClickActionChange() mClickActionDirty = true; } +void LLFloaterPreference::onDeleteTranscripts() +{ + LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); +} + +void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response) +{ + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + { + gDirUtilp->deleteFilesInDir(gDirUtilp->getPerAccountChatLogsDir(), "*." + LL_TRANSCRIPT_FILE_EXTENSION); + + std::vector list_of_transcriptions_file_names; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); + getChild("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); + + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + } +} + +void LLFloaterPreference::onLogChatHistorySaved() +{ + LLButton * delete_transcripts_buttonp = getChild("delete_transcripts"); + + if (!delete_transcripts_buttonp->getEnabled()) + { + delete_transcripts_buttonp->setEnabled(true); + } +} + void LLFloaterPreference::updateClickActionSettings() { const int single_clk_action = getChild("single_click_action_combo")->getValue().asInteger(); @@ -1624,6 +1665,11 @@ void LLFloaterPreference::selectChatPanel() selectPanel("chat"); } +void LLFloaterPreference::changed() +{ + getChild("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0); +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) @@ -1717,11 +1763,6 @@ BOOL LLPanelPreference::postBuild() } - if (hasChild("online_visibility") && hasChild("send_im_to_email")) - { - getChild("email_address")->setValue(getString("log_in_to_change") ); - } - //////////////////////PanelPrivacy /////////////////// if (hasChild("media_enabled")) { @@ -1898,7 +1939,7 @@ public: for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); ) { const std::string setting = it->first->getName(); - if (std::find(mAccountIndependentSettings.begin(), + if (find(mAccountIndependentSettings.begin(), mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) { mSavedValues.erase(it++); @@ -2187,4 +2228,4 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings() otherHttpProxy->selectFirstItem(); } -}; +} diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 37a531e99e..f9f1d52244 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -35,7 +35,9 @@ #include "llfloater.h" #include "llavatarpropertiesprocessor.h" +#include "llconversationlog.h" +class LLConversationLogObserver; class LLPanelPreference; class LLPanelLCD; class LLPanelDebug; @@ -58,7 +60,7 @@ typedef enum // Floater to control preferences (display, audio, bandwidth, general. -class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver +class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver, public LLConversationLogObserver { public: LLFloaterPreference(const LLSD& key); @@ -70,9 +72,11 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void changed(); + /*virtual*/ void changed(const LLUUID& session_id, U32 mask) {}; // static data update, called from message handler - static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email); + static void updateUserInfo(const std::string& visibility, bool im_via_email); // refresh all the graphics preferences menus static void refreshEnabledGraphics(); @@ -134,15 +138,13 @@ public: void setKey(KEY key); void onClickSetMiddleMouse(); void onClickSetSounds(); -// void onClickSkipDialogs(); -// void onClickResetDialogs(); void onClickEnablePopup(); void onClickDisablePopup(); void resetAllIgnored(); void setAllIgnored(); void onClickLogPath(); void enableHistory(); - void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email); + void setPersonalInfo(const std::string& visibility, bool im_via_email); void refreshEnabledState(); void disableUnavailableSettings(); void onCommitWindowedMode(); @@ -166,12 +168,17 @@ public: void onClickSpellChecker(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); - + void onLogChatHistorySaved(); void buildPopupLists(); static void refreshSkin(void* data); void selectPanel(const LLSD& name); private: + + void onDeleteTranscripts(); + void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response); + void updateDeleteTranscriptsButton(); + static std::string sSkin; notifications_map mNotificationOptions; bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user. diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 433ddad35d..37c9ee8c99 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -378,15 +378,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& } buildHistoryFileName(); - - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - std::list chat_history; - - //involves parsing of a chat history - LLLogChat::loadChatHistory(mHistoryFileName, chat_history); - addMessagesFromHistory(chat_history); - } + loadHistory(); // Localizing name of ad-hoc session. STORM-153 // Changing name should happen here- after the history file was created, so that @@ -579,11 +571,11 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list& histo { const LLSD& msg = *it; - std::string from = msg[IM_FROM]; + std::string from = msg[LL_IM_FROM]; LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) + if (msg[LL_IM_FROM_ID].isDefined()) { - from_id = msg[IM_FROM_ID].asUUID(); + from_id = msg[LL_IM_FROM_ID].asUUID(); } else { @@ -592,8 +584,8 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list& histo gCacheName->getUUID(legacy_name, from_id); } - std::string timestamp = msg[IM_TIME]; - std::string text = msg[IM_TEXT]; + std::string timestamp = msg[LL_IM_TIME]; + std::string text = msg[LL_IM_TEXT]; addMessage(from, from_id, text, timestamp, true); @@ -617,6 +609,20 @@ void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const } } +void LLIMModel::LLIMSession::loadHistory() +{ + mMsgs.clear(); + + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) + { + std::list chat_history; + + //involves parsing of a chat history + LLLogChat::loadChatHistory(mHistoryFileName, chat_history); + addMessagesFromHistory(chat_history); + } +} + LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const { return get_if_there(mId2SessionMap, session_id, @@ -921,8 +927,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages") - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) + if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = from; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 8578fa8c06..da6039a3ae 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -101,6 +101,8 @@ public: /** ad-hoc sessions involve sophisticated chat history file naming schemes */ void buildHistoryFileName(); + void loadHistory(); + LLUUID mSessionID; std::string mName; EInstantMessage mType; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 3692658e9e..545b44ef92 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -58,10 +58,11 @@ const S32 LOG_RECALL_SIZE = 2048; -const std::string IM_TIME("time"); -const std::string IM_TEXT("message"); -const std::string IM_FROM("from"); -const std::string IM_FROM_ID("from_id"); +const std::string LL_IM_TIME("time"); +const std::string LL_IM_TEXT("message"); +const std::string LL_IM_FROM("from"); +const std::string LL_IM_FROM_ID("from_id"); +const std::string LL_TRANSCRIPT_FILE_EXTENSION("ll.txt"); const static std::string IM_SEPARATOR(": "); const static std::string NEW_LINE("\n"); @@ -116,6 +117,15 @@ const static int IDX_TEXT = 3; using namespace boost::posix_time; using namespace boost::gregorian; +void append_to_last_message(std::list& messages, const std::string& line) +{ + if (!messages.size()) return; + + std::string im_text = messages.back()[LL_IM_TEXT].asString(); + im_text.append(line); + messages.back()[LL_IM_TEXT] = im_text; +} + class LLLogChatTimeScanner: public LLSingleton { public: @@ -191,15 +201,17 @@ private: std::stringstream mTimeStream; }; +LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; + //static std::string LLLogChat::makeLogFileName(std::string filename) { /** - * Testing for in bound and out bound ad-hoc file names - * if it is then skip date stamping. - **/ - //LL_INFOS("") << "Befor:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - boost::match_results matches; + * Testing for in bound and out bound ad-hoc file names + * if it is then skip date stamping. + **/ + + boost::match_results matches; bool inboundConf = boost::regex_match(filename, matches, INBOUND_CONFERENCE); bool outboundConf = boost::regex_match(filename, matches, OUTBOUND_CONFERENCE); if (!(inboundConf || outboundConf)) @@ -220,17 +232,17 @@ std::string LLLogChat::makeLogFileName(std::string filename) filename += dbuffer; } } - //LL_INFOS("") << "After:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ + filename = cleanFileName(filename); - filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename); - filename += ".txt"; - //LL_INFOS("") << "Full:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ + filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); + filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + return filename; } std::string LLLogChat::cleanFileName(std::string filename) { - std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars + std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars std::string::size_type position = filename.find_first_of(invalidChars); while (position != filename.npos) { @@ -242,27 +254,24 @@ std::string LLLogChat::cleanFileName(std::string filename) std::string LLLogChat::timestamp(bool withdate) { - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr; - LLSD substitution; - substitution["datetime"] = (S32) utc_time; - if (withdate) { - timeStr = "["+LLTrans::getString ("TimeYear")+"]/[" - +LLTrans::getString ("TimeMonth")+"]/[" - +LLTrans::getString ("TimeDay")+"] [" - +LLTrans::getString ("TimeHour")+"]:[" - +LLTrans::getString ("TimeMin")+"]"; + timeStr = "[" + LLTrans::getString ("TimeYear") + "]/[" + + LLTrans::getString ("TimeMonth") + "]/[" + + LLTrans::getString ("TimeDay") + "] [" + + LLTrans::getString ("TimeHour") + "]:[" + + LLTrans::getString ("TimeMin") + "]"; } else { timeStr = "[" + LLTrans::getString("TimeHour") + "]:[" - + LLTrans::getString ("TimeMin")+"]"; + + LLTrans::getString ("TimeMin")+"]"; } + LLSD substitution; + substitution["datetime"] = (S32)time_corrected(); + LLStringUtil::format (timeStr, substitution); return timeStr; } @@ -270,9 +279,9 @@ std::string LLLogChat::timestamp(bool withdate) //static void LLLogChat::saveHistory(const std::string& filename, - const std::string& from, - const LLUUID& from_id, - const std::string& line) + const std::string& from, + const LLUUID& from_id, + const std::string& line) { std::string tmp_filename = filename; LLStringUtil::trim(tmp_filename); @@ -312,6 +321,11 @@ void LLLogChat::saveHistory(const std::string& filename, file << LLChatLogFormatter(item) << std::endl; file.close(); + + if (NULL != sSaveHistorySignal) + { + (*sSaveHistorySignal)(); + } } void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata) @@ -321,7 +335,7 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi llwarns << "Filename is Empty!" << llendl; return ; } - + LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/ if (!fptr) { @@ -377,15 +391,6 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi } } -void append_to_last_message(std::list& messages, const std::string& line) -{ - if (!messages.size()) return; - - std::string im_text = messages.back()[IM_TEXT].asString(); - im_text.append(line); - messages.back()[IM_TEXT] = im_text; -} - // static void LLLogChat::loadChatHistory(const std::string& file_name, std::list& messages, const LLSD& load_params) { @@ -397,19 +402,16 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; - //LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - //LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ if (!fptr) - { + { fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ - if (!fptr) - { - if (!fptr) return; //No previous conversation with this name. - } + if (!fptr) + { + return; //No previous conversation with this name. + } } - //LL_INFOS("") << "Reading:" << file_name << LL_ENDL; char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ char *bptr; S32 len; @@ -454,7 +456,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m LLSD item; if (!LLChatLogParser::parse(line, item, load_params)) { - item[IM_TEXT] = line; + item[LL_IM_TEXT] = line; } messages.push_back(item); } @@ -462,9 +464,78 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m fclose(fptr); } +// static +std::string LLLogChat::oldLogFileName(std::string filename) +{ + // get Users log directory + std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + directory += gDirUtilp->getDirDelimiter(); + + // lest make sure the file name has no invalid characters before making the pattern + filename = cleanFileName(filename); + + // create search pattern + std::string pattern = filename + ( filename == "chat" ? "-???\?-?\?-??.txt" : "-???\?-??.txt"); + + std::vector allfiles; + LLDirIterator iter(directory, pattern); + std::string scanResult; + + while (iter.next(scanResult)) + { + allfiles.push_back(scanResult); + } + + if (allfiles.size() == 0) // if no result from date search, return generic filename + { + scanResult = directory + filename + '.' + LL_TRANSCRIPT_FILE_EXTENSION; + } + else + { + sort(allfiles.begin(), allfiles.end()); + scanResult = directory + allfiles.back(); + // this file is now the most recent version of the file. + } + + return scanResult; +} + +// static +void LLLogChat::getListOfTranscriptFiles(std::vector& list_of_transcriptions) +{ + // get Users log directory + std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + directory += gDirUtilp->getDirDelimiter(); + + // create search pattern + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; + + LLDirIterator iter(directory, pattern); + std::string scanResult; + while (iter.next(scanResult)) + { + list_of_transcriptions.push_back(scanResult); + } +} + +//static +boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb) +{ + if (NULL == sSaveHistorySignal) + { + sSaveHistorySignal = new save_history_signal_t(); + } + + return sSaveHistorySignal->connect(cb); +} + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) -//Example, an object's name can be writen like "Object " +//Example, an object's name can be written like "Object " void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const { if (!im.isMap()) @@ -473,19 +544,19 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const return; } - if (im[IM_TIME].isDefined()) + if (im[LL_IM_TIME].isDefined()) { - std::string timestamp = im[IM_TIME].asString(); + std::string timestamp = im[LL_IM_TIME].asString(); boost::trim(timestamp); ostr << '[' << timestamp << ']' << TWO_SPACES; } //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) - //Example, an object's name can be writen like "Object " - if (im[IM_FROM].isDefined()) + //Example, an object's name can be written like "Object " + if (im[LL_IM_FROM].isDefined()) { - std::string from = im[IM_FROM].asString(); + std::string from = im[LL_IM_FROM].asString(); boost::trim(from); if (from.size()) { @@ -493,9 +564,9 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const } } - if (im[IM_TEXT].isDefined()) + if (im[LL_IM_TEXT].isDefined()) { - std::string im_text = im[IM_TEXT].asString(); + std::string im_text = im[LL_IM_TEXT].asString(); //multilined text will be saved with prepended spaces boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX); @@ -528,12 +599,12 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); } - im[IM_TIME] = timestamp; + im[LL_IM_TIME] = timestamp; } else { //timestamp is optional - im[IM_TIME] = ""; + im[LL_IM_TIME] = ""; } bool has_stuff = matches[IDX_STUFF].matched; @@ -559,8 +630,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params if (!has_name || name == SYSTEM_FROM) { //name is optional too - im[IM_FROM] = SYSTEM_FROM; - im[IM_FROM_ID] = LLUUID::null; + im[LL_IM_FROM] = SYSTEM_FROM; + im[LL_IM_FROM_ID] = LLUUID::null; } //possibly a case of complex object names consisting of 3+ words @@ -569,8 +640,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params U32 divider_pos = stuff.find(NAME_TEXT_DIVIDER); if (divider_pos != std::string::npos && divider_pos < (stuff.length() - NAME_TEXT_DIVIDER.length())) { - im[IM_FROM] = stuff.substr(0, divider_pos); - im[IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length()); + im[LL_IM_FROM] = stuff.substr(0, divider_pos); + im[LL_IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length()); return true; } } @@ -578,7 +649,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params if (!has_name) { //text is mandatory - im[IM_TEXT] = stuff; + im[LL_IM_TEXT] = stuff; return true; //parse as a message from Second Life } @@ -590,45 +661,15 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params { std::string agent_name; LLAgentUI::buildFullname(agent_name); - im[IM_FROM] = agent_name; - im[IM_FROM_ID] = gAgentID; + im[LL_IM_FROM] = agent_name; + im[LL_IM_FROM_ID] = gAgentID; } else { - im[IM_FROM] = name; + im[LL_IM_FROM] = name; } - im[IM_TEXT] = name_and_text[IDX_TEXT]; + im[LL_IM_TEXT] = name_and_text[IDX_TEXT]; return true; //parsed name and message text, maybe have a timestamp too } -std::string LLLogChat::oldLogFileName(std::string filename) -{ - std::string scanResult; - std::string directory = gDirUtilp->getPerAccountChatLogsDir();/* get Users log directory */ - directory += gDirUtilp->getDirDelimiter();/* add final OS dependent delimiter */ - filename=cleanFileName(filename);/* lest make shure the file name has no invalad charecters befor making the pattern */ - std::string pattern = (filename+(( filename == "chat" ) ? "-???\?-?\?-??.txt" : "-???\?-??.txt"));/* create search pattern*/ - //LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - std::vector allfiles; - - LLDirIterator iter(directory, pattern); - while (iter.next(scanResult)) - { - //LL_INFOS("") << "Found :" << scanResult << LL_ENDL; - allfiles.push_back(scanResult); - } - - if (allfiles.size() == 0) // if no result from date search, return generic filename - { - scanResult = directory + filename + ".txt"; - } - else - { - std::sort(allfiles.begin(), allfiles.end()); - scanResult = directory + allfiles.back(); - // thisfile is now the most recent version of the file. - } - //LL_INFOS("") << "Reading:" << scanResult << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - return scanResult; -} diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index d3e9adcc37..b35a94b4b3 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -49,6 +49,7 @@ public: const std::string& from, const LLUUID& from_id, const std::string& line); + static void getListOfTranscriptFiles(std::vector& list); /** @deprecated @see loadChatHistory() */ static void loadHistory(const std::string& filename, @@ -56,8 +57,13 @@ public: void* userdata); static void loadChatHistory(const std::string& file_name, std::list& messages, const LLSD& load_params = LLSD()); + + typedef boost::signals2::signal save_history_signal_t; + static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); + private: static std::string cleanFileName(std::string filename); + static save_history_signal_t * sSaveHistorySignal; }; /** @@ -113,9 +119,10 @@ protected: }; // LLSD map lookup constants -extern const std::string IM_TIME; //("time"); -extern const std::string IM_TEXT; //("message"); -extern const std::string IM_FROM; //("from"); -extern const std::string IM_FROM_ID; //("from_id"); +extern const std::string LL_IM_TIME; //("time"); +extern const std::string LL_IM_TEXT; //("message"); +extern const std::string LL_IM_FROM; //("from"); +extern const std::string LL_IM_FROM_ID; //("from_id"); +extern const std::string LL_TRANSCRIPT_FILE_EXTENSION; //("ll.txt"); #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8489e92d15..f141419c43 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6943,7 +6943,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**) std::string dir_visibility; msg->getString( "UserData", "DirectoryVisibility", dir_visibility); - LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); + LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email); LLFloaterSnapshot::setAgentEmail(email); } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6a464ccdc4..9c36873141 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8316,4 +8316,30 @@ Attempt cancelled. yestext="Yes"/> + + This will delete the log of previous conversations, and all transcripts of those conversations. Proceed? + confirm + + + + + This will delete transcripts for all previous conversations. The list of conversations will not be affected. Proceed? + confirm + + + diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 37bfbae991..4f33699aa6 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -1,7 +1,7 @@ + width="330"> + + - + width="330"> + + + width="350"> + + + Font size: - - + - + - + - - - + name="Large" + value="2"/> + + + + + + + - Notifications: + Notifications + top_pad="13"> Friend IMs: - - - - + top_pad="9"> Non-friend IMs: - - - - + top_pad="9"> Conference IMs: - - - - + top_pad="9"> Group chat: - - - - + top_pad="9"> Nearby chat: - - - - To temporarily stop all notifications, use Communicate > Do Not Disturb. @@ -308,14 +297,13 @@ + + + + + + + Save: + + + + + + + + + + + + + + + Location: + + + + + + + + - - (Locations, images, web, search history) - - - - + border="true" + follows="left|top|right|bottom" + height="408" + label="Communication" + layout="topleft" + left="102" + name="im" + top="1" + width="517"> + + + log in to change + + + + + + (Locations, images, web, search history) + + + + + + - - Chat Logs: - - - - - - - - - Location of logs: - - - +