From c24f638088f3d67ceebe82520787a4d344ebd72f Mon Sep 17 00:00:00 2001
From: maxim_productengine <mnikolenko@productengine.com>
Date: Thu, 23 Aug 2018 15:38:04 +0300
Subject: MAINT-8997 Add "Sort by recent arrival" to viewer People / Nearby map
 and list

---
 indra/newview/llpanelpeople.cpp                    | 51 ++++++++++++++++++++++
 indra/newview/llpanelpeople.h                      |  3 ++
 indra/newview/llrecentpeople.cpp                   | 30 +++++++++++++
 indra/newview/llrecentpeople.h                     |  5 +++
 .../default/xui/en/menu_people_nearby_view.xml     | 10 +++++
 5 files changed, 99 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 30fef9f5f0..1cbff37287 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -213,10 +213,39 @@ protected:
 	}
 };
 
+class LLAvatarItemRecentArrivalComparator : public  LLAvatarItemNameComparator
+{
+public:
+	LLAvatarItemRecentArrivalComparator() {};
+	virtual ~LLAvatarItemRecentArrivalComparator() {};
+
+protected:
+	virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
+	{
+
+		F32 arr_time1 = LLRecentPeople::instance().getArrivalTimeByID(item1->getAvatarId());
+		F32 arr_time2 = LLRecentPeople::instance().getArrivalTimeByID(item2->getAvatarId());
+
+		if (arr_time1 == arr_time2)
+		{
+			std::string name1 = item1->getAvatarName();
+			std::string name2 = item2->getAvatarName();
+
+			LLStringUtil::toUpper(name1);
+			LLStringUtil::toUpper(name2);
+
+			return name1 < name2;
+		}
+
+		return arr_time1 > arr_time2;
+	}
+};
+
 static const LLAvatarItemRecentComparator RECENT_COMPARATOR;
 static const LLAvatarItemStatusComparator STATUS_COMPARATOR;
 static LLAvatarItemDistanceComparator DISTANCE_COMPARATOR;
 static const LLAvatarItemRecentSpeakerComparator RECENT_SPEAKER_COMPARATOR;
+static LLAvatarItemRecentArrivalComparator RECENT_ARRIVAL_COMPARATOR;
 
 static LLPanelInjector<LLPanelPeople> t_people("panel_people");
 
@@ -539,6 +568,8 @@ LLPanelPeople::LLPanelPeople()
 	mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2));
 
 	mEnableCallbackRegistrar.add("People.Group.Plus.Validate",	boost::bind(&LLPanelPeople::onGroupPlusButtonValidate,	this));
+
+	doPeriodically(boost::bind(&LLPanelPeople::updateNearbyArrivalTime, this), 2.0);
 }
 
 LLPanelPeople::~LLPanelPeople()
@@ -1049,6 +1080,10 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save
 		list->setComparator(&DISTANCE_COMPARATOR);
 		list->sort();
 		break;
+	case E_SORT_BY_RECENT_ARRIVAL:
+		list->setComparator(&RECENT_ARRIVAL_COMPARATOR);
+		list->sort();
+		break;
 	default:
 		LL_WARNS() << "Unrecognized people sort order for " << list->getName() << LL_ENDL;
 		return;
@@ -1386,6 +1421,10 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
 	{
 		setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);
 	}
+	else if (chosen_item == "sort_arrival")
+	{
+		setSortOrder(mNearbyList, E_SORT_BY_RECENT_ARRIVAL);
+	}
 	else if (chosen_item == "view_usernames")
 	{
 	    bool hide_usernames = !gSavedSettings.getBOOL("NearbyListHideUsernames");
@@ -1407,6 +1446,8 @@ bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata)
 		return sort_order == E_SORT_BY_NAME;
 	if (item == "sort_distance")
 		return sort_order == E_SORT_BY_DISTANCE;
+	if (item == "sort_arrival")
+		return sort_order == E_SORT_BY_RECENT_ARRIVAL;
 
 	return false;
 }
@@ -1594,5 +1635,15 @@ bool LLPanelPeople::isAccordionCollapsedByUser(const std::string& name)
 	return isAccordionCollapsedByUser(getChild<LLUICtrl>(name));
 }
 
