Add [first|middle|last]_name_native support.

This commit is contained in:
John Preston 2018-08-14 15:51:12 +03:00
parent b935d54fe7
commit 6558a32794
6 changed files with 111 additions and 73 deletions

View File

@ -151,6 +151,13 @@ void CollectToRequestedRow(
});
}
void ApplyDataChanges(ValueData &data, ValueMap &&changes) {
data.parsedInEdit = data.parsed;
for (auto &[key, value] : changes.fields) {
data.parsedInEdit.fields[key] = std::move(value);
}
}
RequestedRow CollectRequestedRow(const MTPSecureRequiredType &data) {
auto result = RequestedRow();
CollectToRequestedRow(result, data);
@ -220,6 +227,39 @@ QString ValidateUrl(const QString &url) {
} // namespace
bool ValueChanged(not_null<const Value*> value, const ValueMap &data) {
const auto FileChanged = [](const EditFile &file) {
if (file.uploadData) {
return !file.deleted;
}
return file.deleted;
};
auto filesCount = 0;
for (const auto &scan : value->scansInEdit) {
if (FileChanged(scan)) {
return true;
}
}
for (const auto &[type, scan] : value->specialScansInEdit) {
if (FileChanged(scan)) {
return true;
}
}
const auto &existing = value->data.parsed.fields;
for (const auto &[key, value] : data.fields) {
const auto i = existing.find(key);
if (i != existing.end()) {
if (i->second.text != value.text) {
return true;
}
} else if (!value.text.isEmpty()) {
return true;
}
}
return false;
}
FormRequest::FormRequest(
UserId botId,
const QString &scope,
@ -1576,42 +1616,6 @@ bool FormController::isEncryptedValue(Value::Type type) const {
return (type != Value::Type::Phone && type != Value::Type::Email);
}
bool FormController::editFileChanged(const EditFile &file) const {
if (file.uploadData) {
return !file.deleted;
}
return file.deleted;
}
bool FormController::editValueChanged(
not_null<const Value*> value,
const ValueMap &data) const {
auto filesCount = 0;
for (const auto &scan : value->scansInEdit) {
if (editFileChanged(scan)) {
return true;
}
}
for (const auto &[type, scan] : value->specialScansInEdit) {
if (editFileChanged(scan)) {
return true;
}
}
auto existing = value->data.parsed.fields;
for (const auto &[key, value] : data.fields) {
const auto i = existing.find(key);
if (i != existing.end()) {
if (i->second.text != value.text) {
return true;
}
existing.erase(i);
} else if (!value.text.isEmpty()) {
return true;
}
}
return !existing.empty();
}
void FormController::saveValueEdit(
not_null<const Value*> value,
ValueMap &&data) {
@ -1623,7 +1627,7 @@ void FormController::saveValueEdit(
// and we don't reset value->error/[scan|translation]MissingError.
// Otherwise we reset them after save by re-parsing the value.
const auto nonconst = findValue(value);
if (!editValueChanged(nonconst, data)) {
if (!ValueChanged(nonconst, data)) {
nonconst->saveRequestId = -1;
crl::on_main(this, [=] {
base::take(nonconst->scansInEdit);
@ -1636,7 +1640,7 @@ void FormController::saveValueEdit(
});
return;
}
nonconst->data.parsedInEdit = std::move(data);
ApplyDataChanges(nonconst->data, std::move(data));
if (isEncryptedValue(nonconst->type)) {
saveEncryptedValue(nonconst);

View File

@ -201,6 +201,8 @@ private:
};
bool ValueChanged(not_null<const Value*> value, const ValueMap &data);
struct RequestedValue {
explicit RequestedValue(Value::Type type);
@ -327,9 +329,6 @@ public:
void startValueEdit(not_null<const Value*> value);
void cancelValueEdit(not_null<const Value*> value);
void cancelValueVerification(not_null<const Value*> value);
bool editValueChanged(
not_null<const Value*> value,
const ValueMap &data) const;
void saveValueEdit(not_null<const Value*> value, ValueMap &&data);
void deleteValueEdit(not_null<const Value*> value);
bool savingValue(not_null<const Value*> value) const;
@ -454,7 +453,6 @@ private:
void valueEditFailed(not_null<Value*> value);
void clearValueEdit(not_null<Value*> value);
void clearValueVerification(not_null<Value*> value);
bool editFileChanged(const EditFile &file) const;
bool isEncryptedValue(Value::Type type) const;
void saveEncryptedValue(not_null<Value*> value);

View File

@ -278,7 +278,10 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
}
return nullptr;
}();
if (document && scope.documents.size() > 1) {
if ((document && scope.documents.size() > 1)
|| (!scope.details
&& (ScopeTypeForValueType(document->type)
== Scope::Type::Address))) {
pushListValue("_type", [&] {
using Type = Value::Type;
switch (document->type) {
@ -307,7 +310,10 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
if (!scope.documents.empty() && !document) {
return QString();
}
const auto scheme = GetDocumentScheme(scope.type);
const auto scheme = GetDocumentScheme(
scope.type,
document ? base::make_optional(document->type) : base::none,
scope.details ? scope.details->nativeNames : false);
for (const auto &row : scheme.rows) {
const auto format = row.format;
if (row.valueClass == EditDocumentScheme::ValueClass::Fields) {
@ -357,9 +363,10 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
}
ScopeRow ComputeScopeRow(const Scope &scope) {
const auto addReadyError = [&](ScopeRow &&row) {
const auto ready = ComputeScopeRowReadyString(scope);
row.ready = ready;
const auto addReadyError = [&](
ScopeRow &&row,
QString titleFallback = QString()) {
row.ready = ComputeScopeRowReadyString(scope);
auto errors = QStringList();
const auto addValueErrors = [&](not_null<const Value*> value) {
if (!value->error.isEmpty()) {
@ -408,7 +415,10 @@ ScopeRow ComputeScopeRow(const Scope &scope) {
}
if (!errors.isEmpty()) {
row.error = errors[0];// errors.join('\n');
} else if (row.title == row.ready && !titleFallback.isEmpty()) {
row.title = titleFallback;
}
// #TODO passport half-full value
//if (row.error.isEmpty()
// && row.ready.isEmpty()
@ -464,7 +474,7 @@ ScopeRow ComputeScopeRow(const Scope &scope) {
return addReadyError({
lang(lng_passport_address),
lang(lng_passport_address_enter),
});
});
case Scope::Type::Address:
Assert(!scope.documents.empty());
if (scope.documents.size() == 1) {
@ -473,27 +483,27 @@ ScopeRow ComputeScopeRow(const Scope &scope) {
return addReadyError({
lang(lng_passport_address_statement),
lang(lng_passport_address_statement_upload),
});
}, lang(lng_passport_address_title));
case Value::Type::UtilityBill:
return addReadyError({
lang(lng_passport_address_bill),
lang(lng_passport_address_bill_upload),
});
}, lang(lng_passport_address_title));
case Value::Type::RentalAgreement:
return addReadyError({
lang(lng_passport_address_agreement),
lang(lng_passport_address_agreement_upload),
});
}, lang(lng_passport_address_title));
case Value::Type::PassportRegistration:
return addReadyError({
lang(lng_passport_address_registration),
lang(lng_passport_address_registration_upload),
});
}, lang(lng_passport_address_title));
case Value::Type::TemporaryRegistration:
return addReadyError({
lang(lng_passport_address_temporary),
lang(lng_passport_address_temporary_upload),
});
}, lang(lng_passport_address_title));
default: Unexpected("Address type in ComputeScopeRow.");
}
}

View File

@ -34,7 +34,8 @@ constexpr auto kMaxPostcodeSize = 10;
EditDocumentScheme GetDocumentScheme(
Scope::Type type,
base::optional<Value::Type> scansType) {
base::optional<Value::Type> scansType,
bool nativeNames) {
using Scheme = EditDocumentScheme;
using ValueClass = Scheme::ValueClass;
const auto DontFormat = nullptr;
@ -74,7 +75,8 @@ EditDocumentScheme GetDocumentScheme(
}
return base::none;
};
const auto NativeNameValidate = LimitedValidate(kMaxNameSize);
const auto NativeNameOrEmptyValidate = LimitedValidate(kMaxNameSize, 0);
const auto DocumentValidate = LimitedValidate(kMaxDocumentSize);
const auto StreetValidate = LimitedValidate(kMaxStreetSize);
const auto CityValidate = LimitedValidate(kMaxCitySize, kMinCitySize);
@ -129,35 +131,40 @@ EditDocumentScheme GetDocumentScheme(
Unexpected("scansType in GetDocumentScheme:Identity.");
}
}
using Validator = EditDocumentScheme::Row::Validator;
result.rows = {
{
ValueClass::Fields,
PanelDetailsType::Text,
qsl("first_name"),
nativeNames ? qsl("first_name_native") : qsl("first_name"),
lang(lng_passport_first_name),
NameValidate,
nativeNames ? Validator(NativeNameValidate) : NameValidate,
DontFormat,
kMaxNameSize,
},
{
ValueClass::Fields,
PanelDetailsType::Text,
qsl("middle_name"),
(nativeNames
? qsl("middle_name_native")
: qsl("middle_name")),
lang(lng_passport_middle_name),
NameOrEmptyValidate,
(nativeNames
? Validator(NativeNameOrEmptyValidate)
: NameOrEmptyValidate),
DontFormat,
kMaxNameSize,
qsl("first_name")
nativeNames ? qsl("first_name_native") : qsl("first_name"),
},
{
ValueClass::Fields,
PanelDetailsType::Text,
qsl("last_name"),
nativeNames ? qsl("last_name_native") : qsl("last_name"),
lang(lng_passport_last_name),
NameValidate,
nativeNames ? Validator(NativeNameValidate) : NameValidate,
DontFormat,
kMaxNameSize,
qsl("first_name")
nativeNames ? qsl("first_name_native") : qsl("first_name"),
},
{
ValueClass::Fields,
@ -360,6 +367,15 @@ const std::map<QString, QString> &NativeToLatinMap() {
return result;
}
QString AdjustKeyName(not_null<const Value*> value, const QString &key) {
if (!value->nativeNames) {
return key;
}
const auto &map = LatinToNativeMap();
const auto i = map.find(key);
return (i == end(map)) ? key : i->second;
}
bool SkipFieldCheck(not_null<const Value*> value, const QString &key) {
if (value->type != Value::Type::PersonalDetails) {
return false;
@ -1058,7 +1074,8 @@ void PanelController::startScopeEdit(int index, int documentIndex) {
this,
GetDocumentScheme(
_editScope->type,
_editDocument->type),
_editDocument->type,
_editValue->nativeNames),
_editValue->error,
_editValue->data.parsedInEdit,
_editDocument->error,
@ -1071,7 +1088,8 @@ void PanelController::startScopeEdit(int index, int documentIndex) {
this,
GetDocumentScheme(
_editScope->type,
_editDocument->type),
_editDocument->type,
false),
_editDocument->error,
_editDocument->data.parsedInEdit,
_editDocument->scanMissingError,
@ -1089,7 +1107,10 @@ void PanelController::startScopeEdit(int index, int documentIndex) {
auto result = object_ptr<PanelEditDocument>(
_panel->widget(),
this,
GetDocumentScheme(_editScope->type),
GetDocumentScheme(
_editScope->type,
base::none,
_editValue->nativeNames),
_editValue->error,
_editValue->data.parsedInEdit);
const auto weak = make_weak(result.data());
@ -1288,6 +1309,8 @@ void PanelController::saveScope(ValueMap &&data, ValueMap &&filesData) {
if (_editValue) {
_form->saveValueEdit(_editValue, std::move(data));
} else {
Assert(data.fields.empty());
}
if (_editDocument) {
_form->saveValueEdit(_editDocument, std::move(filesData));
@ -1299,10 +1322,9 @@ void PanelController::saveScope(ValueMap &&data, ValueMap &&filesData) {
bool PanelController::editScopeChanged(
const ValueMap &data,
const ValueMap &filesData) const {
if (_editValue && _form->editValueChanged(_editValue, data)) {
if (_editValue && ValueChanged(_editValue, data)) {
return true;
} else if (_editDocument
&& _form->editValueChanged(_editDocument, filesData)) {
} else if (_editDocument && ValueChanged(_editDocument, filesData)) {
return true;
}
return false;

View File

@ -22,11 +22,13 @@ enum class ReadScanError;
EditDocumentScheme GetDocumentScheme(
Scope::Type type,
base::optional<Value::Type> scansType = base::none);
base::optional<Value::Type> scansType,
bool nativeNames);
EditContactScheme GetContactScheme(Scope::Type type);
const std::map<QString, QString> &LatinToNativeMap();
const std::map<QString, QString> &NativeToLatinMap();
QString AdjustKeyName(not_null<const Value*> value, const QString &key);
bool SkipFieldCheck(not_null<const Value*> value, const QString &key);
struct ScanInfo {

View File

@ -42,14 +42,16 @@ struct EditDocumentScheme {
Scans,
};
struct Row {
using Validator = Fn<base::optional<QString>(const QString &value)>;
using Formatter = Fn<QString(const QString &value)>;
ValueClass valueClass = ValueClass::Fields;
PanelDetailsType inputType = PanelDetailsType();
QString key;
QString label;
Fn<base::optional<QString>(const QString &value)> error;
Fn<QString(const QString &value)> format;
Validator error;
Formatter format;
int lengthLimit = 0;
QString keyForAttachmentTo; // attach last_name to first_name
QString keyForAttachmentTo; // attach [last|middle]_name to first_*
};
std::vector<Row> rows;
QString fieldsHeader;