From e9ec09b91a43e510f4500a2aeb4659ac5d6a4f7e Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 22 Mar 2017 18:38:40 +0300 Subject: [PATCH] Add MTP::Sender to replace RPCSender some day. Also use c++1z language standard in Xcode build. Also treat warnings as errors. --- .../SourceFiles/boxes/edit_privacy_box.cpp | 98 +++-- Telegram/SourceFiles/boxes/edit_privacy_box.h | 8 +- Telegram/SourceFiles/core/lambda.h | 8 +- Telegram/SourceFiles/mtproto/core_types.h | 3 + Telegram/SourceFiles/mtproto/sender.h | 374 ++++++++++++++++++ Telegram/SourceFiles/mtproto/session.cpp | 2 +- Telegram/SourceFiles/mtproto/session.h | 4 +- .../platform/linux/file_utilities_linux.cpp | 5 +- .../platform/linux/specific_linux.cpp | 2 +- .../settings/settings_privacy_controllers.cpp | 10 +- .../settings/settings_privacy_controllers.h | 3 +- Telegram/gyp/settings_linux.gypi | 2 +- Telegram/gyp/settings_mac.gypi | 6 +- Telegram/gyp/settings_win.gypi | 1 + Telegram/gyp/telegram_sources.txt | 1 + 15 files changed, 449 insertions(+), 78 deletions(-) create mode 100644 Telegram/SourceFiles/mtproto/sender.h diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 409c2efa7..8e52170e5 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -99,16 +99,7 @@ void EditPrivacyBox::prepare() { setTitle(_controller->title()); addButton(lang(lng_cancel), [this] { closeBox(); }); - _loadRequestId = MTP::send(MTPaccount_GetPrivacy(_controller->key()), rpcDone(base::lambda_guarded(this, [this](const MTPaccount_PrivacyRules &result) { - _loadRequestId = 0; - loadDone(result); - })), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) { - if (MTP::isDefaultHandledError(error)) { - return false; - } - _loadRequestId = 0; - return true; - }))); + loadData(); setDimensions(st::boxWideWidth, countDefaultHeight(st::boxWideWidth)); } @@ -323,55 +314,54 @@ void EditPrivacyBox::createWidgets() { setDimensions(st::boxWideWidth, resizeGetHeight(st::boxWideWidth)); } -void EditPrivacyBox::loadDone(const MTPaccount_PrivacyRules &result) { - t_assert(result.type() == mtpc_account_privacyRules); - auto &rules = result.c_account_privacyRules(); - App::feedUsers(rules.vusers); +void EditPrivacyBox::loadData() { + request(MTPaccount_GetPrivacy(_controller->key())).done([this](const MTPaccount_PrivacyRules &result) { + Expects(result.type() == mtpc_account_privacyRules); + auto &rules = result.c_account_privacyRules(); + App::feedUsers(rules.vusers); - // This is simplified version of privacy rules interpretation. - // But it should be fine for all the apps that use the same subset of features. - auto optionSet = false; - auto setOption = [this, &optionSet](Option option) { - if (optionSet) return; - optionSet = true; - _option = option; - }; - auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) { - switch (rule.type()) { - case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break; - case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break; - case mtpc_privacyValueAllowUsers: { - auto &users = rule.c_privacyValueAllowUsers().vusers.v; - _alwaysUsers.reserve(_alwaysUsers.size() + users.size()); - for (auto &userId : users) { - auto user = App::user(UserId(userId.v)); - if (!_neverUsers.contains(user) && !_alwaysUsers.contains(user)) { - _alwaysUsers.push_back(user); + // This is simplified version of privacy rules interpretation. + // But it should be fine for all the apps that use the same subset of features. + auto optionSet = false; + auto setOption = [this, &optionSet](Option option) { + if (optionSet) return; + optionSet = true; + _option = option; + }; + auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) { + switch (rule.type()) { + case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break; + case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break; + case mtpc_privacyValueAllowUsers: { + auto &users = rule.c_privacyValueAllowUsers().vusers.v; + _alwaysUsers.reserve(_alwaysUsers.size() + users.size()); + for (auto &userId : users) { + auto user = App::user(UserId(userId.v)); + if (!_neverUsers.contains(user) && !_alwaysUsers.contains(user)) { + _alwaysUsers.push_back(user); + } } - } - } break; - case mtpc_privacyValueDisallowContacts: // not supported, fall through - case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break; - case mtpc_privacyValueDisallowUsers: { - auto &users = rule.c_privacyValueDisallowUsers().vusers.v; - _neverUsers.reserve(_neverUsers.size() + users.size()); - for (auto &userId : users) { - auto user = App::user(UserId(userId.v)); - if (!_alwaysUsers.contains(user) && !_neverUsers.contains(user)) { - _neverUsers.push_back(user); + } break; + case mtpc_privacyValueDisallowContacts: // not supported, fall through + case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break; + case mtpc_privacyValueDisallowUsers: { + auto &users = rule.c_privacyValueDisallowUsers().vusers.v; + _neverUsers.reserve(_neverUsers.size() + users.size()); + for (auto &userId : users) { + auto user = App::user(UserId(userId.v)); + if (!_alwaysUsers.contains(user) && !_neverUsers.contains(user)) { + _neverUsers.push_back(user); + } } + } break; } - } break; + }; + for (auto &rule : rules.vrules.v) { + feedRule(rule); } - }; - for (auto &rule : rules.vrules.v) { - feedRule(rule); - } - feedRule(MTP_privacyValueDisallowAll()); // disallow by default. + feedRule(MTP_privacyValueDisallowAll()); // disallow by default. - createWidgets(); + createWidgets(); + }).send(); } -EditPrivacyBox::~EditPrivacyBox() { - MTP::cancel(_loadRequestId); -} diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.h b/Telegram/SourceFiles/boxes/edit_privacy_box.h index 5a01a9990..85c882db6 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.h +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.h @@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #pragma once #include "boxes/abstractbox.h" +#include "mtproto/sender.h" namespace Ui { class FlatLabel; @@ -33,7 +34,7 @@ template class WidgetSlideWrap; } // namespace Ui -class EditPrivacyBox : public BoxContent { +class EditPrivacyBox : public BoxContent, private MTP::Sender { public: enum class Option { Everyone, @@ -84,7 +85,6 @@ public: }; EditPrivacyBox(QWidget*, std::unique_ptr controller); - ~EditPrivacyBox(); protected: void prepare() override; @@ -97,7 +97,7 @@ private: bool showExceptionLink(Exception exception) const; void createWidgets(); QVector collectResult(); - void loadDone(const MTPaccount_PrivacyRules &result); + void loadData(); int countDefaultHeight(int newWidth); void editExceptionUsers(Exception exception); @@ -120,8 +120,6 @@ private: object_ptr> _neverLink = { nullptr }; object_ptr _exceptionsDescription = { nullptr }; - mtpRequestId _loadRequestId = 0; - QVector _alwaysUsers; QVector _neverUsers; diff --git a/Telegram/SourceFiles/core/lambda.h b/Telegram/SourceFiles/core/lambda.h index 5e9250243..7468b6e51 100644 --- a/Telegram/SourceFiles/core/lambda.h +++ b/Telegram/SourceFiles/core/lambda.h @@ -335,12 +335,12 @@ public: } // Copy / move construct / assign from an arbitrary type. - template + template ()(std::declval()...))> lambda_once(Lambda other) { data_.vtable = &lambda_internal::vtable_once::instance; lambda_internal::vtable_once::construct_move_lambda_method(data_.storage, &other); } - template + template ()(std::declval()...))> lambda_once &operator=(Lambda other) { if (data_.vtable) { data_.vtable->destruct(data_.storage); @@ -414,11 +414,11 @@ public: } // Copy / move construct / assign from an arbitrary type. - template + template ()(std::declval()...))> lambda(Lambda other) : Parent(&lambda_internal::vtable::instance, typename Parent::Private()) { lambda_internal::vtable::construct_move_lambda_method(this->data_.storage, &other); } - template + template ()(std::declval()...))> lambda &operator=(Lambda other) { if (this->data_.vtable) { this->data_.vtable->destruct(this->data_.storage); diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 9cdbd2239..5afa0c710 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -354,6 +354,9 @@ public: to.push_back(bareT::type()); bareT::write(to); } + + using Unboxed = bareT; + }; template class MTPBoxed > { diff --git a/Telegram/SourceFiles/mtproto/sender.h b/Telegram/SourceFiles/mtproto/sender.h new file mode 100644 index 000000000..40d93cc1a --- /dev/null +++ b/Telegram/SourceFiles/mtproto/sender.h @@ -0,0 +1,374 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "core/variant.h" + +namespace MTP { + +class Instance; +Instance *MainInstance(); + +class Sender { + class RequestBuilder { + public: + RequestBuilder(const RequestBuilder &other) = delete; + RequestBuilder &operator=(const RequestBuilder &other) = delete; + RequestBuilder &operator=(RequestBuilder &&other) = delete; + + protected: + using FailPlainHandler = base::lambda_once; + using FailRequestIdHandler = base::lambda_once; + enum class FailSkipPolicy { + Simple, + HandleFlood, + HandleAll, + }; + template + struct DonePlainPolicy { + using Callback = base::lambda_once; + static void handle(Callback &&handler, mtpRequestId requestId, Response &&result) { + handler(result); + } + + }; + template + struct DoneRequestIdPolicy { + using Callback = base::lambda_once; + static void handle(Callback &&handler, mtpRequestId requestId, Response &&result) { + handler(result, requestId); + } + + }; + template typename PolicyTemplate> + class DoneHandler : public RPCAbstractDoneHandler { + using Policy = PolicyTemplate; + using Callback = typename Policy::Callback; + + public: + DoneHandler(gsl::not_null sender, Callback handler) : _sender(sender), _handler(std::move(handler)) { + } + + void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override { + auto handler = std::move(_handler); + _sender->requestHandled(requestId); + + if (handler) { + auto result = Response(); + result.read(from, end); + Policy::handle(std::move(handler), requestId, std::move(result)); + } + } + + private: + gsl::not_null _sender; + Callback _handler; + + }; + + struct FailPlainPolicy { + using Callback = base::lambda_once; + static void handle(Callback &&handler, mtpRequestId requestId, const RPCError &error) { + handler(error); + } + + }; + struct FailRequestIdPolicy { + using Callback = base::lambda_once; + static void handle(Callback &&handler, mtpRequestId requestId, const RPCError &error) { + handler(error, requestId); + } + + }; + template + class FailHandler : public RPCAbstractFailHandler { + using Callback = typename Policy::Callback; + + public: + FailHandler(gsl::not_null sender, Callback handler, FailSkipPolicy skipPolicy) + : _sender(sender) + , _handler(std::move(handler)) + , _skipPolicy(skipPolicy) { + } + + bool operator()(mtpRequestId requestId, const RPCError &error) override { + if (_skipPolicy == FailSkipPolicy::Simple) { + if (MTP::isDefaultHandledError(error)) { + return false; + } + } else if (_skipPolicy == FailSkipPolicy::HandleFlood) { + if (MTP::isDefaultHandledError(error) && !MTP::isFloodError(error)) { + return false; + } + } + + auto handler = std::move(_handler); + _sender->requestHandled(requestId); + + if (handler) { + Policy::handle(std::move(handler), requestId, error); + } + return true; + } + + private: + gsl::not_null _sender; + Callback _handler; + FailSkipPolicy _skipPolicy = FailSkipPolicy::Simple; + + }; + + explicit RequestBuilder(gsl::not_null sender) noexcept : _sender(sender) { + } + RequestBuilder(RequestBuilder &&other) = default; + + void setToDC(ShiftedDcId dcId) noexcept { + _dcId = dcId; + } + void setCanWait(TimeMs ms) noexcept { + _canWait = ms; + } + void setDoneHandler(RPCDoneHandlerPtr &&handler) noexcept { + _done = std::move(handler); + } + void setFailHandler(FailPlainHandler &&handler) noexcept { + _fail = std::move(handler); + } + void setFailHandler(FailRequestIdHandler &&handler) noexcept { + _fail = std::move(handler); + } + void setFailSkipPolicy(FailSkipPolicy policy) noexcept { + _failSkipPolicy = policy; + } + void setAfter(mtpRequestId requestId) noexcept { + _afterRequestId = requestId; + } + + ShiftedDcId takeDcId() const noexcept { + return _dcId; + } + TimeMs takeCanWait() const noexcept { + return _canWait; + } + RPCDoneHandlerPtr takeOnDone() noexcept { + return std::move(_done); + } + RPCFailHandlerPtr takeOnFail() { + if (auto handler = base::get_if(&_fail)) { + return MakeShared>(_sender, std::move(*handler), _failSkipPolicy); + } else if (auto handler = base::get_if(&_fail)) { + return MakeShared>(_sender, std::move(*handler), _failSkipPolicy); + } + return RPCFailHandlerPtr(); + } + mtpRequestId takeAfter() const noexcept { + return _afterRequestId; + } + + gsl::not_null sender() const noexcept { + return _sender; + } + gsl::not_null instance() const noexcept { + return _sender->_instance; + } + void registerRequest(mtpRequestId requestId) { + _sender->requestRegister(requestId); + } + + private: + gsl::not_null _sender; + ShiftedDcId _dcId = 0; + TimeMs _canWait = 0; + RPCDoneHandlerPtr _done; + base::variant _fail; + FailSkipPolicy _failSkipPolicy = FailSkipPolicy::Simple; + mtpRequestId _afterRequestId = 0; + + }; + +public: + Sender(gsl::not_null instance = MainInstance()) noexcept : _instance(instance) { + } + + template + class SpecificRequestBuilder : public RequestBuilder { + private: + friend class Sender; + SpecificRequestBuilder(gsl::not_null sender, Request &&request) noexcept : RequestBuilder(sender), _request(std::move(request)) { + } + SpecificRequestBuilder(SpecificRequestBuilder &&other) = default; + + public: + SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept WARN_UNUSED_RESULT { + setToDC(dcId); + return *this; + } + SpecificRequestBuilder &canWait(TimeMs ms) noexcept WARN_UNUSED_RESULT { + setCanWait(ms); + return *this; + } + SpecificRequestBuilder &done(base::lambda_once callback) WARN_UNUSED_RESULT { + setDoneHandler(MakeShared>(sender(), std::move(callback))); + return *this; + } + SpecificRequestBuilder &done(base::lambda_once callback) WARN_UNUSED_RESULT { + setDoneHandler(MakeShared>(sender(), std::move(callback))); + return *this; + } + SpecificRequestBuilder &fail(base::lambda_once callback) noexcept WARN_UNUSED_RESULT { + setFailHandler(std::move(callback)); + return *this; + } + SpecificRequestBuilder &fail(base::lambda_once callback) noexcept WARN_UNUSED_RESULT { + setFailHandler(std::move(callback)); + return *this; + } + SpecificRequestBuilder &handleFloodErrors() noexcept WARN_UNUSED_RESULT { + setFailSkipPolicy(FailSkipPolicy::HandleFlood); + return *this; + } + SpecificRequestBuilder &handleAllErrors() noexcept WARN_UNUSED_RESULT { + setFailSkipPolicy(FailSkipPolicy::HandleAll); + return *this; + } + SpecificRequestBuilder &after(mtpRequestId requestId) noexcept WARN_UNUSED_RESULT { + setAfter(requestId); + return *this; + } + + mtpRequestId send() { + auto id = instance()->send(_request, takeOnDone(), takeOnFail(), takeDcId(), takeCanWait(), takeAfter()); + registerRequest(id); + return id; + } + + private: + Request _request; + + }; + + class SentRequestWrap { + private: + friend class Sender; + SentRequestWrap(gsl::not_null sender, mtpRequestId requestId) : _sender(sender), _requestId(requestId) { + } + + public: + void cancel() { + _sender->requestCancel(_requestId); + } + + private: + gsl::not_null _sender; + mtpRequestId _requestId = 0; + + }; + + template ::value>, typename = typename Request::Unboxed> + SpecificRequestBuilder request(Request &&request) noexcept WARN_UNUSED_RESULT; + + SentRequestWrap request(mtpRequestId requestId) noexcept WARN_UNUSED_RESULT; + +private: + class RequestWrap { + public: + RequestWrap(Instance *instance, mtpRequestId requestId) noexcept : _instance(instance), _id(requestId) { + } + + mtpRequestId id() const noexcept { + return _id; + } + void handled() const noexcept { + _instance = nullptr; + } + + ~RequestWrap() { + if (_instance) { + _instance->cancel(_id); + } + } + + private: + mutable Instance *_instance = nullptr; + mtpRequestId _id = 0; + + }; + + struct RequestWrapComparator { + using is_transparent = std::true_type; + + struct helper { + mtpRequestId requestId = 0; + + helper() = default; + helper(const helper &other) = default; + helper(mtpRequestId requestId) noexcept : requestId(requestId) { + } + helper(const RequestWrap &request) noexcept : requestId(request.id()) { + } + bool operator<(helper other) const { + return requestId < other.requestId; + } + }; + bool operator()(const helper &&lhs, const helper &&rhs) const { + return lhs < rhs; + } + + }; + + template + friend class SpecialRequestBuilder; + friend class RequestBuilder; + friend class RequestWrap; + friend class SentRequestWrap; + + void requestRegister(mtpRequestId requestId) { + _requests.emplace(_instance, requestId); + } + void requestHandled(mtpRequestId requestId) { + auto it = _requests.find(requestId); + if (it != _requests.cend()) { + it->handled(); + _requests.erase(it); + } + } + void requestCancel(mtpRequestId requestId) { + auto it = _requests.find(requestId); + if (it != _requests.cend()) { + _requests.erase(it); + } + } + + gsl::not_null _instance; + std::set _requests; + +}; + +template +Sender::SpecificRequestBuilder Sender::request(Request &&request) noexcept { + return SpecificRequestBuilder(this, std::move(request)); +} + +inline Sender::SentRequestWrap Sender::request(mtpRequestId requestId) noexcept { + return SentRequestWrap(this, requestId); +} + +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/session.cpp b/Telegram/SourceFiles/mtproto/session.cpp index a6019fcf1..3a68fb94c 100644 --- a/Telegram/SourceFiles/mtproto/session.cpp +++ b/Telegram/SourceFiles/mtproto/session.cpp @@ -69,7 +69,7 @@ void SessionData::clear(Instance *instance) { instance->clearCallbacksDelayed(clearCallbacks); } -Session::Session(Instance *instance, ShiftedDcId shiftedDcId) : QObject() +Session::Session(gsl::not_null instance, ShiftedDcId shiftedDcId) : QObject() , _instance(instance) , data(this) , dcWithShift(shiftedDcId) { diff --git a/Telegram/SourceFiles/mtproto/session.h b/Telegram/SourceFiles/mtproto/session.h index f9bf6df54..5b08dba64 100644 --- a/Telegram/SourceFiles/mtproto/session.h +++ b/Telegram/SourceFiles/mtproto/session.h @@ -278,7 +278,7 @@ class Session : public QObject { Q_OBJECT public: - Session(Instance *instance, ShiftedDcId shiftedDcId); + Session(gsl::not_null instance, ShiftedDcId shiftedDcId); void start(); void restart(); @@ -340,7 +340,7 @@ private: mtpRequest getRequest(mtpRequestId requestId); bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err); - Instance *_instance; + gsl::not_null _instance; std::unique_ptr _connection; bool _killed = false; diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp index f23c78cd2..fddf1771b 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp @@ -62,7 +62,10 @@ QByteArray EscapeShell(const QByteArray &content) { void UnsafeShowInFolder(const QString &filepath) { Ui::hideLayer(true); - system(("xdg-open " + internal::EscapeShell(QFile::encodeName(QFileInfo(filepath).absoluteDir().absolutePath()))).constData()); + auto result = system(("xdg-open " + internal::EscapeShell(QFile::encodeName(QFileInfo(filepath).absoluteDir().absolutePath()))).constData()); + if (result) { + LOG(("Failed to launch xdg-open")); + } } } // namespace File diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index df4534f4a..3386c8a08 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -422,7 +422,7 @@ void finish() { namespace { bool _psRunCommand(const QByteArray &command) { - int result = system(command.constData()); + auto result = system(command.constData()); if (result) { DEBUG_LOG(("App Error: command failed, code: %1, command (in utf8): %2").arg(result).arg(command.constData())); return false; diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index 25ba4dd3e..8f36e2c00 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -114,7 +114,7 @@ void BlockedBoxController::preloadRows() { return; } - _loadRequestId = MTP::send(MTPcontacts_GetBlocked(MTP_int(_offset), MTP_int(kBlockedPerPage)), rpcDone(base::lambda_guarded(this, [this](const MTPcontacts_Blocked &result) { + _loadRequestId = request(MTPcontacts_GetBlocked(MTP_int(_offset), MTP_int(kBlockedPerPage))).done([this](const MTPcontacts_Blocked &result) { _loadRequestId = 0; if (!_offset) { @@ -135,13 +135,9 @@ void BlockedBoxController::preloadRows() { } break; default: Unexpected("Bad type() in MTPcontacts_GetBlocked() result."); } - })), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) { - if (MTP::isDefaultHandledError(error)) { - return false; - } + }).fail([this](const RPCError &error) { _loadRequestId = 0; - return true; - }))); + }).send(); } void BlockedBoxController::rowClicked(PeerListBox::Row *row) { diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.h b/Telegram/SourceFiles/settings/settings_privacy_controllers.h index 80a885f5f..678b99c9b 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.h +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.h @@ -22,10 +22,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "boxes/peer_list_box.h" #include "boxes/edit_privacy_box.h" +#include "mtproto/sender.h" namespace Settings { -class BlockedBoxController : public QObject, public PeerListBox::Controller, private base::Subscriber { +class BlockedBoxController : public PeerListBox::Controller, private base::Subscriber, private MTP::Sender { public: void prepare() override; void rowClicked(PeerListBox::Row *row) override; diff --git a/Telegram/gyp/settings_linux.gypi b/Telegram/gyp/settings_linux.gypi index 4cdf7a5ba..fde88dcd1 100644 --- a/Telegram/gyp/settings_linux.gypi +++ b/Telegram/gyp/settings_linux.gypi @@ -25,9 +25,9 @@ '-pipe', '-g', '-Wall', + '-Werror', '-W', '-fPIC', - '-Wno-unused-result', '-Wno-unused-variable', '-Wno-unused-parameter', '-Wno-unused-function', diff --git a/Telegram/gyp/settings_mac.gypi b/Telegram/gyp/settings_mac.gypi index 600ec0a79..10725d934 100644 --- a/Telegram/gyp/settings_mac.gypi +++ b/Telegram/gyp/settings_mac.gypi @@ -46,6 +46,7 @@ '-pipe', '-g', '-Wall', + '-Werror', '-W', '-fPIE', '-Wno-unused-variable', @@ -71,7 +72,7 @@ 'MACOSX_DEPLOYMENT_TARGET': '<(mac_target)', 'COMBINE_HIDPI_IMAGES': 'YES', 'COPY_PHASE_STRIP': 'NO', - 'CLANG_CXX_LANGUAGE_STANDARD': 'c++14', + 'CLANG_CXX_LANGUAGE_STANDARD': 'c++1z', }, 'configurations': { 'Debug': { @@ -92,6 +93,9 @@ 'OTHER_CPLUSPLUSFLAGS': [ '-Wno-inconsistent-missing-override', ], + 'OTHER_LDFLAGS': [ + '-w', # Suppress 'libstdc++ is deprecated' warning. + ], }, }, { 'xcode_settings': { diff --git a/Telegram/gyp/settings_win.gypi b/Telegram/gyp/settings_win.gypi index 5d5cca9f5..2bcb0797e 100644 --- a/Telegram/gyp/settings_win.gypi +++ b/Telegram/gyp/settings_win.gypi @@ -38,6 +38,7 @@ 'AdditionalOptions': [ '/MP', # Enable multi process build. '/EHsc', # Catch C++ exceptions only, extern C functions never throw a C++ exception. + '/WX', # Treat warnings as errors. ], 'TreatWChar_tAsBuiltInType': 'false', }, diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 8aeb5b9df..01f08e354 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -203,6 +203,7 @@ <(src_loc)/mtproto/rsa_public_key.h <(src_loc)/mtproto/rpc_sender.cpp <(src_loc)/mtproto/rpc_sender.h +<(src_loc)/mtproto/sender.h <(src_loc)/mtproto/session.cpp <(src_loc)/mtproto/session.h <(src_loc)/overview/overview_layout.cpp