From 558a0f9b35e6c5a0e0d919261a68965a9ba644de Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 7 Feb 2019 02:58:27 +0300 Subject: [PATCH] Support PageBlockTable. GitOrigin-RevId: 602d58aaba14e6433c624fe08f8d12be20b2f1b2 --- td/generate/scheme/td_api.tl | 30 +++++ td/generate/scheme/td_api.tlo | Bin 141848 -> 142952 bytes td/telegram/WebPagesManager.cpp | 226 +++++++++++++++++++++++++++++++- td/telegram/WebPagesManager.h | 5 + td/tl/tl_jni_object.cpp | 3 + td/tl/tl_jni_object.h | 10 ++ 6 files changed, 273 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 110a115b6..858f68bfb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -711,6 +711,33 @@ pageBlockCaption text:RichText credit:RichText = PageBlockCaption; //@description Describes an item of a list page block @label Item label, can be empty @page_blocks Item blocks pageBlockListItem label:string page_blocks:vector = PageBlockListItem; +//@class PageBlockHorizontalAlignment @description Describes a horizontal alignment of a table cell content + +//@description The content should be left-aligned +pageBlockHorizontalAlignmentLeft = PageBlockHorizontalAlignment; + +//@description The content should be center-aligned +pageBlockHorizontalAlignmentCenter = PageBlockHorizontalAlignment; + +//@description The content should be right-aligned +pageBlockHorizontalAlignmentRight = PageBlockHorizontalAlignment; + +//@class PageBlockVerticalAlignment @description Describes a Vertical alignment of a table cell content + +//@description The content should be top-aligned +pageBlockVerticalAlignmentTop = PageBlockVerticalAlignment; + +//@description The content should be middle-aligned +pageBlockVerticalAlignmentMiddle = PageBlockVerticalAlignment; + +//@description The content should be bottom-aligned +pageBlockVerticalAlignmentBottom = PageBlockVerticalAlignment; + +//@description Represents a cell of a table @text Cell text @is_header True, if it is a header cell +//@colspan The number of columns the cell should span @rowspan The number of rows the cell should span +//@align Horizontal cell content alignment @valign Vertical cell content alignment +pageBlockTableCell text:RichText is_header:Bool colspan:int32 rowspan:int32 align:PageBlockHorizontalAlignment valign:PageBlockVerticalAlignment = PageBlockTableCell; + //@class PageBlock @description Describes a block of an instant view web page @@ -786,6 +813,9 @@ pageBlockSlideshow page_blocks:vector caption:pageBlockCaption = Page //@description A link to a chat @title Chat title @photo Chat photo; may be null @username Chat username, by which all other information about the chat should be resolved pageBlockChatLink title:string photo:chatPhoto username:string = PageBlock; +//@description A table @title Table title @cells Table cells @is_bordered True, if the table is bordered @is_striped True, if the table is striped +pageBlockTable title:RichText cells:vector> is_bordered:Bool is_striped:Bool = PageBlock; + //@description Describes an instant view page for a web page @page_blocks Content of the web page @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 diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 832e23f2f87101238c5ae97e5d3ae9c21a5924f0..d36127cfca339480be0bad6f9c8db1aab3e6784b 100644 GIT binary patch delta 1472 zcmbPnh2zB?4&Fzz^{p77;O<6Veo?_)NA??X1|+7ZI_2aiXEQKJPX5R!KG{XoK=E(y z=LIrw8ISy;%&PpnlEfUxoXqsR+|<01$rDASCzpsCh^OtZ4-tZ^3`tDNNp()m$(h(M zsn}YX^-T&c6_#35l9`NT1Oqe3y3I>O@9;BD+1#kQ`8X%YK{t;H`7lma^cSD(@m_=l zBr-YYtqO!O<*f;XaptWGTrtz+zu&|s3%s*|NCmu8fG|ql89*2--a)lrcn8(a@gAy1 z=RH(S!h49C=?*fCP@z5VH6Z#AeAJm9;mHW)IedWXP5A&-IOBtg1kB~2@GWv?)8Vjf zI|z3B6{zy*GJjzP>wJWo5b)6jV#AD&P!}Hf7yuCw`GhVq0VXo%jKgGsF9MS}KI=f# zT6~6@7xNjadjm|w;G7LmE!3SZUlibh#xj|4vH0Wz%>t9p{E(Tv;Y$d_D2}hNfcYu| z_7g0@p!g}_DZOh!&}e{5CH%lC z^#v+5eZdk&oyh?<3e#ogGHU38!WQPXt8!d1Ywr6i@D;$4GB_DBz~Y1joSGs&39zyz z1C!?D#C!77=SVS%$bix=Bh(b>XZJO^GmGPs@{3YZi&9gj8zeAFasUO2ONufJCMTK$ zlb9t3#7k3tcGSOApJt>0w-8GX@kvc90h$fUNuVSRvIZ82ATbah1VD~|b>zljC46Q% z19Mzz5wcm4I1T%kw>MA`pJ73n=@~$m;d0nyfnPNcZ%+87pa{<1aMR$~n*k&a@)p}< z$4}}UoWO9(NKH(cykUn72YYgUPH{nE-eiSxN%o@raxmMWT(Uk9RCqvq4ay$Kp#Tbf zwlahQkUXgPfT%`<9LQRj7%1eHNiOG>g*y+UhzZFrU|;~519ECTNFyu?kPQbJ^i{T` z5fPmj2Ki>Dq~xRm^}`IqXV$gaoi$j@(u9?rPWdGz`MG!u+q~pg#6)l$Z0li^m*$fO4lRq+wPj(SCn7l#M zV6%tV9e&21&8ljfkF$VOPQLTj0KyP>rvhPEyfc9?3f`%3g4EnRCgj63dEs~Q$tykx zOg{2X2O|CDodSd*@g8b~&wHp5CGVj|ta%Sra{;D?b?h` z0w5wgFhoo~L)AE(b(q}nlV|dQFD#SSe1`h@&S!`%lfFO=2>AlFw&F_;#K;#g5uUGe zAR=qNLe*UODg*WaEW%Jc!14`Z@n)TGDvS_~A>TFN5x_Rt@SF1VHGPZEeTd3}A5d58{4_zAWBG|&ZU#*5z|RthNeaI^Cina)0COh&RoL|3XCj!rJzxT( G#5@4(i|7sj diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index 061f3c952..1c76173a0 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -427,6 +427,10 @@ class WebPagesManager::RichText { FileId document_file_id; WebPageId web_page_id; + bool empty() const { + return type == Type::Plain && content.empty(); + } + template void store(T &storer) const { using ::td::store; @@ -488,6 +492,78 @@ class WebPagesManager::PageBlockCaption { } }; +class WebPagesManager::PageBlockTableCell { + public: + RichText text; + bool is_header = false; + bool align_left = false; + bool align_center = false; + bool align_right = false; + bool valign_top = false; + bool valign_middle = false; + bool valign_bottom = false; + int32 colspan = 1; + int32 rowspan = 1; + + template + void store(T &storer) const { + using ::td::store; + bool has_text = !text.empty(); + bool has_colspan = colspan != 1; + bool has_rowspan = rowspan != 1; + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_header); + STORE_FLAG(align_left); + STORE_FLAG(align_center); + STORE_FLAG(align_right); + STORE_FLAG(valign_top); + STORE_FLAG(valign_middle); + STORE_FLAG(valign_bottom); + STORE_FLAG(has_text); + STORE_FLAG(has_colspan); + STORE_FLAG(has_rowspan); + END_STORE_FLAGS(); + if (has_text) { + store(text, storer); + } + if (has_colspan) { + store(colspan, storer); + } + if (has_rowspan) { + store(rowspan, storer); + } + } + + template + void parse(T &parser) { + using ::td::parse; + bool has_text; + bool has_colspan; + bool has_rowspan; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_header); + PARSE_FLAG(align_left); + PARSE_FLAG(align_center); + PARSE_FLAG(align_right); + PARSE_FLAG(valign_top); + PARSE_FLAG(valign_middle); + PARSE_FLAG(valign_bottom); + PARSE_FLAG(has_text); + PARSE_FLAG(has_colspan); + PARSE_FLAG(has_rowspan); + END_PARSE_FLAGS(); + if (has_text) { + parse(text, parser); + } + if (has_colspan) { + parse(colspan, parser); + } + if (has_rowspan) { + parse(rowspan, parser); + } + } +}; + class WebPagesManager::PageBlock { public: enum class Type : int32 { @@ -514,7 +590,8 @@ class WebPagesManager::PageBlock { Slideshow, ChatLink, Audio, - Kicker + Kicker, + Table }; virtual Type get_type() const = 0; @@ -537,6 +614,7 @@ class WebPagesManager::PageBlock { store(type, storer); call_impl(type, this, [&](const auto *object) { store(*object, storer); }); } + template static unique_ptr parse(T &parser) { using ::td::parse; @@ -593,6 +671,7 @@ class WebPagesManager::PageBlockTitle : public PageBlock { using ::td::store; store(title, storer); } + template void parse(T &parser) { using ::td::parse; @@ -625,6 +704,7 @@ class WebPagesManager::PageBlockSubtitle : public PageBlock { using ::td::store; store(subtitle, storer); } + template void parse(T &parser) { using ::td::parse; @@ -659,6 +739,7 @@ class WebPagesManager::PageBlockAuthorDate : public PageBlock { store(author, storer); store(date, storer); } + template void parse(T &parser) { using ::td::parse; @@ -692,6 +773,7 @@ class WebPagesManager::PageBlockHeader : public PageBlock { using ::td::store; store(header, storer); } + template void parse(T &parser) { using ::td::parse; @@ -724,6 +806,7 @@ class WebPagesManager::PageBlockSubheader : public PageBlock { using ::td::store; store(subheader, storer); } + template void parse(T &parser) { using ::td::parse; @@ -756,6 +839,7 @@ class WebPagesManager::PageBlockKicker : public PageBlock { using ::td::store; store(kicker, storer); } + template void parse(T &parser) { using ::td::parse; @@ -788,6 +872,7 @@ class WebPagesManager::PageBlockParagraph : public PageBlock { using ::td::store; store(text, storer); } + template void parse(T &parser) { using ::td::parse; @@ -822,6 +907,7 @@ class WebPagesManager::PageBlockPreformatted : public PageBlock { store(text, storer); store(language, storer); } + template void parse(T &parser) { using ::td::parse; @@ -855,6 +941,7 @@ class WebPagesManager::PageBlockFooter : public PageBlock { using ::td::store; store(footer, storer); } + template void parse(T &parser) { using ::td::parse; @@ -874,9 +961,11 @@ class WebPagesManager::PageBlockDivider : public PageBlock { tl_object_ptr get_page_block_object() const override { return make_tl_object(); } + template void store(T &storer) const { } + template void parse(T &parser) { } @@ -900,11 +989,13 @@ class WebPagesManager::PageBlockAnchor : public PageBlock { tl_object_ptr get_page_block_object() const override { return make_tl_object(name); } + template void store(T &storer) const { using ::td::store; store(name, storer); } + template void parse(T &parser) { using ::td::parse; @@ -924,6 +1015,7 @@ class WebPagesManager::PageBlockList : public PageBlock { store(label, storer); store(page_blocks, storer); } + template void parse(T &parser) { using ::td::parse; @@ -966,6 +1058,7 @@ class WebPagesManager::PageBlockList : public PageBlock { using ::td::store; store(items, storer); } + template void parse(T &parser) { using ::td::parse; @@ -1408,6 +1501,7 @@ class WebPagesManager::PageBlockEmbeddedPost : public PageBlock { url, author, get_photo_object(G()->td().get_actor_unsafe()->file_manager_.get(), &author_photo), date, get_page_block_objects(page_blocks), get_page_block_caption_object(caption)); } + template void store(T &storer) const { using ::td::store; @@ -1623,6 +1717,63 @@ class WebPagesManager::PageBlockAudio : public PageBlock { } }; +class WebPagesManager::PageBlockTable : public PageBlock { + RichText title; + vector> cells; + bool is_bordered = false; + bool is_striped = false; + + public: + PageBlockTable() = default; + PageBlockTable(RichText &&title, vector> &&cells, bool is_bordered, bool is_striped) + : title(std::move(title)), cells(std::move(cells)), is_bordered(is_bordered), is_striped(is_striped) { + } + + Type get_type() const override { + return Type::Table; + } + + void append_file_ids(vector &file_ids) const override { + append_rich_text_file_ids(title, file_ids); + for (auto &row : cells) { + for (auto &cell : row) { + append_rich_text_file_ids(cell.text, file_ids); + } + } + } + + tl_object_ptr get_page_block_object() const override { + auto cell_objects = transform(cells, [&](const vector &row) { + return transform(row, [&](const PageBlockTableCell &cell) { return get_page_block_table_cell_object(cell); }); + }); + + return make_tl_object(get_rich_text_object(title), std::move(cell_objects), is_bordered, + is_striped); + } + + template + void store(T &storer) const { + using ::td::store; + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_bordered); + STORE_FLAG(is_striped); + END_STORE_FLAGS(); + store(title, storer); + store(cells, storer); + } + + template + void parse(T &parser) { + using ::td::parse; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_bordered); + PARSE_FLAG(is_striped); + END_PARSE_FLAGS(); + parse(title, parser); + parse(cells, parser); + } +}; + template void WebPagesManager::PageBlock::call_impl(Type type, const PageBlock *ptr, F &&f) { switch (type) { @@ -1674,6 +1825,8 @@ void WebPagesManager::PageBlock::call_impl(Type type, const PageBlock *ptr, F && return f(static_cast(ptr)); case Type::Audio: return f(static_cast(ptr)); + case Type::Table: + return f(static_cast(ptr)); } UNREACHABLE(); } @@ -2676,6 +2829,38 @@ td_api::object_ptr WebPagesManager::get_page_block_cap get_rich_text_object(caption.credit)); } +td_api::object_ptr WebPagesManager::get_page_block_table_cell_object( + const PageBlockTableCell &cell) { + auto align = [&]() -> td_api::object_ptr { + if (cell.align_left) { + return td_api::make_object(); + } + if (cell.align_center) { + return td_api::make_object(); + } + if (cell.align_right) { + return td_api::make_object(); + } + UNREACHABLE(); + return nullptr; + }(); + auto valign = [&]() -> td_api::object_ptr { + if (cell.valign_top) { + return td_api::make_object(); + } + if (cell.valign_middle) { + return td_api::make_object(); + } + if (cell.valign_bottom) { + return td_api::make_object(); + } + UNREACHABLE(); + return nullptr; + }(); + return td_api::make_object(get_rich_text_object(cell.text), cell.is_header, cell.colspan, + cell.rowspan, std::move(align), std::move(valign)); +} + vector> WebPagesManager::get_page_block_objects( const vector> &page_blocks) { return transform(page_blocks, @@ -2927,6 +3112,45 @@ unique_ptr WebPagesManager::get_page_block( return make_unique(audio_file_id, get_page_block_caption(std::move(page_block->caption_), documents)); } + case telegram_api::pageBlockTable::ID: { + auto page_block = move_tl_object_as(page_block_ptr); + auto is_bordered = (page_block->flags_ & telegram_api::pageBlockTable::BORDERED_MASK) != 0; + auto is_striped = (page_block->flags_ & telegram_api::pageBlockTable::STRIPED_MASK) != 0; + auto cells = transform(std::move(page_block->rows_), [&](tl_object_ptr &&row) { + return transform(std::move(row->cells_), [&](tl_object_ptr &&table_cell) { + PageBlockTableCell cell; + auto flags = table_cell->flags_; + cell.is_header = (flags & telegram_api::pageTableCell::HEADER_MASK) != 0; + cell.align_center = (flags & telegram_api::pageTableCell::ALIGN_CENTER_MASK) != 0; + if (!cell.align_center) { + cell.align_right = (flags & telegram_api::pageTableCell::ALIGN_RIGHT_MASK) != 0; + if (!cell.align_right) { + cell.align_left = true; + } + } + cell.valign_middle = (flags & telegram_api::pageTableCell::VALIGN_MIDDLE_MASK) != 0; + if (!cell.valign_middle) { + cell.valign_bottom = (flags & telegram_api::pageTableCell::VALIGN_BOTTOM_MASK) != 0; + if (!cell.valign_bottom) { + cell.valign_top = true; + } + } + if (table_cell->text_ != nullptr) { + cell.text = get_rich_text(std::move(table_cell->text_), documents); + } + if ((flags & telegram_api::pageTableCell::COLSPAN_MASK) != 0) { + cell.colspan = table_cell->colspan_; + } + if ((flags & telegram_api::pageTableCell::ROWSPAN_MASK) != 0) { + cell.rowspan = table_cell->rowspan_; + } + return cell; + }); + }); + return td::make_unique(get_rich_text(std::move(page_block->title_), documents), std::move(cells), + is_bordered, is_striped); + } + default: UNREACHABLE(); } diff --git a/td/telegram/WebPagesManager.h b/td/telegram/WebPagesManager.h index 7b5e37298..d6dde92cb 100644 --- a/td/telegram/WebPagesManager.h +++ b/td/telegram/WebPagesManager.h @@ -101,6 +101,7 @@ class WebPagesManager : public Actor { class RichText; class PageBlockCaption; + class PageBlockTableCell; class PageBlock; class PageBlockTitle; @@ -127,6 +128,7 @@ class WebPagesManager : public Actor { class PageBlockSlideshow; class PageBlockChatLink; class PageBlockAudio; + class PageBlockTable; class WebPageInstantView; @@ -178,6 +180,9 @@ class WebPagesManager : public Actor { static td_api::object_ptr get_page_block_caption_object(const PageBlockCaption &caption); + static td_api::object_ptr get_page_block_table_cell_object( + const PageBlockTableCell &cell); + static vector> get_page_block_objects( const vector> &page_blocks); diff --git a/td/tl/tl_jni_object.cpp b/td/tl/tl_jni_object.cpp index fa5b36290..220199edb 100644 --- a/td/tl/tl_jni_object.cpp +++ b/td/tl/tl_jni_object.cpp @@ -26,6 +26,7 @@ static jclass StringClass; static jclass ObjectClass; jclass ArrayKeyboardButtonClass; jclass ArrayInlineKeyboardButtonClass; +jclass ArrayPageBlockTableCellClass; jmethodID GetConstructorID; jmethodID BooleanGetValueMethodID; jmethodID IntegerGetValueMethodID; @@ -103,6 +104,8 @@ void init_vars(JNIEnv *env, const char *td_api_java_package) { get_jclass(env, (PSLICE() << "[L" << td_api_java_package << "/TdApi$KeyboardButton;").c_str()); ArrayInlineKeyboardButtonClass = get_jclass(env, (PSLICE() << "[L" << td_api_java_package << "/TdApi$InlineKeyboardButton;").c_str()); + ArrayPageBlockTableCellClass = + get_jclass(env, (PSLICE() << "[L" << td_api_java_package << "/TdApi$PageBlockTableCell;").c_str()); GetConstructorID = get_method_id(env, ObjectClass, "getConstructor", "()I"); BooleanGetValueMethodID = get_method_id(env, BooleanClass, "booleanValue", "()Z"); IntegerGetValueMethodID = get_method_id(env, IntegerClass, "intValue", "()I"); diff --git a/td/tl/tl_jni_object.h b/td/tl/tl_jni_object.h index a3a153e6c..15a060b33 100644 --- a/td/tl/tl_jni_object.h +++ b/td/tl/tl_jni_object.h @@ -17,6 +17,7 @@ namespace td { namespace td_api { class keyboardButton; class inlineKeyboardButton; +class pageBlockTableCell; } // namespace td_api namespace jni { @@ -25,6 +26,7 @@ extern thread_local bool parse_error; extern jclass ArrayKeyboardButtonClass; extern jclass ArrayInlineKeyboardButtonClass; +extern jclass ArrayPageBlockTableCellClass; extern jmethodID GetConstructorID; extern jmethodID BooleanGetValueMethodID; extern jmethodID IntegerGetValueMethodID; @@ -143,6 +145,14 @@ class get_array_class { } }; +template <> +class get_array_class { + public: + static jclass get() { + return ArrayPageBlockTableCellClass; + } +}; + template jobjectArray store_vector(JNIEnv *env, const std::vector> &v) { jint length = static_cast(v.size());