From 10c5f2f080b47561db2b1f9a2f063ad8dcc175b9 Mon Sep 17 00:00:00 2001
From: Eugene Mutavchi <emutavchi@productengine.com>
Date: Fri, 19 Feb 2010 13:36:47 +0200
Subject: [PATCH] Implemented low task EXT-5215 (Disable showing full
 yyyy/mm/dd timestamp for messages (nearby chat/im) received today)

--HG--
branch : product-engine
---
 indra/llcommon/llchat.h         |  3 +-
 indra/newview/llchathistory.cpp | 13 +++--
 indra/newview/llchathistory.h   |  3 +-
 indra/newview/llimfloater.cpp   |  2 +
 indra/newview/llimview.cpp      |  9 ++--
 indra/newview/llimview.h        |  2 +-
 indra/newview/lllogchat.cpp     | 90 ++++++++++++++++++++++++++++++++-
 indra/newview/llnearbychat.cpp  |  1 +
 8 files changed, 108 insertions(+), 15 deletions(-)

diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
index a77bd211f34..52238d4533f 100644
--- a/indra/llcommon/llchat.h
+++ b/indra/llcommon/llchat.h
@@ -68,7 +68,8 @@ typedef enum e_chat_audible_level
 typedef enum e_chat_style
 {
 	CHAT_STYLE_NORMAL,
-	CHAT_STYLE_IRC
+	CHAT_STYLE_IRC,
+	CHAT_STYLE_HISTORY
 }EChatStyle;
 
 // A piece of chat
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 8fb9decf7bc..6180b880b58 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -66,8 +66,6 @@ static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
 
 const static std::string NEW_LINE(rawstr_to_utf8("\n"));
 
-const static U32 LENGTH_OF_TIME_STR = std::string("12:00").length();
-
 const static std::string SLURL_APP_AGENT = "secondlife:///app/agent/";
 const static std::string SLURL_ABOUT = "/about";
 
@@ -435,7 +433,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
 	mTopSeparatorPad(p.top_separator_pad),
 	mBottomSeparatorPad(p.bottom_separator_pad),
 	mTopHeaderPad(p.top_header_pad),
-	mBottomHeaderPad(p.bottom_header_pad)
+	mBottomHeaderPad(p.bottom_header_pad),
+	mIsLastMessageFromLog(false)
 {
 	LLTextEditor::Params editor_params(p);
 	editor_params.rect = getLocalRect();
@@ -602,8 +601,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		style_params.font.style = "ITALIC";
 	}
 
-	//*HACK we graying out chat history by graying out messages that contains full date in a time string
-	bool message_from_log = chat.mTimeStr.length() > LENGTH_OF_TIME_STR; 
+	bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;
+	// We graying out chat history by graying out messages that contains full date in a time string
 	if (message_from_log)
 	{
 		style_params.color(LLColor4::grey);
@@ -672,7 +671,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 			&& mLastFromID == chat.mFromID
 			&& mLastMessageTime.notNull() 
 			&& (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0
-			&& mLastMessageTimeStr.size() == chat.mTimeStr.size())  //*HACK to distinguish between current and previous chat session's histories
+			&& mIsLastMessageFromLog == message_from_log)  //distinguish between current and previous chat session's histories
 		{
 			view = getSeparator();
 			p.top_pad = mTopSeparatorPad;
@@ -706,7 +705,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 		mLastFromName = chat.mFromName;
 		mLastFromID = chat.mFromID;
 		mLastMessageTime = new_message_time;
-		mLastMessageTimeStr = chat.mTimeStr;
+		mIsLastMessageFromLog = message_from_log;
 	}
 
    if (chat.mNotifId.notNull())
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index 32600bb71d0..950b32861bd 100644
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -128,7 +128,8 @@ class LLChatHistory : public LLUICtrl
 		std::string mLastFromName;
 		LLUUID mLastFromID;
 		LLDate mLastMessageTime;
-		std::string mLastMessageTimeStr;
+		bool mIsLastMessageFromLog;
+		//std::string mLastMessageTimeStr;
 
 		std::string mMessageHeaderFilename;
 		std::string mMessageSeparatorFilename;
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 847695577a0..9c0e7a158d5 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -633,12 +633,14 @@ void LLIMFloater::updateMessages()
 			LLUUID from_id = msg["from_id"].asUUID();
 			std::string from = msg["from"].asString();
 			std::string message = msg["message"].asString();
+			bool is_history = msg["is_history"].asBoolean();
 
 			LLChat chat;
 			chat.mFromID = from_id;
 			chat.mSessionID = mSessionID;
 			chat.mFromName = from;
 			chat.mTimeStr = time;
+			chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle;
 
 			// process offer notification
 			if (msg.has("notification_id"))
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 77e3012d261..faddffe0fc2 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -357,7 +357,7 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_
 	}
 }
 
-void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time)
+void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history)
 {
 	LLSD message;
 	message["from"] = from;
@@ -365,6 +365,7 @@ void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& f
 	message["message"] = utf8_text;
 	message["time"] = time; 
 	message["index"] = (LLSD::Integer)mMsgs.size(); 
+	message["is_history"] = is_history;
 
 	mMsgs.push_front(message); 
 
@@ -393,7 +394,7 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo
 		std::string timestamp = msg[IM_TIME];
 		std::string text = msg[IM_TEXT];
 
-		addMessage(from, from_id, text, timestamp);
+		addMessage(from, from_id, text, timestamp, true);
 
 		it++;
 	}
