Improve handling of Instant View anchors.

GitOrigin-RevId: 9293ea4c1c7f4767c7f91421b3719e00d836470c
This commit is contained in:
levlam 2020-03-03 00:40:52 +03:00
parent c36b6948b0
commit 5dee42c734
5 changed files with 59 additions and 13 deletions

View File

@ -843,8 +843,14 @@ richTextPhoneNumber text:RichText phone_number:string = RichText;
//@height Height of a bounding box in which the image should be shown; 0 if unknown
richTextIcon document:document width:int32 height:int32 = RichText;
//@description A rich text anchor @text Text @name Anchor name
richTextAnchor text:RichText name:string = RichText;
//@description A rich text reference of a text on the same web page @text The text @reference_text The text to show on click
richTextReference text:RichText reference_text:RichText = RichText;
//@description An anchor @name Anchor name
richTextAnchor name:string = RichText;
//@description A link to an anchor on the same web page @text The link text @name The anchor name
richTextAnchorLink text:RichText name:string = RichText;
//@description A concatenation of rich texts @texts Texts
richTexts texts:vector<RichText> = RichText;
@ -980,10 +986,9 @@ pageBlockMap location:location zoom:int32 width:int32 height:int32 caption:pageB
//@description Describes an instant view page for a web page @page_blocks Content of the web page
//@version Version of the instant view, currently can be 1 or 2
//@url Instant view URL; may be different from WebPage.url and must be used for the correct anchors handling
//@is_rtl True, if the instant view must be shown from right to left
//@is_full True, if the instant view contains the full page. A network request might be needed to get the full web page instant view
webPageInstantView page_blocks:vector<PageBlock> version:int32 url:string is_rtl:Bool is_full:Bool = WebPageInstantView;
webPageInstantView page_blocks:vector<PageBlock> version:int32 is_rtl:Bool is_full:Bool = WebPageInstantView;
//@description Describes a web page preview

Binary file not shown.

View File

@ -38,8 +38,15 @@
namespace td {
class RichText;
struct GetWebPageBlockObjectContext {
Td *td_;
Td *td_ = nullptr;
Slice base_url_;
bool is_first_pass_ = true;
bool has_anchor_urls_ = false;
std::unordered_map<Slice, const RichText *, SliceHash> anchors_; // anchor -> text
};
static vector<td_api::object_ptr<td_api::PageBlock>> get_page_block_objects(
@ -49,8 +56,6 @@ static vector<td_api::object_ptr<td_api::PageBlock>> get_page_block_objects(
});
}
namespace {
class RichText {
static vector<td_api::object_ptr<td_api::RichText>> get_rich_text_objects(const vector<RichText> &rich_texts,
GetWebPageBlockObjectContext *context) {
@ -112,6 +117,23 @@ class RichText {
case RichText::Type::Fixed:
return make_tl_object<td_api::richTextFixed>(texts[0].get_rich_text_object(context));
case RichText::Type::Url:
if (!context->base_url_.empty() && begins_with(content, context->base_url_) &&
content.size() > context->base_url_.size() + 1 && content[context->base_url_.size()] == '#') {
if (context->is_first_pass_) {
context->has_anchor_urls_ = true;
} else {
auto anchor = Slice(content).substr(context->base_url_.size() + 1);
auto it = context->anchors_.find(anchor);
if (it != context->anchors_.end()) {
if (it->second == nullptr) {
return make_tl_object<td_api::richTextAnchorLink>(texts[0].get_rich_text_object(context), anchor.str());
} else {
return make_tl_object<td_api::richTextReference>(texts[0].get_rich_text_object(context),
it->second->get_rich_text_object(context));
}
}
}
}
return make_tl_object<td_api::richTextUrl>(texts[0].get_rich_text_object(context), content,
web_page_id.is_valid());
case RichText::Type::EmailAddress:
@ -134,7 +156,13 @@ class RichText {
context->td_->documents_manager_->get_document_object(document_file_id), width, height);
}
case RichText::Type::Anchor:
return make_tl_object<td_api::richTextAnchor>(texts[0].get_rich_text_object(context), content);
if (context->is_first_pass_) {
context->anchors_.emplace(Slice(content), texts[0].empty() ? nullptr : &texts[0]);
}
if (texts[0].empty()) {
return make_tl_object<td_api::richTextAnchor>(content);
}
return texts[0].get_rich_text_object(context);
}
UNREACHABLE();
return nullptr;
@ -177,6 +205,8 @@ class RichText {
}
};
namespace {
class WebPageBlockCaption {
public:
RichText text;
@ -740,6 +770,9 @@ class WebPageBlockAnchor : public WebPageBlock {
}
td_api::object_ptr<td_api::PageBlock> get_page_block_object(Context *context) const override {
if (context->is_first_pass_) {
context->anchors_.emplace(name, nullptr);
}
return make_tl_object<td_api::pageBlockAnchor>(name);
}
@ -2348,9 +2381,16 @@ vector<unique_ptr<WebPageBlock>> get_web_page_blocks(
}
vector<td_api::object_ptr<td_api::PageBlock>> get_page_block_objects(
const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td) {
const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td, Slice base_url) {
GetWebPageBlockObjectContext context;
context.td_ = td;
context.base_url_ = base_url;
auto blocks = get_page_block_objects(page_blocks, &context);
if (context.anchors_.empty() || !context.has_anchor_urls_) {
return blocks;
}
context.is_first_pass_ = false;
return get_page_block_objects(page_blocks, &context);
}

View File

@ -14,6 +14,7 @@
#include "td/telegram/Photo.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include <unordered_map>
@ -103,6 +104,6 @@ vector<unique_ptr<WebPageBlock>> get_web_page_blocks(
const std::unordered_map<int64, FileId> &videos, const std::unordered_map<int64, FileId> &voice_notes);
vector<td_api::object_ptr<td_api::PageBlock>> get_page_block_objects(
const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td);
const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td, Slice base_url);
} // namespace td

View File

@ -1226,9 +1226,9 @@ tl_object_ptr<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_
LOG(ERROR) << "Trying to get not loaded web page instant view";
return nullptr;
}
return make_tl_object<td_api::webPageInstantView>(get_page_block_objects(web_page_instant_view->page_blocks, td_),
web_page_instant_view->is_v2 ? 2 : 1, web_page_instant_view->url,
web_page_instant_view->is_rtl, web_page_instant_view->is_full);
return td_api::make_object<td_api::webPageInstantView>(
get_page_block_objects(web_page_instant_view->page_blocks, td_, web_page_instant_view->url),
web_page_instant_view->is_v2 ? 2 : 1, web_page_instant_view->is_rtl, web_page_instant_view->is_full);
}
void WebPagesManager::on_web_page_changed(WebPageId web_page_id, bool have_web_page) {