summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/lllineeditor.cpp9
-rw-r--r--indra/llui/lllineeditor.h3
-rw-r--r--indra/llui/lltexteditor.cpp19
-rw-r--r--indra/llui/lltexteditor.h5
-rw-r--r--indra/llvfs/lldir.cpp13
-rw-r--r--indra/llvfs/lldir.h2
-rwxr-xr-xindra/newview/app_settings/settings.xml4
-rw-r--r--indra/newview/llautoreplace.cpp99
-rw-r--r--indra/newview/llautoreplace.h54
-rw-r--r--indra/newview/llconversationlog.cpp60
-rw-r--r--indra/newview/llconversationlog.h11
-rw-r--r--indra/newview/llconversationmodel.cpp18
-rwxr-xr-xindra/newview/llconversationmodel.h6
-rw-r--r--indra/newview/llfloaterconversationlog.cpp14
-rw-r--r--indra/newview/llfloaterconversationlog.h2
-rw-r--r--indra/newview/llfloaterimcontainer.cpp11
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp31
-rw-r--r--indra/newview/llfloaterimnearbychat.h2
-rw-r--r--indra/newview/llfloaterimsession.cpp22
-rw-r--r--indra/newview/llfloaterimsession.h2
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp28
-rw-r--r--indra/newview/llfloaterimsessiontab.h2
-rwxr-xr-xindra/newview/llfloaterpreference.cpp109
-rw-r--r--indra/newview/llfloaterpreference.h19
-rw-r--r--indra/newview/llimview.cpp49
-rw-r--r--indra/newview/llimview.h2
-rw-r--r--indra/newview/lllogchat.cpp235
-rw-r--r--indra/newview/lllogchat.h15
-rwxr-xr-xindra/newview/llviewermessage.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml26
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml284
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_privacy.xml226
-rw-r--r--indra/viewer_components/updater/tests/llupdaterservice_test.cpp1
33 files changed, 796 insertions, 589 deletions
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 48d49af588..2e64be89fa 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -157,8 +157,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mHighlightColor(p.highlight_color()),
mPreeditBgColor(p.preedit_bg_color()),
mGLFont(p.font),
- mContextMenuHandle(),
- mAutoreplaceCallback()
+ mContextMenuHandle()
{
llassert( mMaxLengthBytes > 0 );
@@ -971,12 +970,6 @@ void LLLineEditor::addChar(const llwchar uni_char)
LLUI::reportBadKeystroke();
}
- if (!mReadOnly && mAutoreplaceCallback != NULL)
- {
- // call callback
- mAutoreplaceCallback(mText, mCursorPos);
- }
-
getWindow()->hideCursorUntilMouseMove();
}
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 71dd53f608..40f931ecc1 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -189,9 +189,6 @@ public:
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
- typedef boost::function<void(LLUIString&, S32&)> autoreplace_callback_t;
- autoreplace_callback_t mAutoreplaceCallback;
- void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; }
const std::string& getLabel() { return mLabel.getString(); }
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index d42d6473ed..562bbc7100 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -247,6 +247,7 @@ LLTextEditor::Params::Params()
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
LLTextBase(p),
+ mAutoreplaceCallback(),
mBaseDocIsPristine(TRUE),
mPristineCmd( NULL ),
mLastCmd( NULL ),
@@ -1097,7 +1098,25 @@ void LLTextEditor::addChar(llwchar wc)
}
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
+
+ if (!mReadOnly && mAutoreplaceCallback != NULL)
+ {
+ // autoreplace the text, if necessary
+ S32 replacement_start;
+ S32 replacement_length;
+ LLWString replacement_string;
+ S32 new_cursor_pos = mCursorPos;
+ mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText());
+
+ if (replacement_length > 0 || !replacement_string.empty())
+ {
+ remove(replacement_start, replacement_length, true);
+ insert(replacement_start, replacement_string, false, LLTextSegmentPtr());
+ setCursorPos(new_cursor_pos);
+ }
+ }
}
+
void LLTextEditor::addLineBreakChar()
{
if( !getEnabled() )
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index f8f636b876..5e189070fa 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -157,6 +157,11 @@ public:
BOOL isPristine() const;
BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
+ // Autoreplace (formerly part of LLLineEditor)
+ typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t;
+ autoreplace_callback_t mAutoreplaceCallback;
+ void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
+
//
// Text manipulation
//
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<std::string> 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 @@
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>S32</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>2</integer>
</map>
<key>LandBrushSize</key>
<map>
diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp
index d71cf290d6..1d72397cbc 100644
--- a/indra/newview/llautoreplace.cpp
+++ b/indra/newview/llautoreplace.cpp
@@ -30,68 +30,60 @@
#include "llviewercontrol.h"
#include "llnotificationsutil.h"
-LLAutoReplace* LLAutoReplace::sInstance;
-
const char* LLAutoReplace::SETTINGS_FILE_NAME = "autoreplace.xml";
-LLAutoReplace::LLAutoReplace()
-{
-}
-
-LLAutoReplace::~LLAutoReplace()
+void LLAutoReplace::autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text)
{
- sInstance = NULL;
-}
+ // make sure these returned values are cleared in case there is no replacement
+ replacement_start = 0;
+ replacement_length = 0;
+ replacement_string.clear();
-void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos)
-{
static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace");
- if(perform_autoreplace)
+ if (perform_autoreplace)
{
- S32 wordEnd = cursorPos-1;
- LLWString text = inputText.getWString();
+ S32 word_end = cursor_pos - 1;
- bool atSpace = (text[wordEnd] == ' ');
- bool haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd]));
+ bool at_space = (input_text[word_end] == ' ');
+ bool have_word = (LLWStringUtil::isPartOfWord(input_text[word_end]));
- if (atSpace || haveWord)
+ if (at_space || have_word)
{
- if (atSpace && wordEnd > 0)
+ if (at_space && word_end > 0)
{
// find out if this space immediately follows a word
- wordEnd--;
- haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd]));
+ word_end--;
+ have_word = (LLWStringUtil::isPartOfWord(input_text[word_end]));
}
- if (haveWord)
+ if (have_word)
{
- // wordEnd points to the end of a word, now find the start of the word
+ // word_end points to the end of a word, now find the start of the word
std::string word;
- S32 wordStart = wordEnd;
- for ( S32 backOne = wordStart - 1;
- backOne >= 0 && LLWStringUtil::isPartOfWord(text[backOne]);
- backOne--
- )
+ S32 word_start = word_end;
+ for (S32 back_one = word_start - 1;
+ back_one >= 0 && LLWStringUtil::isPartOfWord(input_text[back_one]);
+ back_one--
+ )
{
- wordStart--; // walk wordStart back to the beginning of the word
+ word_start--; // walk word_start back to the beginning of the word
}
- LL_DEBUGS("AutoReplace")<<"wordStart: "<<wordStart<<" wordEnd: "<<wordEnd<<LL_ENDL;
- std::string strText = std::string(text.begin(), text.end());
- std::string lastWord = strText.substr(wordStart, wordEnd-wordStart+1);
- std::string replacementWord( mSettings.replaceWord( lastWord ) );
+ LL_DEBUGS("AutoReplace") << "word_start: " << word_start << " word_end: " << word_end << LL_ENDL;
+ std::string str_text = std::string(input_text.begin(), input_text.end());
+ std::string last_word = str_text.substr(word_start, word_end - word_start + 1);
+ std::string replacement_word(mSettings.replaceWord(last_word));
- if ( replacementWord != lastWord )
+ if (replacement_word != last_word)
{
// The last word is one for which we have a replacement
- if (atSpace)
+ if (at_space)
{
- // replace the last word in the input
- LLWString strNew = utf8str_to_wstring(replacementWord);
- LLWString strOld = utf8str_to_wstring(lastWord);
- int size_change = strNew.size() - strOld.size();
-
- text.replace(wordStart,lastWord.length(),strNew);
- inputText = wstring_to_utf8str(text);
- cursorPos+=size_change;
+ // return the replacement string
+ replacement_start = word_start;
+ replacement_length = last_word.length();
+ replacement_string = utf8str_to_wstring(replacement_word);
+ LLWString old_string = utf8str_to_wstring(last_word);
+ S32 size_change = replacement_string.size() - old_string.size();
+ cursor_pos += size_change;
}
}
}
@@ -99,16 +91,6 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos)
}
}
-LLAutoReplace* LLAutoReplace::getInstance()
-{
- if(!sInstance)
- {
- sInstance = new LLAutoReplace();
- sInstance->loadFromSettings();
- }
- return sInstance;
-}
-
std::string LLAutoReplace::getUserSettingsFileName()
{
std::string path=gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
@@ -147,6 +129,15 @@ void LLAutoReplace::setSettings(const LLAutoReplaceSettings& newSettings)
saveToUserSettings();
}
+LLAutoReplace::LLAutoReplace()
+{
+}
+
+void LLAutoReplace::initSingleton()
+{
+ loadFromSettings();
+}
+
void LLAutoReplace::loadFromSettings()
{
std::string filename=getUserSettingsFileName();
@@ -220,7 +211,7 @@ void LLAutoReplace::saveToUserSettings()
std::string filename=getUserSettingsFileName();
llofstream file;
file.open(filename.c_str());
- LLSDSerialize::toPrettyXML(mSettings.getAsLLSD(), file);
+ LLSDSerialize::toPrettyXML(mSettings.asLLSD(), file);
file.close();
LL_INFOS("AutoReplace") << "settings saved to '" << filename << "'" << LL_ENDL;
}
@@ -801,7 +792,7 @@ LLSD LLAutoReplaceSettings::getExampleLLSD()
return example;
}
-const LLSD& LLAutoReplaceSettings::getAsLLSD()
+const LLSD& LLAutoReplaceSettings::asLLSD()
{
return mLists;
}
diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h
index f720cc4eda..9eecc2d981 100644
--- a/indra/newview/llautoreplace.h
+++ b/indra/newview/llautoreplace.h
@@ -132,7 +132,7 @@ class LLAutoReplaceSettings
LLSD getExampleLLSD();
/// Get the actual settings as LLSD
- const LLSD& getAsLLSD();
+ const LLSD& asLLSD();
///< @note for use only in AutoReplace::saveToUserSettings
private:
@@ -183,49 +183,45 @@ class LLAutoReplaceSettings
* When the end of a word is detected (defined as any punctuation character,
* or any whitespace except newline or return), the preceding word is used
* as a lookup key in an ordered list of maps. If a match is found in any
- * map, the keyword is replaced by the associated value from the map.
+ * map, the replacement start index and length are returned along with the
+ * new replacement string.
*
* See the autoreplaceCallback method for how to add autoreplace functionality
* to a text entry tool.
*/
class LLAutoReplace : public LLSingleton<LLAutoReplace>
{
- public:
- LLAutoReplace();
- ~LLAutoReplace();
-
- /// @return a pointer to the active instance
- static LLAutoReplace* getInstance();
+public:
+ /// Callback that provides the hook for use in text entry methods
+ void autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text);
- /// Callback that provides the hook for use in text entry methods
- void autoreplaceCallback(LLUIString& inputText, S32& cursorPos);
+ /// Get a copy of the current settings
+ LLAutoReplaceSettings getSettings();
- /// Get a copy of the current settings
- LLAutoReplaceSettings getSettings();
+ /// Commit new settings after making changes
+ void setSettings(const LLAutoReplaceSettings& settings);
- /// Commit new settings after making changes
- void setSettings(const LLAutoReplaceSettings& settings);
-
- private:
- friend class LLSingleton<LLAutoReplace>;
- static LLAutoReplace* sInstance; ///< the active settings instance
+private:
+ friend class LLSingleton<LLAutoReplace>;
+ LLAutoReplace();
+ /*virtual*/ void initSingleton();
- LLAutoReplaceSettings mSettings; ///< configuration information
+ LLAutoReplaceSettings mSettings; ///< configuration information
- /// Read settings from persistent storage
- void loadFromSettings();
+ /// Read settings from persistent storage
+ void loadFromSettings();
- /// Make the newSettings active and write them to user storage
- void saveToUserSettings();
+ /// Make the newSettings active and write them to user storage
+ void saveToUserSettings();
- /// Compute the user settings file name
- std::string getUserSettingsFileName();
+ /// Compute the user settings file name
+ std::string getUserSettingsFileName();
- /// Compute the (read-ony) application settings file name
- std::string getAppSettingsFileName();
+ /// Compute the (read-ony) application settings file name
+ std::string getAppSettingsFileName();
- /// basename for the settings files
- static const char* SETTINGS_FILE_NAME;
+ /// basename for the settings files
+ static const char* SETTINGS_FILE_NAME;
};
#endif /* LLAUTOREPLACE_H */
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/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index a8da4908ce..7184a70db5 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -35,6 +35,7 @@
#include "llsdutil.h"
#include "llconversationmodel.h"
#include "llimview.h" //For LLIMModel
+#include "lltrans.h"
//
// Conversation items : common behaviors
@@ -461,6 +462,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display
LLConversationItem(display_name,uuid,root_view_model),
mIsMuted(false),
mIsModerator(false),
+ mDisplayModeratorLabel(false),
mDistToAgent(-1.0)
{
mDisplayName = display_name;
@@ -471,6 +473,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid,
LLConversationItem(uuid,root_view_model),
mIsMuted(false),
mIsModerator(false),
+ mDisplayModeratorLabel(false),
mDistToAgent(-1.0)
{
mConvType = CONV_PARTICIPANT;
@@ -503,6 +506,12 @@ void LLConversationItemParticipant::updateName(const LLAvatarName& av_name)
{
mName = av_name.getUserName();
mDisplayName = av_name.getDisplayName();
+
+ if (mDisplayModeratorLabel)
+ {
+ mDisplayName += " " + LLTrans::getString("IM_moderator_label");
+ }
+
renameItem(mDisplayName);
if (mParent != NULL)
{
@@ -541,6 +550,15 @@ void LLConversationItemParticipant::dumpDebugData()
llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl;
}
+void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole)
+{
+ if (displayRole != mDisplayModeratorLabel)
+ {
+ mDisplayModeratorLabel = displayRole;
+ updateName();
+ }
+}
+
//
// LLConversationSort
//
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 6aaea041e4..c907d1d6d2 100755
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -205,13 +205,15 @@ public:
void dumpDebugData();
void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; }
+ void setDisplayModeratorRole(bool displayRole);
private:
void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName
void updateName(const LLAvatarName& av_name);
- bool mIsMuted; // default is false
- bool mIsModerator; // default is false
+ bool mIsMuted; // default is false
+ bool mIsModerator; // default is false
+ bool mDisplayModeratorLabel; // default is false
std::string mDisplayName;
F64 mDistToAgent; // Distance to the agent. A negative (meaningless) value means the distance has not been set.
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<LLFilterEditor>("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 ff6234fa27..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())
{
@@ -1086,7 +1086,10 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
}
else
{
- doToParticipants(command, selectedIDS);
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1)
+ {
+ doToParticipants(command, selectedIDS);
+ }
}
}
}
@@ -1139,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
@@ -1790,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..a2dd93e10d 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -66,6 +66,7 @@
#include "llrootview.h"
#include "llviewerchat.h"
#include "lltranslate.h"
+#include "llautoreplace.h"
S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
@@ -111,7 +112,8 @@ BOOL LLFloaterIMNearbyChat::postBuild()
{
setIsSingleInstance(TRUE);
BOOL result = LLFloaterIMSessionTab::postBuild();
-
+
+ mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2, _3, _4, _5));
mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this));
mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this));
mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this));
@@ -148,8 +150,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 +182,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 +197,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 +527,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..f754853b82 100644
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -162,7 +162,7 @@ void LLFloaterIMSession::newIMCallback(const LLSD& data)
LLFloaterIMSession* floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id);
// update if visible, otherwise will be updated when opened
- if (floater && (floater->getHost()? floater->hasFocus() : floater->getVisible()))
+ if (floater && floater->isInVisibleChain())
{
floater->updateMessages();
}
@@ -332,13 +332,7 @@ BOOL LLFloaterIMSession::postBuild()
BOOL result = LLFloaterIMSessionTab::postBuild();
mInputEditor->setMaxTextLength(1023);
- // enable line history support for instant message bar
- // XXX stinson TODO : resolve merge by adding autoreplace to text editors
-#if 0
- // *TODO Establish LineEditor with autoreplace callback
- mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2));
-#endif
-
+ mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2, _3, _4, _5));
mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) );
mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) );
@@ -853,8 +847,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..f52cf3b8f0 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -497,6 +497,28 @@ void LLFloaterIMSessionTab::refreshConversation()
}
updateSessionName(session_name);
}
+
+ LLParticipantList* participant_list = getParticipantList();
+ if (participant_list)
+ {
+ LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = participant_list->getChildrenBegin();
+ LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = participant_list->getChildrenEnd();
+ LLIMSpeakerMgr *speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ while (current_participant_model != end_participant_model)
+ {
+ LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
+ if (speaker_mgr && participant_model)
+ {
+ LLSpeaker *participant_speaker = speaker_mgr->findSpeaker(participant_model->getUUID());
+ LLSpeaker *agent_speaker = speaker_mgr->findSpeaker(gAgentID);
+ if (participant_speaker && agent_speaker)
+ {
+ participant_model->setDisplayModeratorRole(agent_speaker->mIsModerator && participant_speaker->mIsModerator);
+ }
+ }
+ current_participant_model++;
+ }
+ }
mConversationViewModel.requestSortAll();
if(mConversationsRoot != NULL)
@@ -680,7 +702,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 +711,14 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate()
LLFloaterIMSession* floater = dynamic_cast<LLFloaterIMSession*>(*iter);
if (floater)
{
- floater->reloadMessages();
+ floater->reloadMessages(clean_messages);
}
}
LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("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<LLFloaterPreference>);
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<std::string> list_of_transcriptions_file_names;
+ LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names);
+ getChild<LLButton>("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<LLFloaterPreference>("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<LLUICtrl>("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<LLUICtrl>("online_visibility")->setValue(mOriginalHideOnlineStatus);
getChild<LLUICtrl>("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility);
getChildView("send_im_to_email")->setEnabled(TRUE);
getChild<LLUICtrl>("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<LLUICtrl>("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<std::string> list_of_transcriptions_file_names;
+ LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names);
+ getChild<LLButton>("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0);
+
+ LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true);
+ }
+}
+
+void LLFloaterPreference::onLogChatHistorySaved()
+{
+ LLButton * delete_transcripts_buttonp = getChild<LLButton>("delete_transcripts");
+
+ if (!delete_transcripts_buttonp->getEnabled())
+ {
+ delete_transcripts_buttonp->setEnabled(true);
+ }
+}
+
void LLFloaterPreference::updateClickActionSettings()
{
const int single_clk_action = getChild<LLComboBox>("single_click_action_combo")->getValue().asInteger();
@@ -1624,6 +1665,11 @@ void LLFloaterPreference::selectChatPanel()
selectPanel("chat");
}
+void LLFloaterPreference::changed()
+{
+ getChild<LLButton>("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<LLUICtrl>("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..8f010850f7 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -237,7 +237,7 @@ void on_new_message(const LLSD& msg)
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
}
}
- }
+ }
}
else if ("flash" == action)
@@ -273,9 +273,9 @@ void on_new_message(const LLSD& msg)
if(!gAgent.isDoNotDisturb())
{
- //Surface conversations floater
- LLFloaterReg::showInstance("im_container");
- }
+ //Surface conversations floater
+ LLFloaterReg::showInstance("im_container");
+ }
//If in DND mode, allow notification to be stored so upon DND exit
//useMostItrusiveIMNotification will be called to notify user a message exists
@@ -284,8 +284,8 @@ void on_new_message(const LLSD& msg)
&& gAgent.isDoNotDisturb())
{
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
-}
+ }
+ }
}
}
@@ -378,15 +378,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
}
buildHistoryFileName();
-
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
- {
- std::list<LLSD> 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<LLSD>& 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<LLSD>& 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<LLSD> 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<LLSD>& 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<LLLogChatTimeScanner>
{
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<std::string::const_iterator> matches;
+ * Testing for in bound and out bound ad-hoc file names
+ * if it is then skip date stamping.
+ **/
+
+ boost::match_results<std::string::const_iterator> 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<LLSD>& 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<LLSD>& messages, const LLSD& load_params)
{
@@ -397,19 +402,16 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& 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<LLSD>& 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<LLSD>& 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<std::string> 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<std::string>& 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 <actual_object's_name>"
+//Example, an object's name can be written like "Object <actual_object's_name>"
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 <actual_object's_name>"
- if (im[IM_FROM].isDefined())
+ //Example, an object's name can be written like "Object <actual_object's_name>"
+ 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<std::string> 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<std::string>& 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<LLSD>& messages, const LLSD& load_params = LLSD());
+
+ typedef boost::signals2::signal<void ()> 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"/>
</notification>
+ <notification
+ icon="alertmodal.tga"
+ name="PreferenceChatClearLog"
+ type="alertmodal">
+ This will delete the log of previous conversations, and all transcripts of those conversations. Proceed?
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm before I delete the log of previous conversations."
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PreferenceChatDeleteTranscripts"
+ type="alertmodal">
+ This will delete transcripts for all previous conversations. The list of conversations will not be affected. Proceed?
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm before I delete transcripts."
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
</notifications>
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 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
border="true"
- follows="left|top|right|bottom"
+ has_border="true"
height="408"
label="Text Chat"
layout="topleft"
@@ -12,8 +12,7 @@
<panel
border="false"
- follows="left|top"
- height="90"
+ height="60"
layout="topleft"
top="10"
left="13"
@@ -27,7 +26,9 @@
layout="topleft"
top="0"
name="play_typing_animation"
- width="330" />
+ width="330">
+ </check_box>
+
<check_box
enabled="false"
height="16"
@@ -35,26 +36,21 @@
layout="topleft"
name="send_im_to_email"
top_pad="6"
- width="330" />
- <check_box
- control_name="KeepConversationLogTranscripts"
- height="16"
- label="Keep a conversation log and transcripts"
- layout="topleft"
- name="keep_convo_log_and_transcripts"
- top_pad="6"
- width="330" />
+ width="330">
+ </check_box>
+
<check_box
- control_name="UseChatBubbles"
- follows="left|top"
+ control_name="VoiceCallsFriendsOnly"
height="16"
- label="Bubble Chat"
+ label="Only friends and groups can call or IM me"
layout="topleft"
+ name="voice_call_friends_only_check"
top_pad="6"
- name="bubble_text_chat"
- width="330" />
+ width="350">
+ <check_box.label_text text_color="White" />
+ </check_box>
+
<text
- follows="left|top"
layout="topleft"
left="345"
height="12"
@@ -63,67 +59,65 @@
top="0">
Font size:
</text>
- <radio_group
- height="90"
- layout="topleft"
- left="352"
+
+ <combo_box
control_name="ChatFontSize"
+ height="23"
+ layout="topleft"
+ left="341"
name="chat_font_size"
- top_pad="0"
- width="50">
- <radio_item
- height="16"
+ top_pad="5"
+ width="100">
+ <item
label="Small"
- layout="topleft"
- name="radio"
- value="0"
- top="10"
- width="125" />
- <radio_item
- height="16"
+ name="Small"
+ value="0"/>
+ <item
label="Medium"
- layout="topleft"
- name="radio2"
- value="1"
- top_pad="6"
- width="125" />
- <radio_item
- height="16"
+ name="Medium"
+ value="1"/>
+ <item
label="Large"
- layout="topleft"
- name="radio3"
- value="2"
- top_pad="6"
- width="125" />
- </radio_group>
-
- </panel>
+ name="Large"
+ value="2"/>
+ <combo_box.drop_down_button label_color="White" />
+ </combo_box>
+
+ <check_box
+ control_name="UseChatBubbles"
+ height="16"
+ label="Bubble Chat"
+ layout="topleft"
+ top_pad="4"
+ name="bubble_text_chat"
+ width="330">
+ </check_box>
+
+ </panel>
<panel
border="false"
- follows="left|top"
- height="198"
+ height="165"
layout="topleft"
left="13"
width="517">
<text
- follows="left|top"
layout="topleft"
height="12"
name="notifications"
left="0"
+ text_color="White"
width="120">
- Notifications:
+ Notifications
</text>
<text
- follows="left|top"
layout="topleft"
height="12"
name="friend_ims"
width="145"
left="0"
- top_pad="15">
+ top_pad="13">
Friend IMs:
</text>
<combo_box
@@ -134,31 +128,30 @@
top_delta="-6"
name="FriendIMOptions"
width="223">
- <combo_box.item
+ <item
label="Open Conversations window"
name="OpenConversationsWindow"
value="openconversations"/>
- <combo_box.item
+ <item
label="Pop up the message"
name="PopUpMessage"
value="toast"/>
- <combo_box.item
+ <item
label="Flash toolbar button"
name="FlashToolbarButton"
value="flash"/>
- <combo_box.item
+ <item
label="None"
name="None"
value="none"/>
</combo_box>
<text
- follows="left|top"
layout="topleft"
height="12"
name="non_friend_ims"
width="145"
left="0"
- top_pad="15">
+ top_pad="9">
Non-friend IMs:
</text>
<combo_box
@@ -169,31 +162,30 @@
top_delta="-6"
name="NonFriendIMOptions"
width="223">
- <combo_box.item
+ <item
label="Open Conversations window"
name="OpenConversationsWindow"
value="openconversations"/>
- <combo_box.item
+ <item
label="Pop up the message"
name="PopUpMessage"
value="toast"/>
- <combo_box.item
+ <item
label="Flash toolbar button"
name="FlashToolbarButton"
value="flash"/>
- <combo_box.item
+ <item
label="None"
name="None"
value="none"/>
</combo_box>
<text
- follows="left|top"
layout="topleft"
left="0"
height="13"
name="conference_ims"
width="145"
- top_pad="14">
+ top_pad="9">
Conference IMs:
</text>
<combo_box
@@ -204,31 +196,30 @@
top_delta="-6"
name="ConferenceIMOptions"
width="223">
- <combo_box.item
+ <item
label="Open Conversations window"
name="OpenConversationsWindow"
value="openconversations"/>
- <combo_box.item
+ <item
label="Pop up the message"
name="PopUpMessage"
value="toast"/>
- <combo_box.item
+ <item
label="Flash toolbar button"
name="FlashToolbarButton"
value="flash"/>
- <combo_box.item
+ <item
label="None"
name="None"
value="none"/>
</combo_box>
<text
- follows="left|top"
layout="topleft"
left="0"
height="13"
name="group_chat"
width="145"
- top_pad="14">
+ top_pad="9">
Group chat:
</text>
<combo_box
@@ -239,31 +230,30 @@
top_delta="-6"
name="GroupChatOptions"
width="223">
- <combo_box.item
+ <item
label="Open Conversations window"
name="OpenConversationsWindow"
value="openconversations"/>
- <combo_box.item
+ <item
label="Pop up the message"
name="PopUpMessage"
value="toast"/>
- <combo_box.item
+ <item
label="Flash toolbar button"
name="FlashToolbarButton"
value="flash"/>
- <combo_box.item
+ <item
label="None"
name="None"
value="none"/>
</combo_box>
<text
- follows="left|top"
layout="topleft"
left="0"
height="12"
name="nearby_chat"
width="145"
- top_pad="14">
+ top_pad="9">
Nearby chat:
</text>
<combo_box
@@ -274,31 +264,30 @@
top_delta="-6"
name="NearbyChatOptions"
width="223">
- <combo_box.item
+ <item
label="Open Conversations window"
name="OpenConversationsWindow"
value="openconversations"/>
- <combo_box.item
+ <item
label="Pop up the message"
name="PopUpMessage"
value="toast"/>
- <combo_box.item
+ <item
label="Flash toolbar button"
name="FlashToolBarButton"
value="flash"/>
- <combo_box.item
+ <item
label="None"
name="None"
value="none"/>
</combo_box>
<text
- follows="left|top"
layout="topleft"
left="0"
height="13"
name="notifications_alert"
width="500"
- top_pad="11"
+ top_pad="9"
visible="true"
text_color="DrYellow">
To temporarily stop all notifications, use Communicate &gt; Do Not Disturb.
@@ -308,14 +297,13 @@
<panel
border="false"
- follows="left|top"
- height="67"
+ height="50"
layout="topleft"
left="13"
+ top_pad="10"
width="517">
<text
- follows="left|top"
layout="topleft"
left="0"
name="play_sound"
@@ -360,9 +348,123 @@
width="150" />
</panel>
+
+ <view_border
+ bevel_style="none"
+ height="0"
+ layout="topleft"
+ left="13"
+ name="cost_text_border"
+ top_pad="5"
+ width="495"/>
+
+ <panel
+ height="50"
+ layout="topleft"
+ left="13"
+ top_pad="10"
+ width="505">
+
+ <text
+ layout="topleft"
+ left="0"
+ text_color="White"
+ height="12"
+ top="5"
+ width="55">
+ Save:
+ </text>
+
+ <combo_box
+ control_name="KeepConversationLogTranscripts"
+ height="23"
+ layout="topleft"
+ left_pad="5"
+ name="chat_font_size"
+ top="0"
+ width="165">
+ <item
+ label="Log and transcripts"
+ value="2"/>
+ <item
+ label="Log only"
+ value="1"/>
+ <item
+ label="No log or transcripts"
+ value="0"/>
+ <drop_down_button label_color="White" />
+ </combo_box>
+
+ <button
+ enabled="false"
+ height="23"
+ label="Clear log..."
+ label_color="White"
+ layout="topleft"
+ left_pad="5"
+ top="0"
+ name="clear_log"
+ width="110">
+ <commit_callback
+ function="Pref.ClearLog" />
+ </button>
+
+ <button
+ enabled="false"
+ height="23"
+ label="Delete transcripts..."
+ label_color="White"
+ layout="topleft"
+ left_pad="5"
+ top="0"
+ name="delete_transcripts"
+ width="147">
+ <button.commit_callback
+ function="Pref.DeleteTranscripts" />
+ </button>
+
+ <text
+ layout="topleft"
+ left="0"
+ text_color="White"
+ height="12"
+ top_pad="15"
+ width="55">
+ Location:
+ </text>
+
+ <line_editor
+ control_name="InstantMessageLogPath"
+ border_style="line"
+ border_thickness="1"
+ font="SansSerif"
+ height="23"
+ layout="topleft"
+ left_pad="55"
+ max_length="4096"
+ name="log_path_string"
+ top_delta="-5"
+ width="185">
+ </line_editor>
+
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Browse..."
+ label_color="White"
+ label_selected="Browse"
+ layout="topleft"
+ left_pad="5"
+ name="log_path_button"
+ top_delta="0"
+ width="112">
+ <commit_callback function="Pref.LogPath" />
+ </button>
+
+ </panel>
<button
- follows="left|top"
height="23"
label="Translation..."
layout="topleft"
@@ -370,11 +472,10 @@
name="ok_btn"
top="-29"
width="170">
- <button.commit_callback
+ <commit_callback
function="Pref.TranslationSettings" />
</button>
<button
- follows="top|left"
height="23"
layout="topleft"
top_pad="-23"
@@ -385,7 +486,6 @@
width="150">
</button>
<button
- follows="top|left"
height="23"
layout="topleft"
top_pad="-23"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
index 587c461bee..78743d26bb 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -1,72 +1,69 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- border="true"
- follows="left|top|right|bottom"
- height="408"
- label="Communication"
- layout="topleft"
- left="102"
- name="im"
- top="1"
- width="517">
- <panel.string
- name="log_in_to_change">
- log in to change
- </panel.string>
- <button
- follows="left|bottom"
- height="23"
- label="Clear History"
- tool_tip="Clear login image, last location, teleport history, web, and texture cache"
- layout="topleft"
- left="30"
- name="clear_cache"
- top="10"
- width="145">
- <button.commit_callback
- function="Pref.WebClearCache" />
- </button>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_pad="10"
- mouse_opaque="false"
- name="cache_size_label_l"
- top_delta="3"
- text_color="LtGray_50"
- width="300">
- (Locations, images, web, search history)
- </text>
- <check_box
- height="16"
- enabled="false"
- label="Show me in Search results"
- layout="topleft"
- left="30"
- name="online_searchresults"
- top_pad="20"
- width="350" />
- <check_box
- height="16"
- enabled="false"
- label="Only friends and groups know I'm online"
- layout="topleft"
- left="30"
- name="online_visibility"
- top_pad="30"
- width="350" />
- <check_box
- control_name="VoiceCallsFriendsOnly"
- height="16"
- label="Only friends and groups can call or IM me"
- layout="topleft"
- left="30"
- name="voice_call_friends_only_check"
- top_pad="10"
- width="350" />
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Communication"
+ layout="topleft"
+ left="102"
+ name="im"
+ top="1"
+ width="517">
+
+ <panel.string
+ name="log_in_to_change">
+ log in to change
+ </panel.string>
+
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Clear History"
+ tool_tip="Clear login image, last location, teleport history, web, and texture cache"
+ layout="topleft"
+ left="30"
+ name="clear_cache"
+ top="10"
+ width="145">
+ <button.commit_callback
+ function="Pref.WebClearCache" />
+ </button>
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="cache_size_label_l"
+ top_delta="3"
+ text_color="LtGray_50"
+ width="300">
+ (Locations, images, web, search history)
+ </text>
+
+ <check_box
+ height="16"
+ enabled="false"
+ label="Show me in Search results"
+ layout="topleft"
+ left="30"
+ name="online_searchresults"
+ top_pad="20"
+ width="350" />
+
+ <check_box
+ height="16"
+ enabled="false"
+ label="Only friends and groups know I'm online"
+ layout="topleft"
+ left="30"
+ name="online_visibility"
+ top_pad="30"
+ width="350" />
+
<check_box
enabled_control="EnableVoiceChat"
control_name="AutoDisengageMic"
@@ -87,100 +84,7 @@
name="favorites_on_login_check"
top_pad="10"
width="350" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left="30"
- mouse_opaque="false"
- name="Logs:"
- top_pad="20"
- width="350">
- Chat Logs:
- </text>
- <check_box
- enabled="false"
- control_name="LogNearbyChat"
- height="16"
- label="Save nearby chat logs on my computer"
- layout="topleft"
- left="30"
- name="log_nearby_chat"
- top_pad="10"
- width="350">
- </check_box>
- <check_box
- enabled="false"
- control_name="LogInstantMessages"
- height="16"
- label="Save IM logs on my computer"
- layout="topleft"
- left="30"
- name="log_instant_messages"
- top_pad="10"
- width="350">
- </check_box>
- <check_box
- control_name="LogTimestamp"
- enabled="false"
- height="16"
- label="Add timestamp to each line in chat log"
- layout="topleft"
- left_delta="0"
- name="show_timestamps_check_im"
- top_pad="10"
- width="237" />
- <check_box
- control_name="LogFileNamewithDate"
- enabled="false"
- height="16"
- label="Add datestamp to log file name."
- layout="topleft"
- left_delta="5"
- name="logfile_name_datestamp"
- top_pad="10"
- width="350"/>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- name="log_path_desc"
- top_pad="30"
- width="128">
- Location of logs:
- </text>
- <line_editor
- bottom="366"
- control_name="InstantMessageLogPath"
- follows="top|left|right"
- halign="right"
- height="23"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- name="log_path_string"
- top_pad="5"
- width="250"/>
- <button
- enabled="false"
- follows="right|bottom"
- height="23"
- label="Browse"
- label_selected="Browse"
- layout="topleft"
- left_pad="5"
- name="log_path_button"
- top_delta="0"
- width="145">
- <button.commit_callback
- function="Pref.LogPath" />
- </button>
+
<button
follows="left|bottom"
height="23"
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index a49bc4161e..de07beee7c 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -83,6 +83,7 @@ std::string LLDir::getSkinFolder() const { return "default"; }
std::string LLDir::getLanguage() const { return "en"; }
bool LLDir::setCacheDir(const std::string &path){ return true; }
void LLDir::dumpCurrentDirectories() {}
+void LLDir::updatePerAccountChatLogsDir() {}
std::string LLDir::getExpandedFilename(ELLPath location,
const std::string &filename) const