From d3f85b4c4ed5f33762b39dc4f64399565df145a3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 11 May 2018 17:03:53 +0300 Subject: [PATCH] Display channels promoted by proxy on top. --- Telegram/Resources/scheme.tl | 8 +- Telegram/SourceFiles/apiwrap.cpp | 85 ++++- Telegram/SourceFiles/apiwrap.h | 11 +- Telegram/SourceFiles/auth_session.cpp | 3 + Telegram/SourceFiles/boxes/connection_box.cpp | 302 +++--------------- Telegram/SourceFiles/boxes/connection_box.h | 47 +-- .../codegen/scheme/codegen_scheme.py | 15 +- Telegram/SourceFiles/data/data_feed.cpp | 4 + Telegram/SourceFiles/data/data_feed.h | 1 + Telegram/SourceFiles/data/data_session.cpp | 28 +- Telegram/SourceFiles/data/data_session.h | 5 + .../SourceFiles/dialogs/dialogs_entry.cpp | 16 +- Telegram/SourceFiles/dialogs/dialogs_entry.h | 6 + .../dialogs/dialogs_inner_widget.cpp | 103 +++--- .../dialogs/dialogs_inner_widget.h | 10 +- .../SourceFiles/dialogs/dialogs_layout.cpp | 28 +- Telegram/SourceFiles/history/history.cpp | 17 +- Telegram/SourceFiles/history/history.h | 2 + Telegram/SourceFiles/mainwidget.cpp | 8 +- Telegram/SourceFiles/messenger.cpp | 4 +- Telegram/SourceFiles/mtproto/connection.cpp | 34 +- Telegram/SourceFiles/mtproto/mtp_instance.cpp | 31 +- Telegram/SourceFiles/mtproto/mtp_instance.h | 1 + .../mtproto/special_config_request.cpp | 4 +- .../SourceFiles/window/window_peer_menu.cpp | 6 +- 25 files changed, 392 insertions(+), 387 deletions(-) diff --git a/Telegram/Resources/scheme.tl b/Telegram/Resources/scheme.tl index 3a72d4d5c..3a47c5d55 100644 --- a/Telegram/Resources/scheme.tl +++ b/Telegram/Resources/scheme.tl @@ -959,11 +959,16 @@ messages.foundStickerSets#5108d648 hash:int sets:Vector = mes fileHash#6242c773 offset:int limit:int hash:bytes = FileHash; +inputClientProxy#75588b3f address:string port:int = InputClientProxy; + +help.proxyDataEmpty#e09e1fb8 expires:int = help.ProxyData; +help.proxyDataPromo#2bf7ee23 expires:int peer:Peer chats:Vector users:Vector = help.ProxyData; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector query:!X = X; -initConnection#c7481da6 {X:Type} api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string query:!X = X; +initConnection#785188b8 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X; invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X; invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X; @@ -1161,6 +1166,7 @@ help.getTermsOfService#350170f3 = help.TermsOfService; help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool; help.getCdnConfig#52029342 = CdnConfig; help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls; +help.getProxyData#3d7758e1 = help.ProxyData; channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool; channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector = messages.AffectedMessages; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index e094a04ea..b2bbb5b4a 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -50,6 +50,8 @@ namespace { constexpr auto kReloadChannelMembersTimeout = 1000; // 1 second wait before reload members in channel after adding constexpr auto kSaveCloudDraftTimeout = 1000; // save draft to the cloud with 1 sec extra delay constexpr auto kSaveDraftBeforeQuitTimeout = 1500; // give the app 1.5 secs to save drafts to cloud when quitting +constexpr auto kProxyPromotionInterval = TimeId(60 * 60); +constexpr auto kProxyPromotionMinDelay = TimeId(10); constexpr auto kSmallDelayMs = 5; constexpr auto kUnreadMentionsPreloadIfLess = 5; constexpr auto kUnreadMentionsFirstRequestLimit = 10; @@ -134,12 +136,13 @@ FileLoadTo FileLoadTaskOptions(const ApiWrap::SendOptions &options) { ApiWrap::ApiWrap(not_null session) : _session(session) -, _messageDataResolveDelayed([this] { resolveMessageDatas(); }) -, _webPagesTimer([this] { resolveWebPages(); }) -, _draftsSaveTimer([this] { saveDraftsToCloud(); }) -, _featuredSetsReadTimer([this] { readFeaturedSets(); }) +, _messageDataResolveDelayed([=] { resolveMessageDatas(); }) +, _webPagesTimer([=] { resolveWebPages(); }) +, _draftsSaveTimer([=] { saveDraftsToCloud(); }) +, _featuredSetsReadTimer([=] { readFeaturedSets(); }) , _fileLoader(std::make_unique(kFileLoaderQueueStopTimeout)) -, _feedReadTimer([this] { readFeeds(); }) { +, _feedReadTimer([=] { readFeeds(); }) +, _proxyPromotionTimer([=] { refreshProxyPromotion(); }) { } void ApiWrap::requestChangelog( @@ -152,6 +155,78 @@ void ApiWrap::requestChangelog( ).send(); } +void ApiWrap::refreshProxyPromotion() { + const auto now = unixtime(); + const auto next = (_proxyPromotionNextRequestTime != 0) + ? _proxyPromotionNextRequestTime + : now; + if (_proxyPromotionRequestId) { + getProxyPromotionDelayed(now, next); + return; + } + const auto proxy = Global::UseProxy() + ? Global::SelectedProxy() + : ProxyData(); + const auto key = [&]() -> std::pair { + if (!Global::UseProxy()) { + return {}; + } + const auto &proxy = Global::SelectedProxy(); + if (proxy.type != ProxyData::Type::Mtproto) { + return {}; + } + return { proxy.host, proxy.port }; + }(); + if (_proxyPromotionKey == key && now < next) { + getProxyPromotionDelayed(now, next); + return; + } + _proxyPromotionKey = key; + if (key.first.isEmpty() || !key.second) { + proxyPromotionDone(MTP_help_proxyDataEmpty( + MTP_int(unixtime() + kProxyPromotionInterval))); + return; + } + _proxyPromotionRequestId = request(MTPhelp_GetProxyData( + )).done([=](const MTPhelp_ProxyData &result) { + _proxyPromotionRequestId = 0; + proxyPromotionDone(result); + }).fail([=](const RPCError &error) { + _proxyPromotionRequestId = 0; + const auto now = unixtime(); + const auto next = _proxyPromotionNextRequestTime = now + + kProxyPromotionInterval; + if (!_proxyPromotionTimer.isActive()) { + getProxyPromotionDelayed(now, next); + } + }).send(); +} + +void ApiWrap::getProxyPromotionDelayed(TimeId now, TimeId next) { + _proxyPromotionTimer.callOnce(std::min( + std::max(next - now, kProxyPromotionMinDelay), + kProxyPromotionInterval) * TimeMs(1000)); +}; + +void ApiWrap::proxyPromotionDone(const MTPhelp_ProxyData &proxy) { + if (proxy.type() == mtpc_help_proxyDataEmpty) { + const auto &data = proxy.c_help_proxyDataEmpty(); + const auto next = _proxyPromotionNextRequestTime = data.vexpires.v; + getProxyPromotionDelayed(unixtime(), next); + _session->data().setProxyPromoted(nullptr); + return; + } + Assert(proxy.type() == mtpc_help_proxyDataPromo); + const auto &data = proxy.c_help_proxyDataPromo(); + const auto next = _proxyPromotionNextRequestTime = data.vexpires.v; + getProxyPromotionDelayed(unixtime(), next); + + App::feedChats(data.vchats); + App::feedUsers(data.vusers); + const auto peerId = peerFromMTP(data.vpeer); + _session->data().setProxyPromoted(App::peer(peerId)); +} + void ApiWrap::applyUpdates( const MTPUpdates &updates, uint64 sentMessageRandomId) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 45c36ceb2..4bb74a047 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -93,6 +93,7 @@ public: void requestChangelog( const QString &sinceVersion, base::lambda callback); + void refreshProxyPromotion(); void requestChannelMembersForAdd( not_null channel, @@ -359,7 +360,6 @@ private: not_null channel, const QVector &participants); - void jumpToHistoryDate(not_null peer, const QDate &date); void jumpToFeedDate(not_null feed, const QDate &date); template @@ -437,6 +437,9 @@ private: void readFeeds(); + void getProxyPromotionDelayed(TimeId now, TimeId next); + void proxyPromotionDone(const MTPhelp_ProxyData &proxy); + not_null _session; MessageDataRequests _messageDataRequests; @@ -567,4 +570,10 @@ private: base::flat_map, mtpRequestId> _feedReadRequests; base::Timer _feedReadTimer; + mtpRequestId _proxyPromotionRequestId = 0; + std::pair _proxyPromotionKey; + TimeId _proxyPromotionNextRequestTime = TimeId(0); + base::Timer _proxyPromotionTimer; + + }; diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp index 3e055a7c3..a2e881565 100644 --- a/Telegram/SourceFiles/auth_session.cpp +++ b/Telegram/SourceFiles/auth_session.cpp @@ -285,6 +285,9 @@ AuthSession::AuthSession(UserId userId) _shouldLockAt = 0; notifications().updateAll(); }); + subscribe(Global::RefConnectionTypeChanged(), [=] { + _api->refreshProxyPromotion(); + }); Window::Theme::Background()->start(); } diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index bb241a5a4..871d5c1c6 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -897,240 +897,6 @@ void ProxyBox::addLabel( } // namespace -void ConnectionBox::ShowApplyProxyConfirmation( - Type type, - const QMap &fields) { - const auto server = fields.value(qsl("server")); - const auto port = fields.value(qsl("port")).toUInt(); - auto proxy = ProxyData(); - proxy.type = type; - proxy.host = server; - proxy.port = port; - if (type == Type::Socks5) { - proxy.user = fields.value(qsl("user")); - proxy.password = fields.value(qsl("pass")); - } else if (type == Type::Mtproto) { - proxy.password = fields.value(qsl("secret")); - } - if (proxy) { - const auto box = std::make_shared>(); - const auto text = lng_sure_enable_socks( - lt_server, - server, - lt_port, - QString::number(port)); - *box = Ui::show(Box(text, lang(lng_sure_enable), [=] { - auto &proxies = Global::RefProxiesList(); - if (ranges::find(proxies, proxy) == end(proxies)) { - proxies.push_back(proxy); - } - Global::SetSelectedProxy(proxy); - Global::SetUseProxy(true); - Local::writeSettings(); - Sandbox::refreshGlobalProxy(); - Global::RefConnectionTypeChanged().notify(); - MTP::restart(); - if (const auto strong = box->data()) { - strong->closeBox(); - } - }), LayerOption::KeepOther); - } -} - -ConnectionBox::ConnectionBox(QWidget *parent) -: _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph), Global::SelectedProxy().host) -, _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph), QString::number(Global::SelectedProxy().port)) -, _userInput(this, st::connectionUserInputField, langFactory(lng_connection_user_ph), Global::SelectedProxy().user) -, _passwordInput(this, st::connectionPasswordInputField, langFactory(lng_connection_password_ph), Global::SelectedProxy().password) -, _typeGroup(std::make_shared>(Global::SelectedProxy().type)) -, _autoRadio(this, _typeGroup, Type::None, lang(lng_connection_auto_rb), st::defaultBoxCheckbox) -, _httpProxyRadio(this, _typeGroup, Type::Http, lang(lng_connection_http_proxy_rb), st::defaultBoxCheckbox) -, _tcpProxyRadio(this, _typeGroup, Type::Socks5, lang(lng_connection_tcp_proxy_rb), st::defaultBoxCheckbox) -, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) { -} - -void ConnectionBox::prepare() { - setTitle(langFactory(lng_connection_header)); - - addButton(langFactory(lng_connection_save), [this] { onSave(); }); - addButton(langFactory(lng_cancel), [this] { closeBox(); }); - - _typeGroup->setChangedCallback([this](Type value) { typeChanged(value); }); - - connect(_hostInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); - connect(_portInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); - connect(_userInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); - connect(_passwordInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); - connect(_hostInput, SIGNAL(focused()), this, SLOT(onFieldFocus())); - connect(_portInput, SIGNAL(focused()), this, SLOT(onFieldFocus())); - connect(_userInput, SIGNAL(focused()), this, SLOT(onFieldFocus())); - connect(_passwordInput, SIGNAL(focused()), this, SLOT(onFieldFocus())); - - updateControlsVisibility(); -} - -bool ConnectionBox::badProxyValue() const { - return (_hostInput->getLastText().isEmpty() || !_portInput->getLastText().toInt()); -} - -void ConnectionBox::updateControlsVisibility() { - auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip + _httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() + st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::defaultCheckbox.margin.bottom() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom(); - if (!proxyFieldsVisible()) { - _hostInput->hide(); - _portInput->hide(); - _userInput->hide(); - _passwordInput->hide(); - } else { - newHeight += 2 * st::boxOptionInputSkip + 2 * _hostInput->height(); - _hostInput->show(); - _portInput->show(); - _userInput->show(); - _passwordInput->show(); - } - - setDimensions(st::boxWidth, newHeight); - updateControlsPosition(); -} - -bool ConnectionBox::proxyFieldsVisible() const { - return (_typeGroup->value() == Type::Http - || _typeGroup->value() == Type::Socks5); -} - -void ConnectionBox::setInnerFocus() { - if (proxyFieldsVisible()) { - _hostInput->setFocusFast(); - } else { - setFocus(); - } -} - -void ConnectionBox::resizeEvent(QResizeEvent *e) { - BoxContent::resizeEvent(e); - - updateControlsPosition(); -} - -void ConnectionBox::updateControlsPosition() { - auto type = _typeGroup->value(); - _autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->getMargins().top() + st::boxOptionListPadding.top()); - _httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListSkip); - - auto inputy = 0; - auto fieldsVisible = proxyFieldsVisible(); - auto fieldsBelowHttp = fieldsVisible && (type == Type::Http); - auto fieldsBelowTcp = fieldsVisible && (type == Type::Socks5); - if (fieldsBelowHttp) { - inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; - _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip); - } else { - _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListSkip); - if (fieldsBelowTcp) { - inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; - } - } - - if (inputy) { - _hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), inputy); - _portInput->moveToRight(st::boxPadding.right(), inputy); - _userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), _hostInput->y() + _hostInput->height() + st::boxOptionInputSkip); - _passwordInput->moveToRight(st::boxPadding.right(), _userInput->y()); - } - - auto tryipv6y = (fieldsBelowTcp ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip; - _tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y); -} - -void ConnectionBox::typeChanged(Type type) { - if (!proxyFieldsVisible()) { - setFocus(); - } - updateControlsVisibility(); - if (proxyFieldsVisible()) { - if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) { - _hostInput->setFocusFast(); - } - if ((type == Type::Http) && !_portInput->getLastText().toInt()) { - _portInput->setText(qsl("80")); - _portInput->finishAnimating(); - } - } - update(); -} - -void ConnectionBox::onFieldFocus() { -} - -void ConnectionBox::onSubmit() { - onFieldFocus(); - if (_hostInput->hasFocus()) { - if (!_hostInput->getLastText().trimmed().isEmpty()) { - _portInput->setFocus(); - } else { - _hostInput->showError(); - } - } else if (_portInput->hasFocus()) { - if (_portInput->getLastText().trimmed().toInt() > 0) { - _userInput->setFocus(); - } else { - _portInput->showError(); - } - } else if (_userInput->hasFocus()) { - _passwordInput->setFocus(); - } else if (_passwordInput->hasFocus()) { - if (_hostInput->getLastText().trimmed().isEmpty()) { - _hostInput->setFocus(); - _hostInput->showError(); - } else if (_portInput->getLastText().trimmed().toInt() <= 0) { - _portInput->setFocus(); - _portInput->showError(); - } else { - onSave(); - } - } -} - -void ConnectionBox::onSave() { - auto proxy = ProxyData(); - proxy.host = _hostInput->getLastText().trimmed(); - proxy.user = _userInput->getLastText().trimmed(); - proxy.password = _passwordInput->getLastText().trimmed(); - proxy.port = _portInput->getLastText().toUInt(); - - auto type = _typeGroup->value(); - if (type == Type::None) { - proxy = ProxyData(); - } else if (type == Type::Mtproto) { - proxy = Global::SelectedProxy(); - } else { - if (proxy.host.isEmpty()) { - _hostInput->showError(); - return; - } else if (!proxy.port) { - _portInput->showError(); - return; - } - proxy.type = type; - } - Global::SetSelectedProxy(proxy ? proxy : ProxyData()); - Global::SetUseProxy(proxy ? true : false); - if (cPlatform() == dbipWindows && Global::TryIPv6() != _tryIPv6->checked()) { - Global::SetTryIPv6(_tryIPv6->checked()); - Local::writeSettings(); - Global::RefConnectionTypeChanged().notify(); - - App::restart(); - } else { - Global::SetTryIPv6(_tryIPv6->checked()); - Local::writeSettings(); - Sandbox::refreshGlobalProxy(); - Global::RefConnectionTypeChanged().notify(); - - MTP::restart(); - closeBox(); - } -} - AutoDownloadBox::AutoDownloadBox(QWidget *parent) : _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox) , _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups), st::defaultBoxCheckbox) @@ -1259,6 +1025,42 @@ ProxiesBoxController::ProxiesBoxController() } } +void ProxiesBoxController::ShowApplyConfirmation( + Type type, + const QMap &fields) { + const auto server = fields.value(qsl("server")); + const auto port = fields.value(qsl("port")).toUInt(); + auto proxy = ProxyData(); + proxy.type = type; + proxy.host = server; + proxy.port = port; + if (type == Type::Socks5) { + proxy.user = fields.value(qsl("user")); + proxy.password = fields.value(qsl("pass")); + } else if (type == Type::Mtproto) { + proxy.password = fields.value(qsl("secret")); + } + if (proxy) { + const auto box = std::make_shared>(); + const auto text = lng_sure_enable_socks( + lt_server, + server, + lt_port, + QString::number(port)); + *box = Ui::show(Box(text, lang(lng_sure_enable), [=] { + auto &proxies = Global::RefProxiesList(); + if (ranges::find(proxies, proxy) == end(proxies)) { + proxies.push_back(proxy); + } + Messenger::Instance().mtp()->setCurrentProxy(proxy, true); + Local::writeSettings(); + if (const auto strong = box->data()) { + strong->closeBox(); + } + }), LayerOption::KeepOther); + } +} + rpl::producer ProxiesBoxController::proxyEnabledValue() const { return _proxyEnabledChanges.events_starting_with_copy( Global::UseProxy() @@ -1411,9 +1213,8 @@ void ProxiesBoxController::applyItem(int id) { auto j = findByProxy(Global::SelectedProxy()); - Global::SetSelectedProxy(item->data); - Global::SetUseProxy(true); - applyChanges(); + Messenger::Instance().mtp()->setCurrentProxy(item->data, true); + saveDelayed(); if (j != end(_list)) { updateView(*j); @@ -1433,8 +1234,10 @@ void ProxiesBoxController::setDeleted(int id, bool deleted) { _lastSelectedProxy = base::take(Global::RefSelectedProxy()); if (Global::UseProxy()) { _lastSelectedProxyUsed = true; - Global::SetUseProxy(false); - applyChanges(); + Messenger::Instance().mtp()->setCurrentProxy( + ProxyData(), + false); + saveDelayed(); } else { _lastSelectedProxyUsed = false; } @@ -1455,10 +1258,12 @@ void ProxiesBoxController::setDeleted(int id, bool deleted) { if (!Global::SelectedProxy() && _lastSelectedProxy == item->data) { Assert(!Global::UseProxy()); - Global::SetSelectedProxy(base::take(_lastSelectedProxy)); if (base::take(_lastSelectedProxyUsed)) { - Global::SetUseProxy(true); - applyChanges(); + Messenger::Instance().mtp()->setCurrentProxy( + base::take(_lastSelectedProxy), + true); + } else { + Global::SetSelectedProxy(base::take(_lastSelectedProxy)); } } } @@ -1559,8 +1364,10 @@ bool ProxiesBoxController::setProxyEnabled(bool enabled) { } } } - Global::SetUseProxy(enabled); - applyChanges(); + Messenger::Instance().mtp()->setCurrentProxy( + Global::SelectedProxy(), + enabled); + saveDelayed(); return true; } @@ -1580,13 +1387,8 @@ void ProxiesBoxController::setTryIPv6(bool enabled) { return; } Global::SetTryIPv6(enabled); - applyChanges(); -} - -void ProxiesBoxController::applyChanges() { - Sandbox::refreshGlobalProxy(); - Global::RefConnectionTypeChanged().notify(); MTP::restart(); + Global::RefConnectionTypeChanged().notify(); saveDelayed(); } diff --git a/Telegram/SourceFiles/boxes/connection_box.h b/Telegram/SourceFiles/boxes/connection_box.h index 04b33cc9f..fd422ab6d 100644 --- a/Telegram/SourceFiles/boxes/connection_box.h +++ b/Telegram/SourceFiles/boxes/connection_box.h @@ -22,48 +22,6 @@ template class Radioenum; } // namespace Ui -class ConnectionBox : public BoxContent { - Q_OBJECT - -public: - using Type = ProxyData::Type; - - ConnectionBox(QWidget *parent); - - static void ShowApplyProxyConfirmation( - Type type, - const QMap &fields); - -protected: - void prepare() override; - void setInnerFocus() override; - - void resizeEvent(QResizeEvent *e) override; - -private slots: - void onSubmit(); - void onFieldFocus(); - void onSave(); - -private: - void typeChanged(Type type); - void updateControlsVisibility(); - void updateControlsPosition(); - bool badProxyValue() const; - bool proxyFieldsVisible() const; - - object_ptr _hostInput; - object_ptr _portInput; - object_ptr _userInput; - object_ptr _passwordInput; - std::shared_ptr> _typeGroup; - object_ptr> _autoRadio; - object_ptr> _httpProxyRadio; - object_ptr> _tcpProxyRadio; - object_ptr _tryIPv6; - -}; - class AutoDownloadBox : public BoxContent { Q_OBJECT @@ -98,6 +56,10 @@ public: ProxiesBoxController(); + static void ShowApplyConfirmation( + Type type, + const QMap &fields); + static object_ptr CreateOwningBox(); object_ptr create(); @@ -155,7 +117,6 @@ private: void setDeleted(int id, bool deleted); void updateView(const Item &item); void share(const ProxyData &proxy); - void applyChanges(); void saveDelayed(); void refreshChecker(Item &item); void setupChecker(int id, const Checker &checker); diff --git a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py index f5d1a3a17..6652a1caf 100644 --- a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py +++ b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py @@ -429,7 +429,7 @@ for line in lines: funcsList.append(restype); funcsDict[restype] = []; # TypesDict[restype] = resType; - funcsDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions]); + funcsDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions, isTemplate]); else: if (isTemplate != ''): print('Template types not allowed: "' + resType + '" in line: ' + line); @@ -438,7 +438,7 @@ for line in lines: typesList.append(restype); typesDict[restype] = []; TypesDict[restype] = resType; - typesDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions]); + typesDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions, isTemplate]); consts = consts + 1; @@ -455,10 +455,15 @@ def addTextSerialize(lst, dct, dataLetter): conditionsList = data[5]; conditions = data[6]; trivialConditions = data[7]; + isTemplate = data[8]; + + templateArgument = '' + if (isTemplate != ''): + templateArgument = '' result += 'void Serialize_' + name + '(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n'; if (len(conditions)): - result += '\tauto flag = MTP' + dataLetter + name + '::Flags::from_raw(iflag);\n\n'; + result += '\tauto flag = MTP' + dataLetter + name + templateArgument + '::Flags::from_raw(iflag);\n\n'; if (len(prms)): result += '\tif (stage) {\n'; result += '\t\tto.add(",\\n").addSpaces(lev);\n'; @@ -474,12 +479,12 @@ def addTextSerialize(lst, dct, dataLetter): if (k == hasFlags): result += 'if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; '; if (k in trivialConditions): - result += 'if (flag & MTP' + dataLetter + name + '::Flag::f_' + k + ') { '; + result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { '; result += 'to.add("YES [ BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); '; result += '} else { to.add("[ SKIPPED BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); } '; else: if (k in conditions): - result += 'if (flag & MTP' + dataLetter + name + '::Flag::f_' + k + ') { '; + result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { '; result += 'types.push_back('; vtypeget = re.match(r'^[Vv]ector', v); if (vtypeget): diff --git a/Telegram/SourceFiles/data/data_feed.cpp b/Telegram/SourceFiles/data/data_feed.cpp index ac850955a..d7366e286 100644 --- a/Telegram/SourceFiles/data/data_feed.cpp +++ b/Telegram/SourceFiles/data/data_feed.cpp @@ -443,6 +443,10 @@ bool Feed::toImportant() const { return false; // TODO feeds workmode } +bool Feed::useProxyPromotion() const { + return false; +} + bool Feed::shouldBeInChatList() const { return _channels.size() > 1; } diff --git a/Telegram/SourceFiles/data/data_feed.h b/Telegram/SourceFiles/data/data_feed.h index 806724326..d182de08d 100644 --- a/Telegram/SourceFiles/data/data_feed.h +++ b/Telegram/SourceFiles/data/data_feed.h @@ -59,6 +59,7 @@ public: int unreadCount() const; bool unreadCountKnown() const; + bool useProxyPromotion() const override; bool toImportant() const override; bool shouldBeInChatList() const override; int chatListUnreadCount() const override; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index fc8c23ffc..ff11e6d8b 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -83,10 +83,14 @@ void Session::setupChannelLeavingViewer() { return update.peer->asChannel(); }) | rpl::filter([](ChannelData *channel) { return (channel != nullptr) - && !(channel->amIn()) - && (channel->feed() != nullptr); + && !(channel->amIn()); }) | rpl::start_with_next([=](not_null channel) { channel->clearFeed(); + if (const auto history = App::historyLoaded(channel->id)) { + history->removeJoinedMessage(); + history->updateChatListExistence(); + history->updateChatListSortPosition(); + } }, _lifetime); } @@ -1592,4 +1596,24 @@ MessageIdsList Session::takeMimeForwardIds() { return std::move(_mimeForwardIds); } +void Session::setProxyPromoted(PeerData *promoted) { + if (_proxyPromoted != promoted) { + if (const auto history = App::historyLoaded(_proxyPromoted)) { + history->cacheProxyPromoted(false); + } + _proxyPromoted = promoted; + if (_proxyPromoted) { + const auto history = App::history(_proxyPromoted); + history->cacheProxyPromoted(true); + if (!history->lastMessageKnown()) { + _session->api().requestDialogEntry(history); + } + } + } +} + +PeerData *Session::proxyPromoted() const { + return _proxyPromoted; +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 197345cf8..c3bea5698 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -363,6 +363,9 @@ public: void setMimeForwardIds(MessageIdsList &&list); MessageIdsList takeMimeForwardIds(); + void setProxyPromoted(PeerData *promoted); + PeerData *proxyPromoted() const; + Groups &groups() { return _groups; } @@ -543,6 +546,8 @@ private: not_null, std::vector>> _views; + PeerData *_proxyPromoted = nullptr; + MessageIdsList _mimeForwardIds; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index baa59f8bc..5d4a774e9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -26,6 +26,10 @@ uint64 DialogPosFromDate(const QDateTime &date) { return (uint64(date.toTime_t()) << 32) | (++DialogsPosToTopShift); } +uint64 ProxyPromotedDialogPos() { + return 0xFFFFFFFFFFFF0001ULL; +} + uint64 PinnedDialogPos(int pinnedIndex) { return 0xFFFFFFFF00000000ULL + pinnedIndex; } @@ -49,12 +53,22 @@ void Entry::cachePinnedIndex(int index) { } } +void Entry::cacheProxyPromoted(bool promoted) { + if (_isProxyPromoted != promoted) { + _isProxyPromoted = promoted; + updateChatListSortPosition(); + updateChatListEntry(); + } +} + bool Entry::needUpdateInChatList() const { return inChatList(Dialogs::Mode::All) || shouldBeInChatList(); } void Entry::updateChatListSortPosition() { - _sortKeyInChatList = isPinnedDialog() + _sortKeyInChatList = useProxyPromotion() + ? ProxyPromotedDialogPos() + : isPinnedDialog() ? PinnedDialogPos(_pinnedIndex) : DialogPosFromDate(adjustChatListDate()); if (needUpdateInChatList()) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index a30712efe..4d70ee1b6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -56,6 +56,11 @@ public: return _pinnedIndex > 0; } void cachePinnedIndex(int index); + bool isProxyPromoted() const { + return _isProxyPromoted; + } + virtual bool useProxyPromotion() const = 0; + void cacheProxyPromoted(bool promoted); uint64 sortKeyInChatList() const { return _sortKeyInChatList; } @@ -111,6 +116,7 @@ private: RowsByLetter _chatListLinks[2]; uint64 _sortKeyInChatList = 0; int _pinnedIndex = 0; + bool _isProxyPromoted = false; QDateTime _lastMessageDate; }; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 1f4239598..37bb04ef4 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -165,6 +165,22 @@ int DialogsInner::dialogsOffset() const { return _dialogsImportant ? st::dialogsImportantBarHeight : 0; } +int DialogsInner::proxyPromotedCount() const { + auto result = 0; + for_const (auto row, *shownDialogs()) { + if (row->entry()->useProxyPromotion()) { + ++result; + } else { + break; + } + } + return result; +} + +int DialogsInner::pinnedOffset() const { + return dialogsOffset() + proxyPromotedCount() * st::dialogsRowHeight; +} + int DialogsInner::filteredOffset() const { return _hashtagResults.size() * st::mentionHeight; } @@ -231,13 +247,39 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO dialogsClip = dialogsClip.marginsAdded(QMargins(0, st::dialogsRowHeight, 0, st::dialogsRowHeight)); } + const auto promoted = proxyPromotedCount(); + const auto paintDialog = [&](not_null row) { + const auto pinned = row->pos() - promoted; + const auto count = _pinnedRows.size(); + const auto xadd = 0; + const auto yadd = base::in_range(pinned, 0, count) + ? qRound(_pinnedRows[pinned].yadd.current()) + : 0; + if (xadd || yadd) { + p.translate(xadd, yadd); + } + const auto isActive = (row->key() == active); + const auto isSelected = (row->key() == selected); + Dialogs::Layout::RowPainter::paint( + p, + row, + fullWidth, + isActive, + isSelected, + paintingOther, + ms); + if (xadd || yadd) { + p.translate(-xadd, -yadd); + } + }; + auto i = list.cfind(dialogsClip.top(), st::dialogsRowHeight); if (i != list.cend()) { auto lastPaintedPos = (*i)->pos(); // If we're reordering pinned chats we need to fill this area background first. if (reorderingPinned) { - p.fillRect(0, 0, fullWidth, st::dialogsRowHeight * _pinnedRows.size(), st::dialogsBg); + p.fillRect(0, promoted * st::dialogsRowHeight, fullWidth, st::dialogsRowHeight * _pinnedRows.size(), st::dialogsBg); } p.translate(0, lastPaintedPos * st::dialogsRowHeight); @@ -248,15 +290,9 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } // Skip currently dragged chat to paint it above others after. - if (lastPaintedPos != _aboveIndex) { - paintDialog( - p, - row, - fullWidth, - active, - selected, - paintingOther, - ms); + if (lastPaintedPos != promoted + _aboveIndex + || _aboveIndex < 0) { + paintDialog(row); } p.translate(0, st::dialogsRowHeight); @@ -265,11 +301,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO // Paint the dragged chat above all others. if (_aboveIndex >= 0) { - auto i = list.cfind(_aboveIndex, 1); + auto i = list.cfind(promoted + _aboveIndex, 1); auto pos = (i == list.cend()) ? -1 : (*i)->pos(); - if (pos == _aboveIndex) { + if (pos == promoted + _aboveIndex) { p.translate(0, (pos - lastPaintedPos) * st::dialogsRowHeight); - paintDialog(p, *i, fullWidth, active, selected, paintingOther, ms); + paintDialog(*i); p.translate(0, (lastPaintedPos - pos) * st::dialogsRowHeight); } } @@ -459,33 +495,6 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO } } -void DialogsInner::paintDialog( - Painter &p, - not_null row, - int fullWidth, - Dialogs::Key active, - Dialogs::Key selected, - bool onlyBackground, - TimeMs ms) { - auto pos = row->pos(); - auto xadd = 0, yadd = 0; - if (pos < _pinnedRows.size()) { - yadd = qRound(_pinnedRows[pos].yadd.current()); - } - if (xadd || yadd) p.translate(xadd, yadd); - const auto isActive = (row->key() == active); - const auto isSelected = (row->key() == selected); - Dialogs::Layout::RowPainter::paint( - p, - row, - fullWidth, - isActive, - isSelected, - onlyBackground, - ms); - if (xadd || yadd) p.translate(-xadd, -yadd); -} - void DialogsInner::paintPeerSearchResult( Painter &p, not_null result, @@ -846,7 +855,9 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { int DialogsInner::shownPinnedCount() const { auto result = 0; for_const (auto row, *shownDialogs()) { - if (!row->entry()->isPinnedDialog()) { + if (row->entry()->useProxyPromotion()) { + continue; + } else if (!row->entry()->isPinnedDialog()) { break; } ++result; @@ -860,7 +871,9 @@ int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) { } auto result = 0; for_const (auto row, *shownDialogs()) { - if (!row->entry()->isPinnedDialog()) { + if (row->entry()->useProxyPromotion()) { + continue; + } else if (!row->entry()->isPinnedDialog()) { break; } else if (row == ofRow) { return result; @@ -1013,7 +1026,7 @@ void DialogsInner::step_pinnedShifting(TimeMs ms, bool timer) { if (updateMax < _draggingIndex) updateMax = _draggingIndex; } if (updateMin >= 0) { - auto top = _dialogsImportant ? st::dialogsImportantBarHeight : 0; + auto top = pinnedOffset(); auto updateFrom = top + st::dialogsRowHeight * (updateMin - 1); auto updateHeight = st::dialogsRowHeight * (updateMax - updateMin + 3); if (base::in_range(_aboveIndex, 0, _pinnedRows.size())) { @@ -1770,7 +1783,7 @@ void DialogsInner::applyDialog(const MTPDdialog &dialog) { const auto history = App::history(peerId); history->applyDialog(dialog); - if (!history->isPinnedDialog()) { + if (!history->useProxyPromotion() && !history->isPinnedDialog()) { const auto date = history->chatsListDate(); if (!date.isNull()) { addSavedPeersAfter(date); @@ -1793,7 +1806,7 @@ void DialogsInner::applyDialog(const MTPDdialog &dialog) { // const auto feed = Auth().data().feed(feedId); // feed->applyDialog(dialog); // -// if (!feed->isPinnedDialog()) { +// if (!feed->useProxyPromotion() && !feed->isPinnedDialog()) { // const auto date = feed->chatsListDate(); // if (!date.isNull()) { // addSavedPeersAfter(date); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 46de6c91f..9f6f033a0 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -213,19 +213,13 @@ private: UpdateRowSections sections = UpdateRowSection::All); int dialogsOffset() const; + int proxyPromotedCount() const; + int pinnedOffset() const; int filteredOffset() const; int peerSearchOffset() const; int searchedOffset() const; int searchInChatSkip() const; - void paintDialog( - Painter &p, - not_null row, - int fullWidth, - Dialogs::Key active, - Dialogs::Key selected, - bool onlyBackground, - TimeMs ms); void paintPeerSearchResult( Painter &p, not_null result, diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index dba8821bc..b86bde560 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -25,6 +25,14 @@ namespace { // Show all dates that are in the last 20 hours in time format. constexpr int kRecentlyInSeconds = 20 * 3600; +void paintRowTopRight(Painter &p, const QString &text, QRect &rectForName, bool active, bool selected) { + const auto width = st::dialogsDateFont->width(text); + rectForName.setWidth(rectForName.width() - width - st::dialogsDateSkip); + p.setFont(st::dialogsDateFont); + p.setPen(active ? st::dialogsDateFgActive : (selected ? st::dialogsDateFgOver : st::dialogsDateFg)); + p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent, text); +} + void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, bool selected) { auto now = QDateTime::currentDateTime(); auto lastTime = date; @@ -41,11 +49,7 @@ void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, b } else { dt = lastDate.toString(qsl("d.MM.yy")); } - int32 dtWidth = st::dialogsDateFont->width(dt); - rectForName.setWidth(rectForName.width() - dtWidth - st::dialogsDateSkip); - p.setFont(st::dialogsDateFont); - p.setPen(active ? st::dialogsDateFgActive : (selected ? st::dialogsDateFgOver : st::dialogsDateFg)); - p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent, dt); + paintRowTopRight(p, dt, rectForName, active, selected); } enum class Flag { @@ -132,7 +136,11 @@ void paintRow( namewidth, st::msgNameFont->height); - if (from && !(flags & Flag::FeedSearchResult)) { + const auto promoted = chat.entry()->useProxyPromotion(); + if (promoted) { + const auto text = QString("Proxy sponsor"); + paintRowTopRight(p, text, rectForName, active, selected); + } else if (from && !(flags & Flag::FeedSearchResult)) { if (const auto chatTypeIcon = ChatTypeIcon(from, active, selected)) { chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); @@ -147,7 +155,9 @@ void paintRow( + st::msgNameFont->height + st::dialogsSkip; if (draft) { - paintRowDate(p, date, rectForName, active, selected); + if (!promoted) { + paintRowDate(p, date, rectForName, active, selected); + } auto availableWidth = namewidth; if (entry->isPinnedDialog()) { @@ -183,7 +193,9 @@ void paintRow( // Empty history } } else if (!item->isEmpty()) { - paintRowDate(p, date, rectForName, active, selected); + if (!promoted) { + paintRowDate(p, date, rectForName, active, selected); + } paintItemCallback(nameleft, namewidth); } else if (entry->isPinnedDialog()) { diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 2d12ca128..19f01b640 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -2134,6 +2134,15 @@ void History::updateChatListExistence() { } } +bool History::useProxyPromotion() const { + if (!isProxyPromoted()) { + return false; + } else if (const auto channel = peer->asChannel()) { + return !isPinnedDialog() && !channel->amIn(); + } + return false; +} + bool History::shouldBeInChatList() const { if (peer->migrateTo()) { return false; @@ -2141,7 +2150,7 @@ bool History::shouldBeInChatList() const { return true; } else if (const auto channel = peer->asChannel()) { if (!channel->amIn()) { - return false; + return isProxyPromoted(); } else if (const auto feed = channel->feed()) { return !feed->needUpdateInChatList(); } @@ -2474,6 +2483,12 @@ void History::checkJoinedMessage(bool createUnread) { } } +void History::removeJoinedMessage() { + if (_joinedMessage) { + base::take(_joinedMessage)->destroy(); + } +} + bool History::isEmpty() const { return blocks.empty(); } diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 92f87262a..e80d5bce8 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -123,6 +123,7 @@ public: MsgRange rangeForDifferenceRequest() const; HistoryService *insertJoinedMessage(bool unread); void checkJoinedMessage(bool createUnread = false); + void removeJoinedMessage(); bool isEmpty() const; bool isDisplayedEmpty() const; @@ -318,6 +319,7 @@ public: HistoryItemsList validateForwardDraft(); void setForwardDraft(MessageIdsList &&items); + bool useProxyPromotion() const override; void updateChatListExistence() override; bool shouldBeInChatList() const override; bool toImportant() const override { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index be979d225..a96628f40 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -5095,11 +5095,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { auto &d = update.c_updateChannel(); if (const auto channel = App::channelLoaded(d.vchannel_id.v)) { channel->inviter = UserId(0); - if (!channel->amIn()) { - if (const auto history = App::historyLoaded(channel->id)) { - history->updateChatListExistence(); - } - } else if (!channel->amCreator() && App::history(channel->id)) { + if (channel->amIn() + && !channel->amCreator() + && App::history(channel->id)) { _updatedChannels.insert(channel, true); Auth().api().requestSelfParticipant(channel); } diff --git a/Telegram/SourceFiles/messenger.cpp b/Telegram/SourceFiles/messenger.cpp index de28b7b24..93942aec3 100644 --- a/Telegram/SourceFiles/messenger.cpp +++ b/Telegram/SourceFiles/messenger.cpp @@ -856,11 +856,11 @@ bool Messenger::openLocalUrl(const QString &url) { } } else if (auto socksMatch = regex_match(qsl("^socks/?\\?(.+)(#|$)"), command, matchOptions)) { auto params = url_parse_params(socksMatch->captured(1), UrlParamNameTransform::ToLower); - ConnectionBox::ShowApplyProxyConfirmation(ProxyData::Type::Socks5, params); + ProxiesBoxController::ShowApplyConfirmation(ProxyData::Type::Socks5, params); return true; } else if (auto proxyMatch = regex_match(qsl("^proxy/?\\?(.+)(#|$)"), command, matchOptions)) { auto params = url_parse_params(proxyMatch->captured(1), UrlParamNameTransform::ToLower); - ConnectionBox::ShowApplyProxyConfirmation(ProxyData::Type::Mtproto, params); + ProxiesBoxController::ShowApplyConfirmation(ProxyData::Type::Mtproto, params); return true; } return false; diff --git a/Telegram/SourceFiles/mtproto/connection.cpp b/Telegram/SourceFiles/mtproto/connection.cpp index 0de6cd8f8..fb70f6dea 100644 --- a/Telegram/SourceFiles/mtproto/connection.cpp +++ b/Telegram/SourceFiles/mtproto/connection.cpp @@ -835,12 +835,34 @@ void ConnectionPrivate::tryToSend() { int32 initSize = 0, initSizeInInts = 0; if (needsLayer) { Assert(_connectionOptions != nullptr); - auto systemLangCode = _connectionOptions->systemLangCode; - auto cloudLangCode = _connectionOptions->cloudLangCode; - auto langPack = "tdesktop"; - auto deviceModel = (_dcType == DcType::Cdn) ? "n/a" : cApiDeviceModel(); - auto systemVersion = (_dcType == DcType::Cdn) ? "n/a" : cApiSystemVersion(); - initWrapper = MTPInitConnection(MTP_int(ApiId), MTP_string(deviceModel), MTP_string(systemVersion), MTP_string(str_const_toString(AppVersionStr)), MTP_string(systemLangCode), MTP_string(langPack), MTP_string(cloudLangCode), mtpRequest()); + const auto systemLangCode = _connectionOptions->systemLangCode; + const auto cloudLangCode = _connectionOptions->cloudLangCode; + const auto langPack = "tdesktop"; + const auto deviceModel = (_dcType == DcType::Cdn) + ? "n/a" + : cApiDeviceModel(); + const auto systemVersion = (_dcType == DcType::Cdn) + ? "n/a" + : cApiSystemVersion(); + const auto proxyType = _connectionOptions->proxy.type; + const auto mtprotoProxy = (proxyType == ProxyData::Type::Mtproto); + const auto clientProxyFields = mtprotoProxy + ? MTP_inputClientProxy( + MTP_string(_connectionOptions->proxy.host), + MTP_int(_connectionOptions->proxy.port)) + : MTPInputClientProxy(); + using Flag = MTPInitConnection::Flag; + initWrapper = MTPInitConnection( + MTP_flags(mtprotoProxy ? Flag::f_proxy : Flag(0)), + MTP_int(ApiId), + MTP_string(deviceModel), + MTP_string(systemVersion), + MTP_string(str_const_toString(AppVersionStr)), + MTP_string(systemLangCode), + MTP_string(langPack), + MTP_string(cloudLangCode), + clientProxyFields, + mtpRequest()); initSizeInInts = (initWrapper.innerLength() >> 2) + 2; initSize = initSizeInInts * sizeof(mtpPrime); } diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 9e173fa76..f6b3a2359 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/rsa_public_key.h" #include "storage/localstorage.h" #include "auth_session.h" +#include "application.h" #include "apiwrap.h" #include "messenger.h" #include "lang/lang_instance.h" @@ -36,6 +37,7 @@ public: void start(Config &&config); + void setCurrentProxy(const ProxyData &proxy, bool enabled); void suggestMainDcId(DcId mainDcId); void setMainDcId(DcId mainDcId); DcId mainDcId() const; @@ -259,6 +261,28 @@ void Instance::Private::start(Config &&config) { requestConfig(); } +void Instance::Private::setCurrentProxy( + const ProxyData &proxy, + bool enabled) { + const auto key = [&](const ProxyData &proxy) { + if (proxy.type == ProxyData::Type::Mtproto) { + return std::make_pair(proxy.host, proxy.port); + } + return std::make_pair(QString(), uint32(0)); + }; + const auto previousKey = key(Global::UseProxy() + ? Global::SelectedProxy() + : ProxyData()); + Global::SetSelectedProxy(proxy); + Global::SetUseProxy(enabled); + Sandbox::refreshGlobalProxy(); + restart(); + if (previousKey != key(proxy)) { + reInitConnection(mainDcId()); + } + Global::RefConnectionTypeChanged().notify(); +} + void Instance::Private::suggestMainDcId(DcId mainDcId) { if (_mainDcIdForced) return; setMainDcId(mainDcId); @@ -1342,11 +1366,16 @@ void Instance::Private::prepareToDestroy() { MustNotCreateSessions = true; } -Instance::Instance(not_null options, Mode mode, Config &&config) : QObject() +Instance::Instance(not_null options, Mode mode, Config &&config) +: QObject() , _private(std::make_unique(this, options, mode)) { _private->start(std::move(config)); } +void Instance::setCurrentProxy(const ProxyData &proxy, bool enabled) { + _private->setCurrentProxy(proxy, enabled); +} + void Instance::suggestMainDcId(DcId mainDcId) { _private->suggestMainDcId(mainDcId); } diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.h b/Telegram/SourceFiles/mtproto/mtp_instance.h index 0e0d3e915..1fc0b7202 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.h +++ b/Telegram/SourceFiles/mtproto/mtp_instance.h @@ -46,6 +46,7 @@ public: Instance(const Instance &other) = delete; Instance &operator=(const Instance &other) = delete; + void setCurrentProxy(const ProxyData &proxy, bool enabled); void suggestMainDcId(DcId mainDcId); void setMainDcId(DcId mainDcId); DcId mainDcId() const; diff --git a/Telegram/SourceFiles/mtproto/special_config_request.cpp b/Telegram/SourceFiles/mtproto/special_config_request.cpp index 1faf7b72b..9ed1828a6 100644 --- a/Telegram/SourceFiles/mtproto/special_config_request.cpp +++ b/Telegram/SourceFiles/mtproto/special_config_request.cpp @@ -171,7 +171,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) { switch (type) { case Type::App: { url.setPath(cTestMode() - ? qsl("/test/config.txt") + ? qsl("/testv2/config.txt") : qsl("/prodv2/config.txt")); request.setRawHeader("Host", "tcdnb.azureedge.net"); } break; @@ -179,7 +179,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) { url.setPath(qsl("/resolve")); url.setQuery( qsl("name=%1.stel.com&type=16").arg( - cTestMode() ? qsl("tap") : qsl("apv2"))); + cTestMode() ? qsl("testapv2") : qsl("apv2"))); request.setRawHeader("Host", "dns.google.com"); } break; default: Unexpected("Type in SpecialConfigRequest::performRequest."); diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index a844ec428..7dbf160e1 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -386,7 +386,11 @@ void Filler::addChannelActions(not_null channel) { void Filler::fill() { if (_source == PeerMenuSource::ChatsList) { - addPinToggle(); + if (const auto history = App::historyLoaded(_peer)) { + if (!history->useProxyPromotion()) { + addPinToggle(); + } + } } if (showInfo()) { addInfo();