mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Migrate games to AttachWebView.
This commit is contained in:
parent
78093173a9
commit
6effac7915
11 changed files with 223 additions and 223 deletions
|
@ -127,11 +127,7 @@ void SendBotCallbackData(
|
|||
UrlClickHandler::Open(link);
|
||||
return;
|
||||
}
|
||||
const auto scoreLink = AppendShareGameScoreUrl(
|
||||
session,
|
||||
link,
|
||||
item->fullId());
|
||||
BotGameUrlClickHandler(bot, scoreLink).onClick({
|
||||
BotGameUrlClickHandler(bot, link).onClick({
|
||||
Qt::LeftButton,
|
||||
QVariant::fromValue(ClickHandlerContext{
|
||||
.itemId = item->fullId(),
|
||||
|
|
|
@ -1409,55 +1409,6 @@ std::vector<not_null<Data::Thread*>> ShareBox::Inner::selected() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
QString AppendShareGameScoreUrl(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &url,
|
||||
const FullMsgId &fullId) {
|
||||
auto shareHashData = QByteArray(0x20, Qt::Uninitialized);
|
||||
auto shareHashDataInts = reinterpret_cast<uint64*>(shareHashData.data());
|
||||
const auto peer = fullId.peer
|
||||
? session->data().peerLoaded(fullId.peer)
|
||||
: static_cast<PeerData*>(nullptr);
|
||||
const auto channelAccessHash = uint64((peer && peer->isChannel())
|
||||
? peer->asChannel()->access
|
||||
: 0);
|
||||
shareHashDataInts[0] = session->userId().bare;
|
||||
shareHashDataInts[1] = fullId.peer.value;
|
||||
shareHashDataInts[2] = uint64(fullId.msg.bare);
|
||||
shareHashDataInts[3] = channelAccessHash;
|
||||
|
||||
// Count SHA1() of data.
|
||||
auto key128Size = 0x10;
|
||||
auto shareHashEncrypted = QByteArray(key128Size + shareHashData.size(), Qt::Uninitialized);
|
||||
hashSha1(shareHashData.constData(), shareHashData.size(), shareHashEncrypted.data());
|
||||
|
||||
//// Mix in channel access hash to the first 64 bits of SHA1 of data.
|
||||
//*reinterpret_cast<uint64*>(shareHashEncrypted.data()) ^= channelAccessHash;
|
||||
|
||||
// Encrypt data.
|
||||
if (!session->local().encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
|
||||
return url;
|
||||
}
|
||||
|
||||
auto shareHash = shareHashEncrypted.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
auto shareUrl = u"tg://share_game_score?hash="_q + QString::fromLatin1(shareHash);
|
||||
|
||||
auto shareComponent = u"tgShareScoreUrl="_q + qthelp::url_encode(shareUrl);
|
||||
|
||||
auto hashPosition = url.indexOf('#');
|
||||
if (hashPosition < 0) {
|
||||
return url + '#' + shareComponent;
|
||||
}
|
||||
auto hash = url.mid(hashPosition + 1);
|
||||
if (hash.indexOf('=') >= 0 || hash.indexOf('?') >= 0) {
|
||||
return url + '&' + shareComponent;
|
||||
}
|
||||
if (!hash.isEmpty()) {
|
||||
return url + '?' + shareComponent;
|
||||
}
|
||||
return url + shareComponent;
|
||||
}
|
||||
|
||||
ChatHelpers::ForwardedMessagePhraseArgs CreateForwardedMessagePhraseArgs(
|
||||
const std::vector<not_null<Data::Thread*>> &result,
|
||||
const MessageIdsList &msgIds) {
|
||||
|
@ -1612,9 +1563,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
|||
}
|
||||
|
||||
void FastShareMessage(
|
||||
not_null<Window::SessionController*> controller,
|
||||
std::shared_ptr<Main::SessionShow> show,
|
||||
not_null<HistoryItem*> item) {
|
||||
const auto show = controller->uiShow();
|
||||
const auto history = item->history();
|
||||
const auto owner = &history->owner();
|
||||
const auto session = &history->session();
|
||||
|
@ -1643,7 +1593,7 @@ void FastShareMessage(
|
|||
}
|
||||
if (item->hasDirectLink()) {
|
||||
using namespace HistoryView;
|
||||
CopyPostLink(controller, item->fullId(), Context::History);
|
||||
CopyPostLink(show, item->fullId(), Context::History);
|
||||
} else if (const auto bot = item->getMessageBot()) {
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto game = media->game()) {
|
||||
|
@ -1675,23 +1625,27 @@ void FastShareMessage(
|
|||
auto copyLinkCallback = canCopyLink
|
||||
? Fn<void()>(std::move(copyCallback))
|
||||
: Fn<void()>();
|
||||
controller->show(
|
||||
Box<ShareBox>(ShareBox::Descriptor{
|
||||
.session = session,
|
||||
.copyCallback = std::move(copyLinkCallback),
|
||||
.submitCallback = ShareBox::DefaultForwardCallback(
|
||||
show,
|
||||
history,
|
||||
msgIds),
|
||||
.filterCallback = std::move(filterCallback),
|
||||
.forwardOptions = {
|
||||
.sendersCount = ItemsForwardSendersCount(items),
|
||||
.captionsCount = ItemsForwardCaptionsCount(items),
|
||||
.show = !hasOnlyForcedForwardedInfo,
|
||||
},
|
||||
.premiumRequiredError = SharePremiumRequiredError(),
|
||||
}),
|
||||
Ui::LayerOption::CloseOther);
|
||||
show->show(Box<ShareBox>(ShareBox::Descriptor{
|
||||
.session = session,
|
||||
.copyCallback = std::move(copyLinkCallback),
|
||||
.submitCallback = ShareBox::DefaultForwardCallback(
|
||||
show,
|
||||
history,
|
||||
msgIds),
|
||||
.filterCallback = std::move(filterCallback),
|
||||
.forwardOptions = {
|
||||
.sendersCount = ItemsForwardSendersCount(items),
|
||||
.captionsCount = ItemsForwardCaptionsCount(items),
|
||||
.show = !hasOnlyForcedForwardedInfo,
|
||||
},
|
||||
.premiumRequiredError = SharePremiumRequiredError(),
|
||||
}), Ui::LayerOption::CloseOther);
|
||||
}
|
||||
|
||||
void FastShareMessage(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<HistoryItem*> item) {
|
||||
FastShareMessage(controller->uiShow(), item);
|
||||
}
|
||||
|
||||
void FastShareLink(
|
||||
|
@ -1793,111 +1747,3 @@ auto SharePremiumRequiredError()
|
|||
-> Fn<RecipientPremiumRequiredError(not_null<UserData*>)> {
|
||||
return WritePremiumRequiredError;
|
||||
}
|
||||
|
||||
void ShareGameScoreByHash(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &hash) {
|
||||
auto &session = controller->session();
|
||||
auto key128Size = 0x10;
|
||||
|
||||
auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
if (hashEncrypted.size() <= key128Size || (hashEncrypted.size() != key128Size + 0x20)) {
|
||||
controller->show(
|
||||
Ui::MakeInformBox(tr::lng_confirm_phone_link_invalid()),
|
||||
Ui::LayerOption::CloseOther);
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrypt data.
|
||||
auto hashData = QByteArray(hashEncrypted.size() - key128Size, Qt::Uninitialized);
|
||||
if (!session.local().decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size, hashEncrypted.constData())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Count SHA1() of data.
|
||||
char dataSha1[20] = { 0 };
|
||||
hashSha1(hashData.constData(), hashData.size(), dataSha1);
|
||||
|
||||
//// Mix out channel access hash from the first 64 bits of SHA1 of data.
|
||||
//auto channelAccessHash = *reinterpret_cast<uint64*>(hashEncrypted.data()) ^ *reinterpret_cast<uint64*>(dataSha1);
|
||||
|
||||
//// Check next 64 bits of SHA1() of data.
|
||||
//auto skipSha1Part = sizeof(channelAccessHash);
|
||||
//if (memcmp(dataSha1 + skipSha1Part, hashEncrypted.constData() + skipSha1Part, key128Size - skipSha1Part) != 0) {
|
||||
// Ui::show(Box<Ui::InformBox>(tr::lng_share_wrong_user(tr::now)));
|
||||
// return;
|
||||
//}
|
||||
|
||||
// Check 128 bits of SHA1() of data.
|
||||
if (memcmp(dataSha1, hashEncrypted.constData(), key128Size) != 0) {
|
||||
controller->show(
|
||||
Ui::MakeInformBox(tr::lng_share_wrong_user()),
|
||||
Ui::LayerOption::CloseOther);
|
||||
return;
|
||||
}
|
||||
|
||||
auto hashDataInts = reinterpret_cast<uint64*>(hashData.data());
|
||||
if (hashDataInts[0] != session.userId().bare) {
|
||||
controller->show(
|
||||
Ui::MakeInformBox(tr::lng_share_wrong_user()),
|
||||
Ui::LayerOption::CloseOther);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto peerId = PeerId(hashDataInts[1]);
|
||||
const auto channelAccessHash = hashDataInts[3];
|
||||
if (!peerIsChannel(peerId) && channelAccessHash) {
|
||||
// If there is no channel id, there should be no channel access_hash.
|
||||
controller->show(
|
||||
Ui::MakeInformBox(tr::lng_share_wrong_user()),
|
||||
Ui::LayerOption::CloseOther);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto msgId = MsgId(int64(hashDataInts[2]));
|
||||
if (const auto item = session.data().message(peerId, msgId)) {
|
||||
FastShareMessage(controller, item);
|
||||
} else {
|
||||
const auto weak = base::make_weak(controller);
|
||||
const auto resolveMessageAndShareScore = crl::guard(weak, [=](
|
||||
PeerData *peer) {
|
||||
auto done = crl::guard(weak, [=] {
|
||||
const auto item = weak->session().data().message(
|
||||
peerId,
|
||||
msgId);
|
||||
if (item) {
|
||||
FastShareMessage(weak.get(), item);
|
||||
} else {
|
||||
weak->show(
|
||||
Ui::MakeInformBox(tr::lng_edit_deleted()),
|
||||
Ui::LayerOption::CloseOther);
|
||||
}
|
||||
});
|
||||
auto &api = weak->session().api();
|
||||
api.requestMessageData(peer, msgId, std::move(done));
|
||||
});
|
||||
|
||||
const auto peer = peerIsChannel(peerId)
|
||||
? controller->session().data().peerLoaded(peerId)
|
||||
: nullptr;
|
||||
if (peer || !peerIsChannel(peerId)) {
|
||||
resolveMessageAndShareScore(peer);
|
||||
} else {
|
||||
const auto owner = &controller->session().data();
|
||||
controller->session().api().request(MTPchannels_GetChannels(
|
||||
MTP_vector<MTPInputChannel>(
|
||||
1,
|
||||
MTP_inputChannel(
|
||||
MTP_long(peerToChannel(peerId).bare),
|
||||
MTP_long(channelAccessHash)))
|
||||
)).done([=](const MTPmessages_Chats &result) {
|
||||
result.match([&](const auto &data) {
|
||||
owner->processChats(data.vchats());
|
||||
});
|
||||
if (const auto peer = owner->peerLoaded(peerId)) {
|
||||
resolveMessageAndShareScore(peer);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,13 +59,11 @@ class SlideWrap;
|
|||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
||||
QString AppendShareGameScoreUrl(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &url,
|
||||
const FullMsgId &fullId);
|
||||
void ShareGameScoreByHash(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &hash);
|
||||
class ShareBox;
|
||||
|
||||
void FastShareMessage(
|
||||
std::shared_ptr<Main::SessionShow> show,
|
||||
not_null<HistoryItem*> item);
|
||||
void FastShareMessage(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<HistoryItem*> item);
|
||||
|
|
|
@ -20,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/history_item.h"
|
||||
#include "inline_bots/bot_attach_web_view.h"
|
||||
#include "data/data_game.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "window/window_controller.h"
|
||||
|
@ -171,23 +173,40 @@ void BotGameUrlClickHandler::onClick(ClickContext context) const {
|
|||
if (Core::InternalPassportLink(url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto open = [=] {
|
||||
const auto openLink = [=] {
|
||||
UrlClickHandler::Open(url, context.other);
|
||||
};
|
||||
if (url.startsWith(u"tg://"_q, Qt::CaseInsensitive)) {
|
||||
open();
|
||||
} else if (!_bot
|
||||
|| _bot->isVerified()
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
const auto weakController = my.sessionWindow;
|
||||
const auto controller = weakController.get();
|
||||
const auto item = controller
|
||||
? controller->session().data().message(my.itemId)
|
||||
: nullptr;
|
||||
const auto media = item ? item->media() : nullptr;
|
||||
const auto game = media ? media->game() : nullptr;
|
||||
if (url.startsWith(u"tg://"_q, Qt::CaseInsensitive) || !_bot || !game) {
|
||||
openLink();
|
||||
}
|
||||
const auto bot = _bot;
|
||||
const auto title = game->title;
|
||||
const auto itemId = my.itemId;
|
||||
const auto openGame = [=] {
|
||||
bot->session().attachWebView().showGame({
|
||||
.bot = bot,
|
||||
.context = itemId,
|
||||
.url = url,
|
||||
.title = title,
|
||||
});
|
||||
};
|
||||
if (_bot->isVerified()
|
||||
|| _bot->session().local().isBotTrustedOpenGame(_bot->id)) {
|
||||
open();
|
||||
openGame();
|
||||
} else {
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
const auto callback = [=, bot = _bot](Fn<void()> close) {
|
||||
close();
|
||||
bot->session().local().markBotTrustedOpenGame(bot->id);
|
||||
open();
|
||||
openGame();
|
||||
};
|
||||
controller->show(Ui::MakeConfirmBox({
|
||||
.text = tr::lng_allow_bot_pass(
|
||||
|
|
|
@ -327,21 +327,6 @@ bool ConfirmPhone(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ShareGameScore(
|
||||
Window::SessionController *controller,
|
||||
const Match &match,
|
||||
const QVariant &context) {
|
||||
if (!controller) {
|
||||
return false;
|
||||
}
|
||||
const auto params = url_parse_params(
|
||||
match->captured(1),
|
||||
qthelp::UrlParamNameTransform::ToLower);
|
||||
ShareGameScoreByHash(controller, params.value(u"hash"_q));
|
||||
controller->window().activate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplySocksProxy(
|
||||
Window::SessionController *controller,
|
||||
const Match &match,
|
||||
|
@ -1230,10 +1215,6 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
|||
u"^confirmphone/?\\?(.+)(#|$)"_q,
|
||||
ConfirmPhone
|
||||
},
|
||||
{
|
||||
u"^share_game_score/?\\?(.+)(#|$)"_q,
|
||||
ShareGameScore
|
||||
},
|
||||
{
|
||||
u"^socks/?\\?(.+)(#|$)"_q,
|
||||
ApplySocksProxy
|
||||
|
|
|
@ -1284,7 +1284,14 @@ void CopyPostLink(
|
|||
not_null<Window::SessionController*> controller,
|
||||
FullMsgId itemId,
|
||||
Context context) {
|
||||
const auto item = controller->session().data().message(itemId);
|
||||
CopyPostLink(controller->uiShow(), itemId, context);
|
||||
}
|
||||
|
||||
void CopyPostLink(
|
||||
std::shared_ptr<Main::SessionShow> show,
|
||||
FullMsgId itemId,
|
||||
Context context) {
|
||||
const auto item = show->session().data().message(itemId);
|
||||
if (!item || !item->hasDirectLink()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1311,7 +1318,7 @@ void CopyPostLink(
|
|||
return channel->hasUsername();
|
||||
}();
|
||||
|
||||
controller->showToast(isPublicLink
|
||||
show->showToast(isPublicLink
|
||||
? tr::lng_channel_public_link_copied(tr::now)
|
||||
: tr::lng_context_about_private_link(tr::now));
|
||||
}
|
||||
|
|
|
@ -61,6 +61,10 @@ void CopyPostLink(
|
|||
not_null<Window::SessionController*> controller,
|
||||
FullMsgId itemId,
|
||||
Context context);
|
||||
void CopyPostLink(
|
||||
std::shared_ptr<Main::SessionShow> show,
|
||||
FullMsgId itemId,
|
||||
Context context);
|
||||
void CopyStoryLink(
|
||||
std::shared_ptr<Main::SessionShow> show,
|
||||
FullStoryId storyId);
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_blocked_peers.h"
|
||||
#include "api/api_common.h"
|
||||
#include "base/qthelp_url.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "data/data_bot_app.h"
|
||||
#include "data/data_changes.h"
|
||||
|
@ -802,6 +803,16 @@ void AttachWebView::botInvokeCustomMethod(
|
|||
}).send();
|
||||
}
|
||||
|
||||
void AttachWebView::botShareGameScore() {
|
||||
if (!_panel || !_gameContext) {
|
||||
return;
|
||||
} else if (const auto item = _session->data().message(_gameContext)) {
|
||||
FastShareMessage(uiShow(), item);
|
||||
} else {
|
||||
_panel->showToast({ tr::lng_message_not_found(tr::now) });
|
||||
}
|
||||
}
|
||||
|
||||
void AttachWebView::botClose() {
|
||||
crl::on_main(this, [=] { cancel(); });
|
||||
}
|
||||
|
@ -1547,6 +1558,7 @@ void AttachWebView::show(
|
|||
_lastShownUrl = url;
|
||||
_lastShownQueryId = queryId;
|
||||
_lastShownButtonText = buttonText;
|
||||
_gameContext = {};
|
||||
base::take(_panel);
|
||||
_catchingCancelInShowCall = true;
|
||||
_panel = Ui::BotWebView::Show({
|
||||
|
@ -1562,6 +1574,24 @@ void AttachWebView::show(
|
|||
started(queryId);
|
||||
}
|
||||
|
||||
void AttachWebView::showGame(ShowGameParams &¶ms) {
|
||||
ActiveWebViews().emplace(this);
|
||||
|
||||
base::take(_panel);
|
||||
_gameContext = params.context;
|
||||
|
||||
_catchingCancelInShowCall = true;
|
||||
_panel = Ui::BotWebView::Show({
|
||||
.url = params.url,
|
||||
.storageId = _session->local().resolveStorageIdBots(),
|
||||
.title = rpl::single(params.title),
|
||||
.bottom = rpl::single('@' + params.bot->username()),
|
||||
.delegate = static_cast<Ui::BotWebView::Delegate*>(this),
|
||||
.menuButtons = Ui::BotWebView::MenuButton::ShareGame,
|
||||
});
|
||||
_catchingCancelInShowCall = false;
|
||||
}
|
||||
|
||||
void AttachWebView::started(uint64 queryId) {
|
||||
Expects(_bot != nullptr);
|
||||
Expects(_context != nullptr);
|
||||
|
@ -1601,6 +1631,57 @@ void AttachWebView::started(uint64 queryId) {
|
|||
}, _panel->lifetime());
|
||||
}
|
||||
|
||||
std::shared_ptr<Main::SessionShow> AttachWebView::uiShow() {
|
||||
class Show final : public Main::SessionShow {
|
||||
public:
|
||||
explicit Show(not_null<AttachWebView*> that) : _that(that) {
|
||||
}
|
||||
|
||||
void showOrHideBoxOrLayer(
|
||||
std::variant<
|
||||
v::null_t,
|
||||
object_ptr<Ui::BoxContent>,
|
||||
std::unique_ptr<Ui::LayerWidget>> &&layer,
|
||||
Ui::LayerOptions options,
|
||||
anim::type animated) const override {
|
||||
using UniqueLayer = std::unique_ptr<Ui::LayerWidget>;
|
||||
using ObjectBox = object_ptr<Ui::BoxContent>;
|
||||
const auto panel = _that ? _that->_panel.get() : nullptr;
|
||||
if (auto layerWidget = std::get_if<UniqueLayer>(&layer)) {
|
||||
Unexpected("Layers in AttachWebView are not implemented.");
|
||||
} else if (auto box = std::get_if<ObjectBox>(&layer)) {
|
||||
if (panel) {
|
||||
panel->showBox(std::move(*box), options, animated);
|
||||
}
|
||||
} else if (panel) {
|
||||
panel->hideLayer(animated);
|
||||
}
|
||||
}
|
||||
[[nodiscard]] not_null<QWidget*> toastParent() const override {
|
||||
const auto panel = _that ? _that->_panel.get() : nullptr;
|
||||
|
||||
Ensures(panel != nullptr);
|
||||
return panel->toastParent();
|
||||
}
|
||||
[[nodiscard]] bool valid() const override {
|
||||
return _that && (_that->_panel != nullptr);
|
||||
}
|
||||
operator bool() const override {
|
||||
return valid();
|
||||
}
|
||||
|
||||
[[nodiscard]] Main::Session &session() const override {
|
||||
Expects(_that.get() != nullptr);
|
||||
return *_that->_session;
|
||||
}
|
||||
|
||||
private:
|
||||
const base::weak_ptr<AttachWebView> _that;
|
||||
|
||||
};
|
||||
return std::make_shared<Show>(this);
|
||||
}
|
||||
|
||||
void AttachWebView::showToast(
|
||||
const QString &text,
|
||||
Window::SessionController *controller) {
|
||||
|
|
|
@ -29,6 +29,7 @@ class Panel;
|
|||
|
||||
namespace Main {
|
||||
class Session;
|
||||
class SessionShow;
|
||||
} // namespace Main
|
||||
|
||||
namespace Window {
|
||||
|
@ -155,12 +156,21 @@ public:
|
|||
[[nodiscard]] std::optional<Api::SendAction> lookupLastAction(
|
||||
const QString &url) const;
|
||||
|
||||
struct ShowGameParams {
|
||||
not_null<UserData*> bot;
|
||||
FullMsgId context;
|
||||
QString url;
|
||||
QString title;
|
||||
};
|
||||
void showGame(ShowGameParams &¶ms);
|
||||
|
||||
[[nodiscard]] std::shared_ptr<Main::SessionShow> uiShow();
|
||||
|
||||
static void ClearAll();
|
||||
|
||||
private:
|
||||
struct Context;
|
||||
|
||||
|
||||
Webview::ThemeParams botThemeParams() override;
|
||||
bool botHandleLocalUri(QString uri, bool keepOpen) override;
|
||||
void botHandleInvoice(QString slug) override;
|
||||
|
@ -176,6 +186,7 @@ private:
|
|||
void botSharePhone(Fn<void(bool shared)> callback) override;
|
||||
void botInvokeCustomMethod(
|
||||
Ui::BotWebView::CustomMethodRequest request) override;
|
||||
void botShareGameScore() override;
|
||||
void botClose() override;
|
||||
|
||||
[[nodiscard]] static Context LookupContext(
|
||||
|
@ -271,6 +282,8 @@ private:
|
|||
rpl::event_stream<> _attachBotsUpdates;
|
||||
base::flat_set<not_null<UserData*>> _disclaimerAccepted;
|
||||
|
||||
FullMsgId _gameContext;
|
||||
|
||||
std::unique_ptr<Ui::BotWebView::Panel> _panel;
|
||||
bool _catchingCancelInShowCall = false;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "webview/webview_interface.h"
|
||||
#include "base/debug_log.h"
|
||||
#include "base/invoke_queued.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "styles/style_payments.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
|
@ -34,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtCore/QJsonArray>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
namespace Ui::BotWebView {
|
||||
namespace {
|
||||
|
@ -373,6 +375,13 @@ Panel::~Panel() {
|
|||
|
||||
void Panel::requestActivate() {
|
||||
_widget->showAndActivate();
|
||||
if (const auto widget = _webview ? _webview->window.widget() : nullptr) {
|
||||
InvokeQueued(widget, [=] {
|
||||
if (widget->isVisible()) {
|
||||
_webview->window.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::toggleProgress(bool shown) {
|
||||
|
@ -527,9 +536,15 @@ bool Panel::showWebview(
|
|||
_webview->window.navigate(url);
|
||||
}
|
||||
}, &st::menuIconRestore);
|
||||
callback(tr::lng_bot_terms(tr::now), [=] {
|
||||
File::OpenUrl(tr::lng_mini_apps_tos_url(tr::now));
|
||||
}, &st::menuIconGroupLog);
|
||||
if (_menuButtons & MenuButton::ShareGame) {
|
||||
callback(tr::lng_iv_share(tr::now), [=] {
|
||||
_delegate->botShareGameScore();
|
||||
}, &st::menuIconShare);
|
||||
} else {
|
||||
callback(tr::lng_bot_terms(tr::now), [=] {
|
||||
File::OpenUrl(tr::lng_mini_apps_tos_url(tr::now));
|
||||
}, &st::menuIconGroupLog);
|
||||
}
|
||||
const auto main = (_menuButtons & MenuButton::RemoveFromMainMenu);
|
||||
if (main || (_menuButtons & MenuButton::RemoveFromMenu)) {
|
||||
const auto handler = [=] {
|
||||
|
@ -691,6 +706,8 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
|||
requestClipboardText(arguments);
|
||||
} else if (command == "web_app_set_header_color") {
|
||||
processHeaderColor(arguments);
|
||||
} else if (command == "share_score") {
|
||||
_delegate->botShareGameScore();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -722,6 +739,17 @@ postEvent: function(eventType, eventData) {
|
|||
|
||||
setupProgressGeometry();
|
||||
|
||||
base::qt_signal_producer(
|
||||
_widget->window()->windowHandle(),
|
||||
&QWindow::activeChanged
|
||||
) | rpl::filter([=] {
|
||||
return _webview && _widget->window()->windowHandle()->isActive();
|
||||
}) | rpl::start_with_next([=] {
|
||||
if (_webview && !_webview->window.widget()->isHidden()) {
|
||||
_webview->window.focus();
|
||||
}
|
||||
}, _webview->lifetime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1207,6 +1235,13 @@ void Panel::updateFooterHeight() {
|
|||
}
|
||||
|
||||
void Panel::showBox(object_ptr<BoxContent> box) {
|
||||
showBox(std::move(box), LayerOption::KeepOther, anim::type::normal);
|
||||
}
|
||||
|
||||
void Panel::showBox(
|
||||
object_ptr<BoxContent> box,
|
||||
LayerOptions options,
|
||||
anim::type animated) {
|
||||
if (const auto widget = _webview ? _webview->window.widget() : nullptr) {
|
||||
const auto hideNow = !widget->isHidden();
|
||||
if (hideNow || _webview->lastHidingBox) {
|
||||
|
@ -1220,10 +1255,12 @@ void Panel::showBox(object_ptr<BoxContent> box) {
|
|||
&& widget->isHidden()
|
||||
&& _webview->lastHidingBox == raw) {
|
||||
widget->show();
|
||||
_webviewBottom->show();
|
||||
}
|
||||
}, _webview->lifetime);
|
||||
if (hideNow) {
|
||||
widget->hide();
|
||||
_webviewBottom->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1237,6 +1274,14 @@ void Panel::showToast(TextWithEntities &&text) {
|
|||
_widget->showToast(std::move(text));
|
||||
}
|
||||
|
||||
not_null<QWidget*> Panel::toastParent() const {
|
||||
return _widget->uiShow()->toastParent();
|
||||
}
|
||||
|
||||
void Panel::hideLayer(anim::type animated) {
|
||||
_widget->hideLayer(animated);
|
||||
}
|
||||
|
||||
void Panel::showCriticalError(const TextWithEntities &text) {
|
||||
_progress = nullptr;
|
||||
_webviewProgress = false;
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace Ui {
|
|||
class BoxContent;
|
||||
class RpWidget;
|
||||
class SeparatePanel;
|
||||
enum class LayerOption;
|
||||
using LayerOptions = base::flags<LayerOption>;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Webview {
|
||||
|
@ -40,6 +42,7 @@ enum class MenuButton {
|
|||
OpenBot = 0x01,
|
||||
RemoveFromMenu = 0x02,
|
||||
RemoveFromMainMenu = 0x04,
|
||||
ShareGame = 0x08,
|
||||
};
|
||||
inline constexpr bool is_flag_type(MenuButton) { return true; }
|
||||
using MenuButtons = base::flags<MenuButton>;
|
||||
|
@ -67,6 +70,7 @@ public:
|
|||
virtual void botAllowWriteAccess(Fn<void(bool allowed)> callback) = 0;
|
||||
virtual void botSharePhone(Fn<void(bool shared)> callback) = 0;
|
||||
virtual void botInvokeCustomMethod(CustomMethodRequest request) = 0;
|
||||
virtual void botShareGameScore() = 0;
|
||||
virtual void botClose() = 0;
|
||||
};
|
||||
|
||||
|
@ -89,7 +93,13 @@ public:
|
|||
rpl::producer<QString> bottomText);
|
||||
|
||||
void showBox(object_ptr<BoxContent> box);
|
||||
void showBox(
|
||||
object_ptr<BoxContent> box,
|
||||
LayerOptions options,
|
||||
anim::type animated);
|
||||
void hideLayer(anim::type animated);
|
||||
void showToast(TextWithEntities &&text);
|
||||
not_null<QWidget*> toastParent() const;
|
||||
void showCriticalError(const TextWithEntities &text);
|
||||
void showWebviewError(
|
||||
const QString &text,
|
||||
|
|
Loading…
Add table
Reference in a new issue