Add export statistics for the final screen.

This commit is contained in:
John Preston 2018-06-20 17:10:38 +01:00
parent e8dd277a00
commit e11c27048b
13 changed files with 116 additions and 18 deletions

View File

@ -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_progress" = "Note: Please don't close Telegram while exporting files and personal data.";
"lng_export_stop" = "Stop"; "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_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_done" = "Show my data";
"lng_export_finished" = "Export is finished."; "lng_export_finished" = "Export is finished.";
"lng_export_total_files" = "Total files: {count}"; "lng_export_total_files" = "Total files: {count}.";
"lng_export_total_size" = "Total size: {size}"; "lng_export_total_size" = "Total size: {size}.";
// Wnd specific // Wnd specific

View File

@ -135,7 +135,7 @@ struct ApiWrap::UserpicsProcess {
}; };
struct ApiWrap::FileProcess { struct ApiWrap::FileProcess {
FileProcess(const QString &path); FileProcess(const QString &path, Output::Stats *stats);
Output::File file; Output::File file;
QString relativePath; QString relativePath;
@ -222,7 +222,8 @@ base::optional<QString> ApiWrap::LoadedFileCache::find(
return base::none; return base::none;
} }
ApiWrap::FileProcess::FileProcess(const QString &path) : file(path) { ApiWrap::FileProcess::FileProcess(const QString &path, Output::Stats *stats)
: file(path, stats) {
} }
template <typename Request> template <typename Request>
@ -267,11 +268,13 @@ rpl::producer<Output::Result> ApiWrap::ioErrors() const {
void ApiWrap::startExport( void ApiWrap::startExport(
const Settings &settings, const Settings &settings,
Output::Stats *stats,
FnMut<void(StartInfo)> done) { FnMut<void(StartInfo)> done) {
Expects(_settings == nullptr); Expects(_settings == nullptr);
Expects(_startProcess == nullptr); Expects(_startProcess == nullptr);
_settings = std::make_unique<Settings>(settings); _settings = std::make_unique<Settings>(settings);
_stats = stats;
_startProcess = std::make_unique<StartProcess>(); _startProcess = std::make_unique<StartProcess>();
_startProcess->done = std::move(done); _startProcess->done = std::move(done);
@ -1079,7 +1082,8 @@ auto ApiWrap::prepareFileProcess(const Data::File &file) const
_settings->path, _settings->path,
file.suggestedPath); file.suggestedPath);
auto result = std::make_unique<FileProcess>( auto result = std::make_unique<FileProcess>(
_settings->path + relativePath); _settings->path + relativePath,
_stats);
result->relativePath = relativePath; result->relativePath = relativePath;
result->location = file.location; result->location = file.location;
result->size = file.size; result->size = file.size;

View File

@ -27,13 +27,14 @@ struct Message;
namespace Output { namespace Output {
struct Result; struct Result;
class Stats;
} // namespace Output } // namespace Output
struct Settings; struct Settings;
class ApiWrap { class ApiWrap {
public: public:
ApiWrap(Fn<void(FnMut<void()>)> runner); explicit ApiWrap(Fn<void(FnMut<void()>)> runner);
rpl::producer<RPCError> errors() const; rpl::producer<RPCError> errors() const;
rpl::producer<Output::Result> ioErrors() const; rpl::producer<Output::Result> ioErrors() const;
@ -45,6 +46,7 @@ public:
}; };
void startExport( void startExport(
const Settings &settings, const Settings &settings,
Output::Stats *stats,
FnMut<void(StartInfo)> done); FnMut<void(StartInfo)> done);
void requestLeftChannelsList( void requestLeftChannelsList(
@ -155,6 +157,7 @@ private:
MTP::ConcurrentSender _mtp; MTP::ConcurrentSender _mtp;
base::optional<uint64> _takeoutId; base::optional<uint64> _takeoutId;
Output::Stats *_stats = nullptr;
std::unique_ptr<Settings> _settings; std::unique_ptr<Settings> _settings;
MTPInputUser _user = MTP_inputUserSelf(); MTPInputUser _user = MTP_inputUserSelf();

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "export/data/export_data_types.h" #include "export/data/export_data_types.h"
#include "export/output/export_output_abstract.h" #include "export/output/export_output_abstract.h"
#include "export/output/export_output_result.h" #include "export/output/export_output_result.h"
#include "export/output/export_output_stats.h"
namespace Export { namespace Export {
@ -102,6 +103,9 @@ private:
// rpl::variable<State> fails to compile in MSVC :( // rpl::variable<State> fails to compile in MSVC :(
State _state; State _state;
rpl::event_stream<State> _stateChanges; rpl::event_stream<State> _stateChanges;
Output::Stats _stats;
std::vector<int> _substepsInStep; std::vector<int> _substepsInStep;
int _substepsTotal = 0; int _substepsTotal = 0;
mutable int _substepsPassed = 0; mutable int _substepsPassed = 0;
@ -321,7 +325,7 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
void Controller::exportNext() { void Controller::exportNext() {
if (!++_stepIndex) { if (!++_stepIndex) {
if (ioCatchError(_writer->start(_settings))) { if (ioCatchError(_writer->start(_settings, &_stats))) {
return; return;
} }
} }
@ -350,7 +354,7 @@ void Controller::exportNext() {
void Controller::initialize() { void Controller::initialize() {
setState(stateInitializing()); setState(stateInitializing());
_api.startExport(_settings, [=](ApiWrap::StartInfo info) { _api.startExport(_settings, &_stats, [=](ApiWrap::StartInfo info) {
fillSubstepsInSteps(info); fillSubstepsInSteps(info);
exportNext(); exportNext();
}); });
@ -642,7 +646,10 @@ int Controller::substepsInStep(Step step) const {
} }
void Controller::setFinishedState() { void Controller::setFinishedState() {
setState(FinishedState{ _writer->mainFilePath() }); setState(FinishedState{
_writer->mainFilePath(),
_stats.filesCount(),
_stats.bytesCount() });
} }
ControllerWrap::ControllerWrap() { ControllerWrap::ControllerWrap() {

View File

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <vector> #include <vector>
#include <map> #include <map>
#include <deque> #include <deque>
#include <atomic>
#include <range/v3/all.hpp> #include <range/v3/all.hpp>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@ -26,6 +26,7 @@ struct Settings;
namespace Output { namespace Output {
struct Result; struct Result;
class Stats;
enum class Format { enum class Format {
Text, Text,
@ -36,7 +37,9 @@ enum class Format {
class AbstractWriter { class AbstractWriter {
public: public:
[[nodiscard]] virtual Result start(const Settings &settings) = 0; [[nodiscard]] virtual Result start(
const Settings &settings,
Stats *stats) = 0;
[[nodiscard]] virtual Result writePersonal( [[nodiscard]] virtual Result writePersonal(
const Data::PersonalInfo &data) = 0; const Data::PersonalInfo &data) = 0;

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "export/output/export_output_file.h" #include "export/output/export_output_file.h"
#include "export/output/export_output_result.h" #include "export/output/export_output_result.h"
#include "export/output/export_output_stats.h"
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QDir> #include <QtCore/QDir>
@ -17,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Export { namespace Export {
namespace Output { namespace Output {
File::File(const QString &path) : _path(path) { File::File(const QString &path, Stats *stats) : _path(path), _stats(stats) {
} }
int File::size() const { int File::size() const {
@ -37,11 +38,22 @@ Result File::writeBlock(const QByteArray &block) {
} }
Result File::writeBlockAttempt(const QByteArray &block) { Result File::writeBlockAttempt(const QByteArray &block) {
if (_stats && !_inStats) {
_inStats = true;
_stats->incrementFiles();
}
if (const auto result = reopen(); !result) { if (const auto result = reopen(); !result) {
return result; return result;
} }
if (_file->write(block) == block.size() && _file->flush()) { const auto size = block.size();
_offset += 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 Result::Success();
} }
return error(); return error();

View File

@ -17,10 +17,11 @@ namespace Export {
namespace Output { namespace Output {
struct Result; struct Result;
class Stats;
class File { class File {
public: public:
File(const QString &path); File(const QString &path, Stats *stats);
[[nodiscard]] int size() const; [[nodiscard]] int size() const;
[[nodiscard]] bool empty() const; [[nodiscard]] bool empty() const;
@ -42,6 +43,9 @@ private:
int _offset = 0; int _offset = 0;
base::optional<QFile> _file; base::optional<QFile> _file;
Stats *_stats = nullptr;
bool _inStats = false;
}; };
} // namespace Output } // namespace Output

View File

@ -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

View File

@ -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 <atomic>
namespace Export {
namespace Output {
class Stats {
public:
void incrementFiles();
void incrementBytes(int count);
int filesCount() const;
int64 bytesCount() const;
private:
std::atomic<int> _files;
std::atomic<int64> _bytes;
};
} // namespace Output
} // namespace Export

View File

@ -432,10 +432,11 @@ QByteArray SerializeMessage(
} // namespace } // namespace
Result TextWriter::start(const Settings &settings) { Result TextWriter::start(const Settings &settings, Stats *stats) {
Expects(settings.path.endsWith('/')); Expects(settings.path.endsWith('/'));
_settings = base::duplicate(settings); _settings = base::duplicate(settings);
_stats = stats;
_summary = fileWithRelativePath(mainFileRelativePath()); _summary = fileWithRelativePath(mainFileRelativePath());
return Result::Success(); return Result::Success();
} }
@ -827,7 +828,7 @@ QString TextWriter::pathWithRelativePath(const QString &path) const {
std::unique_ptr<File> TextWriter::fileWithRelativePath( std::unique_ptr<File> TextWriter::fileWithRelativePath(
const QString &path) const { const QString &path) const {
return std::make_unique<File>(pathWithRelativePath(path)); return std::make_unique<File>(pathWithRelativePath(path), _stats);
} }
} // namespace Output } // namespace Output

View File

@ -16,7 +16,7 @@ namespace Output {
class TextWriter : public AbstractWriter { class TextWriter : public AbstractWriter {
public: public:
Result start(const Settings &settings) override; Result start(const Settings &settings, Stats *stats) override;
Result writePersonal(const Data::PersonalInfo &data) override; Result writePersonal(const Data::PersonalInfo &data) override;
@ -61,6 +61,7 @@ private:
Result writeChatEnd(); Result writeChatEnd();
Settings _settings; Settings _settings;
Stats *_stats = nullptr;
std::unique_ptr<File> _summary; std::unique_ptr<File> _summary;
int _userpicsCount = 0; int _userpicsCount = 0;

View File

@ -61,6 +61,8 @@
'<(src_loc)/export/output/export_output_abstract.h', '<(src_loc)/export/output/export_output_abstract.h',
'<(src_loc)/export/output/export_output_file.cpp', '<(src_loc)/export/output/export_output_file.cpp',
'<(src_loc)/export/output/export_output_file.h', '<(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.cpp',
'<(src_loc)/export/output/export_output_text.h', '<(src_loc)/export/output/export_output_text.h',
], ],