Load full webpage and update in IV.
This commit is contained in:
parent
0a87dbea68
commit
315859bf7b
10 changed files with 199 additions and 38 deletions
1
Telegram/Resources/iv_html/morphdom-umd.min.2.7.2.js
Normal file
1
Telegram/Resources/iv_html/morphdom-umd.min.2.7.2.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -335,39 +335,82 @@ var IV = {
|
||||||
}
|
}
|
||||||
IV.pending = [index, hash];
|
IV.pending = [index, hash];
|
||||||
if (!IV.cache[index]) {
|
if (!IV.cache[index]) {
|
||||||
IV.cache[index] = { loading: true };
|
IV.loadPage(index);
|
||||||
|
|
||||||
let xhr = new XMLHttpRequest();
|
|
||||||
xhr.onload = function () {
|
|
||||||
IV.cache[index].loading = false;
|
|
||||||
IV.cache[index].content = xhr.responseText;
|
|
||||||
if (IV.pending && IV.pending[0] == index) {
|
|
||||||
IV.navigateToLoaded(index, IV.pending[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.open('GET', 'page' + index + '.json');
|
|
||||||
xhr.send();
|
|
||||||
} else if (IV.cache[index].dom) {
|
} else if (IV.cache[index].dom) {
|
||||||
IV.navigateToDOM(index, hash);
|
IV.navigateToDOM(index, hash);
|
||||||
} else if (IV.cache[index].content) {
|
} else if (IV.cache[index].content) {
|
||||||
IV.navigateToLoaded(index, hash);
|
IV.navigateToLoaded(index, hash);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
applyUpdatedContent: function (index) {
|
||||||
|
if (IV.index != index) {
|
||||||
|
IV.cache[index].contentUpdated = (IV.cache[index].dom !== undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = JSON.parse(IV.cache[index].content);
|
||||||
|
var article = function (el) {
|
||||||
|
return el.getElementsByTagName('article')[0];
|
||||||
|
};
|
||||||
|
var from = article(IV.findPageScroll());
|
||||||
|
var to = article(IV.makeScrolledContent(data.html));
|
||||||
|
morphdom(from, to, {
|
||||||
|
onBeforeElUpdated: function (fromEl, toEl) {
|
||||||
|
if (fromEl.classList.contains('loaded')) {
|
||||||
|
toEl.classList.add('loaded');
|
||||||
|
}
|
||||||
|
return !fromEl.isEqualNode(toEl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
IV.initMedia();
|
||||||
|
eval(data.js);
|
||||||
|
},
|
||||||
|
loadPage: function (index) {
|
||||||
|
if (!IV.cache[index]) {
|
||||||
|
IV.cache[index] = {};
|
||||||
|
}
|
||||||
|
IV.cache[index].loading = true;
|
||||||
|
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.onload = function () {
|
||||||
|
IV.cache[index].loading = false;
|
||||||
|
IV.cache[index].content = xhr.responseText;
|
||||||
|
IV.applyUpdatedContent(index);
|
||||||
|
if (IV.pending && IV.pending[0] == index) {
|
||||||
|
IV.navigateToLoaded(index, IV.pending[1]);
|
||||||
|
}
|
||||||
|
if (IV.cache[index].reloadPending) {
|
||||||
|
IV.cache[index].reloadPending = false;
|
||||||
|
IV.reloadPage(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xhr.open('GET', 'page' + index + '.json');
|
||||||
|
xhr.send();
|
||||||
|
},
|
||||||
|
reloadPage: function (index) {
|
||||||
|
if (IV.cache[index] && IV.cache[index].loading) {
|
||||||
|
IV.cache[index].reloadPending = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IV.loadPage(index);
|
||||||
|
},
|
||||||
|
|
||||||
|
makeScrolledContent: function (html) {
|
||||||
|
var result = document.createElement('div');
|
||||||
|
result.className = 'page-scroll';
|
||||||
|
result.tabIndex = '-1';
|
||||||
|
result.innerHTML = '<div class="page-slide"><article>'
|
||||||
|
+ html
|
||||||
|
+ '</article></div>';
|
||||||
|
result.onscroll = IV.frameScrolled;
|
||||||
|
return result;
|
||||||
|
},
|
||||||
navigateToLoaded: function (index, hash) {
|
navigateToLoaded: function (index, hash) {
|
||||||
if (IV.cache[index].dom) {
|
if (IV.cache[index].dom) {
|
||||||
IV.navigateToDOM(index, hash);
|
IV.navigateToDOM(index, hash);
|
||||||
} else {
|
} else {
|
||||||
var data = JSON.parse(IV.cache[index].content);
|
var data = JSON.parse(IV.cache[index].content);
|
||||||
var el = document.createElement('div');
|
IV.cache[index].dom = IV.makeScrolledContent(data.html);
|
||||||
el.className = 'page-scroll';
|
|
||||||
el.tabIndex = '-1';
|
|
||||||
el.innerHTML = '<div class="page-slide"><article>'
|
|
||||||
+ data.html
|
|
||||||
+ '</article></div>';
|
|
||||||
el.onscroll = IV.frameScrolled;
|
|
||||||
IV.cache[index].dom = el;
|
|
||||||
|
|
||||||
IV.navigateToDOM(index, hash);
|
IV.navigateToDOM(index, hash);
|
||||||
eval(data.js);
|
eval(data.js);
|
||||||
|
@ -417,6 +460,14 @@ var IV = {
|
||||||
was.parentNode.appendChild(now);
|
was.parentNode.appendChild(now);
|
||||||
if (scroll !== undefined) {
|
if (scroll !== undefined) {
|
||||||
now.scrollTop = scroll;
|
now.scrollTop = scroll;
|
||||||
|
setTimeout(function () {
|
||||||
|
// When returning by history.back to an URL with a hash
|
||||||
|
// for the first time browser forces the scroll to the
|
||||||
|
// hash instead of the saved scroll position.
|
||||||
|
//
|
||||||
|
// This workaround prevents incorrect scroll position.
|
||||||
|
now.scrollTop = scroll;
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
now.classList.add(back ? 'hidden-left' : 'hidden-right');
|
now.classList.add(back ? 'hidden-left' : 'hidden-right');
|
||||||
|
@ -446,7 +497,12 @@ var IV = {
|
||||||
topBack.classList.remove('hidden');
|
topBack.classList.remove('hidden');
|
||||||
}
|
}
|
||||||
IV.index = index;
|
IV.index = index;
|
||||||
IV.initMedia();
|
if (IV.cache[index].contentUpdated) {
|
||||||
|
IV.cache[index].contentUpdated = false;
|
||||||
|
IV.applyUpdatedContent(index);
|
||||||
|
} else {
|
||||||
|
IV.initMedia();
|
||||||
|
}
|
||||||
if (scroll === undefined) {
|
if (scroll === undefined) {
|
||||||
IV.jumpToHash(hash, true);
|
IV.jumpToHash(hash, true);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
<file alias="page.js">../../iv_html/page.js</file>
|
<file alias="page.js">../../iv_html/page.js</file>
|
||||||
<file alias="highlight.css">../../iv_html/highlight.9.12.0.css</file>
|
<file alias="highlight.css">../../iv_html/highlight.9.12.0.css</file>
|
||||||
<file alias="highlight.js">../../iv_html/highlight.9.12.0.js</file>
|
<file alias="highlight.js">../../iv_html/highlight.9.12.0.js</file>
|
||||||
|
<file alias="morphdom.js">../../iv_html/morphdom-umd.min.2.7.2.js</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -281,6 +281,7 @@ bool WebPageData::applyChanges(
|
||||||
&& document == newDocument
|
&& document == newDocument
|
||||||
&& collage.items == newCollage.items
|
&& collage.items == newCollage.items
|
||||||
&& (!iv == !newIv)
|
&& (!iv == !newIv)
|
||||||
|
&& (!iv || iv->partial() == newIv->partial())
|
||||||
&& duration == newDuration
|
&& duration == newDuration
|
||||||
&& author == resultAuthor
|
&& author == resultAuthor
|
||||||
&& hasLargeMedia == (newHasLargeMedia ? 1 : 0)
|
&& hasLargeMedia == (newHasLargeMedia ? 1 : 0)
|
||||||
|
|
|
@ -161,9 +161,7 @@ namespace {
|
||||||
<meta name="robots" content="noindex, nofollow">
|
<meta name="robots" content="noindex, nofollow">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<script src="/iv/page.js"></script>
|
<script src="/iv/page.js"></script>
|
||||||
<script src="/iv/highlight.js"></script>
|
|
||||||
<link rel="stylesheet" href="/iv/page.css" />
|
<link rel="stylesheet" href="/iv/page.css" />
|
||||||
<link rel="stylesheet" href="/iv/highlight.css">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<button class="fixed_button hidden" id="top_back" onclick="IV.back();">
|
<button class="fixed_button hidden" id="top_back" onclick="IV.back();">
|
||||||
|
@ -193,6 +191,11 @@ namespace {
|
||||||
)"_q;
|
)"_q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QByteArray ReadResource(const QString &name) {
|
||||||
|
auto file = QFile(u":/iv/"_q + name);
|
||||||
|
return file.open(QIODevice::ReadOnly) ? file.readAll() : QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Controller::Controller()
|
Controller::Controller()
|
||||||
|
@ -225,11 +228,28 @@ void Controller::show(
|
||||||
base::flat_map<QByteArray, rpl::producer<bool>> inChannelValues) {
|
base::flat_map<QByteArray, rpl::producer<bool>> inChannelValues) {
|
||||||
page.script = fillInChannelValuesScript(std::move(inChannelValues));
|
page.script = fillInChannelValuesScript(std::move(inChannelValues));
|
||||||
_titleText.setText(st::ivTitle.style, page.title);
|
_titleText.setText(st::ivTitle.style, page.title);
|
||||||
|
_title->update();
|
||||||
InvokeQueued(_container, [=, page = std::move(page)]() mutable {
|
InvokeQueued(_container, [=, page = std::move(page)]() mutable {
|
||||||
showInWindow(dataPath, std::move(page));
|
showInWindow(dataPath, std::move(page));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Controller::update(Prepared page) {
|
||||||
|
const auto url = page.url;
|
||||||
|
auto i = _indices.find(url);
|
||||||
|
if (i == end(_indices)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto index = i->second;
|
||||||
|
_pages[index] = std::move(page);
|
||||||
|
|
||||||
|
if (_ready) {
|
||||||
|
_webview->eval(reloadScript(index));
|
||||||
|
} else if (!index) {
|
||||||
|
_reloadInitialWhenReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray Controller::fillInChannelValuesScript(
|
QByteArray Controller::fillInChannelValuesScript(
|
||||||
base::flat_map<QByteArray, rpl::producer<bool>> inChannelValues) {
|
base::flat_map<QByteArray, rpl::producer<bool>> inChannelValues) {
|
||||||
auto result = QByteArray();
|
auto result = QByteArray();
|
||||||
|
@ -426,6 +446,9 @@ void Controller::createWebview(const QString &dataPath) {
|
||||||
std::exchange(_navigateToIndexWhenReady, -1),
|
std::exchange(_navigateToIndexWhenReady, -1),
|
||||||
base::take(_navigateToHashWhenReady));
|
base::take(_navigateToHashWhenReady));
|
||||||
}
|
}
|
||||||
|
if (base::take(_reloadInitialWhenReady)) {
|
||||||
|
script += reloadScript(0);
|
||||||
|
}
|
||||||
if (!script.isEmpty()) {
|
if (!script.isEmpty()) {
|
||||||
_webview->eval(script);
|
_webview->eval(script);
|
||||||
}
|
}
|
||||||
|
@ -501,10 +524,13 @@ void Controller::createWebview(const QString &dataPath) {
|
||||||
const auto qstring = QString::fromUtf8(id.data(), id.size());
|
const auto qstring = QString::fromUtf8(id.data(), id.size());
|
||||||
const auto pattern = u"^[a-zA-Z\\.\\-_0-9]+$"_q;
|
const auto pattern = u"^[a-zA-Z\\.\\-_0-9]+$"_q;
|
||||||
if (QRegularExpression(pattern).match(qstring).hasMatch()) {
|
if (QRegularExpression(pattern).match(qstring).hasMatch()) {
|
||||||
auto file = QFile(u":/iv/"_q + qstring);
|
const auto bytes = ReadResource(qstring);
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
if (!bytes.isEmpty()) {
|
||||||
const auto mime = css ? "text/css" : "text/javascript";
|
const auto mime = css ? "text/css" : "text/javascript";
|
||||||
return finishWith(file.readAll(), mime);
|
const auto full = (qstring == u"page.js"_q)
|
||||||
|
? (ReadResource("morphdom.js") + bytes)
|
||||||
|
: bytes;
|
||||||
|
return finishWith(full, mime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Webview::DataResult::Failed;
|
return Webview::DataResult::Failed;
|
||||||
|
@ -560,6 +586,12 @@ QByteArray Controller::navigateScript(int index, const QString &hash) {
|
||||||
+ "');";
|
+ "');";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray Controller::reloadScript(int index) {
|
||||||
|
return "IV.reloadPage("
|
||||||
|
+ QByteArray::number(index)
|
||||||
|
+ ");";
|
||||||
|
}
|
||||||
|
|
||||||
void Controller::processKey(const QString &key, const QString &modifier) {
|
void Controller::processKey(const QString &key, const QString &modifier) {
|
||||||
const auto ctrl = Platform::IsMac() ? u"cmd"_q : u"ctrl"_q;
|
const auto ctrl = Platform::IsMac() ? u"cmd"_q : u"ctrl"_q;
|
||||||
if (key == u"escape"_q) {
|
if (key == u"escape"_q) {
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
const QString &dataPath,
|
const QString &dataPath,
|
||||||
Prepared page,
|
Prepared page,
|
||||||
base::flat_map<QByteArray, rpl::producer<bool>> inChannelValues);
|
base::flat_map<QByteArray, rpl::producer<bool>> inChannelValues);
|
||||||
|
void update(Prepared page);
|
||||||
|
|
||||||
[[nodiscard]] bool active() const;
|
[[nodiscard]] bool active() const;
|
||||||
void showJoinedTooltip();
|
void showJoinedTooltip();
|
||||||
void minimize();
|
void minimize();
|
||||||
|
@ -73,6 +75,7 @@ private:
|
||||||
void createWindow();
|
void createWindow();
|
||||||
void createWebview(const QString &dataPath);
|
void createWebview(const QString &dataPath);
|
||||||
[[nodiscard]] QByteArray navigateScript(int index, const QString &hash);
|
[[nodiscard]] QByteArray navigateScript(int index, const QString &hash);
|
||||||
|
[[nodiscard]] QByteArray reloadScript(int index);
|
||||||
|
|
||||||
void updateTitleGeometry();
|
void updateTitleGeometry();
|
||||||
void paintTitle(Painter &p, QRect clip);
|
void paintTitle(Painter &p, QRect clip);
|
||||||
|
@ -104,6 +107,7 @@ private:
|
||||||
base::flat_map<QByteArray, bool> _inChannelChanged;
|
base::flat_map<QByteArray, bool> _inChannelChanged;
|
||||||
base::flat_set<QByteArray> _inChannelSubscribed;
|
base::flat_set<QByteArray> _inChannelSubscribed;
|
||||||
SingleQueuedInvokation _updateStyles;
|
SingleQueuedInvokation _updateStyles;
|
||||||
|
bool _reloadInitialWhenReady = false;
|
||||||
bool _subscribedToColors = false;
|
bool _subscribedToColors = false;
|
||||||
bool _ready = false;
|
bool _ready = false;
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,10 @@ QString Data::id() const {
|
||||||
return qs(_source->page.data().vurl());
|
return qs(_source->page.data().vurl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Data::partial() const {
|
||||||
|
return _source->page.data().is_part();
|
||||||
|
}
|
||||||
|
|
||||||
Data::~Data() = default;
|
Data::~Data() = default;
|
||||||
|
|
||||||
void Data::prepare(const Options &options, Fn<void(Prepared)> done) const {
|
void Data::prepare(const Options &options, Fn<void(Prepared)> done) const {
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
~Data();
|
~Data();
|
||||||
|
|
||||||
[[nodiscard]] QString id() const;
|
[[nodiscard]] QString id() const;
|
||||||
|
[[nodiscard]] bool partial() const;
|
||||||
|
|
||||||
void prepare(const Options &options, Fn<void(Prepared)> done) const;
|
void prepare(const Options &options, Fn<void(Prepared)> done) const;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "iv/iv_instance.h"
|
#include "iv/iv_instance.h"
|
||||||
|
|
||||||
|
#include "base/call_delayed.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
|
@ -82,6 +83,7 @@ public:
|
||||||
[[nodiscard]] bool active() const;
|
[[nodiscard]] bool active() const;
|
||||||
|
|
||||||
void moveTo(not_null<Data*> data, QString hash);
|
void moveTo(not_null<Data*> data, QString hash);
|
||||||
|
void update(not_null<Data*> data);
|
||||||
|
|
||||||
void showJoinedTooltip();
|
void showJoinedTooltip();
|
||||||
void minimize();
|
void minimize();
|
||||||
|
@ -149,6 +151,7 @@ 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 fillEmbeds(base::flat_map<QByteArray, QByteArray> added);
|
||||||
void subscribeToDocuments();
|
void subscribeToDocuments();
|
||||||
[[nodiscard]] QByteArray readFile(
|
[[nodiscard]] QByteArray readFile(
|
||||||
const std::shared_ptr<::Data::DocumentMedia> &media);
|
const std::shared_ptr<::Data::DocumentMedia> &media);
|
||||||
|
@ -206,8 +209,8 @@ void Shown::prepare(not_null<Data*> data, const QString &hash) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_preparing = false;
|
_preparing = false;
|
||||||
_embeds = std::move(result.embeds);
|
|
||||||
fillChannelJoinedValues(result);
|
fillChannelJoinedValues(result);
|
||||||
|
fillEmbeds(std::move(result.embeds));
|
||||||
if (!base.isEmpty()) {
|
if (!base.isEmpty()) {
|
||||||
_localBase = base;
|
_localBase = base;
|
||||||
showLocal(std::move(result));
|
showLocal(std::move(result));
|
||||||
|
@ -234,6 +237,16 @@ void Shown::fillChannelJoinedValues(const Prepared &result) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shown::fillEmbeds(base::flat_map<QByteArray, QByteArray> added) {
|
||||||
|
if (_embeds.empty()) {
|
||||||
|
_embeds = std::move(added);
|
||||||
|
} else {
|
||||||
|
for (auto &[k, v] : added) {
|
||||||
|
_embeds[k] = std::move(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Shown::showLocal(Prepared result) {
|
void Shown::showLocal(Prepared result) {
|
||||||
showProgress(0);
|
showProgress(0);
|
||||||
|
|
||||||
|
@ -783,6 +796,23 @@ void Shown::moveTo(not_null<Data*> data, QString hash) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shown::update(not_null<Data*> data) {
|
||||||
|
const auto weak = base::make_weak(this);
|
||||||
|
|
||||||
|
const auto id = data->id();
|
||||||
|
const auto base = /*local ? LookupLocalPath(show) : */QString();
|
||||||
|
data->prepare({ .saveToFolder = base }, [=](Prepared result) {
|
||||||
|
crl::on_main(weak, [=, result = std::move(result)]() mutable {
|
||||||
|
result.url = id;
|
||||||
|
fillChannelJoinedValues(result);
|
||||||
|
fillEmbeds(std::move(result.embeds));
|
||||||
|
if (_controller) {
|
||||||
|
_controller->update(std::move(result));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Shown::showJoinedTooltip() {
|
void Shown::showJoinedTooltip() {
|
||||||
if (_controller) {
|
if (_controller) {
|
||||||
_controller->showJoinedTooltip();
|
_controller->showJoinedTooltip();
|
||||||
|
@ -804,6 +834,13 @@ void Instance::show(
|
||||||
not_null<Data*> data,
|
not_null<Data*> data,
|
||||||
QString hash) {
|
QString hash) {
|
||||||
const auto session = &show->session();
|
const auto session = &show->session();
|
||||||
|
const auto guard = gsl::finally([&] {
|
||||||
|
if (data->partial()) {
|
||||||
|
base::call_delayed(10000, [=] {
|
||||||
|
requestFull(session, data->id());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
if (_shown && _shownSession == session) {
|
if (_shown && _shownSession == session) {
|
||||||
_shown->moveTo(data, hash);
|
_shown->moveTo(data, hash);
|
||||||
return;
|
return;
|
||||||
|
@ -891,7 +928,9 @@ void Instance::show(
|
||||||
) | rpl::start_with_next([=](const ::Data::PeerUpdate &update) {
|
) | rpl::start_with_next([=](const ::Data::PeerUpdate &update) {
|
||||||
if (const auto channel = update.peer->asChannel()) {
|
if (const auto channel = update.peer->asChannel()) {
|
||||||
if (channel->amIn()) {
|
if (channel->amIn()) {
|
||||||
if (_joining.remove(not_null(channel))) {
|
const auto i = _joining.find(session);
|
||||||
|
const auto value = not_null{ channel };
|
||||||
|
if (i != end(_joining) && i->second.remove(value)) {
|
||||||
_shown->showJoinedTooltip();
|
_shown->showJoinedTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -902,13 +941,8 @@ void Instance::show(
|
||||||
_tracking.emplace(session);
|
_tracking.emplace(session);
|
||||||
session->lifetime().add([=] {
|
session->lifetime().add([=] {
|
||||||
_tracking.remove(session);
|
_tracking.remove(session);
|
||||||
for (auto i = begin(_joining); i != end(_joining);) {
|
_joining.remove(session);
|
||||||
if (&(*i)->session() == session) {
|
_fullRequested.remove(session);
|
||||||
i = _joining.erase(i);
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_shownSession == session) {
|
if (_shownSession == session) {
|
||||||
_shownSession = nullptr;
|
_shownSession = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -919,6 +953,27 @@ void Instance::show(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Instance::requestFull(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const QString &id) {
|
||||||
|
if (!_tracking.contains(session)
|
||||||
|
|| !_fullRequested[session].emplace(id).second) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
session->api().request(MTPmessages_GetWebPage(
|
||||||
|
MTP_string(id),
|
||||||
|
MTP_int(0)
|
||||||
|
)).done([=](const MTPmessages_WebPage &result) {
|
||||||
|
session->data().processUsers(result.data().vusers());
|
||||||
|
session->data().processChats(result.data().vchats());
|
||||||
|
const auto page = session->data().processWebpage(
|
||||||
|
result.data().vwebpage());
|
||||||
|
if (page && page->iv && _shown && _shownSession == session) {
|
||||||
|
_shown->update(page->iv.get());
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
void Instance::processOpenChannel(const QString &context) {
|
void Instance::processOpenChannel(const QString &context) {
|
||||||
if (!_shownSession) {
|
if (!_shownSession) {
|
||||||
return;
|
return;
|
||||||
|
@ -949,7 +1004,7 @@ void Instance::processJoinChannel(const QString &context) {
|
||||||
return;
|
return;
|
||||||
} else if (const auto channelId = ChannelId(context.toLongLong())) {
|
} else if (const auto channelId = ChannelId(context.toLongLong())) {
|
||||||
const auto channel = _shownSession->data().channel(channelId);
|
const auto channel = _shownSession->data().channel(channelId);
|
||||||
_joining.emplace(channel);
|
_joining[_shownSession].emplace(channel);
|
||||||
if (channel->isLoaded()) {
|
if (channel->isLoaded()) {
|
||||||
_shownSession->api().joinChannel(channel);
|
_shownSession->api().joinChannel(channel);
|
||||||
} else if (!channel->username().isEmpty()) {
|
} else if (!channel->username().isEmpty()) {
|
||||||
|
|
|
@ -40,11 +40,17 @@ public:
|
||||||
private:
|
private:
|
||||||
void processOpenChannel(const QString &context);
|
void processOpenChannel(const QString &context);
|
||||||
void processJoinChannel(const QString &context);
|
void processJoinChannel(const QString &context);
|
||||||
|
void requestFull(not_null<Main::Session*> session, const QString &id);
|
||||||
|
|
||||||
std::unique_ptr<Shown> _shown;
|
std::unique_ptr<Shown> _shown;
|
||||||
Main::Session *_shownSession = nullptr;
|
Main::Session *_shownSession = nullptr;
|
||||||
base::flat_set<not_null<Main::Session*>> _tracking;
|
base::flat_set<not_null<Main::Session*>> _tracking;
|
||||||
base::flat_set<not_null<ChannelData*>> _joining;
|
base::flat_map<
|
||||||
|
not_null<Main::Session*>,
|
||||||
|
base::flat_set<not_null<ChannelData*>>> _joining;
|
||||||
|
base::flat_map<
|
||||||
|
not_null<Main::Session*>,
|
||||||
|
base::flat_set<QString>> _fullRequested;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue