Added support of inline markup reply to HTML export.

This commit is contained in:
23rd 2024-02-21 20:47:11 +03:00 committed by John Preston
parent de1bd6ef28
commit 52c779bffa
6 changed files with 106 additions and 24 deletions

View file

@ -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
}

View file

@ -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");

View file

@ -160,6 +160,30 @@ std::vector<std::vector<HistoryMessageMarkupButton>> 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)];

View file

@ -690,6 +690,8 @@ struct HistoryMessageMarkupButton {
SimpleWebView,
};
static QByteArray TypeToString(const HistoryMessageMarkupButton &);
Type type;
QString text;
QByteArray data;

View file

@ -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<QByteArray, QByteArray>;
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));

View file

@ -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<HistoryMessageMarkupButton> &row) {
context.nesting.push_back(Context::kArray);
@ -817,7 +794,8 @@ QByteArray SerializeMessage(
auto pairs = std::vector<std::pair<QByteArray, QByteArray>>();
pairs.push_back({
"type",
SerializeString(typeString(entry)),
SerializeString(
HistoryMessageMarkupButton::TypeToString(entry)),
});
if (!entry.text.isEmpty()) {
pairs.push_back({