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