Always jump to next field in payments.

This commit is contained in:
John Preston 2021-04-01 19:06:48 +04:00
parent 491ec2db7f
commit bdffdea358
4 changed files with 82 additions and 16 deletions

View file

@ -276,8 +276,18 @@ not_null<RpWidget*> EditCard::setupContent() {
const auto showBox = [=](object_ptr<BoxContent> box) {
_delegate->panelShowBox(std::move(box));
};
auto last = (Field*)nullptr;
const auto make = [&](QWidget *parent, FieldConfig &&config) {
auto result = std::make_unique<Field>(parent, std::move(config));
if (last) {
last->setNextField(result.get());
result->setPreviousField(last);
}
last = result.get();
return result;
};
const auto add = [&](FieldConfig &&config) {
auto result = std::make_unique<Field>(inner, std::move(config));
auto result = make(inner, std::move(config));
inner->add(result->ownedWidget(), st::paymentsFieldPadding);
return result;
};
@ -291,12 +301,12 @@ not_null<RpWidget*> EditCard::setupContent() {
inner,
_number->widget()->height()),
st::paymentsFieldPadding);
_expire = std::make_unique<Field>(container, FieldConfig{
_expire = make(container, {
.type = FieldType::CardExpireDate,
.placeholder = rpl::single(u"MM / YY"_q),
.validator = ExpireDateValidator(),
});
_cvc = std::make_unique<Field>(container, FieldConfig{
_cvc = make(container, {
.type = FieldType::CardCVC,
.placeholder = rpl::single(u"CVC"_q),
.validator = CvcValidator([=] { return _number->value(); }),
@ -319,15 +329,6 @@ not_null<RpWidget*> EditCard::setupContent() {
});
}
_number->setNextField(_expire.get());
_expire->setPreviousField(_number.get());
_expire->setNextField(_cvc.get());
_cvc->setPreviousField(_expire.get());
if (_name) {
_cvc->setNextField(_name.get());
_name->setPreviousField(_cvc.get());
}
if (_native.needCountry || _native.needZip) {
inner->add(
object_ptr<Ui::FlatLabel>(
@ -366,6 +367,12 @@ not_null<RpWidget*> EditCard::setupContent() {
false),
st::paymentsSaveCheckboxPadding);
}
last->submitted(
) | rpl::start_with_next([=] {
_delegate->panelValidateCard(collect(), _save && _save->checked());
}, lifetime());
return inner;
}

View file

@ -113,9 +113,15 @@ not_null<RpWidget*> EditInformation::setupContent() {
const auto showBox = [=](object_ptr<BoxContent> box) {
_delegate->panelShowBox(std::move(box));
};
auto last = (Field*)nullptr;
const auto add = [&](FieldConfig &&config) {
auto result = std::make_unique<Field>(inner, std::move(config));
inner->add(result->ownedWidget(), st::paymentsFieldPadding);
if (last) {
last->setNextField(result.get());
result->setPreviousField(last);
}
last = result.get();
return result;
};
if (_invoice.isShippingAddressRequested) {
@ -200,6 +206,14 @@ not_null<RpWidget*> EditInformation::setupContent() {
tr::lng_payments_save_information(tr::now),
true),
st::paymentsSaveCheckboxPadding);
if (last) {
last->submitted(
) | rpl::start_with_next([=] {
_delegate->panelValidateInformation(collect());
}, lifetime());
}
return inner;
}

View file

@ -430,6 +430,7 @@ Field::Field(QWidget *parent, FieldConfig &&config)
setupValidator(MoneyValidator(LookupCurrencyRule(config.currency)));
}
setupFrontBackspace();
setupSubmit();
}
RpWidget *Field::widget() const {
@ -455,6 +456,10 @@ rpl::producer<> Field::finished() const {
return _finished.events();
}
rpl::producer<> Field::submitted() const {
return _submitted.events();
}
void Field::setupMaskedGeometry() {
Expects(_masked != nullptr);
@ -492,6 +497,13 @@ void Field::setupCountry() {
_masked->setText(Data::CountryNameByISO2(iso2));
_masked->hideError();
raw->closeBox();
if (!iso2.isEmpty()) {
if (_nextField) {
_nextField->activate();
} else {
_submitted.fire({});
}
}
}, _masked->lifetime());
raw->boxClosing() | rpl::start_with_next([=] {
setFocus();
@ -563,6 +575,8 @@ void Field::setupValidator(Fn<ValidateResult(ValidateRequest)> validator) {
.nowValue = now.value,
.nowPosition = now.position,
});
_valid = result.finished || !result.invalid;
const auto changed = (result.value != now.value);
if (changed) {
setText(result.value);
@ -609,7 +623,26 @@ void Field::setupFrontBackspace() {
}
}
void Field::setupSubmit() {
const auto submitted = [=] {
if (!_valid) {
showError();
} else if (_nextField) {
_nextField->activate();
} else {
_submitted.fire({});
}
};
if (_masked) {
QObject::connect(_masked, &MaskedInputField::submitted, submitted);
} else {
QObject::connect(_input, &InputField::submitted, submitted);
}
}
void Field::setNextField(not_null<Field*> field) {
_nextField = field;
finished() | rpl::start_with_next([=] {
field->setFocus();
}, _masked ? _masked->lifetime() : _input->lifetime());
@ -622,16 +655,22 @@ void Field::setPreviousField(not_null<Field*> field) {
}, _masked ? _masked->lifetime() : _input->lifetime());
}
void Field::setFocus() {
if (_config.type == FieldType::Country) {
_wrap->setFocus();
} else if (_input) {
void Field::activate() {
if (_input) {
_input->setFocus();
} else {
_masked->setFocus();
}
}
void Field::setFocus() {
if (_config.type == FieldType::Country) {
_wrap->setFocus();
} else {
activate();
}
}
void Field::setFocusFast() {
if (_config.type == FieldType::Country) {
setFocus();

View file

@ -98,7 +98,9 @@ public:
[[nodiscard]] QString value() const;
[[nodiscard]] rpl::producer<> frontBackspace() const;
[[nodiscard]] rpl::producer<> finished() const;
[[nodiscard]] rpl::producer<> submitted() const;
void activate();
void setFocus();
void setFocusFast();
void showError();
@ -120,17 +122,21 @@ private:
void setupCountry();
void setupValidator(Fn<ValidateResult(ValidateRequest)> validator);
void setupFrontBackspace();
void setupSubmit();
const FieldConfig _config;
const base::unique_qptr<RpWidget> _wrap;
rpl::event_stream<> _frontBackspace;
rpl::event_stream<> _finished;
rpl::event_stream<> _submitted;
rpl::event_stream<> _textPossiblyChanged; // Must be above _masked.
InputField *_input = nullptr;
MaskedInputField *_masked = nullptr;
Field *_nextField = nullptr;
QString _countryIso2;
State _was;
bool _validating = false;
bool _valid = true;
};