Replace SingleTimer with base::Timer.

This commit is contained in:
John Preston 2019-01-18 15:26:43 +04:00
parent 61b9a32504
commit 314e30272b
66 changed files with 448 additions and 511 deletions

View File

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h" #include "base/timer.h"
#include "base/flat_map.h" #include "base/flat_map.h"
#include "base/flat_set.h" #include "base/flat_set.h"
#include "core/single_timer.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "data/data_messages.h" #include "data/data_messages.h"

View File

@ -810,7 +810,7 @@ namespace App {
setLaunchState(QuitRequested); setLaunchState(QuitRequested);
if (auto window = App::wnd()) { if (auto window = App::wnd()) {
if (!Sandbox::isSavingSession()) { if (!Core::App().isSavingSession()) {
window->hide(); window->hide();
} }
} }

View File

@ -510,39 +510,8 @@ void Application::closeApplication() {
_updateChecker = nullptr; _updateChecker = nullptr;
} }
inline Application *application() {
return qobject_cast<Application*>(QApplication::instance());
}
namespace Sandbox { namespace Sandbox {
QRect availableGeometry() {
if (auto a = application()) {
return a->desktop()->availableGeometry();
}
return QDesktopWidget().availableGeometry();
}
QRect screenGeometry(const QPoint &p) {
if (auto a = application()) {
return a->desktop()->screenGeometry(p);
}
return QDesktopWidget().screenGeometry(p);
}
void setActiveWindow(QWidget *window) {
if (auto a = application()) {
a->setActiveWindow(window);
}
}
bool isSavingSession() {
if (auto a = application()) {
return a->isSavingSession();
}
return false;
}
void execExternal(const QString &cmd) { void execExternal(const QString &cmd) {
DEBUG_LOG(("Application Info: executing external command '%1'").arg(cmd)); DEBUG_LOG(("Application Info: executing external command '%1'").arg(cmd));
if (cmd == "show") { if (cmd == "show") {
@ -554,23 +523,7 @@ void execExternal(const QString &cmd) {
} }
} }
void adjustSingleTimers() {
if (auto a = application()) {
a->adjustSingleTimers();
}
base::Timer::Adjust();
base::ConcurrentTimerEnvironment::Adjust();
}
void connect(const char *signal, QObject *object, const char *method) {
if (auto a = application()) {
a->connect(a, signal, object, method);
}
}
void launch() { void launch() {
Assert(application() != 0);
const auto dpi = Application::primaryScreen()->logicalDotsPerInch(); const auto dpi = Application::primaryScreen()->logicalDotsPerInch();
LOG(("Primary screen DPI: %1").arg(dpi)); LOG(("Primary screen DPI: %1").arg(dpi));
if (dpi <= 108) { if (dpi <= 108) {
@ -587,7 +540,7 @@ void launch() {
cSetScreenScale(300); // 300%: 288 DPI (264-inf) cSetScreenScale(300); // 300%: 288 DPI (264-inf)
} }
auto devicePixelRatio = application()->devicePixelRatio(); auto devicePixelRatio = Core::App().devicePixelRatio();
if (devicePixelRatio > 1.) { if (devicePixelRatio > 1.) {
if ((cPlatform() != dbipMac && cPlatform() != dbipMacOld) || (devicePixelRatio != 2.)) { if ((cPlatform() != dbipMac && cPlatform() != dbipMacOld) || (devicePixelRatio != 2.)) {
LOG(("Found non-trivial Device Pixel Ratio: %1").arg(devicePixelRatio)); LOG(("Found non-trivial Device Pixel Ratio: %1").arg(devicePixelRatio));
@ -601,13 +554,7 @@ void launch() {
cSetScreenScale(kInterfaceScaleDefault); cSetScreenScale(kInterfaceScaleDefault);
} }
application()->createMessenger(); Core::App().createMessenger();
}
void refreshGlobalProxy() {
if (const auto instance = application()) {
instance->refreshGlobalProxy();
}
} }
} // namespace Sandbox } // namespace Sandbox

View File

@ -40,9 +40,6 @@ public:
~Application(); ~Application();
signals:
void adjustSingleTimers();
// Single instance application // Single instance application
public slots: public slots:
void socketConnected(); void socketConnected();
@ -115,19 +112,7 @@ inline Application &App() {
namespace Sandbox { namespace Sandbox {
QRect availableGeometry();
QRect screenGeometry(const QPoint &p);
void setActiveWindow(QWidget *window);
bool isSavingSession();
void execExternal(const QString &cmd); void execExternal(const QString &cmd);
void adjustSingleTimers();
void refreshGlobalProxy();
void connect(const char *signal, QObject *object, const char *method);
void launch(); void launch();
} // namespace Sandbox } // namespace Sandbox

View File

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "application.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -70,7 +69,7 @@ void AboutBox::showVersionHistory() {
} }
url = url.arg(qsl("talpha%1_%2").arg(cRealAlphaVersion()).arg(Core::countAlphaVersionSignature(cRealAlphaVersion()))); url = url.arg(qsl("talpha%1_%2").arg(cRealAlphaVersion()).arg(Core::countAlphaVersionSignature(cRealAlphaVersion())));
Application::clipboard()->setText(url); QApplication::clipboard()->setText(url);
Ui::show(Box<InformBox>("The link to the current private alpha version of Telegram Desktop was copied to the clipboard.")); Ui::show(Box<InformBox>("The link to the current private alpha version of Telegram Desktop was copied to the clipboard."));
} else { } else {

View File

@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "messenger.h" #include "messenger.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "application.h"
#include "auth_session.h" #include "auth_session.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -742,7 +741,7 @@ object_ptr<Ui::RpWidget> Controller::createInviteLinkEdit() {
_controls.inviteLink->setContextCopyText(QString()); _controls.inviteLink->setContextCopyText(QString());
_controls.inviteLink->setBreakEverywhere(true); _controls.inviteLink->setBreakEverywhere(true);
_controls.inviteLink->setClickHandlerFilter([=](auto&&...) { _controls.inviteLink->setClickHandlerFilter([=](auto&&...) {
Application::clipboard()->setText(inviteLinkText()); QApplication::clipboard()->setText(inviteLinkText());
Ui::Toast::Show(lang(lng_group_invite_copied)); Ui::Toast::Show(lang(lng_group_invite_copied));
return false; return false;
}); });

View File

@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/username_box.h" #include "boxes/username_box.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "application.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
@ -166,7 +165,7 @@ void UsernameBox::changed() {
} }
void UsernameBox::linkClick() { void UsernameBox::linkClick() {
Application::clipboard()->setText(Messenger::Instance().createInternalLinkFull(getName())); QApplication::clipboard()->setText(Messenger::Instance().createInternalLinkFull(getName()));
Ui::Toast::Show(lang(lng_username_copied)); Ui::Toast::Show(lang(lng_username_copied));
} }
@ -180,7 +179,7 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
_saveRequestId = 0; _saveRequestId = 0;
const auto self = Auth().user(); const auto self = Auth().user();
const auto err = error.type(); const auto &err = error.type();
if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == self->username) { if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == self->username) {
self->setName( self->setName(
TextUtilities::SingleLine(self->firstName), TextUtilities::SingleLine(self->firstName),

View File

@ -26,8 +26,6 @@ enum {
MTPKillFileSessionTimeout = 5000, // how much time without upload / download causes additional session kill MTPKillFileSessionTimeout = 5000, // how much time without upload / download causes additional session kill
MTPChannelGetDifferenceLimit = 100,
MaxSelectedItems = 100, MaxSelectedItems = 100,
MaxPhoneCodeLength = 4, // max length of country phone code MaxPhoneCodeLength = 4, // max length of country phone code
@ -80,8 +78,6 @@ enum {
ServiceUserId = 777000, ServiceUserId = 777000,
WebPageUserId = 701000, WebPageUserId = 701000,
CacheBackgroundTimeout = 3000, // cache background scaled image after 3s
UpdateDelayConstPart = 8 * 3600, // 8 hour min time between update check requests UpdateDelayConstPart = 8 * 3600, // 8 hour min time between update check requests
UpdateDelayRandPart = 8 * 3600, // 8 hour max - min time between update check requests UpdateDelayRandPart = 8 * 3600, // 8 hour max - min time between update check requests
@ -246,32 +242,6 @@ inline const QString &cTempDir() {
return res; return res;
} }
enum {
DialogsFirstLoad = 20, // first dialogs part size requested
DialogsPerPage = 500, // next dialogs part size
UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb
UploadPartSize = 32 * 1024, // 32kb for photo
DocumentMaxPartsCount = 3000, // no more than 3000 parts
DocumentUploadPartSize0 = 32 * 1024, // 32kb for tiny document ( < 1mb )
DocumentUploadPartSize1 = 64 * 1024, // 64kb for little document ( <= 32mb )
DocumentUploadPartSize2 = 128 * 1024, // 128kb for small document ( <= 375mb )
DocumentUploadPartSize3 = 256 * 1024, // 256kb for medium document ( <= 750mb )
DocumentUploadPartSize4 = 512 * 1024, // 512kb for large document ( <= 1500mb )
UploadRequestInterval = 500, // one part each half second, if not uploaded faster
MaxPhotosInMemory = 50, // try to clear some memory after 50 photos are created
NoUpdatesTimeout = 60 * 1000, // if nothing is received in 1 min we ping
NoUpdatesAfterSleepTimeout = 60 * 1000, // if nothing is received in 1 min when was a sleepmode we ping
WaitForSkippedTimeout = 1000, // 1s wait for skipped seq or pts in updates
WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle
SendViewsTimeout = 1000, // send views each second
};
inline const QRegularExpression &cRussianLetters() { inline const QRegularExpression &cRussianLetters() {
static QRegularExpression regexp(QString::fromUtf8("[а-яА-ЯёЁ]")); static QRegularExpression regexp(QString::fromUtf8("[а-яА-ЯёЁ]"));
return regexp; return regexp;

View File

@ -806,7 +806,7 @@ void LastCrashedWindow::onNetworkSettingsSaved(
proxy.user = username; proxy.user = username;
proxy.password = password; proxy.password = password;
Sandbox::refreshGlobalProxy(); Core::App().refreshGlobalProxy();
if (_updaterData if (_updaterData
&& ((_updaterData->state == UpdatingCheck) && ((_updaterData->state == UpdatingCheck)

View File

@ -1,59 +0,0 @@
/*
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 "core/single_timer.h"
#include "application.h"
SingleTimer::SingleTimer(QObject *parent) : QTimer(parent) {
QTimer::setSingleShot(true);
Sandbox::connect(SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));
}
void SingleTimer::setTimeoutHandler(Fn<void()> handler) {
if (_handler && !handler) {
disconnect(this, SIGNAL(timeout()), this, SLOT(onTimeout()));
} else if (handler && !_handler) {
connect(this, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
_handler = std::move(handler);
}
void SingleTimer::adjust() {
auto n = getms(true);
if (isActive()) {
if (n >= _finishing) {
start(0);
} else {
start(_finishing - n);
}
}
}
void SingleTimer::onTimeout() {
if (_handler) {
_handler();
}
}
void SingleTimer::start(int msec) {
_finishing = getms(true) + (msec < 0 ? 0 : msec);
QTimer::start(msec);
}
void SingleTimer::startIfNotActive(int msec) {
if (isActive()) {
int remains = remainingTime();
if (remains > msec) {
start(msec);
} else if (!remains) {
start(1);
}
} else {
start(msec);
}
}

View File

@ -1,33 +0,0 @@
/*
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
*/
#pragma once
class SingleTimer : public QTimer { // single shot timer with check
Q_OBJECT
public:
SingleTimer(QObject *parent = nullptr);
void setSingleShot(bool); // is not available
void start(); // is not available
void setTimeoutHandler(Fn<void()> handler);
public slots:
void start(int msec);
void startIfNotActive(int msec);
private slots:
void adjust();
void onTimeout();
private:
TimeMs _finishing = 0;
Fn<void()> _handler;
};

View File

@ -8,7 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/utils.h" #include "core/utils.h"
#include "base/qthelp_url.h" #include "base/qthelp_url.h"
#include "application.h" #include "base/timer.h"
#include "base/concurrent_timer.h"
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
extern "C" { extern "C" {
@ -84,7 +85,7 @@ std::atomic<int> GlobalAtomicRequestId = 0;
} }
TimeId LocalUnixtime() { TimeId LocalUnixtime() {
return (TimeId)time(NULL); return (TimeId)time(nullptr);
} }
void unixtimeInit() { void unixtimeInit() {
@ -173,24 +174,24 @@ namespace {
int _ffmpegLockManager(void **mutex, AVLockOp op) { int _ffmpegLockManager(void **mutex, AVLockOp op) {
switch (op) { switch (op) {
case AV_LOCK_CREATE: { case AV_LOCK_CREATE: {
Assert(*mutex == 0); Assert(*mutex == nullptr);
*mutex = reinterpret_cast<void*>(new QMutex()); *mutex = reinterpret_cast<void*>(new QMutex());
} break; } break;
case AV_LOCK_OBTAIN: { case AV_LOCK_OBTAIN: {
Assert(*mutex != 0); Assert(*mutex != nullptr);
reinterpret_cast<QMutex*>(*mutex)->lock(); reinterpret_cast<QMutex*>(*mutex)->lock();
} break; } break;
case AV_LOCK_RELEASE: { case AV_LOCK_RELEASE: {
Assert(*mutex != 0); Assert(*mutex != nullptr);
reinterpret_cast<QMutex*>(*mutex)->unlock(); reinterpret_cast<QMutex*>(*mutex)->unlock();
}; break; }; break;
case AV_LOCK_DESTROY: { case AV_LOCK_DESTROY: {
Assert(*mutex != 0); Assert(*mutex != nullptr);
delete reinterpret_cast<QMutex*>(*mutex); delete reinterpret_cast<QMutex*>(*mutex);
*mutex = 0; *mutex = nullptr;
} break; } break;
} }
return 0; return 0;
@ -428,7 +429,8 @@ namespace ThirdParty {
bool checkms() { bool checkms() {
if (crl::adjust_time()) { if (crl::adjust_time()) {
Sandbox::adjustSingleTimers(); base::Timer::Adjust();
base::ConcurrentTimerEnvironment::Adjust();
return true; return true;
} }
return false; return false;

View File

@ -139,7 +139,8 @@ bool PtsWaiter::updateAndApply(ChannelData *channel, int32 pts, int32 count) {
return true; return true;
} }
bool PtsWaiter::check(ChannelData *channel, int32 pts, int32 count) { // return false if need to save that update and apply later // Return false if need to save that update and apply later.
bool PtsWaiter::check(ChannelData *channel, int32 pts, int32 count) {
if (!inited()) { if (!inited()) {
init(pts); init(pts);
return true; return true;
@ -153,7 +154,7 @@ bool PtsWaiter::check(ChannelData *channel, int32 pts, int32 count) { // return
} else if (_last < _count) { } else if (_last < _count) {
setWaitingForSkipped(channel, 1); setWaitingForSkipped(channel, 1);
} else { } else {
setWaitingForSkipped(channel, WaitForSkippedTimeout); setWaitingForSkipped(channel, kWaitForSkippedTimeout);
} }
return !count; return !count;
} }

View File

@ -15,6 +15,10 @@ enum PtsSkippedQueue {
class PtsWaiter { class PtsWaiter {
public: public:
PtsWaiter() = default; PtsWaiter() = default;
// 1s wait for skipped seq or pts in updates.
static constexpr auto kWaitForSkippedTimeout = 1000;
void init(int32 pts) { void init(int32 pts) {
_good = _last = _count = pts; _good = _last = _count = pts;
clearSkippedUpdates(); clearSkippedUpdates();

View File

@ -41,6 +41,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
constexpr auto kDialogsFirstLoad = 20;
constexpr auto kDialogsPerPage = 500;
QString SwitchToChooseFromQuery() { QString SwitchToChooseFromQuery() {
return qsl("from:"); return qsl("from:");
} }
@ -877,7 +880,7 @@ void DialogsWidget::loadDialogs() {
} }
const auto firstLoad = !_dialogsOffsetDate; const auto firstLoad = !_dialogsOffsetDate;
const auto loadCount = firstLoad ? DialogsFirstLoad : DialogsPerPage; const auto loadCount = firstLoad ? kDialogsFirstLoad : kDialogsPerPage;
const auto flags = MTPmessages_GetDialogs::Flag::f_exclude_pinned; const auto flags = MTPmessages_GetDialogs::Flag::f_exclude_pinned;
const auto feedId = 0; const auto feedId = 0;
const auto hash = 0; const auto hash = 0;

View File

@ -182,8 +182,6 @@ void WorkingDirReady();
void WriteInstallBetaVersionsSetting(); void WriteInstallBetaVersionsSetting();
void WriteDebugModeSetting(); void WriteDebugModeSetting();
void MainThreadTaskAdded();
void start(); void start();
bool started(); bool started();
void finish(); void finish();

View File

@ -39,7 +39,7 @@ class HistoryInner
: public Ui::RpWidget : public Ui::RpWidget
, public Ui::AbstractTooltipShower , public Ui::AbstractTooltipShower
, private base::Subscriber { , private base::Subscriber {
// The Q_OBJECT meta info is used for qobject_cast to HistoryInner! // The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
public: public:

View File

@ -176,6 +176,7 @@ HistoryWidget::HistoryWidget(
QWidget *parent, QWidget *parent,
not_null<Window::Controller*> controller) not_null<Window::Controller*> controller)
: Window::AbstractSectionWidget(parent, controller) : Window::AbstractSectionWidget(parent, controller)
, _updateEditTimeLeftDisplay([=] { updateField(); })
, _fieldBarCancel(this, st::historyReplyCancel) , _fieldBarCancel(this, st::historyReplyCancel)
, _previewTimer([=] { requestPreview(); }) , _previewTimer([=] { requestPreview(); })
, _topBar(this, controller) , _topBar(this, controller)
@ -360,8 +361,6 @@ HistoryWidget::HistoryWidget(
ActivateWindow(this->controller()); ActivateWindow(this->controller());
}); });
connect(&_updateEditTimeLeftDisplay, SIGNAL(timeout()), this, SLOT(updateField()));
subscribe(Adaptive::Changed(), [this] { update(); }); subscribe(Adaptive::Changed(), [this] { update(); });
Auth().data().itemRemoved( Auth().data().itemRemoved(
) | rpl::start_with_next( ) | rpl::start_with_next(
@ -6425,7 +6424,7 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
// Restart timer only if we are sure that we've painted the whole timer. // Restart timer only if we are sure that we've painted the whole timer.
if (rect.contains(myrtlrect(left, top, width() - left, st::normalFont->height)) && updateIn > 0) { if (rect.contains(myrtlrect(left, top, width() - left, st::normalFont->height)) && updateIn > 0) {
_updateEditTimeLeftDisplay.start(updateIn); _updateEditTimeLeftDisplay.callOnce(updateIn);
} }
if (!editTimeLeftText.isEmpty()) { if (!editTimeLeftText.isEmpty()) {

View File

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "chat_helpers/field_autocomplete.h" #include "chat_helpers/field_autocomplete.h"
#include "window/section_widget.h" #include "window/section_widget.h"
#include "core/single_timer.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "base/flags.h" #include "base/flags.h"
@ -358,14 +357,13 @@ private slots:
void onModerateKeyActivate(int index, bool *outHandled); void onModerateKeyActivate(int index, bool *outHandled);
void updateField();
private: private:
using TabbedPanel = ChatHelpers::TabbedPanel; using TabbedPanel = ChatHelpers::TabbedPanel;
using TabbedSelector = ChatHelpers::TabbedSelector; using TabbedSelector = ChatHelpers::TabbedSelector;
using DragState = Storage::MimeDataState; using DragState = Storage::MimeDataState;
void initTabbedSelector(); void initTabbedSelector();
void updateField();
void send(Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers()); void send(Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers());
void handlePendingHistoryUpdate(); void handlePendingHistoryUpdate();
@ -516,7 +514,7 @@ private:
HistoryItem *_replyEditMsg = nullptr; HistoryItem *_replyEditMsg = nullptr;
Text _replyEditMsgText; Text _replyEditMsgText;
mutable SingleTimer _updateEditTimeLeftDisplay; mutable base::Timer _updateEditTimeLeftDisplay;
object_ptr<Ui::IconButton> _fieldBarCancel; object_ptr<Ui::IconButton> _fieldBarCancel;
void updateReplyEditTexts(bool force = false); void updateReplyEditTexts(bool force = false);

View File

@ -40,7 +40,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "auth_session.h" #include "auth_session.h"
#include "messenger.h" #include "messenger.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "application.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -293,7 +292,7 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
auto link = Messenger::Instance().createInternalLinkFull( auto link = Messenger::Instance().createInternalLinkFull(
peer->userName()); peer->userName());
if (!link.isEmpty()) { if (!link.isEmpty()) {
Application::clipboard()->setText(link); QApplication::clipboard()->setText(link);
Ui::Toast::Show(lang(lng_username_copied)); Ui::Toast::Show(lang(lng_username_copied));
} }
return false; return false;

View File

@ -100,6 +100,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
constexpr auto kChannelGetDifferenceLimit = 100;
// 1s wait after show channel history before sending getChannelDifference.
constexpr auto kWaitForChannelGetDifference = TimeMs(1000);
// If nothing is received in 1 min we ping.
constexpr auto kNoUpdatesTimeout = 60 * 1000;
// If nothing is received in 1 min when was a sleepmode we ping.
constexpr auto kNoUpdatesAfterSleepTimeout = 60 * TimeMs(1000);
// Send channel views each second.
constexpr auto kSendViewsTimeout = TimeMs(1000);
// Cache background scaled image after 3s.
constexpr auto kCacheBackgroundTimeout = 3000;
bool IsForceLogoutNotification(const MTPDupdateServiceNotification &data) { bool IsForceLogoutNotification(const MTPDupdateServiceNotification &data) {
return qs(data.vtype).startsWith(qstr("AUTH_KEY_DROP_")); return qs(data.vtype).startsWith(qstr("AUTH_KEY_DROP_"));
} }
@ -239,7 +256,16 @@ MainWidget::MainWidget(
this, this,
_controller, _controller,
Media::Player::Panel::Layout::OnlyPlaylist) Media::Player::Panel::Layout::OnlyPlaylist)
, _playerPanel(this, _controller, Media::Player::Panel::Layout::Full) { , _playerPanel(this, _controller, Media::Player::Panel::Layout::Full)
, _noUpdatesTimer([=] { sendPing(); })
, _byPtsTimer([=] { getDifferenceByPts(); })
, _bySeqTimer([=] { getDifference(); })
, _byMinChannelTimer([=] { getDifference(); })
, _onlineTimer([=] { updateOnline(); })
, _idleFinishTimer([=] { checkIdleFinish(); })
, _failDifferenceTimer([=] { getDifferenceAfterFail(); })
, _cacheBackgroundTimer([=] { cacheBackground(); })
, _viewsIncrementTimer([=] { viewsIncrement(); }) {
Messenger::Instance().mtp()->setUpdatesHandler(rpcDone(&MainWidget::updateReceived)); Messenger::Instance().mtp()->setUpdatesHandler(rpcDone(&MainWidget::updateReceived));
Messenger::Instance().mtp()->setGlobalFailHandler(rpcFail(&MainWidget::updateFail)); Messenger::Instance().mtp()->setGlobalFailHandler(rpcFail(&MainWidget::updateFail));
@ -256,13 +282,6 @@ MainWidget::MainWidget(
connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled())); connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled()));
connect(this, SIGNAL(dialogsUpdated()), _dialogs, SLOT(onListScroll())); connect(this, SIGNAL(dialogsUpdated()), _dialogs, SLOT(onListScroll()));
connect(_history, SIGNAL(cancelled()), _dialogs, SLOT(activate())); connect(_history, SIGNAL(cancelled()), _dialogs, SLOT(activate()));
connect(&noUpdatesTimer, SIGNAL(timeout()), this, SLOT(mtpPing()));
connect(&_onlineTimer, SIGNAL(timeout()), this, SLOT(updateOnline()));
connect(&_idleFinishTimer, SIGNAL(timeout()), this, SLOT(checkIdleFinish()));
connect(&_bySeqTimer, SIGNAL(timeout()), this, SLOT(getDifference()));
connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeByPts()));
connect(&_byMinChannelTimer, SIGNAL(timeout()), this, SLOT(getDifference()));
connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail()));
subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) { subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) {
if (audioId.type() != AudioMsgId::Type::Video) { if (audioId.type() != AudioMsgId::Type::Video) {
handleAudioUpdate(audioId); handleAudioUpdate(audioId);
@ -310,15 +329,12 @@ MainWidget::MainWidget(
QCoreApplication::instance()->installEventFilter(this); QCoreApplication::instance()->installEventFilter(this);
connect(&_viewsIncrementTimer, SIGNAL(timeout()), this, SLOT(onViewsIncrement()));
using Update = Window::Theme::BackgroundUpdate; using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [this](const Update &update) { subscribe(Window::Theme::Background(), [this](const Update &update) {
if (update.type == Update::Type::New || update.type == Update::Type::Changed) { if (update.type == Update::Type::New || update.type == Update::Type::Changed) {
clearCachedBackground(); clearCachedBackground();
} }
}); });
connect(&_cacheBackgroundTimer, SIGNAL(timeout()), this, SLOT(onCacheBackground()));
_playerPanel->setPinCallback([this] { switchToFixedPlayer(); }); _playerPanel->setPinCallback([this] { switchToFixedPlayer(); });
_playerPanel->setCloseCallback([this] { closeBothPlayers(); }); _playerPanel->setCloseCallback([this] { closeBothPlayers(); });
@ -925,7 +941,7 @@ bool MainWidget::sendMessageFail(const RPCError &error) {
return false; return false;
} }
void MainWidget::onCacheBackground() { void MainWidget::cacheBackground() {
if (Window::Theme::Background()->color()) { if (Window::Theme::Background()->color()) {
return; return;
} else if (Window::Theme::Background()->tile()) { } else if (Window::Theme::Background()->tile()) {
@ -1025,7 +1041,7 @@ void MainWidget::itemEdited(not_null<HistoryItem*> item) {
void MainWidget::checkLastUpdate(bool afterSleep) { void MainWidget::checkLastUpdate(bool afterSleep) {
auto n = getms(true); auto n = getms(true);
if (_lastUpdateTime && n > _lastUpdateTime + (afterSleep ? NoUpdatesAfterSleepTimeout : NoUpdatesTimeout)) { if (_lastUpdateTime && n > _lastUpdateTime + (afterSleep ? kNoUpdatesAfterSleepTimeout : kNoUpdatesTimeout)) {
_lastUpdateTime = n; _lastUpdateTime = n;
MTP::ping(); MTP::ping();
} }
@ -1399,7 +1415,7 @@ bool MainWidget::isIdle() const {
void MainWidget::clearCachedBackground() { void MainWidget::clearCachedBackground() {
_cachedBackground = QPixmap(); _cachedBackground = QPixmap();
_cacheBackgroundTimer.stop(); _cacheBackgroundTimer.cancel();
update(); update();
} }
@ -1411,7 +1427,7 @@ QPixmap MainWidget::cachedBackground(const QRect &forRect, int &x, int &y) {
} }
if (_willCacheFor != forRect || !_cacheBackgroundTimer.isActive()) { if (_willCacheFor != forRect || !_cacheBackgroundTimer.isActive()) {
_willCacheFor = forRect; _willCacheFor = forRect;
_cacheBackgroundTimer.start(CacheBackgroundTimeout); _cacheBackgroundTimer.callOnce(kCacheBackgroundTimeout);
} }
return QPixmap(); return QPixmap();
} }
@ -1562,12 +1578,12 @@ void MainWidget::scheduleViewIncrement(HistoryItem *item) {
auto j = _viewsToIncrement.find(peer); auto j = _viewsToIncrement.find(peer);
if (j == _viewsToIncrement.cend()) { if (j == _viewsToIncrement.cend()) {
j = _viewsToIncrement.insert(peer, ViewsIncrementMap()); j = _viewsToIncrement.insert(peer, ViewsIncrementMap());
_viewsIncrementTimer.start(SendViewsTimeout); _viewsIncrementTimer.callOnce(kSendViewsTimeout);
} }
j.value().insert(item->id, true); j.value().insert(item->id, true);
} }
void MainWidget::onViewsIncrement() { void MainWidget::viewsIncrement() {
for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) { for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
if (_viewsIncrementRequests.contains(i.key())) { if (_viewsIncrementRequests.contains(i.key())) {
++i; ++i;
@ -1603,7 +1619,7 @@ void MainWidget::viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint>
} }
} }
if (!_viewsToIncrement.isEmpty() && !_viewsIncrementTimer.isActive()) { if (!_viewsToIncrement.isEmpty() && !_viewsIncrementTimer.isActive()) {
_viewsIncrementTimer.start(SendViewsTimeout); _viewsIncrementTimer.callOnce(kSendViewsTimeout);
} }
} }
@ -1617,7 +1633,7 @@ bool MainWidget::viewsIncrementFail(const RPCError &error, mtpRequestId req) {
} }
} }
if (!_viewsToIncrement.isEmpty() && !_viewsIncrementTimer.isActive()) { if (!_viewsToIncrement.isEmpty() && !_viewsIncrementTimer.isActive()) {
_viewsIncrementTimer.start(SendViewsTimeout); _viewsIncrementTimer.callOnce(kSendViewsTimeout);
} }
return false; return false;
} }
@ -1775,7 +1791,7 @@ void MainWidget::ui_showPeerHistory(
if (nowActivePeer && nowActivePeer != wasActivePeer) { if (nowActivePeer && nowActivePeer != wasActivePeer) {
if (const auto channel = nowActivePeer->asChannel()) { if (const auto channel = nowActivePeer->asChannel()) {
channel->ptsWaitingForShortPoll( channel->ptsWaitingForShortPoll(
WaitForChannelGetDifference); kWaitForChannelGetDifference);
} }
_viewsIncremented.remove(nowActivePeer); _viewsIncremented.remove(nowActivePeer);
} }
@ -2787,7 +2803,7 @@ void MainWidget::keyPressEvent(QKeyEvent *e) {
bool MainWidget::eventFilter(QObject *o, QEvent *e) { bool MainWidget::eventFilter(QObject *o, QEvent *e) {
if (e->type() == QEvent::FocusIn) { if (e->type() == QEvent::FocusIn) {
if (auto widget = qobject_cast<QWidget*>(o)) { if (const auto widget = qobject_cast<QWidget*>(o)) {
if (_history == widget || _history->isAncestorOf(widget) if (_history == widget || _history->isAncestorOf(widget)
|| (_mainSection && (_mainSection == widget || _mainSection->isAncestorOf(widget))) || (_mainSection && (_mainSection == widget || _mainSection->isAncestorOf(widget)))
|| (_thirdSection && (_thirdSection == widget || _thirdSection->isAncestorOf(widget)))) { || (_thirdSection && (_thirdSection == widget || _thirdSection->isAncestorOf(widget)))) {
@ -2928,7 +2944,9 @@ void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
} }
if (seq && seq != updSeq) { if (seq && seq != updSeq) {
updSeq = seq; updSeq = seq;
if (_bySeqTimer.isActive()) _bySeqTimer.stop(); if (_bySeqTimer.isActive()) {
_bySeqTimer.cancel();
}
for (QMap<int32, MTPUpdates>::iterator i = _bySeqUpdates.begin(); i != _bySeqUpdates.end();) { for (QMap<int32, MTPUpdates>::iterator i = _bySeqUpdates.begin(); i != _bySeqUpdates.end();) {
int32 s = i.key(); int32 s = i.key();
if (s <= seq + 1) { if (s <= seq + 1) {
@ -2938,7 +2956,9 @@ void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
return feedUpdates(v); return feedUpdates(v);
} }
} else { } else {
if (!_bySeqTimer.isActive()) _bySeqTimer.start(WaitForSkippedTimeout); if (!_bySeqTimer.isActive()) {
_bySeqTimer.callOnce(PtsWaiter::kWaitForSkippedTimeout);
}
break; break;
} }
} }
@ -3008,7 +3028,9 @@ void MainWidget::gotChannelDifference(
MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received }%1").arg(cTestMode() ? " TESTMODE" : ""));
getChannelDifference(channel); getChannelDifference(channel);
} else if (_controller->activeChatCurrent().peer() == channel) { } else if (_controller->activeChatCurrent().peer() == channel) {
channel->ptsWaitingForShortPoll(timeout ? (timeout * 1000) : WaitForChannelGetDifference); channel->ptsWaitingForShortPoll(timeout
? (timeout * TimeMs(1000))
: kWaitForChannelGetDifference);
} }
} }
@ -3037,7 +3059,7 @@ void MainWidget::gotState(const MTPupdates_State &state) {
updSetState(d.vpts.v, d.vdate.v, d.vqts.v, d.vseq.v); updSetState(d.vpts.v, d.vdate.v, d.vqts.v, d.vseq.v);
_lastUpdateTime = getms(true); _lastUpdateTime = getms(true);
noUpdatesTimer.start(NoUpdatesTimeout); _noUpdatesTimer.callOnce(kNoUpdatesTimeout);
_ptsWaiter.setRequesting(false); _ptsWaiter.setRequesting(false);
_dialogs->loadDialogs(); _dialogs->loadDialogs();
@ -3053,7 +3075,7 @@ void MainWidget::gotDifference(const MTPupdates_Difference &difference) {
updSetState(_ptsWaiter.current(), d.vdate.v, updQts, d.vseq.v); updSetState(_ptsWaiter.current(), d.vdate.v, updQts, d.vseq.v);
_lastUpdateTime = getms(true); _lastUpdateTime = getms(true);
noUpdatesTimer.start(NoUpdatesTimeout); _noUpdatesTimer.callOnce(kNoUpdatesTimeout);
_ptsWaiter.setRequesting(false); _ptsWaiter.setRequesting(false);
} break; } break;
@ -3125,7 +3147,7 @@ bool MainWidget::getDifferenceTimeChanged(ChannelData *channel, int32 ms, Channe
void MainWidget::ptsWaiterStartTimerFor(ChannelData *channel, int32 ms) { void MainWidget::ptsWaiterStartTimerFor(ChannelData *channel, int32 ms) {
if (getDifferenceTimeChanged(channel, ms, _channelGetDifferenceTimeByPts, _getDifferenceTimeByPts)) { if (getDifferenceTimeChanged(channel, ms, _channelGetDifferenceTimeByPts, _getDifferenceTimeByPts)) {
onGetDifferenceTimeByPts(); getDifferenceByPts();
} }
} }
@ -3140,7 +3162,7 @@ void MainWidget::failDifferenceStartTimerFor(ChannelData *channel) {
: i.value(); : i.value();
}(); }();
if (getDifferenceTimeChanged(channel, timeout * 1000, _channelGetDifferenceTimeAfterFail, _getDifferenceTimeAfterFail)) { if (getDifferenceTimeChanged(channel, timeout * 1000, _channelGetDifferenceTimeAfterFail, _getDifferenceTimeAfterFail)) {
onGetDifferenceTimeAfterFail(); getDifferenceAfterFail();
} }
if (timeout < 64) timeout *= 2; if (timeout < 64) timeout *= 2;
} }
@ -3174,11 +3196,11 @@ bool MainWidget::failDifference(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
LOG(("RPC Error in getDifference: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description())); LOG(("RPC Error in getDifference: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description()));
failDifferenceStartTimerFor(0); failDifferenceStartTimerFor(nullptr);
return true; return true;
} }
void MainWidget::onGetDifferenceTimeByPts() { void MainWidget::getDifferenceByPts() {
auto now = getms(true), wait = 0LL; auto now = getms(true), wait = 0LL;
if (_getDifferenceTimeByPts) { if (_getDifferenceTimeByPts) {
if (_getDifferenceTimeByPts > now) { if (_getDifferenceTimeByPts > now) {
@ -3197,13 +3219,13 @@ void MainWidget::onGetDifferenceTimeByPts() {
} }
} }
if (wait) { if (wait) {
_byPtsTimer.start(wait); _byPtsTimer.callOnce(wait);
} else { } else {
_byPtsTimer.stop(); _byPtsTimer.cancel();
} }
} }
void MainWidget::onGetDifferenceTimeAfterFail() { void MainWidget::getDifferenceAfterFail() {
auto now = getms(true), wait = 0LL; auto now = getms(true), wait = 0LL;
if (_getDifferenceTimeAfterFail) { if (_getDifferenceTimeAfterFail) {
if (_getDifferenceTimeAfterFail > now) { if (_getDifferenceTimeAfterFail > now) {
@ -3224,9 +3246,9 @@ void MainWidget::onGetDifferenceTimeAfterFail() {
} }
} }
if (wait) { if (wait) {
_failDifferenceTimer.start(wait); _failDifferenceTimer.callOnce(wait);
} else { } else {
_failDifferenceTimer.stop(); _failDifferenceTimer.cancel();
} }
} }
@ -3238,14 +3260,22 @@ void MainWidget::getDifference() {
if (requestingDifference()) return; if (requestingDifference()) return;
_bySeqUpdates.clear(); _bySeqUpdates.clear();
_bySeqTimer.stop(); _bySeqTimer.cancel();
noUpdatesTimer.stop(); _noUpdatesTimer.cancel();
_getDifferenceTimeAfterFail = 0; _getDifferenceTimeAfterFail = 0;
_ptsWaiter.setRequesting(true); _ptsWaiter.setRequesting(true);
MTP::send(MTPupdates_GetDifference(MTP_flags(0), MTP_int(_ptsWaiter.current()), MTPint(), MTP_int(updDate), MTP_int(updQts)), rpcDone(&MainWidget::gotDifference), rpcFail(&MainWidget::failDifference)); MTP::send(
MTPupdates_GetDifference(
MTP_flags(0),
MTP_int(_ptsWaiter.current()),
MTPint(),
MTP_int(updDate),
MTP_int(updQts)),
rpcDone(&MainWidget::gotDifference),
rpcFail(&MainWidget::failDifference));
} }
void MainWidget::getChannelDifference(ChannelData *channel, ChannelDifferenceRequest from) { void MainWidget::getChannelDifference(ChannelData *channel, ChannelDifferenceRequest from) {
@ -3270,10 +3300,18 @@ void MainWidget::getChannelDifference(ChannelData *channel, ChannelDifferenceReq
flags = 0; // No force flag when requesting for short poll. flags = 0; // No force flag when requesting for short poll.
} }
} }
MTP::send(MTPupdates_GetChannelDifference(MTP_flags(flags), channel->inputChannel, filter, MTP_int(channel->pts()), MTP_int(MTPChannelGetDifferenceLimit)), rpcDone(&MainWidget::gotChannelDifference, channel), rpcFail(&MainWidget::failChannelDifference, channel)); MTP::send(
MTPupdates_GetChannelDifference(
MTP_flags(flags),
channel->inputChannel,
filter,
MTP_int(channel->pts()),
MTP_int(kChannelGetDifferenceLimit)),
rpcDone(&MainWidget::gotChannelDifference, channel),
rpcFail(&MainWidget::failChannelDifference, channel));
} }
void MainWidget::mtpPing() { void MainWidget::sendPing() {
MTP::ping(); MTP::ping();
} }
@ -3470,7 +3508,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
it->stickers.removeAt(index); it->stickers.removeAt(index);
for (auto i = it->emoji.begin(); i != it->emoji.end();) { for (auto i = it->emoji.begin(); i != it->emoji.end();) {
if (const auto index = i->indexOf(sticker); index >= 0) { if (const auto index = i->indexOf(sticker); index >= 0) {
removedFromEmoji.push_back(i.key()); removedFromEmoji.emplace_back(i.key());
i->removeAt(index); i->removeAt(index);
if (i->isEmpty()) { if (i->isEmpty()) {
i = it->emoji.erase(i); i = it->emoji.erase(i);
@ -3620,7 +3658,7 @@ void MainWidget::updateOnline(bool gotOtherOffline) {
isOnline = false; isOnline = false;
if (!_isIdle) { if (!_isIdle) {
_isIdle = true; _isIdle = true;
_idleFinishTimer.start(900); _idleFinishTimer.callOnce(900);
} }
} else { } else {
updateIn = qMin(updateIn, int(Global::OfflineIdleTimeout() - idle)); updateIn = qMin(updateIn, int(Global::OfflineIdleTimeout() - idle));
@ -3652,7 +3690,7 @@ void MainWidget::updateOnline(bool gotOtherOffline) {
} else if (isOnline) { } else if (isOnline) {
updateIn = qMin(updateIn, int(_lastSetOnline + Global::OnlineUpdatePeriod() - ms)); updateIn = qMin(updateIn, int(_lastSetOnline + Global::OnlineUpdatePeriod() - ms));
} }
_onlineTimer.start(updateIn); _onlineTimer.callOnce(updateIn);
} }
void MainWidget::saveDraftToCloud() { void MainWidget::saveDraftToCloud() {
@ -3703,14 +3741,13 @@ void MainWidget::writeDrafts(History *history) {
} }
void MainWidget::checkIdleFinish() { void MainWidget::checkIdleFinish() {
if (this != App::main()) return;
if (psIdleTime() < Global::OfflineIdleTimeout()) { if (psIdleTime() < Global::OfflineIdleTimeout()) {
_idleFinishTimer.stop(); _idleFinishTimer.cancel();
_isIdle = false; _isIdle = false;
updateOnline(); updateOnline();
if (App::wnd()) App::wnd()->checkHistoryActivation(); App::wnd()->checkHistoryActivation();
} else { } else {
_idleFinishTimer.start(900); _idleFinishTimer.callOnce(900);
} }
} }
@ -3734,7 +3771,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
updates.read(from, end); updates.read(from, end);
_lastUpdateTime = getms(true); _lastUpdateTime = getms(true);
noUpdatesTimer.start(NoUpdatesTimeout); _noUpdatesTimer.callOnce(kNoUpdatesTimeout);
if (!requestingDifference() if (!requestingDifference()
|| HasForceLogoutNotification(updates)) { || HasForceLogoutNotification(updates)) {
feedUpdates(updates); feedUpdates(updates);
@ -3860,7 +3897,8 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
} }
if (d.vseq.v > updSeq + 1) { if (d.vseq.v > updSeq + 1) {
_bySeqUpdates.insert(d.vseq.v, updates); _bySeqUpdates.insert(d.vseq.v, updates);
return _bySeqTimer.start(WaitForSkippedTimeout); _bySeqTimer.callOnce(PtsWaiter::kWaitForSkippedTimeout);
return;
} }
} }
@ -3879,7 +3917,8 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
} }
if (d.vseq_start.v > updSeq + 1) { if (d.vseq_start.v > updSeq + 1) {
_bySeqUpdates.insert(d.vseq_start.v, updates); _bySeqUpdates.insert(d.vseq_start.v, updates);
return _bySeqTimer.start(WaitForSkippedTimeout); _bySeqTimer.callOnce(PtsWaiter::kWaitForSkippedTimeout);
return;
} }
} }
@ -4019,7 +4058,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
} }
if (!_byMinChannelTimer.isActive()) { // getDifference after timeout if (!_byMinChannelTimer.isActive()) { // getDifference after timeout
_byMinChannelTimer.start(WaitForSkippedTimeout); _byMinChannelTimer.callOnce(PtsWaiter::kWaitForSkippedTimeout);
} }
return; return;
} }
@ -4068,7 +4107,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
if (!channel) { if (!channel) {
if (!_byMinChannelTimer.isActive()) { if (!_byMinChannelTimer.isActive()) {
// getDifference after timeout. // getDifference after timeout.
_byMinChannelTimer.start(WaitForSkippedTimeout); _byMinChannelTimer.callOnce(PtsWaiter::kWaitForSkippedTimeout);
} }
return; return;
} }
@ -4615,13 +4654,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
auto &v = set.vdocuments.v; auto &v = set.vdocuments.v;
it->stickers.clear(); it->stickers.clear();
it->stickers.reserve(v.size()); it->stickers.reserve(v.size());
for (int i = 0, l = v.size(); i < l; ++i) { for (const auto &item : v) {
const auto doc = Auth().data().document(v.at(i)); const auto document = Auth().data().document(item);
if (!doc->sticker()) continue; if (!document->sticker()) continue;
it->stickers.push_back(doc); it->stickers.push_back(document);
if (doc->sticker()->set.type() != mtpc_inputStickerSetID) { if (document->sticker()->set.type() != mtpc_inputStickerSetID) {
doc->sticker()->set = inputSet; document->sticker()->set = inputSet;
} }
} }
it->emoji.clear(); it->emoji.clear();
@ -4678,11 +4717,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
auto &order = d.vorder.v; auto &order = d.vorder.v;
auto &sets = Auth().data().stickerSets(); auto &sets = Auth().data().stickerSets();
Stickers::Order result; Stickers::Order result;
for (int i = 0, l = order.size(); i < l; ++i) { for (const auto &item : order) {
if (sets.constFind(order.at(i).v) == sets.cend()) { if (sets.constFind(item.v) == sets.cend()) {
break; break;
} }
result.push_back(order.at(i).v); result.push_back(item.v);
} }
if (result.size() != Auth().data().stickerSetsOrder().size() || result.size() != order.size()) { if (result.size() != Auth().data().stickerSetsOrder().size() || result.size() != order.size()) {
Auth().data().setLastStickersUpdate(0); Auth().data().setLastStickersUpdate(0);

View File

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "core/single_timer.h" #include "base/timer.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "media/player/media_player_float.h" #include "media/player/media_player_float.h"
@ -257,11 +257,14 @@ public:
void feedChannelDifference(const MTPDupdates_channelDifference &data); void feedChannelDifference(const MTPDupdates_channelDifference &data);
// Mayde public for ApiWrap, while it is still here. // Made public for ApiWrap, while it is still here.
// Better would be for this to be moved to ApiWrap. // Better would be for this to be moved to ApiWrap.
bool requestingDifference() const { bool requestingDifference() const {
return _ptsWaiter.requesting(); return _ptsWaiter.requesting();
} }
void getDifference();
void updateOnline(bool gotOtherOffline = false);
void checkIdleFinish();
bool contentOverlapped(const QRect &globalRect); bool contentOverlapped(const QRect &globalRect);
@ -307,18 +310,6 @@ public slots:
void dialogsCancelled(); void dialogsCancelled();
void getDifference();
void onGetDifferenceTimeByPts();
void onGetDifferenceTimeAfterFail();
void mtpPing();
void updateOnline(bool gotOtherOffline = false);
void checkIdleFinish();
void onCacheBackground();
void onViewsIncrement();
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
@ -343,6 +334,11 @@ private:
UserData *from; UserData *from;
}; };
void viewsIncrement();
void sendPing();
void getDifferenceByPts();
void getDifferenceAfterFail();
void animationCallback(); void animationCallback();
void handleAdaptiveLayoutUpdate(); void handleAdaptiveLayoutUpdate();
void updateWindowAdaptiveLayout(); void updateWindowAdaptiveLayout();
@ -429,6 +425,7 @@ private:
void showAll(); void showAll();
void clearHider(not_null<Window::HistoryHider*> instance); void clearHider(not_null<Window::HistoryHider*> instance);
void cacheBackground();
void clearCachedBackground(); void clearCachedBackground();
not_null<Media::Player::FloatDelegate*> floatPlayerDelegate(); not_null<Media::Player::FloatDelegate*> floatPlayerDelegate();
@ -510,7 +507,7 @@ private:
int32 updDate = 0; int32 updDate = 0;
int32 updQts = -1; int32 updQts = -1;
int32 updSeq = 0; int32 updSeq = 0;
SingleTimer noUpdatesTimer; base::Timer _noUpdatesTimer;
PtsWaiter _ptsWaiter; PtsWaiter _ptsWaiter;
@ -518,22 +515,23 @@ private:
TimeMs _getDifferenceTimeByPts = 0; TimeMs _getDifferenceTimeByPts = 0;
TimeMs _getDifferenceTimeAfterFail = 0; TimeMs _getDifferenceTimeAfterFail = 0;
SingleTimer _byPtsTimer; base::Timer _byPtsTimer;
QMap<int32, MTPUpdates> _bySeqUpdates; QMap<int32, MTPUpdates> _bySeqUpdates;
SingleTimer _bySeqTimer; base::Timer _bySeqTimer;
SingleTimer _byMinChannelTimer; base::Timer _byMinChannelTimer;
mtpRequestId _onlineRequest = 0; mtpRequestId _onlineRequest = 0;
SingleTimer _onlineTimer, _idleFinishTimer; base::Timer _onlineTimer;
base::Timer _idleFinishTimer;
bool _lastWasOnline = false; bool _lastWasOnline = false;
TimeMs _lastSetOnline = 0; TimeMs _lastSetOnline = 0;
bool _isIdle = false; bool _isIdle = false;
int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails
QMap<ChannelData*, int32> _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails QMap<ChannelData*, int32> _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails
SingleTimer _failDifferenceTimer; base::Timer _failDifferenceTimer;
TimeMs _lastUpdateTime = 0; TimeMs _lastUpdateTime = 0;
bool _handlingChannelDifference = false; bool _handlingChannelDifference = false;
@ -542,7 +540,7 @@ private:
QRect _cachedFor, _willCacheFor; QRect _cachedFor, _willCacheFor;
int _cachedX = 0; int _cachedX = 0;
int _cachedY = 0; int _cachedY = 0;
SingleTimer _cacheBackgroundTimer; base::Timer _cacheBackgroundTimer;
PhotoData *_deletingPhoto = nullptr; PhotoData *_deletingPhoto = nullptr;
@ -550,7 +548,7 @@ private:
QMap<PeerData*, ViewsIncrementMap> _viewsIncremented, _viewsToIncrement; QMap<PeerData*, ViewsIncrementMap> _viewsIncremented, _viewsToIncrement;
QMap<PeerData*, mtpRequestId> _viewsIncrementRequests; QMap<PeerData*, mtpRequestId> _viewsIncrementRequests;
QMap<mtpRequestId, PeerData*> _viewsIncrementByRequest; QMap<mtpRequestId, PeerData*> _viewsIncrementByRequest;
SingleTimer _viewsIncrementTimer; base::Timer _viewsIncrementTimer;
struct SettingBackground; struct SettingBackground;
std::unique_ptr<SettingBackground> _background; std::unique_ptr<SettingBackground> _background;

View File

@ -714,7 +714,7 @@ void MainWindow::toggleDisplayNotifyFromTray() {
} }
void MainWindow::closeEvent(QCloseEvent *e) { void MainWindow::closeEvent(QCloseEvent *e) {
if (Sandbox::isSavingSession()) { if (Core::App().isSavingSession()) {
e->accept(); e->accept();
App::quit(); App::quit();
} else { } else {

View File

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "platform/platform_main_window.h" #include "platform/platform_main_window.h"
#include "core/single_timer.h"
#include "base/unique_qptr.h" #include "base/unique_qptr.h"
class MainWidget; class MainWidget;

View File

@ -906,7 +906,7 @@ void MediaView::onSaveAs() {
})); }));
} }
activateWindow(); activateWindow();
Sandbox::setActiveWindow(this); Core::App().setActiveWindow(this);
setFocus(); setFocus();
} }
@ -1777,7 +1777,7 @@ void MediaView::displayFinished() {
show(); show();
psShowOverAll(this); psShowOverAll(this);
activateWindow(); activateWindow();
Sandbox::setActiveWindow(this); Core::App().setActiveWindow(this);
setFocus(); setFocus();
} }
} }

View File

@ -79,6 +79,7 @@ struct Messenger::Private {
Messenger::Messenger(not_null<Core::Launcher*> launcher) Messenger::Messenger(not_null<Core::Launcher*> launcher)
: QObject() : QObject()
, _launcher(launcher) , _launcher(launcher)
, _killDownloadSessionsTimer([=] { killDownloadSessions(); })
, _private(std::make_unique<Private>()) , _private(std::make_unique<Private>())
, _databases(std::make_unique<Storage::Databases>()) , _databases(std::make_unique<Storage::Databases>())
, _langpack(std::make_unique<Lang::Instance>()) , _langpack(std::make_unique<Lang::Instance>())
@ -95,7 +96,7 @@ Messenger::Messenger(not_null<Core::Launcher*> launcher)
ThirdParty::start(); ThirdParty::start();
Global::start(); Global::start();
Sandbox::refreshGlobalProxy(); // Depends on Global::started(). Core::App().refreshGlobalProxy(); // Depends on Global::started().
startLocalStorage(); startLocalStorage();
@ -110,7 +111,7 @@ Messenger::Messenger(not_null<Core::Launcher*> launcher)
} }
_translator = std::make_unique<Lang::Translator>(); _translator = std::make_unique<Lang::Translator>();
QCoreApplication::instance()->installTranslator(_translator.get()); qApp->installTranslator(_translator.get());
style::startManager(); style::startManager();
anim::startManager(); anim::startManager();
@ -120,12 +121,10 @@ Messenger::Messenger(not_null<Core::Launcher*> launcher)
DEBUG_LOG(("Application Info: inited...")); DEBUG_LOG(("Application Info: inited..."));
QCoreApplication::instance()->installNativeEventFilter(psNativeEventFilter()); QApplication::instance()->installNativeEventFilter(psNativeEventFilter());
cChangeTimeFormat(QLocale::system().timeFormat(QLocale::ShortFormat)); cChangeTimeFormat(QLocale::system().timeFormat(QLocale::ShortFormat));
connect(&killDownloadSessionsTimer, SIGNAL(timeout()), this, SLOT(killDownloadSessions()));
DEBUG_LOG(("Application Info: starting app...")); DEBUG_LOG(("Application Info: starting app..."));
// Create mime database, so it won't be slow later. // Create mime database, so it won't be slow later.
@ -138,8 +137,12 @@ Messenger::Messenger(not_null<Core::Launcher*> launcher)
_mediaView = std::make_unique<MediaView>(); _mediaView = std::make_unique<MediaView>();
_window->setGeometry(currentGeometry); _window->setGeometry(currentGeometry);
QCoreApplication::instance()->installEventFilter(this); qApp->installEventFilter(this);
Sandbox::connect(SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onAppStateChanged(Qt::ApplicationState))); connect(
qApp,
SIGNAL(applicationStateChanged(Qt::ApplicationState)),
this,
SLOT(onAppStateChanged(Qt::ApplicationState)));
DEBUG_LOG(("Application Info: window created...")); DEBUG_LOG(("Application Info: window created..."));
@ -252,13 +255,13 @@ bool Messenger::eventFilter(QObject *object, QEvent *e) {
} break; } break;
case QEvent::ApplicationActivate: { case QEvent::ApplicationActivate: {
if (object == QCoreApplication::instance()) { if (object == qApp) {
psUserActionDone(); psUserActionDone();
} }
} break; } break;
case QEvent::FileOpen: { case QEvent::FileOpen: {
if (object == QCoreApplication::instance()) { if (object == qApp) {
auto url = QString::fromUtf8(static_cast<QFileOpenEvent*>(e)->url().toEncoded().trimmed()); auto url = QString::fromUtf8(static_cast<QFileOpenEvent*>(e)->url().toEncoded().trimmed());
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) { if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
cSetStartUrl(url.mid(0, 8192)); cSetStartUrl(url.mid(0, 8192));
@ -289,7 +292,7 @@ void Messenger::setCurrentProxy(
: ProxyData())); : ProxyData()));
Global::SetSelectedProxy(proxy); Global::SetSelectedProxy(proxy);
Global::SetProxySettings(settings); Global::SetProxySettings(settings);
Sandbox::refreshGlobalProxy(); Core::App().refreshGlobalProxy();
if (_mtproto) { if (_mtproto) {
_mtproto->restart(); _mtproto->restart();
if (previousKey != key(proxy)) { if (previousKey != key(proxy)) {
@ -527,13 +530,18 @@ void Messenger::destroyMtpKeys(MTP::AuthKeysList &&keys) {
destroyConfig.mainDcId = MTP::Instance::Config::kNoneMainDc; destroyConfig.mainDcId = MTP::Instance::Config::kNoneMainDc;
destroyConfig.keys = std::move(keys); destroyConfig.keys = std::move(keys);
_mtprotoForKeysDestroy = std::make_unique<MTP::Instance>(_dcOptions.get(), MTP::Instance::Mode::KeysDestroyer, std::move(destroyConfig)); _mtprotoForKeysDestroy = std::make_unique<MTP::Instance>(_dcOptions.get(), MTP::Instance::Mode::KeysDestroyer, std::move(destroyConfig));
connect(_mtprotoForKeysDestroy.get(), SIGNAL(allKeysDestroyed()), this, SLOT(onAllKeysDestroyed())); connect(
_mtprotoForKeysDestroy.get(),
&MTP::Instance::allKeysDestroyed,
[=] { allKeysDestroyed(); });
} }
void Messenger::onAllKeysDestroyed() { void Messenger::allKeysDestroyed() {
LOG(("MTP Info: all keys scheduled for destroy are destroyed.")); LOG(("MTP Info: all keys scheduled for destroy are destroyed."));
_mtprotoForKeysDestroy.reset(); crl::on_main(this, [=] {
Local::writeMtpData(); _mtprotoForKeysDestroy = nullptr;
Local::writeMtpData();
});
} }
void Messenger::suggestMainDcId(MTP::DcId mainDcId) { void Messenger::suggestMainDcId(MTP::DcId mainDcId) {
@ -601,18 +609,19 @@ void Messenger::startLocalStorage() {
} }
void Messenger::killDownloadSessionsStart(MTP::DcId dcId) { void Messenger::killDownloadSessionsStart(MTP::DcId dcId) {
if (killDownloadSessionTimes.constFind(dcId) == killDownloadSessionTimes.cend()) { if (!_killDownloadSessionTimes.contains(dcId)) {
killDownloadSessionTimes.insert(dcId, getms() + MTPAckSendWaiting + MTPKillFileSessionTimeout); _killDownloadSessionTimes.emplace(dcId, getms() + MTPAckSendWaiting + MTPKillFileSessionTimeout);
} }
if (!killDownloadSessionsTimer.isActive()) { if (!_killDownloadSessionsTimer.isActive()) {
killDownloadSessionsTimer.start(MTPAckSendWaiting + MTPKillFileSessionTimeout + 5); _killDownloadSessionsTimer.callOnce(MTPAckSendWaiting + MTPKillFileSessionTimeout + 5);
} }
} }
void Messenger::killDownloadSessionsStop(MTP::DcId dcId) { void Messenger::killDownloadSessionsStop(MTP::DcId dcId) {
killDownloadSessionTimes.remove(dcId); _killDownloadSessionTimes.erase(dcId);
if (killDownloadSessionTimes.isEmpty() && killDownloadSessionsTimer.isActive()) { if (_killDownloadSessionTimes.empty()
killDownloadSessionsTimer.stop(); && _killDownloadSessionsTimer.isActive()) {
_killDownloadSessionsTimer.cancel();
} }
} }
@ -673,25 +682,25 @@ void Messenger::call_handleObservables() {
void Messenger::killDownloadSessions() { void Messenger::killDownloadSessions() {
auto ms = getms(), left = static_cast<TimeMs>(MTPAckSendWaiting) + MTPKillFileSessionTimeout; auto ms = getms(), left = static_cast<TimeMs>(MTPAckSendWaiting) + MTPKillFileSessionTimeout;
for (auto i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) { for (auto i = _killDownloadSessionTimes.begin(); i != _killDownloadSessionTimes.end(); ) {
if (i.value() <= ms) { if (i->second <= ms) {
for (int j = 0; j < MTP::kDownloadSessionsCount; ++j) { for (int j = 0; j < MTP::kDownloadSessionsCount; ++j) {
MTP::stopSession(MTP::downloadDcId(i.key(), j)); MTP::stopSession(MTP::downloadDcId(i->first, j));
} }
i = killDownloadSessionTimes.erase(i); i = _killDownloadSessionTimes.erase(i);
} else { } else {
if (i.value() - ms < left) { if (i->second - ms < left) {
left = i.value() - ms; left = i->second - ms;
} }
++i; ++i;
} }
} }
if (!killDownloadSessionTimes.isEmpty()) { if (!_killDownloadSessionTimes.empty()) {
killDownloadSessionsTimer.start(left); _killDownloadSessionsTimer.callOnce(left);
} }
} }
void Messenger::onSwitchDebugMode() { void Messenger::switchDebugMode() {
if (Logs::DebugEnabled()) { if (Logs::DebugEnabled()) {
Logs::SetDebugEnabled(false); Logs::SetDebugEnabled(false);
Sandbox::WriteDebugModeSetting(); Sandbox::WriteDebugModeSetting();
@ -704,14 +713,14 @@ void Messenger::onSwitchDebugMode() {
} }
} }
void Messenger::onSwitchWorkMode() { void Messenger::switchWorkMode() {
Global::SetDialogsModeEnabled(!Global::DialogsModeEnabled()); Global::SetDialogsModeEnabled(!Global::DialogsModeEnabled());
Global::SetDialogsMode(Dialogs::Mode::All); Global::SetDialogsMode(Dialogs::Mode::All);
Local::writeUserSettings(); Local::writeUserSettings();
App::restart(); App::restart();
} }
void Messenger::onSwitchTestMode() { void Messenger::switchTestMode() {
if (cTestMode()) { if (cTestMode()) {
QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove(); QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove();
cSetTestMode(false); cSetTestMode(false);
@ -971,7 +980,7 @@ QWidget *Messenger::getFileDialogParent() {
void Messenger::checkMediaViewActivation() { void Messenger::checkMediaViewActivation() {
if (_mediaView && !_mediaView->isHidden()) { if (_mediaView && !_mediaView->isHidden()) {
_mediaView->activateWindow(); _mediaView->activateWindow();
Sandbox::setActiveWindow(_mediaView.get()); Core::App().setActiveWindow(_mediaView.get());
_mediaView->setFocus(); _mediaView->setFocus();
} }
} }
@ -1062,7 +1071,7 @@ void Messenger::unregisterLeaveSubscription(QWidget *widget) {
void Messenger::QuitAttempt() { void Messenger::QuitAttempt() {
auto prevents = false; auto prevents = false;
if (!Sandbox::isSavingSession() && AuthSession::Exists()) { if (AuthSession::Exists() && !Core::App().isSavingSession()) {
if (Auth().api().isQuitPrevent()) { if (Auth().api().isQuitPrevent()) {
prevents = true; prevents = true;
} }
@ -1073,7 +1082,7 @@ void Messenger::QuitAttempt() {
if (prevents) { if (prevents) {
Instance().quitDelayed(); Instance().quitDelayed();
} else { } else {
QCoreApplication::quit(); QApplication::quit();
} }
} }
@ -1085,7 +1094,7 @@ void Messenger::quitPreventFinished() {
void Messenger::quitDelayed() { void Messenger::quitDelayed() {
if (!_private->quitTimer.isActive()) { if (!_private->quitTimer.isActive()) {
_private->quitTimer.setCallback([] { QCoreApplication::quit(); }); _private->quitTimer.setCallback([] { QApplication::quit(); });
_private->quitTimer.callOnce(kQuitPreventTimeoutMs); _private->quitTimer.callOnce(kQuitPreventTimeoutMs);
} }
} }

View File

@ -199,6 +199,10 @@ public:
void handleAppActivated(); void handleAppActivated();
void handleAppDeactivated(); void handleAppDeactivated();
void switchDebugMode();
void switchWorkMode();
void switchTestMode();
void call_handleUnreadCounterUpdate(); void call_handleUnreadCounterUpdate();
void call_handleDelayedPeerUpdates(); void call_handleDelayedPeerUpdates();
void call_handleObservables(); void call_handleObservables();
@ -211,17 +215,13 @@ protected:
bool eventFilter(QObject *object, QEvent *event) override; bool eventFilter(QObject *object, QEvent *event) override;
public slots: public slots:
void onAllKeysDestroyed();
void onSwitchDebugMode();
void onSwitchWorkMode();
void onSwitchTestMode();
void killDownloadSessions(); void killDownloadSessions();
void onAppStateChanged(Qt::ApplicationState state); void onAppStateChanged(Qt::ApplicationState state);
private: private:
void destroyMtpKeys(MTP::AuthKeysList &&keys); void destroyMtpKeys(MTP::AuthKeysList &&keys);
void allKeysDestroyed();
void startLocalStorage(); void startLocalStorage();
void startShortcuts(); void startShortcuts();
@ -238,8 +238,8 @@ private:
not_null<Core::Launcher*> _launcher; not_null<Core::Launcher*> _launcher;
QMap<MTP::DcId, TimeMs> killDownloadSessionTimes; base::flat_map<MTP::DcId, TimeMs> _killDownloadSessionTimes;
SingleTimer killDownloadSessionsTimer; base::Timer _killDownloadSessionsTimer;
// Some fields are just moved from the declaration. // Some fields are just moved from the declaration.
struct Private; struct Private;

View File

@ -37,6 +37,7 @@ class RSAPublicKey;
struct ConnectionOptions; struct ConnectionOptions;
class Thread : public QThread { class Thread : public QThread {
// The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
public: public:

View File

@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "core/single_timer.h"
#include "mtproto/type_utils.h" #include "mtproto/type_utils.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"

View File

@ -361,7 +361,7 @@ void Instance::Private::setGoodProxyDomain(
} }
if (applyToProxy(Global::RefSelectedProxy()) if (applyToProxy(Global::RefSelectedProxy())
&& (Global::ProxySettings() == ProxyData::Settings::Enabled)) { && (Global::ProxySettings() == ProxyData::Settings::Enabled)) {
Sandbox::refreshGlobalProxy(); Core::App().refreshGlobalProxy();
} }
} }

View File

@ -122,13 +122,12 @@ void SessionData::clear(Instance *instance) {
Session::Session(not_null<Instance*> instance, ShiftedDcId shiftedDcId) : QObject() Session::Session(not_null<Instance*> instance, ShiftedDcId shiftedDcId) : QObject()
, _instance(instance) , _instance(instance)
, data(this) , data(this)
, dcWithShift(shiftedDcId) { , dcWithShift(shiftedDcId)
, sender([=] { needToResumeAndSend(); }) {
connect(&timeouter, SIGNAL(timeout()), this, SLOT(checkRequestsByTimer())); connect(&timeouter, SIGNAL(timeout()), this, SLOT(checkRequestsByTimer()));
timeouter.start(1000); timeouter.start(1000);
refreshOptions(); refreshOptions();
connect(&sender, SIGNAL(timeout()), this, SLOT(needToResumeAndSend()));
} }
void Session::start() { void Session::start() {
@ -247,10 +246,10 @@ void Session::sendAnything(qint64 msCanWait) {
if (msWait) { if (msWait) {
DEBUG_LOG(("MTP Info: dcWithShift %1 can wait for %2ms from current %3").arg(dcWithShift).arg(msWait).arg(msSendCall)); DEBUG_LOG(("MTP Info: dcWithShift %1 can wait for %2ms from current %3").arg(dcWithShift).arg(msWait).arg(msSendCall));
msSendCall = ms; msSendCall = ms;
sender.start(msWait); sender.callOnce(msWait);
} else { } else {
DEBUG_LOG(("MTP Info: dcWithShift %1 stopped send timer, can wait for %2ms from current %3").arg(dcWithShift).arg(msWait).arg(msSendCall)); DEBUG_LOG(("MTP Info: dcWithShift %1 stopped send timer, can wait for %2ms from current %3").arg(dcWithShift).arg(msWait).arg(msSendCall));
sender.stop(); sender.cancel();
msSendCall = 0; msSendCall = 0;
needToResumeAndSend(); needToResumeAndSend();
} }

View File

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "core/single_timer.h" #include "base/timer.h"
#include "mtproto/rpc_sender.h" #include "mtproto/rpc_sender.h"
namespace MTP { namespace MTP {
@ -394,7 +394,7 @@ private:
bool _ping = false; bool _ping = false;
QTimer timeouter; QTimer timeouter;
SingleTimer sender; base::Timer sender;
}; };

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "storage/storage_media_prepare.h" #include "storage/storage_media_prepare.h"
#include "storage/file_upload.h" // For Storage::kUseBigFilesFrom.
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_passport.h" #include "styles/style_passport.h"
@ -31,7 +32,7 @@ constexpr auto kMaxDimensions = 2048;
constexpr auto kMaxSize = 10 * 1024 * 1024; constexpr auto kMaxSize = 10 * 1024 * 1024;
constexpr auto kJpegQuality = 89; constexpr auto kJpegQuality = 89;
static_assert(kMaxSize <= UseBigFilesFrom); static_assert(kMaxSize <= Storage::kUseBigFilesFrom);
base::variant<ReadScanError, QByteArray> ProcessImage(QByteArray &&bytes) { base::variant<ReadScanError, QByteArray> ProcessImage(QByteArray &&bytes) {
auto image = App::readImage(base::take(bytes)); auto image = App::readImage(base::take(bytes));

View File

@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
class MainWindow : public Window::MainWindow { class MainWindow : public Window::MainWindow {
// The Q_OBJECT meta info is used for qobject_cast to MainWindow! // The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
public: public:

View File

@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_window.h" #include "styles/style_window.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "application.h"
#include "messenger.h" #include "messenger.h"
#include "auth_session.h" #include "auth_session.h"
#include "history/history.h" #include "history/history.h"
@ -70,7 +69,7 @@ public:
LayerCreationChecker(NSView * __weak view, Fn<void()> callback) LayerCreationChecker(NSView * __weak view, Fn<void()> callback)
: _weakView(view) : _weakView(view)
, _callback(std::move(callback)) { , _callback(std::move(callback)) {
QCoreApplication::instance()->installEventFilter(this); QApplication::instance()->installEventFilter(this);
} }
protected: protected:
@ -334,7 +333,7 @@ bool MainWindow::Private::clipboardHasText() {
auto currentChangeCount = static_cast<int>([_generalPasteboard changeCount]); auto currentChangeCount = static_cast<int>([_generalPasteboard changeCount]);
if (_generalPasteboardChangeCount != currentChangeCount) { if (_generalPasteboardChangeCount != currentChangeCount) {
_generalPasteboardChangeCount = currentChangeCount; _generalPasteboardChangeCount = currentChangeCount;
_generalPasteboardHasText = !Application::clipboard()->text().isEmpty(); _generalPasteboardHasText = !QApplication::clipboard()->text().isEmpty();
} }
return _generalPasteboardHasText; return _generalPasteboardHasText;
} }

View File

@ -179,7 +179,7 @@ public:
return false; return false;
} }
QRect avail(Sandbox::availableGeometry()); const auto avail = QApplication::desktop()->availableGeometry();
max_w = avail.width(); max_w = avail.width();
accumulate_max(max_w, st::windowMinWidth); accumulate_max(max_w, st::windowMinWidth);
max_h = avail.height(); max_h = avail.height();

View File

@ -374,8 +374,8 @@ private:
}; };
Manager::Private::Private(Manager *instance, Type type) Manager::Private::Private(Manager *instance, Type type)
: _guarded(std::make_shared<Manager*>(instance)) : _cachedUserpics(type)
, _cachedUserpics(type) { , _guarded(std::make_shared<Manager*>(instance)) {
} }
bool Manager::Private::init() { bool Manager::Private::init() {

View File

@ -34,7 +34,7 @@ auto GenerateCodes() {
: qsl("Do you want to enable DEBUG logs?\n\n" : qsl("Do you want to enable DEBUG logs?\n\n"
"All network events will be logged."); "All network events will be logged.");
Ui::show(Box<ConfirmBox>(text, [] { Ui::show(Box<ConfirmBox>(text, [] {
Messenger::Instance().onSwitchDebugMode(); Messenger::Instance().switchDebugMode();
})); }));
}); });
codes.emplace(qsl("viewlogs"), [] { codes.emplace(qsl("viewlogs"), [] {
@ -43,7 +43,7 @@ auto GenerateCodes() {
codes.emplace(qsl("testmode"), [] { codes.emplace(qsl("testmode"), [] {
auto text = cTestMode() ? qsl("Do you want to disable TEST mode?") : qsl("Do you want to enable TEST mode?\n\nYou will be switched to test cloud."); auto text = cTestMode() ? qsl("Do you want to disable TEST mode?") : qsl("Do you want to enable TEST mode?\n\nYou will be switched to test cloud.");
Ui::show(Box<ConfirmBox>(text, [] { Ui::show(Box<ConfirmBox>(text, [] {
Messenger::Instance().onSwitchTestMode(); Messenger::Instance().switchTestMode();
})); }));
}); });
if (!Core::UpdaterDisabled()) { if (!Core::UpdaterDisabled()) {
@ -71,7 +71,7 @@ auto GenerateCodes() {
codes.emplace(qsl("workmode"), [] { codes.emplace(qsl("workmode"), [] {
auto text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?"); auto text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?");
Ui::show(Box<ConfirmBox>(text, [] { Ui::show(Box<ConfirmBox>(text, [] {
Messenger::Instance().onSwitchWorkMode(); Messenger::Instance().switchWorkMode();
})); }));
}); });
codes.emplace(qsl("moderate"), [] { codes.emplace(qsl("moderate"), [] {

View File

@ -1440,18 +1440,18 @@ void WebLoadManager::onFailed(QNetworkReply *reply) {
} }
void WebLoadManager::onProgress(qint64 already, qint64 size) { void WebLoadManager::onProgress(qint64 already, qint64 size) {
QNetworkReply *reply = qobject_cast<QNetworkReply*>(QObject::sender()); const auto reply = qobject_cast<QNetworkReply*>(QObject::sender());
if (!reply) return; if (!reply) return;
Replies::iterator j = _replies.find(reply); const auto j = _replies.find(reply);
if (j == _replies.cend()) { // handled already if (j == _replies.cend()) { // handled already
return; return;
} }
webFileLoaderPrivate *loader = j.value(); const auto loader = j.value();
WebReplyProcessResult result = WebReplyProcessProgress; auto result = WebReplyProcessProgress;
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); const auto statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
int32 status = statusCode.isValid() ? statusCode.toInt() : 200; const auto status = statusCode.isValid() ? statusCode.toInt() : 200;
if (status != 200 && status != 206 && status != 416) { if (status != 200 && status != 206 && status != 416) {
if (status == 301 || status == 302) { if (status == 301 || status == 302) {
QString loc = reply->header(QNetworkRequest::LocationHeader).toString(); QString loc = reply->header(QNetworkRequest::LocationHeader).toString();
@ -1490,20 +1490,19 @@ void WebLoadManager::onProgress(qint64 already, qint64 size) {
} }
void WebLoadManager::onMeta() { void WebLoadManager::onMeta() {
QNetworkReply *reply = qobject_cast<QNetworkReply*>(QObject::sender()); const auto reply = qobject_cast<QNetworkReply*>(QObject::sender());
if (!reply) return; if (!reply) return;
Replies::iterator j = _replies.find(reply); const auto j = _replies.find(reply);
if (j == _replies.cend()) { // handled already if (j == _replies.cend()) { // handled already
return; return;
} }
webFileLoaderPrivate *loader = j.value(); const auto loader = j.value();
typedef QList<QNetworkReply::RawHeaderPair> Pairs; const auto pairs = reply->rawHeaderPairs();
Pairs pairs = reply->rawHeaderPairs(); for (auto i = pairs.begin(), e = pairs.end(); i != e; ++i) {
for (Pairs::iterator i = pairs.begin(), e = pairs.end(); i != e; ++i) {
if (QString::fromUtf8(i->first).toLower() == "content-range") { if (QString::fromUtf8(i->first).toLower() == "content-range") {
QRegularExpressionMatch m = QRegularExpression(qsl("/(\\d+)([^\\d]|$)")).match(QString::fromUtf8(i->second)); const auto m = QRegularExpression(qsl("/(\\d+)([^\\d]|$)")).match(QString::fromUtf8(i->second));
if (m.hasMatch()) { if (m.hasMatch()) {
loader->setProgress(qMax(qint64(loader->data().size()), loader->already()), m.captured(1).toLongLong()); loader->setProgress(qMax(qint64(loader->data().size()), loader->already()), m.captured(1).toLongLong());
if (!handleReplyResult(loader, WebReplyProcessProgress)) { if (!handleReplyResult(loader, WebReplyProcessProgress)) {

View File

@ -17,7 +17,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Storage { namespace Storage {
namespace { namespace {
constexpr auto kMaxUploadFileParallelSize = MTP::kUploadSessionsCount * 512 * 1024; // max 512kb uploaded at the same time in each session // max 512kb uploaded at the same time in each session
constexpr auto kMaxUploadFileParallelSize = MTP::kUploadSessionsCount * 512 * 1024;
constexpr auto kDocumentMaxPartsCount = 3000;
// 32kb for tiny document ( < 1mb )
constexpr auto kDocumentUploadPartSize0 = 32 * 1024;
// 64kb for little document ( <= 32mb )
constexpr auto kDocumentUploadPartSize1 = 64 * 1024;
// 128kb for small document ( <= 375mb )
constexpr auto kDocumentUploadPartSize2 = 128 * 1024;
// 256kb for medium document ( <= 750mb )
constexpr auto kDocumentUploadPartSize3 = 256 * 1024;
// 512kb for large document ( <= 1500mb )
constexpr auto kDocumentUploadPartSize4 = 512 * 1024;
// One part each half second, if not uploaded faster.
constexpr auto kUploadRequestInterval = TimeMs(500);
} // namespace } // namespace
@ -75,11 +96,11 @@ void Uploader::File::setDocSize(int32 size) {
docSize = size; docSize = size;
constexpr auto limit0 = 1024 * 1024; constexpr auto limit0 = 1024 * 1024;
constexpr auto limit1 = 32 * limit0; constexpr auto limit1 = 32 * limit0;
if (docSize >= limit0 || !setPartSize(DocumentUploadPartSize0)) { if (docSize >= limit0 || !setPartSize(kDocumentUploadPartSize0)) {
if (docSize > limit1 || !setPartSize(DocumentUploadPartSize1)) { if (docSize > limit1 || !setPartSize(kDocumentUploadPartSize1)) {
if (!setPartSize(DocumentUploadPartSize2)) { if (!setPartSize(kDocumentUploadPartSize2)) {
if (!setPartSize(DocumentUploadPartSize3)) { if (!setPartSize(kDocumentUploadPartSize3)) {
if (!setPartSize(DocumentUploadPartSize4)) { if (!setPartSize(kDocumentUploadPartSize4)) {
LOG(("Upload Error: bad doc size: %1").arg(docSize)); LOG(("Upload Error: bad doc size: %1").arg(docSize));
} }
} }
@ -92,7 +113,7 @@ bool Uploader::File::setPartSize(uint32 partSize) {
docPartSize = partSize; docPartSize = partSize;
docPartsCount = (docSize / docPartSize) docPartsCount = (docSize / docPartSize)
+ ((docSize % docPartSize) ? 1 : 0); + ((docSize % docPartSize) ? 1 : 0);
return (docPartsCount <= DocumentMaxPartsCount); return (docPartsCount <= kDocumentMaxPartsCount);
} }
uint64 Uploader::File::id() const { uint64 Uploader::File::id() const {
@ -288,7 +309,7 @@ void Uploader::sendNext() {
QByteArray docMd5(32, Qt::Uninitialized); QByteArray docMd5(32, Qt::Uninitialized);
hashMd5Hex(uploadingData.md5Hash.result(), docMd5.data()); hashMd5Hex(uploadingData.md5Hash.result(), docMd5.data());
const auto file = (uploadingData.docSize > UseBigFilesFrom) const auto file = (uploadingData.docSize > kUseBigFilesFrom)
? MTP_inputFileBig( ? MTP_inputFileBig(
MTP_long(uploadingData.id()), MTP_long(uploadingData.id()),
MTP_int(uploadingData.docPartsCount), MTP_int(uploadingData.docPartsCount),
@ -347,7 +368,7 @@ void Uploader::sendNext() {
} }
} }
toSend = uploadingData.docFile->read(uploadingData.docPartSize); toSend = uploadingData.docFile->read(uploadingData.docPartSize);
if (uploadingData.docSize <= UseBigFilesFrom) { if (uploadingData.docSize <= kUseBigFilesFrom) {
uploadingData.md5Hash.feed(toSend.constData(), toSend.size()); uploadingData.md5Hash.feed(toSend.constData(), toSend.size());
} }
} else { } else {
@ -356,7 +377,7 @@ void Uploader::sendNext() {
toSend = content.mid(offset, uploadingData.docPartSize); toSend = content.mid(offset, uploadingData.docPartSize);
if ((uploadingData.type() == SendMediaType::File if ((uploadingData.type() == SendMediaType::File
|| uploadingData.type() == SendMediaType::Audio) || uploadingData.type() == SendMediaType::Audio)
&& uploadingData.docSentParts <= UseBigFilesFrom) { && uploadingData.docSentParts <= kUseBigFilesFrom) {
uploadingData.md5Hash.feed(toSend.constData(), toSend.size()); uploadingData.md5Hash.feed(toSend.constData(), toSend.size());
} }
} }
@ -367,7 +388,7 @@ void Uploader::sendNext() {
return; return;
} }
mtpRequestId requestId; mtpRequestId requestId;
if (uploadingData.docSize > UseBigFilesFrom) { if (uploadingData.docSize > kUseBigFilesFrom) {
requestId = MTP::send( requestId = MTP::send(
MTPupload_SaveBigFilePart( MTPupload_SaveBigFilePart(
MTP_long(uploadingData.id()), MTP_long(uploadingData.id()),
@ -411,7 +432,7 @@ void Uploader::sendNext() {
parts.erase(part); parts.erase(part);
} }
nextTimer.start(UploadRequestInterval); nextTimer.start(kUploadRequestInterval);
} }
void Uploader::cancel(const FullMsgId &msgId) { void Uploader::cancel(const FullMsgId &msgId) {

View File

@ -12,6 +12,9 @@ struct SendMediaReady;
namespace Storage { namespace Storage {
// MTP big files methods used for files greater than 10mb.
constexpr auto kUseBigFilesFrom = 10 * 1024 * 1024;
struct UploadedPhoto { struct UploadedPhoto {
FullMsgId fullId; FullMsgId fullId;
bool silent = false; bool silent = false;

View File

@ -25,6 +25,9 @@ namespace {
constexpr auto kThumbnailQuality = 87; constexpr auto kThumbnailQuality = 87;
constexpr auto kThumbnailSize = 320; constexpr auto kThumbnailSize = 320;
constexpr auto kPhotoUploadPartSize = 32 * 1024;
using Storage::ValidateThumbDimensions;
struct PreparedFileThumbnail { struct PreparedFileThumbnail {
uint64 id = 0; uint64 id = 0;
@ -37,7 +40,7 @@ struct PreparedFileThumbnail {
PreparedFileThumbnail PrepareFileThumbnail(QImage &&original) { PreparedFileThumbnail PrepareFileThumbnail(QImage &&original) {
const auto width = original.width(); const auto width = original.width();
const auto height = original.height(); const auto height = original.height();
if (!Storage::ValidateThumbDimensions(width, height)) { if (!ValidateThumbDimensions(width, height)) {
return {}; return {};
} }
auto result = PreparedFileThumbnail(); auto result = PreparedFileThumbnail();
@ -133,7 +136,43 @@ MTPInputSingleMedia PrepareAlbumItemMedia(
} // namespace } // namespace
using Storage::ValidateThumbDimensions; SendMediaReady::SendMediaReady(
SendMediaType type,
const QString &file,
const QString &filename,
int32 filesize,
const QByteArray &data,
const uint64 &id,
const uint64 &thumbId,
const QString &thumbExt,
const PeerId &peer,
const MTPPhoto &photo,
const PreparedPhotoThumbs &photoThumbs,
const MTPDocument &document,
const QByteArray &jpeg,
MsgId replyTo)
: replyTo(replyTo)
, type(type)
, file(file)
, filename(filename)
, filesize(filesize)
, data(data)
, thumbExt(thumbExt)
, id(id)
, thumbId(thumbId)
, peer(peer)
, photo(photo)
, document(document)
, photoThumbs(photoThumbs) {
if (!jpeg.isEmpty()) {
int32 size = jpeg.size();
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
parts.insert(part, jpeg.mid(i, kPhotoUploadPartSize));
}
jpeg_md5.resize(32);
hashMd5Hex(jpeg.constData(), jpeg.size(), jpeg_md5.data());
}
}
SendMediaReady PreparePeerPhoto(PeerId peerId, QImage &&image) { SendMediaReady PreparePeerPhoto(PeerId peerId, QImage &&image) {
PreparedPhotoThumbs photoThumbs; PreparedPhotoThumbs photoThumbs;
@ -290,10 +329,8 @@ void TaskQueue::stop() {
_thread->quit(); _thread->quit();
DEBUG_LOG(("Waiting for taskThread to finish")); DEBUG_LOG(("Waiting for taskThread to finish"));
_thread->wait(); _thread->wait();
delete _worker; delete base::take(_worker);
delete _thread; delete base::take(_thread);
_worker = 0;
_thread = 0;
} }
_tasksToProcess.clear(); _tasksToProcess.clear();
_tasksToFinish.clear(); _tasksToFinish.clear();
@ -399,6 +436,31 @@ FileLoadResult::FileLoadResult(
, caption(caption) { , caption(caption) {
} }
void FileLoadResult::setFileData(const QByteArray &filedata) {
if (filedata.isEmpty()) {
partssize = 0;
} else {
partssize = filedata.size();
for (int32 i = 0, part = 0; i < partssize; i += kPhotoUploadPartSize, ++part) {
fileparts.insert(part, filedata.mid(i, kPhotoUploadPartSize));
}
filemd5.resize(32);
hashMd5Hex(filedata.constData(), filedata.size(), filemd5.data());
}
}
void FileLoadResult::setThumbData(const QByteArray &thumbdata) {
if (!thumbdata.isEmpty()) {
int32 size = thumbdata.size();
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
thumbparts.insert(part, thumbdata.mid(i, kPhotoUploadPartSize));
}
thumbmd5.resize(32);
hashMd5Hex(thumbdata.constData(), thumbdata.size(), thumbmd5.data());
}
}
FileLoadTask::FileLoadTask( FileLoadTask::FileLoadTask(
const QString &filepath, const QString &filepath,
const QByteArray &content, const QByteArray &content,

View File

@ -47,29 +47,22 @@ using SendMediaPrepareList = QList<SendMediaPrepare>;
using UploadFileParts = QMap<int, QByteArray>; using UploadFileParts = QMap<int, QByteArray>;
struct SendMediaReady { struct SendMediaReady {
SendMediaReady() = default; // temp SendMediaReady() = default; // temp
SendMediaReady(SendMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, MsgId replyTo) SendMediaReady(
: replyTo(replyTo) SendMediaType type,
, type(type) const QString &file,
, file(file) const QString &filename,
, filename(filename) int32 filesize,
, filesize(filesize) const QByteArray &data,
, data(data) const uint64 &id,
, thumbExt(thumbExt) const uint64 &thumbId,
, id(id) const QString &thumbExt,
, thumbId(thumbId) const PeerId &peer,
, peer(peer) const MTPPhoto &photo,
, photo(photo) const PreparedPhotoThumbs &photoThumbs,
, document(document) const MTPDocument &document,
, photoThumbs(photoThumbs) { const QByteArray &jpeg,
if (!jpeg.isEmpty()) { MsgId replyTo);
int32 size = jpeg.size();
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
parts.insert(part, jpeg.mid(i, UploadPartSize));
}
jpeg_md5.resize(32);
hashMd5Hex(jpeg.constData(), jpeg.size(), jpeg_md5.data());
}
}
MsgId replyTo; MsgId replyTo;
SendMediaType type; SendMediaType type;
QString file, filename; QString file, filename;
@ -233,28 +226,9 @@ struct FileLoadResult {
PreparedPhotoThumbs photoThumbs; PreparedPhotoThumbs photoThumbs;
TextWithTags caption; TextWithTags caption;
void setFileData(const QByteArray &filedata) { void setFileData(const QByteArray &filedata);
if (filedata.isEmpty()) { void setThumbData(const QByteArray &thumbdata);
partssize = 0;
} else {
partssize = filedata.size();
for (int32 i = 0, part = 0; i < partssize; i += UploadPartSize, ++part) {
fileparts.insert(part, filedata.mid(i, UploadPartSize));
}
filemd5.resize(32);
hashMd5Hex(filedata.constData(), filedata.size(), filemd5.data());
}
}
void setThumbData(const QByteArray &thumbdata) {
if (!thumbdata.isEmpty()) {
int32 size = thumbdata.size();
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
thumbparts.insert(part, thumbdata.mid(i, UploadPartSize));
}
thumbmd5.resize(32);
hashMd5Hex(thumbdata.constData(), thumbdata.size(), thumbmd5.data());
}
}
}; };
struct FileMediaInformation { struct FileMediaInformation {

View File

@ -1283,7 +1283,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
} else { } else {
Global::SetProxiesList({}); Global::SetProxiesList({});
} }
Sandbox::refreshGlobalProxy(); Core::App().refreshGlobalProxy();
} break; } break;
case dbiConnectionType: { case dbiConnectionType: {
@ -1383,7 +1383,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
Global::SetProxySettings(ProxyData::Settings::System); Global::SetProxySettings(ProxyData::Settings::System);
} }
} }
Sandbox::refreshGlobalProxy(); Core::App().refreshGlobalProxy();
} break; } break;
case dbiThemeKeyOld: { case dbiThemeKeyOld: {

View File

@ -20,8 +20,8 @@ NeverFreedPointer<QMap<QObject*, Manager*>> _managers;
} // namespace } // namespace
Manager::Manager(QWidget *parent) : QObject(parent) { Manager::Manager(QWidget *parent) : QObject(parent)
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(onHideTimeout())); , _hideTimer([=] { hideByTimer(); }) {
} }
bool Manager::eventFilter(QObject *o, QEvent *e) { bool Manager::eventFilter(QObject *o, QEvent *e) {
@ -80,7 +80,7 @@ void Manager::addToast(std::unique_ptr<Instance> &&toast) {
} }
} }
void Manager::onHideTimeout() { void Manager::hideByTimer() {
auto now = getms(true); auto now = getms(true);
for (auto i = _toastByHideTime.begin(); i != _toastByHideTime.cend();) { for (auto i = _toastByHideTime.begin(); i != _toastByHideTime.cend();) {
if (i.key() <= now) { if (i.key() <= now) {
@ -114,9 +114,11 @@ void Manager::startNextHideTimer() {
auto ms = getms(true); auto ms = getms(true);
if (ms >= _toastByHideTime.firstKey()) { if (ms >= _toastByHideTime.firstKey()) {
QMetaObject::invokeMethod(this, SLOT("onHideTimeout"), Qt::QueuedConnection); crl::on_main(this, [=] {
hideByTimer();
});
} else { } else {
_hideTimer.start(_toastByHideTime.firstKey() - ms); _hideTimer.callOnce(_toastByHideTime.firstKey() - ms);
} }
} }

View File

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "core/single_timer.h" #include "base/timer.h"
namespace Ui { namespace Ui {
namespace Toast { namespace Toast {
@ -32,14 +32,14 @@ protected:
bool eventFilter(QObject *o, QEvent *e); bool eventFilter(QObject *o, QEvent *e);
private slots: private slots:
void onHideTimeout();
void onToastWidgetDestroyed(QObject *widget); void onToastWidgetDestroyed(QObject *widget);
private: private:
Manager(QWidget *parent); Manager(QWidget *parent);
void startNextHideTimer(); void startNextHideTimer();
void hideByTimer();
SingleTimer _hideTimer; base::Timer _hideTimer;
TimeMs _nextHide = 0; TimeMs _nextHide = 0;
QMultiMap<TimeMs, Instance*> _toastByHideTime; QMultiMap<TimeMs, Instance*> _toastByHideTime;

View File

@ -234,8 +234,7 @@ void ForceFullRepaint(not_null<QWidget*> widget) {
} }
void PostponeCall(FnMut<void()> &&callable) { void PostponeCall(FnMut<void()> &&callable) {
const auto application = static_cast<Application*>(qApp); Core::App().postponeCall(std::move(callable));
application->postponeCall(std::move(callable));
} }
} // namespace Ui } // namespace Ui

View File

@ -341,6 +341,7 @@ private:
}; };
class TWidget : public TWidgetHelper<QWidget> { class TWidget : public TWidgetHelper<QWidget> {
// The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
public: public:

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/continuous_sliders.h"
#include "base/timer.h"
namespace Ui { namespace Ui {
namespace { namespace {
@ -29,14 +31,13 @@ void ContinuousSlider::setDisabled(bool disabled) {
void ContinuousSlider::setMoveByWheel(bool move) { void ContinuousSlider::setMoveByWheel(bool move) {
if (move != moveByWheel()) { if (move != moveByWheel()) {
if (move) { if (move) {
_byWheelFinished = std::make_unique<SingleTimer>(); _byWheelFinished = std::make_unique<base::Timer>([=] {
_byWheelFinished->setTimeoutHandler([this] {
if (_changeFinishedCallback) { if (_changeFinishedCallback) {
_changeFinishedCallback(getCurrentValue()); _changeFinishedCallback(getCurrentValue());
} }
}); });
} else { } else {
_byWheelFinished.reset(); _byWheelFinished = nullptr;
} }
} }
} }
@ -109,7 +110,7 @@ void ContinuousSlider::wheelEvent(QWheelEvent *e) {
if (_changeProgressCallback) { if (_changeProgressCallback) {
_changeProgressCallback(finalValue); _changeProgressCallback(finalValue);
} }
_byWheelFinished->start(kByWheelFinishedTimeout); _byWheelFinished->callOnce(kByWheelFinishedTimeout);
} }
void ContinuousSlider::updateDownValueFromPos(const QPoint &pos) { void ContinuousSlider::updateDownValueFromPos(const QPoint &pos) {

View File

@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
namespace base {
class Timer;
} // namespace base
namespace Ui { namespace Ui {
class ContinuousSlider : public RpWidget { class ContinuousSlider : public RpWidget {
@ -87,7 +91,7 @@ private:
Direction _direction = Direction::Horizontal; Direction _direction = Direction::Horizontal;
bool _disabled = false; bool _disabled = false;
std::unique_ptr<SingleTimer> _byWheelFinished; std::unique_ptr<base::Timer> _byWheelFinished;
Fn<float64(float64)> _adjustCallback; Fn<float64(float64)> _adjustCallback;
Fn<void(float64)> _changeProgressCallback; Fn<void(float64)> _changeProgressCallback;

View File

@ -231,7 +231,7 @@ void DropdownMenu::hideFinish() {
// //
// auto menuTopLeft = mapFromGlobal(_menu->mapToGlobal(QPoint(0, 0))); // auto menuTopLeft = mapFromGlobal(_menu->mapToGlobal(QPoint(0, 0)));
// auto w = p - QPoint(0, menuTopLeft.y()); // auto w = p - QPoint(0, menuTopLeft.y());
// auto r = Sandbox::screenGeometry(p); // auto r = QApplication::desktop()->screenGeometry(p);
// if (rtl()) { // if (rtl()) {
// if (w.x() - width() < r.x() - _padding.left()) { // if (w.x() - width() < r.x() - _padding.left()) {
// if (_parent && w.x() + _parent->width() - _padding.left() - _padding.right() + width() - _padding.right() <= r.x() + r.width()) { // if (_parent && w.x() + _parent->width() - _padding.left() - _padding.right() + width() - _padding.right() <= r.x() + r.width()) {

View File

@ -528,12 +528,12 @@ public:
setParent(QCoreApplication::instance()); setParent(QCoreApplication::instance());
} }
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const { void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override {
} }
QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const { QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = nullptr) const override {
switch (r) { switch (r) {
case SE_LineEditContents: case SE_LineEditContents:
const InputClass *w = widget ? qobject_cast<const InputClass*>(widget) : 0; const auto w = widget ? qobject_cast<const InputClass*>(widget) : nullptr;
return w ? w->getTextRect() : QCommonStyle::subElementRect(r, opt, widget); return w ? w->getTextRect() : QCommonStyle::subElementRect(r, opt, widget);
break; break;
} }

View File

@ -41,6 +41,7 @@ enum class InputSubmitSettings {
}; };
class FlatInput : public TWidgetHelper<QLineEdit>, private base::Subscriber { class FlatInput : public TWidgetHelper<QLineEdit>, private base::Subscriber {
// The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
public: public:
@ -493,6 +494,7 @@ private:
class MaskedInputField class MaskedInputField
: public RpWidgetWrap<QLineEdit> : public RpWidgetWrap<QLineEdit>
, private base::Subscriber { , private base::Subscriber {
// The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
using Parent = RpWidgetWrap<QLineEdit>; using Parent = RpWidgetWrap<QLineEdit>;

View File

@ -447,7 +447,7 @@ void PopupMenu::showMenu(const QPoint &p, PopupMenu *parent, TriggeredSource sou
auto origin = PanelAnimation::Origin::TopLeft; auto origin = PanelAnimation::Origin::TopLeft;
auto w = p - QPoint(0, _padding.top()); auto w = p - QPoint(0, _padding.top());
auto r = Sandbox::screenGeometry(p); auto r = QApplication::desktop()->screenGeometry(p);
_useTransparency = Platform::TranslucentWindowsSupported(p); _useTransparency = Platform::TranslucentWindowsSupported(p);
setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency); setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
handleCompositingUpdate(); handleCompositingUpdate();

View File

@ -636,7 +636,7 @@ void ScrollArea::resizeEvent(QResizeEvent *e) {
_verticalBar->recountSize(); _verticalBar->recountSize();
_topShadow->setGeometry(QRect(0, 0, width(), qAbs(_st.topsh))); _topShadow->setGeometry(QRect(0, 0, width(), qAbs(_st.topsh)));
_bottomShadow->setGeometry(QRect(0, height() - qAbs(_st.bottomsh), width(), qAbs(_st.bottomsh))); _bottomShadow->setGeometry(QRect(0, height() - qAbs(_st.bottomsh), width(), qAbs(_st.bottomsh)));
if (SplittedWidget *w = qobject_cast<SplittedWidget*>(widget())) { if (const auto w = qobject_cast<SplittedWidget*>(widget())) {
w->resize(width() - w->otherWidth(), w->height()); w->resize(width() - w->otherWidth(), w->height());
if (!rtl()) { if (!rtl()) {
_other->move(w->width(), w->y()); _other->move(w->width(), w->y());
@ -720,7 +720,7 @@ void ScrollArea::scrollToY(int toTop, int toBottom) {
} }
void ScrollArea::doSetOwnedWidget(object_ptr<TWidget> w) { void ScrollArea::doSetOwnedWidget(object_ptr<TWidget> w) {
auto splitted = qobject_cast<SplittedWidget*>(w.data()); const auto splitted = qobject_cast<SplittedWidget*>(w.data());
if (widget() && _touchEnabled) { if (widget() && _touchEnabled) {
widget()->removeEventFilter(this); widget()->removeEventFilter(this);
if (!_widgetAcceptsTouch) widget()->setAttribute(Qt::WA_AcceptTouchEvents, false); if (!_widgetAcceptsTouch) widget()->setAttribute(Qt::WA_AcceptTouchEvents, false);

View File

@ -110,6 +110,7 @@ private:
}; };
class SplittedWidget : public Ui::RpWidget { class SplittedWidget : public Ui::RpWidget {
// The Q_OBJECT meta info is used for qobject_cast!
Q_OBJECT Q_OBJECT
public: public:

View File

@ -33,14 +33,12 @@ constexpr auto kMinimalAlertDelay = TimeMs(500);
} // namespace } // namespace
System::System(AuthSession *session) : _authSession(session) { System::System(AuthSession *session)
: _authSession(session)
, _waitTimer([=] { showNext(); }) {
createManager(); createManager();
_waitTimer.setTimeoutHandler([this] { subscribe(settingsChanged(), [=](ChangeType type) {
showNext();
});
subscribe(settingsChanged(), [this](ChangeType type) {
if (type == ChangeType::DesktopEnabled) { if (type == ChangeType::DesktopEnabled) {
App::wnd()->updateTrayMenu(); App::wnd()->updateTrayMenu();
clearAll(); clearAll();
@ -124,7 +122,7 @@ void System::schedule(History *history, HistoryItem *item) {
} }
if (haveSetting) { if (haveSetting) {
if (!_waitTimer.isActive() || _waitTimer.remainingTime() > delay) { if (!_waitTimer.isActive() || _waitTimer.remainingTime() > delay) {
_waitTimer.start(delay); _waitTimer.callOnce(delay);
} }
} }
} }
@ -150,7 +148,7 @@ void System::clearFromHistory(History *history) {
_waiters.remove(history); _waiters.remove(history);
_settingWaiters.remove(history); _settingWaiters.remove(history);
_waitTimer.stop(); _waitTimer.cancel();
showNext(); showNext();
} }
@ -209,7 +207,7 @@ void System::checkDelayed() {
++i; ++i;
} }
} }
_waitTimer.stop(); _waitTimer.cancel();
showNext(); showNext();
} }
@ -259,7 +257,7 @@ void System::showNext() {
if (_waiters.isEmpty() || !Global::DesktopNotify() || Platform::Notifications::SkipToast()) { if (_waiters.isEmpty() || !Global::DesktopNotify() || Platform::Notifications::SkipToast()) {
if (nextAlert) { if (nextAlert) {
_waitTimer.start(nextAlert - ms); _waitTimer.callOnce(nextAlert - ms);
} }
return; return;
} }
@ -306,7 +304,7 @@ void System::showNext() {
next = nextAlert; next = nextAlert;
nextAlert = 0; nextAlert = 0;
} }
_waitTimer.start(next - ms); _waitTimer.callOnce(next - ms);
break; break;
} else { } else {
auto forwardedItem = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping auto forwardedItem = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
@ -366,7 +364,7 @@ void System::showNext() {
} }
} }
if (nextAlert) { if (nextAlert) {
_waitTimer.start(nextAlert - ms); _waitTimer.callOnce(nextAlert - ms);
} }
} }

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "base/timer.h"
class AuthSession; class AuthSession;
namespace Platform { namespace Platform {
@ -96,7 +98,7 @@ private:
using Waiters = QMap<History*, Waiter>; using Waiters = QMap<History*, Waiter>;
Waiters _waiters; Waiters _waiters;
Waiters _settingWaiters; Waiters _settingWaiters;
SingleTimer _waitTimer; base::Timer _waitTimer;
QMap<History*, QMap<TimeMs, PeerData*>> _whenAlerts; QMap<History*, QMap<TimeMs, PeerData*>> _whenAlerts;

View File

@ -53,7 +53,9 @@ std::unique_ptr<Manager> Create(System *system) {
return std::make_unique<Manager>(system); return std::make_unique<Manager>(system);
} }
Manager::Manager(System *system) : Notifications::Manager(system) { Manager::Manager(System *system)
: Notifications::Manager(system)
, _inputCheckTimer([=] { checkLastInput(); }) {
subscribe(system->authSession()->downloader().taskFinished(), [this] { subscribe(system->authSession()->downloader().taskFinished(), [this] {
for_const (auto &notification, _notifications) { for_const (auto &notification, _notifications) {
notification->updatePeerPhoto(); notification->updatePeerPhoto();
@ -62,7 +64,6 @@ Manager::Manager(System *system) : Notifications::Manager(system) {
subscribe(system->settingsChanged(), [this](ChangeType change) { subscribe(system->settingsChanged(), [this](ChangeType change) {
settingsChanged(change); settingsChanged(change);
}); });
_inputCheckTimer.setTimeoutHandler([this] { checkLastInput(); });
} }
Manager::QueuedNotification::QueuedNotification( Manager::QueuedNotification::QueuedNotification(
@ -144,7 +145,7 @@ void Manager::checkLastInput() {
} }
} }
if (waiting) { if (waiting) {
_inputCheckTimer.start(300); _inputCheckTimer.callOnce(300);
} }
} }
@ -494,15 +495,25 @@ void Background::paintEvent(QPaintEvent *e) {
p.fillRect(st::notifyBorderWidth, height() - st::notifyBorderWidth, width() - 2 * st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder); p.fillRect(st::notifyBorderWidth, height() - st::notifyBorderWidth, width() - 2 * st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder);
} }
Notification::Notification(Manager *manager, History *history, PeerData *peer, PeerData *author, HistoryItem *msg, int forwardedCount, QPoint startPosition, int shift, Direction shiftDirection) : Widget(manager, startPosition, shift, shiftDirection) Notification::Notification(
Manager *manager,
History *history,
PeerData *peer,
PeerData *author,
HistoryItem *msg,
int forwardedCount,
QPoint startPosition,
int shift,
Direction shiftDirection)
: Widget(manager, startPosition, shift, shiftDirection)
#ifdef Q_OS_WIN
, _started(GetTickCount())
#endif // Q_OS_WIN
, _history(history) , _history(history)
, _peer(peer) , _peer(peer)
, _author(author) , _author(author)
, _item(msg) , _item(msg)
, _forwardedCount(forwardedCount) , _forwardedCount(forwardedCount)
#ifdef Q_OS_WIN
, _started(GetTickCount())
#endif // Q_OS_WIN
, _close(this, st::notifyClose) , _close(this, st::notifyClose)
, _reply(this, langFactory(lng_notification_reply), st::defaultBoxButton) { , _reply(this, langFactory(lng_notification_reply), st::defaultBoxButton) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); }); subscribe(Lang::Current().updated(), [this] { refreshLang(); });

View File

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "core/single_timer.h" #include "base/timer.h"
namespace Ui { namespace Ui {
class IconButton; class IconButton;
@ -79,7 +79,7 @@ private:
std::unique_ptr<HideAllButton> _hideAll; std::unique_ptr<HideAllButton> _hideAll;
bool _positionsOutdated = false; bool _positionsOutdated = false;
SingleTimer _inputCheckTimer; base::Timer _inputCheckTimer;
struct QueuedNotification { struct QueuedNotification {
QueuedNotification(not_null<HistoryItem*> item, int forwardedCount); QueuedNotification(not_null<HistoryItem*> item, int forwardedCount);

View File

@ -21,8 +21,9 @@ constexpr int kNotifyDeletePhotoAfterMs = 60000;
} // namespace } // namespace
CachedUserpics::CachedUserpics(Type type) : _type(type) { CachedUserpics::CachedUserpics(Type type)
connect(&_clearTimer, SIGNAL(timeout()), this, SLOT(onClear())); : _type(type)
, _clearTimer([=] { onClear(); }) {
QDir().mkpath(cWorkingDir() + qsl("tdata/temp")); QDir().mkpath(cWorkingDir() + qsl("tdata/temp"));
} }
@ -87,7 +88,7 @@ void CachedUserpics::clearInMs(int ms) {
return; return;
} }
} }
_clearTimer.start(ms); _clearTimer.callOnce(ms);
} }
void CachedUserpics::onClear() { void CachedUserpics::onClear() {

View File

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "core/single_timer.h" #include "base/timer.h"
namespace Window { namespace Window {
namespace Notifications { namespace Notifications {
@ -42,7 +42,7 @@ private:
using Images = QMap<StorageKey, Image>; using Images = QMap<StorageKey, Image>;
Images _images; Images _images;
bool _someSavedFlag = false; bool _someSavedFlag = false;
SingleTimer _clearTimer; base::Timer _clearTimer;
}; };

View File

@ -21,13 +21,14 @@ constexpr int kWaitBeforeRevertMs = 15999;
} // namespace } // namespace
WarningWidget::WarningWidget(QWidget *parent) : TWidget(parent) WarningWidget::WarningWidget(QWidget *parent)
: TWidget(parent)
, _timer([=] { handleTimer(); })
, _secondsLeft(kWaitBeforeRevertMs / 1000) , _secondsLeft(kWaitBeforeRevertMs / 1000)
, _keepChanges(this, langFactory(lng_theme_keep_changes), st::defaultBoxButton) , _keepChanges(this, langFactory(lng_theme_keep_changes), st::defaultBoxButton)
, _revert(this, langFactory(lng_theme_revert), st::defaultBoxButton) { , _revert(this, langFactory(lng_theme_revert), st::defaultBoxButton) {
_keepChanges->setClickedCallback([] { Window::Theme::KeepApplied(); }); _keepChanges->setClickedCallback([] { Window::Theme::KeepApplied(); });
_revert->setClickedCallback([] { Window::Theme::Revert(); }); _revert->setClickedCallback([] { Window::Theme::Revert(); });
_timer.setTimeoutHandler([this] { handleTimer(); });
updateText(); updateText();
} }
@ -52,7 +53,7 @@ void WarningWidget::paintEvent(QPaintEvent *e) {
_cache = QPixmap(); _cache = QPixmap();
showChildren(); showChildren();
_started = getms(true); _started = getms(true);
_timer.start(100); _timer.callOnce(100);
} }
return; return;
} }
@ -100,7 +101,7 @@ void WarningWidget::setSecondsLeft(int secondsLeft) {
updateText(); updateText();
update(); update();
} }
_timer.start(100); _timer.callOnce(100);
} }
} }
@ -119,7 +120,7 @@ void WarningWidget::hideAnimated() {
} }
void WarningWidget::startAnimation(bool hiding) { void WarningWidget::startAnimation(bool hiding) {
_timer.stop(); _timer.cancel();
_hiding = hiding; _hiding = hiding;
if (_cache.isNull()) { if (_cache.isNull()) {
showChildren(); showChildren();

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "base/timer.h"
namespace Ui { namespace Ui {
class RoundButton; class RoundButton;
} // namespace Ui } // namespace Ui
@ -43,7 +45,7 @@ private:
QPixmap _cache; QPixmap _cache;
QRect _inner, _outer; QRect _inner, _outer;
SingleTimer _timer; base::Timer _timer;
TimeMs _started = 0; TimeMs _started = 0;
int _secondsLeft = 0; int _secondsLeft = 0;
QString _text; QString _text;

View File

@ -30,6 +30,7 @@
'/MP', # Enable multi process build. '/MP', # Enable multi process build.
'/EHsc', # Catch C++ exceptions only, extern C functions never throw a C++ exception. '/EHsc', # Catch C++ exceptions only, extern C functions never throw a C++ exception.
'/w14834', # [[nodiscard]] '/w14834', # [[nodiscard]]
'/w15038', # wrong initialization order
], ],
'TreatWChar_tAsBuiltInType': 'false', 'TreatWChar_tAsBuiltInType': 'false',
}, },

View File

@ -140,8 +140,6 @@
<(src_loc)/core/mime_type.h <(src_loc)/core/mime_type.h
<(src_loc)/core/shortcuts.cpp <(src_loc)/core/shortcuts.cpp
<(src_loc)/core/shortcuts.h <(src_loc)/core/shortcuts.h
<(src_loc)/core/single_timer.cpp
<(src_loc)/core/single_timer.h
<(src_loc)/core/update_checker.cpp <(src_loc)/core/update_checker.cpp
<(src_loc)/core/update_checker.h <(src_loc)/core/update_checker.h
<(src_loc)/core/utils.cpp <(src_loc)/core/utils.cpp