Implement nice call link box.

This commit is contained in:
John Preston 2025-03-29 10:40:04 +05:00
parent 1d32e5267c
commit 5d5dda548a
5 changed files with 112 additions and 25 deletions

View file

@ -1490,7 +1490,7 @@ confcallLinkButton: RoundButton(defaultActiveButton) {
style: semiboldTextStyle;
}
confcallLinkBox: Box(defaultBox) {
buttonPadding: margins(22px, 11px, 22px, 64px);
buttonPadding: margins(12px, 11px, 24px, 96px);
buttonHeight: 42px;
button: confcallLinkButton;
shadowIgnoreTopSkip: true;
@ -1513,3 +1513,6 @@ confcallLinkCenteredText: FlatLabel(defaultFlatLabel) {
confcallLinkFooterOr: FlatLabel(confcallLinkCenteredText) {
textFg: windowSubTextFg;
}
confcallLinkFooterOrTop: 12px;
confcallLinkFooterOrSkip: 8px;
confcallLinkFooterOrLineTop: 9px;

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/base_platform_info.h"
#include "boxes/share_box.h"
#include "core/local_url_handlers.h"
#include "data/data_group_call.h"
#include "info/bot/starref/info_bot_starref_common.h"
#include "ui/boxes/boost_box.h"
@ -130,19 +131,46 @@ void ShowConferenceCallLinkBox(
FastShareLink(controller, link);
};
preview->setClickedCallback(copyCallback);
[[maybe_unused]] const auto copy = box->addButton(
tr::lng_group_invite_copy(),
copyCallback,
st::confcallLinkCopyButton);
[[maybe_unused]] const auto share = box->addButton(
tr::lng_group_invite_share(),
shareCallback,
st::confcallLinkShareButton);
[[maybe_unused]] const auto copy = box->addButton(
tr::lng_group_invite_copy(),
copyCallback,
st::confcallLinkCopyButton);
rpl::combine(
box->widthValue(),
copy->widthValue(),
share->widthValue()
) | rpl::start_with_next([=] {
const auto width = st::boxWideWidth;
const auto padding = st::confcallLinkBox.buttonPadding;
const auto available = width - 2 * padding.right();
const auto buttonWidth = (available - padding.left()) / 2;
copy->resizeToWidth(buttonWidth);
share->resizeToWidth(buttonWidth);
copy->moveToLeft(padding.right(), copy->y(), width);
share->moveToRight(padding.right(), share->y(), width);
}, box->lifetime());
const auto sep = Ui::CreateChild<Ui::FlatLabel>(
copy->parentWidget(),
tr::lng_confcall_link_or(),
st::confcallLinkFooterOr);
sep->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(sep);
const auto text = sep->textMaxWidth();
const auto white = (sep->width() - 2 * text) / 2;
const auto line = st::lineWidth;
const auto top = st::confcallLinkFooterOrLineTop;
const auto fg = st::windowSubTextFg->b;
p.setOpacity(0.4);
p.fillRect(0, top, white, line, fg);
p.fillRect(sep->width() - white, top, white, line, fg);
}, sep->lifetime());
const auto footer = Ui::CreateChild<Ui::FlatLabel>(
copy->parentWidget(),
tr::lng_confcall_link_join(
@ -154,22 +182,29 @@ void ShowConferenceCallLinkBox(
Ui::Text::WithEntities),
st::confcallLinkCenteredText);
footer->setTryMakeSimilarLines(true);
footer->setClickHandlerFilter([=](const auto &...) {
const auto local = Core::TryConvertUrlToLocal(link);
controller->resolveConferenceCall(
local,
crl::guard(box, [=](bool ok) { if (ok) box->closeBox(); }),
true);
return false;
});
copy->geometryValue() | rpl::start_with_next([=](QRect geometry) {
const auto width = st::boxWideWidth
- st::boxRowPadding.left()
- st::boxRowPadding.right();
footer->resizeToWidth(width);
const auto &st = box->getDelegate()->style();
const auto top = geometry.y() + geometry.height();
const auto available = st.buttonPadding.bottom();
const auto footerHeight = sep->height() + footer->height();
const auto skip = (available - footerHeight) / 2;
const auto top = geometry.y()
+ geometry.height()
+ st::confcallLinkFooterOrTop;
sep->resizeToWidth(width / 2);
sep->move(
st::boxRowPadding.left() + (width - sep->width()) / 2,
top + skip);
top);
footer->moveToLeft(
st::boxRowPadding.left(),
top + skip + sep->height());
top + sep->height() + st::confcallLinkFooterOrSkip);
}, footer->lifetime());
}));
}

