mirror of https://github.com/procxx/kepka.git
Add MTP::Sender to replace RPCSender some day.
Also use c++1z language standard in Xcode build. Also treat warnings as errors.
This commit is contained in:
parent
7fcc5d649c
commit
e9ec09b91a
|
@ -99,16 +99,7 @@ void EditPrivacyBox::prepare() {
|
||||||
setTitle(_controller->title());
|
setTitle(_controller->title());
|
||||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||||
|
|
||||||
_loadRequestId = MTP::send(MTPaccount_GetPrivacy(_controller->key()), rpcDone(base::lambda_guarded(this, [this](const MTPaccount_PrivacyRules &result) {
|
loadData();
|
||||||
_loadRequestId = 0;
|
|
||||||
loadDone(result);
|
|
||||||
})), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) {
|
|
||||||
if (MTP::isDefaultHandledError(error)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_loadRequestId = 0;
|
|
||||||
return true;
|
|
||||||
})));
|
|
||||||
|
|
||||||
setDimensions(st::boxWideWidth, countDefaultHeight(st::boxWideWidth));
|
setDimensions(st::boxWideWidth, countDefaultHeight(st::boxWideWidth));
|
||||||
}
|
}
|
||||||
|
@ -323,55 +314,54 @@ void EditPrivacyBox::createWidgets() {
|
||||||
setDimensions(st::boxWideWidth, resizeGetHeight(st::boxWideWidth));
|
setDimensions(st::boxWideWidth, resizeGetHeight(st::boxWideWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditPrivacyBox::loadDone(const MTPaccount_PrivacyRules &result) {
|
void EditPrivacyBox::loadData() {
|
||||||
t_assert(result.type() == mtpc_account_privacyRules);
|
request(MTPaccount_GetPrivacy(_controller->key())).done([this](const MTPaccount_PrivacyRules &result) {
|
||||||
auto &rules = result.c_account_privacyRules();
|
Expects(result.type() == mtpc_account_privacyRules);
|
||||||
App::feedUsers(rules.vusers);
|
auto &rules = result.c_account_privacyRules();
|
||||||
|
App::feedUsers(rules.vusers);
|
||||||
|
|
||||||
// This is simplified version of privacy rules interpretation.
|
// This is simplified version of privacy rules interpretation.
|
||||||
// But it should be fine for all the apps that use the same subset of features.
|
// But it should be fine for all the apps that use the same subset of features.
|
||||||
auto optionSet = false;
|
auto optionSet = false;
|
||||||
auto setOption = [this, &optionSet](Option option) {
|
auto setOption = [this, &optionSet](Option option) {
|
||||||
if (optionSet) return;
|
if (optionSet) return;
|
||||||
optionSet = true;
|
optionSet = true;
|
||||||
_option = option;
|
_option = option;
|
||||||
};
|
};
|
||||||
auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) {
|
auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) {
|
||||||
switch (rule.type()) {
|
switch (rule.type()) {
|
||||||
case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break;
|
case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break;
|
||||||
case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break;
|
case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break;
|
||||||
case mtpc_privacyValueAllowUsers: {
|
case mtpc_privacyValueAllowUsers: {
|
||||||
auto &users = rule.c_privacyValueAllowUsers().vusers.v;
|
auto &users = rule.c_privacyValueAllowUsers().vusers.v;
|
||||||
_alwaysUsers.reserve(_alwaysUsers.size() + users.size());
|
_alwaysUsers.reserve(_alwaysUsers.size() + users.size());
|
||||||
for (auto &userId : users) {
|
for (auto &userId : users) {
|
||||||
auto user = App::user(UserId(userId.v));
|
auto user = App::user(UserId(userId.v));
|
||||||
if (!_neverUsers.contains(user) && !_alwaysUsers.contains(user)) {
|
if (!_neverUsers.contains(user) && !_alwaysUsers.contains(user)) {
|
||||||
_alwaysUsers.push_back(user);
|
_alwaysUsers.push_back(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
} break;
|
case mtpc_privacyValueDisallowContacts: // not supported, fall through
|
||||||
case mtpc_privacyValueDisallowContacts: // not supported, fall through
|
case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break;
|
||||||
case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break;
|
case mtpc_privacyValueDisallowUsers: {
|
||||||
case mtpc_privacyValueDisallowUsers: {
|
auto &users = rule.c_privacyValueDisallowUsers().vusers.v;
|
||||||
auto &users = rule.c_privacyValueDisallowUsers().vusers.v;
|
_neverUsers.reserve(_neverUsers.size() + users.size());
|
||||||
_neverUsers.reserve(_neverUsers.size() + users.size());
|
for (auto &userId : users) {
|
||||||
for (auto &userId : users) {
|
auto user = App::user(UserId(userId.v));
|
||||||
auto user = App::user(UserId(userId.v));
|
if (!_alwaysUsers.contains(user) && !_neverUsers.contains(user)) {
|
||||||
if (!_alwaysUsers.contains(user) && !_neverUsers.contains(user)) {
|
_neverUsers.push_back(user);
|
||||||
_neverUsers.push_back(user);
|
}
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
};
|
||||||
|
for (auto &rule : rules.vrules.v) {
|
||||||
|
feedRule(rule);
|
||||||
}
|
}
|
||||||
};
|
feedRule(MTP_privacyValueDisallowAll()); // disallow by default.
|
||||||
for (auto &rule : rules.vrules.v) {
|
|
||||||
feedRule(rule);
|
|
||||||
}
|
|
||||||
feedRule(MTP_privacyValueDisallowAll()); // disallow by default.
|
|
||||||
|
|
||||||
createWidgets();
|
createWidgets();
|
||||||
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
EditPrivacyBox::~EditPrivacyBox() {
|
|
||||||
MTP::cancel(_loadRequestId);
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "boxes/abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FlatLabel;
|
class FlatLabel;
|
||||||
|
@ -33,7 +34,7 @@ template <typename Widget>
|
||||||
class WidgetSlideWrap;
|
class WidgetSlideWrap;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class EditPrivacyBox : public BoxContent {
|
class EditPrivacyBox : public BoxContent, private MTP::Sender {
|
||||||
public:
|
public:
|
||||||
enum class Option {
|
enum class Option {
|
||||||
Everyone,
|
Everyone,
|
||||||
|
@ -84,7 +85,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller);
|
EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller);
|
||||||
~EditPrivacyBox();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
@ -97,7 +97,7 @@ private:
|
||||||
bool showExceptionLink(Exception exception) const;
|
bool showExceptionLink(Exception exception) const;
|
||||||
void createWidgets();
|
void createWidgets();
|
||||||
QVector<MTPInputPrivacyRule> collectResult();
|
QVector<MTPInputPrivacyRule> collectResult();
|
||||||
void loadDone(const MTPaccount_PrivacyRules &result);
|
void loadData();
|
||||||
int countDefaultHeight(int newWidth);
|
int countDefaultHeight(int newWidth);
|
||||||
|
|
||||||
void editExceptionUsers(Exception exception);
|
void editExceptionUsers(Exception exception);
|
||||||
|
@ -120,8 +120,6 @@ private:
|
||||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
|
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
|
||||||
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
|
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
|
||||||
|
|
||||||
mtpRequestId _loadRequestId = 0;
|
|
||||||
|
|
||||||
QVector<UserData*> _alwaysUsers;
|
QVector<UserData*> _alwaysUsers;
|
||||||
QVector<UserData*> _neverUsers;
|
QVector<UserData*> _neverUsers;
|
||||||
|
|
||||||
|
|
|
@ -335,12 +335,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy / move construct / assign from an arbitrary type.
|
// Copy / move construct / assign from an arbitrary type.
|
||||||
template <typename Lambda>
|
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||||
lambda_once(Lambda other) {
|
lambda_once(Lambda other) {
|
||||||
data_.vtable = &lambda_internal::vtable_once<Lambda, Return, Args...>::instance;
|
data_.vtable = &lambda_internal::vtable_once<Lambda, Return, Args...>::instance;
|
||||||
lambda_internal::vtable_once<Lambda, Return, Args...>::construct_move_lambda_method(data_.storage, &other);
|
lambda_internal::vtable_once<Lambda, Return, Args...>::construct_move_lambda_method(data_.storage, &other);
|
||||||
}
|
}
|
||||||
template <typename Lambda>
|
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||||
lambda_once &operator=(Lambda other) {
|
lambda_once &operator=(Lambda other) {
|
||||||
if (data_.vtable) {
|
if (data_.vtable) {
|
||||||
data_.vtable->destruct(data_.storage);
|
data_.vtable->destruct(data_.storage);
|
||||||
|
@ -414,11 +414,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy / move construct / assign from an arbitrary type.
|
// Copy / move construct / assign from an arbitrary type.
|
||||||
template <typename Lambda>
|
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||||
lambda(Lambda other) : Parent(&lambda_internal::vtable<Lambda, Return, Args...>::instance, typename Parent::Private()) {
|
lambda(Lambda other) : Parent(&lambda_internal::vtable<Lambda, Return, Args...>::instance, typename Parent::Private()) {
|
||||||
lambda_internal::vtable<Lambda, Return, Args...>::construct_move_lambda_method(this->data_.storage, &other);
|
lambda_internal::vtable<Lambda, Return, Args...>::construct_move_lambda_method(this->data_.storage, &other);
|
||||||
}
|
}
|
||||||
template <typename Lambda>
|
template <typename Lambda, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||||
lambda &operator=(Lambda other) {
|
lambda &operator=(Lambda other) {
|
||||||
if (this->data_.vtable) {
|
if (this->data_.vtable) {
|
||||||
this->data_.vtable->destruct(this->data_.storage);
|
this->data_.vtable->destruct(this->data_.storage);
|
||||||
|
|
|
@ -354,6 +354,9 @@ public:
|
||||||
to.push_back(bareT::type());
|
to.push_back(bareT::type());
|
||||||
bareT::write(to);
|
bareT::write(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using Unboxed = bareT;
|
||||||
|
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MTPBoxed<MTPBoxed<T> > {
|
class MTPBoxed<MTPBoxed<T> > {
|
||||||
|
|
|
@ -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<void(const RPCError &error)>;
|
||||||
|
using FailRequestIdHandler = base::lambda_once<void(const RPCError &error, mtpRequestId requestId)>;
|
||||||
|
enum class FailSkipPolicy {
|
||||||
|
Simple,
|
||||||
|
HandleFlood,
|
||||||
|
HandleAll,
|
||||||
|
};
|
||||||
|
template <typename Response>
|
||||||
|
struct DonePlainPolicy {
|
||||||
|
using Callback = base::lambda_once<void(const Response &result)>;
|
||||||
|
static void handle(Callback &&handler, mtpRequestId requestId, Response &&result) {
|
||||||
|
handler(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Response>
|
||||||
|
struct DoneRequestIdPolicy {
|
||||||
|
using Callback = base::lambda_once<void(const Response &result, mtpRequestId requestId)>;
|
||||||
|
static void handle(Callback &&handler, mtpRequestId requestId, Response &&result) {
|
||||||
|
handler(result, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Response, template <typename> typename PolicyTemplate>
|
||||||
|
class DoneHandler : public RPCAbstractDoneHandler {
|
||||||
|
using Policy = PolicyTemplate<Response>;
|
||||||
|
using Callback = typename Policy::Callback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DoneHandler(gsl::not_null<Sender*> 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*> _sender;
|
||||||
|
Callback _handler;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FailPlainPolicy {
|
||||||
|
using Callback = base::lambda_once<void(const RPCError &error)>;
|
||||||
|
static void handle(Callback &&handler, mtpRequestId requestId, const RPCError &error) {
|
||||||
|
handler(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
struct FailRequestIdPolicy {
|
||||||
|
using Callback = base::lambda_once<void(const RPCError &error, mtpRequestId requestId)>;
|
||||||
|
static void handle(Callback &&handler, mtpRequestId requestId, const RPCError &error) {
|
||||||
|
handler(error, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Policy>
|
||||||
|
class FailHandler : public RPCAbstractFailHandler {
|
||||||
|
using Callback = typename Policy::Callback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FailHandler(gsl::not_null<Sender*> 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*> _sender;
|
||||||
|
Callback _handler;
|
||||||
|
FailSkipPolicy _skipPolicy = FailSkipPolicy::Simple;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit RequestBuilder(gsl::not_null<Sender*> 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<FailPlainHandler>(&_fail)) {
|
||||||
|
return MakeShared<FailHandler<FailPlainPolicy>>(_sender, std::move(*handler), _failSkipPolicy);
|
||||||
|
} else if (auto handler = base::get_if<FailRequestIdHandler>(&_fail)) {
|
||||||
|
return MakeShared<FailHandler<FailRequestIdPolicy>>(_sender, std::move(*handler), _failSkipPolicy);
|
||||||
|
}
|
||||||
|
return RPCFailHandlerPtr();
|
||||||
|
}
|
||||||
|
mtpRequestId takeAfter() const noexcept {
|
||||||
|
return _afterRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsl::not_null<Sender*> sender() const noexcept {
|
||||||
|
return _sender;
|
||||||
|
}
|
||||||
|
gsl::not_null<Instance*> instance() const noexcept {
|
||||||
|
return _sender->_instance;
|
||||||
|
}
|
||||||
|
void registerRequest(mtpRequestId requestId) {
|
||||||
|
_sender->requestRegister(requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
gsl::not_null<Sender*> _sender;
|
||||||
|
ShiftedDcId _dcId = 0;
|
||||||
|
TimeMs _canWait = 0;
|
||||||
|
RPCDoneHandlerPtr _done;
|
||||||
|
base::variant<FailPlainHandler, FailRequestIdHandler> _fail;
|
||||||
|
FailSkipPolicy _failSkipPolicy = FailSkipPolicy::Simple;
|
||||||
|
mtpRequestId _afterRequestId = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Sender(gsl::not_null<Instance*> instance = MainInstance()) noexcept : _instance(instance) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Request>
|
||||||
|
class SpecificRequestBuilder : public RequestBuilder {
|
||||||
|
private:
|
||||||
|
friend class Sender;
|
||||||
|
SpecificRequestBuilder(gsl::not_null<Sender*> 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<void(const typename Request::ResponseType &result)> callback) WARN_UNUSED_RESULT {
|
||||||
|
setDoneHandler(MakeShared<DoneHandler<typename Request::ResponseType, DonePlainPolicy>>(sender(), std::move(callback)));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SpecificRequestBuilder &done(base::lambda_once<void(const typename Request::ResponseType &result, mtpRequestId requestId)> callback) WARN_UNUSED_RESULT {
|
||||||
|
setDoneHandler(MakeShared<DoneHandler<typename Request::ResponseType, DoneRequestIdPolicy>>(sender(), std::move(callback)));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SpecificRequestBuilder &fail(base::lambda_once<void(const RPCError &error)> callback) noexcept WARN_UNUSED_RESULT {
|
||||||
|
setFailHandler(std::move(callback));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SpecificRequestBuilder &fail(base::lambda_once<void(const RPCError &error, mtpRequestId requestId)> 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*> sender, mtpRequestId requestId) : _sender(sender), _requestId(requestId) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void cancel() {
|
||||||
|
_sender->requestCancel(_requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
gsl::not_null<Sender*> _sender;
|
||||||
|
mtpRequestId _requestId = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Request, typename = std::enable_if_t<std::is_rvalue_reference<Request&&>::value>, typename = typename Request::Unboxed>
|
||||||
|
SpecificRequestBuilder<Request> 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 <typename Request>
|
||||||
|
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*> _instance;
|
||||||
|
std::set<RequestWrap, RequestWrapComparator> _requests;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Request, typename, typename>
|
||||||
|
Sender::SpecificRequestBuilder<Request> Sender::request(Request &&request) noexcept {
|
||||||
|
return SpecificRequestBuilder<Request>(this, std::move(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Sender::SentRequestWrap Sender::request(mtpRequestId requestId) noexcept {
|
||||||
|
return SentRequestWrap(this, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MTP
|
|
@ -69,7 +69,7 @@ void SessionData::clear(Instance *instance) {
|
||||||
instance->clearCallbacksDelayed(clearCallbacks);
|
instance->clearCallbacksDelayed(clearCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
Session::Session(Instance *instance, ShiftedDcId shiftedDcId) : QObject()
|
Session::Session(gsl::not_null<Instance*> instance, ShiftedDcId shiftedDcId) : QObject()
|
||||||
, _instance(instance)
|
, _instance(instance)
|
||||||
, data(this)
|
, data(this)
|
||||||
, dcWithShift(shiftedDcId) {
|
, dcWithShift(shiftedDcId) {
|
||||||
|
|
|
@ -278,7 +278,7 @@ class Session : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Session(Instance *instance, ShiftedDcId shiftedDcId);
|
Session(gsl::not_null<Instance*> instance, ShiftedDcId shiftedDcId);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void restart();
|
void restart();
|
||||||
|
@ -340,7 +340,7 @@ private:
|
||||||
mtpRequest getRequest(mtpRequestId requestId);
|
mtpRequest getRequest(mtpRequestId requestId);
|
||||||
bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err);
|
bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err);
|
||||||
|
|
||||||
Instance *_instance;
|
gsl::not_null<Instance*> _instance;
|
||||||
std::unique_ptr<Connection> _connection;
|
std::unique_ptr<Connection> _connection;
|
||||||
|
|
||||||
bool _killed = false;
|
bool _killed = false;
|
||||||
|
|
|
@ -62,7 +62,10 @@ QByteArray EscapeShell(const QByteArray &content) {
|
||||||
|
|
||||||
void UnsafeShowInFolder(const QString &filepath) {
|
void UnsafeShowInFolder(const QString &filepath) {
|
||||||
Ui::hideLayer(true);
|
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
|
} // namespace File
|
||||||
|
|
|
@ -422,7 +422,7 @@ void finish() {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool _psRunCommand(const QByteArray &command) {
|
bool _psRunCommand(const QByteArray &command) {
|
||||||
int result = system(command.constData());
|
auto result = system(command.constData());
|
||||||
if (result) {
|
if (result) {
|
||||||
DEBUG_LOG(("App Error: command failed, code: %1, command (in utf8): %2").arg(result).arg(command.constData()));
|
DEBUG_LOG(("App Error: command failed, code: %1, command (in utf8): %2").arg(result).arg(command.constData()));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -114,7 +114,7 @@ void BlockedBoxController::preloadRows() {
|
||||||
return;
|
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;
|
_loadRequestId = 0;
|
||||||
|
|
||||||
if (!_offset) {
|
if (!_offset) {
|
||||||
|
@ -135,13 +135,9 @@ void BlockedBoxController::preloadRows() {
|
||||||
} break;
|
} break;
|
||||||
default: Unexpected("Bad type() in MTPcontacts_GetBlocked() result.");
|
default: Unexpected("Bad type() in MTPcontacts_GetBlocked() result.");
|
||||||
}
|
}
|
||||||
})), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) {
|
}).fail([this](const RPCError &error) {
|
||||||
if (MTP::isDefaultHandledError(error)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_loadRequestId = 0;
|
_loadRequestId = 0;
|
||||||
return true;
|
}).send();
|
||||||
})));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockedBoxController::rowClicked(PeerListBox::Row *row) {
|
void BlockedBoxController::rowClicked(PeerListBox::Row *row) {
|
||||||
|
|
|
@ -22,10 +22,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "boxes/peer_list_box.h"
|
#include "boxes/peer_list_box.h"
|
||||||
#include "boxes/edit_privacy_box.h"
|
#include "boxes/edit_privacy_box.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
||||||
class BlockedBoxController : public QObject, public PeerListBox::Controller, private base::Subscriber {
|
class BlockedBoxController : public PeerListBox::Controller, private base::Subscriber, private MTP::Sender {
|
||||||
public:
|
public:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
void rowClicked(PeerListBox::Row *row) override;
|
void rowClicked(PeerListBox::Row *row) override;
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
'-pipe',
|
'-pipe',
|
||||||
'-g',
|
'-g',
|
||||||
'-Wall',
|
'-Wall',
|
||||||
|
'-Werror',
|
||||||
'-W',
|
'-W',
|
||||||
'-fPIC',
|
'-fPIC',
|
||||||
'-Wno-unused-result',
|
|
||||||
'-Wno-unused-variable',
|
'-Wno-unused-variable',
|
||||||
'-Wno-unused-parameter',
|
'-Wno-unused-parameter',
|
||||||
'-Wno-unused-function',
|
'-Wno-unused-function',
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
'-pipe',
|
'-pipe',
|
||||||
'-g',
|
'-g',
|
||||||
'-Wall',
|
'-Wall',
|
||||||
|
'-Werror',
|
||||||
'-W',
|
'-W',
|
||||||
'-fPIE',
|
'-fPIE',
|
||||||
'-Wno-unused-variable',
|
'-Wno-unused-variable',
|
||||||
|
@ -71,7 +72,7 @@
|
||||||
'MACOSX_DEPLOYMENT_TARGET': '<(mac_target)',
|
'MACOSX_DEPLOYMENT_TARGET': '<(mac_target)',
|
||||||
'COMBINE_HIDPI_IMAGES': 'YES',
|
'COMBINE_HIDPI_IMAGES': 'YES',
|
||||||
'COPY_PHASE_STRIP': 'NO',
|
'COPY_PHASE_STRIP': 'NO',
|
||||||
'CLANG_CXX_LANGUAGE_STANDARD': 'c++14',
|
'CLANG_CXX_LANGUAGE_STANDARD': 'c++1z',
|
||||||
},
|
},
|
||||||
'configurations': {
|
'configurations': {
|
||||||
'Debug': {
|
'Debug': {
|
||||||
|
@ -92,6 +93,9 @@
|
||||||
'OTHER_CPLUSPLUSFLAGS': [
|
'OTHER_CPLUSPLUSFLAGS': [
|
||||||
'-Wno-inconsistent-missing-override',
|
'-Wno-inconsistent-missing-override',
|
||||||
],
|
],
|
||||||
|
'OTHER_LDFLAGS': [
|
||||||
|
'-w', # Suppress 'libstdc++ is deprecated' warning.
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'xcode_settings': {
|
'xcode_settings': {
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
'AdditionalOptions': [
|
'AdditionalOptions': [
|
||||||
'/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.
|
||||||
|
'/WX', # Treat warnings as errors.
|
||||||
],
|
],
|
||||||
'TreatWChar_tAsBuiltInType': 'false',
|
'TreatWChar_tAsBuiltInType': 'false',
|
||||||
},
|
},
|
||||||
|
|
|
@ -203,6 +203,7 @@
|
||||||
<(src_loc)/mtproto/rsa_public_key.h
|
<(src_loc)/mtproto/rsa_public_key.h
|
||||||
<(src_loc)/mtproto/rpc_sender.cpp
|
<(src_loc)/mtproto/rpc_sender.cpp
|
||||||
<(src_loc)/mtproto/rpc_sender.h
|
<(src_loc)/mtproto/rpc_sender.h
|
||||||
|
<(src_loc)/mtproto/sender.h
|
||||||
<(src_loc)/mtproto/session.cpp
|
<(src_loc)/mtproto/session.cpp
|
||||||
<(src_loc)/mtproto/session.h
|
<(src_loc)/mtproto/session.h
|
||||||
<(src_loc)/overview/overview_layout.cpp
|
<(src_loc)/overview/overview_layout.cpp
|
||||||
|
|
Loading…
Reference in New Issue