tdesktop/Telegram/SourceFiles/intro/introwidget.cpp

653 lines
17 KiB
C++
Raw Normal View History

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "intro/introwidget.h"
#include "intro/introstart.h"
#include "intro/introphone.h"
#include "intro/introcode.h"
#include "intro/introsignup.h"
#include "intro/intropwdcheck.h"
2019-11-26 11:10:44 +00:00
#include "lang/lang_keys.h"
#include "lang/lang_cloud_manager.h"
#include "storage/localstorage.h"
2019-07-24 08:46:23 +00:00
#include "main/main_account.h"
#include "mainwindow.h"
2017-04-06 14:38:10 +00:00
#include "boxes/confirm_box.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h"
2016-11-24 19:28:23 +00:00
#include "ui/widgets/labels.h"
#include "ui/wrap/fade_wrap.h"
#include "core/update_checker.h"
2016-11-24 19:28:23 +00:00
#include "window/window_slide_animation.h"
2018-05-07 17:44:33 +00:00
#include "window/window_connecting_widget.h"
2019-09-17 16:13:12 +00:00
#include "base/platform/base_platform_info.h"
#include "facades.h"
#include "app.h"
2019-09-18 11:19:05 +00:00
#include "styles/style_layers.h"
2019-02-07 16:36:30 +00:00
#include "styles/style_intro.h"
2016-11-24 19:28:23 +00:00
namespace Intro {
namespace {
2019-11-26 11:10:44 +00:00
using namespace ::Intro::details;
2018-10-07 09:02:10 +00:00
} // namespace
2019-07-24 08:46:23 +00:00
Widget::Widget(QWidget *parent, not_null<Main::Account*> account)
: RpWidget(parent)
, _account(account)
, _back(this, object_ptr<Ui::IconButton>(this, st::introBackButton))
, _settings(
this,
object_ptr<Ui::RoundButton>(
this,
tr::lng_menu_settings(),
st::defaultBoxButton))
2019-11-26 11:39:54 +00:00
, _next(
this,
object_ptr<Ui::RoundButton>(
this,
nullptr,
st::introNextButton)) {
getData()->country = Platform::SystemCountry();
2016-11-24 19:28:23 +00:00
2019-11-26 11:10:44 +00:00
_back->entity()->setClickedCallback([=] {
historyMove(Direction::Back);
});
_back->hide(anim::type::instant);
2019-11-26 11:39:54 +00:00
_next->entity()->setClickedCallback([this] { getStep()->submit(); });
2016-11-24 19:28:23 +00:00
_settings->entity()->setClickedCallback([] { App::wnd()->showSettings(); });
2017-05-30 09:31:40 +00:00
getNearestDC();
2018-05-07 17:44:33 +00:00
setupConnectingWidget();
2019-07-24 08:46:23 +00:00
appendStep(new StartWidget(this, _account, getData()));
2016-11-24 19:28:23 +00:00
fixOrder();
subscribe(Lang::CurrentCloudManager().firstLanguageSuggestion(), [this] { createLanguageLink(); });
createLanguageLink();
if (_changeLanguage) _changeLanguage->finishAnimating();
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
show();
2016-11-24 19:28:23 +00:00
showControls();
getStep()->showFast();
setInnerFocus();
cSetPasswordRecovered(false);
if (!Core::UpdaterDisabled()) {
Core::UpdateChecker checker;
checker.start();
2019-11-26 11:10:44 +00:00
rpl::merge(
rpl::single(rpl::empty_value()),
checker.isLatest(),
checker.failed(),
checker.ready()
) | rpl::start_with_next([=] {
checkUpdateStatus();
}, lifetime());
}
}
2018-05-07 17:44:33 +00:00
void Widget::setupConnectingWidget() {
2019-02-10 16:29:55 +00:00
_connecting = std::make_unique<Window::ConnectionState>(
2018-05-07 17:44:33 +00:00
this,
rpl::single(true));
}
void Widget::refreshLang() {
_changeLanguage.destroy();
createLanguageLink();
InvokeQueued(this, [this] { updateControlsGeometry(); });
}
2017-05-30 09:31:40 +00:00
void Widget::createLanguageLink() {
if (_changeLanguage) return;
auto createLink = [this](const QString &text, const QString &languageId) {
_changeLanguage.create(
this,
object_ptr<Ui::LinkButton>(this, text));
_changeLanguage->hide(anim::type::instant);
_changeLanguage->entity()->setClickedCallback([=] {
2017-05-30 09:31:40 +00:00
Lang::CurrentCloudManager().switchToLanguage(languageId);
});
2018-05-30 15:08:12 +00:00
_changeLanguage->toggle(
!_resetAccount && !_terms,
anim::type::normal);
updateControlsGeometry();
2017-05-30 09:31:40 +00:00
};
const auto currentId = Lang::LanguageIdOrDefault(Lang::Current().id());
const auto defaultId = Lang::DefaultLanguageId();
const auto suggested = Lang::CurrentCloudManager().suggestedLanguage();
if (currentId != defaultId) {
2019-06-19 15:42:16 +00:00
createLink(
Lang::GetOriginalValue(tr::lng_switch_to_this.base),
defaultId);
} else if (!suggested.isEmpty() && suggested != currentId) {
request(MTPlangpack_GetStrings(
2018-08-20 11:31:40 +00:00
MTP_string(Lang::CloudLangPackName()),
MTP_string(suggested),
MTP_vector<MTPstring>(1, MTP_string("lng_switch_to_this"))
)).done([=](const MTPVector<MTPLangPackString> &result) {
2019-06-19 15:42:16 +00:00
const auto strings = Lang::Instance::ParseStrings(result);
const auto i = strings.find(tr::lng_switch_to_this.base);
if (i != strings.end()) {
createLink(i->second, suggested);
2017-05-30 09:31:40 +00:00
}
}).send();
}
}
2019-11-26 11:10:44 +00:00
void Widget::checkUpdateStatus() {
Expects(!Core::UpdaterDisabled());
if (Core::UpdateChecker().state() == Core::UpdateChecker::State::Ready) {
if (_update) return;
_update.create(
this,
object_ptr<Ui::RoundButton>(
this,
tr::lng_menu_update(),
st::defaultBoxButton));
if (!_a_show.animating()) {
_update->setVisible(true);
}
const auto stepHasCover = getStep()->hasCover();
_update->toggle(!stepHasCover, anim::type::instant);
2016-11-24 19:28:23 +00:00
_update->entity()->setClickedCallback([] {
Core::checkReadyUpdate();
App::restart();
});
} else {
if (!_update) return;
_update.destroy();
}
updateControlsGeometry();
}
2016-11-24 19:28:23 +00:00
void Widget::setInnerFocus() {
if (getStep()->animating()) {
setFocus();
} else {
getStep()->setInnerFocus();
}
}
2016-11-24 19:28:23 +00:00
void Widget::historyMove(Direction direction) {
2019-11-26 11:10:44 +00:00
Expects(_stepHistory.size() > 1);
2019-11-26 11:10:44 +00:00
if (getStep()->animating()) {
return;
}
2016-11-24 19:28:23 +00:00
auto wasStep = getStep((direction == Direction::Back) ? 0 : 1);
if (direction == Direction::Back) {
_stepHistory.pop_back();
2016-11-24 19:28:23 +00:00
wasStep->cancelled();
} else if (direction == Direction::Replace) {
2019-11-26 11:10:44 +00:00
_stepHistory.erase(_stepHistory.end() - 2);
2016-11-24 19:28:23 +00:00
}
2018-06-01 07:00:18 +00:00
if (_resetAccount) {
hideAndDestroy(std::exchange(_resetAccount, { nullptr }));
}
if (_terms) {
hideAndDestroy(std::exchange(_terms, { nullptr }));
}
getStep()->finishInit();
2016-11-24 19:28:23 +00:00
getStep()->prepareShowAnimated(wasStep);
if (wasStep->hasCover() != getStep()->hasCover()) {
2019-11-26 11:10:44 +00:00
_nextTopFrom = wasStep->contentTop() + st::introNextTop;
2016-11-24 19:28:23 +00:00
_controlsTopFrom = wasStep->hasCover() ? st::introCoverHeight : 0;
_coverShownAnimation.start([this] { updateControlsGeometry(); }, 0., 1., st::introCoverDuration, wasStep->hasCover() ? anim::linear : anim::easeOutCirc);
}
2015-04-04 20:01:34 +00:00
2016-11-24 19:28:23 +00:00
if (direction == Direction::Forward || direction == Direction::Replace) {
wasStep->finished();
}
if (direction == Direction::Back || direction == Direction::Replace) {
delete base::take(wasStep);
}
_back->toggle(getStep()->hasBack(), anim::type::normal);
auto stepHasCover = getStep()->hasCover();
_settings->toggle(!stepHasCover, anim::type::normal);
2018-05-30 15:08:12 +00:00
if (_update) {
_update->toggle(!stepHasCover, anim::type::normal);
}
2019-11-26 11:10:44 +00:00
setupNextButton();
2018-06-01 07:00:18 +00:00
if (_resetAccount) _resetAccount->show(anim::type::normal);
if (_terms) _terms->show(anim::type::normal);
2018-05-30 15:08:12 +00:00
if (_changeLanguage) {
_changeLanguage->toggle(
!_resetAccount && !_terms,
anim::type::normal);
}
2016-11-24 19:28:23 +00:00
getStep()->showAnimated(direction);
fixOrder();
}
2018-05-30 15:08:12 +00:00
void Widget::hideAndDestroy(object_ptr<Ui::FadeWrap<Ui::RpWidget>> widget) {
2019-09-13 12:22:54 +00:00
const auto weak = Ui::MakeWeak(widget.data());
2018-05-30 15:08:12 +00:00
widget->hide(anim::type::normal);
widget->shownValue(
) | rpl::start_with_next([=](bool shown) {
if (!shown && weak) {
weak->deleteLater();
}
}, widget->lifetime());
}
2016-11-24 19:28:23 +00:00
void Widget::fixOrder() {
_next->raise();
if (_update) _update->raise();
_settings->raise();
_back->raise();
2018-05-07 17:44:33 +00:00
_connecting->raise();
2016-11-24 19:28:23 +00:00
}
void Widget::moveToStep(Step *step, Direction direction) {
appendStep(step);
_back->raise();
_settings->raise();
if (_update) {
_update->raise();
}
2018-05-07 17:44:33 +00:00
_connecting->raise();
2016-11-24 19:28:23 +00:00
historyMove(direction);
}
2016-11-24 19:28:23 +00:00
void Widget::appendStep(Step *step) {
_stepHistory.push_back(step);
2019-11-26 11:10:44 +00:00
step->setGeometry(rect());
2018-05-30 15:08:12 +00:00
step->setGoCallback([=](Step *step, Direction direction) {
2016-11-24 19:28:23 +00:00
if (direction == Direction::Back) {
historyMove(direction);
} else {
moveToStep(step, direction);
}
});
2018-05-30 15:08:12 +00:00
step->setShowResetCallback([=] {
2016-11-24 19:28:23 +00:00
showResetButton();
});
2018-06-01 07:00:18 +00:00
step->setShowTermsCallback([=]() {
showTerms();
2018-05-30 15:08:12 +00:00
});
step->setAcceptTermsCallback([=](Fn<void()> callback) {
2018-06-01 07:00:18 +00:00
acceptTerms(callback);
2018-05-30 15:08:12 +00:00
});
2016-11-24 19:28:23 +00:00
}
void Widget::showResetButton() {
if (!_resetAccount) {
auto entity = object_ptr<Ui::RoundButton>(
this,
tr::lng_signin_reset_account(),
st::introResetButton);
2018-05-30 15:08:12 +00:00
_resetAccount.create(this, std::move(entity));
_resetAccount->hide(anim::type::instant);
2016-11-24 19:28:23 +00:00
_resetAccount->entity()->setClickedCallback([this] { resetAccount(); });
updateControlsGeometry();
2016-04-14 19:24:42 +00:00
}
_resetAccount->show(anim::type::normal);
2018-05-30 15:08:12 +00:00
if (_changeLanguage) {
_changeLanguage->hide(anim::type::normal);
}
}
2018-06-01 07:00:18 +00:00
void Widget::showTerms() {
if (getData()->termsLock.text.text.isEmpty()) {
2018-06-01 07:00:18 +00:00
_terms.destroy();
} else if (!_terms) {
auto entity = object_ptr<Ui::FlatLabel>(
this,
tr::lng_terms_signup(
2018-06-01 07:00:18 +00:00
lt_link,
tr::lng_terms_signup_link() | Ui::Text::ToLink(),
Ui::Text::WithEntities),
2018-06-01 07:00:18 +00:00
st::introTermsLabel);
_terms.create(this, std::move(entity));
_terms->entity()->setClickHandlerFilter([=](
const ClickHandlerPtr &handler,
Qt::MouseButton button) {
if (button == Qt::LeftButton) {
2018-06-01 07:00:18 +00:00
showTerms(nullptr);
}
return false;
});
2018-06-01 07:00:18 +00:00
updateControlsGeometry();
_terms->hide(anim::type::instant);
2018-05-30 15:08:12 +00:00
}
if (_changeLanguage) {
_changeLanguage->toggle(
!_terms && !_resetAccount,
anim::type::normal);
}
}
void Widget::acceptTerms(Fn<void()> callback) {
2018-05-30 15:08:12 +00:00
showTerms(callback);
2016-11-24 19:28:23 +00:00
}
void Widget::resetAccount() {
if (_resetRequest) return;
2019-06-19 15:09:03 +00:00
Ui::show(Box<ConfirmBox>(tr::lng_signin_sure_reset(tr::now), tr::lng_signin_reset(tr::now), st::attentionBoxButton, crl::guard(this, [this] {
if (_resetRequest) return;
2017-05-30 09:31:40 +00:00
_resetRequest = request(MTPaccount_DeleteAccount(MTP_string("Forgot password"))).done([this](const MTPBool &result) {
_resetRequest = 0;
Ui::hideLayer();
2019-07-24 08:46:23 +00:00
moveToStep(
new SignupWidget(this, _account, getData()),
Direction::Replace);
2017-05-30 09:31:40 +00:00
}).fail([this](const RPCError &error) {
_resetRequest = 0;
2019-07-24 08:46:23 +00:00
const auto &type = error.type();
2017-05-30 09:31:40 +00:00
if (type.startsWith(qstr("2FA_CONFIRM_WAIT_"))) {
const auto seconds = type.mid(qstr("2FA_CONFIRM_WAIT_").size()).toInt();
const auto days = (seconds + 59) / 86400;
const auto hours = ((seconds + 59) % 86400) / 3600;
const auto minutes = ((seconds + 59) % 3600) / 60;
auto when = tr::lng_signin_reset_minutes(
tr::now,
lt_count,
minutes);
2017-05-30 09:31:40 +00:00
if (days > 0) {
const auto daysCount = tr::lng_signin_reset_days(
tr::now,
lt_count,
days);
const auto hoursCount = tr::lng_signin_reset_hours(
tr::now,
lt_count,
hours);
when = tr::lng_signin_reset_in_days(
tr::now,
lt_days_count,
daysCount,
lt_hours_count,
hoursCount,
lt_minutes_count,
when);
2017-05-30 09:31:40 +00:00
} else if (hours > 0) {
const auto hoursCount = tr::lng_signin_reset_hours(
tr::now,
lt_count,
hours);
when = tr::lng_signin_reset_in_hours(
tr::now,
lt_hours_count,
hoursCount,
lt_minutes_count,
when);
2017-05-30 09:31:40 +00:00
}
Ui::show(Box<InformBox>(tr::lng_signin_reset_wait(
tr::now,
lt_phone_number,
App::formatPhone(getData()->phone),
lt_when,
when)));
2017-05-30 09:31:40 +00:00
} else if (type == qstr("2FA_RECENT_CONFIRM")) {
Ui::show(Box<InformBox>(
tr::lng_signin_reset_cancelled(tr::now)));
2017-05-30 09:31:40 +00:00
} else {
Ui::hideLayer();
getStep()->showError(rpl::single(Lang::Hard::ServerError()));
2017-05-30 09:31:40 +00:00
}
}).send();
})));
}
2017-05-30 09:31:40 +00:00
void Widget::getNearestDC() {
request(MTPhelp_GetNearestDc()).done([this](const MTPNearestDc &result) {
auto &nearest = result.c_nearestDc();
2018-05-30 15:08:12 +00:00
DEBUG_LOG(("Got nearest dc, country: %1, nearest: %2, this: %3"
2019-07-05 13:38:38 +00:00
).arg(qs(nearest.vcountry())
).arg(nearest.vnearest_dc().v
).arg(nearest.vthis_dc().v));
2019-07-24 08:46:23 +00:00
_account->suggestMainDcId(nearest.vnearest_dc().v);
const auto nearestCountry = qs(nearest.vcountry());
2017-05-30 09:31:40 +00:00
if (getData()->country != nearestCountry) {
getData()->country = nearestCountry;
getData()->updated.notify();
2016-11-24 19:28:23 +00:00
}
2017-05-30 09:31:40 +00:00
}).send();
2016-11-24 19:28:23 +00:00
}
void Widget::showTerms(Fn<void()> callback) {
if (getData()->termsLock.text.text.isEmpty()) {
2018-05-30 15:08:12 +00:00
return;
}
2019-09-13 12:22:54 +00:00
const auto weak = Ui::MakeWeak(this);
const auto box = Ui::show(callback
? Box<Window::TermsBox>(
getData()->termsLock,
tr::lng_terms_agree(),
tr::lng_terms_decline())
: Box<Window::TermsBox>(
getData()->termsLock.text,
tr::lng_box_ok(),
nullptr));
box->setCloseByEscape(false);
box->setCloseByOutsideClick(false);
2018-06-01 07:00:18 +00:00
box->agreeClicks(
) | rpl::start_with_next([=] {
if (callback) {
callback();
}
if (box) {
box->closeBox();
}
}, box->lifetime());
box->cancelClicks(
) | rpl::start_with_next([=] {
const auto box = Ui::show(Box<Window::TermsBox>(
2019-06-19 15:09:03 +00:00
TextWithEntities{ tr::lng_terms_signup_sorry(tr::now) },
tr::lng_intro_finish(),
tr::lng_terms_decline()));
2018-05-30 15:08:12 +00:00
box->agreeClicks(
) | rpl::start_with_next([=] {
2018-06-01 07:00:18 +00:00
if (weak) {
showTerms(callback);
2018-05-30 15:08:12 +00:00
}
2018-06-01 07:00:18 +00:00
}, box->lifetime());
box->cancelClicks(
) | rpl::start_with_next([=] {
2018-05-30 15:08:12 +00:00
if (box) {
box->closeBox();
}
}, box->lifetime());
2018-06-01 07:00:18 +00:00
}, box->lifetime());
2018-05-30 15:08:12 +00:00
}
2016-11-24 19:28:23 +00:00
void Widget::showControls() {
getStep()->show();
2019-11-26 11:10:44 +00:00
setupNextButton();
2019-11-26 11:39:54 +00:00
_next->show(anim::type::instant);
2019-11-26 11:10:44 +00:00
_nextShownAnimation.stop();
2018-05-07 17:44:33 +00:00
_connecting->setForceHidden(false);
auto hasCover = getStep()->hasCover();
_settings->toggle(!hasCover, anim::type::instant);
2018-05-30 15:08:12 +00:00
if (_update) {
_update->toggle(!hasCover, anim::type::instant);
}
if (_changeLanguage) {
_changeLanguage->toggle(
!_resetAccount && !_terms,
anim::type::instant);
}
2018-06-01 07:00:18 +00:00
if (_terms) {
_terms->show(anim::type::instant);
}
_back->toggle(getStep()->hasBack(), anim::type::instant);
2016-11-24 19:28:23 +00:00
}
2019-11-26 11:10:44 +00:00
void Widget::setupNextButton() {
2019-11-26 11:39:54 +00:00
_next->entity()->setText(getStep()->nextButtonText(
2019-11-26 11:10:44 +00:00
) | rpl::filter([](const QString &text) {
return !text.isEmpty();
}));
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) {
2019-11-26 11:39:54 +00:00
_next->toggle(visible, anim::type::normal);
2019-11-26 11:10:44 +00:00
_nextShown = visible;
_nextShownAnimation.start(
[=] { updateControlsGeometry(); },
_nextShown ? 0. : 1.,
_nextShown ? 1. : 0.,
st::slideDuration);
}, getStep()->lifetime());
}
2016-11-24 19:28:23 +00:00
void Widget::hideControls() {
getStep()->hide();
2019-11-26 11:39:54 +00:00
_next->hide(anim::type::instant);
2018-05-07 17:44:33 +00:00
_connecting->setForceHidden(true);
_settings->hide(anim::type::instant);
if (_update) _update->hide(anim::type::instant);
if (_changeLanguage) _changeLanguage->hide(anim::type::instant);
2018-06-01 07:00:18 +00:00
if (_terms) _terms->hide(anim::type::instant);
_back->hide(anim::type::instant);
2016-11-24 19:28:23 +00:00
}
void Widget::showAnimated(const QPixmap &bgAnimCache, bool back) {
_showBack = back;
2016-11-24 19:28:23 +00:00
(_showBack ? _cacheOver : _cacheUnder) = bgAnimCache;
2016-11-24 19:28:23 +00:00
2019-04-02 09:13:30 +00:00
_a_show.stop();
2016-11-24 19:28:23 +00:00
showControls();
(_showBack ? _cacheUnder : _cacheOver) = Ui::GrabWidget(this);
2016-11-24 19:28:23 +00:00
hideControls();
2015-10-17 14:52:26 +00:00
2019-11-26 11:10:44 +00:00
_a_show.start(
[=] { animationCallback(); },
0.,
1.,
st::slideDuration,
Window::SlideAnimation::transition());
2015-10-17 14:52:26 +00:00
show();
}
void Widget::animationCallback() {
update();
if (!_a_show.animating()) {
2015-10-17 14:52:26 +00:00
_cacheUnder = _cacheOver = QPixmap();
2016-11-24 19:28:23 +00:00
showControls();
getStep()->activate();
2015-10-17 14:52:26 +00:00
}
}
2016-11-24 19:28:23 +00:00
void Widget::paintEvent(QPaintEvent *e) {
bool trivial = (rect() == e->rect());
setMouseTracking(true);
QPainter p(this);
if (!trivial) {
p.setClipRect(e->rect());
}
2016-10-31 12:29:26 +00:00
p.fillRect(e->rect(), st::windowBg);
2019-04-02 09:13:30 +00:00
auto progress = _a_show.value(1.);
2015-10-17 14:52:26 +00:00
if (_a_show.animating()) {
auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
auto shadow = _showBack ? (1. - progress) : progress;
if (coordOver > 0) {
p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor()));
p.setOpacity(shadow);
p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg);
2015-10-17 14:52:26 +00:00
p.setOpacity(1);
}
p.drawPixmap(coordOver, 0, _cacheOver);
p.setOpacity(shadow);
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
}
}
2016-11-24 19:28:23 +00:00
void Widget::resizeEvent(QResizeEvent *e) {
2019-11-26 11:10:44 +00:00
for (const auto step : _stepHistory) {
step->setGeometry(rect());
2016-11-24 19:28:23 +00:00
}
updateControlsGeometry();
}
2016-11-24 19:28:23 +00:00
void Widget::updateControlsGeometry() {
2019-04-02 09:13:30 +00:00
auto shown = _coverShownAnimation.value(1.);
2016-11-24 19:28:23 +00:00
auto controlsTopTo = getStep()->hasCover() ? st::introCoverHeight : 0;
auto controlsTop = anim::interpolate(_controlsTopFrom, controlsTopTo, shown);
_settings->moveToRight(st::introSettingsSkip, controlsTop + st::introSettingsSkip);
if (_update) {
_update->moveToRight(st::introSettingsSkip + _settings->width() + st::introSettingsSkip, _settings->y());
}
_back->moveToLeft(0, controlsTop);
2019-11-26 11:10:44 +00:00
auto nextTopTo = getStep()->contentTop() + st::introNextTop;
2016-11-24 19:28:23 +00:00
auto nextTop = anim::interpolate(_nextTopFrom, nextTopTo, shown);
2019-11-26 11:10:44 +00:00
const auto shownAmount = _nextShownAnimation.value(_nextShown ? 1. : 0.);
2019-11-26 11:39:54 +00:00
const auto realNextTop = anim::interpolate(
nextTop + st::introNextSlide,
nextTop,
shownAmount);
2019-11-26 11:10:44 +00:00
_next->moveToLeft((width() - _next->width()) / 2, realNextTop);
2016-11-24 19:28:23 +00:00
if (_changeLanguage) {
_changeLanguage->moveToLeft((width() - _changeLanguage->width()) / 2, _next->y() + _next->height() + _changeLanguage->height());
}
if (_resetAccount) {
_resetAccount->moveToLeft((width() - _resetAccount->width()) / 2, height() - st::introResetBottom - _resetAccount->height());
}
2018-05-30 15:08:12 +00:00
if (_terms) {
_terms->moveToLeft((width() - _terms->width()) / 2, height() - st::introTermsBottom - _terms->height());
}
2016-11-24 19:28:23 +00:00
}
void Widget::keyPressEvent(QKeyEvent *e) {
if (_a_show.animating() || getStep()->animating()) return;
if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) {
2016-11-24 19:28:23 +00:00
if (getStep()->hasBack()) {
historyMove(Direction::Back);
}
} else if (e->key() == Qt::Key_Enter
|| e->key() == Qt::Key_Return
|| e->key() == Qt::Key_Space) {
2016-11-24 19:28:23 +00:00
getStep()->submit();
}
}
2016-11-24 19:28:23 +00:00
Widget::~Widget() {
for (auto step : base::take(_stepHistory)) {
delete step;
}
if (App::wnd()) App::wnd()->noIntro(this);
}
2016-11-24 19:28:23 +00:00
} // namespace Intro