282 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| 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
 | |
| */
 | |
| #include "payments/ui/payments_edit_information.h"
 | |
| 
 | |
| #include "payments/ui/payments_panel_delegate.h"
 | |
| #include "payments/ui/payments_field.h"
 | |
| #include "ui/widgets/scroll_area.h"
 | |
| #include "ui/widgets/buttons.h"
 | |
| #include "ui/widgets/labels.h"
 | |
| #include "ui/widgets/checkbox.h"
 | |
| #include "ui/wrap/vertical_layout.h"
 | |
| #include "ui/wrap/fade_wrap.h"
 | |
| #include "lang/lang_keys.h"
 | |
| #include "styles/style_payments.h"
 | |
| #include "styles/style_passport.h"
 | |
| 
 | |
| namespace Payments::Ui {
 | |
| namespace {
 | |
| 
 | |
| constexpr auto kMaxStreetSize = 64;
 | |
| constexpr auto kMaxPostcodeSize = 10;
 | |
| constexpr auto kMaxNameSize = 64;
 | |
| constexpr auto kMaxEmailSize = 128;
 | |
| constexpr auto kMaxPhoneSize = 16;
 | |
| constexpr auto kMinCitySize = 2;
 | |
| constexpr auto kMaxCitySize = 64;
 | |
| 
 | |
| } // namespace
 | |
| 
 | |
| EditInformation::EditInformation(
 | |
| 	QWidget *parent,
 | |
| 	const Invoice &invoice,
 | |
| 	const RequestedInformation ¤t,
 | |
| 	InformationField field,
 | |
| 	not_null<PanelDelegate*> delegate)
 | |
| : _delegate(delegate)
 | |
| , _invoice(invoice)
 | |
| , _information(current)
 | |
| , _scroll(this, st::passportPanelScroll)
 | |
| , _topShadow(this)
 | |
| , _bottomShadow(this)
 | |
| , _submit(
 | |
| 	this,
 | |
| 	tr::lng_settings_save(),
 | |
| 	st::paymentsPanelButton)
 | |
| , _cancel(
 | |
| 		this,
 | |
| 		tr::lng_cancel(),
 | |
| 		st::paymentsPanelButton) {
 | |
| 	setupControls();
 | |
| }
 | |
| 
 | |
| EditInformation::~EditInformation() = default;
 | |
| 
 | |
| void EditInformation::setFocus(InformationField field) {
 | |
| 	_focusField = field;
 | |
| 	if (const auto control = lookupField(field)) {
 | |
| 		_scroll->ensureWidgetVisible(control->widget());
 | |
| 		control->setFocus();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void EditInformation::setFocusFast(InformationField field) {
 | |
| 	_focusField = field;
 | |
| 	if (const auto control = lookupField(field)) {
 | |
| 		_scroll->ensureWidgetVisible(control->widget());
 | |
| 		control->setFocusFast();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void EditInformation::showError(InformationField field) {
 | |
| 	if (const auto control = lookupField(field)) {
 | |
| 		_scroll->ensureWidgetVisible(control->widget());
 | |
| 		control->showError();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void EditInformation::setupControls() {
 | |
| 	const auto inner = setupContent();
 | |
| 
 | |
| 	_submit->addClickHandler([=] {
 | |
| 		_delegate->panelValidateInformation(collect());
 | |
| 	});
 | |
| 	_cancel->addClickHandler([=] {
 | |
| 		_delegate->panelCancelEdit();
 | |
| 	});
 | |
| 
 | |
| 	using namespace rpl::mappers;
 | |
| 
 | |
| 	_topShadow->toggleOn(
 | |
| 		_scroll->scrollTopValue() | rpl::map(_1 > 0));
 | |
| 	_bottomShadow->toggleOn(rpl::combine(
 | |
| 		_scroll->scrollTopValue(),
 | |
| 		_scroll->heightValue(),
 | |
| 		inner->heightValue(),
 | |
| 		_1 + _2 < _3));
 | |
| }
 | |
| 
 | |
| not_null<RpWidget*> EditInformation::setupContent() {
 | |
| 	const auto inner = _scroll->setOwnedWidget(
 | |
| 		object_ptr<VerticalLayout>(this));
 | |
| 
 | |
| 	_scroll->widthValue(
 | |
| 	) | rpl::start_with_next([=](int width) {
 | |
| 		inner->resizeToWidth(width);
 | |
| 	}, inner->lifetime());
 | |
| 
 | |
| 	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) {
 | |
| 		_street1 = add({
 | |
| 			.placeholder = tr::lng_payments_address_street1(),
 | |
| 			.value = _information.shippingAddress.address1,
 | |
| 			.validator = RangeLengthValidator(1, kMaxStreetSize),
 | |
| 		});
 | |
| 		_street2 = add({
 | |
| 			.placeholder = tr::lng_payments_address_street2(),
 | |
| 			.value = _information.shippingAddress.address2,
 | |
| 			.validator = MaxLengthValidator(kMaxStreetSize),
 | |
| 		});
 | |
| 		_city = add({
 | |
| 			.placeholder = tr::lng_payments_address_city(),
 | |
| 			.value = _information.shippingAddress.city,
 | |
| 			.validator = RangeLengthValidator(kMinCitySize, kMaxCitySize),
 | |
| 		});
 | |
| 		_state = add({
 | |
| 			.placeholder = tr::lng_payments_address_state(),
 | |
| 			.value = _information.shippingAddress.state,
 | |
| 		});
 | |
| 		_country = add({
 | |
| 			.type = FieldType::Country,
 | |
| 			.placeholder = tr::lng_payments_address_country(),
 | |
| 			.value = _information.shippingAddress.countryIso2,
 | |
| 			.validator = RequiredFinishedValidator(),
 | |
| 			.showBox = showBox,
 | |
| 			.defaultCountry = _information.defaultCountry,
 | |
| 		});
 | |
| 		_postcode = add({
 | |
| 			.placeholder = tr::lng_payments_address_postcode(),
 | |
| 			.value = _information.shippingAddress.postcode,
 | |
| 			.validator = RangeLengthValidator(1, kMaxPostcodeSize),
 | |
| 		});
 | |
| 	}
 | |
| 	if (_invoice.isNameRequested) {
 | |
| 		_name = add({
 | |
| 			.placeholder = tr::lng_payments_info_name(),
 | |
| 			.value = _information.name,
 | |
| 			.validator = RangeLengthValidator(1, kMaxNameSize),
 | |
| 		});
 | |
| 	}
 | |
| 	if (_invoice.isEmailRequested) {
 | |
| 		_email = add({
 | |
| 			.type = FieldType::Email,
 | |
| 			.placeholder = tr::lng_payments_info_email(),
 | |
| 			.value = _information.email,
 | |
| 			.validator = RangeLengthValidator(1, kMaxEmailSize),
 | |
| 		});
 | |
| 	}
 | |
| 	if (_invoice.isPhoneRequested) {
 | |
| 		_phone = add({
 | |
| 			.type = FieldType::Phone,
 | |
| 			.placeholder = tr::lng_payments_info_phone(),
 | |
| 			.value = _information.phone,
 | |
| 			.validator = RangeLengthValidator(1, kMaxPhoneSize),
 | |
| 			.defaultPhone = _information.defaultPhone,
 | |
| 		});
 | |
| 	}
 | |
| 	const auto emailToProvider = _invoice.isEmailRequested
 | |
| 		&& _invoice.emailSentToProvider;
 | |
| 	const auto phoneToProvider = _invoice.isPhoneRequested
 | |
| 		&& _invoice.phoneSentToProvider;
 | |
| 	if (emailToProvider || phoneToProvider) {
 | |
| 		inner->add(
 | |
| 			object_ptr<Ui::FlatLabel>(
 | |
| 				inner,
 | |
| 				((emailToProvider && phoneToProvider)
 | |
| 					? tr::lng_payments_to_provider_phone_email
 | |
| 					: emailToProvider
 | |
| 					? tr::lng_payments_to_provider_email
 | |
| 					: tr::lng_payments_to_provider_phone)(
 | |
| 						lt_provider,
 | |
| 						rpl::single(_invoice.provider)),
 | |
| 				st::paymentsToProviderLabel),
 | |
| 			st::paymentsToProviderPadding);
 | |
| 	}
 | |
| 	_save = inner->add(
 | |
| 		object_ptr<Ui::Checkbox>(
 | |
| 			inner,
 | |
| 			tr::lng_payments_save_information(tr::now),
 | |
| 			true),
 | |
| 		st::paymentsSaveCheckboxPadding);
 | |
| 
 | |
| 	if (last) {
 | |
| 		last->submitted(
 | |
| 		) | rpl::start_with_next([=] {
 | |
| 			_delegate->panelValidateInformation(collect());
 | |
| 		}, lifetime());
 | |
| 	}
 | |
| 
 | |
| 	return inner;
 | |
| }
 | |
| 
 | |
| void EditInformation::resizeEvent(QResizeEvent *e) {
 | |
| 	updateControlsGeometry();
 | |
| }
 | |
| 
 | |
| void EditInformation::focusInEvent(QFocusEvent *e) {
 | |
| 	if (const auto control = lookupField(_focusField)) {
 | |
| 		control->setFocus();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void EditInformation::updateControlsGeometry() {
 | |
| 	const auto &padding = st::paymentsPanelPadding;
 | |
| 	const auto buttonsHeight = padding.top()
 | |
| 		+ _cancel->height()
 | |
| 		+ padding.bottom();
 | |
| 	const auto buttonsTop = height() - buttonsHeight;
 | |
| 	_scroll->setGeometry(0, 0, width(), buttonsTop);
 | |
| 	_topShadow->resizeToWidth(width());
 | |
| 	_topShadow->moveToLeft(0, 0);
 | |
| 	_bottomShadow->resizeToWidth(width());
 | |
| 	_bottomShadow->moveToLeft(0, buttonsTop - st::lineWidth);
 | |
| 	auto right = padding.right();
 | |
| 	_submit->moveToRight(right, buttonsTop + padding.top());
 | |
| 	right += _submit->width() + padding.left();
 | |
| 	_cancel->moveToRight(right, buttonsTop + padding.top());
 | |
| 
 | |
| 	_scroll->updateBars();
 | |
| }
 | |
| 
 | |
| auto EditInformation::lookupField(InformationField field) const -> Field* {
 | |
| 	switch (field) {
 | |
| 	case InformationField::ShippingStreet: return _street1.get();
 | |
| 	case InformationField::ShippingCity: return _city.get();
 | |
| 	case InformationField::ShippingState: return _state.get();
 | |
| 	case InformationField::ShippingCountry: return _country.get();
 | |
| 	case InformationField::ShippingPostcode: return _postcode.get();
 | |
| 	case InformationField::Name: return _name.get();
 | |
| 	case InformationField::Email: return _email.get();
 | |
| 	case InformationField::Phone: return _phone.get();
 | |
| 	}
 | |
| 	Unexpected("Unknown field in EditInformation::lookupField.");
 | |
| }
 | |
| 
 | |
| RequestedInformation EditInformation::collect() const {
 | |
| 	return {
 | |
| 		.defaultPhone = _information.defaultPhone,
 | |
| 		.defaultCountry = _information.defaultCountry,
 | |
| 		.save = _save->checked(),
 | |
| 		.name = _name ? _name->value() : QString(),
 | |
| 		.phone = _phone ? _phone->value() : QString(),
 | |
| 		.email = _email ? _email->value() : QString(),
 | |
| 		.shippingAddress = {
 | |
| 			.address1 = _street1 ? _street1->value() : QString(),
 | |
| 			.address2 = _street2 ? _street2->value() : QString(),
 | |
| 			.city = _city ? _city->value() : QString(),
 | |
| 			.state = _state ? _state->value() : QString(),
 | |
| 			.countryIso2 = _country ? _country->value() : QString(),
 | |
| 			.postcode = _postcode ? _postcode->value() : QString(),
 | |
| 		},
 | |
| 	};
 | |
| }
 | |
| 
 | |
| } // namespace Payments::Ui
 | 
