Use rpl for file download progress notifications.

This commit is contained in:
John Preston 2020-04-10 15:17:10 +04:00
parent bf616036b3
commit 97bab388ea
14 changed files with 125 additions and 142 deletions

View file

@ -1282,11 +1282,12 @@ ThumbnailSource::ThumbnailSource(
}
QImage ThumbnailSource::takeLoaded() {
const auto loader = currentLoader();
if (_bytesForAnimated.isEmpty()
&& _loader
&& _loader->finished()
&& !_loader->cancelled()) {
_bytesForAnimated = _loader->bytes();
&& loader
&& loader->finished()
&& !loader->cancelled()) {
_bytesForAnimated = loader->bytes();
}
auto result = StorageSource::takeLoaded();
if (!_bytesForAnimated.isEmpty()
@ -1301,16 +1302,4 @@ QByteArray ThumbnailSource::bytesForCache() {
return _bytesForAnimated;
}
std::unique_ptr<FileLoader> ThumbnailSource::createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) {
auto result = StorageSource::createLoader(
origin,
fromCloud,
autoLoading);
_loader = result.get();
return result;
}
} // namespace Stickers

View file

@ -178,14 +178,7 @@ public:
QByteArray bytesForCache() override;
protected:
std::unique_ptr<FileLoader> createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
private:
QPointer<FileLoader> _loader;
QByteArray _bytesForAnimated;
};

View file