@@ -407,11 +408,11 @@ void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const
 
 	if (type == LLLogChat::LOG_LINE)
 	{
-		self->addMessage("", LLSD(), msg["message"].asString(), "");
+		self->addMessage("", LLSD(), msg["message"].asString(), "", true);
 	}
 	else if (type == LLLogChat::LOG_LLSD)
 	{
-		self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString());
+		self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString(), true);
 	}
 }
 
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index ad6cede727b..e7404074e04 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -66,7 +66,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 
 		void sessionInitReplyReceived(const LLUUID& new_session_id);
 		void addMessagesFromHistory(const std::list<LLSD>& history);
-		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
+		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false);
 		void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
 		
 		/** @deprecated */
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index f13445fa5dc..3650b433648 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -39,12 +39,17 @@
 #include "llviewercontrol.h"
 
 #include "llinstantmessage.h"
+#include "llsingleton.h" // for LLSingleton
 
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/regex.hpp>
 #include <boost/regex/v4/match_results.hpp>
 
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/local_time_adjustor.hpp>
+
 const S32 LOG_RECALL_SIZE = 2048;
 
 const static std::string IM_TIME("time");
@@ -83,11 +88,93 @@ const static boost::regex NAME_AND_TEXT("(You:|Second Life:|[^\\s:]+\\s*[:]{1}|\
 //is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st"
 const static std::string NAME_TEXT_DIVIDER(": ");
 
+// is used for timestamps adjusting
+const static char* DATE_FORMAT("%Y/%m/%d %H:%M");
+const static char* TIME_FORMAT("%H:%M");
+
 const static int IDX_TIMESTAMP = 1;
 const static int IDX_STUFF = 2;
 const static int IDX_NAME = 1;
 const static int IDX_TEXT = 3;
 
+using namespace boost::posix_time;
+using namespace boost::gregorian;
+
+class LLLogChatTimeScaner: public LLSingleton<LLLogChatTimeScaner>
+{
+public:
+	LLLogChatTimeScaner()
+	{
+		// Note, date/time facets will be destroyed by string streams
+		mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT)));
+		mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT)));
+		mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT)));
+	}
+
+	date getTodayPacificDate()
+	{
+		typedef	boost::date_time::local_adjustor<ptime, -8, no_dst> pst;
+		typedef boost::date_time::local_adjustor<ptime, -7, no_dst> pdt;
+		time_t t_time = time(NULL);
+		ptime p_time = LLStringOps::getPacificDaylightTime()
+			? pdt::utc_to_local(from_time_t(t_time))
+			: pst::utc_to_local(from_time_t(t_time));
+		struct tm s_tm = to_tm(p_time);
+		return date_from_tm(s_tm);
+	}
+
+	void checkAndCutOffDate(std::string& time_str)
+	{
+		// Cuts off the "%Y/%m/%d" from string for todays timestamps.
+		// Assume that passed string has at least "%H:%M" time format.
+		date log_date(not_a_date_time);
+		date today(getTodayPacificDate());
+
+		// Parse the passed date
+		mDateStream.str(LLStringUtil::null);
+		mDateStream << time_str;
+		mDateStream >> log_date;
+		mDateStream.clear();
+
+		days zero_days(0);
+		days days_alive = today - log_date;
+
+		if ( days_alive == zero_days )
+		{
+			// Yep, today's so strip "%Y/%m/%d" info
+			ptime stripped_time(not_a_date_time);
+
+			mTimeStream.str(LLStringUtil::null);
+			mTimeStream << time_str;
+			mTimeStream >> stripped_time;
+			mTimeStream.clear();
+
+			time_str.clear();
+
+			mTimeStream.str(LLStringUtil::null);
+			mTimeStream << stripped_time;
+			mTimeStream >> time_str;
+			mTimeStream.clear();
+		}
+
+		LL_DEBUGS("LLChatLogParser")
+			<< " log_date: "
+			<< log_date
+			<< " today: "
+			<< today
+			<< " days alive: "
+			<< days_alive
+			<< " new time: "
+			<< time_str
+			<< LL_ENDL;
+	}
+
+
+private:
+	std::stringstream mDateStream;
+	std::stringstream mTimeStream;
+};
+
 //static
 std::string LLLogChat::makeLogFileName(std::string filename)
 {
@@ -377,7 +464,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im)
 		boost::trim(timestamp);
 		timestamp.erase(0, 1);
 		timestamp.erase(timestamp.length()-1, 1);
-		im[IM_TIME] = timestamp;	
+		LLLogChatTimeScaner::instance().checkAndCutOffDate(timestamp);
+		im[IM_TIME] = timestamp;
 	}
 	else
 	{
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 8fc11d3929b..16384ef6e0c 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -303,6 +303,7 @@ void LLNearbyChat::loadHistory()
 		chat.mFromID = from_id;
 		chat.mText = msg[IM_TEXT].asString();
 		chat.mTimeStr = msg[IM_TIME].asString();
+		chat.mChatStyle = CHAT_STYLE_HISTORY;
 		addMessage(chat, true, do_not_log);
 
 		it++;
-- 
GitLab