From 55ec4ebf868adadf2eaadd7f038fb0495333453d Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 23 Jun 2020 18:55:08 +0400 Subject: [PATCH] Allow returning from new account setup. --- Telegram/SourceFiles/intro/intro_code.cpp | 4 +- Telegram/SourceFiles/intro/intro_phone.cpp | 4 +- Telegram/SourceFiles/intro/intro_qr.cpp | 6 +- Telegram/SourceFiles/intro/intro_step.cpp | 15 ++-- Telegram/SourceFiles/intro/intro_step.h | 15 ++-- Telegram/SourceFiles/intro/intro_widget.cpp | 70 +++++++++++++------ Telegram/SourceFiles/intro/intro_widget.h | 26 +++++-- Telegram/SourceFiles/main/main_domain.cpp | 19 +++++ Telegram/SourceFiles/main/main_domain.h | 2 + Telegram/SourceFiles/mainwindow.cpp | 4 +- Telegram/SourceFiles/mainwindow.h | 3 +- .../SourceFiles/window/window_controller.cpp | 14 +++- .../SourceFiles/window/window_main_menu.cpp | 25 ++++--- 13 files changed, 146 insertions(+), 61 deletions(-) diff --git a/Telegram/SourceFiles/intro/intro_code.cpp b/Telegram/SourceFiles/intro/intro_code.cpp index 24684ca48..45464513f 100644 --- a/Telegram/SourceFiles/intro/intro_code.cpp +++ b/Telegram/SourceFiles/intro/intro_code.cpp @@ -259,7 +259,7 @@ void CodeWidget::codeSubmitDone(const MTPauth_Authorization &result) { } else { getData()->termsLock = Window::TermsLock(); } - goReplace(); + goReplace(Animate::Forward); }); } @@ -358,7 +358,7 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) { getData()->hasRecovery = d.is_has_recovery(); getData()->pwdHint = qs(d.vhint().value_or_empty()); getData()->pwdNotEmptyPassport = d.is_has_secure_values(); - goReplace(); + goReplace(Animate::Forward); } void CodeWidget::submit() { diff --git a/Telegram/SourceFiles/intro/intro_phone.cpp b/Telegram/SourceFiles/intro/intro_phone.cpp index 9d250c47d..2254bae25 100644 --- a/Telegram/SourceFiles/intro/intro_phone.cpp +++ b/Telegram/SourceFiles/intro/intro_phone.cpp @@ -94,7 +94,9 @@ void PhoneWidget::setupQrLogin() { contentTop() + st::introQrLoginLinkTop); }, qrLogin->lifetime()); - qrLogin->setClickedCallback([=] { goReplace(); }); + qrLogin->setClickedCallback([=] { + goReplace(Animate::Forward); + }); }, lifetime()); } diff --git a/Telegram/SourceFiles/intro/intro_qr.cpp b/Telegram/SourceFiles/intro/intro_qr.cpp index 9cc11fbc1..63368fa4e 100644 --- a/Telegram/SourceFiles/intro/intro_qr.cpp +++ b/Telegram/SourceFiles/intro/intro_qr.cpp @@ -218,7 +218,7 @@ void QrWidget::checkForTokenUpdate(const MTPUpdate &update) { } void QrWidget::submit() { - goReplace(); + goReplace(Animate::Forward); } rpl::producer QrWidget::nextButtonText() const { @@ -389,7 +389,7 @@ void QrWidget::sendCheckPasswordRequest() { data); if (!data.vcurrent_algo() || !data.vsrp_id() || !data.vsrp_B()) { LOG(("API Error: No current password received on login.")); - goReplace(); + goReplace(Animate::Forward); return; } else if (!getData()->pwdRequest) { const auto box = std::make_shared>(); @@ -406,7 +406,7 @@ void QrWidget::sendCheckPasswordRequest() { getData()->hasRecovery = data.is_has_recovery(); getData()->pwdHint = qs(data.vhint().value_or_empty()); getData()->pwdNotEmptyPassport = data.is_has_secure_values(); - goReplace(); + goReplace(Animate::Forward); }); }).fail([=](const RPCError &error) { showTokenError(error); diff --git a/Telegram/SourceFiles/intro/intro_step.cpp b/Telegram/SourceFiles/intro/intro_step.cpp index db5b04a61..6d1b36547 100644 --- a/Telegram/SourceFiles/intro/intro_step.cpp +++ b/Telegram/SourceFiles/intro/intro_step.cpp @@ -118,19 +118,19 @@ rpl::producer Step::nextButtonText() const { void Step::goBack() { if (_goCallback) { - _goCallback(nullptr, Direction::Back); + _goCallback(nullptr, StackAction::Back, Animate::Back); } } void Step::goNext(Step *step) { if (_goCallback) { - _goCallback(step, Direction::Forward); + _goCallback(step, StackAction::Forward, Animate::Forward); } } -void Step::goReplace(Step *step) { +void Step::goReplace(Step *step, Animate animate) { if (_goCallback) { - _goCallback(step, Direction::Replace); + _goCallback(step, StackAction::Replace, animate); } } @@ -455,12 +455,12 @@ QPixmap Step::prepareSlideAnimation() { QRect(grabLeft, grabTop, st::introStepWidth, st::introStepHeight)); } -void Step::showAnimated(Direction direction) { +void Step::showAnimated(Animate animate) { setFocus(); show(); hideChildren(); if (_slideAnimation) { - auto slideLeft = (direction == Direction::Back); + auto slideLeft = (animate == Animate::Back); _slideAnimation->start( slideLeft, [=] { update(0, contentTop(), width(), st::introStepHeight); }, @@ -474,7 +474,8 @@ void Step::setShowAnimationClipping(QRect clipping) { _coverAnimation.clipping = clipping; } -void Step::setGoCallback(Fn callback) { +void Step::setGoCallback( + Fn callback) { _goCallback = std::move(callback); } diff --git a/Telegram/SourceFiles/intro/intro_step.h b/Telegram/SourceFiles/intro/intro_step.h index 1aa6c4a50..4e9d0ee90 100644 --- a/Telegram/SourceFiles/intro/intro_step.h +++ b/Telegram/SourceFiles/intro/intro_step.h @@ -28,7 +28,8 @@ namespace Intro { namespace details { struct Data; -enum class Direction; +enum class StackAction; +enum class Animate; class Step : public Ui::RpWidget, protected base::Subscriber { public: @@ -55,7 +56,7 @@ public: } void setGoCallback( - Fn callback); + Fn callback); void setShowResetCallback(Fn callback); void setShowTermsCallback( Fn callback); @@ -63,7 +64,7 @@ public: Fn callback)> callback); void prepareShowAnimated(Step *after); - void showAnimated(Direction direction); + void showAnimated(Animate animate); void showFast(); [[nodiscard]] bool animating() const; void setShowAnimationClipping(QRect clipping); @@ -114,8 +115,8 @@ protected: } template - void goReplace() { - goReplace(new StepType(parentWidget(), _account, _data)); + void goReplace(Animate animate) { + goReplace(new StepType(parentWidget(), _account, _data), animate); } void showResetButton() { @@ -157,7 +158,7 @@ private: void refreshError(const QString &text); void goNext(Step *step); - void goReplace(Step *step); + void goReplace(Step *step, Animate animate); [[nodiscard]] CoverAnimation prepareCoverAnimation(Step *step); [[nodiscard]] QPixmap prepareContentSnapshot(); @@ -172,7 +173,7 @@ private: mutable std::optional _api; bool _hasCover = false; - Fn _goCallback; + Fn _goCallback; Fn _showResetCallback; Fn _showTermsCallback; Fn callback)> _acceptTermsCallback; diff --git a/Telegram/SourceFiles/intro/intro_widget.cpp b/Telegram/SourceFiles/intro/intro_widget.cpp index c4476a5c9..6c93d7524 100644 --- a/Telegram/SourceFiles/intro/intro_widget.cpp +++ b/Telegram/SourceFiles/intro/intro_widget.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "intro/intro_start.h" #include "intro/intro_phone.h" +#include "intro/intro_qr.h" #include "intro/intro_code.h" #include "intro/intro_signup.h" #include "intro/intro_password_check.h" @@ -16,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_cloud_manager.h" #include "storage/localstorage.h" #include "main/main_account.h" +#include "main/main_domain.h" #include "mainwindow.h" #include "boxes/confirm_box.h" #include "ui/text/text_utilities.h" @@ -40,7 +42,10 @@ using namespace ::Intro::details; } // namespace -Widget::Widget(QWidget *parent, not_null account) +Widget::Widget( + QWidget *parent, + not_null account, + EnterPoint point) : RpWidget(parent) , _account(account) , _back(this, object_ptr(this, st::introBackButton)) @@ -57,7 +62,19 @@ Widget::Widget(QWidget *parent, not_null account) this, account, rpl::single(true))) { - appendStep(new StartWidget(this, _account, getData())); + switch (point) { + case EnterPoint::Start: + appendStep(new StartWidget(this, _account, getData())); + break; + case EnterPoint::Phone: + appendStep(new PhoneWidget(this, _account, getData())); + break; + case EnterPoint::Qr: + appendStep(new QrWidget(this, _account, getData())); + break; + default: Unexpected("Enter point in Intro::Widget::Widget."); + } + fixOrder(); getData()->country = Platform::SystemCountry(); @@ -77,9 +94,7 @@ Widget::Widget(QWidget *parent, not_null account) handleUpdates(updates); }, lifetime()); - _back->entity()->setClickedCallback([=] { - historyMove(Direction::Back); - }); + _back->entity()->setClickedCallback([=] { backRequested(); }); _back->hide(anim::type::instant); _next->entity()->setClickedCallback([=] { getStep()->submit(); }); @@ -227,18 +242,18 @@ void Widget::setInnerFocus() { } } -void Widget::historyMove(Direction direction) { +void Widget::historyMove(StackAction action, Animate animate) { Expects(_stepHistory.size() > 1); if (getStep()->animating()) { return; } - auto wasStep = getStep((direction == Direction::Back) ? 0 : 1); - if (direction == Direction::Back) { + auto wasStep = getStep((action == StackAction::Back) ? 0 : 1); + if (action == StackAction::Back) { _stepHistory.pop_back(); wasStep->cancelled(); - } else if (direction == Direction::Replace) { + } else if (action == StackAction::Replace) { _stepHistory.erase(_stepHistory.end() - 2); } @@ -258,10 +273,10 @@ void Widget::historyMove(Direction direction) { } _stepLifetime.destroy(); - if (direction == Direction::Forward || direction == Direction::Replace) { + if (action == StackAction::Forward || action == StackAction::Replace) { wasStep->finished(); } - if (direction == Direction::Back || direction == Direction::Replace) { + if (action == StackAction::Back || action == StackAction::Replace) { delete base::take(wasStep); } _back->toggle(getStep()->hasBack(), anim::type::normal); @@ -274,7 +289,7 @@ void Widget::historyMove(Direction direction) { setupNextButton(); if (_resetAccount) _resetAccount->show(anim::type::normal); if (_terms) _terms->show(anim::type::normal); - getStep()->showAnimated(direction); + getStep()->showAnimated(animate); fixOrder(); } @@ -298,7 +313,7 @@ void Widget::fixOrder() { _connecting->raise(); } -void Widget::moveToStep(Step *step, Direction direction) { +void Widget::moveToStep(Step *step, StackAction action, Animate animate) { appendStep(step); _back->raise(); _settings->raise(); @@ -307,17 +322,17 @@ void Widget::moveToStep(Step *step, Direction direction) { } _connecting->raise(); - historyMove(direction); + historyMove(action, animate); } void Widget::appendStep(Step *step) { _stepHistory.push_back(step); step->setGeometry(rect()); - step->setGoCallback([=](Step *step, Direction direction) { - if (direction == Direction::Back) { - historyMove(direction); + step->setGoCallback([=](Step *step, StackAction action, Animate animate) { + if (action == StackAction::Back) { + historyMove(action, animate); } else { - moveToStep(step, direction); + moveToStep(step, action, animate); } }); step->setShowResetCallback([=] { @@ -399,7 +414,8 @@ void Widget::resetAccount() { Ui::hideLayer(); moveToStep( new SignupWidget(this, _account, getData()), - Direction::Replace); + StackAction::Replace, + Animate::Forward); }).fail([=](const RPCError &error) { _resetRequest = 0; @@ -689,7 +705,7 @@ void Widget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { if (getStep()->hasBack()) { - historyMove(Direction::Back); + backRequested(); } } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return @@ -698,6 +714,20 @@ void Widget::keyPressEvent(QKeyEvent *e) { } } +void Widget::backRequested() { + if (_stepHistory.size() > 1) { + historyMove(StackAction::Back, Animate::Back); + } else if (const auto parent + = Core::App().domain().maybeLastOrSomeAuthedAccount()) { + Core::App().domain().activate(parent); + } else { + moveToStep( + new StartWidget(this, _account, getData()), + StackAction::Replace, + Animate::Back); + } +} + Widget::~Widget() { for (auto step : base::take(_stepHistory)) { delete step; diff --git a/Telegram/SourceFiles/intro/intro_widget.h b/Telegram/SourceFiles/intro/intro_widget.h index 978bfc812..c4b618eb4 100644 --- a/Telegram/SourceFiles/intro/intro_widget.h +++ b/Telegram/SourceFiles/intro/intro_widget.h @@ -62,19 +62,33 @@ struct Data { }; -enum class Direction { +enum class StackAction { Back, Forward, Replace, }; +enum class Animate { + Back, + Forward, +}; + class Step; } // namespace details +enum class EnterPoint : uchar { + Start, + Phone, + Qr, +}; + class Widget : public Ui::RpWidget, private base::Subscriber { public: - Widget(QWidget *parent, not_null account); + Widget( + QWidget *parent, + not_null account, + EnterPoint point); void showAnimated(const QPixmap &bgAnimCache, bool back = false); @@ -95,6 +109,7 @@ private: void setupNextButton(); void handleUpdates(const MTPUpdates &updates); void handleUpdate(const MTPUpdate &update); + void backRequested(); void updateControlsGeometry(); [[nodiscard]] not_null getData() { @@ -118,8 +133,11 @@ private: return _stepHistory[_stepHistory.size() - skip - 1]; } - void historyMove(details::Direction direction); - void moveToStep(details::Step *step, details::Direction direction); + void historyMove(details::StackAction action, details::Animate animate); + void moveToStep( + details::Step *step, + details::StackAction action, + details::Animate animate); void appendStep(details::Step *step); void getNearestDC(); diff --git a/Telegram/SourceFiles/main/main_domain.cpp b/Telegram/SourceFiles/main/main_domain.cpp index a8db8e4e3..7ca6b64ed 100644 --- a/Telegram/SourceFiles/main/main_domain.cpp +++ b/Telegram/SourceFiles/main/main_domain.cpp @@ -103,6 +103,20 @@ rpl::producer<> Domain::accountsChanges() const { return _accountsChanges.events(); } +Account *Domain::maybeLastOrSomeAuthedAccount() { + auto result = (Account*)nullptr; + for (const auto &[index, account] : _accounts) { + if (!account->sessionExists()) { + continue; + } else if (index == _lastActiveIndex) { + return account.get(); + } else if (!result) { + result = account.get(); + } + } + return result; +} + rpl::producer Domain::activeValue() const { return _active.value(); } @@ -114,6 +128,8 @@ Account &Domain::active() const { return *_active.current(); } + + rpl::producer> Domain::activeChanges() const { return _active.changes() | rpl::map([](Account *value) { return not_null{ value }; @@ -316,6 +332,9 @@ void Domain::activate(not_null account) { const auto changed = (_accountToActivate != i->index); _activeLifetime.destroy(); + if (_active.current()) { + _lastActiveIndex = _accountToActivate; + } _accountToActivate = i->index; _active = account.get(); _active.current()->sessionValue( diff --git a/Telegram/SourceFiles/main/main_domain.h b/Telegram/SourceFiles/main/main_domain.h index aa7a9e0e4..587299552 100644 --- a/Telegram/SourceFiles/main/main_domain.h +++ b/Telegram/SourceFiles/main/main_domain.h @@ -48,6 +48,7 @@ public: -> const std::vector &; [[nodiscard]] rpl::producer activeValue() const; [[nodiscard]] rpl::producer<> accountsChanges() const; + [[nodiscard]] Account *maybeLastOrSomeAuthedAccount(); // Expects(started()); [[nodiscard]] Account &active() const; @@ -87,6 +88,7 @@ private: rpl::event_stream<> _accountsChanges; rpl::variable _active = nullptr; int _accountToActivate = -1; + int _lastActiveIndex = -1; bool _writeAccountsScheduled = false; rpl::event_stream _activeSessions; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 12d9b4453..c36afaeb4 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -257,12 +257,12 @@ void MainWindow::clearPasscodeLock() { } } -void MainWindow::setupIntro() { +void MainWindow::setupIntro(Intro::EnterPoint point) { auto animated = (_main || _passcodeLock); auto bg = animated ? grabInner() : QPixmap(); clearWidgets(); - _intro.create(bodyWidget(), &account()); + _intro.create(bodyWidget(), &account(), point); if (_passcodeLock) { _intro->hide(); } else { diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index f0338935c..be8006a8c 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -17,6 +17,7 @@ class MainWidget; namespace Intro { class Widget; +enum class EnterPoint : uchar; } // namespace Intro namespace Local { @@ -53,7 +54,7 @@ public: void setupPasscodeLock(); void clearPasscodeLock(); - void setupIntro(); + void setupIntro(Intro::EnterPoint point); void setupMain(); MainWidget *sessionContent() const; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 26576a73f..f03b2a026 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_domain.h" #include "main/main_session.h" #include "main/main_session_settings.h" +#include "main/main_app_config.h" +#include "intro/intro_widget.h" #include "mtproto/mtproto_config.h" #include "ui/layers/box_content.h" #include "ui/layers/layer_widget.h" @@ -100,7 +102,17 @@ void Controller::clearPasscodeLock() { } void Controller::setupIntro() { - _widget.setupIntro(); + const auto parent = Core::App().domain().maybeLastOrSomeAuthedAccount(); + if (!parent) { + _widget.setupIntro(Intro::EnterPoint::Start); + return; + } + const auto qrLogin = parent->appConfig().get( + "qr_login_code", + "[not-set]"); + DEBUG_LOG(("qr_login_code in setup: %1").arg(qrLogin)); + const auto qr = (qrLogin == "primary"); + _widget.setupIntro(qr ? Intro::EnterPoint::Qr : Intro::EnterPoint::Phone); } void Controller::setupMain() { diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index ba5cfb6e8..d194c7fa9 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -115,7 +115,7 @@ private: class MainMenu::ToggleAccountsButton final : public Ui::AbstractButton { public: - ToggleAccountsButton(QWidget *parent, rpl::producer toggled); + explicit ToggleAccountsButton(QWidget *parent); [[nodiscard]] int rightSkip() const { return _rightSkip.current(); @@ -274,9 +274,7 @@ void MainMenu::AccountButton::paintEvent(QPaintEvent *e) { available); } -MainMenu::ToggleAccountsButton::ToggleAccountsButton( - QWidget *parent, - rpl::producer toggled) +MainMenu::ToggleAccountsButton::ToggleAccountsButton(QWidget *parent) : AbstractButton(parent) { rpl::single( rpl::empty_value() @@ -290,8 +288,12 @@ MainMenu::ToggleAccountsButton::ToggleAccountsButton( } }, lifetime()); - std::move( - toggled + auto &settings = Core::App().settings(); + if (Core::App().domain().accounts().size() < 2 + && settings.mainMenuAccountsShown()) { + settings.setMainMenuAccountsShown(false); + } + settings.mainMenuAccountsShownValue( ) | rpl::filter([=](bool value) { return (_toggled != value); }) | rpl::start_with_next([=](bool value) { @@ -481,7 +483,7 @@ MainMenu::MainMenu( _controller->session().user(), Ui::UserpicButton::Role::Custom, st::mainMenuUserpic) -, _toggleAccounts(this, Core::App().settings().mainMenuAccountsShownValue()) +, _toggleAccounts(this) , _archiveButton(this, st::mainMenuCloudButton) , _scroll(this, st::defaultSolidScroll) , _inner(_scroll->setOwnedWidget( @@ -506,8 +508,8 @@ MainMenu::MainMenu( setupArchiveButton(); setupUserpicButton(); - setupAccounts(); setupAccountsToggle(); + setupAccounts(); _nightThemeSwitch.setCallback([this] { if (const auto action = *_nightThemeAction) { @@ -671,6 +673,7 @@ void MainMenu::setupAccounts() { rebuildAccounts(); }, lifetime()); + _accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue()); _accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue()); _accounts->finishAnimating(); @@ -798,12 +801,8 @@ void MainMenu::setupAccountsToggle() { auto &settings = Core::App().settings(); const auto shown = !settings.mainMenuAccountsShown(); settings.setMainMenuAccountsShown(shown); + Core::App().saveSettingsDelayed(); }); - _toggleAccounts->paintRequest( - ) | rpl::start_with_next([=] { - auto p = Painter(_toggleAccounts.data()); - - }, _toggleAccounts->lifetime()); } void MainMenu::parentResized() {