mirror of https://github.com/procxx/kepka.git
Preprocess images before passport upload.
This commit is contained in:
parent
ab5f35e952
commit
ab797b4dff
|
@ -1612,6 +1612,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_passport_stop" = "Stop";
|
"lng_passport_stop" = "Stop";
|
||||||
"lng_passport_restart_sure" = "Unexpected error has occurred. Perhaps some changes were done from a different Telegram application. Would you like to restart this authorization?";
|
"lng_passport_restart_sure" = "Unexpected error has occurred. Perhaps some changes were done from a different Telegram application. Would you like to restart this authorization?";
|
||||||
"lng_passport_restart" = "Restart";
|
"lng_passport_restart" = "Restart";
|
||||||
|
"lng_passport_error_too_large" = "This file is too large.";
|
||||||
|
"lng_passport_error_bad_size" = "This image has bad dimensions.";
|
||||||
|
"lng_passport_error_cant_read" = "Can't read this file. Please choose an image.";
|
||||||
|
|
||||||
// Wnd specific
|
// Wnd specific
|
||||||
|
|
||||||
|
|
|
@ -54,5 +54,9 @@ inline QString PassportCorruptedResetSure() {
|
||||||
return qsl("Are you sure you want to reset your Telegram Passport data?");
|
return qsl("Are you sure you want to reset your Telegram Passport data?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QString UnknownSecureScanError() {
|
||||||
|
return qsl("Unknown scan read error.");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Hard
|
} // namespace Hard
|
||||||
} // namespace Lang
|
} // namespace Lang
|
||||||
|
|
|
@ -843,9 +843,27 @@ void PanelController::editWithUpload(int index, int documentIndex) {
|
||||||
base::take(_scopeDocumentTypeBox);
|
base::take(_scopeDocumentTypeBox);
|
||||||
editScope(index, documentIndex);
|
editScope(index, documentIndex);
|
||||||
uploadScan(std::move(content));
|
uploadScan(std::move(content));
|
||||||
|
}, [=](ReadScanError error) {
|
||||||
|
readScanError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PanelController::readScanError(ReadScanError error) {
|
||||||
|
show(Box<InformBox>([&] {
|
||||||
|
switch (error) {
|
||||||
|
case ReadScanError::FileTooLarge:
|
||||||
|
return lang(lng_passport_error_too_large);
|
||||||
|
case ReadScanError::BadImageSize:
|
||||||
|
return lang(lng_passport_error_bad_size);
|
||||||
|
case ReadScanError::CantReadImage:
|
||||||
|
return lang(lng_passport_error_cant_read);
|
||||||
|
case ReadScanError::Unknown:
|
||||||
|
return Lang::Hard::UnknownSecureScanError();
|
||||||
|
}
|
||||||
|
Unexpected("Error type in PanelController::readScanError.");
|
||||||
|
}()));
|
||||||
|
}
|
||||||
|
|
||||||
void PanelController::editScope(int index, int documentIndex) {
|
void PanelController::editScope(int index, int documentIndex) {
|
||||||
Expects(_panel != nullptr);
|
Expects(_panel != nullptr);
|
||||||
Expects(index >= 0 && index < _scopes.size());
|
Expects(index >= 0 && index < _scopes.size());
|
||||||
|
|
|
@ -18,6 +18,8 @@ class Panel;
|
||||||
struct EditDocumentScheme;
|
struct EditDocumentScheme;
|
||||||
struct EditContactScheme;
|
struct EditContactScheme;
|
||||||
|
|
||||||
|
enum class ReadScanError;
|
||||||
|
|
||||||
EditDocumentScheme GetDocumentScheme(
|
EditDocumentScheme GetDocumentScheme(
|
||||||
Scope::Type type,
|
Scope::Type type,
|
||||||
base::optional<Value::Type> scansType = base::none);
|
base::optional<Value::Type> scansType = base::none);
|
||||||
|
@ -84,6 +86,7 @@ public:
|
||||||
void restoreSelfie();
|
void restoreSelfie();
|
||||||
rpl::producer<ScanInfo> scanUpdated() const;
|
rpl::producer<ScanInfo> scanUpdated() const;
|
||||||
rpl::producer<ScopeError> saveErrors() const;
|
rpl::producer<ScopeError> saveErrors() const;
|
||||||
|
void readScanError(ReadScanError error);
|
||||||
|
|
||||||
base::optional<rpl::producer<QString>> deleteValueLabel() const;
|
base::optional<rpl::producer<QString>> deleteValueLabel() const;
|
||||||
void deleteValue();
|
void deleteValue();
|
||||||
|
|
|
@ -20,9 +20,49 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
|
#include "storage/storage_media_prepare.h"
|
||||||
#include "styles/style_passport.h"
|
#include "styles/style_passport.h"
|
||||||
|
|
||||||
namespace Passport {
|
namespace Passport {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kMaxDimensions = 2048;
|
||||||
|
constexpr auto kMaxSize = 10 * 1024 * 1024;
|
||||||
|
constexpr auto kJpegQuality = 89;
|
||||||
|
|
||||||
|
static_assert(kMaxSize <= UseBigFilesFrom);
|
||||||
|
|
||||||
|
base::variant<ReadScanError, QByteArray> ProcessImage(QByteArray &&bytes) {
|
||||||
|
auto image = App::readImage(base::take(bytes));
|
||||||
|
if (image.isNull()) {
|
||||||
|
return ReadScanError::CantReadImage;
|
||||||
|
} else if (!Storage::ValidateThumbDimensions(image.width(), image.height())) {
|
||||||
|
return ReadScanError::BadImageSize;
|
||||||
|
}
|
||||||
|
if (std::max(image.width(), image.height()) > kMaxDimensions) {
|
||||||
|
image = std::move(image).scaled(
|
||||||
|
kMaxDimensions,
|
||||||
|
kMaxDimensions,
|
||||||
|
Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
|
auto result = QByteArray();
|
||||||
|
{
|
||||||
|
QBuffer buffer(&result);
|
||||||
|
if (!image.save(&buffer, QByteArray("JPG"), kJpegQuality)) {
|
||||||
|
return ReadScanError::Unknown;
|
||||||
|
}
|
||||||
|
base::take(image);
|
||||||
|
}
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return ReadScanError::Unknown;
|
||||||
|
} else if (result.size() > kMaxSize) {
|
||||||
|
return ReadScanError::FileTooLarge;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class ScanButton : public Ui::AbstractButton {
|
class ScanButton : public Ui::AbstractButton {
|
||||||
public:
|
public:
|
||||||
|
@ -496,39 +536,71 @@ void EditScans::chooseScan() {
|
||||||
}
|
}
|
||||||
ChooseScan(this, [=](QByteArray &&content) {
|
ChooseScan(this, [=](QByteArray &&content) {
|
||||||
_controller->uploadScan(std::move(content));
|
_controller->uploadScan(std::move(content));
|
||||||
|
}, [=](ReadScanError error) {
|
||||||
|
_controller->readScanError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditScans::chooseSelfie() {
|
void EditScans::chooseSelfie() {
|
||||||
ChooseScan(this, [=](QByteArray &&content) {
|
ChooseScan(this, [=](QByteArray &&content) {
|
||||||
_controller->uploadSelfie(std::move(content));
|
_controller->uploadSelfie(std::move(content));
|
||||||
|
}, [=](ReadScanError error) {
|
||||||
|
_controller->readScanError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditScans::ChooseScan(
|
void EditScans::ChooseScan(
|
||||||
QPointer<QWidget> parent,
|
QPointer<QWidget> parent,
|
||||||
base::lambda<void(QByteArray&&)> callback) {
|
base::lambda<void(QByteArray&&)> doneCallback,
|
||||||
|
base::lambda<void(ReadScanError)> errorCallback) {
|
||||||
Expects(parent != nullptr);
|
Expects(parent != nullptr);
|
||||||
|
|
||||||
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 = base::lambda_guarded(parent, callback);
|
const auto guardedCallback = base::lambda_guarded(parent, doneCallback);
|
||||||
|
const auto guardedError = base::lambda_guarded(parent, errorCallback);
|
||||||
|
const auto onMainCallback = [=](QByteArray content) {
|
||||||
|
crl::on_main([=, bytes = std::move(content)]() mutable {
|
||||||
|
guardedCallback(std::move(bytes));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const auto onMainError = [=](ReadScanError error) {
|
||||||
|
crl::on_main([=] {
|
||||||
|
guardedError(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const auto processImage = [=](QByteArray &&content) {
|
||||||
|
crl::async([=, bytes = std::move(content)]() 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));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
const auto processFile = [=](FileDialog::OpenResult &&result) {
|
const auto processFile = [=](FileDialog::OpenResult &&result) {
|
||||||
if (result.paths.size() == 1) {
|
if (result.paths.size() == 1) {
|
||||||
auto content = [&] {
|
auto content = [&] {
|
||||||
QFile f(result.paths.front());
|
QFile f(result.paths.front());
|
||||||
if (!f.open(QIODevice::ReadOnly)) {
|
if (f.size() > App::kImageSizeLimit) {
|
||||||
|
guardedError(ReadScanError::FileTooLarge);
|
||||||
|
return QByteArray();
|
||||||
|
} else if (!f.open(QIODevice::ReadOnly)) {
|
||||||
|
guardedError(ReadScanError::CantReadImage);
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
return f.readAll();
|
return f.readAll();
|
||||||
}();
|
}();
|
||||||
if (!content.isEmpty()) {
|
if (!content.isEmpty()) {
|
||||||
guardedCallback(std::move(content));
|
processImage(std::move(content));
|
||||||
}
|
}
|
||||||
} else if (!result.remoteContent.isEmpty()) {
|
} else if (!result.remoteContent.isEmpty()) {
|
||||||
guardedCallback(std::move(result.remoteContent));
|
processImage(std::move(result.remoteContent));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
FileDialog::GetOpenPath(
|
FileDialog::GetOpenPath(
|
||||||
|
|
|
@ -30,6 +30,13 @@ class PanelController;
|
||||||
class ScanButton;
|
class ScanButton;
|
||||||
struct ScanInfo;
|
struct ScanInfo;
|
||||||
|
|
||||||
|
enum class ReadScanError {
|
||||||
|
FileTooLarge,
|
||||||
|
CantReadImage,
|
||||||
|
BadImageSize,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
class EditScans : public Ui::RpWidget {
|
class EditScans : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
EditScans(
|
EditScans(
|
||||||
|
@ -44,7 +51,8 @@ public:
|
||||||
|
|
||||||
static void ChooseScan(
|
static void ChooseScan(
|
||||||
QPointer<QWidget> parent,
|
QPointer<QWidget> parent,
|
||||||
base::lambda<void(QByteArray&&)> callback);
|
base::lambda<void(QByteArray&&)> doneCallback,
|
||||||
|
base::lambda<void(ReadScanError)> errorCallback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupContent(const QString &header);
|
void setupContent(const QString &header);
|
||||||
|
|
Loading…
Reference in New Issue