mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-10-15 14:26:04 +00:00
Better steps division in export.
This commit is contained in:
@@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
namespace Export {
|
||||
|
||||
auto kNullStateCallback = [](ProcessingState&) {};
|
||||
|
||||
class Controller {
|
||||
public:
|
||||
Controller(crl::weak_on_queue<Controller> weak);
|
||||
@@ -21,11 +23,11 @@ public:
|
||||
rpl::producer<State> state() const;
|
||||
|
||||
// Password step.
|
||||
void submitPassword(const QString &password);
|
||||
void requestPasswordRecover();
|
||||
rpl::producer<PasswordUpdate> passwordUpdate() const;
|
||||
void reloadPasswordState();
|
||||
void cancelUnconfirmedPassword();
|
||||
//void submitPassword(const QString &password);
|
||||
//void requestPasswordRecover();
|
||||
//rpl::producer<PasswordUpdate> passwordUpdate() const;
|
||||
//void reloadPasswordState();
|
||||
//void cancelUnconfirmedPassword();
|
||||
|
||||
// Processing step.
|
||||
void startExport(const Settings &settings);
|
||||
@@ -37,30 +39,56 @@ private:
|
||||
void ioError(const QString &path);
|
||||
void setFinishedState();
|
||||
|
||||
void requestPasswordState();
|
||||
void passwordStateDone(const MTPaccount_Password &password);
|
||||
//void requestPasswordState();
|
||||
//void passwordStateDone(const MTPaccount_Password &password);
|
||||
|
||||
void fillExportSteps();
|
||||
void fillSubstepsInSteps(const ApiWrap::StartInfo &info);
|
||||
void exportNext();
|
||||
void initialize();
|
||||
void collectLeftChannels();
|
||||
void collectDialogsList();
|
||||
void exportPersonalInfo();
|
||||
void exportUserpics();
|
||||
void exportContacts();
|
||||
void exportSessions();
|
||||
void exportDialogs();
|
||||
void exportNextDialog();
|
||||
void exportLeftChannels();
|
||||
void exportNextLeftChannel();
|
||||
|
||||
template <typename Callback = const decltype(kNullStateCallback) &>
|
||||
ProcessingState prepareState(
|
||||
Step step,
|
||||
Callback &&callback = kNullStateCallback) const;
|
||||
ProcessingState stateInitializing() const;
|
||||
ProcessingState stateLeftChannelsList(int processed) const;
|
||||
ProcessingState stateDialogsList(int processed) const;
|
||||
ProcessingState statePersonalInfo() const;
|
||||
ProcessingState stateUserpics() const;
|
||||
ProcessingState stateContacts() const;
|
||||
ProcessingState stateSessions() const;
|
||||
ProcessingState stateLeftChannels() const;
|
||||
ProcessingState stateDialogs() const;
|
||||
|
||||
int substepsInStep(Step step) const;
|
||||
|
||||
bool normalizePath();
|
||||
|
||||
ApiWrap _api;
|
||||
Settings _settings;
|
||||
Data::DialogsInfo _leftChannelsInfo;
|
||||
Data::DialogsInfo _dialogsInfo;
|
||||
int _leftChannelIndex = -1;
|
||||
int _dialogIndex = -1;
|
||||
|
||||
// rpl::variable<State> fails to compile in MSVC :(
|
||||
State _state;
|
||||
rpl::event_stream<State> _stateChanges;
|
||||
|
||||
mtpRequestId _passwordRequestId = 0;
|
||||
std::vector<int> _substepsInStep;
|
||||
|
||||
std::unique_ptr<Output::AbstractWriter> _writer;
|
||||
std::vector<ProcessingState::Step> _steps;
|
||||
std::vector<Step> _steps;
|
||||
int _stepIndex = -1;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
@@ -102,49 +130,49 @@ void Controller::ioError(const QString &path) {
|
||||
setState(ErrorState{ ErrorState::Type::IO, base::none, path });
|
||||
}
|
||||
|
||||
void Controller::submitPassword(const QString &password) {
|
||||
|
||||
}
|
||||
|
||||
void Controller::requestPasswordRecover() {
|
||||
|
||||
}
|
||||
|
||||
rpl::producer<PasswordUpdate> Controller::passwordUpdate() const {
|
||||
return rpl::never<PasswordUpdate>();
|
||||
}
|
||||
|
||||
void Controller::reloadPasswordState() {
|
||||
//_mtp.request(base::take(_passwordRequestId)).cancel();
|
||||
requestPasswordState();
|
||||
}
|
||||
|
||||
void Controller::requestPasswordState() {
|
||||
if (_passwordRequestId) {
|
||||
return;
|
||||
}
|
||||
//_passwordRequestId = _mtp.request(MTPaccount_GetPassword(
|
||||
//)).done([=](const MTPaccount_Password &result) {
|
||||
// _passwordRequestId = 0;
|
||||
// passwordStateDone(result);
|
||||
//}).fail([=](const RPCError &error) {
|
||||
// apiError(error);
|
||||
//}).send();
|
||||
}
|
||||
|
||||
void Controller::passwordStateDone(const MTPaccount_Password &result) {
|
||||
auto state = PasswordCheckState();
|
||||
state.checked = false;
|
||||
state.requesting = false;
|
||||
state.hasPassword;
|
||||
state.hint;
|
||||
state.unconfirmedPattern;
|
||||
setState(std::move(state));
|
||||
}
|
||||
|
||||
void Controller::cancelUnconfirmedPassword() {
|
||||
|
||||
}
|
||||
//void Controller::submitPassword(const QString &password) {
|
||||
//
|
||||
//}
|
||||
//
|
||||
//void Controller::requestPasswordRecover() {
|
||||
//
|
||||
//}
|
||||
//
|
||||
//rpl::producer<PasswordUpdate> Controller::passwordUpdate() const {
|
||||
// return rpl::never<PasswordUpdate>();
|
||||
//}
|
||||
//
|
||||
//void Controller::reloadPasswordState() {
|
||||
// //_mtp.request(base::take(_passwordRequestId)).cancel();
|
||||
// requestPasswordState();
|
||||
//}
|
||||
//
|
||||
//void Controller::requestPasswordState() {
|
||||
// if (_passwordRequestId) {
|
||||
// return;
|
||||
// }
|
||||
// //_passwordRequestId = _mtp.request(MTPaccount_GetPassword(
|
||||
// //)).done([=](const MTPaccount_Password &result) {
|
||||
// // _passwordRequestId = 0;
|
||||
// // passwordStateDone(result);
|
||||
// //}).fail([=](const RPCError &error) {
|
||||
// // apiError(error);
|
||||
// //}).send();
|
||||
//}
|
||||
//
|
||||
//void Controller::passwordStateDone(const MTPaccount_Password &result) {
|
||||
// auto state = PasswordCheckState();
|
||||
// state.checked = false;
|
||||
// state.requesting = false;
|
||||
// state.hasPassword;
|
||||
// state.hint;
|
||||
// state.unconfirmedPattern;
|
||||
// setState(std::move(state));
|
||||
//}
|
||||
//
|
||||
//void Controller::cancelUnconfirmedPassword() {
|
||||
//
|
||||
//}
|
||||
|
||||
void Controller::startExport(const Settings &settings) {
|
||||
if (!_settings.path.isEmpty()) {
|
||||
@@ -158,9 +186,7 @@ void Controller::startExport(const Settings &settings) {
|
||||
}
|
||||
_writer = Output::CreateWriter(_settings.format);
|
||||
fillExportSteps();
|
||||
_api.startExport(_settings, [=] {
|
||||
exportNext();
|
||||
});
|
||||
exportNext();
|
||||
}
|
||||
|
||||
bool Controller::normalizePath() {
|
||||
@@ -195,6 +221,13 @@ bool Controller::normalizePath() {
|
||||
|
||||
void Controller::fillExportSteps() {
|
||||
using Type = Settings::Type;
|
||||
_steps.push_back(Step::Initializing);
|
||||
if (_settings.types & Type::GroupsChannelsMask) {
|
||||
_steps.push_back(Step::LeftChannels);
|
||||
}
|
||||
if (_settings.types & Type::AnyChatsMask) {
|
||||
_steps.push_back(Step::DialogsList);
|
||||
}
|
||||
if (_settings.types & Type::PersonalInfo) {
|
||||
_steps.push_back(Step::PersonalInfo);
|
||||
}
|
||||
@@ -207,17 +240,46 @@ void Controller::fillExportSteps() {
|
||||
if (_settings.types & Type::Sessions) {
|
||||
_steps.push_back(Step::Sessions);
|
||||
}
|
||||
const auto dialogTypes = Type::PersonalChats
|
||||
| Type::BotChats
|
||||
| Type::PrivateGroups
|
||||
| Type::PublicGroups
|
||||
| Type::PrivateChannels
|
||||
| Type::PublicChannels;
|
||||
if (_settings.types & dialogTypes) {
|
||||
if (_settings.types & Type::AnyChatsMask) {
|
||||
_steps.push_back(Step::Dialogs);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
|
||||
const auto push = [&](Step step, int count) {
|
||||
const auto index = static_cast<int>(step);
|
||||
if (index >= _substepsInStep.size()) {
|
||||
_substepsInStep.resize(index + 1, 0);
|
||||
}
|
||||
_substepsInStep[index] = count;
|
||||
};
|
||||
push(Step::Initializing, 1);
|
||||
if (_settings.types & Settings::Type::GroupsChannelsMask) {
|
||||
push(Step::LeftChannelsList, 1);
|
||||
}
|
||||
if (_settings.types & Settings::Type::AnyChatsMask) {
|
||||
push(Step::DialogsList, 1);
|
||||
}
|
||||
if (_settings.types & Settings::Type::PersonalInfo) {
|
||||
push(Step::PersonalInfo, 1);
|
||||
}
|
||||
if (_settings.types & Settings::Type::Userpics) {
|
||||
push(Step::Userpics, info.userpicsCount);
|
||||
}
|
||||
if (_settings.types & Settings::Type::Contacts) {
|
||||
push(Step::Contacts, 1);
|
||||
}
|
||||
if (_settings.types & Settings::Type::Sessions) {
|
||||
push(Step::Sessions, 1);
|
||||
}
|
||||
if (_settings.types & Settings::Type::GroupsChannelsMask) {
|
||||
push(Step::LeftChannels, info.leftChannelsCount);
|
||||
}
|
||||
if (_settings.types & Settings::Type::AnyChatsMask) {
|
||||
push(Step::Dialogs, info.dialogsCount);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::exportNext() {
|
||||
if (!++_stepIndex) {
|
||||
_writer->start(_settings);
|
||||
@@ -229,15 +291,52 @@ void Controller::exportNext() {
|
||||
}
|
||||
const auto step = _steps[_stepIndex];
|
||||
switch (step) {
|
||||
case Step::Initializing: return initialize();
|
||||
case Step::LeftChannelsList: return collectLeftChannels();
|
||||
case Step::DialogsList: return collectDialogsList();
|
||||
case Step::PersonalInfo: return exportPersonalInfo();
|
||||
case Step::Userpics: return exportUserpics();
|
||||
case Step::Contacts: return exportContacts();
|
||||
case Step::Sessions: return exportSessions();
|
||||
case Step::LeftChannels: return exportLeftChannels();
|
||||
case Step::Dialogs: return exportDialogs();
|
||||
}
|
||||
Unexpected("Step in Controller::exportNext.");
|
||||
}
|
||||
|
||||
void Controller::initialize() {
|
||||
setState(stateInitializing());
|
||||
|
||||
_api.startExport(_settings, [=](ApiWrap::StartInfo info) {
|
||||
fillSubstepsInSteps(info);
|
||||
exportNext();
|
||||
});
|
||||
}
|
||||
|
||||
void Controller::collectLeftChannels() {
|
||||
_api.requestLeftChannelsList([=](Data::DialogsInfo &&result) {
|
||||
_leftChannelsInfo = std::move(result);
|
||||
exportNext();
|
||||
});
|
||||
|
||||
_api.leftChannelsLoadedCount(
|
||||
) | rpl::start_with_next([=](int count) {
|
||||
setState(stateLeftChannelsList(count));
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Controller::collectDialogsList() {
|
||||
_api.requestDialogsList([=](Data::DialogsInfo &&result) {
|
||||
_dialogsInfo = std::move(result);
|
||||
exportNext();
|
||||
});
|
||||
|
||||
_api.dialogsLoadedCount(
|
||||
) | rpl::start_with_next([=](int count) {
|
||||
setState(stateDialogsList(count));
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Controller::exportPersonalInfo() {
|
||||
_api.requestPersonalInfo([=](Data::PersonalInfo &&result) {
|
||||
_writer->writePersonal(result);
|
||||
@@ -271,20 +370,123 @@ void Controller::exportSessions() {
|
||||
}
|
||||
|
||||
void Controller::exportDialogs() {
|
||||
_api.requestDialogs([=](const Data::DialogsInfo &result) {
|
||||
_writer->writeDialogsStart(result);
|
||||
}, [=](const Data::DialogInfo &result) {
|
||||
_writer->writeDialogStart(result);
|
||||
}, [=](Data::MessagesSlice &&result) {
|
||||
_writer->writeMessagesSlice(result);
|
||||
}, [=] {
|
||||
_writer->writeDialogEnd();
|
||||
}, [=] {
|
||||
_writer->writeDialogsEnd();
|
||||
exportNext();
|
||||
_writer->writeDialogsStart(_dialogsInfo);
|
||||
|
||||
exportNextDialog();
|
||||
}
|
||||
|
||||
void Controller::exportNextDialog() {
|
||||
const auto index = ++_dialogIndex;
|
||||
if (index < _dialogsInfo.list.size()) {
|
||||
const auto &info = _dialogsInfo.list[index];
|
||||
_writer->writeDialogStart(info);
|
||||
|
||||
_api.requestMessages(info, [=](Data::MessagesSlice &&result) {
|
||||
_writer->writeDialogSlice(result);
|
||||
}, [=] {
|
||||
_writer->writeDialogEnd();
|
||||
exportNextDialog();
|
||||
});
|
||||
return;
|
||||
}
|
||||
_writer->writeDialogsEnd();
|
||||
exportNext();
|
||||
}
|
||||
|
||||
void Controller::exportLeftChannels() {
|
||||
_writer->writeLeftChannelsStart(_leftChannelsInfo);
|
||||
|
||||
exportNextLeftChannel();
|
||||
}
|
||||
|
||||
void Controller::exportNextLeftChannel() {
|
||||
const auto index = ++_leftChannelIndex;
|
||||
if (index < _leftChannelsInfo.list.size()) {
|
||||
const auto &chat = _leftChannelsInfo.list[index];
|
||||
_writer->writeLeftChannelStart(chat);
|
||||
|
||||
_api.requestMessages(chat, [=](Data::MessagesSlice &&result) {
|
||||
_writer->writeLeftChannelSlice(result);
|
||||
}, [=] {
|
||||
_writer->writeLeftChannelEnd();
|
||||
exportNextLeftChannel();
|
||||
});
|
||||
return;
|
||||
}
|
||||
_writer->writeLeftChannelsEnd();
|
||||
exportNext();
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
ProcessingState Controller::prepareState(
|
||||
Step step,
|
||||
Callback &&callback) const {
|
||||
auto result = ProcessingState();
|
||||
callback(result);
|
||||
result.step = step;
|
||||
result.substepsInStep = _substepsInStep;
|
||||
return result;
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateInitializing() const {
|
||||
return ProcessingState();
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateLeftChannelsList(int processed) const {
|
||||
const auto step = Step::LeftChannelsList;
|
||||
return prepareState(step, [&](ProcessingState &result) {
|
||||
result.entityIndex = processed;
|
||||
result.entityCount = std::max(processed, substepsInStep(step));
|
||||
});
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateDialogsList(int processed) const {
|
||||
const auto step = Step::DialogsList;
|
||||
return prepareState(step, [&](ProcessingState &result) {
|
||||
result.entityIndex = processed;
|
||||
result.entityCount = std::max(processed, substepsInStep(step));
|
||||
});
|
||||
}
|
||||
ProcessingState Controller::statePersonalInfo() const {
|
||||
return prepareState(Step::PersonalInfo);
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateUserpics() const {
|
||||
return prepareState(Step::Userpics, [&](ProcessingState &result) {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateContacts() const {
|
||||
return prepareState(Step::Contacts);
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateSessions() const {
|
||||
return prepareState(Step::Sessions);
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateLeftChannels() const {
|
||||
const auto step = Step::LeftChannels;
|
||||
return prepareState(step, [&](ProcessingState &result) {
|
||||
//result.entityIndex = processed;
|
||||
//result.entityCount = std::max(processed, substepsInStep(step));
|
||||
});
|
||||
}
|
||||
|
||||
ProcessingState Controller::stateDialogs() const {
|
||||
const auto step = Step::Dialogs;
|
||||
return prepareState(step, [&](ProcessingState &result) {
|
||||
//result.entityIndex = processed;
|
||||
//result.entityCount = std::max(processed, substepsInStep(step));
|
||||
});
|
||||
}
|
||||
|
||||
int Controller::substepsInStep(Step step) const {
|
||||
Expects(_substepsInStep.size() > static_cast<int>(step));
|
||||
|
||||
return _substepsInStep[static_cast<int>(step)];
|
||||
}
|
||||
|
||||
void Controller::setFinishedState() {
|
||||
setState(FinishedState{ _writer->mainFilePath() });
|
||||
}
|
||||
@@ -298,35 +500,35 @@ rpl::producer<State> ControllerWrap::state() const {
|
||||
});
|
||||
}
|
||||
|
||||
void ControllerWrap::submitPassword(const QString &password) {
|
||||
_wrapped.with([=](Controller &controller) {
|
||||
controller.submitPassword(password);
|
||||
});
|
||||
}
|
||||
|
||||
void ControllerWrap::requestPasswordRecover() {
|
||||
_wrapped.with([=](Controller &controller) {
|
||||
controller.requestPasswordRecover();
|
||||
});
|
||||
}
|
||||
|
||||
rpl::producer<PasswordUpdate> ControllerWrap::passwordUpdate() const {
|
||||
return _wrapped.producer_on_main([=](const Controller &controller) {
|
||||
return controller.passwordUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
void ControllerWrap::reloadPasswordState() {
|
||||
_wrapped.with([=](Controller &controller) {
|
||||
controller.reloadPasswordState();
|
||||
});
|
||||
}
|
||||
|
||||
void ControllerWrap::cancelUnconfirmedPassword() {
|
||||
_wrapped.with([=](Controller &controller) {
|
||||
controller.cancelUnconfirmedPassword();
|
||||
});
|
||||
}
|
||||
//void ControllerWrap::submitPassword(const QString &password) {
|
||||
// _wrapped.with([=](Controller &controller) {
|
||||
// controller.submitPassword(password);
|
||||
// });
|
||||
//}
|
||||
//
|
||||
//void ControllerWrap::requestPasswordRecover() {
|
||||
// _wrapped.with([=](Controller &controller) {
|
||||
// controller.requestPasswordRecover();
|
||||
// });
|
||||
//}
|
||||
//
|
||||
//rpl::producer<PasswordUpdate> ControllerWrap::passwordUpdate() const {
|
||||
// return _wrapped.producer_on_main([=](const Controller &controller) {
|
||||
// return controller.passwordUpdate();
|
||||
// });
|
||||
//}
|
||||
//
|
||||
//void ControllerWrap::reloadPasswordState() {
|
||||
// _wrapped.with([=](Controller &controller) {
|
||||
// controller.reloadPasswordState();
|
||||
// });
|
||||
//}
|
||||
//
|
||||
//void ControllerWrap::cancelUnconfirmedPassword() {
|
||||
// _wrapped.with([=](Controller &controller) {
|
||||
// controller.cancelUnconfirmedPassword();
|
||||
// });
|
||||
//}
|
||||
|
||||
void ControllerWrap::startExport(const Settings &settings) {
|
||||
LOG(("Export Info: Started export to '%1'.").arg(settings.path));
|
||||
|
Reference in New Issue
Block a user