tdesktop/Telegram/SourceFiles/payments/ui/payments_field.h

144 lines
3.3 KiB
C
Raw Normal View History

/*
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
*/
#pragma once
#include "base/object_ptr.h"
#include "base/unique_qptr.h"
namespace Ui {
class RpWidget;
class InputField;
class MaskedInputField;
2021-03-26 17:09:09 +00:00
class BoxContent;
} // namespace Ui
namespace Payments::Ui {
using namespace ::Ui;
enum class FieldType {
Text,
CardNumber,
CardExpireDate,
CardCVC,
Country,
Phone,
Email,
2021-04-01 09:27:39 +00:00
Money,
};
struct FieldValidateRequest {
QString wasValue;
int wasPosition = 0;
int wasAnchor = 0;
QString nowValue;
int nowPosition = 0;
};
struct FieldValidateResult {
QString value;
int position = 0;
bool invalid = false;
bool finished = false;
};
2021-03-31 17:30:42 +00:00
[[nodiscard]] inline auto RangeLengthValidator(int minLength, int maxLength) {
return [=](FieldValidateRequest request) {
return FieldValidateResult{
.value = request.nowValue,
.position = request.nowPosition,
.invalid = (request.nowValue.size() < minLength
|| request.nowValue.size() > maxLength),
};
};
}
2021-03-31 17:30:42 +00:00
[[nodiscard]] inline auto MaxLengthValidator(int maxLength) {
return RangeLengthValidator(0, maxLength);
}
2021-03-31 17:30:42 +00:00
[[nodiscard]] inline auto RequiredValidator() {
return RangeLengthValidator(1, std::numeric_limits<int>::max());
}
2021-03-31 17:30:42 +00:00
[[nodiscard]] inline auto RequiredFinishedValidator() {
return [=](FieldValidateRequest request) {
return FieldValidateResult{
.value = request.nowValue,
.position = request.nowPosition,
.invalid = request.nowValue.isEmpty(),
.finished = !request.nowValue.isEmpty(),
};
};
}
struct FieldConfig {
FieldType type = FieldType::Text;
rpl::producer<QString> placeholder;
QString value;
Fn<FieldValidateResult(FieldValidateRequest)> validator;
2021-03-26 17:09:09 +00:00
Fn<void(object_ptr<BoxContent>)> showBox;
2021-04-01 09:27:39 +00:00
QString currency;
QString defaultPhone;
2021-03-26 17:09:09 +00:00
QString defaultCountry;
};
class Field final {
public:
Field(QWidget *parent, FieldConfig &&config);
[[nodiscard]] RpWidget *widget() const;
[[nodiscard]] object_ptr<RpWidget> ownedWidget() const;
[[nodiscard]] QString value() const;
[[nodiscard]] rpl::producer<> frontBackspace() const;
[[nodiscard]] rpl::producer<> finished() const;
2021-04-01 15:06:48 +00:00
[[nodiscard]] rpl::producer<> submitted() const;
2021-04-01 15:06:48 +00:00
void activate();
void setFocus();
void setFocusFast();
void showError();
void showErrorNoFocus();
void setNextField(not_null<Field*> field);
void setPreviousField(not_null<Field*> field);
private:
struct State {
QString value;
int position = 0;
int anchor = 0;
};
using ValidateRequest = FieldValidateRequest;
using ValidateResult = FieldValidateResult;
2021-03-26 17:09:09 +00:00
void setupMaskedGeometry();
void setupCountry();
void setupValidator(Fn<ValidateResult(ValidateRequest)> validator);
void setupFrontBackspace();
2021-04-01 15:06:48 +00:00
void setupSubmit();
2021-03-26 17:09:09 +00:00
const FieldConfig _config;
const base::unique_qptr<RpWidget> _wrap;
rpl::event_stream<> _frontBackspace;
rpl::event_stream<> _finished;
2021-04-01 15:06:48 +00:00
rpl::event_stream<> _submitted;
2021-04-01 09:27:39 +00:00
rpl::event_stream<> _textPossiblyChanged; // Must be above _masked.
InputField *_input = nullptr;
MaskedInputField *_masked = nullptr;
2021-04-01 15:06:48 +00:00
Field *_nextField = nullptr;
2021-03-26 17:09:09 +00:00
QString _countryIso2;
State _was;
bool _validating = false;
2021-04-01 15:06:48 +00:00
bool _valid = true;
};
} // namespace Payments::Ui