@ -795,34 +795,32 @@ void DocumentData::automaticLoadSettingsChanged() {
}
bool DocumentData::loaded(bool check) const {
if (loading() && _loader->finished()) {
if (_loader->cancelled()) {
_flags |= Flag::DownloadCancelled;
destroyLoader();
} else {
auto that = const_cast<DocumentData*>(this);
that->setLocation(FileLocation(_loader->fileName()));
ActiveCache().decrement(that->_data.size());
that->_data = _loader->bytes();
ActiveCache().increment(that->_data.size());
that->setGoodThumbnailDataReady();
if (const auto media = activeMediaView()) {
media->setBytes(_loader->bytes());
media->checkStickerLarge(_loader.get());
}
destroyLoader();
if (!that->_data.isEmpty()) {
ActiveCache().up(that);
}
}
_owner->notifyDocumentLayoutChanged(this);
}
return !rawBytes().isEmpty() || !filepath(check).isEmpty();
}
void DocumentData::finishLoad() {
const auto guard = gsl::finally([&] {
destroyLoader();
});
if (_loader->cancelled()) {
_flags |= Flag::DownloadCancelled;
return;
}
setLocation(FileLocation(_loader->fileName()));
ActiveCache().decrement(_data.size());
_data = _loader->bytes();
ActiveCache().increment(_data.size());
setGoodThumbnailDataReady();
if (const auto media = activeMediaView()) {
media->setBytes(_loader->bytes());
media->checkStickerLarge(_loader.get());
}
if (!_data.isEmpty()) {
ActiveCache().up(this);
}
}
void DocumentData::destroyLoader() const {
if (!_loader) {
return;
@ -996,17 +994,7 @@ void DocumentData::save(
autoLoading,
cacheTag());
}
QObject::connect(
_loader.get(),
&FileLoader::progress,
App::main(),
[=](FileLoader *l) { App::main()->documentLoadProgress(l); });
QObject::connect(
_loader.get(),
&FileLoader::failed,
App::main(),
&MainWidget::documentLoadFailed);
handleLoaderUpdates();
}
if (loading()) {
_loader->start();
@ -1014,6 +1002,46 @@ void DocumentData::save(
_owner->notifyDocumentLayoutChanged(this);
}
void DocumentData::handleLoaderUpdates() {
_loader->updates(
) | rpl::start_with_next_error_done([=] {
_owner->documentLoadProgress(this);
}, [=](bool started) {
if (started) {
const auto origin = _loader->fileOrigin();
const auto failedFileName = _loader->fileName();
const auto retry = [=] {
Ui::hideLayer();
save(origin, failedFileName);
};
Ui::show(Box<ConfirmBox>(
tr::lng_download_finish_failed(tr::now),
crl::guard(&session(), retry)));
} else {
// Sometimes we have LOCATION_INVALID error in documents / stickers.
// Sometimes FILE_REFERENCE_EXPIRED could not be handled.
//
//const auto openSettings = [=] {
// Global::SetDownloadPath(QString());
// Global::SetDownloadPathBookmark(QByteArray());
// Ui::show(Box<DownloadPathBox>());
// Global::RefDownloadPathChanged().notify();
//};
//Ui::show(Box<ConfirmBox>(
// tr::lng_download_path_failed(tr::now),
// tr::lng_download_path_settings(tr::now),
// crl::guard(&session(), openSettings)));
}
finishLoad();
status = FileDownloadFailed;
_owner->documentLoadFail(this, started);
}, [=] {
finishLoad();
_owner->documentLoadDone(this);
}) | rpl::release();
}
void DocumentData::cancel() {
if (!loading()) {
return;
@ -1021,8 +1049,7 @@ void DocumentData::cancel() {
_flags |= Flag::DownloadCancelled;
destroyLoader();
_owner->notifyDocumentLayoutChanged(this);
App::main()->documentLoadProgress(this);
_owner->documentLoadDone(this);
}
bool DocumentData::cancelled() const {

View file

@ -287,6 +287,8 @@ private:
void setMaybeSupportsStreaming(bool supports);
void setLoadedInMediaCacheLocation();
void finishLoad();
void handleLoaderUpdates();
void destroyLoader() const;
[[nodiscard]] bool useStreamingLoader() const;

View file

@ -1114,6 +1114,25 @@ void Session::requestPollViewRepaint(not_null<const PollData*> poll) {
}
}
void Session::documentLoadProgress(not_null<DocumentData*> document) {
requestDocumentViewRepaint(document);
session().documentUpdated.notify(document, true);
if (document->isAudioFile()) {
::Media::Player::instance()->documentLoadProgress(document);
}
}
void Session::documentLoadDone(not_null<DocumentData*> document) {
notifyDocumentLayoutChanged(document);
}
void Session::documentLoadFail(
not_null<DocumentData*> document,
bool started) {
notifyDocumentLayoutChanged(document);
}
void Session::markMediaRead(not_null<const DocumentData*> document) {
const auto i = _documentItems.find(document);
if (i != end(_documentItems)) {

View file

@ -433,6 +433,10 @@ public:
void markMediaRead(not_null<const DocumentData*> document);
void requestPollViewRepaint(not_null<const PollData*> poll);
void documentLoadProgress(not_null<DocumentData*> document);
void documentLoadDone(not_null<DocumentData*> document);
void documentLoadFail(not_null<DocumentData*> document, bool started);
HistoryItem *addNewMessage(
const MTPMessage &data,
MTPDmessage_ClientFlags flags,

View file

@ -1252,53 +1252,6 @@ void MainWidget::exportTopBarHeightUpdated() {
}
}
void MainWidget::documentLoadProgress(FileLoader *loader) {
if (const auto documentId = loader ? loader->objId() : 0) {
documentLoadProgress(session().data().document(documentId));
}
}
void MainWidget::documentLoadProgress(DocumentData *document) {
session().data().requestDocumentViewRepaint(document);
session().documentUpdated.notify(document, true);
if (!document->loaded() && document->isAudioFile()) {
Media::Player::instance()->documentLoadProgress(document);
}
}
void MainWidget::documentLoadFailed(FileLoader *loader, bool started) {
const auto documentId = loader ? loader->objId() : 0;
if (!documentId) return;
const auto document = session().data().document(documentId);
if (started) {
const auto origin = loader->fileOrigin();
const auto failedFileName = loader->fileName();
Ui::show(Box<ConfirmBox>(tr::lng_download_finish_failed(tr::now), crl::guard(this, [=] {
Ui::hideLayer();
if (document) {
document->save(origin, failedFileName);
}
})));
} else {
// Sometimes we have LOCATION_INVALID error in documents / stickers.
// Sometimes FILE_REFERENCE_EXPIRED could not be handled.
//
//Ui::show(Box<ConfirmBox>(tr::lng_download_path_failed(tr::now), tr::lng_download_path_settings(tr::now), crl::guard(this, [=] {
// Global::SetDownloadPath(QString());
// Global::SetDownloadPathBookmark(QByteArray());
// Ui::show(Box<DownloadPathBox>());
// Global::RefDownloadPathChanged().notify();
//})));
}
if (document) {
if (document->loading()) document->cancel();
document->status = FileDownloadFailed;
}
}
void MainWidget::inlineResultLoadProgress(FileLoader *loader) {
//InlineBots::Result *result = InlineBots::resultFromLoader(loader);
//if (!result) return;

View file

@ -266,8 +266,6 @@ public:
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount);
void documentLoadProgress(DocumentData *document);
void searchInChat(Dialogs::Key chat);
void app_sendBotCallback(
@ -299,8 +297,6 @@ signals:
void dialogsUpdated();
public slots:
void documentLoadProgress(FileLoader *loader);
void documentLoadFailed(FileLoader *loader, bool started);
void inlineResultLoadProgress(FileLoader *loader);
void inlineResultLoadFailed(FileLoader *loader, bool started);

View file

@ -1738,16 +1738,14 @@ void FormController::loadFile(File &file) {
false,
Data::kImageCacheTag));
const auto loader = j->second.get();
loader->connect(loader, &mtpFileLoader::progress, [=] {
if (loader->finished()) {
fileLoadDone(key, loader->bytes());
} else {
fileLoadProgress(key, loader->currentOffset());
}
});
loader->connect(loader, &mtpFileLoader::failed, [=] {
loader->updates(
) | rpl::start_with_next_error_done([=] {
fileLoadProgress(key, loader->currentOffset());
}, [=](bool started) {
fileLoadFail(key);
});
}, [=] {
fileLoadDone(key, loader->bytes());
}) | rpl::release();
loader->start();
}

View file

@ -529,7 +529,7 @@ private:
Form _form;
bool _cancelled = false;
mtpRequestId _recoverRequestId = 0;
std::map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
base::flat_map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
rpl::event_stream<not_null<const EditFile*>> _scanUpdated;
rpl::event_stream<not_null<const Value*>> _valueSaveFinished;

View file

@ -72,7 +72,8 @@ void FileLoader::finishWithBytes(const QByteArray &data) {
Platform::File::PostprocessDownloaded(
QFileInfo(_file).absoluteFilePath());
}
Auth().downloaderTaskFinished().notify();
_session->downloaderTaskFinished().notify();
_updates.fire_done();
}
QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const {
@ -130,7 +131,7 @@ void FileLoader::permitLoadFromCloud() {
}
void FileLoader::notifyAboutProgress() {
emit progress(this);
_updates.fire({});
}
void FileLoader::localLoaded(
@ -148,7 +149,6 @@ void FileLoader::localLoaded(
_imageData = imageData;
}
finishWithBytes(result.data);
notifyAboutProgress();
}
void FileLoader::start() {
@ -186,7 +186,7 @@ void FileLoader::loadLocal(const Storage::Cache::Key &key) {
std::move(image));
});
};
session().data().cache().get(key, [=, callback = std::move(done)](
_session->data().cache().get(key, [=, callback = std::move(done)](
QByteArray &&value) mutable {
if (readImage) {
crl::async([
@ -218,10 +218,10 @@ bool FileLoader::tryLoadLocal() {
return true;
}
const auto weak = QPointer<FileLoader>(this);
const auto weak = base::make_weak(this);
if (_toCache == LoadToCacheAsWell) {
loadLocal(cacheKey());
emit progress(this);
notifyAboutProgress();
}
if (!weak) {
return false;
@ -253,11 +253,11 @@ void FileLoader::cancel(bool fail) {
}
_data = QByteArray();
const auto weak = QPointer<FileLoader>(this);
const auto weak = base::make_weak(this);
if (fail) {
emit failed(this, started);
_updates.fire_error_copy(started);
} else {
emit progress(this);
_updates.fire_done();
}
if (weak) {
_filename = QString();
@ -361,13 +361,14 @@ bool FileLoader::finalizeResult() {
}
if ((_toCache == LoadToCacheAsWell)
&& (_data.size() <= Storage::kMaxFileInMemory)) {
session().data().cache().put(
_session->data().cache().put(
cacheKey(),
Storage::Cache::Database::TaggedValue(
base::duplicate(_data),
_cacheTag));
}
}
Auth().downloaderTaskFinished().notify();
_session->downloaderTaskFinished().notify();
_updates.fire_done();
return true;
}

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/observer.h"
#include "base/timer.h"
#include "base/binary_guard.h"
#include "base/weak_ptr.h"
#include <QtNetwork/QNetworkReply>
@ -51,9 +52,7 @@ struct StorageImageSaved {
};
class FileLoader : public QObject {
Q_OBJECT
class FileLoader : public base::has_weak_ptr {
public:
FileLoader(
const QString &toFile,
@ -109,9 +108,9 @@ public:
const QByteArray &imageFormat,
const QImage &imageData);
signals:
void progress(FileLoader *loader);
void failed(FileLoader *loader, bool started);
[[nodiscard]] rpl::producer<rpl::empty_value, bool> updates() const {
return _updates.events();
}
protected:
enum class LocalStatus {
@ -139,6 +138,7 @@ protected:
[[nodiscard]] QByteArray readLoadedPartBack(int offset, int size);
const not_null<Main::Session*> _session;
rpl::event_stream<rpl::empty_value, bool> _updates;
bool _autoLoading = false;
uint8 _cacheTag = 0;

View file

@ -109,7 +109,6 @@ bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
if (buffer.empty() || (buffer.size() % 1024)) { // bad next offset
_lastComplete = true;
}
const auto weak = QPointer<mtpFileLoader>(this);
const auto finished = !haveSentRequests()
&& (_lastComplete || (_size && _nextRequestOffset >= _size));
if (finished) {
@ -117,8 +116,7 @@ bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
if (!finalizeResult()) {
return false;
}
}
if (weak) {
} else {
notifyAboutProgress();
}
return true;

View file

@ -148,6 +148,9 @@ protected:
bool autoLoading) = 0;
void loadLocal();
FileLoader *currentLoader() const {
return _loader.get();
}
private:
bool cancelled() const;