mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Emoji status selector in MainMenu/Settings.
This commit is contained in:
parent
64bd4f0926
commit
bd089f20a8
18 changed files with 504 additions and 381 deletions
|
@ -653,27 +653,45 @@ void PeerListRow::invalidatePixmapsCache() {
|
|||
}
|
||||
}
|
||||
|
||||
int PeerListRow::nameIconWidth() const {
|
||||
return special()
|
||||
? 0
|
||||
: _peer->isVerified()
|
||||
? st::dialogsVerifiedIcon.width()
|
||||
: (_peer->isPremium() && !_peer->isSelf())
|
||||
? st::dialogsPremiumIcon.width()
|
||||
: 0;
|
||||
}
|
||||
|
||||
void PeerListRow::paintNameIcon(
|
||||
int PeerListRow::paintNameIconGetWidth(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
Fn<void()> repaint,
|
||||
crl::time now,
|
||||
int nameLeft,
|
||||
int nameTop,
|
||||
int nameWidth,
|
||||
int availableWidth,
|
||||
int outerWidth,
|
||||
bool selected) {
|
||||
if (_peer->isVerified()) {
|
||||
st::dialogsVerifiedIcon.paint(p, x, y, outerWidth);
|
||||
} else if (_peer->isPremium() && !_peer->isSelf()) {
|
||||
st::dialogsPremiumIcon.paint(p, x, y, outerWidth);
|
||||
if (special()
|
||||
|| _isSavedMessagesChat
|
||||
|| _isRepliesMessagesChat
|
||||
|| !_peer->isUser()) {
|
||||
return 0;
|
||||
}
|
||||
return _bagde.drawGetWidth(
|
||||
p,
|
||||
QRect(
|
||||
nameLeft,
|
||||
nameTop,
|
||||
availableWidth,
|
||||
st::msgNameStyle.font->height),
|
||||
nameWidth,
|
||||
outerWidth,
|
||||
{
|
||||
.peer = _peer,
|
||||
.verified = &(selected
|
||||
? st::dialogsVerifiedIconOver
|
||||
: st::dialogsVerifiedIcon),
|
||||
.premium = &(selected
|
||||
? st::dialogsPremiumIconOver
|
||||
: st::dialogsPremiumIcon),
|
||||
.scam = &(selected ? st::dialogsScamFgOver : st::dialogsScamFg),
|
||||
.preview = st::windowBgOver->c,
|
||||
.customEmojiRepaint = repaint,
|
||||
.now = now,
|
||||
.paused = false,
|
||||
});
|
||||
}
|
||||
|
||||
void PeerListRow::paintStatusText(
|
||||
|
@ -829,7 +847,7 @@ PeerListContent::PeerListContent(
|
|||
|
||||
using UpdateFlag = Data::PeerUpdate::Flag;
|
||||
_controller->session().changes().peerUpdates(
|
||||
UpdateFlag::Name | UpdateFlag::Photo
|
||||
UpdateFlag::Name | UpdateFlag::Photo | UpdateFlag::EmojiStatus
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
if (update.flags & UpdateFlag::Name) {
|
||||
handleNameChanged(update.peer);
|
||||
|
@ -1564,15 +1582,16 @@ crl::time PeerListContent::paintRow(
|
|||
- skipRight;
|
||||
}
|
||||
auto statusw = namew;
|
||||
if (auto iconWidth = row->nameIconWidth()) {
|
||||
namew -= iconWidth;
|
||||
row->paintNameIcon(
|
||||
p,
|
||||
namex + qMin(name.maxWidth(), namew),
|
||||
_st.item.namePosition.y(),
|
||||
width(),
|
||||
selected);
|
||||
}
|
||||
namew -= row->paintNameIconGetWidth(
|
||||
p,
|
||||
[=] { updateRow(row); },
|
||||
now,
|
||||
namex,
|
||||
_st.item.namePosition.y(),
|
||||
name.maxWidth(),
|
||||
namew,
|
||||
width(),
|
||||
selected);
|
||||
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
|
||||
p.setPen(anim::pen(_st.item.nameFg, _st.item.nameFgChecked, nameCheckedRatio));
|
||||
name.drawLeftElided(p, namex, _st.item.namePosition.y(), namew, width());
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "ui/unread_badge.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "data/data_cloud_file.h"
|
||||
|
@ -94,11 +95,14 @@ public:
|
|||
void clearCustomStatus();
|
||||
|
||||
// Box interface.
|
||||
virtual int nameIconWidth() const;
|
||||
virtual void paintNameIcon(
|
||||
virtual int paintNameIconGetWidth(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
Fn<void()> repaint,
|
||||
crl::time now,
|
||||
int nameLeft,
|
||||
int nameTop,
|
||||
int nameWidth,
|
||||
int availableWidth,
|
||||
int outerWidth,
|
||||
bool selected);
|
||||
|
||||
|
@ -258,6 +262,7 @@ private:
|
|||
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
|
||||
Ui::Text::String _name;
|
||||
Ui::Text::String _status;
|
||||
Ui::PeerBadge _bagde;
|
||||
StatusType _statusType = StatusType::Online;
|
||||
crl::time _statusValidTill = 0;
|
||||
base::flat_set<QChar> _nameFirstLetters;
|
||||
|
|
|
@ -1932,18 +1932,6 @@ auto ParticipantsBoxController::computeType(
|
|||
? Rights::Admin
|
||||
: Rights::Normal;
|
||||
result.adminRank = user ? _additional.adminRank(user) : QString();
|
||||
using Badge = Info::Profile::Badge;
|
||||
result.badge = !user
|
||||
? Badge::None
|
||||
: user->isScam()
|
||||
? Badge::Scam
|
||||
: user->isFake()
|
||||
? Badge::Fake
|
||||
: user->isVerified()
|
||||
? Badge::Verified
|
||||
: (user->isPremium() && participant->session().premiumBadgesShown())
|
||||
? Badge::Premium
|
||||
: Badge::None;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1952,7 +1940,8 @@ void ParticipantsBoxController::recomputeTypeFor(
|
|||
if (_role != Role::Profile) {
|
||||
return;
|
||||
}
|
||||
if (const auto row = delegate()->peerListFindRow(participant->id.value)) {
|
||||
const auto row = delegate()->peerListFindRow(participant->id.value);
|
||||
if (row) {
|
||||
static_cast<Row*>(row)->setType(computeType(participant));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,16 @@ public:
|
|||
Fn<void()> updateCallback) override;
|
||||
void rightActionStopLastRipple() override;
|
||||
|
||||
int nameIconWidth() const override {
|
||||
int paintNameIconGetWidth(
|
||||
Painter &p,
|
||||
Fn<void()> repaint,
|
||||
crl::time now,
|
||||
int nameLeft,
|
||||
int nameTop,
|
||||
int nameWidth,
|
||||
int availableWidth,
|
||||
int outerWidth,
|
||||
bool selected) override {
|
||||
return 0;
|
||||
}
|
||||
QSize rightActionSize() const override {
|
||||
|
|
|
@ -227,7 +227,11 @@ void TabbedPanel::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
void TabbedPanel::moveHorizontally() {
|
||||
const auto right = std::max(parentWidget()->width() - _right, 0);
|
||||
const auto padding = innerPadding();
|
||||
const auto width = innerRect().width() + padding.left() + padding.right();
|
||||
const auto right = std::max(
|
||||
parentWidget()->width() - std::max(_right, width),
|
||||
0);
|
||||
moveToRight(right, y());
|
||||
updateContentHeight();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,13 @@ InfoToggle {
|
|||
rippleAreaPadding: pixels;
|
||||
}
|
||||
|
||||
InfoPeerBadge {
|
||||
verified: icon;
|
||||
premium: icon;
|
||||
position: point;
|
||||
sizeTag: int;
|
||||
}
|
||||
|
||||
infoMediaHeaderFg: windowFg;
|
||||
|
||||
infoToggleCheckbox: Checkbox(defaultCheckbox) {
|
||||
|
@ -306,6 +313,13 @@ infoVerifiedCheck: icon {
|
|||
};
|
||||
infoPremiumStar: icon {{ "profile_premium", profileVerifiedCheckBg }};
|
||||
|
||||
infoPeerBadge: InfoPeerBadge {
|
||||
verified: infoVerifiedCheck;
|
||||
premium: infoPremiumStar;
|
||||
position: infoVerifiedCheckPosition;
|
||||
sizeTag: 1; // Large
|
||||
}
|
||||
|
||||
infoIconFg: windowBoldFg;
|
||||
|
||||
infoProfileSkip: 7px;
|
||||
|
|
|
@ -81,6 +81,217 @@ auto ChatStatusText(int fullCount, int onlineCount, bool isGroup) {
|
|||
|
||||
} // namespace
|
||||
|
||||
BadgeView::BadgeView(
|
||||
not_null<QWidget*> parent,
|
||||
const style::InfoPeerBadge &st,
|
||||
not_null<PeerData*> peer,
|
||||
Fn<bool()> animationPaused,
|
||||
base::flags<Badge> allowed)
|
||||
: _parent(parent)
|
||||
, _st(st)
|
||||
, _peer(peer)
|
||||
, _allowed(allowed)
|
||||
, _animationPaused(std::move(animationPaused)) {
|
||||
rpl::combine(
|
||||
BadgeValue(peer),
|
||||
EmojiStatusIdValue(peer)
|
||||
) | rpl::start_with_next([=](Badge badge, DocumentId emojiStatusId) {
|
||||
setBadge(badge, emojiStatusId);
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
Ui::RpWidget *BadgeView::widget() const {
|
||||
return _view.data();
|
||||
}
|
||||
|
||||
void BadgeView::setBadge(Badge badge, DocumentId emojiStatusId) {
|
||||
if ((!_peer->session().premiumBadgesShown() && badge == Badge::Premium)
|
||||
|| !(_allowed & badge)) {
|
||||
badge = Badge::None;
|
||||
}
|
||||
if (!(_allowed & badge)) {
|
||||
badge = Badge::None;
|
||||
}
|
||||
if (badge != Badge::Premium) {
|
||||
emojiStatusId = 0;
|
||||
}
|
||||
if (_badge == badge && _emojiStatusId == emojiStatusId) {
|
||||
return;
|
||||
}
|
||||
_badge = badge;
|
||||
_emojiStatusId = emojiStatusId;
|
||||
_emojiStatus = nullptr;
|
||||
_view.destroy();
|
||||
if (_badge == Badge::None) {
|
||||
_updated.fire({});
|
||||
return;
|
||||
}
|
||||
_view.create(_parent);
|
||||
_view->show();
|
||||
switch (_badge) {
|
||||
case Badge::Verified:
|
||||
case Badge::Premium: {
|
||||
if (_emojiStatusId) {
|
||||
using SizeTag = Data::CustomEmojiManager::SizeTag;
|
||||
const auto tag = (_st.sizeTag == 2)
|
||||
? SizeTag::Isolated
|
||||
: (_st.sizeTag == 1)
|
||||
? SizeTag::Large
|
||||
: SizeTag::Normal;
|
||||
_emojiStatus = _peer->owner().customEmojiManager().create(
|
||||
_emojiStatusId,
|
||||
[raw = _view.data()]{ raw->update(); },
|
||||
tag);
|
||||
const auto emoji = Data::FrameSizeFromTag(tag)
|
||||
/ style::DevicePixelRatio();
|
||||
_view->resize(emoji, emoji);
|
||||
_view->paintRequest(
|
||||
) | rpl::start_with_next([=, check = _view.data()]{
|
||||
Painter p(check);
|
||||
_emojiStatus->paint(
|
||||
p,
|
||||
0,
|
||||
0,
|
||||
crl::now(),
|
||||
st::windowBgOver->c,
|
||||
_animationPaused && _animationPaused());
|
||||
}, _view->lifetime());
|
||||
} else {
|
||||
const auto icon = (_badge == Badge::Verified)
|
||||
? &_st.verified
|
||||
: &_st.premium;
|
||||
_view->resize(icon->size());
|
||||
_view->paintRequest(
|
||||
) | rpl::start_with_next([=, check = _view.data()]{
|
||||
Painter p(check);
|
||||
icon->paint(p, 0, 0, check->width());
|
||||
}, _view->lifetime());
|
||||
}
|
||||
} break;
|
||||
case Badge::Scam:
|
||||
case Badge::Fake: {
|
||||
const auto fake = (_badge == Badge::Fake);
|
||||
const auto size = Ui::ScamBadgeSize(fake);
|
||||
const auto skip = st::infoVerifiedCheckPosition.x();
|
||||
_view->resize(
|
||||
size.width() + 2 * skip,
|
||||
size.height() + 2 * skip);
|
||||
_view->paintRequest(
|
||||
) | rpl::start_with_next([=, badge = _view.data()]{
|
||||
Painter p(badge);
|
||||
Ui::DrawScamBadge(
|
||||
fake,
|
||||
p,
|
||||
badge->rect().marginsRemoved({ skip, skip, skip, skip }),
|
||||
badge->width(),
|
||||
st::attentionButtonFg);
|
||||
}, _view->lifetime());
|
||||
} break;
|
||||
}
|
||||
|
||||
if (_badge != Badge::Premium || !_premiumClickCallback) {
|
||||
_view->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
} else {
|
||||
_view->setClickedCallback(_premiumClickCallback);
|
||||
}
|
||||
|
||||
_updated.fire({});
|
||||
}
|
||||
|
||||
void BadgeView::setPremiumClickCallback(Fn<void()> callback) {
|
||||
_premiumClickCallback = std::move(callback);
|
||||
if (_view && _badge == Badge::Premium) {
|
||||
if (!_premiumClickCallback) {
|
||||
_view->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
} else {
|
||||
_view->setAttribute(Qt::WA_TransparentForMouseEvents, false);
|
||||
_view->setClickedCallback(_premiumClickCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<> BadgeView::updated() const {
|
||||
return _updated.events();
|
||||
}
|
||||
|
||||
void BadgeView::move(int left, int top, int bottom) {
|
||||
if (!_view) {
|
||||
return;
|
||||
}
|
||||
const auto star = !_emojiStatus
|
||||
&& (_badge == Badge::Premium || _badge == Badge::Verified);
|
||||
const auto fake = !_emojiStatus && !star;
|
||||
const auto skip = fake ? 0 : _st.position.x();
|
||||
const auto badgeLeft = left + skip;
|
||||
const auto badgeTop = top
|
||||
+ (star
|
||||
? st::infoVerifiedCheckPosition.y()
|
||||
: (bottom - top - _view->height()) / 2);
|
||||
_view->moveToLeft(badgeLeft, badgeTop);
|
||||
}
|
||||
|
||||
void EmojiStatusPanel::show(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<QWidget*> button) {
|
||||
if (!_panel) {
|
||||
create(controller);
|
||||
|
||||
using namespace rpl::mappers;
|
||||
_panel->shownValue(
|
||||
) | rpl::filter(
|
||||
!_1
|
||||
) | rpl::start_with_next([=] {
|
||||
button->removeEventFilter(_panel.get());
|
||||
}, _panel->lifetime());
|
||||
}
|
||||
const auto parent = _panel->parentWidget();
|
||||
const auto global = button->mapToGlobal({ 0, 0 });
|
||||
const auto local = parent->mapFromGlobal(global);
|
||||
_panel->moveTopRight(
|
||||
local.y() + button->height(),
|
||||
local.x() + button->width() * 3);
|
||||
_panel->toggleAnimated();
|
||||
button->installEventFilter(_panel.get());
|
||||
}
|
||||
|
||||
void EmojiStatusPanel::create(
|
||||
not_null<Window::SessionController*> controller) {
|
||||
using Selector = ChatHelpers::TabbedSelector;
|
||||
_panel = base::make_unique_q<ChatHelpers::TabbedPanel>(
|
||||
controller->window().widget()->bodyWidget(),
|
||||
controller,
|
||||
object_ptr<Selector>(
|
||||
nullptr,
|
||||
controller,
|
||||
Window::GifPauseReason::Layer,
|
||||
ChatHelpers::TabbedSelector::Mode::EmojiStatus));
|
||||
_panel->setDropDown(true);
|
||||
_panel->setDesiredHeightValues(
|
||||
1.,
|
||||
st::emojiPanMinHeight / 2,
|
||||
st::emojiPanMinHeight);
|
||||
_panel->hide();
|
||||
_panel->selector()->setAllowEmojiWithoutPremium(false);
|
||||
|
||||
auto statusChosen = _panel->selector()->customEmojiChosen(
|
||||
) | rpl::map([=](Selector::FileChosen data) {
|
||||
return data.document->id;
|
||||
});
|
||||
|
||||
rpl::merge(
|
||||
std::move(statusChosen),
|
||||
_panel->selector()->emojiChosen() | rpl::map_to(DocumentId())
|
||||
) | rpl::start_with_next([=](DocumentId id) {
|
||||
controller->session().user()->setEmojiStatus(id);
|
||||
controller->session().api().request(MTPaccount_UpdateEmojiStatus(
|
||||
id ? MTP_emojiStatus(MTP_long(id)) : MTP_emojiStatusEmpty()
|
||||
)).send();
|
||||
_panel->hideAnimated();
|
||||
}, _panel->lifetime());
|
||||
|
||||
_panel->selector()->showPromoForPremiumEmoji();
|
||||
}
|
||||
|
||||
Cover::Cover(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer,
|
||||
|
@ -104,6 +315,14 @@ Cover::Cover(
|
|||
+ st::infoProfilePhotoBottom)
|
||||
, _controller(controller)
|
||||
, _peer(peer)
|
||||
, _badge(
|
||||
this,
|
||||
st::infoPeerBadge,
|
||||
peer,
|
||||
[=] {
|
||||
return controller->isGifPausedAtLeastFor(
|
||||
Window::GifPauseReason::Layer);
|
||||
})
|
||||
, _userpic(
|
||||
this,
|
||||
controller,
|
||||
|
@ -126,6 +345,19 @@ Cover::Cover(
|
|||
_status->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
_badge.setPremiumClickCallback([=] {
|
||||
if (_peer->isSelf()) {
|
||||
_emojiStatusPanel.show(_controller, _badge.widget());
|
||||
} else {
|
||||
::Settings::ShowPremium(
|
||||
_controller,
|
||||
u"profile__%1"_q.arg(peerToUser(_peer->id).bare));
|
||||
}
|
||||
});
|
||||
_badge.updated() | rpl::start_with_next([=] {
|
||||
refreshNameGeometry(width());
|
||||
}, _name->lifetime());
|
||||
|
||||
initViewers(std::move(title));
|
||||
setupChildGeometry();
|
||||
|
||||
|
@ -184,12 +416,6 @@ void Cover::initViewers(rpl::producer<QString> title) {
|
|||
} else if (_peer->isSelf()) {
|
||||
refreshUploadPhotoOverlay();
|
||||
}
|
||||
rpl::combine(
|
||||
BadgeValue(_peer),
|
||||
EmojiStatusIdValue(_peer)
|
||||
) | rpl::start_with_next([=](Badge badge, DocumentId emojiStatusId) {
|
||||
setBadge(badge, emojiStatusId);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void Cover::refreshUploadPhotoOverlay() {
|
||||
|
@ -203,151 +429,6 @@ void Cover::refreshUploadPhotoOverlay() {
|
|||
}());
|
||||
}
|
||||
|
||||
void Cover::setBadge(Badge badge, DocumentId emojiStatusId) {
|
||||
if (!_peer->session().premiumBadgesShown() && badge == Badge::Premium) {
|
||||
badge = Badge::None;
|
||||
}
|
||||
if (badge != Badge::Premium) {
|
||||
emojiStatusId = 0;
|
||||
}
|
||||
if (_badge == badge && _emojiStatusId == emojiStatusId) {
|
||||
return;
|
||||
}
|
||||
_badge = badge;
|
||||
_emojiStatusId = emojiStatusId;
|
||||
_emojiStatus = nullptr;
|
||||
_badgeView.destroy();
|
||||
switch (_badge) {
|
||||
case Badge::Verified:
|
||||
case Badge::Premium: {
|
||||
_badgeView.create(this);
|
||||
_badgeView->show();
|
||||
if (_emojiStatusId) {
|
||||
auto &owner = _controller->session().data();
|
||||
_emojiStatus = owner.customEmojiManager().create(
|
||||
_emojiStatusId,
|
||||
[raw = _badgeView.data()]{ raw->update(); },
|
||||
Data::CustomEmojiManager::SizeTag::Large);
|
||||
const auto size = Ui::Emoji::GetSizeLarge()
|
||||
/ style::DevicePixelRatio();
|
||||
const auto emoji = Ui::Text::AdjustCustomEmojiSize(size);
|
||||
_badgeView->resize(emoji, emoji);
|
||||
_badgeView->paintRequest(
|
||||
) | rpl::start_with_next([=, check = _badgeView.data()]{
|
||||
Painter p(check);
|
||||
_emojiStatus->paint(
|
||||
p,
|
||||
0,
|
||||
0,
|
||||
crl::now(),
|
||||
st::windowBgOver->c,
|
||||
_controller->isGifPausedAtLeastFor(
|
||||
Window::GifPauseReason::Layer));
|
||||
}, _badgeView->lifetime());
|
||||
} else {
|
||||
const auto icon = (_badge == Badge::Verified)
|
||||
? &st::infoVerifiedCheck
|
||||
: &st::infoPremiumStar;
|
||||
_badgeView->resize(icon->size());
|
||||
_badgeView->paintRequest(
|
||||
) | rpl::start_with_next([=, check = _badgeView.data()]{
|
||||
Painter p(check);
|
||||
icon->paint(p, 0, 0, check->width());
|
||||
}, _badgeView->lifetime());
|
||||
}
|
||||
} break;
|
||||
case Badge::Scam:
|
||||
case Badge::Fake: {
|
||||
const auto fake = (_badge == Badge::Fake);
|
||||
const auto size = Ui::ScamBadgeSize(fake);
|
||||
const auto skip = st::infoVerifiedCheckPosition.x();
|
||||
_badgeView.create(this);
|
||||
_badgeView->show();
|
||||
_badgeView->resize(
|
||||
size.width() + 2 * skip,
|
||||
size.height() + 2 * skip);
|
||||
_badgeView->paintRequest(
|
||||
) | rpl::start_with_next([=, badge = _badgeView.data()]{
|
||||
Painter p(badge);
|
||||
Ui::DrawScamBadge(
|
||||
fake,
|
||||
p,
|
||||
badge->rect().marginsRemoved({ skip, skip, skip, skip }),
|
||||
badge->width(),
|
||||
st::attentionButtonFg);
|
||||
}, _badgeView->lifetime());
|
||||
} break;
|
||||
}
|
||||
|
||||
if (_badge == Badge::Premium) {
|
||||
const auto userId = peerToUser(_peer->id).bare;
|
||||
_badgeView->setClickedCallback([=] {
|
||||
if (_peer->isSelf()) {
|
||||
showEmojiStatusSelector();
|
||||
} else {
|
||||
::Settings::ShowPremium(
|
||||
_controller,
|
||||
u"profile__%1"_q.arg(userId));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_badgeView->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
refreshNameGeometry(width());
|
||||
}
|
||||
|
||||
void Cover::showEmojiStatusSelector() {
|
||||
Expects(_badgeView != nullptr);
|
||||
|
||||
if (!_emojiStatusPanel) {
|
||||
createEmojiStatusSelector();
|
||||
}
|
||||
const auto parent = _emojiStatusPanel->parentWidget();
|
||||
const auto global = _badgeView->mapToGlobal({ 0, 0 });
|
||||
const auto local = parent->mapFromGlobal(global);
|
||||
_emojiStatusPanel->moveTopRight(
|
||||
local.y() + _badgeView->height(),
|
||||
local.x() + _badgeView->width() * 3);
|
||||
_emojiStatusPanel->toggleAnimated();
|
||||
}
|
||||
|
||||
void Cover::createEmojiStatusSelector() {
|
||||
const auto set = [=](DocumentId id) {
|
||||
_controller->session().user()->setEmojiStatus(id);
|
||||
_controller->session().api().request(MTPaccount_UpdateEmojiStatus(
|
||||
id ? MTP_emojiStatus(MTP_long(id)) : MTP_emojiStatusEmpty()
|
||||
)).send();
|
||||
_emojiStatusPanel->hideAnimated();
|
||||
};
|
||||
const auto container = _controller->window().widget()->bodyWidget();
|
||||
using Selector = ChatHelpers::TabbedSelector;
|
||||
_emojiStatusPanel = base::make_unique_q<ChatHelpers::TabbedPanel>(
|
||||
container,
|
||||
_controller,
|
||||
object_ptr<Selector>(
|
||||
nullptr,
|
||||
_controller,
|
||||
Window::GifPauseReason::Layer,
|
||||
ChatHelpers::TabbedSelector::Mode::EmojiStatus));
|
||||
_emojiStatusPanel->setDropDown(true);
|
||||
_emojiStatusPanel->setDesiredHeightValues(
|
||||
1.,
|
||||
st::emojiPanMinHeight / 2,
|
||||
st::emojiPanMinHeight);
|
||||
_emojiStatusPanel->hide();
|
||||
_emojiStatusPanel->selector()->setAllowEmojiWithoutPremium(false);
|
||||
_emojiStatusPanel->selector()->emojiChosen(
|
||||
) | rpl::start_with_next([=] {
|
||||
set(0);
|
||||
}, _emojiStatusPanel->lifetime());
|
||||
_emojiStatusPanel->selector()->customEmojiChosen(
|
||||
) | rpl::start_with_next([=](Selector::FileChosen data) {
|
||||
set(data.document->id);
|
||||
}, _emojiStatusPanel->lifetime());
|
||||
_emojiStatusPanel->selector()->showPromoForPremiumEmoji();
|
||||
}
|
||||
|
||||
void Cover::refreshStatusText() {
|
||||
auto hasMembersLink = [&] {
|
||||
if (auto megagroup = _peer->asMegagroup()) {
|
||||
|
@ -406,23 +487,15 @@ void Cover::refreshNameGeometry(int newWidth) {
|
|||
auto nameWidth = newWidth
|
||||
- nameLeft
|
||||
- st::infoProfileNameRight;
|
||||
if (_badgeView) {
|
||||
nameWidth -= st::infoVerifiedCheckPosition.x() + _badgeView->width();
|
||||
if (const auto width = _badge.widget() ? _badge.widget()->width() : 0) {
|
||||
nameWidth -= st::infoVerifiedCheckPosition.x() + width;
|
||||
}
|
||||
_name->resizeToNaturalWidth(nameWidth);
|
||||
_name->moveToLeft(nameLeft, nameTop, newWidth);
|
||||
if (_badgeView) {
|
||||
const auto star = !_emojiStatus
|
||||
&& (_badge == Badge::Premium || _badge == Badge::Verified);
|
||||
const auto fake = !_emojiStatus && !star;
|
||||
const auto skip = fake ? 0 : st::infoVerifiedCheckPosition.x();
|
||||
const auto badgeLeft = nameLeft + _name->width() + skip;
|
||||
const auto badgeTop = nameTop
|
||||
+ (star
|
||||
? st::infoVerifiedCheckPosition.y()
|
||||
: (_name->height() - _badgeView->height()) / 2);
|
||||
_badgeView->moveToLeft(badgeLeft, badgeTop, newWidth);
|
||||
}
|
||||
const auto badgeLeft = nameLeft + _name->width();
|
||||
const auto badgeTop = nameTop;
|
||||
const auto badgeBottom = nameTop + _name->height();
|
||||
_badge.move(badgeLeft, badgeTop, badgeBottom);
|
||||
}
|
||||
|
||||
void Cover::refreshStatusGeometry(int newWidth) {
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/flags.h"
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
|
@ -17,6 +18,7 @@ class SessionController;
|
|||
|
||||
namespace style {
|
||||
struct InfoToggle;
|
||||
struct InfoPeerBadge;
|
||||
} // namespace style
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
@ -39,9 +41,62 @@ class Section;
|
|||
namespace Info {
|
||||
namespace Profile {
|
||||
|
||||
enum class Badge;
|
||||
enum class Badge {
|
||||
None = 0x00,
|
||||
Verified = 0x01,
|
||||
Premium = 0x02,
|
||||
Scam = 0x04,
|
||||
Fake = 0x08,
|
||||
};
|
||||
inline constexpr bool is_flag_type(Badge) { return true; }
|
||||
|
||||
class Cover : public Ui::FixedHeightWidget {
|
||||
class BadgeView final {
|
||||
public:
|
||||
BadgeView(
|
||||
not_null<QWidget*> parent,
|
||||
const style::InfoPeerBadge &st,
|
||||
not_null<PeerData*> peer,
|
||||
Fn<bool()> animationPaused,
|
||||
base::flags<Badge> allowed = base::flags<Badge>::from_raw(-1));
|
||||
|
||||
[[nodiscard]] Ui::RpWidget *widget() const;
|
||||
|
||||
void setPremiumClickCallback(Fn<void()> callback);
|
||||
[[nodiscrd]] rpl::producer<> updated() const;
|
||||
void move(int left, int top, int bottom);
|
||||
|
||||
private:
|
||||
void setBadge(Badge badge, DocumentId emojiStatusId);
|
||||
|
||||
const not_null<QWidget*> _parent;
|
||||
const style::InfoPeerBadge &_st;
|
||||
const not_null<PeerData*> _peer;
|
||||
DocumentId _emojiStatusId = 0;
|
||||
std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus;
|
||||
base::flags<Badge> _allowed;
|
||||
Badge _badge = Badge();
|
||||
Fn<void()> _premiumClickCallback;
|
||||
Fn<bool()> _animationPaused;
|
||||
object_ptr<Ui::AbstractButton> _view = { nullptr };
|
||||
rpl::event_stream<> _updated;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
class EmojiStatusPanel final {
|
||||
public:
|
||||
void show(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<QWidget*> button);
|
||||
|
||||
private:
|
||||
void create(not_null<Window::SessionController*> controller);
|
||||
|
||||
base::unique_qptr<ChatHelpers::TabbedPanel> _panel;
|
||||
|
||||
};
|
||||
|
||||
class Cover final : public Ui::FixedHeightWidget {
|
||||
public:
|
||||
Cover(
|
||||
QWidget *parent,
|
||||
|
@ -68,21 +123,15 @@ private:
|
|||
void refreshNameGeometry(int newWidth);
|
||||
void refreshStatusGeometry(int newWidth);
|
||||
void refreshUploadPhotoOverlay();
|
||||
void setBadge(Badge badge, DocumentId emojiStatusId);
|
||||
void createEmojiStatusSelector();
|
||||
void showEmojiStatusSelector();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<PeerData*> _peer;
|
||||
DocumentId _emojiStatusId = 0;
|
||||
std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus;
|
||||
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiStatusPanel;
|
||||
BadgeView _badge;
|
||||
EmojiStatusPanel _emojiStatusPanel;
|
||||
int _onlineCount = 0;
|
||||
Badge _badge = Badge();
|
||||
|
||||
object_ptr<Ui::UserpicButton> _userpic;
|
||||
object_ptr<Ui::FlatLabel> _name = { nullptr };
|
||||
object_ptr<Ui::AbstractButton> _badgeView = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _status = { nullptr };
|
||||
//object_ptr<CoverDropArea> _dropArea = { nullptr };
|
||||
base::Timer _refreshStatusTimer;
|
||||
|
|
|
@ -30,11 +30,6 @@ MemberListRow::MemberListRow(
|
|||
|
||||
void MemberListRow::setType(Type type) {
|
||||
_type = type;
|
||||
_fakeScamSize = (_type.badge == Badge::Fake)
|
||||
? Ui::ScamBadgeSize(true)
|
||||
: (_type.badge == Badge::Scam)
|
||||
? Ui::ScamBadgeSize(false)
|
||||
: QSize();
|
||||
PeerListRowWithLink::setActionLink(!_type.adminRank.isEmpty()
|
||||
? _type.adminRank
|
||||
: (_type.rights == Rights::Creator)
|
||||
|
@ -57,55 +52,10 @@ QMargins MemberListRow::rightActionMargins() const {
|
|||
0);
|
||||
}
|
||||
|
||||
int MemberListRow::nameIconWidth() const {
|
||||
switch (_type.badge) {
|
||||
case Badge::None: return 0;
|
||||
case Badge::Verified: return st::dialogsVerifiedIcon.width();
|
||||
case Badge::Premium: return st::dialogsPremiumIcon.width();
|
||||
case Badge::Scam:
|
||||
case Badge::Fake:
|
||||
return st::dialogsScamSkip + _fakeScamSize.width();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
not_null<UserData*> MemberListRow::user() const {
|
||||
return peer()->asUser();
|
||||
}
|
||||
|
||||
void MemberListRow::paintNameIcon(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
bool selected) {
|
||||
switch (_type.badge) {
|
||||
case Badge::None: return;
|
||||
case Badge::Verified:
|
||||
(selected
|
||||
? st::dialogsVerifiedIconOver
|
||||
: st::dialogsVerifiedIcon).paint(p, x, y, outerWidth);
|
||||
break;
|
||||
case Badge::Premium:
|
||||
(selected
|
||||
? st::dialogsPremiumIconOver
|
||||
: st::dialogsPremiumIcon).paint(p, x, y, outerWidth);
|
||||
break;
|
||||
case Badge::Scam:
|
||||
case Badge::Fake:
|
||||
return Ui::DrawScamBadge(
|
||||
(_type.badge == Badge::Fake),
|
||||
p,
|
||||
QRect(
|
||||
x + st::dialogsScamSkip,
|
||||
y + (st::normalFont->height - _fakeScamSize.height()) / 2,
|
||||
_fakeScamSize.width(),
|
||||
_fakeScamSize.height()),
|
||||
outerWidth,
|
||||
(selected ? st::dialogsScamFgOver : st::dialogsScamFg));
|
||||
}
|
||||
}
|
||||
|
||||
void MemberListRow::refreshStatus() {
|
||||
if (user()->isBot()) {
|
||||
const auto seesAllMessages = (user()->botInfo->readsAllHistory
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "ui/unread_badge.h"
|
||||
|
||||
namespace Window {
|
||||
class SessionNavigation;
|
||||
|
@ -16,8 +17,6 @@ class SessionNavigation;
|
|||
namespace Info {
|
||||
namespace Profile {
|
||||
|
||||
enum class Badge;
|
||||
|
||||
class MemberListRow final : public PeerListRowWithLink {
|
||||
public:
|
||||
enum class Rights {
|
||||
|
@ -26,7 +25,6 @@ public:
|
|||
Creator,
|
||||
};
|
||||
struct Type {
|
||||
Badge badge;
|
||||
Rights rights;
|
||||
QString adminRank;
|
||||
};
|
||||
|
@ -36,20 +34,12 @@ public:
|
|||
void setType(Type type);
|
||||
bool rightActionDisabled() const override;
|
||||
QMargins rightActionMargins() const override;
|
||||
int nameIconWidth() const override;
|
||||
void paintNameIcon(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
bool selected) override;
|
||||
void refreshStatus() override;
|
||||
|
||||
not_null<UserData*> user() const;
|
||||
|
||||
private:
|
||||
Type _type;
|
||||
QSize _fakeScamSize;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "info/profile/info_profile_values.h"
|
||||
|
||||
#include "info/profile/info_profile_cover.h"
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "countries/countries_instance.h"
|
||||
|
|
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/flags.h"
|
||||
|
||||
#include <rpl/producer.h>
|
||||
#include <rpl/map.h>
|
||||
|
||||
|
@ -90,13 +92,7 @@ rpl::producer<not_null<PeerData*>> MigratedOrMeValue(
|
|||
[[nodiscard]] rpl::producer<int> AllowedReactionsCountValue(
|
||||
not_null<PeerData*> peer);
|
||||
|
||||
enum class Badge {
|
||||
None,
|
||||
Verified,
|
||||
Premium,
|
||||
Scam,
|
||||
Fake,
|
||||
};
|
||||
enum class Badge;
|
||||
[[nodiscard]] rpl::producer<Badge> BadgeValue(not_null<PeerData*> peer);
|
||||
[[nodiscard]] rpl::producer<DocumentId> EmojiStatusIdValue(
|
||||
not_null<PeerData*> peer);
|
||||
|
|
|
@ -184,6 +184,10 @@ settingsInfoPhotoTop: 0px;
|
|||
settingsInfoPhotoSkip: 7px;
|
||||
settingsInfoNameSkip: -1px;
|
||||
settingsInfoUploadLeft: 6px;
|
||||
settingsInfoPeerBadge: InfoPeerBadge {
|
||||
verified: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }};
|
||||
sizeTag: 0; // Normal
|
||||
}
|
||||
|
||||
settingsBio: InputField(defaultInputField) {
|
||||
textBg: transparent;
|
||||
|
|
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_premium_limits.h"
|
||||
#include "dialogs/ui/dialogs_layout.h"
|
||||
#include "info/profile/info_profile_values.h"
|
||||
#include "info/profile/info_profile_cover.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -71,7 +72,8 @@ public:
|
|||
not_null<Ui::SettingsButton*> button,
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<QString> &&text,
|
||||
bool hasUnread);
|
||||
bool hasUnread,
|
||||
Fn<bool()> animationPaused);
|
||||
|
||||
private:
|
||||
rpl::variable<QString> _text;
|
||||
|
@ -79,7 +81,7 @@ private:
|
|||
rpl::event_stream<int> _premiumWidth;
|
||||
|
||||
QPointer<Ui::RpWidget> _unread;
|
||||
QPointer<Ui::RpWidget> _premium;
|
||||
Info::Profile::BadgeView _badge;
|
||||
|
||||
};
|
||||
|
||||
|
@ -88,9 +90,16 @@ ComposedBadge::ComposedBadge(
|
|||
not_null<Ui::SettingsButton*> button,
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<QString> &&text,
|
||||
bool hasUnread)
|
||||
bool hasUnread,
|
||||
Fn<bool()> animationPaused)
|
||||
: Ui::RpWidget(parent)
|
||||
, _text(std::move(text)) {
|
||||
, _text(std::move(text))
|
||||
, _badge(
|
||||
this,
|
||||
st::settingsInfoPeerBadge,
|
||||
session->user(),
|
||||
std::move(animationPaused),
|
||||
Info::Profile::Badge::Premium) {
|
||||
if (hasUnread) {
|
||||
_unread = CreateUnread(this, rpl::single(
|
||||
rpl::empty
|
||||
|
@ -111,35 +120,19 @@ ComposedBadge::ComposedBadge(
|
|||
}) | rpl::start_to_stream(_unreadWidth, _unread->lifetime());
|
||||
}
|
||||
|
||||
Data::AmPremiumValue(
|
||||
session
|
||||
) | rpl::start_with_next([=](bool hasPremium) {
|
||||
if (hasPremium && !_premium) {
|
||||
_premium = Ui::CreateChild<Ui::RpWidget>(this);
|
||||
const auto offset = st::dialogsPremiumIconOffset;
|
||||
_premium->resize(
|
||||
st::dialogsPremiumIcon.width() - offset.x(),
|
||||
st::dialogsPremiumIcon.height() - offset.y());
|
||||
_premium->paintRequest(
|
||||
) | rpl::start_with_next([=](const QRect &r) {
|
||||
Painter p(_premium);
|
||||
st::dialogsPremiumIcon.paint(
|
||||
p,
|
||||
-offset.x(),
|
||||
-offset.y(),
|
||||
_premium->width());
|
||||
}, _premium->lifetime());
|
||||
_premium->widthValue(
|
||||
) | rpl::start_to_stream(_premiumWidth, _premium->lifetime());
|
||||
} else if (!hasPremium && _premium) {
|
||||
_premium = nullptr;
|
||||
_badge.updated(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (const auto button = _badge.widget()) {
|
||||
button->widthValue(
|
||||
) | rpl::start_to_stream(_premiumWidth, button->lifetime());
|
||||
} else {
|
||||
_premiumWidth.fire(0);
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
rpl::combine(
|
||||
_unreadWidth.events_starting_with(_unread ? _unread->width() : 0),
|
||||
_premiumWidth.events_starting_with(_premium ? _premium->width() : 0),
|
||||
_premiumWidth.events_starting_with(0),
|
||||
_text.value(),
|
||||
button->sizeValue()
|
||||
) | rpl::start_with_next([=](
|
||||
|
@ -151,7 +144,7 @@ ComposedBadge::ComposedBadge(
|
|||
const auto skip = st.style.font->spacew;
|
||||
const auto textRightPosition = st.padding.left()
|
||||
+ st.style.font->width(text)
|
||||
+ skip * 2;
|
||||
+ skip;
|
||||
const auto minWidth = unreadWidth + premiumWidth + skip;
|
||||
const auto maxTextWidth = buttonSize.width()
|
||||
- minWidth
|
||||
|
@ -163,9 +156,7 @@ ComposedBadge::ComposedBadge(
|
|||
buttonSize.width() - st.padding.right() - finalTextRight,
|
||||
buttonSize.height());
|
||||
|
||||
if (_premium) {
|
||||
_premium->moveToLeft(0, st.padding.top());
|
||||
}
|
||||
_badge.move(0, 0, buttonSize.height());
|
||||
if (_unread) {
|
||||
_unread->moveToRight(
|
||||
0,
|
||||
|
@ -618,7 +609,9 @@ void SetupAccountsWrap(
|
|||
raw,
|
||||
session,
|
||||
std::move(text),
|
||||
!active);
|
||||
!active,
|
||||
[=] { return window->isGifPausedAtLeastFor(
|
||||
Window::GifPauseReason::Layer); });
|
||||
composedBadge->sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
container->resize(s);
|
||||
|
@ -986,9 +979,7 @@ not_null<Ui::RpWidget*> AddRight(
|
|||
padding.right(),
|
||||
(outer.height() - inner.height()) / 2,
|
||||
outer.width());
|
||||
padding.setRight(padding.right()
|
||||
+ inner.width()
|
||||
+ button->st().style.font->spacew);
|
||||
padding.setRight(padding.right() + inner.width());
|
||||
}
|
||||
button->setPaddingOverride(padding);
|
||||
button->update();
|
||||
|
|
|
@ -85,12 +85,13 @@ private:
|
|||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<UserData*> _user;
|
||||
Info::Profile::BadgeView _badge;
|
||||
Info::Profile::EmojiStatusPanel _emojiStatusPanel;
|
||||
|
||||
object_ptr<Ui::UserpicButton> _userpic;
|
||||
object_ptr<Ui::FlatLabel> _name = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _phone = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _username = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _badge = { nullptr };
|
||||
|
||||
};
|
||||
|
||||
|
@ -105,6 +106,15 @@ Cover::Cover(
|
|||
+ st::settingsPhotoBottom)
|
||||
, _controller(controller)
|
||||
, _user(user)
|
||||
, _badge(
|
||||
this,
|
||||
st::infoPeerBadge,
|
||||
user,
|
||||
[=] {
|
||||
return controller->isGifPausedAtLeastFor(
|
||||
Window::GifPauseReason::Layer);
|
||||
},
|
||||
Info::Profile::Badge::Premium)
|
||||
, _userpic(
|
||||
this,
|
||||
controller,
|
||||
|
@ -133,23 +143,12 @@ Cover::Cover(
|
|||
_userpic->takeResultImage());
|
||||
}, _userpic->lifetime());
|
||||
|
||||
Data::AmPremiumValue(
|
||||
&controller->session()
|
||||
) | rpl::start_with_next([=](bool hasPremium) {
|
||||
if (hasPremium && !_badge) {
|
||||
const auto icon = &st::infoPremiumStar;
|
||||
_badge.create(this);
|
||||
_badge->show();
|
||||
_badge->resize(icon->size());
|
||||
_badge->paintRequest(
|
||||
) | rpl::start_with_next([icon, check = _badge.data()] {
|
||||
Painter p(check);
|
||||
icon->paint(p, 0, 0, check->width());
|
||||
}, _badge->lifetime());
|
||||
} else if (!hasPremium && _badge) {
|
||||
_badge.destroy();
|
||||
}
|
||||
}, lifetime());
|
||||
_badge.setPremiumClickCallback([=] {
|
||||
_emojiStatusPanel.show(_controller, _badge.widget());
|
||||
});
|
||||
_badge.updated() | rpl::start_with_next([=] {
|
||||
refreshNameGeometry(width());
|
||||
}, _name->lifetime());
|
||||
}
|
||||
|
||||
Cover::~Cover() = default;
|
||||
|
@ -210,19 +209,18 @@ void Cover::initViewers() {
|
|||
void Cover::refreshNameGeometry(int newWidth) {
|
||||
const auto nameLeft = st::settingsNameLeft;
|
||||
const auto nameTop = st::settingsNameTop;
|
||||
const auto nameWidth = newWidth
|
||||
auto nameWidth = newWidth
|
||||
- nameLeft
|
||||
- st::infoProfileNameRight
|
||||
- (!_badge ? 0 : _badge->width() + st::infoVerifiedCheckPosition.x());
|
||||
- st::infoProfileNameRight;
|
||||
if (const auto width = _badge.widget() ? _badge.widget()->width() : 0) {
|
||||
nameWidth -= st::infoVerifiedCheckPosition.x() + width;
|
||||
}
|
||||
_name->resizeToNaturalWidth(nameWidth);
|
||||
_name->moveToLeft(nameLeft, nameTop, newWidth);
|
||||
|
||||
if (_badge) {
|
||||
const auto &pos = st::infoVerifiedCheckPosition;
|
||||
const auto badgeLeft = nameLeft + _name->width() + pos.x();
|
||||
const auto badgeTop = nameTop + pos.y();
|
||||
_badge->moveToLeft(badgeLeft, badgeTop, newWidth);
|
||||
}
|
||||
const auto badgeLeft = nameLeft + _name->width();
|
||||
const auto badgeTop = nameTop;
|
||||
const auto badgeBottom = nameTop + _name->height();
|
||||
_badge.move(badgeLeft, badgeTop, badgeBottom);
|
||||
}
|
||||
|
||||
void Cover::refreshPhoneGeometry(int newWidth) {
|
||||
|
|
|
@ -182,12 +182,12 @@ int PeerBadge::drawGetWidth(
|
|||
}
|
||||
_emojiStatus->emoji->paint(
|
||||
p,
|
||||
iconx - _emojiStatus->skip,
|
||||
iconx - 2 * _emojiStatus->skip,
|
||||
icony + _emojiStatus->skip,
|
||||
descriptor.now,
|
||||
descriptor.preview,
|
||||
descriptor.paused);
|
||||
return iconw - 2 * _emojiStatus->skip;
|
||||
return iconw - 4 * _emojiStatus->skip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "settings/settings_common.h"
|
||||
#include "settings/settings_calls.h"
|
||||
#include "settings/settings_information.h"
|
||||
#include "info/profile/info_profile_cover.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "boxes/about_box.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
|
@ -120,7 +121,10 @@ public:
|
|||
explicit ToggleAccountsButton(QWidget *parent);
|
||||
|
||||
[[nodiscard]] int rightSkip() const {
|
||||
return _rightSkip;
|
||||
return _rightSkip.current();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<int> rightSkipValue() const {
|
||||
return _rightSkip.value();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -130,7 +134,7 @@ private:
|
|||
void validateUnreadBadge();
|
||||
[[nodiscard]] QString computeUnreadBadge() const;
|
||||
|
||||
int _rightSkip = 0;
|
||||
rpl::variable<int> _rightSkip = 0;
|
||||
Ui::Animations::Simple _toggledAnimation;
|
||||
bool _toggled = false;
|
||||
|
||||
|
@ -258,12 +262,13 @@ void MainMenu::ToggleAccountsButton::validateUnreadBadge() {
|
|||
}
|
||||
_unreadBadge = computeUnreadBadge();
|
||||
|
||||
_rightSkip = base;
|
||||
auto skip = base;
|
||||
if (!_unreadBadge.isEmpty()) {
|
||||
const auto st = Settings::Badge::Style();
|
||||
_rightSkip += 2 * st::mainMenuToggleSize
|
||||
skip += 2 * st::mainMenuToggleSize
|
||||
+ Dialogs::Ui::CountUnreadBadgeSize(_unreadBadge, st).width();
|
||||
}
|
||||
_rightSkip = skip;
|
||||
}
|
||||
|
||||
QString MainMenu::ToggleAccountsButton::computeUnreadBadge() const {
|
||||
|
@ -331,6 +336,13 @@ MainMenu::MainMenu(
|
|||
Ui::UserpicButton::Role::Custom,
|
||||
st::mainMenuUserpic)
|
||||
, _toggleAccounts(this)
|
||||
, _badge(std::make_unique<Info::Profile::BadgeView>(
|
||||
this,
|
||||
st::settingsInfoPeerBadge,
|
||||
controller->session().user(),
|
||||
[=] { return controller->isGifPausedAtLeastFor(GifPauseReason::Layer); },
|
||||
Info::Profile::Badge::Premium))
|
||||
, _emojiStatusPanel(std::make_unique<Info::Profile::EmojiStatusPanel>())
|
||||
, _scroll(this, st::defaultSolidScroll)
|
||||
, _inner(_scroll->setOwnedWidget(
|
||||
object_ptr<Ui::VerticalLayout>(_scroll.data())))
|
||||
|
@ -416,6 +428,16 @@ MainMenu::MainMenu(
|
|||
controller->show(Box<AboutBox>());
|
||||
}));
|
||||
|
||||
rpl::combine(
|
||||
_toggleAccounts->rightSkipValue(),
|
||||
rpl::single(rpl::empty) | rpl::then(_badge->updated())
|
||||
) | rpl::start_with_next([=] {
|
||||
moveBadge();
|
||||
}, lifetime());
|
||||
_badge->setPremiumClickCallback([=] {
|
||||
_emojiStatusPanel->show(_controller, _badge->widget());
|
||||
});
|
||||
|
||||
_controller->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
|
@ -432,6 +454,24 @@ MainMenu::MainMenu(
|
|||
initResetScaleButton();
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() = default;
|
||||
|
||||
void MainMenu::moveBadge() {
|
||||
if (!_badge->widget()) {
|
||||
return;
|
||||
}
|
||||
const auto available = width()
|
||||
- st::mainMenuCoverNameLeft
|
||||
- _toggleAccounts->rightSkip()
|
||||
- _badge->widget()->width();
|
||||
const auto left = st::mainMenuCoverNameLeft
|
||||
+ std::min(_name.maxWidth() + st::semiboldFont->spacew, available);
|
||||
_badge->move(
|
||||
left,
|
||||
st::mainMenuCoverNameTop,
|
||||
st::mainMenuCoverNameTop + st::msgNameStyle.font->height);
|
||||
}
|
||||
|
||||
void MainMenu::setupArchive() {
|
||||
using namespace Settings;
|
||||
|
||||
|
@ -771,30 +811,10 @@ void MainMenu::paintEvent(QPaintEvent *e) {
|
|||
st::msgNameStyle,
|
||||
user->name(),
|
||||
Ui::NameTextOptions());
|
||||
moveBadge();
|
||||
}
|
||||
const auto paused = _controller->isGifPausedAtLeastFor(
|
||||
GifPauseReason::Layer);
|
||||
const auto badgeWidth = user->emojiStatusId()
|
||||
? _badge.drawGetWidth(
|
||||
p,
|
||||
QRect(
|
||||
st::mainMenuCoverNameLeft,
|
||||
st::mainMenuCoverNameTop,
|
||||
widthText,
|
||||
st::msgNameStyle.font->height),
|
||||
_name.maxWidth(),
|
||||
width(),
|
||||
{
|
||||
.peer = user,
|
||||
.verified = nullptr,
|
||||
.premium = &st::dialogsPremiumIcon,
|
||||
.scam = nullptr,
|
||||
.preview = st::windowBgOver->c,
|
||||
.customEmojiRepaint = [=] { update(); },
|
||||
.now = crl::now(),
|
||||
.paused = paused,
|
||||
})
|
||||
: 0;
|
||||
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::windowBoldFg);
|
||||
|
@ -802,7 +822,10 @@ void MainMenu::paintEvent(QPaintEvent *e) {
|
|||
p,
|
||||
st::mainMenuCoverNameLeft,
|
||||
st::mainMenuCoverNameTop,
|
||||
widthText - badgeWidth,
|
||||
(widthText
|
||||
- (_badge->widget()
|
||||
? (st::semiboldFont->spacew + _badge->widget()->width())
|
||||
: 0)),
|
||||
width());
|
||||
p.setFont(st::mainMenuPhoneFont);
|
||||
p.setPen(st::windowSubTextFg);
|
||||
|
|
|
@ -28,6 +28,11 @@ template <typename Widget>
|
|||
class SlideWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Info::Profile {
|
||||
class BadgeView;
|
||||
class EmojiStatusPanel;
|
||||
} // namespace Info::Profile
|
||||
|
||||
namespace Main {
|
||||
class Account;
|
||||
} // namespace Main
|
||||
|
@ -39,6 +44,7 @@ class SessionController;
|
|||
class MainMenu final : public Ui::LayerWidget {
|
||||
public:
|
||||
MainMenu(QWidget *parent, not_null<SessionController*> controller);
|
||||
~MainMenu();
|
||||
|
||||
void parentResized() override;
|
||||
|
||||
|
@ -54,6 +60,7 @@ private:
|
|||
class ToggleAccountsButton;
|
||||
class ResetScaleButton;
|
||||
|
||||
void moveBadge();
|
||||
void setupUserpicButton();
|
||||
void setupAccounts();
|
||||
void setupAccountsToggle();
|
||||
|
@ -67,10 +74,11 @@ private:
|
|||
|
||||
const not_null<SessionController*> _controller;
|
||||
object_ptr<Ui::UserpicButton> _userpicButton;
|
||||
Ui::PeerBadge _badge;
|
||||
Ui::Text::String _name;
|
||||
int _nameVersion = 0;
|
||||
object_ptr<ToggleAccountsButton> _toggleAccounts;
|
||||
std::unique_ptr<Info::Profile::BadgeView> _badge;
|
||||
std::unique_ptr<Info::Profile::EmojiStatusPanel> _emojiStatusPanel;
|
||||
object_ptr<ResetScaleButton> _resetScaleButton = { nullptr };
|
||||
object_ptr<Ui::ScrollArea> _scroll;
|
||||
not_null<Ui::VerticalLayout*> _inner;
|
||||
|
|
Loading…
Add table
Reference in a new issue