mirror of https://github.com/procxx/kepka.git
Add export statistics for the final screen.
This commit is contained in:
parent
e8dd277a00
commit
e11c27048b
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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',
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue