Call finish takeout. Handle errors.

This commit is contained in:
John Preston 2018-06-21 01:54:59 +01:00
parent fcda883878
commit 36fb6dac89
11 changed files with 113 additions and 14 deletions

View File

@ -1697,6 +1697,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_export_total_files" = "Total files: {count}.";
"lng_export_total_size" = "Total size: {size}.";
"lng_export_folder" = "Choose export folder";
"lng_export_invalid" = "Sorry, you have started a new data export, so this data export is now cancelled.";
"lng_export_delay" = "Sorry, for security reasons this data export will be available for you:\n\n{date}\n\nAt this time please try again.";
// Wnd specific

View File

@ -1023,6 +1023,7 @@ invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
initConnection#785188b8 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X;
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange query:!X = X;
invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;
auth.sendCode#86aef0ec flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool api_id:int api_hash:string = auth.SentCode;
@ -1082,6 +1083,7 @@ account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_co
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
account.verifyEmail#ecba39db email:string code:string = Bool;
account.initTakeoutSession#f05b4804 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?int = account.Takeout;
account.finishTakeoutSession#1d2652ee flags:# success:flags.0?true = Bool;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
@ -1200,6 +1202,7 @@ messages.getRecentLocations#bbc45b09 peer:InputPeer limit:int hash:int = message
messages.sendMultiMedia#2095512f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> = Updates;
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
messages.searchStickerSets#c2b7d08b flags:# exclude_featured:flags.0?true q:string hash:int = messages.FoundStickerSets;
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;

View File

@ -77,7 +77,7 @@ void Session::startExport() {
_exportViewChanges.fire(_exportPanel.get());
_exportPanel->closed(
_exportPanel->stopRequests(
) | rpl::start_with_next([=] {
stopExport();
}, _export->lifetime());

View File

@ -707,6 +707,23 @@ void ApiWrap::requestMessages(
});
}
void ApiWrap::finishExport(FnMut<void()> done) {
const auto guard = gsl::finally([&] { _takeoutId = base::none; });
mainRequest(MTPaccount_FinishTakeoutSession(
MTP_flags(MTPaccount_FinishTakeoutSession::Flag::f_success)
)).done(std::move(done)).send();
}
void ApiWrap::cancelExportFast() {
if (_takeoutId.has_value()) {
const auto requestId = mainRequest(MTPaccount_FinishTakeoutSession(
MTP_flags(0)
)).send();
_mtp.request(requestId).detach();
}
}
void ApiWrap::requestDialogsSlice() {
Expects(_dialogsProcess != nullptr);

View File

@ -81,6 +81,9 @@ public:
Fn<bool(Data::MessagesSlice&&)> slice,
FnMut<void()> done);
void finishExport(FnMut<void()> done);
void cancelExportFast();
~ApiWrap();
private:

View File

