mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Improved style of input field for login code.
This commit is contained in:
parent
9ef0e5cf83
commit
ac8117a6d8
6 changed files with 389 additions and 93 deletions
|
@ -115,6 +115,12 @@ introPassword: introCountry;
|
|||
introPasswordTop: 74px;
|
||||
introPasswordHintTop: 151px;
|
||||
|
||||
introCodeDigitFont: font(20px);
|
||||
introCodeDigitHeight: 50px;
|
||||
introCodeDigitBorderWidth: 4px;
|
||||
introCodeDigitSkip: 10px;
|
||||
introCodeDigitAnimatioDuration: 120;
|
||||
|
||||
introPasswordHint: FlatLabel(introDescription) {
|
||||
textFg: windowFg;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "intro/intro_code.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "intro/intro_code_input.h"
|
||||
#include "intro/intro_signup.h"
|
||||
#include "intro/intro_password_check.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
|
@ -26,67 +27,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Intro {
|
||||
namespace details {
|
||||
|
||||
CodeInput::CodeInput(
|
||||
QWidget *parent,
|
||||
const style::InputField &st,
|
||||
rpl::producer<QString> placeholder)
|
||||
: Ui::MaskedInputField(parent, st, std::move(placeholder)) {
|
||||
}
|
||||
|
||||
void CodeInput::setDigitsCountMax(int digitsCount) {
|
||||
_digitsCountMax = digitsCount;
|
||||
}
|
||||
|
||||
void CodeInput::correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) {
|
||||
QString newText;
|
||||
int oldPos(nowCursor), newPos(-1), oldLen(now.length()), digitCount = 0;
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (now[i].isDigit()) {
|
||||
++digitCount;
|
||||
}
|
||||
}
|
||||
accumulate_min(digitCount, _digitsCountMax);
|
||||
auto strict = (digitCount == _digitsCountMax);
|
||||
|
||||
newText.reserve(oldLen);
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
QChar ch(now[i]);
|
||||
if (ch.isDigit()) {
|
||||
if (!digitCount--) {
|
||||
break;
|
||||
}
|
||||
newText += ch;
|
||||
if (strict && !digitCount) {
|
||||
break;
|
||||
}
|
||||
} else if (ch == '-') {
|
||||
newText += ch;
|
||||
}
|
||||
if (i == oldPos) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
}
|
||||
if (newPos < 0 || newPos > newText.size()) {
|
||||
newPos = newText.size();
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(now);
|
||||
startPlaceholderAnimation();
|
||||
}
|
||||
if (newPos != nowCursor) {
|
||||
nowCursor = newPos;
|
||||
setCursorPosition(nowCursor);
|
||||
}
|
||||
}
|
||||
|
||||
CodeWidget::CodeWidget(
|
||||
QWidget *parent,
|
||||
not_null<Main::Account*> account,
|
||||
not_null<Data*> data)
|
||||
: Step(parent, account, data)
|
||||
, _noTelegramCode(this, tr::lng_code_no_telegram(tr::now), st::introLink)
|
||||
, _code(this, st::introCode, tr::lng_code_ph())
|
||||
, _code(this)
|
||||
, _callTimer([=] { sendCall(); })
|
||||
, _callStatus(getData()->callStatus)
|
||||
, _callTimeout(getData()->callTimeout)
|
||||
|
@ -97,7 +44,6 @@ CodeWidget::CodeWidget(
|
|||
refreshLang();
|
||||
}, lifetime());
|
||||
|
||||
connect(_code, &CodeInput::changed, [=] { codeChanged(); });
|
||||
_noTelegramCode->addClickHandler([=] { noTelegramCode(); });
|
||||
|
||||
_code->setDigitsCountMax(getData()->codeLength);
|
||||
|
@ -111,9 +57,15 @@ CodeWidget::CodeWidget(
|
|||
}) | rpl::flatten_latest());
|
||||
|
||||
account->setHandleLoginCode([=](const QString &code) {
|
||||
_code->setText(code);
|
||||
submitCode();
|
||||
_code->setCode(code);
|
||||
_code->requestCode();
|
||||
});
|
||||
|
||||
_code->codeCollected(
|
||||
) | rpl::start_with_next([=](const QString &code) {
|
||||
hideError();
|
||||
submitCode(code);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void CodeWidget::refreshLang() {
|
||||
|
@ -210,7 +162,7 @@ void CodeWidget::showCodeError(rpl::producer<QString> text) {
|
|||
}
|
||||
|
||||
void CodeWidget::setInnerFocus() {
|
||||
_code->setFocusFast();
|
||||
_code->setFocus();
|
||||
}
|
||||
|
||||
void CodeWidget::activate() {
|
||||
|
@ -233,7 +185,7 @@ void CodeWidget::finished() {
|
|||
|
||||
cancelled();
|
||||
_sentCode.clear();
|
||||
_code->setText(QString());
|
||||
_code->clear();
|
||||
}
|
||||
|
||||
void CodeWidget::cancelled() {
|
||||
|
@ -267,6 +219,7 @@ void CodeWidget::checkRequest() {
|
|||
|
||||
void CodeWidget::codeSubmitDone(const MTPauth_Authorization &result) {
|
||||
stopCheck();
|
||||
_code->setEnabled(true);
|
||||
_sentRequest = 0;
|
||||
finish(result);
|
||||
}
|
||||
|
@ -274,12 +227,16 @@ void CodeWidget::codeSubmitDone(const MTPauth_Authorization &result) {
|
|||
void CodeWidget::codeSubmitFail(const MTP::Error &error) {
|
||||
if (MTP::IsFloodError(error)) {
|
||||
stopCheck();
|
||||
_code->setEnabled(true);
|
||||
_code->setFocus();
|
||||
_sentRequest = 0;
|
||||
showCodeError(tr::lng_flood_error());
|
||||
return;
|
||||
}
|
||||
|
||||
stopCheck();
|
||||
_code->setEnabled(true);
|
||||
_code->setFocus();
|
||||
_sentRequest = 0;
|
||||
auto &err = error.type();
|
||||
if (err == u"PHONE_NUMBER_INVALID"_q
|
||||
|
@ -303,11 +260,6 @@ void CodeWidget::codeSubmitFail(const MTP::Error &error) {
|
|||
}
|
||||
}
|
||||
|
||||
void CodeWidget::codeChanged() {
|
||||
hideError();
|
||||
submitCode();
|
||||
}
|
||||
|
||||
void CodeWidget::sendCall() {
|
||||
if (_callStatus == CallStatus::Waiting) {
|
||||
if (--_callTimeout <= 0) {
|
||||
|
@ -370,19 +322,13 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) {
|
|||
|
||||
void CodeWidget::submit() {
|
||||
if (getData()->codeByFragmentUrl.isEmpty()) {
|
||||
submitCode();
|
||||
_code->requestCode();
|
||||
} else {
|
||||
File::OpenUrl(getData()->codeByFragmentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeWidget::submitCode() {
|
||||
const auto text = QString(
|
||||
_code->getLastText()
|
||||
).remove(
|
||||
TextUtilities::RegExpDigitsExclude()
|
||||
).mid(0, getData()->codeLength);
|
||||
|
||||
void CodeWidget::submitCode(const QString &text) {
|
||||
if (_sentRequest
|
||||
|| _sentCode == text
|
||||
|| text.size() != getData()->codeLength) {
|
||||
|
@ -394,6 +340,7 @@ void CodeWidget::submitCode() {
|
|||
_checkRequestTimer.callEach(1000);
|
||||
|
||||
_sentCode = text;
|
||||
_code->setEnabled(false);
|
||||
getData()->pwdState = Core::CloudPasswordState();
|
||||
_sentRequest = api().request(MTPauth_SignIn(
|
||||
MTP_flags(MTPauth_SignIn::Flag::f_phone_code),
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Ui {
|
|||
class RoundButton;
|
||||
class LinkButton;
|
||||
class FlatLabel;
|
||||
class CodeInput;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Intro {
|
||||
|
@ -23,23 +24,6 @@ namespace details {
|
|||
|
||||
enum class CallStatus;
|
||||
|
||||
class CodeInput final : public Ui::MaskedInputField {
|
||||
public:
|
||||
CodeInput(
|
||||
QWidget *parent,
|
||||
const style::InputField &st,
|
||||
rpl::producer<QString> placeholder);
|
||||
|
||||
void setDigitsCountMax(int digitsCount);
|
||||
|
||||
protected:
|
||||
void correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) override;
|
||||
|
||||
private:
|
||||
int _digitsCountMax = 5;
|
||||
|
||||
};
|
||||
|
||||
class CodeWidget final : public Step {
|
||||
public:
|
||||
CodeWidget(
|
||||
|
@ -65,7 +49,6 @@ protected:
|
|||
|
||||
private:
|
||||
void noTelegramCode();
|
||||
void codeChanged();
|
||||
void sendCall();
|
||||
void checkRequest();
|
||||
|
||||
|
@ -85,14 +68,14 @@ private:
|
|||
void noTelegramCodeDone(const MTPauth_SentCode &result);
|
||||
void noTelegramCodeFail(const MTP::Error &result);
|
||||
|
||||
void submitCode();
|
||||
void submitCode(const QString &text);
|
||||
|
||||
void stopCheck();
|
||||
|
||||
object_ptr<Ui::LinkButton> _noTelegramCode;
|
||||
mtpRequestId _noTelegramCodeRequestId = 0;
|
||||
|
||||
object_ptr<CodeInput> _code;
|
||||
object_ptr<Ui::CodeInput> _code;
|
||||
QString _sentCode;
|
||||
mtpRequestId _sentRequest = 0;
|
||||
|
||||
|
|
308
Telegram/SourceFiles/intro/intro_code_input.cpp
Normal file
308
Telegram/SourceFiles/intro/intro_code_input.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "intro/intro_code_input.h"
|
||||
|
||||
#include "ui/abstract_button.h"
|
||||
#include "ui/effects/shake_animation.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/text/text_entity.h"
|
||||
#include "styles/style_intro.h"
|
||||
#include "styles/style_layers.h" // boxRadius
|
||||
|
||||
#include <QtCore/QRegularExpression>
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
constexpr auto kDigitNone = int(-1);
|
||||
|
||||
[[nodiscard]] int Circular(int left, int right) {
|
||||
return ((left % right) + right) % right;
|
||||
}
|
||||
|
||||
class Shaker final {
|
||||
public:
|
||||
explicit Shaker(not_null<Ui::RpWidget*> widget);
|
||||
|
||||
void shake();
|
||||
|
||||
private:
|
||||
const not_null<Ui::RpWidget*> _widget;
|
||||
Ui::Animations::Simple _animation;
|
||||
|
||||
};
|
||||
|
||||
Shaker::Shaker(not_null<Ui::RpWidget*> widget)
|
||||
: _widget(widget) {
|
||||
}
|
||||
|
||||
void Shaker::shake() {
|
||||
if (_animation.animating()) {
|
||||
return;
|
||||
}
|
||||
_animation.start(DefaultShakeCallback([=, x = _widget->x()](int shift) {
|
||||
_widget->moveToLeft(x + shift, _widget->y());
|
||||
}), 0., 1., st::shakeDuration);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class CodeDigit final : public Ui::AbstractButton {
|
||||
public:
|
||||
explicit CodeDigit(not_null<Ui::RpWidget*> widget);
|
||||
|
||||
void setDigit(int digit);
|
||||
[[nodiscard]] int digit() const;
|
||||
|
||||
void setBorderColor(const QBrush &brush);
|
||||
void shake();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
Shaker _shaker;
|
||||
Ui::Animations::Simple _animation;
|
||||
int _dataDigit = kDigitNone;
|
||||
int _viewDigit = kDigitNone;
|
||||
|
||||
QPen _borderPen;
|
||||
|
||||
};
|
||||
|
||||
CodeDigit::CodeDigit(not_null<Ui::RpWidget*> widget)
|
||||
: Ui::AbstractButton(widget)
|
||||
, _shaker(this) {
|
||||
setBorderColor(st::windowBgRipple);
|
||||
}
|
||||
|
||||
void CodeDigit::setDigit(int digit) {
|
||||
if ((_dataDigit == digit) && _animation.animating()) {
|
||||
return;
|
||||
}
|
||||
_dataDigit = digit;
|
||||
if (_viewDigit != digit) {
|
||||
constexpr auto kDuration = st::introCodeDigitAnimatioDuration;
|
||||
_animation.stop();
|
||||
if (digit == kDigitNone) {
|
||||
_animation.start([=](float64 value) {
|
||||
update();
|
||||
if (!value) {
|
||||
_viewDigit = digit;
|
||||
}
|
||||
}, 1., 0., kDuration);
|
||||
} else {
|
||||
_viewDigit = digit;
|
||||
_animation.start([=] { update(); }, 0., 1., kDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CodeDigit::digit() const {
|
||||
return _dataDigit;
|
||||
}
|
||||
|
||||
void CodeDigit::setBorderColor(const QBrush &brush) {
|
||||
_borderPen = QPen(brush, st::introCodeDigitBorderWidth);
|
||||
update();
|
||||
}
|
||||
|
||||
void CodeDigit::shake() {
|
||||
_shaker.shake();
|
||||
}
|
||||
|
||||
void CodeDigit::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
|
||||
auto clipPath = QPainterPath();
|
||||
clipPath.addRoundedRect(rect(), st::boxRadius, st::boxRadius);
|
||||
p.setClipPath(clipPath);
|
||||
|
||||
p.fillRect(rect(), st::windowBgOver);
|
||||
p.strokePath(clipPath, _borderPen);
|
||||
|
||||
if (_viewDigit == kDigitNone) {
|
||||
return;
|
||||
}
|
||||
const auto hiding = (_dataDigit == kDigitNone);
|
||||
const auto progress = _animation.value(1.);
|
||||
|
||||
if (hiding) {
|
||||
p.setOpacity(progress * progress);
|
||||
const auto center = rect().center();
|
||||
p.setTransform(QTransform()
|
||||
.translate(center.x(), center.y())
|
||||
.scale(progress, progress)
|
||||
.translate(-center.x(), -center.y()));
|
||||
} else {
|
||||
p.setOpacity(progress);
|
||||
constexpr auto kSlideDistanceRatio = 0.2;
|
||||
const auto distance = rect().height() * kSlideDistanceRatio;
|
||||
p.translate(0, (distance * (1. - progress)));
|
||||
}
|
||||
p.setFont(st::introCodeDigitFont);
|
||||
p.setPen(st::windowFg);
|
||||
p.drawText(rect(), QString::number(_viewDigit), style::al_center);
|
||||
}
|
||||
|
||||
CodeInput::CodeInput(QWidget *parent)
|
||||
: Ui::RpWidget(parent) {
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
void CodeInput::setDigitsCountMax(int digitsCount) {
|
||||
_digitsCountMax = digitsCount;
|
||||
|
||||
_digits.clear();
|
||||
_currentIndex = 0;
|
||||
|
||||
constexpr auto kWidthRatio = 0.8;
|
||||
const auto digitWidth = st::introCodeDigitHeight * kWidthRatio;
|
||||
const auto padding = Margins(st::introCodeDigitSkip);
|
||||
resize(
|
||||
padding.left()
|
||||
+ digitWidth * digitsCount
|
||||
+ st::introCodeDigitSkip * (digitsCount - 1)
|
||||
+ padding.right(),
|
||||
st::introCodeDigitHeight);
|
||||
|
||||
for (auto i = 0; i < digitsCount; i++) {
|
||||
const auto widget = Ui::CreateChild<CodeDigit>(this);
|
||||
widget->setPointerCursor(false);
|
||||
widget->setClickedCallback([=] { unfocusAll(_currentIndex = i); });
|
||||
widget->resize(digitWidth, st::introCodeDigitHeight);
|
||||
widget->moveToLeft(
|
||||
padding.left() + (digitWidth + st::introCodeDigitSkip) * i,
|
||||
0);
|
||||
_digits.emplace_back(widget);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeInput::setCode(QString code) {
|
||||
using namespace TextUtilities;
|
||||
code = code.remove(RegExpDigitsExclude()).mid(0, _digitsCountMax);
|
||||
for (int i = 0; i < _digits.size(); i++) {
|
||||
if (i >= code.size()) {
|
||||
return;
|
||||
}
|
||||
_digits[i]->setDigit(code.at(i).digitValue());
|
||||
}
|
||||
}
|
||||
|
||||
void CodeInput::requestCode() {
|
||||
const auto result = collectDigits();
|
||||
if (result.size() == _digitsCountMax) {
|
||||
_codeCollected.fire_copy(result);
|
||||
} else {
|
||||
findEmptyAndPerform([&](int i) { _digits[i]->shake(); });
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<QString> CodeInput::codeCollected() const {
|
||||
return _codeCollected.events();
|
||||
}
|
||||
|
||||
void CodeInput::clear() {
|
||||
for (const auto &digit : _digits) {
|
||||
digit->setDigit(kDigitNone);
|
||||
}
|
||||
unfocusAll(_currentIndex = 0);
|
||||
}
|
||||
|
||||
void CodeInput::showError() {
|
||||
clear();
|
||||
for (const auto &digit : _digits) {
|
||||
digit->shake();
|
||||
digit->setBorderColor(st::activeLineFgError);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeInput::focusInEvent(QFocusEvent *e) {
|
||||
unfocusAll(_currentIndex);
|
||||
}
|
||||
|
||||
void CodeInput::focusOutEvent(QFocusEvent *e) {
|
||||
unfocusAll(kDigitNone);
|
||||
}
|
||||
|
||||
void CodeInput::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
p.fillRect(rect(), st::windowBg);
|
||||
}
|
||||
|
||||
void CodeInput::keyPressEvent(QKeyEvent *e) {
|
||||
const auto key = e->key();
|
||||
if (key == Qt::Key_Down || key == Qt::Key_Right || key == Qt::Key_Space) {
|
||||
_currentIndex = Circular(_currentIndex + 1, _digits.size());
|
||||
unfocusAll(_currentIndex);
|
||||
} else if (key == Qt::Key_Up || key == Qt::Key_Left) {
|
||||
_currentIndex = Circular(_currentIndex - 1, _digits.size());
|
||||
unfocusAll(_currentIndex);
|
||||
} else if (key >= Qt::Key_0 && key <= Qt::Key_9) {
|
||||
const auto index = int(key - Qt::Key_0);
|
||||
_digits[_currentIndex]->setDigit(index);
|
||||
_currentIndex = Circular(_currentIndex + 1, _digits.size());
|
||||
if (!_currentIndex) {
|
||||
const auto result = collectDigits();
|
||||
if (result.size() == _digitsCountMax) {
|
||||
_codeCollected.fire_copy(result);
|
||||
_currentIndex = _digits.size() - 1;
|
||||
} else {
|
||||
findEmptyAndPerform([&](int i) { _currentIndex = i; });
|
||||
}
|
||||
}
|
||||
unfocusAll(_currentIndex);
|
||||
} else if (key == Qt::Key_Delete) {
|
||||
_digits[_currentIndex]->setDigit(kDigitNone);
|
||||
} else if (key == Qt::Key_Backspace) {
|
||||
const auto wasDigit = _digits[_currentIndex]->digit();
|
||||
_digits[_currentIndex]->setDigit(kDigitNone);
|
||||
_currentIndex = std::clamp(_currentIndex - 1, 0, int(_digits.size()));
|
||||
if (wasDigit == kDigitNone) {
|
||||
_digits[_currentIndex]->setDigit(kDigitNone);
|
||||
}
|
||||
unfocusAll(_currentIndex);
|
||||
} else if (key == Qt::Key_Enter || key == Qt::Key_Return) {
|
||||
requestCode();
|
||||
} else if (key >= Qt::Key_A && key <= Qt::Key_Z) {
|
||||
_digits[_currentIndex]->shake();
|
||||
} else if (key == Qt::Key_Home || key == Qt::Key_PageUp) {
|
||||
unfocusAll(_currentIndex = 0);
|
||||
} else if (key == Qt::Key_End || key == Qt::Key_PageDown) {
|
||||
unfocusAll(_currentIndex = (_digits.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
QString CodeInput::collectDigits() const {
|
||||
auto result = QString();
|
||||
for (const auto &digit : _digits) {
|
||||
if (digit->digit() != kDigitNone) {
|
||||
result += QString::number(digit->digit());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CodeInput::unfocusAll(int except) {
|
||||
for (auto i = 0; i < _digits.size(); i++) {
|
||||
const auto focused = (i == except);
|
||||
_digits[i]->setBorderColor(focused
|
||||
? st::windowActiveTextFg
|
||||
: st::windowBgRipple);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeInput::findEmptyAndPerform(const Fn<void(int)> &callback) {
|
||||
for (auto i = 0; i < _digits.size(); i++) {
|
||||
if (_digits[i]->digit() == kDigitNone) {
|
||||
callback(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ui
|
49
Telegram/SourceFiles/intro/intro_code_input.h
Normal file
49
Telegram/SourceFiles/intro/intro_code_input.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class CodeDigit;
|
||||
|
||||
class CodeInput final : public Ui::RpWidget {
|
||||
public:
|
||||
CodeInput(QWidget *parent);
|
||||
|
||||
void setDigitsCountMax(int digitsCount);
|
||||
|
||||
void setCode(QString code);
|
||||
|
||||
void requestCode();
|
||||
[[nodiscard]] rpl::producer<QString> codeCollected() const;
|
||||
|
||||
void clear();
|
||||
void showError();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
private:
|
||||
[[nodiscard]] QString collectDigits() const;
|
||||
|
||||
void unfocusAll(int except);
|
||||
void findEmptyAndPerform(const Fn<void(int)> &callback);
|
||||
|
||||
int _digitsCountMax = 0;
|
||||
std::vector<not_null<CodeDigit*>> _digits;
|
||||
int _currentIndex = 0;
|
||||
|
||||
rpl::event_stream<QString> _codeCollected;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ui
|
|
@ -117,6 +117,9 @@ PRIVATE
|
|||
info/boosts/giveaway/select_countries_box.cpp
|
||||
info/boosts/giveaway/select_countries_box.h
|
||||
|
||||
intro/intro_code_input.cpp
|
||||
intro/intro_code_input.h
|
||||
|
||||
layout/abstract_layout_item.cpp
|
||||
layout/abstract_layout_item.h
|
||||
layout/layout_mosaic.cpp
|
||||
|
|
Loading…
Add table
Reference in a new issue