mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Extract Data::MediaPreload.
This commit is contained in:
parent
20f53c89ad
commit
677314dacb
5 changed files with 321 additions and 192 deletions
|
@ -569,6 +569,8 @@ PRIVATE
|
||||||
data/data_lastseen_status.h
|
data/data_lastseen_status.h
|
||||||
data/data_location.cpp
|
data/data_location.cpp
|
||||||
data/data_location.h
|
data/data_location.h
|
||||||
|
data/data_media_preload.cpp
|
||||||
|
data/data_media_preload.h
|
||||||
data/data_media_rotation.cpp
|
data/data_media_rotation.cpp
|
||||||
data/data_media_rotation.h
|
data/data_media_rotation.h
|
||||||
data/data_media_types.cpp
|
data/data_media_types.cpp
|
||||||
|
|
210
Telegram/SourceFiles/data/data_media_preload.cpp
Normal file
210
Telegram/SourceFiles/data/data_media_preload.cpp
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "data/data_media_preload.h"
|
||||||
|
|
||||||
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_document_media.h"
|
||||||
|
#include "data/data_file_origin.h"
|
||||||
|
#include "data/data_photo.h"
|
||||||
|
#include "data/data_photo_media.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "main/main_session_settings.h"
|
||||||
|
#include "media/streaming/media_streaming_reader.h"
|
||||||
|
#include "storage/file_download.h" // kMaxFileInMemory.
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kDefaultPreloadPrefix = 4 * 1024 * 1024;
|
||||||
|
|
||||||
|
[[nodiscard]] int64 ChoosePreloadPrefix(not_null<DocumentData*> video) {
|
||||||
|
const auto result = video->videoPreloadPrefix();
|
||||||
|
return result
|
||||||
|
? result
|
||||||
|
: std::min(int64(kDefaultPreloadPrefix), video->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
MediaPreload::MediaPreload(Fn<void()> done)
|
||||||
|
: _done(std::move(done)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaPreload::callDone() {
|
||||||
|
if (const auto onstack = _done) {
|
||||||
|
onstack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PhotoPreload::PhotoPreload(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FileOrigin origin,
|
||||||
|
Fn<void()> done)
|
||||||
|
: MediaPreload(std::move(done))
|
||||||
|
, _photo(photo->createMediaView()) {
|
||||||
|
start(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PhotoPreload::~PhotoPreload() {
|
||||||
|
if (_photo) {
|
||||||
|
base::take(_photo)->owner()->cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhotoPreload::Should(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
not_null<PeerData*> context) {
|
||||||
|
return !photo->cancelled()
|
||||||
|
&& AutoDownload::Should(
|
||||||
|
photo->session().settings().autoDownload(),
|
||||||
|
context,
|
||||||
|
photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoPreload::start(FileOrigin origin) {
|
||||||
|
if (_photo->loaded()) {
|
||||||
|
callDone();
|
||||||
|
} else {
|
||||||
|
_photo->owner()->load(origin, LoadFromCloudOrLocal, true);
|
||||||
|
_photo->owner()->session().downloaderTaskFinished(
|
||||||
|
) | rpl::filter([=] {
|
||||||
|
return _photo->loaded();
|
||||||
|
}) | rpl::start_with_next([=] { callDone(); }, _lifetime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoPreload::VideoPreload(
|
||||||
|
not_null<DocumentData*> video,
|
||||||
|
FileOrigin origin,
|
||||||
|
Fn<void()> done)
|
||||||
|
: MediaPreload(std::move(done))
|
||||||
|
, DownloadMtprotoTask(
|
||||||
|
&video->session().downloader(),
|
||||||
|
video->videoPreloadLocation(),
|
||||||
|
origin)
|
||||||
|
, _video(video)
|
||||||
|
, _full(video->size) {
|
||||||
|
if (Can(video)) {
|
||||||
|
check();
|
||||||
|
} else {
|
||||||
|
callDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoPreload::check() {
|
||||||
|
const auto key = _video->bigFileBaseCacheKey();
|
||||||
|
const auto weak = base::make_weak(static_cast<has_weak_ptr*>(this));
|
||||||
|
_video->owner().cacheBigFile().get(key, [weak](
|
||||||
|
const QByteArray &result) {
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
crl::on_main([weak] {
|
||||||
|
if (const auto strong = weak.get()) {
|
||||||
|
static_cast<VideoPreload*>(strong)->callDone();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
crl::on_main([weak] {
|
||||||
|
if (const auto strong = weak.get()) {
|
||||||
|
static_cast<VideoPreload*>(strong)->load();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoPreload::load() {
|
||||||
|
if (!Can(_video)) {
|
||||||
|
callDone();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto key = _video->bigFileBaseCacheKey();
|
||||||
|
const auto prefix = ChoosePreloadPrefix(_video);
|
||||||
|
Assert(prefix > 0 && prefix <= _video->size);
|
||||||
|
const auto part = Storage::kDownloadPartSize;
|
||||||
|
const auto parts = (prefix + part - 1) / part;
|
||||||
|
for (auto i = 0; i != parts; ++i) {
|
||||||
|
_parts.emplace(i * part, QByteArray());
|
||||||
|
}
|
||||||
|
addToQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoPreload::done(QByteArray result) {
|
||||||
|
const auto key = _video->bigFileBaseCacheKey();
|
||||||
|
if (!result.isEmpty() && key) {
|
||||||
|
Assert(result.size() < Storage::kMaxFileInMemory);
|
||||||
|
_video->owner().cacheBigFile().putIfEmpty(
|
||||||
|
key,
|
||||||
|
Storage::Cache::Database::TaggedValue(std::move(result), 0));
|
||||||
|
}
|
||||||
|
callDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoPreload::~VideoPreload() {
|
||||||
|
if (!_finished && !_failed) {
|
||||||
|
cancelAllRequests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoPreload::Can(not_null<DocumentData*> video) {
|
||||||
|
return video->canBeStreamed(nullptr)
|
||||||
|
&& video->videoPreloadLocation().valid()
|
||||||
|
&& video->bigFileBaseCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoPreload::readyToRequest() const {
|
||||||
|
const auto part = Storage::kDownloadPartSize;
|
||||||
|
return !_failed && (_nextRequestOffset < _parts.size() * part);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 VideoPreload::takeNextRequestOffset() {
|
||||||
|
Expects(readyToRequest());
|
||||||
|
|
||||||
|
_requestedOffsets.emplace(_nextRequestOffset);
|
||||||
|
_nextRequestOffset += Storage::kDownloadPartSize;
|
||||||
|
return _requestedOffsets.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoPreload::feedPart(
|
||||||
|
int64 offset,
|
||||||
|
const QByteArray &bytes) {
|
||||||
|
Expects(offset < _parts.size() * Storage::kDownloadPartSize);
|
||||||
|
Expects(_requestedOffsets.contains(int(offset)));
|
||||||
|
Expects(bytes.size() <= Storage::kDownloadPartSize);
|
||||||
|
|
||||||
|
const auto part = Storage::kDownloadPartSize;
|
||||||
|
_requestedOffsets.remove(int(offset));
|
||||||
|
_parts[offset] = bytes;
|
||||||
|
if ((_nextRequestOffset + part >= _parts.size() * part)
|
||||||
|
&& _requestedOffsets.empty()) {
|
||||||
|
_finished = true;
|
||||||
|
removeFromQueue();
|
||||||
|
auto result = ::Media::Streaming::SerializeComplexPartsMap(_parts);
|
||||||
|
if (result.size() == _full) {
|
||||||
|
// Make sure it is parsed as a complex map.
|
||||||
|
result.push_back(char(0));
|
||||||
|
}
|
||||||
|
done(std::move(result));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoPreload::cancelOnFail() {
|
||||||
|
_failed = true;
|
||||||
|
cancelAllRequests();
|
||||||
|
done({});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoPreload::setWebFileSizeHook(int64 size) {
|
||||||
|
_failed = true;
|
||||||
|
cancelAllRequests();
|
||||||
|
done({});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Data
|
83
Telegram/SourceFiles/data/data_media_preload.h
Normal file
83
Telegram/SourceFiles/data/data_media_preload.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "storage/download_manager_mtproto.h"
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
class PhotoMedia;
|
||||||
|
struct FileOrigin;
|
||||||
|
|
||||||
|
class MediaPreload {
|
||||||
|
public:
|
||||||
|
explicit MediaPreload(Fn<void()> done);
|
||||||
|
virtual ~MediaPreload() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void callDone();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Fn<void()> _done;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class PhotoPreload final : public MediaPreload {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] static bool Should(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
not_null<PeerData*> context);
|
||||||
|
|
||||||
|
PhotoPreload(
|
||||||
|
not_null<PhotoData*> data,
|
||||||
|
FileOrigin origin,
|
||||||
|
Fn<void()> done);
|
||||||
|
~PhotoPreload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void start(FileOrigin origin);
|
||||||
|
|
||||||
|
std::shared_ptr<PhotoMedia> _photo;
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class VideoPreload final
|
||||||
|
: public MediaPreload
|
||||||
|
, private Storage::DownloadMtprotoTask {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] static bool Can(not_null<DocumentData*> video);
|
||||||
|
|
||||||
|
VideoPreload(
|
||||||
|
not_null<DocumentData*> video,
|
||||||
|
FileOrigin origin,
|
||||||
|
Fn<void()> done);
|
||||||
|
~VideoPreload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void check();
|
||||||
|
void load();
|
||||||
|
void done(QByteArray result);
|
||||||
|
|
||||||
|
bool readyToRequest() const override;
|
||||||
|
int64 takeNextRequestOffset() override;
|
||||||
|
bool feedPart(int64 offset, const QByteArray &bytes) override;
|
||||||
|
void cancelOnFail() override;
|
||||||
|
bool setWebFileSizeHook(int64 size) override;
|
||||||
|
|
||||||
|
const not_null<DocumentData*> _video;
|
||||||
|
base::flat_map<uint32, QByteArray> _parts;
|
||||||
|
base::flat_set<int> _requestedOffsets;
|
||||||
|
int64 _full = 0;
|
||||||
|
int _nextRequestOffset = 0;
|
||||||
|
bool _finished = false;
|
||||||
|
bool _failed = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Data
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
#include "data/data_media_preload.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_photo_media.h"
|
#include "data/data_photo_media.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
|
@ -230,107 +231,6 @@ using UpdateFlag = StoryUpdate::Flag;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class StoryPreload::LoadTask final : private Storage::DownloadMtprotoTask {
|
|
||||||
public:
|
|
||||||
LoadTask(
|
|
||||||
FullStoryId id,
|
|
||||||
not_null<DocumentData*> document,
|
|
||||||
Fn<void(QByteArray)> done);
|
|
||||||
~LoadTask();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool readyToRequest() const override;
|
|
||||||
int64 takeNextRequestOffset() override;
|
|
||||||
bool feedPart(int64 offset, const QByteArray &bytes) override;
|
|
||||||
void cancelOnFail() override;
|
|
||||||
bool setWebFileSizeHook(int64 size) override;
|
|
||||||
|
|
||||||
base::flat_map<uint32, QByteArray> _parts;
|
|
||||||
Fn<void(QByteArray)> _done;
|
|
||||||
base::flat_set<int> _requestedOffsets;
|
|
||||||
int64 _full = 0;
|
|
||||||
int _nextRequestOffset = 0;
|
|
||||||
bool _finished = false;
|
|
||||||
bool _failed = false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
StoryPreload::LoadTask::LoadTask(
|
|
||||||
FullStoryId id,
|
|
||||||
not_null<DocumentData*> document,
|
|
||||||
Fn<void(QByteArray)> done)
|
|
||||||
: DownloadMtprotoTask(
|
|
||||||
&document->session().downloader(),
|
|
||||||
document->videoPreloadLocation(),
|
|
||||||
id)
|
|
||||||
, _done(std::move(done))
|
|
||||||
, _full(document->size) {
|
|
||||||
const auto prefix = document->videoPreloadPrefix();
|
|
||||||
Assert(prefix > 0 && prefix <= document->size);
|
|
||||||
const auto part = Storage::kDownloadPartSize;
|
|
||||||
const auto parts = (prefix + part - 1) / part;
|
|
||||||
for (auto i = 0; i != parts; ++i) {
|
|
||||||
_parts.emplace(i * part, QByteArray());
|
|
||||||
}
|
|
||||||
addToQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
StoryPreload::LoadTask::~LoadTask() {
|
|
||||||
if (!_finished && !_failed) {
|
|
||||||
cancelAllRequests();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StoryPreload::LoadTask::readyToRequest() const {
|
|
||||||
const auto part = Storage::kDownloadPartSize;
|
|
||||||
return !_failed && (_nextRequestOffset < _parts.size() * part);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 StoryPreload::LoadTask::takeNextRequestOffset() {
|
|
||||||
Expects(readyToRequest());
|
|
||||||
|
|
||||||
_requestedOffsets.emplace(_nextRequestOffset);
|
|
||||||
_nextRequestOffset += Storage::kDownloadPartSize;
|
|
||||||
return _requestedOffsets.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StoryPreload::LoadTask::feedPart(
|
|
||||||
int64 offset,
|
|
||||||
const QByteArray &bytes) {
|
|
||||||
Expects(offset < _parts.size() * Storage::kDownloadPartSize);
|
|
||||||
Expects(_requestedOffsets.contains(int(offset)));
|
|
||||||
Expects(bytes.size() <= Storage::kDownloadPartSize);
|
|
||||||
|
|
||||||
const auto part = Storage::kDownloadPartSize;
|
|
||||||
_requestedOffsets.remove(int(offset));
|
|
||||||
_parts[offset] = bytes;
|
|
||||||
if ((_nextRequestOffset + part >= _parts.size() * part)
|
|
||||||
&& _requestedOffsets.empty()) {
|
|
||||||
_finished = true;
|
|
||||||
removeFromQueue();
|
|
||||||
auto result = ::Media::Streaming::SerializeComplexPartsMap(_parts);
|
|
||||||
if (result.size() == _full) {
|
|
||||||
// Make sure it is parsed as a complex map.
|
|
||||||
result.push_back(char(0));
|
|
||||||
}
|
|
||||||
_done(result);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryPreload::LoadTask::cancelOnFail() {
|
|
||||||
_failed = true;
|
|
||||||
cancelAllRequests();
|
|
||||||
_done({});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StoryPreload::LoadTask::setWebFileSizeHook(int64 size) {
|
|
||||||
_failed = true;
|
|
||||||
cancelAllRequests();
|
|
||||||
_done({});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Story::Story(
|
Story::Story(
|
||||||
StoryId id,
|
StoryId id,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
@ -999,17 +899,32 @@ PeerData *Story::fromPeer() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
StoryPreload::StoryPreload(not_null<Story*> story, Fn<void()> done)
|
StoryPreload::StoryPreload(not_null<Story*> story, Fn<void()> done)
|
||||||
: _story(story)
|
: _story(story) {
|
||||||
, _done(std::move(done)) {
|
if (const auto photo = _story->photo()) {
|
||||||
start();
|
if (PhotoPreload::Should(photo, story->peer())) {
|
||||||
}
|
_task = std::make_unique<PhotoPreload>(
|
||||||
|
photo,
|
||||||
StoryPreload::~StoryPreload() {
|
story->fullId(),
|
||||||
if (_photo) {
|
std::move(done));
|
||||||
base::take(_photo)->owner()->cancel();
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else if (const auto video = _story->document()) {
|
||||||
|
if (VideoPreload::Can(video)) {
|
||||||
|
_task = std::make_unique<VideoPreload>(
|
||||||
|
video,
|
||||||
|
story->fullId(),
|
||||||
|
std::move(done));
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StoryPreload::~StoryPreload() = default;
|
||||||
|
|
||||||
FullStoryId StoryPreload::id() const {
|
FullStoryId StoryPreload::id() const {
|
||||||
return _story->fullId();
|
return _story->fullId();
|
||||||
}
|
}
|
||||||
|
@ -1018,76 +933,4 @@ not_null<Story*> StoryPreload::story() const {
|
||||||
return _story;
|
return _story;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryPreload::start() {
|
|
||||||
if (const auto photo = _story->photo()) {
|
|
||||||
_photo = photo->createMediaView();
|
|
||||||
if (_photo->loaded()) {
|
|
||||||
callDone();
|
|
||||||
} else {
|
|
||||||
_photo->automaticLoad(_story->fullId(), _story->peer());
|
|
||||||
photo->session().downloaderTaskFinished(
|
|
||||||
) | rpl::filter([=] {
|
|
||||||
return _photo->loaded();
|
|
||||||
}) | rpl::start_with_next([=] { callDone(); }, _lifetime);
|
|
||||||
}
|
|
||||||
} else if (const auto video = _story->document()) {
|
|
||||||
if (video->canBeStreamed(nullptr) && video->videoPreloadPrefix()) {
|
|
||||||
const auto key = video->bigFileBaseCacheKey();
|
|
||||||
if (key) {
|
|
||||||
const auto weak = base::make_weak(this);
|
|
||||||
video->owner().cacheBigFile().get(key, [weak](
|
|
||||||
const QByteArray &result) {
|
|
||||||
if (!result.isEmpty()) {
|
|
||||||
crl::on_main([weak] {
|
|
||||||
if (const auto strong = weak.get()) {
|
|
||||||
strong->callDone();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
crl::on_main([weak] {
|
|
||||||
if (const auto strong = weak.get()) {
|
|
||||||
strong->load();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callDone();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callDone();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callDone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryPreload::load() {
|
|
||||||
Expects(_story->document() != nullptr);
|
|
||||||
|
|
||||||
const auto video = _story->document();
|
|
||||||
const auto valid = video->videoPreloadLocation().valid();
|
|
||||||
const auto prefix = video->videoPreloadPrefix();
|
|
||||||
const auto key = video->bigFileBaseCacheKey();
|
|
||||||
if (!valid || prefix <= 0 || prefix > video->size || !key) {
|
|
||||||
callDone();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_task = std::make_unique<LoadTask>(id(), video, [=](QByteArray data) {
|
|
||||||
if (!data.isEmpty()) {
|
|
||||||
Assert(data.size() < Storage::kMaxFileInMemory);
|
|
||||||
_story->owner().cacheBigFile().putIfEmpty(
|
|
||||||
key,
|
|
||||||
Storage::Cache::Database::TaggedValue(std::move(data), 0));
|
|
||||||
}
|
|
||||||
callDone();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryPreload::callDone() {
|
|
||||||
if (const auto onstack = _done) {
|
|
||||||
onstack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Data {
|
||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
class Thread;
|
class Thread;
|
||||||
class PhotoMedia;
|
class MediaPreload;
|
||||||
|
|
||||||
enum class StoryPrivacy : uchar {
|
enum class StoryPrivacy : uchar {
|
||||||
Public,
|
Public,
|
||||||
|
@ -301,18 +301,9 @@ public:
|
||||||
[[nodiscard]] not_null<Story*> story() const;
|
[[nodiscard]] not_null<Story*> story() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class LoadTask;
|
|
||||||
|
|
||||||
void start();
|
|
||||||
void load();
|
|
||||||
void callDone();
|
|
||||||
|
|
||||||
const not_null<Story*> _story;
|
const not_null<Story*> _story;
|
||||||
Fn<void()> _done;
|
|
||||||
|
|
||||||
std::shared_ptr<Data::PhotoMedia> _photo;
|
std::unique_ptr<MediaPreload> _task;
|
||||||
std::unique_ptr<LoadTask> _task;
|
|
||||||
rpl::lifetime _lifetime;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue