From d4ee17e533d652e90989e60bcbc097c81e73d081 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Tue, 28 Aug 2012 14:48:32 +0300 Subject: CHUI-275 FIXED (Chat history viewer does not show entire user.txt IM log file) - Renamed LLLogChat::loadAllHistory to LLLogChat::loadChatHistory because it doesn't actually loads all history. Also added parameter to the function which is a flag whether to load all file's content or not. - Implemented displaying history by pages (as was decided on meeting page): Added showHistory() method to the LLFloaterConversationPreview which shows the chat history page by page starting from the last conversation (or may say starting from the last page). One page contains 100 entries. Added "More history..." button to display next page of history. --- indra/newview/lllogchat.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index ebb5912ace..073f5f00c5 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -387,7 +387,7 @@ void append_to_last_message(std::list& messages, const std::string& line) } // static -void LLLogChat::loadAllHistory(const std::string& file_name, std::list& messages) +void LLLogChat::loadChatHistory(const std::string& file_name, std::list& messages, bool load_all_history/*= false*/) { if (file_name.empty()) { @@ -412,8 +412,8 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list& me S32 len; bool firstline = TRUE; - if (fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) - { //File is smaller than recall size. Get it all. + if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) + { //We need to load the whole historyFile or it's smaller than recall size, so get it all. firstline = FALSE; if (fseek(fptr, 0, SEEK_SET)) { -- cgit v1.3 From a6370cf4a72371e090d45f2a147929d016f42780 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Thu, 13 Sep 2012 18:49:57 +0300 Subject: CHUI-334 FIXED (Date not shown in the chat log for current date entries) Before the "%Y/%m/%d" was always cutted from timestamp string for today's date. Now I added flag whether we should cut off timestamp or not. --- indra/newview/llfloaterconversationpreview.cpp | 6 +++++- indra/newview/lllogchat.cpp | 17 +++++++++++++---- indra/newview/lllogchat.h | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index dbcf154ef2..88efc39764 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -65,7 +65,11 @@ BOOL LLFloaterConversationPreview::postBuild() std::string title = getString("Title", args); setTitle(title); - LLLogChat::loadChatHistory(file, mMessages, true); + LLSD load_params; + load_params["load_all_history"] = true; + load_params["cut_off_todays_date"] = false; + + LLLogChat::loadChatHistory(file, mMessages, load_params); mCurrentPage = mMessages.size() / mPageSize; mPageSpinner = getChild("history_page_spin"); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 073f5f00c5..3692658e9e 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -387,13 +387,16 @@ void append_to_last_message(std::list& messages, const std::string& line) } // static -void LLLogChat::loadChatHistory(const std::string& file_name, std::list& messages, bool load_all_history/*= false*/) +void LLLogChat::loadChatHistory(const std::string& file_name, std::list& messages, const LLSD& load_params) { if (file_name.empty()) { llwarns << "Session name is Empty!" << llendl; return ; } + + 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*/ @@ -449,7 +452,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m else { LLSD item; - if (!LLChatLogParser::parse(line, item)) + if (!LLChatLogParser::parse(line, item, load_params)) { item[IM_TEXT] = line; } @@ -500,10 +503,11 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const } } -bool LLChatLogParser::parse(std::string& raw, LLSD& im) +bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params) { if (!raw.length()) return false; + bool cut_off_todays_date = parse_params.has("cut_off_todays_date") ? parse_params["cut_off_todays_date"].asBoolean() : true; im = LLSD::emptyMap(); //matching a timestamp @@ -518,7 +522,12 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im) boost::trim(timestamp); timestamp.erase(0, 1); timestamp.erase(timestamp.length()-1, 1); - LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); + + if (cut_off_todays_date) + { + LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); + } + im[IM_TIME] = timestamp; } else diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 95f83e64e5..d3e9adcc37 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -55,7 +55,7 @@ public: void (*callback)(ELogLineType, const LLSD&, void*), void* userdata); - static void loadChatHistory(const std::string& file_name, std::list& messages, bool load_all_history = false); + static void loadChatHistory(const std::string& file_name, std::list& messages, const LLSD& load_params = LLSD()); private: static std::string cleanFileName(std::string filename); }; @@ -105,7 +105,7 @@ public: * * @return false if failed to parse mandatory data - message text */ - static bool parse(std::string& raw, LLSD& im); + static bool parse(std::string& raw, LLSD& im, const LLSD& parse_params = LLSD()); protected: LLChatLogParser(); -- 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/lllogchat.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: - - - +