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); linkFontOver: font(20px semibold underline);
} }
} }
introQrErrorTop: 336px;
introQrTitleTop: 196px; introQrTitleTop: 196px;
introQrStep: defaultFlatLabel; introQrStep: defaultFlatLabel;
introQrStepsTop: 232px; introQrStepsTop: 232px;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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