Cross-fade login QR.

This commit is contained in:
John Preston 2019-11-26 17:27:09 +03:00
parent f4bf79b067
commit a0152557ec
11 changed files with 78 additions and 41 deletions

View File

@ -174,6 +174,7 @@ introQrTitle: FlatLabel(defaultFlatLabel) {
linkFontOver: font(20px semibold underline);
}
}
introQrErrorTop: 336px;
introQrTitleTop: 196px;
introQrStep: defaultFlatLabel;
introQrStepsTop: 232px;

View File

@ -56,7 +56,14 @@ namespace {
if (max > 0 && data.size * pixel > max) {
pixel = std::max(max / data.size, 1);
}
return TelegramQrExact(data, pixel * style::DevicePixelRatio());
const auto qr = TelegramQrExact(data, pixel * style::DevicePixelRatio());
auto result = QImage(qr.size(), QImage::Format_ARGB32_Premultiplied);
result.fill(st::windowBg->c);
{
auto p = QPainter(&result);
p.drawImage(QRect(QPoint(), qr.size()), qr);
}
return result;
}
[[nodiscard]] not_null<Ui::RpWidget*> PrepareQrWidget(
@ -67,8 +74,10 @@ namespace {
: waiting(callback, st::defaultInfiniteRadialAnimation) {
}
QImage previous;
QImage qr;
QImage center;
Ui::Animations::Simple shown;
Ui::InfiniteRadialAnimation waiting;
};
auto qrs = std::move(
@ -92,9 +101,15 @@ namespace {
) | rpl::map([](const Qr::Data &code, const auto &) {
return TelegramQr(code, st::introQrPixel, st::introQrMaxSize);
}) | rpl::start_with_next([=](QImage &&image) {
state->previous = std::move(state->qr);
state->qr = std::move(image);
state->waiting.stop();
result->update();
state->shown.stop();
state->shown.start(
[=] { result->update(); },
0.,
1.,
st::fadeWrapDuration);
}, result->lifetime());
std::move(
palettes
@ -106,7 +121,24 @@ namespace {
result->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(result);
auto rect = QRect(
const auto shown = state->qr.isNull() ? 0. : state->shown.value(1.);
if (!state->qr.isNull()) {
const auto size = state->qr.size() / cIntRetinaFactor();
const auto qr = QRect(
(result->width() - size.width()) / 2,
(result->height() - size.height()) / 2,
size.width(),
size.height());
if (shown == 1.) {
state->previous = QImage();
} else if (!state->previous.isNull()) {
p.drawImage(qr, state->previous);
}
p.setOpacity(shown);
p.drawImage(qr, state->qr);
p.setOpacity(1.);
}
const auto rect = QRect(
(result->width() - st::introQrCenterSize) / 2,
(result->height() - st::introQrCenterSize) / 2,
st::introQrCenterSize,
@ -119,7 +151,7 @@ namespace {
auto pen = st::activeButtonBg->p;
pen.setWidth(line);
pen.setCapStyle(Qt::RoundCap);
p.setOpacity(radial.shown);
p.setOpacity(radial.shown * (1. - shown));
p.setPen(pen);
p.drawArc(
rect.marginsAdded({ line, line, line, line }),
@ -127,16 +159,6 @@ namespace {
radial.arcLength);
p.setOpacity(1.);
}
if (!state->qr.isNull()) {
const auto size = state->qr.size() / cIntRetinaFactor();
p.drawImage(
QRect(
(result->width() - size.width()) / 2,
(result->height() - size.height()) / 2,
size.width(),
size.height()),
state->qr);
}
}, result->lifetime());
return result;
}
@ -148,7 +170,7 @@ QrWidget::QrWidget(
not_null<Main::Account*> account,
not_null<Data*> data)
: Step(parent, account, data)
, _refreshTimer([=] { refreshCode(); }) {
, _refreshTimer([=] { refreshCode(); }) {
setTitleText(rpl::single(QString()));
setDescriptionText(rpl::single(QString()));
setErrorCentered(true);
@ -163,6 +185,10 @@ QrWidget::QrWidget(
refreshCode();
}
int QrWidget::errorTop() const {
return contentTop() + st::introQrErrorTop;
}
void QrWidget::checkForTokenUpdate(const MTPUpdates &updates) {
updates.match([&](const MTPDupdateShort &data) {
checkForTokenUpdate(data.vupdate());
@ -256,9 +282,7 @@ void QrWidget::setupControls() {
contentTop() + st::introQrSkipTop);
}, skip->lifetime());
skip->setClickedCallback([=] {
goNext<PhoneWidget>();
});
skip->setClickedCallback([=] { submit(); });
}
void QrWidget::refreshCode() {

View File

@ -40,6 +40,8 @@ public:
}
private:
int errorTop() const override;
void setupControls();
void refreshCode();
void checkForTokenUpdate(const MTPUpdates &updates);

View File

@ -179,11 +179,14 @@ void Step::updateLabelsPosition() {
}
Ui::SendPendingMoveResizeEvents(_error->entity());
auto errorLeft = _errorCentered ? 0 : (contentLeft() + st::buttonRadius);
auto errorTop = contentTop() + (_errorBelowLink ? st::introErrorBelowLinkTop : st::introErrorTop);
_error->moveToLeft(errorLeft, errorTop);
_error->moveToLeft(errorLeft, errorTop());
}
}
int Step::errorTop() const {
return contentTop() + st::introErrorTop;
}
void Step::setTitleText(rpl::producer<QString> titleText) {
_titleText = std::move(titleText);
}
@ -364,13 +367,6 @@ void Step::setErrorCentered(bool centered) {
_error.destroy();
}
void Step::setErrorBelowLink(bool below) {
_errorBelowLink = below;
if (_error) {
updateLabelsPosition();
}
}
void Step::showError(rpl::producer<QString> text) {
_errorText = std::move(text);
}

View File

@ -78,7 +78,6 @@ public:
[[nodiscard]] int contentTop() const;
void setErrorCentered(bool centered);
void setErrorBelowLink(bool below);
void showError(rpl::producer<QString> text);
void hideError() {
showError(rpl::single(QString()));
@ -128,6 +127,8 @@ protected:
}
}
virtual int errorTop() const;
private:
struct CoverAnimation {
CoverAnimation() = default;

View File

@ -95,7 +95,6 @@ CodeWidget::CodeWidget(
_noTelegramCode->addClickHandler([=] { onNoTelegramCode(); });
_code->setDigitsCountMax(getData()->codeLength);
setErrorBelowLink(true);
setTitleText(rpl::single(App::formatPhone(getData()->phone)));
updateDescText();
@ -107,6 +106,10 @@ void CodeWidget::refreshLang() {
updateControlsGeometry();
}
int CodeWidget::errorTop() const {
return contentTop() + st::introErrorBelowLinkTop;
}
void CodeWidget::updateDescText() {
const auto byTelegram = getData()->codeByTelegram;
setDescriptionText(

View File

@ -69,6 +69,8 @@ private slots:
void onCheckRequest();
private:
int errorTop() const override;
void updateCallText();
void refreshLang();
void updateControlsGeometry();

View File

@ -50,7 +50,6 @@ PwdCheckWidget::PwdCheckWidget(
setTitleText(tr::lng_signin_title());
updateDescriptionText();
setErrorBelowLink(true);
if (_hint.isEmpty()) {
_pwdHint->hide();
@ -79,6 +78,10 @@ void PwdCheckWidget::refreshLang() {
updateControlsGeometry();
}
int PwdCheckWidget::errorTop() const {
return contentTop() + st::introErrorBelowLinkTop;
}
void PwdCheckWidget::resizeEvent(QResizeEvent *e) {
Step::resizeEvent(e);
updateControlsGeometry();

View File

@ -46,6 +46,8 @@ private slots:
void onCheckRequest();
private:
int errorTop() const override;
void showReset();
void refreshLang();
void updateControlsGeometry();

View File

@ -122,7 +122,7 @@ void Widget::createLanguageLink() {
Lang::CurrentCloudManager().switchToLanguage(languageId);
});
_changeLanguage->toggle(
!_resetAccount && !_terms,
!_resetAccount && !_terms && _nextShown,
anim::type::normal);
updateControlsGeometry();
};
@ -230,11 +230,6 @@ void Widget::historyMove(Direction direction) {
setupNextButton();
if (_resetAccount) _resetAccount->show(anim::type::normal);
if (_terms) _terms->show(anim::type::normal);
if (_changeLanguage) {
_changeLanguage->toggle(
!_resetAccount && !_terms,
anim::type::normal);
}
getStep()->showAnimated(direction);
fixOrder();
}
@ -253,6 +248,7 @@ void Widget::hideAndDestroy(object_ptr<Ui::FadeWrap<Ui::RpWidget>> widget) {
void Widget::fixOrder() {
_next->raise();
if (_update) _update->raise();
if (_changeLanguage) _changeLanguage->raise();
_settings->raise();
_back->raise();
_connecting->raise();
@ -333,7 +329,7 @@ void Widget::showTerms() {
}
if (_changeLanguage) {
_changeLanguage->toggle(
!_terms && !_resetAccount,
!_terms && !_resetAccount && _nextShown,
anim::type::normal);
}
}
@ -491,7 +487,7 @@ void Widget::showControls() {
}
if (_changeLanguage) {
_changeLanguage->toggle(
!_resetAccount && !_terms,
!_resetAccount && !_terms && _nextShown,
anim::type::instant);
}
if (_terms) {
@ -508,12 +504,19 @@ void Widget::setupNextButton() {
auto visible = getStep()->nextButtonText(
) | rpl::map([](const QString &text) {
return !text.isEmpty();
}) | rpl::distinct_until_changed();
});
std::move(
visible
) | rpl::start_with_next([=](bool visible) {
) | rpl::filter([=](bool visible) {
return visible != _nextShown;
}) | rpl::start_with_next([=](bool visible) {
_next->toggle(visible, anim::type::normal);
_nextShown = visible;
if (_changeLanguage) {
_changeLanguage->toggle(
!_resetAccount && !_terms && _nextShown,
anim::type::normal);
}
_nextShownAnimation.start(
[=] { updateControlsGeometry(); },
_nextShown ? 0. : 1.,

View File

@ -152,7 +152,7 @@ private:
std::unique_ptr<Window::ConnectionState> _connecting;
bool _nextShown = false;
bool _nextShown = true;
Ui::Animations::Simple _nextShownAnimation;
mtpRequestId _resetRequest = 0;