View file

@ -195,7 +195,6 @@ void Call::apply(int subchain, const Block &last) {
});
if (subchain) {
auto &entry = _subchains[subchain];
auto result = tde2e_api::call_receive_inbound_message(
libId(),
Slice(last.data));

View file

@ -840,17 +840,42 @@ void SessionNavigation::resolveCollectible(
}).send();
}
void SessionNavigation::resolveConferenceCall(const QString &slug) {
resolveConferenceCall(slug, 0);
}
void SessionNavigation::resolveConferenceCall(MsgId inviteMsgId) {
resolveConferenceCall(QString(), inviteMsgId);
void SessionNavigation::resolveConferenceCall(
QString slug,
Fn<void(bool)> finished,
bool skipConfirm) {
resolveConferenceCall(
std::move(slug),
0,
std::move(finished),
skipConfirm);
}
void SessionNavigation::resolveConferenceCall(
const QString &slug,
MsgId inviteMsgId) {
MsgId inviteMsgId,
Fn<void(bool)> finished,
bool skipConfirm) {
resolveConferenceCall({}, inviteMsgId, std::move(finished), skipConfirm);
}
void SessionNavigation::resolveConferenceCall(
QString slug,
MsgId inviteMsgId,
Fn<void(bool)> finished,
bool skipConfirm) {
// Accept tg://call?slug= links as well.
const auto parts1 = QStringView(slug).split('#');
if (!parts1.isEmpty()) {
const auto parts2 = parts1.front().split('&');
if (!parts2.isEmpty()) {
const auto parts3 = parts2.front().split(u"slug="_q);
if (parts3.size() > 1) {
slug = parts3.back().toString();
}
}
}
_conferenceCallResolveFinished = std::move(finished);
if (_conferenceCallSlug == slug
&& _conferenceCallInviteMsgId == inviteMsgId) {
return;
@ -869,7 +894,7 @@ void SessionNavigation::resolveConferenceCall(
_conferenceCallRequestId = 0;
const auto slug = base::take(_conferenceCallSlug);
const auto inviteMsgId = base::take(_conferenceCallInviteMsgId);
const auto finished = base::take(_conferenceCallResolveFinished);
result.data().vcall().match([&](const auto &data) {
const auto call = std::make_shared<Data::GroupCall>(
session().user(),
@ -888,6 +913,13 @@ void SessionNavigation::resolveConferenceCall(
.joinMessageId = inviteMsgId,
});
};
if (skipConfirm) {
join();
if (finished) {
finished(true);
}
return;
}
const auto box = uiShow()->show(Box(
Calls::Group::ConferenceCallJoinConfirm,
call,
@ -899,11 +931,18 @@ void SessionNavigation::resolveConferenceCall(
)).send();
}
}, box->lifetime());
if (finished) {
finished(true);
}
});
}).fail([=] {
_conferenceCallRequestId = 0;
_conferenceCallSlug = QString();
const auto finished = base::take(_conferenceCallResolveFinished);
showToast(tr::lng_group_invite_bad_link(tr::now));
if (finished) {
finished(false);
}
}).send();
}

View file

@ -264,8 +264,14 @@ public:
PeerId ownerId,
const QString &entity,
Fn<void(QString)> fail = nullptr);
void resolveConferenceCall(const QString &slug);
void resolveConferenceCall(MsgId inviteMsgId);
void resolveConferenceCall(
QString slug,
Fn<void(bool)> finished = nullptr,
bool skipConfirm = false);
void resolveConferenceCall(
MsgId inviteMsgId,
Fn<void(bool)> finished = nullptr,
bool skipConfirm = false);
base::weak_ptr<Ui::Toast::Instance> showToast(
Ui::Toast::Config &&config);
@ -292,7 +298,11 @@ private:
void resolveChannelById(
ChannelId channelId,
Fn<void(not_null<ChannelData*>)> done);
void resolveConferenceCall(const QString &slug, MsgId inviteMsgId);
void resolveConferenceCall(
QString slug,
MsgId inviteMsgId,
Fn<void(bool)> finished,
bool skipConfirm);
void resolveDone(
const MTPcontacts_ResolvedPeer &result,
@ -334,6 +344,7 @@ private:
QString _conferenceCallSlug;
MsgId _conferenceCallInviteMsgId;
Fn<void(bool)> _conferenceCallResolveFinished;
mtpRequestId _conferenceCallRequestId = 0;
};