diff --git a/Telegram/Resources/export_html/css/style.css b/Telegram/Resources/export_html/css/style.css
index 79b680cc2..102f5f3a5 100644
--- a/Telegram/Resources/export_html/css/style.css
+++ b/Telegram/Resources/export_html/css/style.css
@@ -559,3 +559,26 @@ div.toast_shown {
opacity: 0;
user-select: none;
}
+
+.bot_buttons_table {
+ border-spacing: 0px 2px;
+ width: 100%;
+}
+.bot_button {
+ border-radius: 8px;
+ text-align: center;
+ vertical-align: middle;
+ background-color: #168acd40;
+}
+.bot_button_row {
+ display: table;
+ table-layout: fixed;
+ padding: 0px;
+ width:100%;
+}
+.bot_button_row div {
+ display: table-cell;
+}
+.bot_button_column_separator {
+ width: 2px
+}
diff --git a/Telegram/Resources/export_html/js/script.js b/Telegram/Resources/export_html/js/script.js
index 8d25f5302..284232202 100644
--- a/Telegram/Resources/export_html/js/script.js
+++ b/Telegram/Resources/export_html/js/script.js
@@ -62,6 +62,12 @@ function ShowNotAvailableEmoji() {
return false;
}
+function ShowTextCopied(content) {
+ navigator.clipboard.writeText(content);
+ ShowToast("Text copied to clipboard.");
+ return false;
+}
+
function ShowSpoiler(target) {
if (target.classList.contains("hidden")) {
target.classList.toggle("hidden");
diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp
index f7928f006..1f56f9ec1 100644
--- a/Telegram/SourceFiles/export/data/export_data_types.cpp
+++ b/Telegram/SourceFiles/export/data/export_data_types.cpp
@@ -160,6 +160,30 @@ std::vector> ButtonRowsFromTL(
} // namespace
+QByteArray HistoryMessageMarkupButton::TypeToString(
+ const HistoryMessageMarkupButton &button) {
+ using Type = HistoryMessageMarkupButton::Type;
+ switch (button.type) {
+ case Type::Default: return "default";
+ case Type::Url: return "url";
+ case Type::Callback: return "callback";
+ case Type::CallbackWithPassword: return "callback_with_password";
+ case Type::RequestPhone: return "request_phone";
+ case Type::RequestLocation: return "request_location";
+ case Type::RequestPoll: return "request_poll";
+ case Type::RequestPeer: return "request_peer";
+ case Type::SwitchInline: return "switch_inline";
+ case Type::SwitchInlineSame: return "switch_inline_same";
+ case Type::Game: return "game";
+ case Type::Buy: return "buy";
+ case Type::Auth: return "auth";
+ case Type::UserProfile: return "user_profile";
+ case Type::WebView: return "web_view";
+ case Type::SimpleWebView: return "simple_web_view";
+ }
+ Unexpected("Type in HistoryMessageMarkupButton::Type.");
+}
+
uint8 PeerColorIndex(BareId bareId) {
const uint8 map[] = { 0, 7, 4, 1, 6, 3, 5 };
return map[bareId % base::array_size(map)];
diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h
index 5f2c2da39..76585991c 100644
--- a/Telegram/SourceFiles/export/data/export_data_types.h
+++ b/Telegram/SourceFiles/export/data/export_data_types.h
@@ -690,6 +690,8 @@ struct HistoryMessageMarkupButton {
SimpleWebView,
};
+ static QByteArray TypeToString(const HistoryMessageMarkupButton &);
+
Type type;
QString text;
QByteArray data;
diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp
index 395315227..9df6bcbb3 100644
--- a/Telegram/SourceFiles/export/output/export_output_html.cpp
+++ b/Telegram/SourceFiles/export/output/export_output_html.cpp
@@ -1443,6 +1443,55 @@ auto HtmlWriter::Wrap::pushMessage(
block.append(text);
block.append(popTag());
}
+ if (!message.inlineButtonRows.empty()) {
+ using Type = HistoryMessageMarkupButton::Type;
+ const auto endline = u" | "_q;
+ block.append(pushTag("table", { { "class", "bot_buttons_table" } }));
+ block.append(pushTag("tbody"));
+ for (const auto &row : message.inlineButtonRows) {
+ block.append(pushTag("tr"));
+ block.append(pushTag("td", { { "class", "bot_button_row" } }));
+ for (const auto &button : row) {
+ using Attribute = std::pair;
+ const auto content = (!button.data.isEmpty()
+ ? (u"Data: "_q + button.data + endline)
+ : QString())
+ + (!button.forwardText.isEmpty()
+ ? (u"Forward text: "_q + button.forwardText + endline)
+ : QString())
+ + (u"Type: "_q
+ + HistoryMessageMarkupButton::TypeToString(button));
+ const auto link = (button.type == Type::Url)
+ ? button.data
+ : QByteArray();
+ const auto onclick = (button.type != Type::Url)
+ ? ("return ShowTextCopied('" + content + "');").toUtf8()
+ : QByteArray();
+ block.append(pushTag("div", { { "class", "bot_button" } }));
+ block.append(pushTag("a", {
+ link.isEmpty() ? Attribute() : Attribute{ "href", link },
+ onclick.isEmpty()
+ ? Attribute()
+ : Attribute{ "onclick", onclick },
+ }));
+ block.append(pushTag("div"));
+ block.append(button.text.toUtf8());
+ block.append(popTag());
+ block.append(popTag());
+ block.append(popTag());
+
+ if (&button != &row.back()) {
+ block.append(pushTag("div", {
+ { "class", "bot_button_column_separator" }
+ }));
+ block.append(popTag());
+ }
+ }
+ block.append(popTag());
+ block.append(popTag());
+ }
+ block.append(popTag());
+ }
if (!message.signature.isEmpty()) {
block.append(pushDiv("signature details"));
block.append(SerializeString(message.signature));
diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp
index dde36a5a3..5bd7f2c37 100644
--- a/Telegram/SourceFiles/export/output/export_output_json.cpp
+++ b/Telegram/SourceFiles/export/output/export_output_json.cpp
@@ -784,29 +784,6 @@ QByteArray SerializeMessage(
pushBare("text_entities", SerializeText(context, message.text, true));
if (!message.inlineButtonRows.empty()) {
- const auto typeString = [](
- const HistoryMessageMarkupButton &entry) -> QByteArray {
- using Type = HistoryMessageMarkupButton::Type;
- switch (entry.type) {
- case Type::Default: return "default";
- case Type::Url: return "url";
- case Type::Callback: return "callback";
- case Type::CallbackWithPassword: return "callback_with_password";
- case Type::RequestPhone: return "request_phone";
- case Type::RequestLocation: return "request_location";
- case Type::RequestPoll: return "request_poll";
- case Type::RequestPeer: return "request_peer";
- case Type::SwitchInline: return "switch_inline";
- case Type::SwitchInlineSame: return "switch_inline_same";
- case Type::Game: return "game";
- case Type::Buy: return "buy";
- case Type::Auth: return "auth";
- case Type::UserProfile: return "user_profile";
- case Type::WebView: return "web_view";
- case Type::SimpleWebView: return "simple_web_view";
- }
- Unexpected("Type in HistoryMessageMarkupButton::Type.");
- };
const auto serializeRow = [&](
const std::vector &row) {
context.nesting.push_back(Context::kArray);
@@ -817,7 +794,8 @@ QByteArray SerializeMessage(
auto pairs = std::vector>();
pairs.push_back({
"type",
- SerializeString(typeString(entry)),
+ SerializeString(
+ HistoryMessageMarkupButton::TypeToString(entry)),
});
if (!entry.text.isEmpty()) {
pairs.push_back({