mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Added birthday sublist to contact list in gift box.
This commit is contained in:
parent
81da453ec4
commit
6008d9e12b
2 changed files with 190 additions and 42 deletions
|
@ -3455,6 +3455,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_gift_show_on_channel" = "Display in channel's Gifts";
|
"lng_gift_show_on_channel" = "Display in channel's Gifts";
|
||||||
"lng_gift_availability" = "Availability";
|
"lng_gift_availability" = "Availability";
|
||||||
"lng_gift_from_hidden" = "Hidden User";
|
"lng_gift_from_hidden" = "Hidden User";
|
||||||
|
"lng_gift_subtitle_birthdays" = "Birthdays";
|
||||||
|
"lng_gift_list_birthday_status_today" = "{emoji} Birthday today";
|
||||||
|
"lng_gift_list_birthday_status_yesterday" = "Birthday yesterday";
|
||||||
"lng_gift_self_status" = "buy yourself a gift";
|
"lng_gift_self_status" = "buy yourself a gift";
|
||||||
"lng_gift_self_title" = "Buy a Gift";
|
"lng_gift_self_title" = "Buy a Gift";
|
||||||
"lng_gift_self_about" = "Buy yourself a gift to display on your page or reserve for later.\n\nLimited-edition gifts upgraded to collectibles can be gifted to others later.";
|
"lng_gift_self_about" = "Buy yourself a gift to display on your page or reserve for later.\n\nLimited-edition gifts upgraded to collectibles can be gifted to others later.";
|
||||||
|
|
|
@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "chat_helpers/tabbed_panel.h"
|
#include "chat_helpers/tabbed_panel.h"
|
||||||
#include "chat_helpers/tabbed_selector.h"
|
#include "chat_helpers/tabbed_selector.h"
|
||||||
#include "core/ui_integration.h"
|
#include "core/ui_integration.h"
|
||||||
|
#include "data/data_birthday.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_credits.h"
|
#include "data/data_credits.h"
|
||||||
|
@ -2257,10 +2258,11 @@ void GiftBox(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SelfOption {
|
struct CustomList {
|
||||||
object_ptr<Ui::RpWidget> content = { nullptr };
|
object_ptr<Ui::RpWidget> content = { nullptr };
|
||||||
Fn<bool(int, int, int)> overrideKey;
|
Fn<bool(int, int, int)> overrideKey;
|
||||||
Fn<void()> activate;
|
Fn<void()> activate;
|
||||||
|
Fn<bool()> hasSelection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Controller final : public ContactsBoxController {
|
class Controller final : public ContactsBoxController {
|
||||||
|
@ -2284,32 +2286,39 @@ private:
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
const Fn<void(not_null<PeerData*>)> _choose;
|
const Fn<void(not_null<PeerData*>)> _choose;
|
||||||
SelfOption _selfOption;
|
const std::vector<UserId> _contactBirthdays;
|
||||||
|
CustomList _selfOption;
|
||||||
|
CustomList _birthdayOptions;
|
||||||
|
|
||||||
|
bool _skipUpDirectionSelect = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] SelfOption MakeSelfOption(
|
[[nodiscard]] CustomList MakeCustomList(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
Fn<void()> activate) {
|
Fn<void(not_null<PeerListController*>)> fill,
|
||||||
|
Fn<void(not_null<PeerData*>)> activate,
|
||||||
|
rpl::producer<QString> below) {
|
||||||
class SelfController final : public PeerListController {
|
class SelfController final : public PeerListController {
|
||||||
public:
|
public:
|
||||||
SelfController(
|
SelfController(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
Fn<void()> activate)
|
Fn<void(not_null<PeerListController*>)> fill,
|
||||||
|
Fn<void(not_null<PeerData*>)> activate)
|
||||||
: _session(session)
|
: _session(session)
|
||||||
, _activate(std::move(activate)) {
|
, _activate(std::move(activate))
|
||||||
|
, _fill(std::move(fill)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare() override {
|
void prepare() override {
|
||||||
auto row = std::make_unique<PeerListRow>(_session->user());
|
if (_fill) {
|
||||||
row->setCustomStatus(tr::lng_gift_self_status(tr::now));
|
_fill(this);
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
}
|
||||||
delegate()->peerListRefreshRows();
|
|
||||||
}
|
}
|
||||||
void loadMoreRows() override {
|
void loadMoreRows() override {
|
||||||
}
|
}
|
||||||
void rowClicked(not_null<PeerListRow*> row) override {
|
void rowClicked(not_null<PeerListRow*> row) override {
|
||||||
_activate();
|
_activate(row->peer());
|
||||||
}
|
}
|
||||||
Main::Session &session() const override {
|
Main::Session &session() const override {
|
||||||
return *_session;
|
return *_session;
|
||||||
|
@ -2317,7 +2326,8 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
Fn<void()> _activate;
|
Fn<void(not_null<PeerData*>)> _activate;
|
||||||
|
Fn<void(not_null<PeerListController*>)> _fill;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2329,9 +2339,12 @@ private:
|
||||||
const auto delegate = container->lifetime().make_state<
|
const auto delegate = container->lifetime().make_state<
|
||||||
PeerListContentDelegateSimple
|
PeerListContentDelegateSimple
|
||||||
>();
|
>();
|
||||||
const auto controller = container->lifetime().make_state<
|
const auto controller
|
||||||
SelfController
|
= container->lifetime().make_state<SelfController>(
|
||||||
>(session, activate);
|
session,
|
||||||
|
fill,
|
||||||
|
activate);
|
||||||
|
|
||||||
controller->setStyleOverrides(&st::peerListSingleRow);
|
controller->setStyleOverrides(&st::peerListSingleRow);
|
||||||
const auto content = container->add(object_ptr<PeerListContent>(
|
const auto content = container->add(object_ptr<PeerListContent>(
|
||||||
container,
|
container,
|
||||||
|
@ -2339,10 +2352,12 @@ private:
|
||||||
delegate->setContent(content);
|
delegate->setContent(content);
|
||||||
controller->setDelegate(delegate);
|
controller->setDelegate(delegate);
|
||||||
|
|
||||||
Ui::AddSkip(container);
|
if (below) {
|
||||||
container->add(CreatePeerListSectionSubtitle(
|
Ui::AddSkip(container);
|
||||||
container,
|
container->add(CreatePeerListSectionSubtitle(
|
||||||
tr::lng_contacts_header()));
|
container,
|
||||||
|
std::move(below)));
|
||||||
|
}
|
||||||
|
|
||||||
const auto overrideKey = [=](int direction, int from, int to) {
|
const auto overrideKey = [=](int direction, int from, int to) {
|
||||||
if (!content->isVisible()) {
|
if (!content->isVisible()) {
|
||||||
|
@ -2368,11 +2383,19 @@ private:
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
const auto hasSelection = [=] {
|
||||||
|
return content->isVisible() && content->hasSelection();
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
.content = std::move(result),
|
.content = std::move(result),
|
||||||
.overrideKey = overrideKey,
|
.overrideKey = overrideKey,
|
||||||
.activate = activate,
|
.activate = [=] {
|
||||||
|
if (content->hasSelection()) {
|
||||||
|
activate(content->rowAt(content->selectedIndex())->peer());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.hasSelection = hasSelection,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2381,7 +2404,73 @@ Controller::Controller(
|
||||||
Fn<void(not_null<PeerData*>)> choose)
|
Fn<void(not_null<PeerData*>)> choose)
|
||||||
: ContactsBoxController(session)
|
: ContactsBoxController(session)
|
||||||
, _choose(std::move(choose))
|
, _choose(std::move(choose))
|
||||||
, _selfOption(MakeSelfOption(session, [=] { _choose(session->user()); })) {
|
, _contactBirthdays(
|
||||||
|
session->data().knownContactBirthdays().value_or(std::vector<UserId>{}))
|
||||||
|
, _selfOption(
|
||||||
|
MakeCustomList(
|
||||||
|
session,
|
||||||
|
[=](not_null<PeerListController*> controller) {
|
||||||
|
auto row = std::make_unique<PeerListRow>(session->user());
|
||||||
|
row->setCustomStatus(tr::lng_gift_self_status(tr::now));
|
||||||
|
controller->delegate()->peerListAppendRow(std::move(row));
|
||||||
|
controller->delegate()->peerListRefreshRows();
|
||||||
|
},
|
||||||
|
[=](not_null<PeerData*> peer) { _choose(peer); },
|
||||||
|
_contactBirthdays.empty()
|
||||||
|
? tr::lng_contacts_header()
|
||||||
|
: tr::lng_gift_subtitle_birthdays()))
|
||||||
|
, _birthdayOptions(
|
||||||
|
MakeCustomList(
|
||||||
|
session,
|
||||||
|
[=](not_null<PeerListController*> controller) {
|
||||||
|
const auto status = [=](const Data::Birthday &date) {
|
||||||
|
if (Data::IsBirthdayToday(date)) {
|
||||||
|
return tr::lng_gift_list_birthday_status_today(
|
||||||
|
tr::now,
|
||||||
|
lt_emoji,
|
||||||
|
Data::BirthdayCake());
|
||||||
|
}
|
||||||
|
const auto yesterday = QDate::currentDate().addDays(-1);
|
||||||
|
return (date.day() == yesterday.day()
|
||||||
|
&& date.month() == yesterday.month())
|
||||||
|
? tr::lng_gift_list_birthday_status_yesterday(tr::now)
|
||||||
|
: QString();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto usersWithBirthdays = ranges::views::all(
|
||||||
|
_contactBirthdays
|
||||||
|
) | ranges::views::transform([&](UserId userId) {
|
||||||
|
return session->data().user(userId);
|
||||||
|
}) | ranges::to_vector;
|
||||||
|
|
||||||
|
ranges::sort(usersWithBirthdays, [](UserData *a, UserData *b) {
|
||||||
|
const auto aBirthday = a->birthday();
|
||||||
|
const auto bBirthday = b->birthday();
|
||||||
|
const auto aIsToday = Data::IsBirthdayToday(aBirthday);
|
||||||
|
const auto bIsToday = Data::IsBirthdayToday(bBirthday);
|
||||||
|
if (aIsToday != bIsToday) {
|
||||||
|
return aIsToday > bIsToday;
|
||||||
|
}
|
||||||
|
if (aBirthday.month() != bBirthday.month()) {
|
||||||
|
return aBirthday.month() < bBirthday.month();
|
||||||
|
}
|
||||||
|
return aBirthday.day() < bBirthday.day();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto user : usersWithBirthdays) {
|
||||||
|
auto row = std::make_unique<PeerListRow>(user);
|
||||||
|
if (auto s = status(user->birthday()); !s.isEmpty()) {
|
||||||
|
row->setCustomStatus(std::move(s));
|
||||||
|
}
|
||||||
|
controller->delegate()->peerListAppendRow(std::move(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->delegate()->peerListRefreshRows();
|
||||||
|
},
|
||||||
|
[=](not_null<PeerData*> peer) { _choose(peer); },
|
||||||
|
_contactBirthdays.empty()
|
||||||
|
? rpl::producer<QString>(nullptr)
|
||||||
|
: tr::lng_contacts_header())) {
|
||||||
setStyleOverrides(&st::peerListSmallSkips);
|
setStyleOverrides(&st::peerListSmallSkips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2389,18 +2478,65 @@ void Controller::noSearchSubmit() {
|
||||||
if (const auto onstack = _selfOption.activate) {
|
if (const auto onstack = _selfOption.activate) {
|
||||||
onstack();
|
onstack();
|
||||||
}
|
}
|
||||||
|
if (const auto onstack = _birthdayOptions.activate) {
|
||||||
|
onstack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::overrideKeyboardNavigation(
|
bool Controller::overrideKeyboardNavigation(
|
||||||
int direction,
|
int direction,
|
||||||
int fromIndex,
|
int from,
|
||||||
int toIndex) {
|
int to) {
|
||||||
return _selfOption.overrideKey
|
if (direction == -1 && from == -1 && to == -1 && _skipUpDirectionSelect) {
|
||||||
&& _selfOption.overrideKey(direction, fromIndex, toIndex);
|
return true;
|
||||||
|
}
|
||||||
|
_skipUpDirectionSelect = false;
|
||||||
|
if (direction > 0) {
|
||||||
|
if (!_selfOption.hasSelection() && !_birthdayOptions.hasSelection()) {
|
||||||
|
return _selfOption.overrideKey(direction, from, to);
|
||||||
|
}
|
||||||
|
if (_selfOption.hasSelection() && !_birthdayOptions.hasSelection()) {
|
||||||
|
if (_selfOption.overrideKey(direction, from, to)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return _birthdayOptions.overrideKey(direction, from, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_selfOption.hasSelection() && _birthdayOptions.hasSelection()) {
|
||||||
|
if (_birthdayOptions.overrideKey(direction, from, to)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (direction < 0) {
|
||||||
|
if (!_selfOption.hasSelection() && !_birthdayOptions.hasSelection()) {
|
||||||
|
return _birthdayOptions.overrideKey(direction, from, to);
|
||||||
|
}
|
||||||
|
if (!_selfOption.hasSelection() && _birthdayOptions.hasSelection()) {
|
||||||
|
if (_birthdayOptions.overrideKey(direction, from, to)) {
|
||||||
|
return true;
|
||||||
|
} else if (!_birthdayOptions.hasSelection()) {
|
||||||
|
const auto res = _selfOption.overrideKey(direction, from, to);
|
||||||
|
_skipUpDirectionSelect = _selfOption.hasSelection();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_selfOption.hasSelection() && !_birthdayOptions.hasSelection()) {
|
||||||
|
if (_selfOption.overrideKey(direction, from, to)) {
|
||||||
|
_skipUpDirectionSelect = _selfOption.hasSelection();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> Controller::createRow(
|
std::unique_ptr<PeerListRow> Controller::createRow(
|
||||||
not_null<UserData*> user) {
|
not_null<UserData*> user) {
|
||||||
|
if (const auto birthday = user->owner().knownContactBirthdays()) {
|
||||||
|
if (ranges::contains(*birthday, peerToUser(user->id))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (user->isSelf()
|
if (user->isSelf()
|
||||||
|| user->isBot()
|
|| user->isBot()
|
||||||
|| user->isServiceUser()
|
|| user->isServiceUser()
|
||||||
|
@ -2411,7 +2547,10 @@ std::unique_ptr<PeerListRow> Controller::createRow(
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::prepareViewHook() {
|
void Controller::prepareViewHook() {
|
||||||
delegate()->peerListSetAboveWidget(std::move(_selfOption.content));
|
auto list = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
||||||
|
list->add(std::move(_selfOption.content));
|
||||||
|
list->add(std::move(_birthdayOptions.content));
|
||||||
|
delegate()->peerListSetAboveWidget(std::move(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
@ -2422,23 +2561,29 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
|
||||||
void ChooseStarGiftRecipient(
|
void ChooseStarGiftRecipient(
|
||||||
not_null<Window::SessionController*> window) {
|
not_null<Window::SessionController*> window) {
|
||||||
auto controller = std::make_unique<Controller>(
|
const auto session = &window->session();
|
||||||
&window->session(),
|
const auto lifetime = std::make_shared<rpl::lifetime>();
|
||||||
[=](not_null<PeerData*> peer) {
|
session->data().contactBirthdays(
|
||||||
ShowStarGiftBox(window, peer);
|
) | rpl::start_with_next(crl::guard(session, [=] {
|
||||||
});
|
lifetime->destroy();
|
||||||
const auto controllerRaw = controller.get();
|
auto controller = std::make_unique<Controller>(
|
||||||
auto initBox = [=](not_null<PeerListBox*> box) {
|
session,
|
||||||
box->setTitle(tr::lng_gift_premium_or_stars());
|
[=](not_null<PeerData*> peer) {
|
||||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
ShowStarGiftBox(window, peer);
|
||||||
|
});
|
||||||
|
const auto controllerRaw = controller.get();
|
||||||
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
|
box->setTitle(tr::lng_gift_premium_or_stars());
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
|
||||||
box->noSearchSubmits() | rpl::start_with_next([=] {
|
box->noSearchSubmits() | rpl::start_with_next([=] {
|
||||||
controllerRaw->noSearchSubmit();
|
controllerRaw->noSearchSubmit();
|
||||||
}, box->lifetime());
|
}, box->lifetime());
|
||||||
};
|
};
|
||||||
window->show(
|
window->show(
|
||||||
Box<PeerListBox>(std::move(controller), std::move(initBox)),
|
Box<PeerListBox>(std::move(controller), std::move(initBox)),
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
|
}), *lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowStarGiftBox(
|
void ShowStarGiftBox(
|
||||||
|
|
Loading…
Add table
Reference in a new issue