Respect 'try_instant_view' in webapps.

This commit is contained in:
John Preston 2024-04-04 18:20:33 +04:00
parent 9464f4b095
commit 36cb28d5cf
6 changed files with 76 additions and 8 deletions

View File

@ -17,10 +17,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_session.h"
#include "data/data_web_page.h"
#include "main/main_session.h"
#include "main/main_domain.h"
#include "storage/storage_domain.h"
#include "info/profile/info_profile_values.h"
#include "iv/iv_instance.h"
#include "ui/boxes/confirm_box.h"
#include "ui/chat/attach/attach_bot_webview.h"
#include "ui/widgets/checkbox.h"
@ -653,6 +655,53 @@ void AttachWebView::botHandleMenuButton(Ui::BotWebView::MenuButton button) {
}
}
void AttachWebView::botOpenIvLink(QString uri) {
const auto parts = uri.split('#');
if (parts.isEmpty()) {
return;
}
const auto hash = (parts.size() > 1) ? parts[1] : u""_q;
const auto url = parts[0];
if (const auto i = _ivCache.find(url); i != end(_ivCache)) {
const auto page = i->second;
if (page && page->iv) {
const auto window = _context
? _context->controller.get()
: nullptr;
if (window) {
Core::App().iv().show(window, page->iv.get(), hash);
} else {
Core::App().iv().show(_session, page->iv.get(), hash);
}
} else {
UrlClickHandler::Open(uri);
}
return;
} else if (_ivRequestUri == uri) {
return;
} else if (_ivRequestId) {
_session->api().request(_ivRequestId).cancel();
}
const auto finish = [=](WebPageData *page) {
_ivRequestId = 0;
_ivRequestUri = QString();
_ivCache[url] = page;
botOpenIvLink(uri);
};
_ivRequestUri = uri;
_ivRequestId = _session->api().request(MTPmessages_GetWebPage(
MTP_string(url),
MTP_int(0)
)).done([=](const MTPmessages_WebPage &result) {
const auto &data = result.data();
_session->data().processUsers(data.vusers());
_session->data().processChats(data.vchats());
finish(_session->data().processWebpage(data.vwebpage()));
}).fail([=] {
finish(nullptr);
}).send();
}
void AttachWebView::botSendData(QByteArray data) {
if (!_context
|| _context->fromSwitch

View File

@ -165,6 +165,7 @@ private:
bool botHandleLocalUri(QString uri, bool keepOpen) override;
void botHandleInvoice(QString slug) override;
void botHandleMenuButton(Ui::BotWebView::MenuButton button) override;
void botOpenIvLink(QString uri) override;
void botSendData(QByteArray data) override;
void botSwitchInlineQuery(
std::vector<QString> chatTypes,
@ -266,6 +267,10 @@ private:
rpl::event_stream<> _attachBotsUpdates;
base::flat_set<not_null<UserData*>> _disclaimerAccepted;
base::flat_map<QString, WebPageData*> _ivCache;
QString _ivRequestUri;
mtpRequestId _ivRequestId = 0;
std::unique_ptr<Ui::BotWebView::Panel> _panel;
bool _catchingCancelInShowCall = false;

View File

@ -63,7 +63,7 @@ class Shown final : public base::has_weak_ptr {
public:
Shown(
not_null<Delegate*> delegate,
std::shared_ptr<Main::SessionShow> show,
not_null<Main::Session*> session,
not_null<Data*> data,
QString hash);
@ -169,12 +169,11 @@ private:
Shown::Shown(
not_null<Delegate*> delegate,
std::shared_ptr<Main::SessionShow> show,
not_null<Main::Session*> session,
not_null<Data*> data,
QString hash)
: _delegate(delegate)
, _session(&show->session())
, _show(show) {
, _session(session) {
prepare(data, hash);
}
@ -818,7 +817,13 @@ void Instance::show(
std::shared_ptr<Main::SessionShow> show,
not_null<Data*> data,
QString hash) {
const auto session = &show->session();
this->show(&show->session(), data, hash);
}
void Instance::show(
not_null<Main::Session*> session,
not_null<Data*> data,
QString hash) {
const auto guard = gsl::finally([&] {
if (data->partial()) {
requestFull(session, data->id());
@ -828,7 +833,7 @@ void Instance::show(
_shown->moveTo(data, hash);
return;
}
_shown = std::make_unique<Shown>(_delegate, show, data, hash);
_shown = std::make_unique<Shown>(_delegate, session, data, hash);
_shownSession = session;
_shown->events() | rpl::start_with_next([=](Controller::Event event) {
using Type = Controller::Event::Type;
@ -896,7 +901,7 @@ void Instance::show(
if (page && page->iv) {
const auto parts = event.url.split('#');
const auto hash = (parts.size() > 1) ? parts[1] : u""_q;
this->show(show, page->iv.get(), hash);
this->show(_shownSession, page->iv.get(), hash);
} else {
UrlClickHandler::Open(event.url);
}

View File

@ -36,6 +36,10 @@ public:
std::shared_ptr<Main::SessionShow> show,
not_null<Data*> data,
QString hash);
void show(
not_null<Main::Session*> session,
not_null<Data*> data,
QString hash);
[[nodiscard]] bool hasActiveWindow(
not_null<Main::Session*> session) const;

View File

@ -801,6 +801,7 @@ void Panel::openExternalLink(const QJsonObject &args) {
return;
}
const auto url = args["url"].toString();
const auto iv = args["try_instant_view"].toBool();
const auto lower = url.toLower();
if (url.isEmpty()
|| (!lower.startsWith("http://") && !lower.startsWith("https://"))) {
@ -809,8 +810,11 @@ void Panel::openExternalLink(const QJsonObject &args) {
return;
} else if (!allowOpenLink()) {
return;
} else if (iv) {
_delegate->botOpenIvLink(url);
} else {
File::OpenUrl(url);
}
File::OpenUrl(url);
}
void Panel::openInvoice(const QJsonObject &args) {

View File

@ -57,6 +57,7 @@ public:
virtual bool botHandleLocalUri(QString uri, bool keepOpen) = 0;
virtual void botHandleInvoice(QString slug) = 0;
virtual void botHandleMenuButton(MenuButton button) = 0;
virtual void botOpenIvLink(QString uri) = 0;
virtual void botSendData(QByteArray data) = 0;
virtual void botSwitchInlineQuery(
std::vector<QString> chatTypes,