confirm_phone_box.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "ui/boxes/confirm_phone_box.h"
  8. #include "core/file_utilities.h"
  9. #include "ui/boxes/confirm_box.h"
  10. #include "ui/widgets/buttons.h"
  11. #include "ui/widgets/labels.h"
  12. #include "ui/text/format_values.h" // Ui::FormatPhone
  13. #include "ui/text/text_utilities.h"
  14. #include "lang/lang_keys.h"
  15. #include "styles/style_layers.h"
  16. #include "styles/style_boxes.h"
  17. namespace Ui {
  18. ConfirmPhoneBox::ConfirmPhoneBox(
  19. QWidget*,
  20. const QString &phone,
  21. int codeLength,
  22. const QString &openUrl,
  23. std::optional<int> timeout)
  24. : _phone(phone)
  25. , _sentCodeLength(codeLength)
  26. , _call([=] { sendCall(); }, [=] { update(); }) {
  27. if (!openUrl.isEmpty()) {
  28. _fragment.create(
  29. this,
  30. tr::lng_intro_fragment_button(),
  31. st::fragmentBoxButton);
  32. _fragment->setClickedCallback([=] { File::OpenUrl(openUrl); });
  33. _fragment->setTextTransform(
  34. Ui::RoundButton::TextTransform::NoTransform);
  35. }
  36. if (timeout) {
  37. _call.setStatus({ Ui::SentCodeCall::State::Waiting, *timeout });
  38. }
  39. }
  40. void ConfirmPhoneBox::sendCall() {
  41. _resendRequests.fire({});
  42. }
  43. void ConfirmPhoneBox::prepare() {
  44. _about.create(
  45. this,
  46. tr::lng_confirm_phone_about(
  47. lt_phone,
  48. rpl::single(Ui::Text::Bold(Ui::FormatPhone(_phone))),
  49. Ui::Text::WithEntities),
  50. st::confirmPhoneAboutLabel);
  51. _code.create(this, st::confirmPhoneCodeField, tr::lng_code_ph());
  52. _code->setAutoSubmit(_sentCodeLength, [=] { sendCode(); });
  53. _code->setChangedCallback([=] { showError(QString()); });
  54. setTitle(tr::lng_confirm_phone_title());
  55. addButton(tr::lng_confirm_phone_send(), [=] { sendCode(); });
  56. addButton(tr::lng_cancel(), [=] { closeBox(); });
  57. setDimensions(
  58. st::boxWidth,
  59. st::usernamePadding.top()
  60. + _code->height()
  61. + st::usernameSkip
  62. + _about->height()
  63. + st::usernameSkip
  64. + (_fragment ? (_fragment->height() + fragmentSkip()) : 0));
  65. _code->submits(
  66. ) | rpl::start_with_next([=] { sendCode(); }, _code->lifetime());
  67. showChildren();
  68. }
  69. void ConfirmPhoneBox::sendCode() {
  70. if (_isWaitingCheck) {
  71. return;
  72. }
  73. const auto code = _code->getDigitsOnly();
  74. if (code.isEmpty()) {
  75. _code->showError();
  76. return;
  77. }
  78. _code->setDisabled(true);
  79. setFocus();
  80. showError(QString());
  81. _checkRequests.fire_copy(code);
  82. _isWaitingCheck = true;
  83. }
  84. void ConfirmPhoneBox::showError(const QString &error) {
  85. _error = error;
  86. if (!_error.isEmpty()) {
  87. _code->showError();
  88. }
  89. update();
  90. }
  91. void ConfirmPhoneBox::paintEvent(QPaintEvent *e) {
  92. BoxContent::paintEvent(e);
  93. auto p = QPainter(this);
  94. p.setFont(st::boxTextFont);
  95. const auto callText = _call.getText();
  96. if (!callText.isEmpty()) {
  97. p.setPen(st::usernameDefaultFg);
  98. const auto callTextRect = QRect(
  99. st::usernamePadding.left(),
  100. _about->y() + _about->height(),
  101. width() - 2 * st::usernamePadding.left(),
  102. st::usernameSkip);
  103. p.drawText(callTextRect, callText, style::al_left);
  104. }
  105. auto errorText = _error;
  106. if (errorText.isEmpty()) {
  107. p.setPen(st::usernameDefaultFg);
  108. errorText = tr::lng_confirm_phone_enter_code(tr::now);
  109. } else {
  110. p.setPen(st::boxTextFgError);
  111. }
  112. const auto errorTextRect = QRect(
  113. st::usernamePadding.left(),
  114. _code->y() + _code->height(),
  115. width() - 2 * st::usernamePadding.left(),
  116. st::usernameSkip);
  117. p.drawText(errorTextRect, errorText, style::al_left);
  118. }
  119. void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
  120. BoxContent::resizeEvent(e);
  121. _code->resize(
  122. width() - st::usernamePadding.left() - st::usernamePadding.right(),
  123. _code->height());
  124. _code->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
  125. if (_fragment) {
  126. _fragment->setFullWidth(_code->width());
  127. _fragment->moveToLeft(
  128. (width() - _fragment->width()) / 2,
  129. _code->y() + _code->height() + st::usernameSkip);
  130. }
  131. const auto aboutTop = _fragment
  132. ? (_fragment->y() + _fragment->height() + fragmentSkip())
  133. : (_code->y() + _code->height() + st::usernameSkip);
  134. _about->moveToLeft(st::usernamePadding.left(), aboutTop);
  135. }
  136. void ConfirmPhoneBox::setInnerFocus() {
  137. _code->setFocusFast();
  138. }
  139. int ConfirmPhoneBox::fragmentSkip() const {
  140. return st::usernamePadding.bottom();
  141. }
  142. rpl::producer<QString> ConfirmPhoneBox::checkRequests() const {
  143. return _checkRequests.events();
  144. }
  145. rpl::producer<> ConfirmPhoneBox::resendRequests() const {
  146. return _resendRequests.events();
  147. }
  148. void ConfirmPhoneBox::callDone() {
  149. _call.callDone();
  150. }
  151. void ConfirmPhoneBox::showServerError(const QString &text) {
  152. _isWaitingCheck = false;
  153. _code->setDisabled(false);
  154. _code->setFocus();
  155. showError(text);
  156. }
  157. QString ConfirmPhoneBox::getPhone() const {
  158. return _phone;
  159. }
  160. } // namespace Ui