diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 641c740377..ebbed9f424 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2933,6 +2933,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_view_button_message" = "View message"; "lng_view_button_voice_chat" = "Voice chat"; "lng_view_button_voice_chat_channel" = "Live stream"; +"lng_view_button_request_join" = "Request to Join"; "lng_sponsored_title" = "What are sponsored messages?"; "lng_sponsored_info_description1" = "Unlike other apps, Telegram never uses your private data to target ads. Sponsored messages on Telegram are based solely on the topic of the public channels in which they are shown. This means that no user data is mined or analyzed to display ads, and every user viewing a channel on Telegram sees the same sponsored messages.\n\nUnlike other apps, Telegram doesn't track whether you tapped on a sponsored message and doesn't profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties can’t spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that.\n\nTelegram offers a free and unlimited service to hundreds of millions of users, which involves significant server and traffic costs. In order to remain independent and stay true to its values, Telegram developed a paid tool to promote messages with user privacy in mind. We welcome responsible advertisers at:"; diff --git a/Telegram/SourceFiles/api/api_chat_invite.cpp b/Telegram/SourceFiles/api/api_chat_invite.cpp index 566d49538e..f96b387d34 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.cpp +++ b/Telegram/SourceFiles/api/api_chat_invite.cpp @@ -38,11 +38,12 @@ void CheckChatInvite( if (!strongController) { return; } + const auto isGroup = !data.is_broadcast(); const auto box = strongController->show(Box( session, data, invitePeekChannel, - [=] { session->api().importChatInvite(hash); })); + [=] { session->api().importChatInvite(hash, isGroup); })); if (invitePeekChannel) { box->boxClosing( ) | rpl::filter([=] { @@ -104,7 +105,8 @@ ConfirmInviteBox::ConfirmInviteBox( , _title(this, st::confirmInviteTitle) , _status(this, st::confirmInviteStatus) , _participants(GetParticipants(_session, data)) -, _isChannel(data.is_channel() && !data.is_megagroup()) { +, _isChannel(data.is_channel() && !data.is_megagroup()) +, _requestApprove(data.is_request_needed()) { const auto title = qs(data.vtitle()); const auto count = data.vparticipants_count().v; const auto status = [&] { @@ -166,7 +168,9 @@ auto ConfirmInviteBox::GetParticipants( void ConfirmInviteBox::prepare() { addButton( - (_isChannel + (_requestApprove + ? tr::lng_group_request_to_join() + : _isChannel ? tr::lng_profile_join_channel() : tr::lng_profile_join_group()), _submit); diff --git a/Telegram/SourceFiles/api/api_chat_invite.h b/Telegram/SourceFiles/api/api_chat_invite.h index de59651309..46a4ad8c5c 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.h +++ b/Telegram/SourceFiles/api/api_chat_invite.h @@ -72,6 +72,7 @@ private: std::unique_ptr _photoEmpty; std::vector _participants; bool _isChannel = false; + bool _requestApprove = false; int _userWidth = 0; diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index eed3d963e2..eebb2895f7 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -239,11 +239,12 @@ Updates::Updates(not_null session) }).send(); using namespace rpl::mappers; - base::ObservableViewer( - api().fullPeerUpdated() - ) | rpl::filter([](not_null peer) { - return peer->isChat() || peer->isMegagroup(); - }) | rpl::start_with_next([=](not_null peer) { + session->changes().peerUpdates( + Data::PeerUpdate::Flag::FullInfo + ) | rpl::filter([](const Data::PeerUpdate &update) { + return update.peer->isChat() || update.peer->isMegagroup(); + }) | rpl::start_with_next([=](const Data::PeerUpdate &update) { + const auto peer = update.peer; if (const auto list = _pendingSpeakingCallParticipants.take(peer)) { if (const auto call = peer->groupCall()) { for (const auto &[participantPeerId, when] : *list) { diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 7511b60efe..2575fc8dc3 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -74,6 +74,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/item_text_options.h" #include "ui/emoji_config.h" #include "ui/chat/attach/attach_prepare.h" +#include "ui/toasts/common_toasts.h" #include "support/support_helper.h" #include "storage/localimageloader.h" #include "storage/download_manager_mtproto.h" @@ -114,6 +115,7 @@ constexpr auto kStickersByEmojiInvalidateTimeout = crl::time(6 * 1000); constexpr auto kNotifySettingSaveTimeout = crl::time(1000); constexpr auto kDialogsFirstLoad = 20; constexpr auto kDialogsPerPage = 500; +constexpr auto kJoinErrorDuration = 5 * crl::time(1000); using PhotoFileLocationId = Data::PhotoFileLocationId; using DocumentFileLocationId = Data::DocumentFileLocationId; @@ -354,7 +356,7 @@ void ApiWrap::checkChatInvite( )).done(std::move(done)).fail(std::move(fail)).send(); } -void ApiWrap::importChatInvite(const QString &hash) { +void ApiWrap::importChatInvite(const QString &hash, bool isGroup) { request(MTPmessages_ImportChatInvite( MTP_string(hash) )).done([=](const MTPUpdates &result) { @@ -391,13 +393,20 @@ void ApiWrap::importChatInvite(const QString &hash) { }); }).fail([=](const MTP::Error &error) { const auto &type = error.type(); - if (type == qstr("CHANNELS_TOO_MUCH")) { - Ui::show(Box(tr::lng_join_channel_error(tr::now))); - } else if (error.code() == 400) { - Ui::show(Box((type == qstr("USERS_TOO_MUCH")) - ? tr::lng_group_invite_no_room(tr::now) - : tr::lng_group_invite_bad_link(tr::now))); - } + Ui::hideLayer(); + Ui::ShowMultilineToast({ .text = { [&] { + if (type == qstr("INVITE_REQUEST_SENT")) { + return isGroup + ? tr::lng_group_request_sent(tr::now) + : tr::lng_group_request_sent_channel(tr::now); + } else if (type == qstr("CHANNELS_TOO_MUCH")) { + return tr::lng_join_channel_error(tr::now); + } else if (type == qstr("USERS_TOO_MUCH")) { + return tr::lng_group_invite_no_room(tr::now); + } else { + return tr::lng_group_invite_bad_link(tr::now); + } + }() }, .duration = kJoinErrorDuration }); }).send(); } @@ -1096,7 +1105,9 @@ void ApiWrap::gotChatFull( _fullPeerRequests.erase(i); } } - fullPeerUpdated().notify(peer); + _session->changes().peerUpdated( + peer, + Data::PeerUpdate::Flag::FullInfo); } void ApiWrap::gotUserFull( @@ -1119,7 +1130,9 @@ void ApiWrap::gotUserFull( _fullPeerRequests.erase(i); } } - fullPeerUpdated().notify(user); + _session->changes().peerUpdated( + user, + Data::PeerUpdate::Flag::FullInfo); } void ApiWrap::requestPeer(not_null peer) { @@ -1544,7 +1557,9 @@ void ApiWrap::applyLastParticipantsList( (Data::PeerUpdate::Flag::Members | Data::PeerUpdate::Flag::Admins)); channel->mgInfo->botStatus = botStatus; - fullPeerUpdated().notify(channel); + _session->changes().peerUpdated( + channel, + Data::PeerUpdate::Flag::FullInfo); } void ApiWrap::applyBotsList( @@ -1593,7 +1608,9 @@ void ApiWrap::applyBotsList( } channel->mgInfo->botStatus = botStatus; - fullPeerUpdated().notify(channel); + _session->changes().peerUpdated( + channel, + Data::PeerUpdate::Flag::FullInfo); } void ApiWrap::requestSelfParticipant(not_null channel) { @@ -2078,20 +2095,35 @@ void ApiWrap::joinChannel(not_null channel) { _channelAmInRequests.remove(channel); applyUpdates(result); }).fail([=](const MTP::Error &error) { - if (error.type() == qstr("CHANNEL_PRIVATE") + const auto &type = error.type(); + if (type == qstr("CHANNEL_PRIVATE") && channel->invitePeekExpires()) { channel->privateErrorReceived(); - } else if (error.type() == qstr("CHANNEL_PRIVATE") - || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") - || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { - Ui::show(Box(channel->isMegagroup() - ? tr::lng_group_not_accessible(tr::now) - : tr::lng_channel_not_accessible(tr::now))); - } else if (error.type() == qstr("CHANNELS_TOO_MUCH")) { - Ui::show(Box( - tr::lng_join_channel_error(tr::now))); - } else if (error.type() == qstr("USERS_TOO_MUCH")) { - Ui::show(Box(tr::lng_group_full(tr::now))); + } else { + const auto text = [&] { + if (type == qstr("INVITE_REQUEST_SENT")) { + return channel->isMegagroup() + ? tr::lng_group_request_sent(tr::now) + : tr::lng_group_request_sent_channel(tr::now); + } else if (type == qstr("CHANNEL_PRIVATE") + || type == qstr("CHANNEL_PUBLIC_GROUP_NA") + || type == qstr("USER_BANNED_IN_CHANNEL")) { + return channel->isMegagroup() + ? tr::lng_group_not_accessible(tr::now) + : tr::lng_channel_not_accessible(tr::now); + } else if (type == qstr("CHANNELS_TOO_MUCH")) { + return tr::lng_join_channel_error(tr::now); + } else if (type == qstr("USERS_TOO_MUCH")) { + return tr::lng_group_full(tr::now); + } + return QString(); + }(); + if (!text.isEmpty()) { + Ui::ShowMultilineToast({ + .text = { text }, + .duration = kJoinErrorDuration, + }); + } } _channelAmInRequests.remove(channel); }).send(); @@ -2194,7 +2226,7 @@ void ApiWrap::saveDraftToCloudDelayed(not_null history) { void ApiWrap::updatePrivacyLastSeens() { const auto now = base::unixtime::now(); _session->data().enumerateUsers([&](UserData *user) { - if (user->isSelf() || !user->isFullLoaded()) { + if (user->isSelf() || !user->isLoaded()) { return; } if (user->onlineTill <= 0) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index ce7fea1950..461d1327b9 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -202,7 +202,7 @@ public: const QString &hash, FnMut done, Fn fail); - void importChatInvite(const QString &hash); + void importChatInvite(const QString &hash, bool isGroup); void requestChannelMembersForAdd( not_null channel, @@ -270,10 +270,6 @@ public: void clearHistory(not_null peer, bool revoke); void deleteConversation(not_null peer, bool revoke); - base::Observable &fullPeerUpdated() { - return _fullPeerUpdated; - } - bool isQuitPrevent(); void jumpToDate(Dialogs::Key chat, const QDate &date); @@ -663,8 +659,6 @@ private: std::unique_ptr _fileLoader; base::flat_map> _sendingAlbums; - base::Observable _fullPeerUpdated; - mtpRequestId _topPromotionRequestId = 0; std::pair _topPromotionKey; TimeId _topPromotionNextRequestTime = TimeId(0); diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp index e494c397e2..09d4df8ab7 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp @@ -746,6 +746,7 @@ void GroupInfoBox::createChannel( channel, std::move(image)); } + channel->session().api().requestFullPeer(channel); _createdChannel = channel; checkInviteLink(); }; @@ -772,12 +773,19 @@ void GroupInfoBox::checkInviteLink() { if (!_createdChannel->inviteLink().isEmpty()) { channelReady(); - return; + } else if (_createdChannel->isFullLoaded() && !_creatingInviteLink) { + _creatingInviteLink = true; + _createdChannel->session().api().inviteLinks().create( + _createdChannel, + crl::guard(this, [=](auto&&) { channelReady(); })); + } else { + _createdChannel->session().changes().peerUpdates( + _createdChannel, + Data::PeerUpdate::Flag::FullInfo + ) | rpl::take(1) | rpl::start_with_next([=] { + checkInviteLink(); + }, lifetime()); } - _creatingInviteLink = true; - _createdChannel->session().api().inviteLinks().create( - _createdChannel, - crl::guard(this, [=](auto&&) { channelReady(); })); } void GroupInfoBox::channelReady() { @@ -871,6 +879,10 @@ SetupChannelBox::SetupChannelBox( void SetupChannelBox::prepare() { _aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth); + if (_channel->inviteLink().isEmpty()) { + _channel->session().api().requestFullPeer(_channel); + } + setMouseTracking(true); _checkRequestId = _api.request(MTPchannels_CheckUsername( @@ -1068,13 +1080,14 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) { } void SetupChannelBox::mousePressEvent(QMouseEvent *e) { - if (_linkOver) { - if (_channel->inviteLink().isEmpty()) { - _channel->session().api().inviteLinks().create(_channel); - } else { - QGuiApplication::clipboard()->setText(_channel->inviteLink()); - Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now)); - } + if (!_linkOver) { + return; + } else if (!_channel->inviteLink().isEmpty()) { + QGuiApplication::clipboard()->setText(_channel->inviteLink()); + Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now)); + } else if (_channel->isFullLoaded() && !_creatingInviteLink) { + _creatingInviteLink = true; + _channel->session().api().inviteLinks().create(_channel); } } diff --git a/Telegram/SourceFiles/boxes/add_contact_box.h b/Telegram/SourceFiles/boxes/add_contact_box.h index d70adf7fc5..0f2d884cc9 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.h +++ b/Telegram/SourceFiles/boxes/add_contact_box.h @@ -191,6 +191,7 @@ private: MTP::Sender _api; bool _existing = false; + bool _creatingInviteLink = false; std::shared_ptr> _privacyGroup; object_ptr> _public; diff --git a/Telegram/SourceFiles/boxes/max_invite_box.cpp b/Telegram/SourceFiles/boxes/max_invite_box.cpp index 190a5e8927..1ecd59128b 100644 --- a/Telegram/SourceFiles/boxes/max_invite_box.cpp +++ b/Telegram/SourceFiles/boxes/max_invite_box.cpp @@ -71,6 +71,9 @@ void MaxInviteBox::prepare() { + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom()); + if (_channel->inviteLink().isEmpty()) { + _channel->session().api().requestFullPeer(_channel); + } _channel->session().changes().peerUpdates( _channel, Data::PeerUpdate::Flag::InviteLinks @@ -86,11 +89,12 @@ void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) { void MaxInviteBox::mousePressEvent(QMouseEvent *e) { mouseMoveEvent(e); if (_linkOver) { - if (_channel->inviteLink().isEmpty()) { - _channel->session().api().inviteLinks().create(_channel); - } else { + if (!_channel->inviteLink().isEmpty()) { QGuiApplication::clipboard()->setText(_channel->inviteLink()); Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now)); + } else if (_channel->isFullLoaded() && !_creatingInviteLink) { + _creatingInviteLink = true; + _channel->session().api().inviteLinks().create(_channel); } } } diff --git a/Telegram/SourceFiles/boxes/max_invite_box.h b/Telegram/SourceFiles/boxes/max_invite_box.h index 0bc9a5f691..f4087ff0ef 100644 --- a/Telegram/SourceFiles/boxes/max_invite_box.h +++ b/Telegram/SourceFiles/boxes/max_invite_box.h @@ -32,6 +32,7 @@ private: QRect _invitationLink; bool _linkOver = false; + bool _creatingInviteLink = false; QPoint _lastMousePos; diff --git a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp index cf75393ae0..8a9ed54091 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "data/data_channel.h" #include "data/data_chat.h" +#include "data/data_changes.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "ui/wrap/vertical_layout.h" @@ -63,12 +64,12 @@ Controller::Controller( , _chat(chat) , _chats(std::move(chats)) , _callback(std::move(callback)) { - base::ObservableViewer( - channel->session().api().fullPeerUpdated() - ) | rpl::start_with_next([=](PeerData *peer) { - if (peer == _waitForFull) { - choose(std::exchange(_waitForFull, nullptr)); - } + channel->session().changes().peerUpdates( + Data::PeerUpdate::Flag::FullInfo + ) | rpl::filter([=](const Data::PeerUpdate &update) { + return (update.peer == _waitForFull); + }) | rpl::start_with_next([=](const Data::PeerUpdate &update) { + choose(std::exchange(_waitForFull, nullptr)); }, lifetime()); } diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp index e72060af48..84eb11e7fe 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp @@ -518,7 +518,7 @@ void Controller::loadMoreRows() { MTP_flags(0), _peer->input, MTP_string(_link), - MTPstring(), // q // #TODO requests + MTPstring(), // q MTP_int(_lastUser ? _lastUser->date : 0), _lastUser ? _lastUser->user->inputUser : MTP_inputUserEmpty(), MTP_int(_lastUser ? kPerPage : kFirstPage) diff --git a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp index 1a3ffa334f..ce9a89669b 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp @@ -584,7 +584,12 @@ void SettingsBox( } return false; }; - if (!lookupLink().isEmpty() || canCreateLink()) { + const auto alreadyHasLink = !lookupLink().isEmpty(); + if (alreadyHasLink || canCreateLink()) { + if (!alreadyHasLink) { + // Request invite link. + peer->session().api().requestFullPeer(peer); + } const auto copyLink = [=] { const auto link = lookupLink(); if (link.isEmpty()) { diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 9882726a42..49fb728279 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -64,38 +64,39 @@ struct PeerUpdate { ChatThemeEmoji = (1ULL << 7), IsBlocked = (1ULL << 8), MessagesTTL = (1ULL << 9), + FullInfo = (1ULL << 10), // For users - CanShareContact = (1ULL << 10), - IsContact = (1ULL << 11), - PhoneNumber = (1ULL << 12), - OnlineStatus = (1ULL << 13), - BotCommands = (1ULL << 14), - BotCanBeInvited = (1ULL << 15), - BotStartToken = (1ULL << 16), - CommonChats = (1ULL << 17), - HasCalls = (1ULL << 18), - SupportInfo = (1ULL << 19), - IsBot = (1ULL << 20), + CanShareContact = (1ULL << 11), + IsContact = (1ULL << 12), + PhoneNumber = (1ULL << 13), + OnlineStatus = (1ULL << 14), + BotCommands = (1ULL << 15), + BotCanBeInvited = (1ULL << 16), + BotStartToken = (1ULL << 17), + CommonChats = (1ULL << 18), + HasCalls = (1ULL << 19), + SupportInfo = (1ULL << 20), + IsBot = (1ULL << 21), // For chats and channels - InviteLinks = (1ULL << 21), - Members = (1ULL << 22), - Admins = (1ULL << 23), - BannedUsers = (1ULL << 24), - Rights = (1ULL << 25), - PendingRequests = (1ULL << 26), + InviteLinks = (1ULL << 22), + Members = (1ULL << 23), + Admins = (1ULL << 24), + BannedUsers = (1ULL << 25), + Rights = (1ULL << 26), + PendingRequests = (1ULL << 27), // For channels - ChannelAmIn = (1ULL << 27), - StickersSet = (1ULL << 28), - ChannelLinkedChat = (1ULL << 29), - ChannelLocation = (1ULL << 30), - Slowmode = (1ULL << 31), - GroupCall = (1ULL << 32), + ChannelAmIn = (1ULL << 28), + StickersSet = (1ULL << 29), + ChannelLinkedChat = (1ULL << 30), + ChannelLocation = (1ULL << 31), + Slowmode = (1ULL << 32), + GroupCall = (1ULL << 33), // For iteration - LastUsedBit = (1ULL << 32), + LastUsedBit = (1ULL << 33), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; } diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 621892f9cd..e98a4d3c3c 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -643,6 +643,7 @@ void PeerData::updateFullForced() { void PeerData::fullUpdated() { _lastFullUpdate = crl::now(); + setLoadedStatus(LoadedStatus::Full); } UserData *PeerData::asUser() { diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 55d9402004..dd9376214e 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -440,6 +440,7 @@ public: enum class LoadedStatus : char { Not, Minimal, + Normal, Full, }; [[nodiscard]] LoadedStatus loadedStatus() const { @@ -448,6 +449,9 @@ public: [[nodiscard]] bool isMinimalLoaded() const { return (loadedStatus() != LoadedStatus::Not); } + [[nodiscard]] bool isLoaded() const { + return (loadedStatus() == LoadedStatus::Normal) || isFullLoaded(); + } [[nodiscard]] bool isFullLoaded() const { return (loadedStatus() == LoadedStatus::Full); } diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 8bc1b3b123..aa9defaf5b 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -348,7 +348,7 @@ PeerData *Session::peerLoaded(PeerId id) const { const auto i = _peers.find(id); if (i == end(_peers)) { return nullptr; - } else if (!i->second->isFullLoaded()) { + } else if (!i->second->isLoaded()) { return nullptr; } return i->second.get(); @@ -556,9 +556,9 @@ not_null Session::processUser(const MTPUser &data) { if (!result->isMinimalLoaded()) { result->setLoadedStatus(PeerData::LoadedStatus::Minimal); } - } else if (!result->isFullLoaded() + } else if (!result->isLoaded() && (!result->isSelf() || !result->phone().isEmpty())) { - result->setLoadedStatus(PeerData::LoadedStatus::Full); + result->setLoadedStatus(PeerData::LoadedStatus::Normal); } if (status && !minimal) { @@ -680,7 +680,7 @@ not_null Session::processChat(const MTPChat &data) { const auto channel = result->asChannel(); minimal = data.is_min(); - if (minimal && !result->isFullLoaded()) { + if (minimal && !result->isLoaded()) { LOG(("API Warning: not loaded minimal channel applied.")); } @@ -825,8 +825,8 @@ not_null Session::processChat(const MTPChat &data) { if (!result->isMinimalLoaded()) { result->setLoadedStatus(PeerData::LoadedStatus::Minimal); } - } else if (!result->isFullLoaded()) { - result->setLoadedStatus(PeerData::LoadedStatus::Full); + } else if (!result->isLoaded()) { + result->setLoadedStatus(PeerData::LoadedStatus::Normal); } if (flags) { session().changes().peerUpdated(result, flags); @@ -1171,7 +1171,7 @@ void Session::setupUserIsContactViewer() { requestViewResize(view); } } - if (!user->isFullLoaded()) { + if (!user->isLoaded()) { LOG(("API Error: " "userIsContactChanged() called for a not loaded user!")); return; diff --git a/Telegram/SourceFiles/data/data_web_page.cpp b/Telegram/SourceFiles/data/data_web_page.cpp index 62e86688d0..eac5343059 100644 --- a/Telegram/SourceFiles/data/data_web_page.cpp +++ b/Telegram/SourceFiles/data/data_web_page.cpp @@ -149,12 +149,18 @@ WebPageType ParseWebPageType( return WebPageType::Theme; } else if (type == qstr("telegram_channel")) { return WebPageType::Channel; + } else if (type == qstr("telegram_channel_request")) { + return WebPageType::ChannelWithRequest; + } else if (type == qstr("telegram_megagroup") + || type == qstr("telegram_chat")) { + return WebPageType::Group; + } else if (type == qstr("telegram_megagroup_request") + || type == qstr("telegram_chat_request")) { + return WebPageType::GroupWithRequest; } else if (type == qstr("telegram_message")) { return WebPageType::Message; } else if (type == qstr("telegram_bot")) { return WebPageType::Bot; - } else if (type == qstr("telegram_megagroup")) { - return WebPageType::Group; } else if (type == qstr("telegram_voicechat")) { return WebPageType::VoiceChat; } else if (type == qstr("telegram_livestream")) { diff --git a/Telegram/SourceFiles/data/data_web_page.h b/Telegram/SourceFiles/data/data_web_page.h index 3000361d5e..4ed47e513a 100644 --- a/Telegram/SourceFiles/data/data_web_page.h +++ b/Telegram/SourceFiles/data/data_web_page.h @@ -20,7 +20,9 @@ enum class WebPageType { Message, Group, + GroupWithRequest, Channel, + ChannelWithRequest, Photo, Video, diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index d5946e620c..e1d6a2a057 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -651,6 +651,7 @@ HistoryWidget::HistoryWidget( | PeerUpdateFlag::BotStartToken | PeerUpdateFlag::MessagesTTL | PeerUpdateFlag::ChatThemeEmoji + | PeerUpdateFlag::FullInfo ) | rpl::filter([=](const Data::PeerUpdate &update) { return (update.peer.get() == _peer); }) | rpl::map([](const Data::PeerUpdate &update) { @@ -720,6 +721,9 @@ HistoryWidget::HistoryWidget( }, _list->lifetime()); } } + if (flags & PeerUpdateFlag::FullInfo) { + fullInfoUpdated(); + } }, lifetime()); rpl::merge( @@ -1264,9 +1268,6 @@ void HistoryWidget::start() { updateStickersByEmoji(); }, lifetime()); session().data().stickers().notifySavedGifsUpdated(); - subscribe(session().api().fullPeerUpdated(), [this](PeerData *peer) { - fullPeerUpdated(peer); - }); } void HistoryWidget::insertMention(UserData *user) { @@ -6585,9 +6586,9 @@ void HistoryWidget::updatePreview() { update(); } -void HistoryWidget::fullPeerUpdated(PeerData *peer) { +void HistoryWidget::fullInfoUpdated() { auto refresh = false; - if (_list && peer == _peer) { + if (_list) { auto newCanSendMessages = _peer->canWrite(); if (newCanSendMessages != _canSendMessages) { _canSendMessages = newCanSendMessages; diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index c8d70ca776..94c8476ef0 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -381,7 +381,7 @@ private: [[nodiscard]] SendMenu::Type sendMenuType() const; [[nodiscard]] SendMenu::Type sendButtonMenuType() const; void handlePendingHistoryUpdate(); - void fullPeerUpdated(PeerData *peer); + void fullInfoUpdated(); void toggleTabbedSelectorMode(); void recountChatWidth(); void historyDownClicked(); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 646c19e43e..3ac7694160 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -2272,6 +2272,7 @@ void ComposeControls::initWebpageProcess() { Data::PeerUpdate::Flag::Rights | Data::PeerUpdate::Flag::Notifications | Data::PeerUpdate::Flag::MessagesTTL + | Data::PeerUpdate::Flag::FullInfo ) | rpl::filter([=](const Data::PeerUpdate &update) { return (update.peer.get() == peer); }) | rpl::map([](const Data::PeerUpdate &update) { @@ -2288,16 +2289,11 @@ void ComposeControls::initWebpageProcess() { if (flags & Data::PeerUpdate::Flag::MessagesTTL) { updateMessagesTTLShown(); } - }, lifetime); - - base::ObservableViewer( - session().api().fullPeerUpdated() - ) | rpl::filter([=](PeerData *peer) { - return _history && (_history->peer == peer); - }) | rpl::start_with_next([=] { - if (updateBotCommandShown()) { - updateControlsVisibility(); - updateControlsGeometry(_wrap->size()); + if (flags & Data::PeerUpdate::Flag::FullInfo) { + if (updateBotCommandShown()) { + updateControlsVisibility(); + updateControlsGeometry(_wrap->size()); + } } }, lifetime); diff --git a/Telegram/SourceFiles/history/view/history_view_view_button.cpp b/Telegram/SourceFiles/history/view/history_view_view_button.cpp index 46ad5ddfca..3fecbac6ba 100644 --- a/Telegram/SourceFiles/history/view/history_view_view_button.cpp +++ b/Telegram/SourceFiles/history/view/history_view_view_button.cpp @@ -57,6 +57,9 @@ inline auto WebPageToPhrase(not_null webpage) { ? tr::lng_view_button_background(tr::now) : (type == WebPageType::Channel) ? tr::lng_view_button_channel(tr::now) + : (type == WebPageType::GroupWithRequest + || type == WebPageType::ChannelWithRequest) + ? tr::lng_view_button_request_join(tr::now) : (type == WebPageType::VoiceChat) ? tr::lng_view_button_voice_chat(tr::now) : (type == WebPageType::Livestream) diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp index 99e02e2aa4..bdd5b40bb6 100644 --- a/Telegram/SourceFiles/main/main_session.cpp +++ b/Telegram/SourceFiles/main/main_session.cpp @@ -69,13 +69,13 @@ Session::Session( std::unique_ptr settings) : _account(account) , _settings(std::move(settings)) +, _changes(std::make_unique(this)) , _api(std::make_unique(this)) , _updates(std::make_unique(this)) , _sendProgressManager(std::make_unique(this)) , _downloader(std::make_unique(_api.get())) , _uploader(std::make_unique(_api.get())) , _storage(std::make_unique()) -, _changes(std::make_unique(this)) , _data(std::make_unique(this)) , _user(_data->processUser(user)) , _emojiStickersPack(std::make_unique(this)) diff --git a/Telegram/SourceFiles/main/main_session.h b/Telegram/SourceFiles/main/main_session.h index 60a641584f..01142396a5 100644 --- a/Telegram/SourceFiles/main/main_session.h +++ b/Telegram/SourceFiles/main/main_session.h @@ -83,6 +83,9 @@ public: } bool validateSelf(const MTPUser &user); + [[nodiscard]] Data::Changes &changes() const { + return *_changes; + } [[nodiscard]] Api::Updates &updates() const { return *_updates; } @@ -104,9 +107,6 @@ public: [[nodiscard]] Stickers::DicePacks &diceStickersPacks() const { return *_diceStickersPacks; } - [[nodiscard]] Data::Changes &changes() const { - return *_changes; - } [[nodiscard]] Data::Session &data() const { return *_data; } @@ -165,6 +165,7 @@ private: const not_null _account; const std::unique_ptr _settings; + const std::unique_ptr _changes; const std::unique_ptr _api; const std::unique_ptr _updates; const std::unique_ptr _sendProgressManager; @@ -173,7 +174,6 @@ private: const std::unique_ptr _storage; // _data depends on _downloader / _uploader. - const std::unique_ptr _changes; const std::unique_ptr _data; const not_null _user; diff --git a/Telegram/SourceFiles/storage/serialize_peer.cpp b/Telegram/SourceFiles/storage/serialize_peer.cpp index 9e80fe0437..9b6c4b4c98 100644 --- a/Telegram/SourceFiles/storage/serialize_peer.cpp +++ b/Telegram/SourceFiles/storage/serialize_peer.cpp @@ -206,10 +206,10 @@ PeerData *readPeer( const auto loaded = (peerId == selfId) ? session->user().get() : session->data().peerLoaded(peerId); - const auto apply = !loaded || !loaded->isFullLoaded(); + const auto apply = !loaded || !loaded->isLoaded(); const auto result = loaded ? loaded : session->data().peer(peerId).get(); if (apply) { - result->setLoadedStatus(PeerData::LoadedStatus::Full); + result->setLoadedStatus(PeerData::LoadedStatus::Normal); } if (const auto user = result->asUser()) { QString first, last, phone, username, inlinePlaceholder; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 8f69fb0e92..f4237d31f8 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -553,13 +553,12 @@ SessionController::SessionController( enableGifPauseReason(GifPauseReason::RoundPlaying); } - base::ObservableViewer( - session->api().fullPeerUpdated() - ) | rpl::start_with_next([=](PeerData *peer) { - if (peer == _showEditPeer) { - _showEditPeer = nullptr; - show(Box(this, peer)); - } + session->changes().peerUpdates( + Data::PeerUpdate::Flag::FullInfo + ) | rpl::filter([=](const Data::PeerUpdate &update) { + return (update.peer == _showEditPeer); + }) | rpl::start_with_next([=] { + show(Box(this, base::take(_showEditPeer))); }, lifetime()); session->data().chatsListChanges(