mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-10 08:51:12 +00:00
Cross-fade login QR.
This commit is contained in:
parent
f4bf79b067
commit
a0152557ec
@ -174,6 +174,7 @@ introQrTitle: FlatLabel(defaultFlatLabel) {
|
||||
linkFontOver: font(20px semibold underline);
|
||||
}
|
||||
}
|
||||
introQrErrorTop: 336px;
|
||||
introQrTitleTop: 196px;
|
||||
introQrStep: defaultFlatLabel;
|
||||
introQrStepsTop: 232px;
|
||||
|
@ -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() {
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
int errorTop() const override;
|
||||
|
||||
void setupControls();
|
||||
void refreshCode();
|
||||
void checkForTokenUpdate(const MTPUpdates &updates);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -69,6 +69,8 @@ private slots:
|
||||
void onCheckRequest();
|
||||
|
||||
private:
|
||||
int errorTop() const override;
|
||||
|
||||
void updateCallText();
|
||||
void refreshLang();
|
||||
void updateControlsGeometry();
|
||||
|
@ -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();
|
||||
|
@ -46,6 +46,8 @@ private slots:
|
||||
void onCheckRequest();
|
||||
|
||||
private:
|
||||
int errorTop() const override;
|
||||
|
||||
void showReset();
|
||||
void refreshLang();
|
||||
void updateControlsGeometry();
|
||||
|
@ -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.,
|
||||
|
@ -152,7 +152,7 @@ private:
|
||||
|
||||
std::unique_ptr<Window::ConnectionState> _connecting;
|
||||
|
||||
bool _nextShown = false;
|
||||
bool _nextShown = true;
|
||||
Ui::Animations::Simple _nextShownAnimation;
|
||||
|
||||
mtpRequestId _resetRequest = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user