Sort contacts by last seen by default.

Fixes #5515.
This commit is contained in:
John Preston 2021-12-22 15:14:16 +00:00
parent a7e552ccab
commit 0f15adb208
12 changed files with 116 additions and 8 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,014 B

View file

@ -160,6 +160,21 @@ contactsAboutFg: windowSubTextFgOver;
contactsAboutTop: 60px;
contactsAboutBottom: 19px;
contactsSortButton: IconButton(defaultIconButton) {
width: 48px;
height: 54px;
icon: icon{{ "contacts_alphabet", boxTitleCloseFg }};
iconOver: icon{{ "contacts_alphabet", boxTitleCloseFgOver }};
iconPosition: point(10px, -1px);
rippleAreaPosition: point(1px, 6px);
rippleAreaSize: 42px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
}
contactsSortOnlineIcon: icon{{ "contacts_online", boxTitleCloseFg }};
contactsSortOnlineIconOver: icon{{ "contacts_online", boxTitleCloseFgOver }};
contactsMarginTop: 4px;
contactsMarginBottom: 4px;
membersMarginTop: 10px;

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_folder.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "mainwindow.h"
@ -26,12 +27,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "dialogs/dialogs_main_list.h"
#include "window/window_session_controller.h" // showAddContact()
#include "base/unixtime.h"
#include "facades.h"
#include "styles/style_boxes.h"
#include "styles/style_profile.h"
namespace {
constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000);
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().history(chat);
auto &histories = history->owner().histories();
@ -110,17 +114,31 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
object_ptr<Ui::BoxContent> PrepareContactsBox(
not_null<Window::SessionController*> sessionController) {
const auto controller = sessionController;
auto delegate = [=](not_null<PeerListBox*> box) {
using Mode = ContactsBoxController::SortMode;
auto controller = std::make_unique<ContactsBoxController>(
&sessionController->session());
const auto raw = controller.get();
auto init = [=](not_null<PeerListBox*> box) {
struct State {
QPointer<Ui::IconButton> toggleSort;
Mode mode = ContactsBoxController::SortMode::Online;
};
const auto state = box->lifetime().make_state<State>();
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
box->addLeftButton(
tr::lng_profile_add_contact(),
[=] { controller->showAddContact(); });
[=] { sessionController->showAddContact(); });
state->toggleSort = box->addTopButton(st::contactsSortButton, [=] {
const auto online = (state->mode == Mode::Online);
state->mode = online ? Mode::Alphabet : Mode::Online;
raw->setSortMode(state->mode);
state->toggleSort->setIconOverride(
online ? &st::contactsSortOnlineIcon : nullptr,
online ? &st::contactsSortOnlineIconOver : nullptr);
});
raw->setSortMode(Mode::Online);
};
return Box<PeerListBox>(
std::make_unique<ContactsBoxController>(
&sessionController->session()),
std::move(delegate));
return Box<PeerListBox>(std::move(controller), std::move(init));
}
void PeerListRowWithLink::setActionLink(const QString &action) {
@ -368,7 +386,8 @@ ContactsBoxController::ContactsBoxController(
not_null<Main::Session*> session,
std::unique_ptr<PeerListSearchController> searchController)
: PeerListController(std::move(searchController))
, _session(session) {
, _session(session)
, _sortByOnlineTimer([=] { sort(); }) {
}
Main::Session &ContactsBoxController::session() const {
@ -404,6 +423,7 @@ void ContactsBoxController::rebuildRows() {
};
appendList(session().data().contactsList());
checkForEmptyRows();
sort();
delegate()->peerListRefreshRows();
}
@ -427,6 +447,66 @@ void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
Ui::showPeerHistory(row->peer(), ShowAtUnreadMsgId);
}
void ContactsBoxController::setSortMode(SortMode mode) {
if (_sortMode == mode) {
return;
}
_sortMode = mode;
sort();
if (_sortMode == SortMode::Online) {
session().changes().peerUpdates(
Data::PeerUpdate::Flag::OnlineStatus
) | rpl::filter([=](const Data::PeerUpdate &update) {
return !_sortByOnlineTimer.isActive()
&& delegate()->peerListFindRow(update.peer->id.value);
}) | rpl::start_with_next([=] {
_sortByOnlineTimer.callOnce(kSortByOnlineThrottle);
}, _sortByOnlineLifetime);
} else {
_sortByOnlineTimer.cancel();
_sortByOnlineLifetime.destroy();
}
}
void ContactsBoxController::sort() {
switch (_sortMode) {
case SortMode::Alphabet: sortByName(); break;
case SortMode::Online: sortByOnline(); break;
default: Unexpected("SortMode in ContactsBoxController.");
}
}
void ContactsBoxController::sortByName() {
auto keys = base::flat_map<PeerListRowId, QString>();
keys.reserve(delegate()->peerListFullRowsCount());
const auto key = [&](const PeerListRow &row) {
const auto id = row.id();
const auto i = keys.find(id);
if (i != end(keys)) {
return i->second;
}
const auto peer = row.peer();
const auto history = peer->owner().history(peer);
return keys.emplace(id, history->chatListNameSortKey()).first->second;
};
const auto predicate = [&](const PeerListRow &a, const PeerListRow &b) {
return (key(a).compare(key(b)) < 0);
};
delegate()->peerListSortRows(predicate);
}
void ContactsBoxController::sortByOnline() {
const auto now = base::unixtime::now();
const auto key = [&](const PeerListRow &row) {
const auto user = row.peer()->asUser();
return user ? (std::min(user->onlineTill, now) + 1) : TimeId();
};
const auto predicate = [&](const PeerListRow &a, const PeerListRow &b) {
return key(a) > key(b);
};
delegate()->peerListSortRows(predicate);
}
bool ContactsBoxController::appendRow(not_null<UserData*> user) {
if (auto row = delegate()->peerListFindRow(user->id.value)) {
updateRowHook(row);

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_box.h"
#include "base/flat_set.h"
#include "base/weak_ptr.h"
#include "base/timer.h"
// Not used for now.
//
@ -136,6 +137,12 @@ public:
not_null<PeerData*> peer) override final;
void rowClicked(not_null<PeerListRow*> row) override;
enum class SortMode {
Alphabet,
Online,
};
void setSortMode(SortMode mode);
protected:
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
virtual void prepareViewHook() {
@ -144,11 +151,17 @@ protected:
}
private:
void sort();
void sortByName();
void sortByOnline();
void rebuildRows();
void checkForEmptyRows();
bool appendRow(not_null<UserData*> user);
const not_null<Main::Session*> _session;
SortMode _sortMode = SortMode::Alphabet;
base::Timer _sortByOnlineTimer;
rpl::lifetime _sortByOnlineLifetime;
};