diff --git a/Telegram/Resources/icons/contacts_add.png b/Telegram/Resources/icons/contacts_add.png deleted file mode 100644 index 3f3efebd0..000000000 Binary files a/Telegram/Resources/icons/contacts_add.png and /dev/null differ diff --git a/Telegram/Resources/icons/contacts_add@2x.png b/Telegram/Resources/icons/contacts_add@2x.png deleted file mode 100644 index 0b68e8665..000000000 Binary files a/Telegram/Resources/icons/contacts_add@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/contacts_add@3x.png b/Telegram/Resources/icons/contacts_add@3x.png deleted file mode 100644 index 8d20e2d44..000000000 Binary files a/Telegram/Resources/icons/contacts_add@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/contacts_alphabet.png b/Telegram/Resources/icons/contacts_alphabet.png new file mode 100644 index 000000000..8a8c99aa1 Binary files /dev/null and b/Telegram/Resources/icons/contacts_alphabet.png differ diff --git a/Telegram/Resources/icons/contacts_alphabet@2x.png b/Telegram/Resources/icons/contacts_alphabet@2x.png new file mode 100644 index 000000000..59b724d9b Binary files /dev/null and b/Telegram/Resources/icons/contacts_alphabet@2x.png differ diff --git a/Telegram/Resources/icons/contacts_alphabet@3x.png b/Telegram/Resources/icons/contacts_alphabet@3x.png new file mode 100644 index 000000000..72a22f9f5 Binary files /dev/null and b/Telegram/Resources/icons/contacts_alphabet@3x.png differ diff --git a/Telegram/Resources/icons/contacts_online.png b/Telegram/Resources/icons/contacts_online.png new file mode 100644 index 000000000..8fe7e9b16 Binary files /dev/null and b/Telegram/Resources/icons/contacts_online.png differ diff --git a/Telegram/Resources/icons/contacts_online@2x.png b/Telegram/Resources/icons/contacts_online@2x.png new file mode 100644 index 000000000..3549bc947 Binary files /dev/null and b/Telegram/Resources/icons/contacts_online@2x.png differ diff --git a/Telegram/Resources/icons/contacts_online@3x.png b/Telegram/Resources/icons/contacts_online@3x.png new file mode 100644 index 000000000..5cf60407b Binary files /dev/null and b/Telegram/Resources/icons/contacts_online@3x.png differ diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 55c010523..a38dcdae0 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -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; diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 2a189f214..6dbc9c95e 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -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 bot, not_null chat) { const auto history = chat->owner().history(chat); auto &histories = history->owner().histories(); @@ -110,17 +114,31 @@ void AddBotToGroup(not_null bot, not_null chat) { object_ptr PrepareContactsBox( not_null sessionController) { - const auto controller = sessionController; - auto delegate = [=](not_null box) { + using Mode = ContactsBoxController::SortMode; + auto controller = std::make_unique( + &sessionController->session()); + const auto raw = controller.get(); + auto init = [=](not_null box) { + struct State { + QPointer toggleSort; + Mode mode = ContactsBoxController::SortMode::Online; + }; + const auto state = box->lifetime().make_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( - std::make_unique( - &sessionController->session()), - std::move(delegate)); + return Box(std::move(controller), std::move(init)); } void PeerListRowWithLink::setActionLink(const QString &action) { @@ -368,7 +386,8 @@ ContactsBoxController::ContactsBoxController( not_null session, std::unique_ptr 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 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(); + 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 user) { if (auto row = delegate()->peerListFindRow(user->id.value)) { updateRowHook(row); diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h index 6250e4236..a9599d8f9 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.h +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h @@ -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 peer) override final; void rowClicked(not_null row) override; + enum class SortMode { + Alphabet, + Online, + }; + void setSortMode(SortMode mode); + protected: virtual std::unique_ptr createRow(not_null user); virtual void prepareViewHook() { @@ -144,11 +151,17 @@ protected: } private: + void sort(); + void sortByName(); + void sortByOnline(); void rebuildRows(); void checkForEmptyRows(); bool appendRow(not_null user); const not_null _session; + SortMode _sortMode = SortMode::Alphabet; + base::Timer _sortByOnlineTimer; + rpl::lifetime _sortByOnlineLifetime; };