diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index d2daeeec0..390011b00 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -101,8 +101,12 @@ PRIVATE api/api_common.h api/api_hash.h + api/api_self_destruct.cpp + api/api_self_destruct.h api/api_sending.cpp api/api_sending.h + api/api_sensitive_content.cpp + api/api_sensitive_content.h api/api_single_message_search.cpp api/api_single_message_search.h api/api_text_entities.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 6adb39522..a30909ba5 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -416,6 +416,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_performance" = "Performance"; "lng_settings_enable_animations" = "Enable animations"; "lng_settings_autoplay_gifs" = "Autoplay GIFs"; +"lng_settings_sensitive_title" = "Sensitive content"; +"lng_settings_sensitive_disable_filtering" = "Disable filtering"; +"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices."; "lng_settings_spellchecker" = "Spell checker"; "lng_settings_system_spellchecker" = "Use system spell checker"; diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index 823e996c2..96cd9f2f3 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -1091,6 +1091,8 @@ auth.loginTokenSuccess#390d5c5e authorization:auth.Authorization = auth.LoginTok auth.loginTokenInfo#5203303a dc_id:int auth_key_id:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string ip:string region:string = auth.LoginTokenInfo; +account.contentSettings#57e28221 flags:# sensitive_enabled:flags.0?true sensitive_can_change:flags.1?true = account.ContentSettings; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1183,6 +1185,8 @@ account.saveTheme#f257106c theme:InputTheme unsave:Bool = Bool; account.installTheme#7ae43737 flags:# dark:flags.0?true format:flags.1?string theme:flags.1?InputTheme = Bool; account.getTheme#8d9d742b format:string theme:InputTheme document_id:long = Theme; account.getThemes#285946f8 format:string hash:int = account.Themes; +account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool; +account.getContentSettings#8b9b4dae = account.ContentSettings; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#ca30a5b1 id:InputUser = UserFull; diff --git a/Telegram/SourceFiles/api/api_self_destruct.cpp b/Telegram/SourceFiles/api/api_self_destruct.cpp new file mode 100644 index 000000000..80ae25186 --- /dev/null +++ b/Telegram/SourceFiles/api/api_self_destruct.cpp @@ -0,0 +1,51 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "api/api_self_destruct.h" + +#include "apiwrap.h" + +namespace Api { + +SelfDestruct::SelfDestruct(not_null api) +: _api(api->instance()) { +} + +void SelfDestruct::reload() { + if (_requestId) { + return; + } + _requestId = _api.request(MTPaccount_GetAccountTTL( + )).done([=](const MTPAccountDaysTTL &result) { + _requestId = 0; + result.match([&](const MTPDaccountDaysTTL &data) { + _days = data.vdays().v; + }); + }).fail([=](const RPCError &error) { + _requestId = 0; + }).send(); +} + +rpl::producer SelfDestruct::days() const { + using namespace rpl::mappers; + + return _days.value() | rpl::filter(_1 != 0); +} + +void SelfDestruct::update(int days) { + _api.request(_requestId).cancel(); + _requestId = _api.request(MTPaccount_SetAccountTTL( + MTP_accountDaysTTL(MTP_int(days)) + )).done([=](const MTPBool &result) { + _requestId = 0; + }).fail([=](const RPCError &result) { + _requestId = 0; + }).send(); + _days = days; +} + +} // namespace Api diff --git a/Telegram/SourceFiles/api/api_self_destruct.h b/Telegram/SourceFiles/api/api_self_destruct.h new file mode 100644 index 000000000..d9534a423 --- /dev/null +++ b/Telegram/SourceFiles/api/api_self_destruct.h @@ -0,0 +1,32 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "mtproto/sender.h" + +class ApiWrap; + +namespace Api { + +class SelfDestruct final { +public: + explicit SelfDestruct(not_null api); + + void reload(); + void update(int days); + + rpl::producer days() const; + +private: + MTP::Sender _api; + mtpRequestId _requestId = 0; + rpl::variable _days = 0; + +}; + +} // namespace Api diff --git a/Telegram/SourceFiles/api/api_sensitive_content.cpp b/Telegram/SourceFiles/api/api_sensitive_content.cpp new file mode 100644 index 000000000..0a5c4f739 --- /dev/null +++ b/Telegram/SourceFiles/api/api_sensitive_content.cpp @@ -0,0 +1,62 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "api/api_sensitive_content.h" + +#include "apiwrap.h" + +namespace Api { + +SensitiveContent::SensitiveContent(not_null api) +: _api(api->instance()) { +} + +void SensitiveContent::reload() { + if (_requestId) { + return; + } + _requestId = _api.request(MTPaccount_GetContentSettings( + )).done([=](const MTPaccount_ContentSettings &result) { + _requestId = 0; + result.match([&](const MTPDaccount_contentSettings &data) { + _enabled = data.is_sensitive_enabled(); + _canChange = data.is_sensitive_can_change(); + }); + }).fail([=](const RPCError &error) { + _requestId = 0; + }).send(); +} + +bool SensitiveContent::enabledCurrent() const { + return _enabled.current(); +} + +rpl::producer SensitiveContent::enabled() const { + return _enabled.value(); +} + +rpl::producer SensitiveContent::canChange() const { + return _canChange.value(); +} + +void SensitiveContent::update(bool enabled) { + if (!_canChange.current()) { + return; + } + using Flag = MTPaccount_SetContentSettings::Flag; + _api.request(_requestId).cancel(); + _requestId = _api.request(MTPaccount_SetContentSettings( + MTP_flags(enabled ? Flag::f_sensitive_enabled : Flag(0)) + )).done([=](const MTPBool &result) { + _requestId = 0; + }).fail([=](const RPCError &error) { + _requestId = 0; + }).send(); + _enabled = enabled; +} + +} // namespace Api diff --git a/Telegram/SourceFiles/api/api_sensitive_content.h b/Telegram/SourceFiles/api/api_sensitive_content.h new file mode 100644 index 000000000..7c9e9d85c --- /dev/null +++ b/Telegram/SourceFiles/api/api_sensitive_content.h @@ -0,0 +1,35 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "mtproto/sender.h" + +class ApiWrap; + +namespace Api { + +class SensitiveContent final { +public: + explicit SensitiveContent(not_null api); + + void reload(); + void update(bool enabled); + + [[nodiscard]] bool enabledCurrent() const; + [[nodiscard]] rpl::producer enabled() const; + [[nodiscard]] rpl::producer canChange() const; + +private: + MTP::Sender _api; + mtpRequestId _requestId = 0; + rpl::variable _enabled = false; + rpl::variable _canChange = false; + +}; + +} // namespace Api diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index ee33614e2..64a4432f1 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "api/api_text_entities.h" +#include "api/api_self_destruct.h" +#include "api/api_sensitive_content.h" #include "data/data_drafts.h" #include "data/data_photo.h" #include "data/data_web_page.h" @@ -233,7 +235,9 @@ ApiWrap::ApiWrap(not_null session) , _fileLoader(std::make_unique(kFileLoaderQueueStopTimeout)) //, _feedReadTimer([=] { readFeeds(); }) // #feed , _proxyPromotionTimer([=] { refreshProxyPromotion(); }) -, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); }) { +, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); }) +, _selfDestruct(std::make_unique(this)) +, _sensitiveContent(std::make_unique(this)) { crl::on_main([=] { // You can't use _session->lifetime() in the constructor, // only queued, because it is not constructed yet. @@ -246,6 +250,8 @@ ApiWrap::ApiWrap(not_null session) }); } +ApiWrap::~ApiWrap() = default; + Main::Session &ApiWrap::session() const { return *_session; } @@ -5800,42 +5806,12 @@ auto ApiWrap::blockedUsersSlice() -> rpl::producer { : (_blockedUsersChanges.events() | rpl::type_erased()); } -void ApiWrap::reloadSelfDestruct() { - if (_selfDestructRequestId) { - return; - } - _selfDestructRequestId = request(MTPaccount_GetAccountTTL( - )).done([=](const MTPAccountDaysTTL &result) { - _selfDestructRequestId = 0; - result.match([&](const MTPDaccountDaysTTL &data) { - setSelfDestructDays(data.vdays().v); - }); - }).fail([=](const RPCError &error) { - _selfDestructRequestId = 0; - }).send(); +Api::SelfDestruct &ApiWrap::selfDestruct() { + return *_selfDestruct; } -rpl::producer ApiWrap::selfDestructValue() const { - return _selfDestructDays - ? _selfDestructChanges.events_starting_with_copy(*_selfDestructDays) - : (_selfDestructChanges.events() | rpl::type_erased()); -} - -void ApiWrap::saveSelfDestruct(int days) { - request(_selfDestructRequestId).cancel(); - _selfDestructRequestId = request(MTPaccount_SetAccountTTL( - MTP_accountDaysTTL(MTP_int(days)) - )).done([=](const MTPBool &result) { - _selfDestructRequestId = 0; - }).fail([=](const RPCError &result) { - _selfDestructRequestId = 0; - }).send(); - setSelfDestructDays(days); -} - -void ApiWrap::setSelfDestructDays(int days) { - _selfDestructDays = days; - _selfDestructChanges.fire_copy(days); +Api::SensitiveContent &ApiWrap::sensitiveContent() { + return *_sensitiveContent; } void ApiWrap::createPoll( @@ -6107,5 +6083,3 @@ void ApiWrap::sendReadRequest(not_null peer, MsgId upTo) { }(); _readRequests.emplace(peer, requestId, upTo); } - -ApiWrap::~ApiWrap() = default; diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 7ac173793..0a57a619b 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -83,6 +83,9 @@ QString RequestKey(Types &&...values) { return result; } +class SelfDestruct; +class SensitiveContent; + } // namespace Api class ApiWrap : public MTP::Sender, private base::Subscriber { @@ -131,6 +134,7 @@ public: }; explicit ApiWrap(not_null session); + ~ApiWrap(); Main::Session &session() const; @@ -465,9 +469,8 @@ public: void reloadBlockedUsers(); rpl::producer blockedUsersSlice(); - void reloadSelfDestruct(); - rpl::producer selfDestructValue() const; - void saveSelfDestruct(int days); + [[nodiscard]] Api::SelfDestruct &selfDestruct(); + [[nodiscard]] Api::SensitiveContent &sensitiveContent(); void createPoll( const PollData &data, @@ -480,8 +483,6 @@ public: void closePoll(not_null item); void reloadPollResults(not_null item); - ~ApiWrap(); - private: struct MessageDataRequest { using Callbacks = QList; @@ -679,8 +680,6 @@ private: const QVector &rules); void updatePrivacyLastSeens(const QVector &rules); - void setSelfDestructDays(int days); - void migrateDone( not_null peer, not_null channel); @@ -874,9 +873,8 @@ private: std::optional _blockedUsersSlice; rpl::event_stream _blockedUsersChanges; - mtpRequestId _selfDestructRequestId = 0; - std::optional _selfDestructDays; - rpl::event_stream _selfDestructChanges; + const std::unique_ptr _selfDestruct; + const std::unique_ptr _sensitiveContent; base::flat_map _pollVotesRequestIds; base::flat_map _pollCloseRequestIds; diff --git a/Telegram/SourceFiles/boxes/self_destruction_box.cpp b/Telegram/SourceFiles/boxes/self_destruction_box.cpp index 79b5cf517..acc9e2427 100644 --- a/Telegram/SourceFiles/boxes/self_destruction_box.cpp +++ b/Telegram/SourceFiles/boxes/self_destruction_box.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" #include "apiwrap.h" +#include "api/api_self_destruct.h" #include "main/main_session.h" #include "styles/style_layers.h" #include "styles/style_boxes.h" @@ -76,7 +77,7 @@ void SelfDestructionBox::showContent() { clearButtons(); addButton(tr::lng_settings_save(), [=] { - _session->api().saveSelfDestruct(_ttlGroup->value()); + _session->api().selfDestruct().update(_ttlGroup->value()); closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); }); diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index b2f6f99f4..d954034ad 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "settings/settings_privacy_security.h" +#include "api/api_self_destruct.h" +#include "api/api_sensitive_content.h" #include "settings/settings_common.h" #include "settings/settings_privacy_controllers.h" #include "boxes/peer_list_box.h" @@ -428,20 +430,56 @@ void SetupCloudPassword( session->api().reloadPasswordState(); AddSkip(container); + AddDivider(container); +} + +void SetupSensitiveContent( + not_null controller, + not_null container) { + using namespace rpl::mappers; + + const auto wrap = container->add( + object_ptr>( + container, + object_ptr(container))); + const auto inner = wrap->entity(); + + AddSkip(inner); + AddSubsectionTitle(inner, tr::lng_settings_sensitive_title()); + + const auto session = &controller->session(); + + session->api().sensitiveContent().reload(); + AddButton( + inner, + tr::lng_settings_sensitive_disable_filtering(), + st::settingsButton + )->toggleOn( + session->api().sensitiveContent().enabled() + )->toggledChanges( + ) | rpl::filter([=](bool toggled) { + return toggled != session->api().sensitiveContent().enabledCurrent(); + }) | rpl::start_with_next([=](bool toggled) { + session->api().sensitiveContent().update(toggled); + }, container->lifetime()); + + AddSkip(inner); + AddDividerText(inner, tr::lng_settings_sensitive_about()); + + wrap->toggleOn(session->api().sensitiveContent().canChange()); } void SetupSelfDestruction( not_null controller, not_null container) { - AddDivider(container); AddSkip(container); AddSubsectionTitle(container, tr::lng_settings_destroy_title()); const auto session = &controller->session(); - session->api().reloadSelfDestruct(); + session->api().selfDestruct().reload(); const auto label = [&] { - return session->api().selfDestructValue( + return session->api().selfDestruct().days( ) | rpl::map( SelfDestructionBox::DaysLabel ); @@ -455,7 +493,7 @@ void SetupSelfDestruction( )->addClickHandler([=] { Ui::show(Box( session, - session->api().selfDestructValue())); + session->api().selfDestruct().days())); }); AddSkip(container); @@ -609,6 +647,11 @@ void PrivacySecurity::setupContent( SetupSessionsList(controller, content); SetupLocalPasscode(controller, content); SetupCloudPassword(controller, content); +#if !defined OS_MAC_STORE && !defined OS_WIN_STORE + SetupSensitiveContent(controller, content); +#else // !OS_MAC_STORE && !OS_WIN_STORE + AddDivider(content); +#endif // !OS_MAC_STORE && !OS_WIN_STORE SetupSelfDestruction(controller, content); Ui::ResizeFitChild(this, content); diff --git a/Telegram/cmake/lib_scheme.cmake b/Telegram/cmake/lib_scheme.cmake index 0689e9cd6..81777adf4 100644 --- a/Telegram/cmake/lib_scheme.cmake +++ b/Telegram/cmake/lib_scheme.cmake @@ -17,6 +17,12 @@ set(scheme_files generate_scheme(lib_scheme ${src_loc}/codegen/scheme/codegen_scheme.py "${scheme_files}") +nice_target_sources(lib_scheme ${res_loc} +PRIVATE + tl/mtproto.tl + tl/api.tl +) + target_include_directories(lib_scheme PUBLIC ${src_loc}