+bool LLPanelPeople::updateNearbyArrivalTime()
+{
+	std::vector<LLVector3d> positions;
+	std::vector<LLUUID> uuids;
+	static LLCachedControl<F32> range(gSavedSettings, "NearMeRange");
+	LLWorld::getInstance()->getAvatars(&uuids, &positions, gAgent.getPositionGlobal(), range);
+	LLRecentPeople::instance().updateAvatarsArrivalTime(uuids);
+	return LLApp::isExiting();
+}
+
 
 // EOF
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index eb7e76a772..c72c4fc08a 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -62,6 +62,8 @@ public:
 	// internals
 	class Updater;
 
+	bool updateNearbyArrivalTime();
+
 private:
 
 	typedef enum e_sort_oder {
@@ -70,6 +72,7 @@ private:
 		E_SORT_BY_MOST_RECENT = 2,
 		E_SORT_BY_DISTANCE = 3,
 		E_SORT_BY_RECENT_SPEAKERS = 4,
+		E_SORT_BY_RECENT_ARRIVAL = 5
 	} ESortOrder;
 
     void				    removePicker();
diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp
index 7689cd1a52..8bea9aad47 100644
--- a/indra/newview/llrecentpeople.cpp
+++ b/indra/newview/llrecentpeople.cpp
@@ -126,3 +126,33 @@ bool LLRecentPeople::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	add(event->getValue().asUUID());
 	return true;
 }
+
+void LLRecentPeople::updateAvatarsArrivalTime(uuid_vec_t& uuids)
+{
+	id_to_time_map_t buf = mAvatarsArrivalTime;
+	mAvatarsArrivalTime.clear();
+
+	for (uuid_vec_t::const_iterator id_it = uuids.begin(); id_it != uuids.end(); ++id_it)
+	{
+		if (buf.find(*id_it) != buf.end())
+		{
+			mAvatarsArrivalTime[*id_it] = buf[*id_it];
+		}
+		else
+		{
+			mAvatarsArrivalTime[*id_it] = LLDate::now().secondsSinceEpoch();
+		}
+	}
+}
+
+F32 LLRecentPeople::getArrivalTimeByID(const LLUUID& id)
+{
+	id_to_time_map_t::const_iterator it = mAvatarsArrivalTime.find(id);
+
+	if (it != mAvatarsArrivalTime.end())
+	{
+		return it->second;
+	}
+	return LLDate::now().secondsSinceEpoch();
+}
+
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index c7aaf604f5..1b4295ddad 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -53,6 +53,7 @@ class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LL
 	LLSINGLETON_EMPTY_CTOR(LLRecentPeople);
 	LOG_CLASS(LLRecentPeople);
 public:
+	typedef std::map <LLUUID, F32> id_to_time_map_t;
 	typedef boost::signals2::signal<void ()> signal_t;
 	
 	/**
@@ -116,6 +117,9 @@ public:
 	 */
 	/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
 
+	void updateAvatarsArrivalTime(uuid_vec_t& uuids);
+	F32 getArrivalTimeByID(const LLUUID& id);
+
 private:
 
 	const LLUUID& getIDByPhoneNumber(const LLSD& userdata);
@@ -123,6 +127,7 @@ private:
 	typedef std::map<LLUUID, LLSD> recent_people_t;
 	recent_people_t		mPeople;
 	signal_t			mChangedSignal;
+	id_to_time_map_t	mAvatarsArrivalTime;
 };
 
 #endif // LL_LLRECENTPEOPLE_H
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
index a9f6b8045d..0f7c6a2aa5 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
@@ -33,6 +33,16 @@
          function="People.Nearby.ViewSort.CheckItem"
          parameter="sort_distance"/>
     </menu_item_check>
+    <menu_item_check
+       label="Sort by Recent arrival"
+       name="sort_arrival">
+      <menu_item_check.on_click
+         function="People.Nearby.ViewSort.Action"
+         parameter="sort_arrival"/>
+      <menu_item_check.on_check
+         function="People.Nearby.ViewSort.CheckItem"
+         parameter="sort_arrival"/>
+  </menu_item_check>
     <menu_item_separator layout="topleft" />
     <menu_item_check name="view_icons" label="View People Icons">
         <menu_item_check.on_click
-- 
cgit v1.2.3