mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-20 18:28:11 +00:00
Improve native name phrases in passport.
Also auto-save *_name to *_name_latin for english countries.
This commit is contained in:
parent
5b88f4d3d2
commit
b8b5ab6378
55
Telegram/Resources/langs/cloud_lang.strings
Normal file
55
Telegram/Resources/langs/cloud_lang.strings
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
"cloud_lng_passport_in_ar" = "Arabic";
|
||||||
|
"cloud_lng_passport_in_az" = "Azerbaijani";
|
||||||
|
"cloud_lng_passport_in_bg" = "Bulgarian";
|
||||||
|
"cloud_lng_passport_in_bn" = "Bangla";
|
||||||
|
"cloud_lng_passport_in_cs" = "Czech";
|
||||||
|
"cloud_lng_passport_in_da" = "Danish";
|
||||||
|
"cloud_lng_passport_in_de" = "German";
|
||||||
|
"cloud_lng_passport_in_dv" = "Divehi";
|
||||||
|
"cloud_lng_passport_in_dz" = "Dzongkha";
|
||||||
|
"cloud_lng_passport_in_el" = "Greek";
|
||||||
|
"cloud_lng_passport_in_en" = "English";
|
||||||
|
"cloud_lng_passport_in_es" = "Spanish";
|
||||||
|
"cloud_lng_passport_in_et" = "Estonian";
|
||||||
|
"cloud_lng_passport_in_fa" = "Persian";
|
||||||
|
"cloud_lng_passport_in_fr" = "French";
|
||||||
|
"cloud_lng_passport_in_he" = "Hebrew";
|
||||||
|
"cloud_lng_passport_in_hr" = "Croatian";
|
||||||
|
"cloud_lng_passport_in_hu" = "Hungarian";
|
||||||
|
"cloud_lng_passport_in_hy" = "Armenian";
|
||||||
|
"cloud_lng_passport_in_id" = "Indonesian";
|
||||||
|
"cloud_lng_passport_in_is" = "Icelandic";
|
||||||
|
"cloud_lng_passport_in_it" = "Italian";
|
||||||
|
"cloud_lng_passport_in_ja" = "Japanese";
|
||||||
|
"cloud_lng_passport_in_ka" = "Georgian";
|
||||||
|
"cloud_lng_passport_in_km" = "Khmer";
|
||||||
|
"cloud_lng_passport_in_ko" = "Korean";
|
||||||
|
"cloud_lng_passport_in_lo" = "Lao";
|
||||||
|
"cloud_lng_passport_in_lt" = "Lithuanian";
|
||||||
|
"cloud_lng_passport_in_lv" = "Latvian";
|
||||||
|
"cloud_lng_passport_in_mk" = "Macedonian";
|
||||||
|
"cloud_lng_passport_in_mn" = "Mongolian";
|
||||||
|
"cloud_lng_passport_in_ms" = "Malay";
|
||||||
|
"cloud_lng_passport_in_my" = "Burmese";
|
||||||
|
"cloud_lng_passport_in_ne" = "Nepali";
|
||||||
|
"cloud_lng_passport_in_nl" = "Dutch";
|
||||||
|
"cloud_lng_passport_in_pl" = "Polish";
|
||||||
|
"cloud_lng_passport_in_pt" = "Portuguese";
|
||||||
|
"cloud_lng_passport_in_ro" = "Romanian";
|
||||||
|
"cloud_lng_passport_in_ru" = "Russian";
|
||||||
|
"cloud_lng_passport_in_sk" = "Slovak";
|
||||||
|
"cloud_lng_passport_in_sl" = "Slovenian";
|
||||||
|
"cloud_lng_passport_in_th" = "Thai";
|
||||||
|
"cloud_lng_passport_in_tk" = "Turkmen";
|
||||||
|
"cloud_lng_passport_in_tr" = "Turkish";
|
||||||
|
"cloud_lng_passport_in_uk" = "Ukrainian";
|
||||||
|
"cloud_lng_passport_in_uz" = "Uzbek";
|
||||||
|
"cloud_lng_passport_in_vi" = "Vietnamese";
|
@ -1553,7 +1553,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_passport_password_wrong" = "The password you entered is not valid.";
|
"lng_passport_password_wrong" = "The password you entered is not valid.";
|
||||||
"lng_passport_header" = "Requested information";
|
"lng_passport_header" = "Requested information";
|
||||||
"lng_passport_identity_title" = "Identity document";
|
"lng_passport_identity_title" = "Identity document";
|
||||||
"lng_passport_identity_description" = "Upload a scan of your passport or another ID";
|
"lng_passport_identity_description" = "Upload proof of your identity";
|
||||||
"lng_passport_identity_passport" = "Passport";
|
"lng_passport_identity_passport" = "Passport";
|
||||||
"lng_passport_identity_passport_upload" = "Upload a scan of your passport";
|
"lng_passport_identity_passport_upload" = "Upload a scan of your passport";
|
||||||
"lng_passport_identity_card" = "Identity card";
|
"lng_passport_identity_card" = "Identity card";
|
||||||
@ -1632,6 +1632,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_passport_expiry_date" = "Expiry date";
|
"lng_passport_expiry_date" = "Expiry date";
|
||||||
"lng_passport_native_name_title" = "Name in document language";
|
"lng_passport_native_name_title" = "Name in document language";
|
||||||
"lng_passport_native_name_about" = "Your name in the language of the country ({country}) that issued the document.";
|
"lng_passport_native_name_about" = "Your name in the language of the country ({country}) that issued the document.";
|
||||||
|
"lng_passport_native_name_language" = "Your name in {language}";
|
||||||
|
"lng_passport_native_name_language_about" = "Your name in the language of the country that issued the document.";
|
||||||
"lng_passport_address" = "Address";
|
"lng_passport_address" = "Address";
|
||||||
"lng_passport_address_enter" = "Please provide your address";
|
"lng_passport_address_enter" = "Please provide your address";
|
||||||
"lng_passport_street" = "Street";
|
"lng_passport_street" = "Street";
|
||||||
|
@ -19,7 +19,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
namespace Lang {
|
namespace Lang {
|
||||||
|
|
||||||
CloudManager::CloudManager(Instance &langpack, not_null<MTP::Instance*> mtproto) : MTP::Sender()
|
CloudManager::CloudManager(
|
||||||
|
Instance &langpack,
|
||||||
|
not_null<MTP::Instance*> mtproto)
|
||||||
|
: MTP::Sender()
|
||||||
, _langpack(langpack) {
|
, _langpack(langpack) {
|
||||||
requestLangPackDifference();
|
requestLangPackDifference();
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,8 @@ void Instance::applyDifference(const MTPDlangPackDifference &difference) {
|
|||||||
_updated.notify();
|
_updated.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<LangKey, QString> Instance::ParseStrings(const MTPVector<MTPLangPackString> &strings) {
|
std::map<LangKey, QString> Instance::ParseStrings(
|
||||||
|
const MTPVector<MTPLangPackString> &strings) {
|
||||||
auto result = std::map<LangKey, QString>();
|
auto result = std::map<LangKey, QString>();
|
||||||
for (auto &mtpString : strings.v) {
|
for (auto &mtpString : strings.v) {
|
||||||
HandleString(mtpString, [&result](auto &&key, auto &&value) {
|
HandleString(mtpString, [&result](auto &&key, auto &&value) {
|
||||||
@ -449,10 +450,16 @@ std::map<LangKey, QString> Instance::ParseStrings(const MTPVector<MTPLangPackStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Result>
|
template <typename Result>
|
||||||
LangKey Instance::ParseKeyValue(const QByteArray &key, const QByteArray &value, Result &result) {
|
LangKey Instance::ParseKeyValue(
|
||||||
|
const QByteArray &key,
|
||||||
|
const QByteArray &value,
|
||||||
|
Result &result) {
|
||||||
auto keyIndex = GetKeyIndex(QLatin1String(key));
|
auto keyIndex = GetKeyIndex(QLatin1String(key));
|
||||||
if (keyIndex == kLangKeysCount) {
|
if (keyIndex == kLangKeysCount) {
|
||||||
LOG(("Lang Error: Unknown key '%1'").arg(QString::fromLatin1(key)));
|
if (!key.startsWith("cloud_")) {
|
||||||
|
LOG(("Lang Warning: Unknown key '%1'"
|
||||||
|
).arg(QString::fromLatin1(key)));
|
||||||
|
}
|
||||||
return kLangKeysCount;
|
return kLangKeysCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,6 +471,13 @@ LangKey Instance::ParseKeyValue(const QByteArray &key, const QByteArray &value,
|
|||||||
return kLangKeysCount;
|
return kLangKeysCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Instance::getNonDefaultValue(const QByteArray &key) const {
|
||||||
|
const auto i = _nonDefaultValues.find(key);
|
||||||
|
return (i != end(_nonDefaultValues))
|
||||||
|
? QString::fromUtf8(i->second)
|
||||||
|
: QString();
|
||||||
|
}
|
||||||
|
|
||||||
void Instance::applyValue(const QByteArray &key, const QByteArray &value) {
|
void Instance::applyValue(const QByteArray &key, const QByteArray &value) {
|
||||||
_nonDefaultValues[key] = value;
|
_nonDefaultValues[key] = value;
|
||||||
auto index = ParseKeyValue(key, value, _values);
|
auto index = ParseKeyValue(key, value, _values);
|
||||||
|
@ -85,6 +85,7 @@ public:
|
|||||||
|
|
||||||
return _values[key];
|
return _values[key];
|
||||||
}
|
}
|
||||||
|
QString getNonDefaultValue(const QByteArray &key) const;
|
||||||
bool isNonDefaultPlural(LangKey key) const {
|
bool isNonDefaultPlural(LangKey key) const {
|
||||||
Expects(key >= 0 && key < kLangKeysCount);
|
Expects(key >= 0 && key < kLangKeysCount);
|
||||||
Expects(_nonDefaultSet.size() == kLangKeysCount);
|
Expects(_nonDefaultSet.size() == kLangKeysCount);
|
||||||
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
#include "passport/passport_encryption.h"
|
#include "passport/passport_encryption.h"
|
||||||
#include "passport/passport_panel_controller.h"
|
#include "passport/passport_panel_controller.h"
|
||||||
|
#include "passport/passport_panel_edit_document.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "boxes/passcode_box.h"
|
#include "boxes/passcode_box.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
@ -34,6 +35,8 @@ constexpr auto kTranslationScansLimit = 20;
|
|||||||
constexpr auto kShortPollTimeout = TimeMs(3000);
|
constexpr auto kShortPollTimeout = TimeMs(3000);
|
||||||
constexpr auto kRememberCredentialsDelay = TimeMs(1800 * 1000);
|
constexpr auto kRememberCredentialsDelay = TimeMs(1800 * 1000);
|
||||||
|
|
||||||
|
Config GlobalConfig;
|
||||||
|
|
||||||
bool ForwardServiceErrorRequired(const QString &error) {
|
bool ForwardServiceErrorRequired(const QString &error) {
|
||||||
return (error == qstr("BOT_INVALID"))
|
return (error == qstr("BOT_INVALID"))
|
||||||
|| (error == qstr("PUBLIC_KEY_REQUIRED"))
|
|| (error == qstr("PUBLIC_KEY_REQUIRED"))
|
||||||
@ -228,6 +231,44 @@ QString ValidateUrl(const QString &url) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
Config &ConfigInstance() {
|
||||||
|
return GlobalConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
Config ParseConfig(const MTPhelp_PassportConfig &data) {
|
||||||
|
return data.match([](const MTPDhelp_passportConfig &data) {
|
||||||
|
auto result = Config();
|
||||||
|
result.hash = data.vhash.v;
|
||||||
|
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
|
||||||
|
const auto document = QJsonDocument::fromJson(
|
||||||
|
data.vcountries_langs.c_dataJSON().vdata.v,
|
||||||
|
&error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
LOG(("API Error: Failed to parse passport config, error: %1."
|
||||||
|
).arg(error.errorString()));
|
||||||
|
return result;
|
||||||
|
} else if (!document.isObject()) {
|
||||||
|
LOG(("API Error: Not an object received in passport config."));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const auto object = document.object();
|
||||||
|
for (auto i = object.constBegin(); i != object.constEnd(); ++i) {
|
||||||
|
const auto countryCode = i.key();
|
||||||
|
const auto language = i.value();
|
||||||
|
if (!language.isString()) {
|
||||||
|
LOG(("API Error: Not a string in passport config item."));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.languagesByCountryCode.emplace(
|
||||||
|
countryCode,
|
||||||
|
language.toString());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, [](const MTPDhelp_passportConfigNotModified &data) {
|
||||||
|
return ConfigInstance();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QString NonceNameByScope(const QString &scope) {
|
QString NonceNameByScope(const QString &scope) {
|
||||||
if (scope.startsWith('{') && scope.endsWith('}')) {
|
if (scope.startsWith('{') && scope.endsWith('}')) {
|
||||||
return qsl("nonce");
|
return qsl("nonce");
|
||||||
@ -579,6 +620,7 @@ FormController::FormController(
|
|||||||
void FormController::show() {
|
void FormController::show() {
|
||||||
requestForm();
|
requestForm();
|
||||||
requestPassword();
|
requestPassword();
|
||||||
|
requestConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
UserData *FormController::bot() const {
|
UserData *FormController::bot() const {
|
||||||
@ -1082,6 +1124,7 @@ void FormController::decryptValues() {
|
|||||||
decryptValue(value);
|
decryptValue(value);
|
||||||
}
|
}
|
||||||
fillErrors();
|
fillErrors();
|
||||||
|
fillNativeFromFallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormController::fillErrors() {
|
void FormController::fillErrors() {
|
||||||
@ -1178,6 +1221,42 @@ void FormController::fillErrors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormController::fillNativeFromFallback() {
|
||||||
|
const auto i = _form.values.find(Value::Type::PersonalDetails);
|
||||||
|
if (i == end(_form.values) || !i->second.nativeNames) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto scheme = GetDocumentScheme(
|
||||||
|
Scope::Type::PersonalDetails,
|
||||||
|
base::none,
|
||||||
|
true);
|
||||||
|
auto changed = false;
|
||||||
|
auto values = i->second.data.parsed;
|
||||||
|
using Scheme = EditDocumentScheme;
|
||||||
|
for (const auto &row : scheme.rows) {
|
||||||
|
if (row.valueClass == Scheme::ValueClass::Additional) {
|
||||||
|
auto &field = values.fields[row.key];
|
||||||
|
if (!field.text.isEmpty() || !field.error.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto i = values.fields.find(row.additionalFallbackKey);
|
||||||
|
const auto value = (i == end(values.fields))
|
||||||
|
? QString()
|
||||||
|
: i->second.text;
|
||||||
|
if (row.error(value).has_value()) {
|
||||||
|
return;
|
||||||
|
} else if (field.text != value) {
|
||||||
|
field.text = value;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
startValueEdit(&i->second);
|
||||||
|
saveValueEdit(&i->second, std::move(values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FormController::decryptValue(Value &value) const {
|
void FormController::decryptValue(Value &value) const {
|
||||||
Expects(!_secret.empty());
|
Expects(!_secret.empty());
|
||||||
|
|
||||||
@ -2375,11 +2454,29 @@ auto FormController::findFile(const FileKey &key)
|
|||||||
void FormController::formDone(const MTPaccount_AuthorizationForm &result) {
|
void FormController::formDone(const MTPaccount_AuthorizationForm &result) {
|
||||||
if (!parseForm(result)) {
|
if (!parseForm(result)) {
|
||||||
_view->showCriticalError(lang(lng_passport_form_error));
|
_view->showCriticalError(lang(lng_passport_form_error));
|
||||||
} else if (!_passwordRequestId) {
|
} else {
|
||||||
showForm();
|
showForm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormController::requestConfig() {
|
||||||
|
const auto i = _form.values.find(Value::Type::PersonalDetails);
|
||||||
|
if (i == end(_form.values) || !i->second.nativeNames) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto hash = ConfigInstance().hash;
|
||||||
|
_configRequestId = request(MTPhelp_GetPassportConfig(
|
||||||
|
MTP_int(hash)
|
||||||
|
)).done([=](const MTPhelp_PassportConfig &result) {
|
||||||
|
_configRequestId = 0;
|
||||||
|
ConfigInstance() = ParseConfig(result);
|
||||||
|
showForm();
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_configRequestId = 0;
|
||||||
|
showForm();
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
bool FormController::parseForm(const MTPaccount_AuthorizationForm &result) {
|
bool FormController::parseForm(const MTPaccount_AuthorizationForm &result) {
|
||||||
Expects(result.type() == mtpc_account_authorizationForm);
|
Expects(result.type() == mtpc_account_authorizationForm);
|
||||||
|
|
||||||
@ -2458,7 +2555,7 @@ void FormController::passwordDone(const MTPaccount_Password &result) {
|
|||||||
Expects(result.type() == mtpc_account_password);
|
Expects(result.type() == mtpc_account_password);
|
||||||
|
|
||||||
const auto changed = applyPassword(result.c_account_password());
|
const auto changed = applyPassword(result.c_account_password());
|
||||||
if (changed && !_formRequestId) {
|
if (changed) {
|
||||||
showForm();
|
showForm();
|
||||||
}
|
}
|
||||||
shortPollEmailConfirmation();
|
shortPollEmailConfirmation();
|
||||||
@ -2473,7 +2570,9 @@ void FormController::shortPollEmailConfirmation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FormController::showForm() {
|
void FormController::showForm() {
|
||||||
if (!_bot) {
|
if (_formRequestId || _passwordRequestId || _configRequestId) {
|
||||||
|
return;
|
||||||
|
} else if (!_bot) {
|
||||||
formFail(Lang::Hard::NoAuthorizationBot());
|
formFail(Lang::Hard::NoAuthorizationBot());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,13 @@ class Controller;
|
|||||||
|
|
||||||
namespace Passport {
|
namespace Passport {
|
||||||
|
|
||||||
|
struct Config {
|
||||||
|
int32 hash = 0;
|
||||||
|
std::map<QString, QString> languagesByCountryCode;
|
||||||
|
};
|
||||||
|
Config &ConfigInstance();
|
||||||
|
Config ParseConfig(const MTPhelp_PassportConfig &data);
|
||||||
|
|
||||||
struct SavedCredentials {
|
struct SavedCredentials {
|
||||||
bytes::vector hashForAuth;
|
bytes::vector hashForAuth;
|
||||||
bytes::vector hashForSecret;
|
bytes::vector hashForSecret;
|
||||||
@ -387,6 +394,7 @@ private:
|
|||||||
|
|
||||||
void requestForm();
|
void requestForm();
|
||||||
void requestPassword();
|
void requestPassword();
|
||||||
|
void requestConfig();
|
||||||
|
|
||||||
void formDone(const MTPaccount_AuthorizationForm &result);
|
void formDone(const MTPaccount_AuthorizationForm &result);
|
||||||
void formFail(const QString &error);
|
void formFail(const QString &error);
|
||||||
@ -436,6 +444,7 @@ private:
|
|||||||
bool validateValueSecrets(Value &value) const;
|
bool validateValueSecrets(Value &value) const;
|
||||||
void resetValue(Value &value) const;
|
void resetValue(Value &value) const;
|
||||||
void fillErrors();
|
void fillErrors();
|
||||||
|
void fillNativeFromFallback();
|
||||||
|
|
||||||
void loadFile(File &file);
|
void loadFile(File &file);
|
||||||
void fileLoadDone(FileKey key, const QByteArray &bytes);
|
void fileLoadDone(FileKey key, const QByteArray &bytes);
|
||||||
@ -505,6 +514,7 @@ private:
|
|||||||
mtpRequestId _formRequestId = 0;
|
mtpRequestId _formRequestId = 0;
|
||||||
mtpRequestId _passwordRequestId = 0;
|
mtpRequestId _passwordRequestId = 0;
|
||||||
mtpRequestId _passwordCheckRequestId = 0;
|
mtpRequestId _passwordCheckRequestId = 0;
|
||||||
|
mtpRequestId _configRequestId = 0;
|
||||||
|
|
||||||
PasswordSettings _password;
|
PasswordSettings _password;
|
||||||
TimeMs _lastSrpIdInvalidTime = 0;
|
TimeMs _lastSrpIdInvalidTime = 0;
|
||||||
|
@ -32,6 +32,7 @@ constexpr auto kMaxStreetSize = 64;
|
|||||||
constexpr auto kMinCitySize = 2;
|
constexpr auto kMinCitySize = 2;
|
||||||
constexpr auto kMaxCitySize = 64;
|
constexpr auto kMaxCitySize = 64;
|
||||||
constexpr auto kMaxPostcodeSize = 10;
|
constexpr auto kMaxPostcodeSize = 10;
|
||||||
|
const auto kLanguageNamePrefix = "cloud_lng_passport_in_";
|
||||||
|
|
||||||
ScanInfo CollectScanInfo(const EditFile &file) {
|
ScanInfo CollectScanInfo(const EditFile &file) {
|
||||||
const auto status = [&] {
|
const auto status = [&] {
|
||||||
@ -282,8 +283,33 @@ EditDocumentScheme GetDocumentScheme(
|
|||||||
};
|
};
|
||||||
if (nativeNames) {
|
if (nativeNames) {
|
||||||
result.additionalDependencyKey = qsl("residence_country_code");
|
result.additionalDependencyKey = qsl("residence_country_code");
|
||||||
result.additionalHeader = lang(lng_passport_native_name_title);
|
|
||||||
result.additionalDescription = [](const QString &countryCode) {
|
const auto languageValue = [](const QString &countryCode) {
|
||||||
|
if (countryCode.isEmpty()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
const auto &config = ConfigInstance();
|
||||||
|
const auto i = config.languagesByCountryCode.find(
|
||||||
|
countryCode);
|
||||||
|
if (i == end(config.languagesByCountryCode)) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return Lang::Current().getNonDefaultValue(
|
||||||
|
kLanguageNamePrefix + i->second.toUtf8());
|
||||||
|
};
|
||||||
|
result.additionalHeader = [=](const QString &countryCode) {
|
||||||
|
const auto language = languageValue(countryCode);
|
||||||
|
return language.isEmpty()
|
||||||
|
? lang(lng_passport_native_name_title)
|
||||||
|
: lng_passport_native_name_language(
|
||||||
|
lt_language,
|
||||||
|
language);
|
||||||
|
};
|
||||||
|
result.additionalDescription = [=](const QString &countryCode) {
|
||||||
|
const auto language = languageValue(countryCode);
|
||||||
|
if (!language.isEmpty()) {
|
||||||
|
return lang(lng_passport_native_name_language_about);
|
||||||
|
}
|
||||||
const auto name = CountrySelectBox::NameByISO(countryCode);
|
const auto name = CountrySelectBox::NameByISO(countryCode);
|
||||||
Assert(!name.isEmpty());
|
Assert(!name.isEmpty());
|
||||||
return lng_passport_native_name_about(
|
return lng_passport_native_name_about(
|
||||||
@ -291,7 +317,18 @@ EditDocumentScheme GetDocumentScheme(
|
|||||||
name);
|
name);
|
||||||
};
|
};
|
||||||
result.additionalShown = [](const QString &countryCode) {
|
result.additionalShown = [](const QString &countryCode) {
|
||||||
return !countryCode.isEmpty();
|
using Result = EditDocumentScheme::AdditionalVisibility;
|
||||||
|
if (countryCode.isEmpty()) {
|
||||||
|
return Result::Hidden;
|
||||||
|
}
|
||||||
|
const auto &config = ConfigInstance();
|
||||||
|
const auto i = config.languagesByCountryCode.find(
|
||||||
|
countryCode);
|
||||||
|
if (i != end(config.languagesByCountryCode)
|
||||||
|
&& i->second == "en") {
|
||||||
|
return Result::OnlyIfError;
|
||||||
|
}
|
||||||
|
return Result::Shown;
|
||||||
};
|
};
|
||||||
using Row = EditDocumentScheme::Row;
|
using Row = EditDocumentScheme::Row;
|
||||||
auto additional = std::initializer_list<Row>{
|
auto additional = std::initializer_list<Row>{
|
||||||
@ -303,6 +340,8 @@ EditDocumentScheme GetDocumentScheme(
|
|||||||
NativeNameValidate,
|
NativeNameValidate,
|
||||||
DontFormat,
|
DontFormat,
|
||||||
kMaxNameSize,
|
kMaxNameSize,
|
||||||
|
QString(),
|
||||||
|
qsl("first_name"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ValueClass::Additional,
|
ValueClass::Additional,
|
||||||
@ -313,6 +352,7 @@ EditDocumentScheme GetDocumentScheme(
|
|||||||
DontFormat,
|
DontFormat,
|
||||||
kMaxNameSize,
|
kMaxNameSize,
|
||||||
qsl("first_name_native"),
|
qsl("first_name_native"),
|
||||||
|
qsl("middle_name"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ValueClass::Additional,
|
ValueClass::Additional,
|
||||||
@ -323,6 +363,7 @@ EditDocumentScheme GetDocumentScheme(
|
|||||||
DontFormat,
|
DontFormat,
|
||||||
kMaxNameSize,
|
kMaxNameSize,
|
||||||
qsl("first_name_native"),
|
qsl("first_name_native"),
|
||||||
|
qsl("last_name"),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
for (auto &row : additional) {
|
for (auto &row : additional) {
|
||||||
|
@ -404,11 +404,47 @@ not_null<Ui::RpWidget*> PanelEditDocument::setupContent(
|
|||||||
inner,
|
inner,
|
||||||
object_ptr<Ui::VerticalLayout>(inner)));
|
object_ptr<Ui::VerticalLayout>(inner)));
|
||||||
const auto added = wrap->entity();
|
const auto added = wrap->entity();
|
||||||
|
|
||||||
|
auto showIfError = false;
|
||||||
|
enumerateRows([&](
|
||||||
|
int i,
|
||||||
|
const Scheme::Row &row,
|
||||||
|
const ValueMap &fields) {
|
||||||
|
if (row.valueClass != Scheme::ValueClass::Additional) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto it = fields.fields.find(row.key);
|
||||||
|
if (it == end(fields.fields)) {
|
||||||
|
return;
|
||||||
|
} else if (!it->second.error.isEmpty()) {
|
||||||
|
showIfError = true;
|
||||||
|
} else if (it->second.text.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto fallbackIt = fields.fields.find(
|
||||||
|
row.additionalFallbackKey);
|
||||||
|
if (fallbackIt != end(fields.fields)
|
||||||
|
&& fallbackIt->second.text != it->second.text) {
|
||||||
|
showIfError = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const auto shown = [=](const QString &code) {
|
||||||
|
using Result = Scheme::AdditionalVisibility;
|
||||||
|
const auto value = _scheme.additionalShown(code);
|
||||||
|
return (value == Result::Shown)
|
||||||
|
|| (value == Result::OnlyIfError && showIfError);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto title = row->value(
|
||||||
|
) | rpl::filter(
|
||||||
|
shown
|
||||||
|
) | rpl::map([=](const QString &code) {
|
||||||
|
return _scheme.additionalHeader(code);
|
||||||
|
});
|
||||||
added->add(
|
added->add(
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
added,
|
added,
|
||||||
_scheme.additionalHeader,
|
std::move(title),
|
||||||
Ui::FlatLabel::InitType::Simple,
|
|
||||||
st::passportFormHeader),
|
st::passportFormHeader),
|
||||||
st::passportNativeNameHeaderPadding);
|
st::passportNativeNameHeaderPadding);
|
||||||
|
|
||||||
@ -422,9 +458,9 @@ not_null<Ui::RpWidget*> PanelEditDocument::setupContent(
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto description = row->value(
|
auto description = row->value(
|
||||||
) | rpl::filter([=](const QString &code) {
|
) | rpl::filter(
|
||||||
return _scheme.additionalShown(code);
|
shown
|
||||||
}) | rpl::map([=](const QString &code) {
|
) | rpl::map([=](const QString &code) {
|
||||||
return _scheme.additionalDescription(code);
|
return _scheme.additionalDescription(code);
|
||||||
});
|
});
|
||||||
added->add(
|
added->add(
|
||||||
@ -437,11 +473,15 @@ not_null<Ui::RpWidget*> PanelEditDocument::setupContent(
|
|||||||
st::passportFormLabelPadding),
|
st::passportFormLabelPadding),
|
||||||
st::passportNativeNameAboutMargin);
|
st::passportNativeNameAboutMargin);
|
||||||
|
|
||||||
wrap->toggleOn(row->value(
|
wrap->toggleOn(row->value() | rpl::map(shown));
|
||||||
) | rpl::map([=](const QString &code) {
|
|
||||||
return _scheme.additionalShown(code);
|
|
||||||
}));
|
|
||||||
wrap->finishAnimating();
|
wrap->finishAnimating();
|
||||||
|
|
||||||
|
row->value(
|
||||||
|
) | rpl::map(
|
||||||
|
shown
|
||||||
|
) | rpl::start_with_next([=](bool visible) {
|
||||||
|
_additionalShown = visible;
|
||||||
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
inner->add(
|
inner->add(
|
||||||
@ -469,8 +509,8 @@ void PanelEditDocument::createDetailsRow(
|
|||||||
const ValueMap &fields,
|
const ValueMap &fields,
|
||||||
int maxLabelWidth) {
|
int maxLabelWidth) {
|
||||||
const auto valueOrEmpty = [&](
|
const auto valueOrEmpty = [&](
|
||||||
const ValueMap &values,
|
const ValueMap &values,
|
||||||
const QString &key) {
|
const QString &key) {
|
||||||
const auto &fields = values.fields;
|
const auto &fields = values.fields;
|
||||||
if (const auto i = fields.find(key); i != fields.end()) {
|
if (const auto i = fields.find(key); i != fields.end()) {
|
||||||
return i->second;
|
return i->second;
|
||||||
@ -561,11 +601,31 @@ PanelEditDocument::Result PanelEditDocument::collect() const {
|
|||||||
auto &fields = (row.valueClass == Scheme::ValueClass::Scans)
|
auto &fields = (row.valueClass == Scheme::ValueClass::Scans)
|
||||||
? result.filesData
|
? result.filesData
|
||||||
: result.data;
|
: result.data;
|
||||||
|
if (row.valueClass == Scheme::ValueClass::Additional
|
||||||
|
&& !_additionalShown) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
fields.fields[row.key].text = field->valueCurrent();
|
fields.fields[row.key].text = field->valueCurrent();
|
||||||
}
|
}
|
||||||
|
if (!_additionalShown) {
|
||||||
|
fillAdditionalFromFallbacks(result);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PanelEditDocument::fillAdditionalFromFallbacks(Result &result) const {
|
||||||
|
for (const auto &row : _scheme.rows) {
|
||||||
|
if (row.valueClass != Scheme::ValueClass::Additional) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Assert(!row.additionalFallbackKey.isEmpty());
|
||||||
|
auto &fields = result.data;
|
||||||
|
const auto j = fields.fields.find(row.additionalFallbackKey);
|
||||||
|
Assert(j != end(fields.fields));
|
||||||
|
fields.fields[row.key] = j->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool PanelEditDocument::validate() {
|
bool PanelEditDocument::validate() {
|
||||||
auto error = _editScans
|
auto error = _editScans
|
||||||
? _editScans->validateGetErrorTop()
|
? _editScans->validateGetErrorTop()
|
||||||
@ -585,6 +645,10 @@ bool PanelEditDocument::validate() {
|
|||||||
auto first = QPointer<PanelDetailsRow>();
|
auto first = QPointer<PanelDetailsRow>();
|
||||||
for (const auto [i, field] : base::reversed(_details)) {
|
for (const auto [i, field] : base::reversed(_details)) {
|
||||||
const auto &row = _scheme.rows[i];
|
const auto &row = _scheme.rows[i];
|
||||||
|
if (row.valueClass == Scheme::ValueClass::Additional
|
||||||
|
&& !_additionalShown) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (field->errorShown()) {
|
if (field->errorShown()) {
|
||||||
field->showError();
|
field->showError();
|
||||||
first = field;
|
first = field;
|
||||||
|
@ -44,6 +44,11 @@ struct EditDocumentScheme {
|
|||||||
Additional,
|
Additional,
|
||||||
Scans,
|
Scans,
|
||||||
};
|
};
|
||||||
|
enum class AdditionalVisibility {
|
||||||
|
Hidden,
|
||||||
|
OnlyIfError,
|
||||||
|
Shown,
|
||||||
|
};
|
||||||
struct Row {
|
struct Row {
|
||||||
using Validator = Fn<base::optional<QString>(const QString &value)>;
|
using Validator = Fn<base::optional<QString>(const QString &value)>;
|
||||||
using Formatter = Fn<QString(const QString &value)>;
|
using Formatter = Fn<QString(const QString &value)>;
|
||||||
@ -54,7 +59,8 @@ struct EditDocumentScheme {
|
|||||||
Validator error;
|
Validator error;
|
||||||
Formatter format;
|
Formatter format;
|
||||||
int lengthLimit = 0;
|
int lengthLimit = 0;
|
||||||
QString keyForAttachmentTo; // attach [last|middle]_name to first_*
|
QString keyForAttachmentTo; // Attach [last|middle]_name to first_*.
|
||||||
|
QString additionalFallbackKey; // *_name_native from *_name.
|
||||||
};
|
};
|
||||||
std::vector<Row> rows;
|
std::vector<Row> rows;
|
||||||
QString fieldsHeader;
|
QString fieldsHeader;
|
||||||
@ -62,8 +68,8 @@ struct EditDocumentScheme {
|
|||||||
QString scansHeader;
|
QString scansHeader;
|
||||||
|
|
||||||
QString additionalDependencyKey;
|
QString additionalDependencyKey;
|
||||||
Fn<bool(const QString &dependency)> additionalShown;
|
Fn<AdditionalVisibility(const QString &dependency)> additionalShown;
|
||||||
QString additionalHeader;
|
Fn<QString(const QString &dependency)> additionalHeader;
|
||||||
Fn<QString(const QString &dependency)> additionalDescription;
|
Fn<QString(const QString &dependency)> additionalDescription;
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -127,6 +133,7 @@ private:
|
|||||||
void updateCommonError();
|
void updateCommonError();
|
||||||
|
|
||||||
Result collect() const;
|
Result collect() const;
|
||||||
|
void fillAdditionalFromFallbacks(Result &result) const;
|
||||||
bool validate();
|
bool validate();
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
@ -149,6 +156,7 @@ private:
|
|||||||
QPointer<Ui::SlideWrap<Ui::FlatLabel>> _commonError;
|
QPointer<Ui::SlideWrap<Ui::FlatLabel>> _commonError;
|
||||||
std::map<int, QPointer<PanelDetailsRow>> _details;
|
std::map<int, QPointer<PanelDetailsRow>> _details;
|
||||||
bool _fieldsChanged = false;
|
bool _fieldsChanged = false;
|
||||||
|
bool _additionalShown = false;
|
||||||
|
|
||||||
QPointer<Info::Profile::Button> _delete;
|
QPointer<Info::Profile::Button> _delete;
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@
|
|||||||
'<@(style_files)',
|
'<@(style_files)',
|
||||||
'<!@(<(list_sources_command) <(qt_moc_list_sources_arg))',
|
'<!@(<(list_sources_command) <(qt_moc_list_sources_arg))',
|
||||||
'telegram_sources.txt',
|
'telegram_sources.txt',
|
||||||
|
'<(res_loc)/langs/cloud_lang.strings',
|
||||||
'<(res_loc)/export_html/css/style.css',
|
'<(res_loc)/export_html/css/style.css',
|
||||||
'<(res_loc)/export_html/js/script.js',
|
'<(res_loc)/export_html/js/script.js',
|
||||||
'<(res_loc)/export_html/images/back.png',
|
'<(res_loc)/export_html/images/back.png',
|
||||||
|
Loading…
Reference in New Issue
Block a user