@ -33,6 +33,7 @@ public:
// Processing step.
void startExport(const Settings &settings);
void cancelExportFast();
private:
using Step = ProcessingState::Step;
@ -153,6 +154,9 @@ rpl::producer<State> Controller::state() const {
}
void Controller::setState(State &&state) {
if (_state.is<CancelledState>()) {
return;
}
_state = std::move(state);
_stateChanges.fire_copy(_state);
}
@ -326,6 +330,11 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
_substepsTotal = ranges::accumulate(_substepsInStep, 0);
}
void Controller::cancelExportFast() {
_api.cancelExportFast();
setState(CancelledState());
}
void Controller::exportNext() {
if (!++_stepIndex) {
if (ioCatchError(_writer->start(_settings, &_stats))) {
@ -336,9 +345,12 @@ void Controller::exportNext() {
if (ioCatchError(_writer->finish())) {
return;
}
setFinishedState();
_api.finishExport([=] {
setFinishedState();
});
return;
}
const auto step = _steps[_stepIndex];
switch (step) {
case Step::Initializing: return initialize();
@ -713,6 +725,14 @@ void ControllerWrap::startExport(const Settings &settings) {
});
}
void ControllerWrap::cancelExportFast() {
LOG(("Export Info: Cancelled export."));
_wrapped.with([=](Controller &controller) {
controller.cancelExportFast();
});
}
rpl::lifetime &ControllerWrap::lifetime() {
return _lifetime;
}

View File

@ -74,6 +74,9 @@ struct OutputErrorState {
QString path;
};
struct CancelledState {
};
struct FinishedState {
QString path;
int filesCount = 0;
@ -85,6 +88,7 @@ using State = base::optional_variant<
ProcessingState,
ApiErrorState,
OutputErrorState,
CancelledState,
FinishedState>;
//struct PasswordUpdate {
@ -113,6 +117,7 @@ public:
// Processing step.
void startExport(const Settings &settings);
void cancelExportFast();
rpl::lifetime &lifetime();

View File

@ -20,6 +20,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Export {
namespace View {
namespace {
constexpr auto kAddDelay = TimeId(60);
} // namespace
PanelController::PanelController(not_null<ControllerWrap*> process)
: _process(process) {
@ -64,17 +69,27 @@ void PanelController::showSettings() {
}
void PanelController::showError(const ApiErrorState &error) {
showError("API Error happened :(\n"
+ QString::number(error.data.code()) + ": " + error.data.type()
+ "\n" + error.data.description());
if (error.data.type() == qstr("TAKEOUT_INVALID")) {
showError(lang(lng_export_invalid));
} else if (error.data.type().startsWith(qstr("TAKEOUT_INIT_DELAY_"))) {
const auto seconds = std::max(error.data.type().mid(
qstr("TAKEOUT_INIT_DELAY_").size()).toInt(), 0) + kAddDelay;
const auto now = QDateTime::currentDateTime();
const auto when = now.addSecs(seconds);
showError(lng_export_delay(lt_date, langDateTimeFull(when)));
} else {
showCriticalError("API Error happened :(\n"
+ QString::number(error.data.code()) + ": " + error.data.type()
+ "\n" + error.data.description());
}
}
void PanelController::showError(const OutputErrorState &error) {
showError("Disk Error happened :(\n"
showCriticalError("Disk Error happened :(\n"
"Could not write path:\n" + error.path);
}
void PanelController::showError(const QString &text) {
void PanelController::showCriticalError(const QString &text) {
auto container = base::make_unique_q<Ui::PaddingWrap<Ui::FlatLabel>>(
_panel.get(),
object_ptr<Ui::FlatLabel>(
@ -92,6 +107,26 @@ void PanelController::showError(const QString &text) {
_panel->setHideOnDeactivate(false);
}
void PanelController::showError(const QString &text) {
auto box = Box<InformBox>(text);
const auto weak = make_weak(box.data());
const auto hidden = _panel->isHidden();
_panel->showBox(
std::move(box),
LayerOption::CloseOther,
hidden ? anim::type::instant : anim::type::normal);
weak->setCloseByEscape(false);
weak->setCloseByOutsideClick(false);
weak->boxClosing(
) | rpl::start_with_next([=] {
_panel->hideGetDuration();
}, weak->lifetime());
if (hidden) {
_panel->showAndActivate();
}
_panel->setHideOnDeactivate(false);
}
void PanelController::showProgress() {
_panel->setTitle(Lang::Viewer(lng_export_progress_title));
@ -125,10 +160,11 @@ void PanelController::stopWithConfirmation(FnMut<void()> callback) {
return;
}
auto stop = [=, callback = std::move(callback)]() mutable {
auto saved = std::move(callback);
stopExport();
if (saved) {
if (auto saved = std::move(callback)) {
stopExport();
saved();
} else {
_process->cancelExportFast();
}
};
const auto hidden = _panel->isHidden();
@ -157,7 +193,7 @@ void PanelController::stopExport() {
_panel->hideGetDuration();
}
rpl::producer<> PanelController::closed() const {
rpl::producer<> PanelController::stopRequests() const {
return _panelCloseEvents.events(
) | rpl::flatten_latest(
) | rpl::filter([=] {
@ -174,9 +210,11 @@ void PanelController::updateState(State &&state) {
showError(*apiError);
} else if (const auto error = base::get_if<OutputErrorState>(&_state)) {
showError(*error);
} else if (const auto finished = base::get_if<FinishedState>(&_state)) {
} else if (_state.is<FinishedState>()) {
_panel->setTitle(Lang::Viewer(lng_export_title));
_panel->setHideOnDeactivate(false);
} else if (_state.is<CancelledState>()) {
stopExport();
}
}

View File

@ -29,7 +29,7 @@ public:
void activatePanel();
void stopWithConfirmation(FnMut<void()> callback = nullptr);
rpl::producer<> closed() const;
rpl::producer<> stopRequests() const;
rpl::lifetime &lifetime() {
return _lifetime;
@ -50,6 +50,7 @@ private:
void showError(const ApiErrorState &error);
void showError(const OutputErrorState &error);
void showError(const QString &text);
void showCriticalError(const QString &text);
not_null<ControllerWrap*> _process;

View File

@ -198,7 +198,7 @@ void ConcurrentSender::senderRequestFail(
}
void ConcurrentSender::senderRequestCancel(mtpRequestId requestId) {
_requests.erase(requestId);
senderRequestDetach(requestId);
with_instance([=](not_null<Instance*> instance) {
instance->cancel(requestId);
});
@ -216,4 +216,8 @@ void ConcurrentSender::senderRequestCancelAll() {
});
}
void ConcurrentSender::senderRequestDetach(mtpRequestId requestId) {
_requests.erase(requestId);
}
} // namespace MTP

View File

@ -148,6 +148,7 @@ public:
class SentRequestWrap {
public:
void cancel();
void detach();
private:
friend class ConcurrentSender;
@ -190,6 +191,7 @@ private:
RPCError &&error);
void senderRequestCancel(mtpRequestId requestId);
void senderRequestCancelAll();
void senderRequestDetach(mtpRequestId requestId);
const Fn<void(FnMut<void()>)> _runner;
base::flat_map<mtpRequestId, Handlers> _requests;
@ -446,6 +448,10 @@ inline void ConcurrentSender::SentRequestWrap::cancel() {
_sender->senderRequestCancel(_requestId);
}
inline void ConcurrentSender::SentRequestWrap::detach() {
_sender->senderRequestDetach(_requestId);
}
inline ConcurrentSender::SentRequestWrap::SentRequestWrap(
not_null<ConcurrentSender*> sender,
mtpRequestId requestId