Added birthday reminder of multiple contacts to top bar in dialogs.

This commit is contained in:
23rd 2025-04-07 00:40:34 +03:00 committed by John Preston
parent f83568c6c9
commit 8c0de22c14
2 changed files with 106 additions and 25 deletions

View file

@ -3867,6 +3867,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_dialogs_suggestions_birthday_about" = "Let your contacts know when youre celebrating."; "lng_dialogs_suggestions_birthday_about" = "Let your contacts know when youre celebrating.";
"lng_dialogs_suggestions_birthday_contact_title" = "Its {text}'s **birthday** today! 🎂"; "lng_dialogs_suggestions_birthday_contact_title" = "Its {text}'s **birthday** today! 🎂";
"lng_dialogs_suggestions_birthday_contact_about" = "Send them a Gift."; "lng_dialogs_suggestions_birthday_contact_about" = "Send them a Gift.";
"lng_dialogs_suggestions_birthday_contacts_title#one" = "{count} contact have **birthdays** today! 🎂";
"lng_dialogs_suggestions_birthday_contacts_title#other" = "{count} contacts have **birthdays** today! 🎂";
"lng_dialogs_suggestions_birthday_contacts_about" = "Send them a Gift.";
"lng_dialogs_suggestions_premium_annual_title" = "Telegram Premium with a {text} discount"; "lng_dialogs_suggestions_premium_annual_title" = "Telegram Premium with a {text} discount";
"lng_dialogs_suggestions_premium_annual_about" = "Sign up for the annual payment plan for Telegram Premium now to get the discount."; "lng_dialogs_suggestions_premium_annual_about" = "Sign up for the annual payment plan for Telegram Premium now to get the discount.";
"lng_dialogs_suggestions_premium_upgrade_title" = "Telegram Premium with a {text} discount"; "lng_dialogs_suggestions_premium_upgrade_title" = "Telegram Premium with a {text} discount";

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "dialogs/ui/dialogs_top_bar_suggestion_content.h" #include "dialogs/ui/dialogs_top_bar_suggestion_content.h"
#include "history/view/history_view_group_call_bar.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_app_config.h" #include "main/main_app_config.h"
@ -31,6 +32,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
namespace Dialogs { namespace Dialogs {
@ -88,7 +91,9 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
rpl::lifetime birthdayLifetime; rpl::lifetime birthdayLifetime;
rpl::lifetime premiumLifetime; rpl::lifetime premiumLifetime;
rpl::lifetime userpicLifetime; rpl::lifetime userpicLifetime;
rpl::lifetime giftsLifetime;
}; };
const auto state = lifetime.make_state<State>(); const auto state = lifetime.make_state<State>();
const auto ensureWrap = [=] { const auto ensureWrap = [=] {
if (!state->content) { if (!state->content) {
@ -129,42 +134,115 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
return; return;
} }
const auto controller = FindSessionController(parent); const auto controller = FindSessionController(parent);
if (!controller) { if (!controller || users.empty()) {
dismiss(); dismiss();
return; return;
} }
if (users.size() != 1) { const auto isSingle = users.size() == 1;
return;
}
content->setRightIcon(RightIcon::Close); content->setRightIcon(RightIcon::Close);
content->setClickedCallback([=] { content->setClickedCallback([=] {
Ui::ShowStarGiftBox(controller, users.front()); if (isSingle) {
Ui::ShowStarGiftBox(controller, users.front());
} else {
Ui::ChooseStarGiftRecipient(controller);
}
}); });
content->setHideCallback(dismiss); content->setHideCallback(dismiss);
content->setContent( auto title = isSingle
tr::lng_dialogs_suggestions_birthday_contact_title( ? tr::lng_dialogs_suggestions_birthday_contact_title(
tr::now, tr::now,
lt_text, lt_text,
{ users.front()->name() }, { users.front()->name() },
Ui::Text::RichLangValue), Ui::Text::RichLangValue)
tr::lng_dialogs_suggestions_birthday_contact_about( : tr::lng_dialogs_suggestions_birthday_contacts_title(
tr::now, tr::now,
TextWithEntities::Simple)); lt_count,
const auto upload = Ui::CreateChild<Ui::UserpicButton>( users.size(),
content, Ui::Text::RichLangValue);
users.front(), auto text = isSingle
st::uploadUserpicButton); ? tr::lng_dialogs_suggestions_birthday_contact_about(
upload->setAttribute(Qt::WA_TransparentForMouseEvents); tr::now,
const auto leftPadding = st::defaultDialogRow.padding.left(); TextWithEntities::Simple)
content->sizeValue() | rpl::filter_size( : tr::lng_dialogs_suggestions_birthday_contacts_about(
) | rpl::start_with_next([=](const QSize &s) { tr::now,
upload->raise(); TextWithEntities::Simple);
upload->show(); content->setContent(std::move(title), std::move(text));
upload->moveToLeft( const auto leftPadding
leftPadding, = st::defaultDialogRow.padding.left();
(s.height() - upload->height()) / 2); state->giftsLifetime.destroy();
}, content->lifetime()); if (!isSingle) {
content->setLeftPadding(upload->width() + leftPadding); struct UserViews {
std::vector<HistoryView::UserpicInRow> inRow;
QImage userpics;
base::unique_qptr<Ui::RpWidget> widget;
};
const auto s
= state->giftsLifetime.template make_state<
UserViews>();
s->widget = base::make_unique_q<Ui::RpWidget>(
content);
const auto widget = s->widget.get();
content->sizeValue() | rpl::filter_size(
) | rpl::start_with_next([=](const QSize &size) {
widget->resize(size);
widget->show();
widget->raise();
}, widget->lifetime());
for (const auto &user : users) {
s->inRow.push_back({ .peer = user });
}
widget->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(widget);
const auto regenerate = [&] {
if (s->userpics.isNull()) {
return true;
}
for (auto &entry : s->inRow) {
if (entry.uniqueKey
!= entry.peer->userpicUniqueKey(
entry.view)) {
return true;
}
}
return false;
}();
if (regenerate) {
const auto &st = st::historyCommentsUserpics;
HistoryView::GenerateUserpicsInRow(
s->userpics,
s->inRow,
st,
3);
content->setLeftPadding(leftPadding
+ (users.size() * st.size - st.shift));
}
p.drawImage(
leftPadding,
(widget->height()
- (s->userpics.height()
/ style::DevicePixelRatio())) / 2,
s->userpics);
}, widget->lifetime());
} else {
using Ptr = base::unique_qptr<Ui::UserpicButton>;
const auto ptr
= state->giftsLifetime.template make_state<Ptr>(
base::make_unique_q<Ui::UserpicButton>(
content,
users.front(),
st::uploadUserpicButton));
const auto fake = ptr->get();
fake->setAttribute(Qt::WA_TransparentForMouseEvents);
content->sizeValue() | rpl::filter_size(
) | rpl::start_with_next([=](const QSize &s) {
fake->raise();
fake->show();
fake->moveToLeft(
leftPadding,
(s.height() - fake->height()) / 2);
}, content->lifetime());
content->setLeftPadding(fake->width() + leftPadding);
}
wrap->toggle(true, anim::type::normal); wrap->toggle(true, anim::type::normal);
})); }));