Added userpic suggestion to top bar in dialogs.

This commit is contained in:
23rd 2025-04-06 00:47:57 +03:00 committed by John Preston
parent 2c3cb3f5ce
commit 10d472728c
5 changed files with 104 additions and 12 deletions

View file

@ -3871,6 +3871,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_dialogs_suggestions_premium_upgrade_about" = "Upgrade to the annual payment plan for Telegram Premium now to get the discount.";
"lng_dialogs_suggestions_premium_restore_title" = "Get Premium back with up to {text} off";
"lng_dialogs_suggestions_premium_restore_about" = "Your Telegram Premium has recently expired. Tap here to extend it.";
"lng_dialogs_suggestions_userpics_title" = "Add your photo! 📸";
"lng_dialogs_suggestions_userpics_about" = "Help your friends spot you easily.";
"lng_about_random" = "Send a {emoji} emoji to any chat to try your luck.";
"lng_about_random_send" = "Send";

View file

@ -1129,3 +1129,10 @@ foldersMenu: PopupMenu(popupMenuWithIcons) {
itemPadding: margins(54px, 8px, 44px, 8px);
}
}
fakeUserpicButton: UserpicButton(defaultUserpicButton) {
size: size(1px, 1px);
photoSize: 1px;
changeIcon: icon {{ "settings/photo", transparent }};
uploadBg: transparent;
}

View file

