mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-28 00:12:26 +00:00
Allow many lines in ConfirmInviteBox about.
This commit is contained in:
@@ -48,6 +48,69 @@ namespace Api {
|
||||
|
||||
namespace {
|
||||
|
||||
struct InviteParticipant {
|
||||
not_null<UserData*> user;
|
||||
Ui::PeerUserpicView userpic;
|
||||
};
|
||||
|
||||
struct ChatInvite {
|
||||
QString title;
|
||||
QString about;
|
||||
PhotoData *photo = nullptr;
|
||||
int participantsCount = 0;
|
||||
std::vector<InviteParticipant> participants;
|
||||
bool isPublic = false;
|
||||
bool isChannel = false;
|
||||
bool isMegagroup = false;
|
||||
bool isBroadcast = false;
|
||||
bool isRequestNeeded = false;
|
||||
bool isFake = false;
|
||||
bool isScam = false;
|
||||
bool isVerified = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] ChatInvite ParseInvite(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data) {
|
||||
auto participants = std::vector<InviteParticipant>();
|
||||
if (const auto list = data.vparticipants()) {
|
||||
participants.reserve(list->v.size());
|
||||
for (const auto &participant : list->v) {
|
||||
if (const auto user = session->data().processUser(participant)) {
|
||||
participants.push_back(InviteParticipant{ user });
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto photo = session->data().processPhoto(data.vphoto());
|
||||
return {
|
||||
.title = qs(data.vtitle()),
|
||||
.about = data.vabout().value_or_empty(),
|
||||
.photo = (photo->isNull() ? nullptr : photo.get()),
|
||||
.participantsCount = data.vparticipants_count().v,
|
||||
.participants = std::move(participants),
|
||||
.isPublic = data.is_public(),
|
||||
.isChannel = data.is_channel(),
|
||||
.isMegagroup = data.is_megagroup(),
|
||||
.isBroadcast = data.is_broadcast(),
|
||||
.isRequestNeeded = data.is_request_needed(),
|
||||
.isFake = data.is_fake(),
|
||||
.isScam = data.is_scam(),
|
||||
.isVerified = data.is_verified(),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Info::Profile::BadgeType BadgeForInvite(
|
||||
const ChatInvite &invite) {
|
||||
using Type = Info::Profile::BadgeType;
|
||||
return invite.isVerified
|
||||
? Type::Verified
|
||||
: invite.isScam
|
||||
? Type::Scam
|
||||
: invite.isFake
|
||||
? Type::Fake
|
||||
: Type::None;
|
||||
}
|
||||
|
||||
void SubmitChatInvite(
|
||||
base::weak_ptr<Window::SessionController> weak,
|
||||
not_null<Main::Session*> session,
|
||||
@@ -356,6 +419,207 @@ void ConfirmSubscriptionBox(
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
void ConfirmInviteBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite *invitePtr,
|
||||
ChannelData *invitePeekChannel,
|
||||
Fn<void()> submit) {
|
||||
auto invite = ParseInvite(session, *invitePtr);
|
||||
const auto isChannel = invite.isChannel && !invite.isMegagroup;
|
||||
const auto requestApprove = invite.isRequestNeeded;
|
||||
const auto count = invite.participantsCount;
|
||||
|
||||
struct State {
|
||||
std::shared_ptr<Data::PhotoMedia> photoMedia;
|
||||
std::unique_ptr<Ui::EmptyUserpic> photoEmpty;
|
||||
std::vector<InviteParticipant> participants;
|
||||
};
|
||||
const auto state = box->lifetime().make_state<State>();
|
||||
state->participants = std::move(invite.participants);
|
||||
|
||||
const auto status = [&] {
|
||||
return invitePeekChannel
|
||||
? tr::lng_channel_invite_private(tr::now)
|
||||
: (!state->participants.empty()
|
||||
&& int(state->participants.size()) < count)
|
||||
? tr::lng_group_invite_members(tr::now, lt_count, count)
|
||||
: (count > 0 && isChannel)
|
||||
? tr::lng_chat_status_subscribers(
|
||||
tr::now,
|
||||
lt_count_decimal,
|
||||
count)
|
||||
: (count > 0)
|
||||
? tr::lng_chat_status_members(tr::now, lt_count_decimal, count)
|
||||
: isChannel
|
||||
? tr::lng_channel_status(tr::now)
|
||||
: tr::lng_group_status(tr::now);
|
||||
}();
|
||||
|
||||
box->setNoContentMargin(true);
|
||||
box->setWidth(st::boxWideWidth);
|
||||
const auto content = box->verticalLayout();
|
||||
|
||||
Ui::AddSkip(content, st::confirmInvitePhotoTop);
|
||||
const auto userpic = content->add(
|
||||
object_ptr<Ui::RpWidget>(content),
|
||||
style::al_top);
|
||||
const auto photoSize = st::confirmInvitePhotoSize;
|
||||
userpic->resize(Size(photoSize));
|
||||
userpic->setNaturalWidth(photoSize);
|
||||
userpic->paintRequest(
|
||||
) | rpl::on_next([=, small = Data::PhotoSize::Small] {
|
||||
auto p = QPainter(userpic);
|
||||
if (state->photoMedia) {
|
||||
if (const auto image = state->photoMedia->image(small)) {
|
||||
p.drawPixmap(
|
||||
0,
|
||||
0,
|
||||
image->pix(
|
||||
Size(photoSize),
|
||||
{ .options = Images::Option::RoundCircle }));
|
||||
}
|
||||
} else if (state->photoEmpty) {
|
||||
state->photoEmpty->paintCircle(
|
||||
p,
|
||||
0,
|
||||
0,
|
||||
userpic->width(),
|
||||
photoSize);
|
||||
}
|
||||
}, userpic->lifetime());
|
||||
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
if (const auto photo = invite.photo) {
|
||||
state->photoMedia = photo->createMediaView();
|
||||
state->photoMedia->wanted(
|
||||
Data::PhotoSize::Small,
|
||||
Data::FileOrigin());
|
||||
if (!state->photoMedia->image(Data::PhotoSize::Small)) {
|
||||
session->downloaderTaskFinished(
|
||||
) | rpl::on_next([=] {
|
||||
userpic->update();
|
||||
}, userpic->lifetime());
|
||||
}
|
||||
} else {
|
||||
state->photoEmpty = std::make_unique<Ui::EmptyUserpic>(
|
||||
Ui::EmptyUserpic::UserpicColor(0),
|
||||
invite.title);
|
||||
}
|
||||
|
||||
Ui::AddSkip(content);
|
||||
const auto title = box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
invite.title,
|
||||
st::confirmInviteTitle),
|
||||
style::al_top);
|
||||
|
||||
const auto badgeType = BadgeForInvite(invite);
|
||||
if (badgeType != Info::Profile::BadgeType::None) {
|
||||
const auto badgeParent = title->parentWidget();
|
||||
const auto badge = box->lifetime().make_state<Info::Profile::Badge>(
|
||||
badgeParent,
|
||||
st::infoPeerBadge,
|
||||
session,
|
||||
rpl::single(Info::Profile::Badge::Content{ badgeType }),
|
||||
nullptr,
|
||||
[] { return false; });
|
||||
title->geometryValue(
|
||||
) | rpl::on_next([=](const QRect &r) {
|
||||
badge->move(r.x() + r.width(), r.y(), r.y() + r.height());
|
||||
}, title->lifetime());
|
||||
}
|
||||
|
||||
box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
status,
|
||||
st::confirmInviteStatus),
|
||||
style::al_top);
|
||||
|
||||
if (!invite.about.isEmpty()) {
|
||||
box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
invite.about,
|
||||
st::confirmInviteAbout),
|
||||
st::confirmInviteAboutPadding,
|
||||
style::al_top);
|
||||
}
|
||||
|
||||
if (requestApprove) {
|
||||
box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
(isChannel
|
||||
? tr::lng_group_request_about_channel(tr::now)
|
||||
: tr::lng_group_request_about(tr::now)),
|
||||
st::confirmInviteStatus),
|
||||
st::confirmInviteAboutRequestsPadding,
|
||||
style::al_top);
|
||||
}
|
||||
|
||||
if (!state->participants.empty()) {
|
||||
while (state->participants.size() > 4) {
|
||||
state->participants.pop_back();
|
||||
}
|
||||
const auto padding = (st::confirmInviteUsersWidth
|
||||
- 4 * st::confirmInviteUserPhotoSize) / 10;
|
||||
const auto userWidth = st::confirmInviteUserPhotoSize + 2 * padding;
|
||||
|
||||
auto strip = object_ptr<Ui::RpWidget>(content);
|
||||
const auto rawStrip = strip.data();
|
||||
rawStrip->resize(st::boxWideWidth, st::confirmInviteUserHeight);
|
||||
rawStrip->setNaturalWidth(st::boxWideWidth);
|
||||
|
||||
const auto shown = int(state->participants.size());
|
||||
const auto sumWidth = shown * userWidth;
|
||||
const auto baseLeft = (st::boxWideWidth - sumWidth) / 2;
|
||||
for (auto i = 0; i != shown; ++i) {
|
||||
const auto &participant = state->participants[i];
|
||||
const auto name = Ui::CreateChild<Ui::FlatLabel>(
|
||||
rawStrip,
|
||||
st::confirmInviteUserName);
|
||||
name->resizeToWidth(
|
||||
st::confirmInviteUserPhotoSize + padding);
|
||||
name->setText(participant.user->firstName.isEmpty()
|
||||
? participant.user->name()
|
||||
: participant.user->firstName);
|
||||
name->moveToLeft(
|
||||
baseLeft + i * userWidth + (padding / 2),
|
||||
st::confirmInviteUserNameTop - st::confirmInviteUserPhotoTop);
|
||||
}
|
||||
|
||||
rawStrip->paintRequest(
|
||||
) | rpl::on_next([=] {
|
||||
auto p = Painter(rawStrip);
|
||||
const auto total = int(state->participants.size());
|
||||
const auto totalWidth = total * userWidth;
|
||||
auto left = (rawStrip->width() - totalWidth) / 2;
|
||||
for (auto &participant : state->participants) {
|
||||
participant.user->paintUserpicLeft(
|
||||
p,
|
||||
participant.userpic,
|
||||
left + (userWidth - st::confirmInviteUserPhotoSize) / 2,
|
||||
0,
|
||||
rawStrip->width(),
|
||||
st::confirmInviteUserPhotoSize);
|
||||
left += userWidth;
|
||||
}
|
||||
}, rawStrip->lifetime());
|
||||
|
||||
Ui::AddSkip(content, st::boxPadding.bottom());
|
||||
content->add(std::move(strip), style::margins());
|
||||
}
|
||||
|
||||
box->addButton((requestApprove
|
||||
? tr::lng_group_request_to_join()
|
||||
: isChannel
|
||||
? tr::lng_profile_join_channel()
|
||||
: tr::lng_profile_join_group()), submit);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void CheckChatInvite(
|
||||
@@ -399,9 +663,10 @@ void CheckChatInvite(
|
||||
session,
|
||||
hash,
|
||||
&data))
|
||||
: strong->show(Box<ConfirmInviteBox>(
|
||||
: strong->show(Box(
|
||||
ConfirmInviteBox,
|
||||
session,
|
||||
data,
|
||||
&data,
|
||||
invitePeekChannel,
|
||||
[=] { SubmitChatInvite(weak, session, hash, isGroup); }));
|
||||
if (invitePeekChannel) {
|
||||
@@ -450,255 +715,3 @@ void CheckChatInvite(
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
struct ConfirmInviteBox::Participant {
|
||||
not_null<UserData*> user;
|
||||
Ui::PeerUserpicView userpic;
|
||||
};
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data,
|
||||
ChannelData *invitePeekChannel,
|
||||
Fn<void()> submit)
|
||||
: ConfirmInviteBox(
|
||||
session,
|
||||
Parse(session, data),
|
||||
invitePeekChannel,
|
||||
std::move(submit)) {
|
||||
}
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(
|
||||
not_null<Main::Session*> session,
|
||||
ChatInvite &&invite,
|
||||
ChannelData *invitePeekChannel,
|
||||
Fn<void()> submit)
|
||||
: _session(session)
|
||||
, _submit(std::move(submit))
|
||||
, _title(this, st::confirmInviteTitle)
|
||||
, _badge(std::make_unique<Info::Profile::Badge>(
|
||||
this,
|
||||
st::infoPeerBadge,
|
||||
_session,
|
||||
rpl::single(Info::Profile::Badge::Content{ BadgeForInvite(invite) }),
|
||||
nullptr,
|
||||
[=] { return false; }))
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _about(this, st::confirmInviteAbout)
|
||||
, _aboutRequests(this, st::confirmInviteStatus)
|
||||
, _participants(std::move(invite.participants))
|
||||
, _isChannel(invite.isChannel && !invite.isMegagroup)
|
||||
, _requestApprove(invite.isRequestNeeded) {
|
||||
const auto count = invite.participantsCount;
|
||||
const auto status = [&] {
|
||||
return invitePeekChannel
|
||||
? tr::lng_channel_invite_private(tr::now)
|
||||
: (!_participants.empty() && _participants.size() < count)
|
||||
? tr::lng_group_invite_members(tr::now, lt_count, count)
|
||||
: (count > 0 && _isChannel)
|
||||
? tr::lng_chat_status_subscribers(
|
||||
tr::now,
|
||||
lt_count_decimal,
|
||||
count)
|
||||
: (count > 0)
|
||||
? tr::lng_chat_status_members(tr::now, lt_count_decimal, count)
|
||||
: _isChannel
|
||||
? tr::lng_channel_status(tr::now)
|
||||
: tr::lng_group_status(tr::now);
|
||||
}();
|
||||
_title->setText(invite.title);
|
||||
_status->setText(status);
|
||||
if (!invite.about.isEmpty()) {
|
||||
_about->setText(invite.about);
|
||||
} else {
|
||||
_about.destroy();
|
||||
}
|
||||
if (_requestApprove) {
|
||||
_aboutRequests->setText(_isChannel
|
||||
? tr::lng_group_request_about_channel(tr::now)
|
||||
: tr::lng_group_request_about(tr::now));
|
||||
} else {
|
||||
_aboutRequests.destroy();
|
||||
}
|
||||
|
||||
if (invite.photo) {
|
||||
_photo = invite.photo->createMediaView();
|
||||
_photo->wanted(Data::PhotoSize::Small, Data::FileOrigin());
|
||||
if (!_photo->image(Data::PhotoSize::Small)) {
|
||||
_session->downloaderTaskFinished(
|
||||
) | rpl::on_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
}
|
||||
} else {
|
||||
_photoEmpty = std::make_unique<Ui::EmptyUserpic>(
|
||||
Ui::EmptyUserpic::UserpicColor(0),
|
||||
invite.title);
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmInviteBox::~ConfirmInviteBox() = default;
|
||||
|
||||
ConfirmInviteBox::ChatInvite ConfirmInviteBox::Parse(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data) {
|
||||
auto participants = std::vector<Participant>();
|
||||
if (const auto list = data.vparticipants()) {
|
||||
participants.reserve(list->v.size());
|
||||
for (const auto &participant : list->v) {
|
||||
if (const auto user = session->data().processUser(participant)) {
|
||||
participants.push_back(Participant{ user });
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto photo = session->data().processPhoto(data.vphoto());
|
||||
return {
|
||||
.title = qs(data.vtitle()),
|
||||
.about = data.vabout().value_or_empty(),
|
||||
.photo = (photo->isNull() ? nullptr : photo.get()),
|
||||
.participantsCount = data.vparticipants_count().v,
|
||||
.participants = std::move(participants),
|
||||
.isPublic = data.is_public(),
|
||||
.isChannel = data.is_channel(),
|
||||
.isMegagroup = data.is_megagroup(),
|
||||
.isBroadcast = data.is_broadcast(),
|
||||
.isRequestNeeded = data.is_request_needed(),
|
||||
.isFake = data.is_fake(),
|
||||
.isScam = data.is_scam(),
|
||||
.isVerified = data.is_verified(),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Info::Profile::BadgeType ConfirmInviteBox::BadgeForInvite(
|
||||
const ChatInvite &invite) {
|
||||
using Type = Info::Profile::BadgeType;
|
||||
return invite.isVerified
|
||||
? Type::Verified
|
||||
: invite.isScam
|
||||
? Type::Scam
|
||||
: invite.isFake
|
||||
? Type::Fake
|
||||
: Type::None;
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::prepare() {
|
||||
addButton(
|
||||
(_requestApprove
|
||||
? tr::lng_group_request_to_join()
|
||||
: _isChannel
|
||||
? tr::lng_profile_join_channel()
|
||||
: tr::lng_profile_join_group()),
|
||||
_submit);
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
|
||||
while (_participants.size() > 4) {
|
||||
_participants.pop_back();
|
||||
}
|
||||
|
||||
auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom();
|
||||
if (!_participants.empty()) {
|
||||
int skip = (st::confirmInviteUsersWidth - 4 * st::confirmInviteUserPhotoSize) / 5;
|
||||
int padding = skip / 2;
|
||||
_userWidth = (st::confirmInviteUserPhotoSize + 2 * padding);
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (st::boxWideWidth - sumWidth) / 2;
|
||||
for (const auto &participant : _participants) {
|
||||
auto name = new Ui::FlatLabel(this, st::confirmInviteUserName);
|
||||
name->resizeToWidth(st::confirmInviteUserPhotoSize + padding);
|
||||
name->setText(participant.user->firstName.isEmpty()
|
||||
? participant.user->name()
|
||||
: participant.user->firstName);
|
||||
name->moveToLeft(left + (padding / 2), st::confirmInviteUserNameTop);
|
||||
left += _userWidth;
|
||||
}
|
||||
|
||||
newHeight += st::confirmInviteUserHeight;
|
||||
}
|
||||
if (_about) {
|
||||
const auto padding = st::confirmInviteAboutPadding;
|
||||
_about->resizeToWidth(st::boxWideWidth - padding.left() - padding.right());
|
||||
newHeight += padding.top() + _about->height() + padding.bottom();
|
||||
}
|
||||
if (_aboutRequests) {
|
||||
const auto padding = st::confirmInviteAboutRequestsPadding;
|
||||
_aboutRequests->resizeToWidth(st::boxWideWidth - padding.left() - padding.right());
|
||||
newHeight += padding.top() + _aboutRequests->height() + padding.bottom();
|
||||
}
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
const auto padding = st::boxRowPadding;
|
||||
auto nameWidth = width() - padding.left() - padding.right();
|
||||
auto badgeWidth = 0;
|
||||
if (const auto widget = _badge->widget()) {
|
||||
badgeWidth = st::infoVerifiedCheckPosition.x() + widget->width();
|
||||
nameWidth -= badgeWidth;
|
||||
}
|
||||
_title->resizeToWidth(std::min(nameWidth, _title->textMaxWidth()));
|
||||
_title->moveToLeft(
|
||||
(width() - _title->width() - badgeWidth) / 2,
|
||||
st::confirmInviteTitleTop);
|
||||
const auto badgeLeft = _title->x() + _title->width();
|
||||
const auto badgeTop = _title->y();
|
||||
const auto badgeBottom = _title->y() + _title->height();
|
||||
_badge->move(badgeLeft, badgeTop, badgeBottom);
|
||||
|
||||
_status->move(
|
||||
(width() - _status->width()) / 2,
|
||||
st::confirmInviteStatusTop);
|
||||
auto bottom = _status->y()
|
||||
+ _status->height()
|
||||
+ st::boxPadding.bottom()
|
||||
+ (_participants.empty() ? 0 : st::confirmInviteUserHeight);
|
||||
if (_about) {
|
||||
const auto padding = st::confirmInviteAboutPadding;
|
||||
_about->move((width() - _about->width()) / 2, bottom + padding.top());
|
||||
bottom += padding.top() + _about->height() + padding.bottom();
|
||||
}
|
||||
if (_aboutRequests) {
|
||||
const auto padding = st::confirmInviteAboutRequestsPadding;
|
||||
_aboutRequests->move((width() - _aboutRequests->width()) / 2, bottom + padding.top());
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
Painter p(this);
|
||||
|
||||
if (_photo) {
|
||||
if (const auto image = _photo->image(Data::PhotoSize::Small)) {
|
||||
const auto size = st::confirmInvitePhotoSize;
|
||||
p.drawPixmap(
|
||||
(width() - size) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
image->pix(
|
||||
{ size, size },
|
||||
{ .options = Images::Option::RoundCircle }));
|
||||
}
|
||||
} else if (_photoEmpty) {
|
||||
_photoEmpty->paintCircle(
|
||||
p,
|
||||
(width() - st::confirmInvitePhotoSize) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
width(),
|
||||
st::confirmInvitePhotoSize);
|
||||
}
|
||||
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for (auto &participant : _participants) {
|
||||
participant.user->paintUserpicLeft(
|
||||
p,
|
||||
participant.userpic,
|
||||
left + (_userWidth - st::confirmInviteUserPhotoSize) / 2,
|
||||
st::confirmInviteUserPhotoTop,
|
||||
width(),
|
||||
st::confirmInviteUserPhotoSize);
|
||||
left += _userWidth;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user