Improve phrases and icons in passport.

This commit is contained in:
John Preston 2018-04-12 14:20:54 +04:00
parent 9142313a6b
commit c20cf243db
19 changed files with 394 additions and 109 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

View file

@ -1553,6 +1553,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_selfie_description" = "Take a picture of yourself holding hour document.";
"lng_passport_upload_selfie" = "Upload selfie";
"lng_passport_personal_details" = "Personal details";
"lng_passport_personal_details_enter" = "Enter your personal details";
"lng_passport_choose_image" = "Choose scan image";
"lng_passport_delete_scan_undo" = "Undo";
"lng_passport_scan_uploaded" = "Uploaded on {date}";
@ -1567,6 +1568,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_document_number" = "Card Number";
"lng_passport_expiry_date" = "Expiry date";
"lng_passport_address" = "Address";
"lng_passport_address_enter" = "Enter your address";
"lng_passport_street" = "Street";
"lng_passport_city" = "City";
"lng_passport_state" = "State";

View file

@ -97,6 +97,8 @@ passportPanelAuthorize: RoundButton(passportPasswordSubmit) {
height: 49px;
padding: margins(0px, -3px, 0px, 0px);
textTop: 16px;
icon: icon {{ "passport_authorize", activeButtonFg }};
iconPosition: point(-8px, 9px);
}
passportPanelSaveValue: RoundButton(passportPanelAuthorize) {
textFg: windowActiveTextFg;
@ -104,6 +106,7 @@ passportPanelSaveValue: RoundButton(passportPanelAuthorize) {
textBg: windowBg;
textBgOver: windowBgOver;
ripple: defaultRippleAnimation;
icon: icon {};
}
passportFormAbout1Padding: margins(10px, 4px, 10px, 0px);
passportFormAbout2Padding: margins(10px, 0px, 10px, 22px);
@ -142,8 +145,8 @@ passportRowSkip: 2px;
passportRowRipple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
passportRowReadyIcon: icon {{ "send_control_save", windowActiveTextFg }};
passportRowEmptyIcon: icon {{ "title_back-flip_horizontal", menuIconFgOver }};
passportRowReadyIcon: icon {{ "passport_ready", windowActiveTextFg }};
passportRowEmptyIcon: icon {{ "passport_empty", menuIconFgOver }};
passportRowTitleFg: windowFg;
passportRowDescriptionFg: windowSubTextFg;

View file

@ -31,8 +31,10 @@ AesParams PrepareAesParams(bytes::const_span bytesForEncryptionKey) {
const auto view = gsl::make_span(hash);
auto result = AesParams();
result.key = bytes::make_vector(view.subspan(0, kAesKeyLength));
result.iv = bytes::make_vector(view.subspan(kAesKeyLength, kAesIvLength));
result.key = bytes::make_vector(
view.subspan(0, kAesKeyLength));
result.iv = bytes::make_vector(
view.subspan(kAesKeyLength, kAesIvLength));
return result;
}

View file

@ -543,7 +543,9 @@ void FormController::verify(
}).fail([=](const RPCError &error) {
nonconst->verification.requestId = 0;
if (error.type() == qstr("PHONE_CODE_INVALID")) {
verificationError(nonconst, lang(lng_signin_wrong_code));
verificationError(
nonconst,
lang(lng_signin_wrong_code));
} else {
verificationError(nonconst, error.type());
}
@ -558,7 +560,9 @@ void FormController::verify(
}).fail([=](const RPCError &error) {
nonconst->verification.requestId = 0;
if (error.type() == qstr("CODE_INVALID")) {
verificationError(nonconst, lang(lng_signin_wrong_code));
verificationError(
nonconst,
lang(lng_signin_wrong_code));
} else {
verificationError(nonconst, error.type());
}
@ -864,7 +868,8 @@ void FormController::saveEncryptedValue(not_null<Value*> value) {
_secret,
value->data.hashInEdit);
const auto selfie = value->selfieInEdit
const auto selfie = (value->selfieInEdit
&& !value->selfieInEdit->deleted)
? inputFile(*value->selfieInEdit)
: MTPInputSecureFile();
@ -896,7 +901,7 @@ void FormController::saveEncryptedValue(not_null<Value*> value) {
| (value->filesInEdit.empty()
? MTPDinputSecureValue::Flag(0)
: MTPDinputSecureValue::Flag::f_files)
| (value->selfieInEdit
| ((value->selfieInEdit && !value->selfieInEdit->deleted)
? MTPDinputSecureValue::Flag::f_selfie
: MTPDinputSecureValue::Flag(0));
Assert(flags != MTPDinputSecureValue::Flags(0));
@ -953,16 +958,16 @@ void FormController::sendSaveRequest(
value->saveRequestId = 0;
const auto &data = result.c_secureValue();
value->files = data.has_files()
? parseFiles(
data.vfiles.v,
base::take(value->filesInEdit))
: std::vector<File>();
const auto filesInEdit = base::take(value->filesInEdit);
auto selfiesInEdit = std::vector<EditFile>();
if (auto selfie = base::take(value->selfieInEdit)) {
selfiesInEdit.push_back(std::move(*selfie));
}
const auto &data = result.c_secureValue();
value->files = data.has_files()
? parseFiles(data.vfiles.v, filesInEdit)
: std::vector<File>();
value->selfie = data.has_selfie()
? parseFile(data.vselfie, selfiesInEdit)
: base::none;

View file

@ -295,7 +295,7 @@ void Panel::focusInEvent(QFocusEvent *e) {
}
void Panel::initGeometry() {
auto center = Messenger::Instance().getPointForCallPanelCenter();
const auto center = Messenger::Instance().getPointForCallPanelCenter();
_useTransparency = Platform::TranslucentWindowsSupported(center);
setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
_padding = _useTransparency
@ -305,9 +305,14 @@ void Panel::initGeometry() {
st::lineWidth,
st::lineWidth,
st::lineWidth);
auto screen = QApplication::desktop()->screenGeometry(center);
auto rect = QRect(0, 0, st::passportPanelWidth, st::passportPanelHeight);
setGeometry(rect.translated(center - rect.center()).marginsAdded(_padding));
const auto screen = QApplication::desktop()->screenGeometry(center);
const auto rect = QRect(
0,
0,
st::passportPanelWidth,
st::passportPanelHeight);
setGeometry(
rect.translated(center - rect.center()).marginsAdded(_padding));
updateControlsGeometry();
}
@ -368,34 +373,110 @@ void Panel::paintShadowBorder(Painter &p) const {
const auto part1 = size / 3;
const auto part2 = size - part1;
const auto corner = QSize(part1, part1) * factor;
const auto topleft = QRect(QPoint(0, 0), corner);
p.drawPixmap(QRect(0, 0, part1, part1), _borderParts, topleft);
const auto topright = QRect(QPoint(part2, 0) * factor, corner);
p.drawPixmap(QRect(width() - part1, 0, part1, part1), _borderParts, topright);
const auto bottomleft = QRect(QPoint(0, part2) * factor, corner);
p.drawPixmap(QRect(0, height() - part1, part1, part1), _borderParts, bottomleft);
const auto bottomright = QRect(QPoint(part2, part2) * factor, corner);
p.drawPixmap(QRect(width() - part1, height() - part1, part1, part1), _borderParts, bottomright);
const auto left = QRect(QPoint(0, part1) * factor, QSize(_padding.left(), part2 - part1) * factor);
p.drawPixmap(QRect(0, part1, _padding.left(), height() - 2 * part1), _borderParts, left);
const auto top = QRect(QPoint(part1, 0) * factor, QSize(part2 - part1, _padding.top() + st::callRadius) * factor);
p.drawPixmap(QRect(part1, 0, width() - 2 * part1, _padding.top() + st::callRadius), _borderParts, top);
const auto right = QRect(QPoint(size - _padding.right(), part1) * factor, QSize(_padding.right(), part2 - part1) * factor);
p.drawPixmap(QRect(width() - _padding.right(), part1, _padding.right(), height() - 2 * part1), _borderParts, right);
const auto bottom = QRect(QPoint(part1, size - _padding.bottom() - st::callRadius) * factor, QSize(part2 - part1, _padding.bottom() + st::callRadius) * factor);
p.drawPixmap(QRect(part1, height() - _padding.bottom() - st::callRadius, width() - 2 * part1, _padding.bottom() + st::callRadius), _borderParts, bottom);
p.fillRect(_padding.left(), _padding.top() + st::callRadius, width() - _padding.left() - _padding.right(), height() - _padding.top() - _padding.bottom() - 2 * st::callRadius, st::windowBg);
const auto topright = QRect(QPoint(part2, 0) * factor, corner);
p.drawPixmap(
QRect(width() - part1, 0, part1, part1),
_borderParts,
topright);
const auto bottomleft = QRect(QPoint(0, part2) * factor, corner);
p.drawPixmap(
QRect(0, height() - part1, part1, part1),
_borderParts,
bottomleft);
const auto bottomright = QRect(QPoint(part2, part2) * factor, corner);
p.drawPixmap(
QRect(width() - part1, height() - part1, part1, part1),
_borderParts,
bottomright);
const auto left = QRect(
QPoint(0, part1) * factor,
QSize(_padding.left(), part2 - part1) * factor);
p.drawPixmap(
QRect(0, part1, _padding.left(), height() - 2 * part1),
_borderParts,
left);
const auto top = QRect(
QPoint(part1, 0) * factor,
QSize(part2 - part1, _padding.top() + st::callRadius) * factor);
p.drawPixmap(
QRect(
part1,
0,
width() - 2 * part1,
_padding.top() + st::callRadius),
_borderParts,
top);
const auto right = QRect(
QPoint(size - _padding.right(), part1) * factor,
QSize(_padding.right(), part2 - part1) * factor);
p.drawPixmap(
QRect(
width() - _padding.right(),
part1,
_padding.right(),
height() - 2 * part1),
_borderParts,
right);
const auto bottom = QRect(
QPoint(part1, size - _padding.bottom() - st::callRadius) * factor,
QSize(part2 - part1, _padding.bottom() + st::callRadius) * factor);
p.drawPixmap(
QRect(
part1,
height() - _padding.bottom() - st::callRadius,
width() - 2 * part1,
_padding.bottom() + st::callRadius),
_borderParts,
bottom);
p.fillRect(
_padding.left(),
_padding.top() + st::callRadius,
width() - _padding.left() - _padding.right(),
height() - _padding.top() - _padding.bottom() - 2 * st::callRadius,
st::windowBg);
}
void Panel::paintOpaqueBorder(Painter &p) const {
const auto border = st::windowShadowFgFallback;
p.fillRect(0, 0, width(), _padding.top(), border);
p.fillRect(myrtlrect(0, _padding.top(), _padding.left(), height() - _padding.top()), border);
p.fillRect(myrtlrect(width() - _padding.right(), _padding.top(), _padding.right(), height() - _padding.top()), border);
p.fillRect(_padding.left(), height() - _padding.bottom(), width() - _padding.left() - _padding.right(), _padding.bottom(), border);
p.fillRect(
myrtlrect(
0,
_padding.top(),
_padding.left(),
height() - _padding.top()),
border);
p.fillRect(
myrtlrect(
width() - _padding.right(),
_padding.top(),
_padding.right(),
height() - _padding.top()),
border);
p.fillRect(
_padding.left(),
height() - _padding.bottom(),
width() - _padding.left() - _padding.right(),
_padding.bottom(),
border);
p.fillRect(_padding.left(), _padding.top(), width() - _padding.left() - _padding.right(), height() - _padding.top() - _padding.bottom(), st::windowBg);
p.fillRect(
_padding.left(),
_padding.top(),
width() - _padding.left() - _padding.right(),
height() - _padding.top() - _padding.bottom(),
st::windowBg);
}
void Panel::closeEvent(QCloseEvent *e) {
@ -423,7 +504,8 @@ void Panel::mouseMoveEvent(QMouseEvent *e) {
if (!(e->buttons() & Qt::LeftButton)) {
_dragging = false;
} else {
move(_dragStartMyPosition + (e->globalPos() - _dragStartMousePosition));
move(_dragStartMyPosition
+ (e->globalPos() - _dragStartMousePosition));
}
}
}

View file

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "passport/passport_panel_edit_scans.h"
#include "passport/passport_panel.h"
#include "boxes/confirm_box.h"
#include "ui/countryinput.h"
#include "layout.h"
namespace Passport {
@ -24,6 +25,19 @@ PanelEditDocument::Scheme GetDocumentScheme(
base::optional<Value::Type> scansType = base::none) {
using Scheme = PanelEditDocument::Scheme;
const auto DontFormat = nullptr;
const auto CountryFormat = [](const QString &value) {
const auto result = CountrySelectBox::NameByISO(value);
return result.isEmpty() ? value : result;
};
const auto GenderFormat = [](const QString &value) {
if (value == qstr("male")) {
return lang(lng_passport_gender_male);
} else if (value == qstr("female")) {
return lang(lng_passport_gender_female);
}
return value;
};
const auto DontValidate = nullptr;
const auto NotEmptyValidate = [](const QString &value) {
return !value.isEmpty();
@ -39,8 +53,8 @@ PanelEditDocument::Scheme GetDocumentScheme(
const auto GenderValidate = [](const QString &value) {
return value == qstr("male") || value == qstr("female");
};
const auto CountryValidate = [](const QString &value) {
return QRegularExpression("^[A-Z]{2}$").match(value).hasMatch();
const auto CountryValidate = [=](const QString &value) {
return !CountryFormat(value).isEmpty();
};
switch (type) {
@ -68,14 +82,16 @@ PanelEditDocument::Scheme GetDocumentScheme(
PanelDetailsType::Text,
qsl("first_name"),
lang(lng_passport_first_name),
NotEmptyValidate
NotEmptyValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
PanelDetailsType::Text,
qsl("last_name"),
lang(lng_passport_last_name),
DontValidate
DontValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
@ -83,6 +99,7 @@ PanelEditDocument::Scheme GetDocumentScheme(
qsl("birth_date"),
lang(lng_passport_birth_date),
DateValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
@ -90,6 +107,7 @@ PanelEditDocument::Scheme GetDocumentScheme(
qsl("gender"),
lang(lng_passport_gender),
GenderValidate,
GenderFormat,
},
{
Scheme::ValueType::Fields,
@ -97,6 +115,7 @@ PanelEditDocument::Scheme GetDocumentScheme(
qsl("country_code"),
lang(lng_passport_country),
CountryValidate,
CountryFormat,
},
{
Scheme::ValueType::Scans,
@ -104,6 +123,7 @@ PanelEditDocument::Scheme GetDocumentScheme(
qsl("document_no"),
lang(lng_passport_document_number),
NotEmptyValidate,
DontFormat,
},
{
Scheme::ValueType::Scans,
@ -111,6 +131,7 @@ PanelEditDocument::Scheme GetDocumentScheme(
qsl("expiry_date"),
lang(lng_passport_expiry_date),
DateOrEmptyValidate,
DontFormat,
},
};
return result;
@ -131,7 +152,7 @@ PanelEditDocument::Scheme GetDocumentScheme(
result.scansHeader = lang(lng_passport_address_agreement);
break;
default:
Unexpected("scansType in GetDocumentScheme:Identity.");
Unexpected("scansType in GetDocumentScheme:Address.");
}
}
result.rows = {
@ -140,42 +161,48 @@ PanelEditDocument::Scheme GetDocumentScheme(
PanelDetailsType::Text,
qsl("street_line1"),
lang(lng_passport_street),
NotEmptyValidate
NotEmptyValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
PanelDetailsType::Text,
qsl("street_line2"),
lang(lng_passport_street),
DontValidate
DontValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
PanelDetailsType::Text,
qsl("city"),
lang(lng_passport_city),
NotEmptyValidate
NotEmptyValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
PanelDetailsType::Text,
qsl("state"),
lang(lng_passport_state),
DontValidate
DontValidate,
DontFormat,
},
{
Scheme::ValueType::Fields,
PanelDetailsType::Country,
qsl("country_code"),
lang(lng_passport_country),
CountryValidate
CountryValidate,
CountryFormat,
},
{
Scheme::ValueType::Fields,
PanelDetailsType::Text,
qsl("post_code"),
lang(lng_passport_postcode),
NotEmptyValidate
NotEmptyValidate,
DontFormat,
},
};
return result;
@ -197,7 +224,7 @@ PanelEditContact::Scheme GetContactScheme(Scope::Type type) {
"^\\d{2,12}$"
).match(value).hasMatch();
};
result.preprocess = [](const QString &value) {
result.format = [](const QString &value) {
return App::formatPhone(value);
};
result.postprocess = [](QString value) {
@ -217,7 +244,7 @@ PanelEditContact::Scheme GetContactScheme(Scope::Type type) {
const auto dot = value.lastIndexOf('.');
return (at > 0) && (dot > at);
};
result.preprocess = result.postprocess = [](const QString &value) {
result.format = result.postprocess = [](const QString &value) {
return value.trimmed();
};
return result;
@ -296,6 +323,158 @@ QString PanelController::privacyPolicyUrl() const {
return _form->privacyPolicyUrl();
}
auto PanelController::collectRowInfo(const Scope &scope) const -> Row {
switch (scope.type) {
case Scope::Type::Identity:
if (scope.files.empty()) {
return {
lang(lng_passport_personal_details),
lang(lng_passport_personal_details_enter)
};
} else if (scope.files.size() == 1) {
switch (scope.files.front()->type) {
case Value::Type::Passport:
return {
lang(lng_passport_identity_passport),
lang(lng_passport_identity_passport_upload)
};
case Value::Type::IdentityCard:
return {
lang(lng_passport_identity_card),
lang(lng_passport_identity_card_upload)
};
case Value::Type::DriverLicense:
return {
lang(lng_passport_identity_license),
lang(lng_passport_identity_license_upload)
};
default: Unexpected("Identity type in collectRowInfo.");
}
}
return {
lang(lng_passport_identity_title),
lang(lng_passport_identity_description)
};
case Scope::Type::Address:
if (scope.files.empty()) {
return {
lang(lng_passport_address),
lang(lng_passport_address_enter)
};
} else if (scope.files.size() == 1) {
switch (scope.files.front()->type) {
case Value::Type::BankStatement:
return {
lang(lng_passport_address_statement),
lang(lng_passport_address_statement_upload)
};
case Value::Type::UtilityBill:
return {
lang(lng_passport_address_bill),
lang(lng_passport_address_bill_upload)
};
case Value::Type::RentalAgreement:
return {
lang(lng_passport_address_agreement),
lang(lng_passport_address_agreement_upload)
};
default: Unexpected("Address type in collectRowInfo.");
}
}
return {
lang(lng_passport_address_title),
lang(lng_passport_address_description)
};
case Scope::Type::Phone:
return {
lang(lng_passport_phone_title),
lang(lng_passport_phone_description)
};
case Scope::Type::Email:
return {
lang(lng_passport_email_title),
lang(lng_passport_email_description)
};
default: Unexpected("Scope type in collectRowInfo.");
}
}
QString PanelController::collectRowReadyString(const Scope &scope) const {
switch (scope.type) {
case Scope::Type::Identity:
case Scope::Type::Address: {
auto list = QStringList();
const auto &fields = scope.fields->data.parsed.fields;
const auto files = [&]() -> const Value* {
for (const auto &files : scope.files) {
if (!files->files.empty()) {
return files;
}
}
return nullptr;
}();
if (files && scope.files.size() > 1) {
list.push_back([&] {
switch (files->type) {
case Value::Type::Passport:
return lang(lng_passport_identity_passport);
case Value::Type::DriverLicense:
return lang(lng_passport_identity_license);
case Value::Type::IdentityCard:
return lang(lng_passport_identity_card);
case Value::Type::BankStatement:
return lang(lng_passport_address_statement);
case Value::Type::UtilityBill:
return lang(lng_passport_address_bill);
case Value::Type::RentalAgreement:
return lang(lng_passport_address_agreement);
default: Unexpected("Files type in collectRowReadyString.");
}
}());
}
if (files
&& (files->files.empty()
|| (scope.selfieRequired && !files->selfie))) {
return QString();
}
const auto scheme = GetDocumentScheme(scope.type);
for (const auto &row : scheme.rows) {
const auto format = row.format;
if (row.type == PanelEditDocument::Scheme::ValueType::Fields) {
const auto i = fields.find(row.key);
if (i == end(fields)) {
return QString();
} else if (row.validate && !row.validate(i->second)) {
return QString();
}
list.push_back(format ? format(i->second) : i->second);
} else if (!files) {
return QString();
} else {
const auto i = files->data.parsed.fields.find(row.key);
if (i == end(files->data.parsed.fields)) {
return QString();
} else if (row.validate && !row.validate(i->second)) {
return QString();
}
list.push_back(i->second);
}
}
return list.join(", ");
} break;
case Scope::Type::Phone:
case Scope::Type::Email: {
const auto format = GetContactScheme(scope.type).format;
const auto &fields = scope.fields->data.parsed.fields;
const auto i = fields.find("value");
return (i != end(fields))
? (format ? format(i->second) : i->second)
: QString();
} break;
}
Unexpected("Scope type in collectRowReadyString.");
}
void PanelController::fillRows(
base::lambda<void(
QString title,
@ -305,32 +484,12 @@ void PanelController::fillRows(
_scopes = ComputeScopes(_form);
}
for (const auto &scope : _scopes) {
switch (scope.type) {
case Scope::Type::Identity:
callback(
lang(lng_passport_identity_title),
lang(lng_passport_identity_description),
false);
break;
case Scope::Type::Address:
callback(
lang(lng_passport_address_title),
lang(lng_passport_address_description),
false);
break;
case Scope::Type::Phone:
callback(
lang(lng_passport_phone_title),
lang(lng_passport_phone_description),
false);
break;
case Scope::Type::Email:
callback(
lang(lng_passport_email_title),
lang(lng_passport_email_description),
false);
break;
}
const auto row = collectRowInfo(scope);
const auto ready = collectRowReadyString(scope);
callback(
row.title,
ready.isEmpty() ? row.description : ready,
!ready.isEmpty());
}
}
@ -427,6 +586,9 @@ rpl::producer<ScanInfo> PanelController::scanUpdated() const {
}
ScanInfo PanelController::collectScanInfo(const EditFile &file) const {
Expects(_editScope != nullptr);
Expects(_editScopeFilesIndex >= 0);
const auto status = [&] {
if (file.fields.accessHash) {
if (file.fields.downloadOffset < 0) {
@ -456,11 +618,10 @@ ScanInfo PanelController::collectScanInfo(const EditFile &file) const {
return formatDownloadText(0, file.fields.size);
}
}();
auto isSelfie = (_editScope != nullptr)
&& (_editScopeFilesIndex >= 0)
&& (file.value == _editScope->files[_editScopeFilesIndex])
&& (_editScope->files[_editScopeFilesIndex]->selfieInEdit.has_value())
&& (&file == &*_editScope->files[_editScopeFilesIndex]->selfieInEdit);
const auto &files = _editScope->files;
auto isSelfie = (file.value == files[_editScopeFilesIndex])
&& (files[_editScopeFilesIndex]->selfieInEdit.has_value())
&& (&file == &*files[_editScopeFilesIndex]->selfieInEdit);
return {
FileKey{ file.fields.id, file.fields.dcId },
status,
@ -508,13 +669,6 @@ int PanelController::findNonEmptyIndex(
if (i != end(files)) {
return (i - begin(files));
}
// Only an uploaded scan counts as non-empty value.
//const auto j = ranges::find_if(files, [](not_null<const Value*> file) {
// return !file->data.parsed.fields.empty();
//});
//if (j != end(files)) {
// return (j - begin(files));
//}
return -1;
}
@ -523,17 +677,17 @@ void PanelController::editScope(int index) {
Expects(_panel != nullptr);
Expects(index >= 0 && index < _scopes.size());
if (_scopes[index].files.size() > 1) {
if (_scopes[index].files.empty()) {
editScope(index, -1);
} else {
const auto filesIndex = findNonEmptyIndex(_scopes[index].files);
if (filesIndex >= 0) {
editScope(index, filesIndex);
} else {
} else if (_scopes[index].files.size() > 1) {
requestScopeFilesType(index);
} else {
editWithUpload(index, 0);
}
} else if (_scopes[index].files.empty()) {
editScope(index, -1);
} else {
editWithUpload(index, 0);
}
}
@ -623,18 +777,19 @@ void PanelController::editScope(int index, int filesIndex) {
switch (_editScope->type) {
case Scope::Type::Identity:
case Scope::Type::Address: {
const auto &files = _editScope->files;
auto result = (_editScopeFilesIndex >= 0)
? object_ptr<PanelEditDocument>(
_panel.get(),
this,
GetDocumentScheme(
_editScope->type,
_editScope->files[_editScopeFilesIndex]->type),
files[_editScopeFilesIndex]->type),
_editScope->fields->data.parsedInEdit,
_editScope->files[_editScopeFilesIndex]->data.parsedInEdit,
valueFiles(*_editScope->files[_editScopeFilesIndex]),
files[_editScopeFilesIndex]->data.parsedInEdit,
valueFiles(*files[_editScopeFilesIndex]),
(_editScope->selfieRequired
? valueSelfie(*_editScope->files[_editScopeFilesIndex])
? valueSelfie(*files[_editScopeFilesIndex])
: nullptr))
: object_ptr<PanelEditDocument>(
_panel.get(),

View file

@ -87,6 +87,10 @@ public:
rpl::lifetime &lifetime();
private:
struct Row {
QString title;
QString description;
};
void ensurePanelCreated();
void editScope(int index, int filesIndex);
@ -100,6 +104,8 @@ private:
void processValueSaveFinished(not_null<const Value*> value);
void processVerificationNeeded(not_null<const Value*> value);
Row collectRowInfo(const Scope &scope) const;
QString collectRowReadyString(const Scope &scope) const;
ScanInfo collectScanInfo(const EditFile &file) const;
QString getDefaultContactValue(Scope::Type type) const;

View file

@ -40,7 +40,8 @@ protected:
void resizeEvent(QResizeEvent *e) override;
private:
object_ptr<BoxContentDivider> _background = object_ptr<BoxContentDivider>(this);
object_ptr<BoxContentDivider> _background
= object_ptr<BoxContentDivider>(this);
};

View file

@ -66,7 +66,12 @@ VerifyBox::VerifyBox(
rpl::producer<QString> call,
rpl::producer<QString> error)
: _title(title) {
setupControls(text, codeLength, submit, std::move(call), std::move(error));
setupControls(
text,
codeLength,
submit,
std::move(call),
std::move(error));
}
void VerifyBox::setupControls(
@ -194,8 +199,8 @@ void PanelEditContact::setupControls(
) | rpl::map([=] {
return lng_passport_use_existing(
lt_existing,
(_scheme.preprocess
? _scheme.preprocess(existing)
(_scheme.format
? _scheme.format(existing)
: existing));
}),
st::passportUploadButton),

View file

@ -36,7 +36,7 @@ public:
base::lambda<QString()> newPlaceholder;
QString aboutNew;
base::lambda<bool(const QString &value)> validate;
base::lambda<QString(const QString &value)> preprocess;
base::lambda<QString(const QString &value)> format;
base::lambda<QString(const QString &value)> postprocess;
};

View file

@ -64,7 +64,7 @@ RequestTypeBox::RequestTypeBox(
void RequestTypeBox::prepare() {
setTitle([=] { return _title; });
addButton(langFactory(lng_passport_upload_document), [=] { _submit(); });
addButton(langFactory(lng_passport_upload_document), _submit);
addButton(langFactory(lng_cancel), [=] { closeBox(); });
setDimensions(st::boxWidth, _height);
}

View file

@ -39,6 +39,7 @@ public:
QString key;
QString label;
base::lambda<bool(const QString &value)> validate;
base::lambda<QString(const QString &value)> format;
};
std::vector<Row> rows;
QString rowsHeader;

View file

@ -90,7 +90,9 @@ int PanelForm::Row::countAvailableWidth(int newWidth) const {
return newWidth
- st::passportRowPadding.left()
- st::passportRowPadding.right()
- (_ready ? st::passportRowReadyIcon : st::passportRowEmptyIcon).width();
- (_ready
? st::passportRowReadyIcon
: st::passportRowEmptyIcon).width();
}
int PanelForm::Row::countAvailableWidth() const {

View file

@ -299,6 +299,9 @@ int RoundButton::contentWidth() const {
if (_numbers) {
result += (result ? _st.numbersSkip : 0) + _numbers->countWidth();
}
if (!_st.icon.empty() && _st.iconPosition.x() < 0) {
result += _st.icon.width() - _st.iconPosition.x();
}
return result;
}
@ -322,11 +325,24 @@ void RoundButton::paintEvent(QPaintEvent *e) {
paintRipple(p, rounded.x(), rounded.y(), ms);
p.setFont(_st.font);
int textLeft = _st.padding.left() + ((width() - innerWidth - _st.padding.left() - _st.padding.right()) / 2);
const auto textTop = _st.padding.top() + _st.textTop;
auto textLeft = _st.padding.left()
+ ((width()
- innerWidth
- _st.padding.left()
- _st.padding.right()) / 2);
if (_fullWidthOverride < 0) {
textLeft = -_fullWidthOverride / 2;
}
int textTop = _st.padding.top() + _st.textTop;
if (!_st.icon.empty() && _st.iconPosition.x() < 0) {
textLeft += _st.icon.width() - _st.iconPosition.x();
}
const auto iconLeft = (_st.iconPosition.x() >= 0)
? _st.iconPosition.x()
: (textLeft + _st.iconPosition.x() - _st.icon.width());
const auto iconTop = (_st.iconPosition.y() >= 0)
? _st.iconPosition.y()
: (textTop + _st.iconPosition.y());
if (!_text.isEmpty()) {
p.setPen((over || down) ? _st.textFgOver : _st.textFg);
p.drawTextLeft(textLeft, textTop, width(), _text);
@ -336,7 +352,9 @@ void RoundButton::paintEvent(QPaintEvent *e) {
p.setPen((over || down) ? _st.numbersTextFgOver : _st.numbersTextFg);
_numbers->paint(p, textLeft, textTop, width());
}
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.top()), width());
if (!_st.icon.empty()) {
_st.icon.paint(p, QPoint(iconLeft, iconTop), width());
}
}
QImage RoundButton::prepareRippleMask() const {

View file

@ -94,6 +94,7 @@ RoundButton {
textTop: pixels;
icon: icon;
iconPosition: point;
font: font;
@ -584,6 +585,8 @@ defaultActiveButton: RoundButton {
textTop: 8px;
iconPosition: point(0px, 0px);
font: semiboldFont;
ripple: RippleAnimation(defaultRippleAnimation) {