@ -7,12 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "dialogs/dialogs_top_bar_suggestion.h"
#include "api/api_peer_photo.h"
#include "api/api_premium.h"
#include "apiwrap.h"
#include "base/call_delayed.h"
#include "core/application.h"
#include "core/click_handler_types.h"
#include "data/data_birthday.h"
#include "data/data_changes.h"
#include "data/data_user.h"
#include "dialogs/ui/dialogs_top_bar_suggestion_content.h"
#include "info/profile/info_profile_values.h"
@ -20,10 +22,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "settings/settings_premium.h"
#include "ui/controls/userpic_button.h"
#include "ui/text/text_utilities.h"
#include "ui/ui_utility.h"
#include "ui/wrap/slide_wrap.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h"
#include "styles/style_boxes.h"
#include "styles/style_dialogs.h"
namespace Dialogs {
namespace {
@ -38,6 +44,7 @@ constexpr auto kSugSetBirthday = "BIRTHDAY_SETUP"_cs;
constexpr auto kSugPremiumAnnual = "PREMIUM_ANNUAL"_cs;
constexpr auto kSugPremiumUpgrade = "PREMIUM_UPGRADE"_cs;
constexpr auto kSugPremiumRestore = "PREMIUM_RESTORE"_cs;
constexpr auto kSugSetUserpic = "USERPIC_SETUP"_cs;
} // namespace
@ -52,6 +59,7 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
Ui::SlideWrap<Ui::RpWidget> *wrap = nullptr;
rpl::lifetime birthdayLifetime;
rpl::lifetime premiumLifetime;
rpl::lifetime userpicLifetime;
};
const auto state = lifetime.make_state<State>();
const auto ensureWrap = [=] {
@ -79,7 +87,6 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
const auto wrap = state->wrap;
using RightIcon = TopBarSuggestionContent::RightIcon;
const auto config = &session->appConfig();
auto hide = false;
if (config->suggestionCurrent(kSugSetBirthday.utf8())
&& !Data::IsBirthdayToday(session->user()->birthday())) {
content->setRightIcon(RightIcon::Close);
@ -116,6 +123,7 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
tr::now,
TextWithEntities::Simple));
wrap->toggle(true, anim::type::normal);
return;
} else if (session->premiumPossible() && !session->premium()) {
const auto isPremiumAnnual = config->suggestionCurrent(
kSugPremiumAnnual.utf8());
@ -171,20 +179,86 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
}
}, state->premiumLifetime);
api->reload();
} else {
hide = true;
return;
}
} else {
hide = true;
}
if (hide) {
if (config->suggestionCurrent(kSugSetUserpic.utf8())
&& !session->user()->userpicPhotoId()) {
const auto controller = FindSessionController(parent);
if (!controller) {
return;
}
content->setRightIcon(RightIcon::Close);
const auto upload = Ui::CreateChild<Ui::UserpicButton>(
content,
&controller->window(),
Ui::UserpicButton::Role::ChoosePhoto,
st::uploadUserpicButton);
const auto leftPadding = st::defaultDialogRow.padding.left();
content->sizeValue() | rpl::filter_size(
) | rpl::start_with_next([=](const QSize &s) {
upload->raise();
upload->show();
upload->moveToLeft(
leftPadding,
(s.height() - upload->height()) / 2);
}, content->lifetime());
content->setLeftPadding(upload->width() + leftPadding);
upload->chosenImages() | rpl::start_with_next([=](
Ui::UserpicButton::ChosenImage &&chosen) {
if (chosen.type == Ui::UserpicButton::ChosenType::Set) {
session->api().peerPhoto().upload(
session->user(),
{
std::move(chosen.image),
chosen.markup.documentId,
chosen.markup.colors,
});
}
}, upload->lifetime());
state->userpicLifetime = session->changes().peerUpdates(
session->user(),
Data::PeerUpdate::Flag::Photo
) | rpl::start_with_next([=] {
if (session->user()->userpicPhotoId()) {
repeat(repeat);
}
});
content->setHideCallback([=] {
config->dismissSuggestion(kSugSetUserpic.utf8());
repeat(repeat);
});
content->setClickedCallback([=] {
const auto syntetic = [=](QEvent::Type type) {
Ui::SendSynteticMouseEvent(
upload,
type,
Qt::LeftButton,
upload->mapToGlobal(QPoint(0, 0)));
};
syntetic(QEvent::MouseMove);
syntetic(QEvent::MouseButtonPress);
syntetic(QEvent::MouseButtonRelease);
});
content->setContent(
tr::lng_dialogs_suggestions_userpics_title(
tr::now,
Ui::Text::Bold),
tr::lng_dialogs_suggestions_userpics_about(
tr::now,
TextWithEntities::Simple));
wrap->toggle(true, anim::type::normal);
return;
}
wrap->toggle(false, anim::type::normal);
base::call_delayed(st::slideWrapDuration * 2, wrap, [=] {
state->content = nullptr;
state->wrap = nullptr;
consumer.put_next(nullptr);
});
}
};
session->appConfig().value() | rpl::start_with_next([=] {

View file

@ -67,7 +67,8 @@ void TopBarSuggestionContent::draw(QPainter &p) {
const auto r = Ui::RpWidget::rect();
p.fillRect(r, st::historyPinnedBg);
Ui::RippleButton::paintRipple(p, 0, 0);
const auto leftPadding = st::defaultDialogRow.padding.left();
const auto leftPadding = st::defaultDialogRow.padding.left()
+ _leftPadding;
const auto rightPadding = st::msgReplyBarSkip;
const auto topPadding = st::msgReplyPadding.top();
const auto availableWidthNoPhoto = r.width()
@ -174,4 +175,9 @@ void TopBarSuggestionContent::setHideCallback(Fn<void()> hideCallback) {
_rightHide->setClickedCallback(std::move(hideCallback));
}
void TopBarSuggestionContent::setLeftPadding(int value) {
_leftPadding = value;
update();
}
} // namespace Dialogs

View file

@ -34,6 +34,7 @@ public:
void setHideCallback(Fn<void()>);
void setRightIcon(RightIcon);
void setLeftPadding(int);
protected:
void paintEvent(QPaintEvent *) override;
@ -54,6 +55,8 @@ private:
base::unique_qptr<Ui::IconButton> _rightArrow;
Fn<void()> _hideCallback;
int _leftPadding = 0;
RightIcon _rightIcon = RightIcon::None;
std::shared_ptr<Ui::DynamicImage> _rightPhoto;