2019-06-06 11:20:21 +00:00
|
|
|
/*
|
|
|
|
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 "window/window_controller.h"
|
|
|
|
|
2020-06-25 11:54:14 +00:00
|
|
|
#include "api/api_updates.h"
|
2019-06-06 11:20:21 +00:00
|
|
|
#include "core/application.h"
|
2020-06-24 07:56:16 +00:00
|
|
|
#include "core/click_handler_types.h"
|
2021-02-03 02:49:26 +00:00
|
|
|
#include "export/export_manager.h"
|
2020-07-07 13:54:39 +00:00
|
|
|
#include "platform/platform_window_title.h"
|
2019-06-06 11:20:21 +00:00
|
|
|
#include "main/main_account.h"
|
2020-06-18 18:04:16 +00:00
|
|
|
#include "main/main_domain.h"
|
2020-03-18 12:14:45 +00:00
|
|
|
#include "main/main_session.h"
|
2020-06-18 18:04:16 +00:00
|
|
|
#include "main/main_session_settings.h"
|
2020-06-23 14:55:08 +00:00
|
|
|
#include "main/main_app_config.h"
|
|
|
|
#include "intro/intro_widget.h"
|
2020-06-17 09:36:25 +00:00
|
|
|
#include "mtproto/mtproto_config.h"
|
2019-09-18 11:19:05 +00:00
|
|
|
#include "ui/layers/box_content.h"
|
|
|
|
#include "ui/layers/layer_widget.h"
|
2020-03-13 06:56:03 +00:00
|
|
|
#include "ui/toast/toast.h"
|
2020-05-07 15:06:44 +00:00
|
|
|
#include "ui/emoji_config.h"
|
|
|
|
#include "chat_helpers/emoji_sets_manager.h"
|
2019-06-06 11:20:21 +00:00
|
|
|
#include "window/window_session_controller.h"
|
2019-09-02 16:10:18 +00:00
|
|
|
#include "window/themes/window_theme.h"
|
|
|
|
#include "window/themes/window_theme_editor.h"
|
2020-06-24 07:56:16 +00:00
|
|
|
#include "boxes/confirm_box.h"
|
2019-06-06 11:20:21 +00:00
|
|
|
#include "mainwindow.h"
|
2020-06-24 07:56:16 +00:00
|
|
|
#include "apiwrap.h" // ApiWrap::acceptTerms.
|
2019-09-13 06:06:02 +00:00
|
|
|
#include "facades.h"
|
|
|
|
#include "app.h"
|
2020-06-24 07:56:16 +00:00
|
|
|
#include "styles/style_layers.h"
|
2019-06-06 11:20:21 +00:00
|
|
|
|
2019-09-04 07:19:15 +00:00
|
|
|
#include <QtGui/QWindow>
|
|
|
|
#include <QtGui/QScreen>
|
|
|
|
|
2019-06-06 11:20:21 +00:00
|
|
|
namespace Window {
|
|
|
|
|
2020-06-15 16:25:02 +00:00
|
|
|
Controller::Controller()
|
2020-06-17 09:36:25 +00:00
|
|
|
: _widget(this)
|
|
|
|
, _isActiveTimer([=] { updateIsActive(); }) {
|
2020-06-15 16:25:02 +00:00
|
|
|
_widget.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
Controller::~Controller() {
|
|
|
|
// We want to delete all widgets before the _sessionController.
|
2020-06-29 12:11:34 +00:00
|
|
|
_widget.ui_hideSettingsAndLayer(anim::type::instant);
|
2020-06-15 16:25:02 +00:00
|
|
|
_widget.clearWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::showAccount(not_null<Main::Account*> account) {
|
2020-07-15 15:37:25 +00:00
|
|
|
const auto prevSessionUniqueId = (_account && _account->sessionExists())
|
|
|
|
? _account->session().uniqueId()
|
|
|
|
: 0;
|
2020-06-15 16:25:02 +00:00
|
|
|
_accountLifetime.destroy();
|
|
|
|
_account = account;
|
|
|
|
|
2020-07-15 15:37:25 +00:00
|
|
|
const auto updateOnlineOfPrevSesssion = crl::guard(_account, [=] {
|
|
|
|
if (!prevSessionUniqueId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (auto &[index, account] : _account->domain().accounts()) {
|
|
|
|
if (const auto anotherSession = account->maybeSession()) {
|
|
|
|
if (anotherSession->uniqueId() == prevSessionUniqueId) {
|
|
|
|
anotherSession->updates().updateOnline();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-06-06 11:59:00 +00:00
|
|
|
_account->sessionValue(
|
2020-06-15 16:25:02 +00:00
|
|
|
) | rpl::start_with_next([=](Main::Session *session) {
|
2020-06-16 06:42:47 +00:00
|
|
|
const auto was = base::take(_sessionController);
|
2019-06-06 11:20:21 +00:00
|
|
|
_sessionController = session
|
2019-09-03 15:24:51 +00:00
|
|
|
? std::make_unique<SessionController>(session, this)
|
2019-06-06 11:20:21 +00:00
|
|
|
: nullptr;
|
2020-03-18 12:14:45 +00:00
|
|
|
if (_sessionController) {
|
|
|
|
_sessionController->filtersMenuChanged(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
sideBarChanged();
|
|
|
|
}, session->lifetime());
|
|
|
|
}
|
2020-06-18 18:04:16 +00:00
|
|
|
if (session && session->settings().dialogsFiltersEnabled()) {
|
2020-03-03 12:07:22 +00:00
|
|
|
_sessionController->toggleFiltersMenu(true);
|
|
|
|
} else {
|
|
|
|
sideBarChanged();
|
|
|
|
}
|
2019-06-06 11:20:21 +00:00
|
|
|
_widget.updateWindowIcon();
|
2020-06-15 16:25:02 +00:00
|
|
|
if (session) {
|
|
|
|
setupMain();
|
2020-06-24 07:56:16 +00:00
|
|
|
|
|
|
|
session->termsLockValue(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
checkLockByTerms();
|
|
|
|
_widget.updateGlobalMenu();
|
|
|
|
}, _lifetime);
|
2020-06-15 16:25:02 +00:00
|
|
|
} else {
|
|
|
|
setupIntro();
|
2020-06-24 07:56:16 +00:00
|
|
|
_widget.updateGlobalMenu();
|
2020-06-15 16:25:02 +00:00
|
|
|
}
|
2020-07-15 15:37:25 +00:00
|
|
|
|
|
|
|
crl::on_main(updateOnlineOfPrevSesssion);
|
2020-06-16 09:40:43 +00:00
|
|
|
}, _accountLifetime);
|
2019-08-16 12:44:20 +00:00
|
|
|
}
|
2019-06-06 11:20:21 +00:00
|
|
|
|
2020-06-24 07:56:16 +00:00
|
|
|
void Controller::checkLockByTerms() {
|
|
|
|
const auto data = account().sessionExists()
|
|
|
|
? account().session().termsLocked()
|
|
|
|
: std::nullopt;
|
|
|
|
if (!data) {
|
|
|
|
if (_termsBox) {
|
|
|
|
_termsBox->closeBox();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Ui::hideSettingsAndLayer(anim::type::instant);
|
|
|
|
const auto box = Ui::show(Box<TermsBox>(
|
|
|
|
*data,
|
|
|
|
tr::lng_terms_agree(),
|
|
|
|
tr::lng_terms_decline()));
|
|
|
|
|
|
|
|
box->setCloseByEscape(false);
|
|
|
|
box->setCloseByOutsideClick(false);
|
|
|
|
|
|
|
|
const auto id = data->id;
|
|
|
|
box->agreeClicks(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
const auto mention = box ? box->lastClickedMention() : QString();
|
|
|
|
box->closeBox();
|
|
|
|
if (const auto session = account().maybeSession()) {
|
|
|
|
session->api().acceptTerms(id);
|
|
|
|
session->unlockTerms();
|
|
|
|
if (!mention.isEmpty()) {
|
|
|
|
MentionClickHandler(mention).onClick({});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, box->lifetime());
|
|
|
|
|
|
|
|
box->cancelClicks(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
showTermsDecline();
|
|
|
|
}, box->lifetime());
|
|
|
|
|
|
|
|
QObject::connect(box, &QObject::destroyed, [=] {
|
|
|
|
crl::on_main(widget(), [=] { checkLockByTerms(); });
|
|
|
|
});
|
|
|
|
|
|
|
|
_termsBox = box;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::showTermsDecline() {
|
|
|
|
const auto box = Ui::show(
|
|
|
|
Box<Window::TermsBox>(
|
|
|
|
TextWithEntities{ tr::lng_terms_update_sorry(tr::now) },
|
|
|
|
tr::lng_terms_decline_and_delete(),
|
|
|
|
tr::lng_terms_back(),
|
|
|
|
true),
|
|
|
|
Ui::LayerOption::KeepOther);
|
|
|
|
|
|
|
|
box->agreeClicks(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
if (box) {
|
|
|
|
box->closeBox();
|
|
|
|
}
|
|
|
|
showTermsDelete();
|
|
|
|
}, box->lifetime());
|
|
|
|
|
|
|
|
box->cancelClicks(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
if (box) {
|
|
|
|
box->closeBox();
|
|
|
|
}
|
|
|
|
}, box->lifetime());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::showTermsDelete() {
|
|
|
|
const auto deleteByTerms = [=] {
|
|
|
|
if (const auto session = account().maybeSession()) {
|
|
|
|
session->termsDeleteNow();
|
|
|
|
} else {
|
|
|
|
Ui::hideLayer();
|
|
|
|
}
|
|
|
|
};
|
2020-09-24 12:48:02 +00:00
|
|
|
Ui::show(
|
2020-06-24 07:56:16 +00:00
|
|
|
Box<ConfirmBox>(
|
|
|
|
tr::lng_terms_delete_warning(tr::now),
|
|
|
|
tr::lng_terms_delete_now(tr::now),
|
|
|
|
st::attentionBoxButton,
|
2020-09-24 12:48:02 +00:00
|
|
|
deleteByTerms),
|
2020-06-24 07:56:16 +00:00
|
|
|
Ui::LayerOption::KeepOther);
|
|
|
|
}
|
|
|
|
|
2020-02-12 08:09:17 +00:00
|
|
|
void Controller::finishFirstShow() {
|
|
|
|
_widget.finishFirstShow();
|
2019-09-02 16:10:18 +00:00
|
|
|
checkThemeEditor();
|
|
|
|
}
|
|
|
|
|
2020-06-24 07:56:16 +00:00
|
|
|
bool Controller::locked() const {
|
|
|
|
if (Core::App().passcodeLocked()) {
|
|
|
|
return true;
|
|
|
|
} else if (const auto controller = sessionController()) {
|
|
|
|
return controller->session().termsLocked().has_value();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-02 16:10:18 +00:00
|
|
|
void Controller::checkThemeEditor() {
|
2019-09-05 10:51:36 +00:00
|
|
|
using namespace Window::Theme;
|
2019-09-05 20:21:44 +00:00
|
|
|
|
|
|
|
if (const auto editing = Background()->editingTheme()) {
|
|
|
|
showRightColumn(Box<Editor>(this, *editing));
|
2019-09-02 16:10:18 +00:00
|
|
|
}
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::setupPasscodeLock() {
|
|
|
|
_widget.setupPasscodeLock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::clearPasscodeLock() {
|
2020-06-15 16:25:02 +00:00
|
|
|
if (!_account) {
|
|
|
|
showAccount(&Core::App().activeAccount());
|
|
|
|
} else {
|
|
|
|
_widget.clearPasscodeLock();
|
|
|
|
}
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::setupIntro() {
|
2020-06-23 14:55:08 +00:00
|
|
|
const auto parent = Core::App().domain().maybeLastOrSomeAuthedAccount();
|
|
|
|
if (!parent) {
|
|
|
|
_widget.setupIntro(Intro::EnterPoint::Start);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto qrLogin = parent->appConfig().get<QString>(
|
|
|
|
"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);
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::setupMain() {
|
2020-06-15 16:25:02 +00:00
|
|
|
Expects(_sessionController != nullptr);
|
2020-06-10 10:49:10 +00:00
|
|
|
|
2019-06-06 11:20:21 +00:00
|
|
|
_widget.setupMain();
|
2020-05-07 15:06:44 +00:00
|
|
|
|
|
|
|
if (const auto id = Ui::Emoji::NeedToSwitchBackToId()) {
|
2020-06-15 16:25:02 +00:00
|
|
|
Ui::Emoji::LoadAndSwitchTo(&_sessionController->session(), id);
|
2020-05-07 15:06:44 +00:00
|
|
|
}
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::showSettings() {
|
|
|
|
_widget.showSettings();
|
|
|
|
}
|
|
|
|
|
2020-07-07 13:54:39 +00:00
|
|
|
int Controller::verticalShadowTop() const {
|
|
|
|
return (Platform::NativeTitleRequiresShadow()
|
2021-02-20 18:06:00 +00:00
|
|
|
&& Platform::AllowNativeWindowFrameToggle()
|
2020-07-07 13:54:39 +00:00
|
|
|
&& Core::App().settings().nativeWindowFrame())
|
|
|
|
? st::lineWidth
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
|
2020-03-13 06:56:03 +00:00
|
|
|
void Controller::showToast(const QString &text) {
|
|
|
|
Ui::Toast::Show(_widget.bodyWidget(), text);
|
|
|
|
}
|
|
|
|
|
2019-06-10 14:58:45 +00:00
|
|
|
void Controller::showBox(
|
2019-09-18 11:19:05 +00:00
|
|
|
object_ptr<Ui::BoxContent> content,
|
|
|
|
Ui::LayerOptions options,
|
2019-06-10 14:58:45 +00:00
|
|
|
anim::type animated) {
|
|
|
|
_widget.ui_showBox(std::move(content), options, animated);
|
|
|
|
}
|
|
|
|
|
2019-09-03 08:25:19 +00:00
|
|
|
void Controller::showRightColumn(object_ptr<TWidget> widget) {
|
|
|
|
_widget.showRightColumn(std::move(widget));
|
|
|
|
}
|
|
|
|
|
2020-03-03 12:07:22 +00:00
|
|
|
void Controller::sideBarChanged() {
|
2020-07-07 13:54:39 +00:00
|
|
|
_widget.recountGeometryConstraints();
|
2020-03-03 12:07:22 +00:00
|
|
|
}
|
|
|
|
|
2019-06-06 11:20:21 +00:00
|
|
|
void Controller::activate() {
|
|
|
|
_widget.activate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::reActivate() {
|
|
|
|
_widget.reActivateWindow();
|
|
|
|
}
|
|
|
|
|
2020-06-17 09:36:25 +00:00
|
|
|
void Controller::updateIsActiveFocus() {
|
|
|
|
_isActiveTimer.callOnce(sessionController()
|
|
|
|
? sessionController()->session().serverConfig().onlineFocusTimeout
|
|
|
|
: crl::time(1000));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::updateIsActiveBlur() {
|
|
|
|
_isActiveTimer.callOnce(sessionController()
|
|
|
|
? sessionController()->session().serverConfig().offlineBlurTimeout
|
|
|
|
: crl::time(1000));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::updateIsActive() {
|
|
|
|
_widget.updateIsActive();
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::minimize() {
|
|
|
|
if (Global::WorkMode().value() == dbiwmTrayOnly) {
|
|
|
|
_widget.minimizeToTray();
|
|
|
|
} else {
|
2020-01-02 11:57:36 +00:00
|
|
|
_widget.setWindowState(_widget.windowState() | Qt::WindowMinimized);
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Controller::close() {
|
2020-06-29 16:03:37 +00:00
|
|
|
_widget.close();
|
2019-06-06 11:20:21 +00:00
|
|
|
}
|
|
|
|
|
2020-12-13 13:08:16 +00:00
|
|
|
void Controller::preventOrInvoke(Fn<void()> &&callback) {
|
|
|
|
_widget.preventOrInvoke(std::move(callback));
|
|
|
|
}
|
|
|
|
|
2019-06-06 11:20:21 +00:00
|
|
|
QPoint Controller::getPointForCallPanelCenter() const {
|
|
|
|
Expects(_widget.windowHandle() != nullptr);
|
|
|
|
|
|
|
|
return _widget.isActive()
|
|
|
|
? _widget.geometry().center()
|
|
|
|
: _widget.windowHandle()->screen()->geometry().center();
|
|
|
|
}
|
|
|
|
|
2021-02-03 02:49:26 +00:00
|
|
|
void Controller::showLogoutConfirmation() {
|
|
|
|
const auto account = Core::App().passcodeLocked()
|
|
|
|
? nullptr
|
|
|
|
: sessionController()
|
|
|
|
? &sessionController()->session().account()
|
|
|
|
: nullptr;
|
|
|
|
const auto weak = base::make_weak(account);
|
|
|
|
const auto callback = [=] {
|
|
|
|
if (account && !weak) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (account
|
|
|
|
&& account->sessionExists()
|
|
|
|
&& Core::App().exportManager().inProgress(&account->session())) {
|
|
|
|
Ui::hideLayer();
|
|
|
|
Core::App().exportManager().stopWithConfirmation([=] {
|
|
|
|
Core::App().logout(account);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
Core::App().logout(account);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
show(Box<ConfirmBox>(
|
|
|
|
tr::lng_sure_logout(tr::now),
|
|
|
|
tr::lng_settings_logout(tr::now),
|
|
|
|
st::attentionBoxButton,
|
|
|
|
callback));
|
|
|
|
}
|
|
|
|
|
2019-06-06 11:20:21 +00:00
|
|
|
} // namespace Window
|