mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Load non-streamable documents.
This commit is contained in:
parent
5c428ca502
commit
c46f34c677
6 changed files with 135 additions and 38 deletions
|
@ -306,7 +306,7 @@ article ol aside {
|
||||||
article blockquote cite,
|
article blockquote cite,
|
||||||
article aside cite,
|
article aside cite,
|
||||||
article footer cite,
|
article footer cite,
|
||||||
article .iv-pullquote cite {
|
article .pullquote cite {
|
||||||
font-family: 'Helvetica Neue';
|
font-family: 'Helvetica Neue';
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -385,7 +385,7 @@ article table {
|
||||||
article table.bordered,
|
article table.bordered,
|
||||||
article table.bordered td,
|
article table.bordered td,
|
||||||
article table.bordered th {
|
article table.bordered th {
|
||||||
border: 1px solid var(--td-box-divider-fg);
|
border: 1px solid var(--td-history-to-down-shadow);
|
||||||
}
|
}
|
||||||
article table.striped tr:nth-child(odd) td {
|
article table.striped tr:nth-child(odd) td {
|
||||||
background-color: var(--td-box-divider-bg);
|
background-color: var(--td-box-divider-bg);
|
||||||
|
@ -425,7 +425,7 @@ article details {
|
||||||
article details:before {
|
article details:before {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
border-bottom: 1px solid var(--td-box-divider-fg);
|
border-bottom: 1px solid var(--td-history-to-down-shadow);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 18px;
|
left: 18px;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -818,6 +818,7 @@ section.embed-post small {
|
||||||
color: var(--td-window-sub-text-fg);
|
color: var(--td-window-sub-text-fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
section.related {
|
section.related {
|
||||||
margin: 7px 0 12px;
|
margin: 7px 0 12px;
|
||||||
}
|
}
|
||||||
|
@ -842,7 +843,7 @@ section.related a.related-link {
|
||||||
section.related a.related-link:after {
|
section.related a.related-link:after {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
border-bottom: 1px solid var(--td-box-divider-fg);
|
border-bottom: 1px solid var(--td-history-to-down-shadow);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 18px;
|
left: 18px;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -975,19 +976,19 @@ section.channel > a > h4 {
|
||||||
padding: 7px 18px;
|
padding: 7px 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.iv-pullquote {
|
.pullquote {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 420px;
|
max-width: 420px;
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.iv-photo-wrap {
|
.photo-wrap {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.iv-photo {
|
.photo {
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -772,7 +772,11 @@ Storage::Cache::Key DocumentData::bigFileBaseCacheKey() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentData::forceToCache(bool force) {
|
void DocumentData::forceToCache(bool force) {
|
||||||
_flags |= Flag::ForceToCache;
|
if (force) {
|
||||||
|
_flags |= Flag::ForceToCache;
|
||||||
|
} else {
|
||||||
|
_flags &= ~Flag::ForceToCache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DocumentData::saveToCache() const {
|
bool DocumentData::saveToCache() const {
|
||||||
|
|
|
@ -482,18 +482,25 @@ void Controller::processKey(const QString &key, const QString &modifier) {
|
||||||
void Controller::processLink(const QString &url, const QString &context) {
|
void Controller::processLink(const QString &url, const QString &context) {
|
||||||
const auto channelPrefix = u"channel"_q;
|
const auto channelPrefix = u"channel"_q;
|
||||||
const auto joinPrefix = u"join_link"_q;
|
const auto joinPrefix = u"join_link"_q;
|
||||||
|
const auto webpagePrefix = u"webpage"_q;
|
||||||
if (context.startsWith(channelPrefix)) {
|
if (context.startsWith(channelPrefix)) {
|
||||||
_events.fire({
|
_events.fire({
|
||||||
Event::Type::OpenChannel,
|
.type = Event::Type::OpenChannel,
|
||||||
context.mid(channelPrefix.size()),
|
.context = context.mid(channelPrefix.size()),
|
||||||
});
|
});
|
||||||
} else if (context.startsWith(joinPrefix)) {
|
} else if (context.startsWith(joinPrefix)) {
|
||||||
_events.fire({
|
_events.fire({
|
||||||
Event::Type::JoinChannel,
|
.type = Event::Type::JoinChannel,
|
||||||
context.mid(joinPrefix.size()),
|
.context = context.mid(joinPrefix.size()),
|
||||||
|
});
|
||||||
|
} else if (context.startsWith(webpagePrefix)) {
|
||||||
|
_events.fire({
|
||||||
|
.type = Event::Type::OpenPage,
|
||||||
|
.url = url,
|
||||||
|
.context = context.mid(webpagePrefix.size()),
|
||||||
});
|
});
|
||||||
} else if (context.isEmpty()) {
|
} else if (context.isEmpty()) {
|
||||||
_events.fire({ Event::Type::OpenLink, url });
|
_events.fire({ .type = Event::Type::OpenLink, .url = url });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,11 @@ public:
|
||||||
Quit,
|
Quit,
|
||||||
OpenChannel,
|
OpenChannel,
|
||||||
JoinChannel,
|
JoinChannel,
|
||||||
|
OpenPage,
|
||||||
OpenLink,
|
OpenLink,
|
||||||
};
|
};
|
||||||
Type type = Type::Close;
|
Type type = Type::Close;
|
||||||
|
QString url;
|
||||||
QString context;
|
QString context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_cloud_file.h"
|
#include "data/data_cloud_file.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_document_media.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_photo_media.h"
|
#include "data/data_photo_media.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_web_page.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
#include "iv/iv_controller.h"
|
#include "iv/iv_controller.h"
|
||||||
#include "iv/iv_data.h"
|
#include "iv/iv_data.h"
|
||||||
|
#include "lottie/lottie_common.h" // Lottie::ReadContent.
|
||||||
#include "main/main_account.h"
|
#include "main/main_account.h"
|
||||||
#include "main/main_domain.h"
|
#include "main/main_domain.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -97,13 +100,17 @@ private:
|
||||||
std::vector<bool> loaded;
|
std::vector<bool> loaded;
|
||||||
int64 offset = 0;
|
int64 offset = 0;
|
||||||
};
|
};
|
||||||
struct FileLoad {
|
struct FileStream {
|
||||||
not_null<DocumentData*> document;
|
not_null<DocumentData*> document;
|
||||||
std::unique_ptr<Media::Streaming::Loader> loader;
|
std::unique_ptr<Media::Streaming::Loader> loader;
|
||||||
std::vector<PartRequest> requests;
|
std::vector<PartRequest> requests;
|
||||||
std::string mime;
|
std::string mime;
|
||||||
rpl::lifetime lifetime;
|
rpl::lifetime lifetime;
|
||||||
};
|
};
|
||||||
|
struct FileLoad {
|
||||||
|
std::shared_ptr<::Data::DocumentMedia> media;
|
||||||
|
std::vector<Webview::DataRequest> requests;
|
||||||
|
};
|
||||||
|
|
||||||
void showLocal(Prepared result);
|
void showLocal(Prepared result);
|
||||||
void showWindowed(Prepared result);
|
void showWindowed(Prepared result);
|
||||||
|
@ -123,9 +130,9 @@ private:
|
||||||
// Windowed.
|
// Windowed.
|
||||||
void streamPhoto(PhotoId photoId, Webview::DataRequest request);
|
void streamPhoto(PhotoId photoId, Webview::DataRequest request);
|
||||||
void streamFile(DocumentId documentId, Webview::DataRequest request);
|
void streamFile(DocumentId documentId, Webview::DataRequest request);
|
||||||
void streamFile(FileLoad &file, Webview::DataRequest request);
|
void streamFile(FileStream &file, Webview::DataRequest request);
|
||||||
void processPartInFile(
|
void processPartInFile(
|
||||||
FileLoad &file,
|
FileStream &file,
|
||||||
Media::Streaming::LoadedPart &&part);
|
Media::Streaming::LoadedPart &&part);
|
||||||
bool finishRequestWithPart(
|
bool finishRequestWithPart(
|
||||||
PartRequest &request,
|
PartRequest &request,
|
||||||
|
@ -134,6 +141,9 @@ private:
|
||||||
void sendEmbed(QByteArray hash, Webview::DataRequest request);
|
void sendEmbed(QByteArray hash, Webview::DataRequest request);
|
||||||
|
|
||||||
void fillChannelJoinedValues(const Prepared &result);
|
void fillChannelJoinedValues(const Prepared &result);
|
||||||
|
void subscribeToDocuments();
|
||||||
|
[[nodiscard]] QByteArray readFile(
|
||||||
|
const std::shared_ptr<::Data::DocumentMedia> &media);
|
||||||
void requestDone(
|
void requestDone(
|
||||||
Webview::DataRequest request,
|
Webview::DataRequest request,
|
||||||
QByteArray bytes,
|
QByteArray bytes,
|
||||||
|
@ -146,6 +156,7 @@ private:
|
||||||
std::shared_ptr<Main::SessionShow> _show;
|
std::shared_ptr<Main::SessionShow> _show;
|
||||||
QString _id;
|
QString _id;
|
||||||
std::unique_ptr<Controller> _controller;
|
std::unique_ptr<Controller> _controller;
|
||||||
|
base::flat_map<DocumentId, FileStream> _streams;
|
||||||
base::flat_map<DocumentId, FileLoad> _files;
|
base::flat_map<DocumentId, FileLoad> _files;
|
||||||
base::flat_map<QByteArray, rpl::producer<bool>> _inChannelValues;
|
base::flat_map<QByteArray, rpl::producer<bool>> _inChannelValues;
|
||||||
|
|
||||||
|
@ -157,6 +168,7 @@ private:
|
||||||
|
|
||||||
rpl::event_stream<Controller::Event> _events;
|
rpl::event_stream<Controller::Event> _events;
|
||||||
|
|
||||||
|
rpl::lifetime _documentLifetime;
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -461,20 +473,37 @@ void Shown::streamFile(
|
||||||
Webview::DataRequest request) {
|
Webview::DataRequest request) {
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
|
|
||||||
const auto i = _files.find(documentId);
|
const auto i = _streams.find(documentId);
|
||||||
if (i != end(_files)) {
|
if (i != end(_streams)) {
|
||||||
streamFile(i->second, std::move(request));
|
streamFile(i->second, std::move(request));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto document = _session->data().document(documentId);
|
const auto document = _session->data().document(documentId);
|
||||||
auto loader = document->createStreamingLoader(FileOrigin(), false);
|
auto loader = document->createStreamingLoader(FileOrigin(), false);
|
||||||
if (!loader) {
|
if (!loader) {
|
||||||
requestFail(std::move(request));
|
if (document->size >= Storage::kMaxFileInMemory) {
|
||||||
|
requestFail(std::move(request));
|
||||||
|
} else {
|
||||||
|
auto media = document->createMediaView();
|
||||||
|
if (const auto content = readFile(media); !content.isEmpty()) {
|
||||||
|
requestDone(
|
||||||
|
std::move(request),
|
||||||
|
content,
|
||||||
|
document->mimeString().toStdString());
|
||||||
|
} else {
|
||||||
|
subscribeToDocuments();
|
||||||
|
auto &file = _files[documentId];
|
||||||
|
file.media = std::move(media);
|
||||||
|
file.requests.push_back(std::move(request));
|
||||||
|
document->forceToCache(true);
|
||||||
|
document->save(::Data::FileOrigin(), QString());
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto &file = _files.emplace(
|
auto &file = _streams.emplace(
|
||||||
documentId,
|
documentId,
|
||||||
FileLoad{
|
FileStream{
|
||||||
.document = document,
|
.document = document,
|
||||||
.loader = std::move(loader),
|
.loader = std::move(loader),
|
||||||
.mime = document->mimeString().toStdString(),
|
.mime = document->mimeString().toStdString(),
|
||||||
|
@ -482,15 +511,15 @@ void Shown::streamFile(
|
||||||
|
|
||||||
file.loader->parts(
|
file.loader->parts(
|
||||||
) | rpl::start_with_next([=](Media::Streaming::LoadedPart &&part) {
|
) | rpl::start_with_next([=](Media::Streaming::LoadedPart &&part) {
|
||||||
const auto i = _files.find(documentId);
|
const auto i = _streams.find(documentId);
|
||||||
Assert(i != end(_files));
|
Assert(i != end(_streams));
|
||||||
processPartInFile(i->second, std::move(part));
|
processPartInFile(i->second, std::move(part));
|
||||||
}, file.lifetime);
|
}, file.lifetime);
|
||||||
|
|
||||||
streamFile(file, std::move(request));
|
streamFile(file, std::move(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shown::streamFile(FileLoad &file, Webview::DataRequest request) {
|
void Shown::streamFile(FileStream &file, Webview::DataRequest request) {
|
||||||
constexpr auto kPart = Media::Streaming::Loader::kPartSize;
|
constexpr auto kPart = Media::Streaming::Loader::kPartSize;
|
||||||
const auto size = file.document->size;
|
const auto size = file.document->size;
|
||||||
const auto last = int((size + kPart - 1) / kPart);
|
const auto last = int((size + kPart - 1) / kPart);
|
||||||
|
@ -519,8 +548,44 @@ void Shown::streamFile(FileLoad &file, Webview::DataRequest request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shown::subscribeToDocuments() {
|
||||||
|
if (_documentLifetime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_documentLifetime = _session->data().documentLoadProgress(
|
||||||
|
) | rpl::filter([=](not_null<DocumentData*> document) {
|
||||||
|
return !document->loading();
|
||||||
|
}) | rpl::start_with_next([=](not_null<DocumentData*> document) {
|
||||||
|
const auto i = _files.find(document->id);
|
||||||
|
if (i == end(_files)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto requests = base::take(i->second.requests);
|
||||||
|
const auto content = readFile(i->second.media);
|
||||||
|
_files.erase(i);
|
||||||
|
|
||||||
|
if (!content.isEmpty()) {
|
||||||
|
for (auto &request : requests) {
|
||||||
|
requestDone(
|
||||||
|
std::move(request),
|
||||||
|
content,
|
||||||
|
document->mimeString().toStdString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto &request : requests) {
|
||||||
|
requestFail(std::move(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Shown::readFile(
|
||||||
|
const std::shared_ptr<::Data::DocumentMedia> &media) {
|
||||||
|
return Lottie::ReadContent(media->bytes(), media->owner()->filepath());
|
||||||
|
}
|
||||||
|
|
||||||
void Shown::processPartInFile(
|
void Shown::processPartInFile(
|
||||||
FileLoad &file,
|
FileStream &file,
|
||||||
Media::Streaming::LoadedPart &&part) {
|
Media::Streaming::LoadedPart &&part) {
|
||||||
for (auto i = begin(file.requests); i != end(file.requests);) {
|
for (auto i = begin(file.requests); i != end(file.requests);) {
|
||||||
if (finishRequestWithPart(*i, part)) {
|
if (finishRequestWithPart(*i, part)) {
|
||||||
|
@ -725,8 +790,26 @@ void Instance::show(
|
||||||
case Type::JoinChannel:
|
case Type::JoinChannel:
|
||||||
processJoinChannel(event.context);
|
processJoinChannel(event.context);
|
||||||
break;
|
break;
|
||||||
|
case Type::OpenPage:
|
||||||
case Type::OpenLink:
|
case Type::OpenLink:
|
||||||
UrlClickHandler::Open(event.context);
|
_shownSession->api().request(MTPmessages_GetWebPage(
|
||||||
|
MTP_string(event.url),
|
||||||
|
MTP_int(0)
|
||||||
|
)).done([=](const MTPmessages_WebPage &result) {
|
||||||
|
_shownSession->data().processUsers(result.data().vusers());
|
||||||
|
_shownSession->data().processChats(result.data().vchats());
|
||||||
|
const auto page = _shownSession->data().processWebpage(
|
||||||
|
result.data().vwebpage());
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
UrlClickHandler::Open(event.url);
|
||||||
|
}
|
||||||
|
}).fail([=] {
|
||||||
|
UrlClickHandler::Open(event.url);
|
||||||
|
}).send();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, _shown->lifetime());
|
}, _shown->lifetime());
|
||||||
|
|
|
@ -214,11 +214,11 @@ QByteArray Parser::block(const MTPDpageBlockUnsupported &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockTitle &data) {
|
QByteArray Parser::block(const MTPDpageBlockTitle &data) {
|
||||||
return tag("h1", { { "class", "iv-title" } }, rich(data.vtext()));
|
return tag("h1", { { "class", "title" } }, rich(data.vtext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockSubtitle &data) {
|
QByteArray Parser::block(const MTPDpageBlockSubtitle &data) {
|
||||||
return tag("h2", { { "class", "iv-subtitle" } }, rich(data.vtext()));
|
return tag("h2", { { "class", "subtitle" } }, rich(data.vtext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockAuthorDate &data) {
|
QByteArray Parser::block(const MTPDpageBlockAuthorDate &data) {
|
||||||
|
@ -232,11 +232,11 @@ QByteArray Parser::block(const MTPDpageBlockAuthorDate &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockHeader &data) {
|
QByteArray Parser::block(const MTPDpageBlockHeader &data) {
|
||||||
return tag("h3", { { "class", "iv-header" } }, rich(data.vtext()));
|
return tag("h3", { { "class", "header" } }, rich(data.vtext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockSubheader &data) {
|
QByteArray Parser::block(const MTPDpageBlockSubheader &data) {
|
||||||
return tag("h4", { { "class", "iv-subheader" } }, rich(data.vtext()));
|
return tag("h4", { { "class", "subheader" } }, rich(data.vtext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockParagraph &data) {
|
QByteArray Parser::block(const MTPDpageBlockParagraph &data) {
|
||||||
|
@ -255,11 +255,11 @@ QByteArray Parser::block(const MTPDpageBlockPreformatted &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockFooter &data) {
|
QByteArray Parser::block(const MTPDpageBlockFooter &data) {
|
||||||
return tag("footer", { { "class", "iv-footer" } }, rich(data.vtext()));
|
return tag("footer", { { "class", "footer" } }, rich(data.vtext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockDivider &data) {
|
QByteArray Parser::block(const MTPDpageBlockDivider &data) {
|
||||||
return tag("hr", { { "class", "iv-divider" } });
|
return tag("hr", { { "class", "divider" } });
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockAnchor &data) {
|
QByteArray Parser::block(const MTPDpageBlockAnchor &data) {
|
||||||
|
@ -285,7 +285,7 @@ QByteArray Parser::block(const MTPDpageBlockPullquote &data) {
|
||||||
: tag("cite", caption);
|
: tag("cite", caption);
|
||||||
return tag(
|
return tag(
|
||||||
"div",
|
"div",
|
||||||
{ { "class", "iv-pullquote" } },
|
{ { "class", "pullquote" } },
|
||||||
rich(data.vtext()) + cite);
|
rich(data.vtext()) + cite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,11 +313,11 @@ QByteArray Parser::block(const MTPDpageBlockPhoto &data) {
|
||||||
const auto style = "background-image:url('" + src + "');"
|
const auto style = "background-image:url('" + src + "');"
|
||||||
"padding-top:" + QByteArray::number(paddingTopPercent) + "%";
|
"padding-top:" + QByteArray::number(paddingTopPercent) + "%";
|
||||||
const auto inner = tag("div", {
|
const auto inner = tag("div", {
|
||||||
{ "class", "iv-photo" },
|
{ "class", "photo" },
|
||||||
{ "style", style } });
|
{ "style", style } });
|
||||||
auto result = tag(
|
auto result = tag(
|
||||||
"div",
|
"div",
|
||||||
{ { "class", "iv-photo-wrap" }, { "style", wrapStyle } },
|
{ { "class", "photo-wrap" }, { "style", wrapStyle } },
|
||||||
inner);
|
inner);
|
||||||
if (const auto url = data.vurl()) {
|
if (const auto url = data.vurl()) {
|
||||||
result = tag("a", { { "href", utf(*url) } }, result);
|
result = tag("a", { { "href", utf(*url) } }, result);
|
||||||
|
@ -552,7 +552,7 @@ QByteArray Parser::block(const MTPDpageBlockAudio &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockKicker &data) {
|
QByteArray Parser::block(const MTPDpageBlockKicker &data) {
|
||||||
return tag("h6", { { "class", "iv-kicker" } }, rich(data.vtext()));
|
return tag("h6", { { "class", "kicker" } }, rich(data.vtext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockTable &data) {
|
QByteArray Parser::block(const MTPDpageBlockTable &data) {
|
||||||
|
@ -599,9 +599,9 @@ QByteArray Parser::block(const MTPDpageBlockRelatedArticles &data) {
|
||||||
}
|
}
|
||||||
auto title = rich(data.vtitle());
|
auto title = rich(data.vtitle());
|
||||||
if (!title.isEmpty()) {
|
if (!title.isEmpty()) {
|
||||||
title = tag("h4", { { "class", "iv-related-title" } }, title);
|
title = tag("h4", { { "class", "related-title" } }, title);
|
||||||
}
|
}
|
||||||
return tag("section", { { "class", "iv-related" } }, title + result);
|
return tag("section", { { "class", "related" } }, title + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Parser::block(const MTPDpageBlockMap &data) {
|
QByteArray Parser::block(const MTPDpageBlockMap &data) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue