diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index e11fcdf2b05878..d9e3dde2b2d789 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1690,11 +1690,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_export_progress" = "Note: Please don't close Telegram while exporting files and personal data."; "lng_export_stop" = "Stop"; "lng_export_sure_stop" = "Are you sure you want to stop exporting your data?\n\nThis action cannot be undone."; -"lng_export_about_done" = "Your data is successfully exported."; +"lng_export_about_done" = "Your data was successfully exported."; "lng_export_done" = "Show my data"; "lng_export_finished" = "Export is finished."; -"lng_export_total_files" = "Total files: {count}"; -"lng_export_total_size" = "Total size: {size}"; +"lng_export_total_files" = "Total files: {count}."; +"lng_export_total_size" = "Total size: {size}."; // Wnd specific diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp index a6dad613211c62..be5579050d8b0d 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.cpp +++ b/Telegram/SourceFiles/export/export_api_wrap.cpp @@ -135,7 +135,7 @@ struct ApiWrap::UserpicsProcess { }; struct ApiWrap::FileProcess { - FileProcess(const QString &path); + FileProcess(const QString &path, Output::Stats *stats); Output::File file; QString relativePath; @@ -222,7 +222,8 @@ base::optional ApiWrap::LoadedFileCache::find( return base::none; } -ApiWrap::FileProcess::FileProcess(const QString &path) : file(path) { +ApiWrap::FileProcess::FileProcess(const QString &path, Output::Stats *stats) +: file(path, stats) { } template @@ -267,11 +268,13 @@ rpl::producer ApiWrap::ioErrors() const { void ApiWrap::startExport( const Settings &settings, + Output::Stats *stats, FnMut done) { Expects(_settings == nullptr); Expects(_startProcess == nullptr); _settings = std::make_unique(settings); + _stats = stats; _startProcess = std::make_unique(); _startProcess->done = std::move(done); @@ -1079,7 +1082,8 @@ auto ApiWrap::prepareFileProcess(const Data::File &file) const _settings->path, file.suggestedPath); auto result = std::make_unique( - _settings->path + relativePath); + _settings->path + relativePath, + _stats); result->relativePath = relativePath; result->location = file.location; result->size = file.size; diff --git a/Telegram/SourceFiles/export/export_api_wrap.h b/Telegram/SourceFiles/export/export_api_wrap.h index ce52f1b13ede29..376fe143ba0d05 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.h +++ b/Telegram/SourceFiles/export/export_api_wrap.h @@ -27,13 +27,14 @@ struct Message; namespace Output { struct Result; +class Stats; } // namespace Output struct Settings; class ApiWrap { public: - ApiWrap(Fn)> runner); + explicit ApiWrap(Fn)> runner); rpl::producer errors() const; rpl::producer ioErrors() const; @@ -45,6 +46,7 @@ class ApiWrap { }; void startExport( const Settings &settings, + Output::Stats *stats, FnMut done); void requestLeftChannelsList( @@ -155,6 +157,7 @@ class ApiWrap { MTP::ConcurrentSender _mtp; base::optional _takeoutId; + Output::Stats *_stats = nullptr; std::unique_ptr _settings; MTPInputUser _user = MTP_inputUserSelf(); diff --git a/Telegram/SourceFiles/export/export_controller.cpp b/Telegram/SourceFiles/export/export_controller.cpp index f5159063d7243e..8b33a81eb13652 100644 --- a/Telegram/SourceFiles/export/export_controller.cpp +++ b/Telegram/SourceFiles/export/export_controller.cpp @@ -12,6 +12,7 @@ For license and copyright information please follow this link: #include "export/data/export_data_types.h" #include "export/output/export_output_abstract.h" #include "export/output/export_output_result.h" +#include "export/output/export_output_stats.h" namespace Export { @@ -102,6 +103,9 @@ class Controller { // rpl::variable fails to compile in MSVC :( State _state; rpl::event_stream _stateChanges; + + Output::Stats _stats; + std::vector _substepsInStep; int _substepsTotal = 0; mutable int _substepsPassed = 0; @@ -321,7 +325,7 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) { void Controller::exportNext() { if (!++_stepIndex) { - if (ioCatchError(_writer->start(_settings))) { + if (ioCatchError(_writer->start(_settings, &_stats))) { return; } } @@ -350,7 +354,7 @@ void Controller::exportNext() { void Controller::initialize() { setState(stateInitializing()); - _api.startExport(_settings, [=](ApiWrap::StartInfo info) { + _api.startExport(_settings, &_stats, [=](ApiWrap::StartInfo info) { fillSubstepsInSteps(info); exportNext(); }); @@ -642,7 +646,10 @@ int Controller::substepsInStep(Step step) const { } void Controller::setFinishedState() { - setState(FinishedState{ _writer->mainFilePath() }); + setState(FinishedState{ + _writer->mainFilePath(), + _stats.filesCount(), + _stats.bytesCount() }); } ControllerWrap::ControllerWrap() { diff --git a/Telegram/SourceFiles/export/export_pch.h b/Telegram/SourceFiles/export/export_pch.h index bfb80883b3605e..b089b6f1d30d39 100644 --- a/Telegram/SourceFiles/export/export_pch.h +++ b/Telegram/SourceFiles/export/export_pch.h @@ -22,6 +22,7 @@ For license and copyright information please follow this link: #include #include #include +#include #include #ifdef Q_OS_WIN diff --git a/Telegram/SourceFiles/export/output/export_output_abstract.h b/Telegram/SourceFiles/export/output/export_output_abstract.h index c1f20b8ab660a2..1122d718810c95 100644 --- a/Telegram/SourceFiles/export/output/export_output_abstract.h +++ b/Telegram/SourceFiles/export/output/export_output_abstract.h @@ -26,6 +26,7 @@ struct Settings; namespace Output { struct Result; +class Stats; enum class Format { Text, @@ -36,7 +37,9 @@ enum class Format { class AbstractWriter { public: - [[nodiscard]] virtual Result start(const Settings &settings) = 0; + [[nodiscard]] virtual Result start( + const Settings &settings, + Stats *stats) = 0; [[nodiscard]] virtual Result writePersonal( const Data::PersonalInfo &data) = 0; diff --git a/Telegram/SourceFiles/export/output/export_output_file.cpp b/Telegram/SourceFiles/export/output/export_output_file.cpp index d16a92b5881f20..c90cdf558c18c7 100644 --- a/Telegram/SourceFiles/export/output/export_output_file.cpp +++ b/Telegram/SourceFiles/export/output/export_output_file.cpp @@ -8,6 +8,7 @@ For license and copyright information please follow this link: #include "export/output/export_output_file.h" #include "export/output/export_output_result.h" +#include "export/output/export_output_stats.h" #include #include @@ -17,7 +18,7 @@ For license and copyright information please follow this link: namespace Export { namespace Output { -File::File(const QString &path) : _path(path) { +File::File(const QString &path, Stats *stats) : _path(path), _stats(stats) { } int File::size() const { @@ -37,11 +38,22 @@ Result File::writeBlock(const QByteArray &block) { } Result File::writeBlockAttempt(const QByteArray &block) { + if (_stats && !_inStats) { + _inStats = true; + _stats->incrementFiles(); + } if (const auto result = reopen(); !result) { return result; } - if (_file->write(block) == block.size() && _file->flush()) { - _offset += block.size(); + const auto size = block.size(); + if (!size) { + return Result::Success(); + } + if (_file->write(block) == size && _file->flush()) { + _offset += size; + if (_stats) { + _stats->incrementBytes(size); + } return Result::Success(); } return error(); diff --git a/Telegram/SourceFiles/export/output/export_output_file.h b/Telegram/SourceFiles/export/output/export_output_file.h index b22b948590fb85..d72e4420faff5a 100644 --- a/Telegram/SourceFiles/export/output/export_output_file.h +++ b/Telegram/SourceFiles/export/output/export_output_file.h @@ -17,10 +17,11 @@ namespace Export { namespace Output { struct Result; +class Stats; class File { public: - File(const QString &path); + File(const QString &path, Stats *stats); [[nodiscard]] int size() const; [[nodiscard]] bool empty() const; @@ -42,6 +43,9 @@ class File { int _offset = 0; base::optional _file; + Stats *_stats = nullptr; + bool _inStats = false; + }; } // namespace Output diff --git a/Telegram/SourceFiles/export/output/export_output_stats.cpp b/Telegram/SourceFiles/export/output/export_output_stats.cpp new file mode 100644 index 00000000000000..80cb0557ffb82c --- /dev/null +++ b/Telegram/SourceFiles/export/output/export_output_stats.cpp @@ -0,0 +1,30 @@ +/* +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 "export/output/export_output_stats.h" + +namespace Export { +namespace Output { + +void Stats::incrementFiles() { + ++_files; +} + +void Stats::incrementBytes(int count) { + _bytes += count; +} + +int Stats::filesCount() const { + return _files; +} + +int64 Stats::bytesCount() const { + return _bytes; +} + +} // namespace Output +} // namespace Export diff --git a/Telegram/SourceFiles/export/output/export_output_stats.h b/Telegram/SourceFiles/export/output/export_output_stats.h new file mode 100644 index 00000000000000..0277bb3c000420 --- /dev/null +++ b/Telegram/SourceFiles/export/output/export_output_stats.h @@ -0,0 +1,30 @@ +/* +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 + +namespace Export { +namespace Output { + +class Stats { +public: + void incrementFiles(); + void incrementBytes(int count); + + int filesCount() const; + int64 bytesCount() const; + +private: + std::atomic _files; + std::atomic _bytes; + +}; + +} // namespace Output +} // namespace Export diff --git a/Telegram/SourceFiles/export/output/export_output_text.cpp b/Telegram/SourceFiles/export/output/export_output_text.cpp index f63d3c05e0a083..c388d314980cd9 100644 --- a/Telegram/SourceFiles/export/output/export_output_text.cpp +++ b/Telegram/SourceFiles/export/output/export_output_text.cpp @@ -432,10 +432,11 @@ QByteArray SerializeMessage( } // namespace -Result TextWriter::start(const Settings &settings) { +Result TextWriter::start(const Settings &settings, Stats *stats) { Expects(settings.path.endsWith('/')); _settings = base::duplicate(settings); + _stats = stats; _summary = fileWithRelativePath(mainFileRelativePath()); return Result::Success(); } @@ -827,7 +828,7 @@ QString TextWriter::pathWithRelativePath(const QString &path) const { std::unique_ptr TextWriter::fileWithRelativePath( const QString &path) const { - return std::make_unique(pathWithRelativePath(path)); + return std::make_unique(pathWithRelativePath(path), _stats); } } // namespace Output diff --git a/Telegram/SourceFiles/export/output/export_output_text.h b/Telegram/SourceFiles/export/output/export_output_text.h index b7c4303daf31cd..e4dc76556b7f4c 100644 --- a/Telegram/SourceFiles/export/output/export_output_text.h +++ b/Telegram/SourceFiles/export/output/export_output_text.h @@ -16,7 +16,7 @@ namespace Output { class TextWriter : public AbstractWriter { public: - Result start(const Settings &settings) override; + Result start(const Settings &settings, Stats *stats) override; Result writePersonal(const Data::PersonalInfo &data) override; @@ -61,6 +61,7 @@ class TextWriter : public AbstractWriter { Result writeChatEnd(); Settings _settings; + Stats *_stats = nullptr; std::unique_ptr _summary; int _userpicsCount = 0; diff --git a/Telegram/gyp/lib_export.gyp b/Telegram/gyp/lib_export.gyp index d79f43b039c337..5a98a1c917a57d 100644 --- a/Telegram/gyp/lib_export.gyp +++ b/Telegram/gyp/lib_export.gyp @@ -61,6 +61,8 @@ '<(src_loc)/export/output/export_output_abstract.h', '<(src_loc)/export/output/export_output_file.cpp', '<(src_loc)/export/output/export_output_file.h', + '<(src_loc)/export/output/export_output_stats.cpp', + '<(src_loc)/export/output/export_output_stats.h', '<(src_loc)/export/output/export_output_text.cpp', '<(src_loc)/export/output/export_output_text.h', ],