Fix a memory leak using a recursive lambda.
This commit is contained in:
parent
900f7e1304
commit
52e780b065
|
@ -129,8 +129,7 @@ void SendExistingMedia(
|
|||
caption,
|
||||
MTPReplyMarkup());
|
||||
|
||||
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
|
||||
auto performRequest = [=] {
|
||||
auto performRequest = [=](const auto &repeatRequest) -> void {
|
||||
auto &histories = history->owner().histories();
|
||||
const auto requestType = Data::Histories::RequestType::Send;
|
||||
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||
|
@ -149,28 +148,25 @@ void SendExistingMedia(
|
|||
api->applyUpdates(result, randomId);
|
||||
finish();
|
||||
}).fail([=](const RPCError &error) {
|
||||
(*failHandler)(error, usedFileReference);
|
||||
if (error.code() == 400
|
||||
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
|
||||
api->refreshFileReference(origin, [=](const auto &result) {
|
||||
if (media->fileReference() != usedFileReference) {
|
||||
repeatRequest(repeatRequest);
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
finish();
|
||||
}).afterRequest(history->sendRequestId
|
||||
).send();
|
||||
return history->sendRequestId;
|
||||
});
|
||||
};
|
||||
*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
|
||||
if (error.code() == 400
|
||||
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
|
||||
api->refreshFileReference(origin, [=](const auto &result) {
|
||||
if (media->fileReference() != usedFileReference) {
|
||||
performRequest();
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
};
|
||||
performRequest();
|
||||
performRequest(performRequest);
|
||||
|
||||
api->finishForwarding(message.action);
|
||||
}
|
||||
|
|
|
@ -604,7 +604,7 @@ bool CanScheduleUntilOnline(not_null<PeerData*> peer) {
|
|||
void ScheduleBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
SendMenuType type,
|
||||
FnMut<void(Api::SendOptions)> done,
|
||||
Fn<void(Api::SendOptions)> done,
|
||||
TimeId time) {
|
||||
box->setTitle((type == SendMenuType::Reminder)
|
||||
? tr::lng_remind_title()
|
||||
|
@ -697,8 +697,6 @@ void ScheduleBox(
|
|||
}), (*calendar)->lifetime());
|
||||
});
|
||||
|
||||
const auto shared = std::make_shared<FnMut<void(Api::SendOptions)>>(
|
||||
std::move(done));
|
||||
const auto collect = [=] {
|
||||
const auto timeValue = timeInput->valueCurrent().split(':');
|
||||
if (timeValue.size() != 2) {
|
||||
|
@ -731,9 +729,9 @@ void ScheduleBox(
|
|||
return;
|
||||
}
|
||||
|
||||
auto copy = shared;
|
||||
auto copy = done;
|
||||
box->closeBox();
|
||||
(*copy)(result);
|
||||
copy(result);
|
||||
};
|
||||
timeInput->submitRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace HistoryView {
|
|||
void ScheduleBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
SendMenuType type,
|
||||
FnMut<void(Api::SendOptions)> done,
|
||||
Fn<void(Api::SendOptions)> done,
|
||||
TimeId time);
|
||||
|
||||
template <typename Guard, typename Submit>
|
||||
|
|
|
@ -853,56 +853,20 @@ void EditScans::ChooseScan(
|
|||
Fn<void(ReadScanError)> errorCallback) {
|
||||
Expects(parent != nullptr);
|
||||
|
||||
const auto processFiles = std::make_shared<Fn<void(QStringList&&)>>();
|
||||
const auto filter = FileDialog::AllFilesFilter()
|
||||
+ qsl(";;Image files (*")
|
||||
+ cImgExtensions().join(qsl(" *"))
|
||||
+ qsl(")");
|
||||
const auto guardedCallback = crl::guard(parent, doneCallback);
|
||||
const auto guardedError = crl::guard(parent, errorCallback);
|
||||
const auto onMainCallback = [=](
|
||||
QByteArray &&content,
|
||||
QStringList &&remainingFiles) {
|
||||
crl::on_main([
|
||||
=,
|
||||
bytes = std::move(content),
|
||||
remainingFiles = std::move(remainingFiles)
|
||||
]() mutable {
|
||||
guardedCallback(std::move(bytes));
|
||||
(*processFiles)(std::move(remainingFiles));
|
||||
});
|
||||
};
|
||||
const auto onMainError = [=](ReadScanError error) {
|
||||
crl::on_main([=] {
|
||||
guardedError(error);
|
||||
});
|
||||
};
|
||||
const auto processImage = [=](
|
||||
QByteArray &&content,
|
||||
QStringList &&remainingFiles) {
|
||||
crl::async([
|
||||
=,
|
||||
bytes = std::move(content),
|
||||
remainingFiles = std::move(remainingFiles)
|
||||
]() mutable {
|
||||
auto result = ProcessImage(std::move(bytes));
|
||||
if (const auto error = base::get_if<ReadScanError>(&result)) {
|
||||
onMainError(*error);
|
||||
} else {
|
||||
auto content = base::get_if<QByteArray>(&result);
|
||||
Assert(content != nullptr);
|
||||
onMainCallback(std::move(*content), std::move(remainingFiles));
|
||||
}
|
||||
});
|
||||
};
|
||||
const auto processOpened = [=](FileDialog::OpenResult &&result) {
|
||||
if (result.paths.size() > 0) {
|
||||
(*processFiles)(std::move(result.paths));
|
||||
} else if (!result.remoteContent.isEmpty()) {
|
||||
processImage(std::move(result.remoteContent), {});
|
||||
}
|
||||
};
|
||||
*processFiles = [=](QStringList &&files) {
|
||||
const auto processFiles = [=](
|
||||
QStringList &&files,
|
||||
const auto &handleImage) -> void {
|
||||
while (!files.isEmpty()) {
|
||||
auto file = files.front();
|
||||
files.removeAt(0);
|
||||
|
@ -919,11 +883,49 @@ void EditScans::ChooseScan(
|
|||
return f.readAll();
|
||||
}();
|
||||
if (!content.isEmpty()) {
|
||||
processImage(std::move(content), std::move(files));
|
||||
handleImage(
|
||||
std::move(content),
|
||||
std::move(files),
|
||||
handleImage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
const auto processImage = [=](
|
||||
QByteArray &&content,
|
||||
QStringList &&remainingFiles,
|
||||
const auto &repeatProcessImage) -> void {
|
||||
crl::async([
|
||||
=,
|
||||
bytes = std::move(content),
|
||||
remainingFiles = std::move(remainingFiles)
|
||||
]() mutable {
|
||||
auto result = ProcessImage(std::move(bytes));
|
||||
if (const auto error = base::get_if<ReadScanError>(&result)) {
|
||||
onMainError(*error);
|
||||
} else {
|
||||
auto content = base::get_if<QByteArray>(&result);
|
||||
Assert(content != nullptr);
|
||||
crl::on_main([
|
||||
=,
|
||||
bytes = std::move(*content),
|
||||
remainingFiles = std::move(remainingFiles)
|
||||
]() mutable {
|
||||
guardedCallback(std::move(bytes));
|
||||
processFiles(
|
||||
std::move(remainingFiles),
|
||||
repeatProcessImage);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
const auto processOpened = [=](FileDialog::OpenResult &&result) {
|
||||
if (result.paths.size() > 0) {
|
||||
processFiles(std::move(result.paths), processImage);
|
||||
} else if (!result.remoteContent.isEmpty()) {
|
||||
processImage(std::move(result.remoteContent), {}, processImage);
|
||||
}
|
||||
};
|
||||
const auto allowMany = (type == FileType::Scan)
|
||||
|| (type == FileType::Translation);
|
||||
(allowMany ? FileDialog::GetOpenPaths : FileDialog::GetOpenPath)(
|
||||
|
|
|
@ -209,10 +209,11 @@ void SetupInterfaceScale(
|
|||
}
|
||||
return (result == ScaleValues.size()) ? (result - 1) : result;
|
||||
};
|
||||
const auto inSetScale = Ui::CreateChild<bool>(container.get());
|
||||
const auto setScale = std::make_shared<Fn<void(int)>>();
|
||||
*setScale = [=](int scale) {
|
||||
if (*inSetScale) return;
|
||||
const auto inSetScale = container->lifetime().make_state<bool>();
|
||||
const auto setScale = [=](int scale, const auto &repeatSetScale) -> void {
|
||||
if (*inSetScale) {
|
||||
return;
|
||||
}
|
||||
*inSetScale = true;
|
||||
const auto guard = gsl::finally([=] { *inSetScale = false; });
|
||||
|
||||
|
@ -228,7 +229,7 @@ void SetupInterfaceScale(
|
|||
base::call_delayed(
|
||||
st::defaultSettingsSlider.duration,
|
||||
button,
|
||||
[=] { (*setScale)(cConfigScale()); });
|
||||
[=] { repeatSetScale(cConfigScale(), repeatSetScale); });
|
||||
});
|
||||
Ui::show(Box<ConfirmBox>(
|
||||
tr::lng_settings_need_restart(tr::now),
|
||||
|
@ -256,16 +257,16 @@ void SetupInterfaceScale(
|
|||
) | rpl::map([=](int section) {
|
||||
return scaleByIndex(section);
|
||||
}) | rpl::start_with_next([=](int scale) {
|
||||
(*setScale)((scale == cScreenScale())
|
||||
? style::kScaleAuto
|
||||
: scale);
|
||||
setScale(
|
||||
(scale == cScreenScale()) ? style::kScaleAuto : scale,
|
||||
setScale);
|
||||
}, slider->lifetime());
|
||||
|
||||
button->toggledValue(
|
||||
) | rpl::map([](bool checked) {
|
||||
return checked ? style::kScaleAuto : cEvalScale(cConfigScale());
|
||||
}) | rpl::start_with_next([=](int scale) {
|
||||
(*setScale)(scale);
|
||||
setScale(scale, setScale);
|
||||
}, button->lifetime());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue