diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 83e139746..b1bff342c 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "lang.h" #include "application.h" #include "mainwindow.h" +#include "messenger.h" #include "mainwidget.h" #include "historywidget.h" #include "storage/localstorage.h" @@ -46,8 +47,7 @@ constexpr auto kSmallDelayMs = 5; ApiWrap::ApiWrap() : _messageDataResolveDelayed([this] { resolveMessageDatas(); }) , _webPagesTimer([this] { resolveWebPages(); }) -, _draftsSaveTimer([this] { saveDraftsToCloud(); }) -, _quitSavingDraftsTimer([] { App::allDraftsSaved(); }) { +, _draftsSaveTimer([this] { saveDraftsToCloud(); }) { Window::Theme::Background()->start(); } @@ -985,10 +985,6 @@ void ApiWrap::saveDraftToCloudDelayed(History *history) { } } -bool ApiWrap::hasUnsavedDrafts() const { - return !_draftsSaveRequestIds.isEmpty(); -} - void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector &&rules) { auto keyTypeId = key.type(); auto it = _privacySaveRequests.find(keyTypeId); @@ -1144,9 +1140,7 @@ void ApiWrap::saveDraftsToCloud() { auto i = _draftsSaveRequestIds.find(history); if (i != _draftsSaveRequestIds.cend() && i.value() == requestId) { _draftsSaveRequestIds.remove(history); - if (_draftsSaveRequestIds.isEmpty()) { - App::allDraftsSaved(); // can quit the application - } + checkQuitPreventFinished(); } }).fail([this, history](const RPCError &error, mtpRequestId requestId) { if (auto cloudDraft = history->cloudDraft()) { @@ -1157,18 +1151,29 @@ void ApiWrap::saveDraftsToCloud() { auto i = _draftsSaveRequestIds.find(history); if (i != _draftsSaveRequestIds.cend() && i.value() == requestId) { _draftsSaveRequestIds.remove(history); - if (_draftsSaveRequestIds.isEmpty()) { - App::allDraftsSaved(); // can quit the application - } + checkQuitPreventFinished(); } }).send(); i.value() = cloudDraft->saveRequestId; } +} + +bool ApiWrap::isQuitPrevent() { if (_draftsSaveRequestIds.isEmpty()) { - App::allDraftsSaved(); // can quit the application - } else if (App::quitting() && !_quitSavingDraftsTimer.isActive()) { - _quitSavingDraftsTimer.callOnce(kSaveDraftBeforeQuitTimeout); + return false; + } + LOG(("ApiWrap prevents quit, saving drafts...")); + saveDraftsToCloud(); + return true; +} + +void ApiWrap::checkQuitPreventFinished() { + if (_draftsSaveRequestIds.isEmpty()) { + if (App::quitting()) { + LOG(("ApiWrap doesn't prevent quit any more.")); + } + Messenger::Instance().quitPreventFinished(); } } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 355d9abfd..390627ec0 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -74,9 +74,7 @@ public: void exportInviteLink(PeerData *peer); void requestNotifySetting(PeerData *peer); - void saveDraftsToCloud(); void saveDraftToCloudDelayed(History *history); - bool hasUnsavedDrafts() const; void savePrivacy(const MTPInputPrivacyKey &key, QVector &&rules); void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector &rules); @@ -86,6 +84,8 @@ public: return _fullPeerUpdated; } + bool isQuitPrevent(); + ~ApiWrap(); private: @@ -97,6 +97,9 @@ private: using MessageDataRequests = QMap; void updatesReceived(const MTPUpdates &updates); + void checkQuitPreventFinished(); + + void saveDraftsToCloud(); void resolveMessageDatas(); void gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId requestId); @@ -147,7 +150,6 @@ private: QMap _draftsSaveRequestIds; base::Timer _draftsSaveTimer; - base::Timer _quitSavingDraftsTimer; OrderedSet _stickerSetDisenableRequests; Stickers::Order _stickersOrder; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index f74da841d..fec4807a8 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -2463,25 +2463,13 @@ namespace { if (auto mainwidget = main()) { mainwidget->saveDraftToCloud(); } - if (auto apiwrap = api()) { - if (apiwrap->hasUnsavedDrafts()) { - apiwrap->saveDraftsToCloud(); - return; - } - } - QCoreApplication::quit(); + Messenger::QuitAttempt(); } bool quitting() { return _launchState != Launched; } - void allDraftsSaved() { - if (quitting()) { - QCoreApplication::quit(); - } - } - LaunchState launchState() { return _launchState; } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 96150950c..cfb5c5783 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -234,7 +234,6 @@ namespace App { }; void quit(); bool quitting(); - void allDraftsSaved(); LaunchState launchState(); void setLaunchState(LaunchState state); void restart(); diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index d3364b146..220434176 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "calls/calls_instance.h" #include "mtproto/connection.h" +#include "messenger.h" #include "auth_session.h" #include "apiwrap.h" #include "lang.h" @@ -70,6 +71,11 @@ void Instance::destroyCall(gsl::not_null call) { _currentCallPanel.reset(); _currentCall.reset(); _currentCallChanged.notify(nullptr, true); + + if (App::quitting()) { + LOG(("Calls::Instance doesn't prevent quit any more.")); + } + Messenger::Instance().quitPreventFinished(); } } @@ -201,6 +207,18 @@ void Instance::showInfoPanel(gsl::not_null call) { } } +bool Instance::isQuitPrevent() { + if (!_currentCall) { + return false; + } + _currentCall->hangup(); + if (!_currentCall) { + return false; + } + LOG(("Calls::Instance prevents quit, saving drafts...")); + return true; +} + void Instance::handleCallUpdate(const MTPPhoneCall &call) { if (call.type() == mtpc_phoneCallRequested) { auto &phoneCall = call.c_phoneCallRequested(); diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index d305b7ac7..ba0be1c9d 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -43,6 +43,8 @@ public: return _newServiceMessage; } + bool isQuitPrevent(); + ~Instance(); private: diff --git a/Telegram/SourceFiles/messenger.cpp b/Telegram/SourceFiles/messenger.cpp index 5c6425b96..ed23bdf62 100644 --- a/Telegram/SourceFiles/messenger.cpp +++ b/Telegram/SourceFiles/messenger.cpp @@ -20,12 +20,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "messenger.h" +#include "base/timer.h" #include "storage/localstorage.h" #include "platform/platform_specific.h" #include "mainwindow.h" #include "application.h" #include "shortcuts.h" #include "auth_session.h" +#include "apiwrap.h" +#include "calls/calls_instance.h" #include "langloaderplain.h" #include "observer_peer.h" #include "storage/file_upload.h" @@ -42,6 +45,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace { +constexpr auto kQuitPreventTimeoutMs = 1500; + Messenger *SingleInstance = nullptr; } // namespace @@ -55,6 +60,7 @@ struct Messenger::Private { std::unique_ptr storedAuthSession; MTP::Instance::Config mtpConfig; MTP::AuthKeysList mtpKeysToDestroy; + base::Timer quitTimer; }; Messenger::Messenger() : QObject() @@ -791,3 +797,33 @@ QPoint Messenger::getPointForCallPanelCenter() const { } return _window->windowHandle()->screen()->geometry().center(); } + +void Messenger::QuitAttempt() { + auto prevents = false; + if (!Sandbox::isSavingSession() && AuthSession::Exists()) { + if (AuthSession::Current().api().isQuitPrevent()) { + prevents = true; + } + if (AuthSession::Current().calls().isQuitPrevent()) { + prevents = true; + } + } + if (prevents) { + Instance().quitDelayed(); + } else { + QCoreApplication::quit(); + } +} + +void Messenger::quitPreventFinished() { + if (App::quitting()) { + QuitAttempt(); + } +} + +void Messenger::quitDelayed() { + if (!_private->quitTimer.isActive()) { + _private->quitTimer.setCallback([] { QCoreApplication::quit(); }); + _private->quitTimer.callOnce(kQuitPreventTimeoutMs); + } +} diff --git a/Telegram/SourceFiles/messenger.h b/Telegram/SourceFiles/messenger.h index a4ea8032e..63c49a3f8 100644 --- a/Telegram/SourceFiles/messenger.h +++ b/Telegram/SourceFiles/messenger.h @@ -22,6 +22,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "base/observer.h" +namespace App { +void quit(); +} // namespace App + namespace MTP { class DcOptions; class Instance; @@ -120,6 +124,8 @@ public: return _passcodedChanged; } + void quitPreventFinished(); + void handleAppActivated(); void handleAppDeactivated(); @@ -149,6 +155,10 @@ private: void startLocalStorage(); void loadLanguage(); + friend void App::quit(); + static void QuitAttempt(); + void quitDelayed(); + QMap photoUpdates; QMap killDownloadSessionTimes;