diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4a0619410..5f9aeed40 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2759,6 +2759,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_payments_terms_title" = "Terms of Service"; "lng_payments_terms_text" = "Subscribe and accept terms of service of {bot}?"; +"lng_payments_terms_text_once" = "Are you accepting terms of service of {bot}?"; "lng_payments_terms_agree" = "I agree to {link}"; "lng_payments_terms_link" = "Terms of Service"; "lng_payments_terms_accept" = "Accept"; @@ -3091,9 +3092,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gigagroup_suggest_more" = "Learn more"; "lng_rights_channel_info" = "Change channel info"; +"lng_rights_channel_manage" = "Manage messages"; "lng_rights_channel_post" = "Post messages"; "lng_rights_channel_edit" = "Edit messages of others"; "lng_rights_channel_delete" = "Delete messages of others"; +"lng_rights_channel_manage_stories" = "Manage stories"; +"lng_rights_channel_post_stories" = "Post stories"; +"lng_rights_channel_edit_stories" = "Edit stories of others"; +"lng_rights_channel_delete_stories" = "Delete stories of others"; "lng_rights_channel_manage_calls" = "Manage live streams"; "lng_rights_group_info" = "Change group info"; "lng_rights_group_ban" = "Ban users"; @@ -3352,6 +3358,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_admin_log_admin_post_messages" = "Post messages"; "lng_admin_log_admin_edit_messages" = "Edit messages"; "lng_admin_log_admin_delete_messages" = "Delete messages"; +"lng_admin_log_admin_post_stories" = "Post stories"; +"lng_admin_log_admin_edit_stories" = "Edit stories"; +"lng_admin_log_admin_delete_stories" = "Delete stories"; "lng_admin_log_admin_remain_anonymous" = "Remain anonymous"; "lng_admin_log_admin_ban_users" = "Ban users"; "lng_admin_log_admin_invite_users" = "Add members"; diff --git a/Telegram/SourceFiles/api/api_report.cpp b/Telegram/SourceFiles/api/api_report.cpp index 501870180..869152737 100644 --- a/Telegram/SourceFiles/api/api_report.cpp +++ b/Telegram/SourceFiles/api/api_report.cpp @@ -78,12 +78,8 @@ void SendReport( MTP_string(comment) )).done(std::move(done)).send(); }, [&](StoryId id) { - const auto user = peer->asUser(); - if (!user) { - return; - } peer->session().api().request(MTPstories_Report( - user->inputUser, + peer->input, MTP_vector(1, MTP_int(id)), ReasonToTL(reason), MTP_string(comment) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index aa83e5f8d..75f4047b3 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -789,7 +789,7 @@ QString ApiWrap::exportDirectStoryLink(not_null story) { ? i->second : fallback(); request(MTPstories_ExportStoryLink( - story->peer()->asUser()->inputUser, + story->peer()->input, MTP_int(story->id()) )).done([=](const MTPExportedStoryLink &result) { const auto link = qs(result.data().vlink()); @@ -2533,14 +2533,9 @@ void ApiWrap::refreshFileReference( }, [&](Data::FileOriginPremiumPreviews data) { request(MTPhelp_GetPremiumPromo()); }, [&](Data::FileOriginStory data) { - const auto user = _session->data().peer(data.peerId)->asUser(); - if (user) { - request(MTPstories_GetStoriesByID( - user->inputUser, - MTP_vector(1, MTP_int(data.storyId)))); - } else { - fail(); - } + request(MTPstories_GetStoriesByID( + _session->data().peer(data.peerId)->input, + MTP_vector(1, MTP_int(data.storyId)))); }, [&](v::null_t) { fail(); }); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index 97a86be3b..755368192 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -51,13 +51,14 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000); } [[nodiscard]] auto NestedRestrictionLabelsList( - Data::RestrictionsSetOptions options) { + Data::RestrictionsSetOptions options) +-> std::vector> { using Flag = ChatRestriction; auto first = std::vector{ { Flag::SendOther, tr::lng_rights_chat_send_text(tr::now) }, }; - auto inner = std::vector{ + auto media = std::vector{ { Flag::SendPhotos, tr::lng_rights_chat_photos(tr::now) }, { Flag::SendVideos, tr::lng_rights_chat_videos(tr::now) }, { Flag::SendVideoMessages, tr::lng_rights_chat_video_messages(tr::now) }, @@ -85,9 +86,64 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000); &RestrictionLabel::flags), end(second)); } - return std::vector>{ + return { { std::nullopt, std::move(first) }, - { tr::lng_rights_chat_send_media(), std::move(inner) }, + { tr::lng_rights_chat_send_media(), std::move(media) }, + { std::nullopt, std::move(second) }, + }; +} + +[[nodiscard]] auto NestedAdminRightLabels( + Data::AdminRightsSetOptions options) +-> std::vector> { + using Flag = ChatAdminRight; + + if (options.isGroup) { + auto result = std::vector{ + { Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) }, + { Flag::DeleteMessages, tr::lng_rights_group_delete(tr::now) }, + { Flag::BanUsers, tr::lng_rights_group_ban(tr::now) }, + { Flag::InviteByLinkOrAdd, options.anyoneCanAddMembers + ? tr::lng_rights_group_invite_link(tr::now) + : tr::lng_rights_group_invite(tr::now) }, + { Flag::ManageTopics, tr::lng_rights_group_topics(tr::now) }, + { Flag::PinMessages, tr::lng_rights_group_pin(tr::now) }, + { Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) }, + { Flag::Anonymous, tr::lng_rights_group_anonymous(tr::now) }, + { Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) }, + }; + if (!options.isForum) { + result.erase( + ranges::remove( + result, + Flag::ManageTopics | Flag(), + &AdminRightLabel::flags), + end(result)); + } + return { { std::nullopt, std::move(result) } }; + } + auto first = std::vector{ + { Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) }, + }; + auto messages = std::vector{ + { Flag::PostMessages, tr::lng_rights_channel_post(tr::now) }, + { Flag::EditMessages, tr::lng_rights_channel_edit(tr::now) }, + { Flag::DeleteMessages, tr::lng_rights_channel_delete(tr::now) }, + }; + auto stories = std::vector{ + { Flag::PostStories, tr::lng_rights_channel_post_stories(tr::now) }, + { Flag::EditStories, tr::lng_rights_channel_edit_stories(tr::now) }, + { Flag::DeleteStories, tr::lng_rights_channel_delete_stories(tr::now) }, + }; + auto second = std::vector{ + { Flag::InviteByLinkOrAdd, tr::lng_rights_group_invite(tr::now) }, + { Flag::ManageCall, tr::lng_rights_channel_manage_calls(tr::now) }, + { Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) }, + }; + return { + { std::nullopt, std::move(first) }, + { tr::lng_rights_channel_manage(), std::move(messages) }, + { tr::lng_rights_channel_manage_stories(), std::move(stories) }, { std::nullopt, std::move(second) }, }; } @@ -1031,42 +1087,11 @@ std::vector RestrictionLabels( std::vector AdminRightLabels( Data::AdminRightsSetOptions options) { - using Flag = ChatAdminRight; - - if (options.isGroup) { - auto result = std::vector{ - { Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) }, - { Flag::DeleteMessages, tr::lng_rights_group_delete(tr::now) }, - { Flag::BanUsers, tr::lng_rights_group_ban(tr::now) }, - { Flag::InviteByLinkOrAdd, options.anyoneCanAddMembers - ? tr::lng_rights_group_invite_link(tr::now) - : tr::lng_rights_group_invite(tr::now) }, - { Flag::ManageTopics, tr::lng_rights_group_topics(tr::now) }, - { Flag::PinMessages, tr::lng_rights_group_pin(tr::now) }, - { Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) }, - { Flag::Anonymous, tr::lng_rights_group_anonymous(tr::now) }, - { Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) }, - }; - if (!options.isForum) { - result.erase( - ranges::remove( - result, - Flag::ManageTopics | Flag(), - &AdminRightLabel::flags), - end(result)); - } - return result; - } else { - return { - { Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) }, - { Flag::PostMessages, tr::lng_rights_channel_post(tr::now) }, - { Flag::EditMessages, tr::lng_rights_channel_edit(tr::now) }, - { Flag::DeleteMessages, tr::lng_rights_channel_delete(tr::now) }, - { Flag::InviteByLinkOrAdd, tr::lng_rights_group_invite(tr::now) }, - { Flag::ManageCall, tr::lng_rights_channel_manage_calls(tr::now) }, - { Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) } - }; + auto result = std::vector(); + for (const auto &[_, r] : NestedAdminRightLabels(options)) { + result.insert(result.end(), r.begin(), r.end()); } + return result; } EditFlagsControl CreateEditRestrictions( @@ -1107,7 +1132,7 @@ EditFlagsControl CreateEditAdminRights( rights, { .header = std::move(header), - .labels = { { std::nullopt, AdminRightLabels(options) } }, + .labels = NestedAdminRightLabels(options), .disabledMessages = std::move(disabledMessages), }); result.widget = std::move(widget); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index dddc44116..2708f55ae 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_chat.h" #include "data/data_session.h" +#include "data/data_stories.h" #include "data/data_folder.h" #include "data/data_forum.h" #include "data/data_forum_icons.h" @@ -530,6 +531,11 @@ bool ChannelData::canBanMembers() const { || (adminRights() & AdminRight::BanUsers); } +bool ChannelData::canPostMessages() const { + return amCreator() + || (adminRights() & AdminRight::PostMessages); +} + bool ChannelData::canEditMessages() const { return amCreator() || (adminRights() & AdminRight::EditMessages); @@ -559,11 +565,6 @@ bool ChannelData::canAddAdmins() const { || (adminRights() & AdminRight::AddAdmins); } -bool ChannelData::canPublish() const { - return amCreator() - || (adminRights() & AdminRight::PostMessages); -} - bool ChannelData::allowsForwarding() const { return !(flags() & Flag::NoForwards); } @@ -877,6 +878,38 @@ const Data::AllowedReactions &ChannelData::allowedReactions() const { return _allowedReactions; } +bool ChannelData::hasActiveStories() const { + return flags() & Flag::HasActiveStories; +} + +bool ChannelData::hasUnreadStories() const { + return flags() & Flag::HasUnreadStories; +} + +void ChannelData::setStoriesState(StoriesState state) { + Expects(state != StoriesState::Unknown); + + const auto was = flags(); + switch (state) { + case StoriesState::None: + _flags.remove(Flag::HasActiveStories | Flag::HasUnreadStories); + break; + case StoriesState::HasRead: + _flags.set( + (flags() & ~Flag::HasUnreadStories) | Flag::HasActiveStories); + break; + case StoriesState::HasUnread: + _flags.add(Flag::HasActiveStories | Flag::HasUnreadStories); + break; + } + if (flags() != was) { + if (const auto history = owner().historyLoaded(this)) { + history->updateChatListEntryPostponed(); + } + session().changes().peerUpdated(this, UpdateFlag::StoriesState); + } +} + void ChannelData::processTopics(const MTPVector &topics) { if (const auto forum = this->forum()) { forum->applyReceivedTopics(topics); @@ -1046,6 +1079,7 @@ void ApplyChannelUpdate( } else { channel->setAllowedReactions({}); } + channel->owner().stories().apply(channel, update.vstories()); channel->fullUpdated(); channel->setPendingRequestsCount( update.vrequests_pending().value_or_empty(), diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 6c05d5c88..ee0550a6d 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -59,6 +59,9 @@ enum class ChannelDataFlag { Forum = (1 << 23), AntiSpam = (1 << 24), ParticipantsHidden = (1 << 25), + StoriesHidden = (1 << 26), + HasActiveStories = (1 << 27), + HasUnreadStories = (1 << 28), }; inline constexpr bool is_flag_type(ChannelDataFlag) { return true; }; using ChannelDataFlags = base::flags; @@ -226,6 +229,9 @@ public: [[nodiscard]] bool isFake() const { return flags() & Flag::Fake; } + [[nodiscard]] bool hasStoriesHidden() const { + return flags() & Flag::StoriesHidden; + } [[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights( not_null participant); @@ -329,10 +335,13 @@ public: [[nodiscard]] bool canBanMembers() const; [[nodiscard]] bool anyoneCanAddMembers() const; + [[nodiscard]] bool canPostMessages() const; [[nodiscard]] bool canEditMessages() const; [[nodiscard]] bool canDeleteMessages() const; + [[nodiscard]] bool canPostStories() const; + [[nodiscard]] bool canEditStories() const; + [[nodiscard]] bool canDeleteStories() const; [[nodiscard]] bool hiddenPreHistory() const; - [[nodiscard]] bool canPublish() const; [[nodiscard]] bool canViewMembers() const; [[nodiscard]] bool canViewAdmins() const; [[nodiscard]] bool canViewBanned() const; @@ -437,6 +446,10 @@ public: void setAllowedReactions(Data::AllowedReactions value); [[nodiscard]] const Data::AllowedReactions &allowedReactions() const; + [[nodiscard]] bool hasActiveStories() const; + [[nodiscard]] bool hasUnreadStories() const; + void setStoriesState(StoriesState state); + [[nodiscard]] Data::Forum *forum() const { return mgInfo ? mgInfo->forum() : nullptr; } diff --git a/Telegram/SourceFiles/data/data_chat_participant_status.cpp b/Telegram/SourceFiles/data/data_chat_participant_status.cpp index 836f13ebc..f875ccdb3 100644 --- a/Telegram/SourceFiles/data/data_chat_participant_status.cpp +++ b/Telegram/SourceFiles/data/data_chat_participant_status.cpp @@ -146,7 +146,7 @@ bool CanSendAnyOf( && !(channel->flags() & Flag::JoinToWrite)); if (!allowed || (forbidInForums && channel->isForum())) { return false; - } else if (channel->canPublish()) { + } else if (channel->canPostMessages()) { return true; } else if (channel->isBroadcast()) { return false; diff --git a/Telegram/SourceFiles/data/data_chat_participant_status.h b/Telegram/SourceFiles/data/data_chat_participant_status.h index 2227e8042..8dd7cd682 100644 --- a/Telegram/SourceFiles/data/data_chat_participant_status.h +++ b/Telegram/SourceFiles/data/data_chat_participant_status.h @@ -25,6 +25,9 @@ enum class ChatAdminRight { ManageCall = (1 << 11), Other = (1 << 12), ManageTopics = (1 << 13), + PostStories = (1 << 14), + EditStories = (1 << 15), + DeleteStories = (1 << 16), }; inline constexpr bool is_flag_type(ChatAdminRight) { return true; } using ChatAdminRights = base::flags; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index c096853c6..00c183161 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -898,6 +898,33 @@ bool PeerData::isRepliesChat() const { : kTestId) == id; } +bool PeerData::sharedMediaInfo() const { + return isSelf() || isRepliesChat(); +} + +bool PeerData::hasStoriesHidden() const { + if (const auto user = asUser()) { + return user->hasStoriesHidden(); + } else if (const auto channel = asChannel()) { + return channel->hasStoriesHidden(); + } + return false; +} + +void PeerData::setStoriesHidden(bool hidden) { + if (const auto user = asUser()) { + user->setFlags(hidden + ? (user->flags() | UserDataFlag::StoriesHidden) + : (user->flags() & ~UserDataFlag::StoriesHidden)); + } else if (const auto channel = asChannel()) { + channel->setFlags(hidden + ? (channel->flags() | ChannelDataFlag::StoriesHidden) + : (channel->flags() & ~ChannelDataFlag::StoriesHidden)); + } else { + Unexpected("PeerData::setStoriesHidden for non-user/non-channel."); + } +} + Data::Forum *PeerData::forum() const { if (const auto channel = asChannel()) { return channel->forum(); @@ -1108,6 +1135,34 @@ const Data::WallPaper *PeerData::wallPaper() const { return _wallPaper.get(); } +bool PeerData::hasActiveStories() const { + if (const auto user = asUser()) { + return user->hasActiveStories(); + } else if (const auto channel = asChannel()) { + return channel->hasActiveStories(); + } + return false; +} + +bool PeerData::hasUnreadStories() const { + if (const auto user = asUser()) { + return user->hasUnreadStories(); + } else if (const auto channel = asChannel()) { + return channel->hasUnreadStories(); + } + return false; +} + +void PeerData::setStoriesState(StoriesState state) { + if (const auto user = asUser()) { + return user->setStoriesState(state); + } else if (const auto channel = asChannel()) { + return channel->setStoriesState(state); + } else { + Unexpected("PeerData::setStoriesState for non-user/non-channel."); + } +} + void PeerData::setIsBlocked(bool is) { const auto status = is ? BlockStatus::Blocked diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 17b19bf63..73c3d85f8 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -183,9 +183,9 @@ public: [[nodiscard]] bool isForum() const; [[nodiscard]] bool isGigagroup() const; [[nodiscard]] bool isRepliesChat() const; - [[nodiscard]] bool sharedMediaInfo() const { - return isSelf() || isRepliesChat(); - } + [[nodiscard]] bool sharedMediaInfo() const; + [[nodiscard]] bool hasStoriesHidden() const; + void setStoriesHidden(bool hidden); [[nodiscard]] bool isNotificationsUser() const { return (id == peerFromUser(333000)) @@ -407,6 +407,16 @@ public: void setWallPaper(std::optional paper); [[nodiscard]] const Data::WallPaper *wallPaper() const; + enum class StoriesState { + Unknown, + None, + HasRead, + HasUnread, + }; + [[nodiscard]] bool hasActiveStories() const; + [[nodiscard]] bool hasUnreadStories() const; + void setStoriesState(StoriesState state); + const PeerId id; MTPinputPeer input = MTP_inputPeerEmpty(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index a65c1fd91..68ef1afa2 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -909,7 +909,17 @@ not_null Session::processChat(const MTPChat &data) { | Flag::NoForwards | Flag::JoinToWrite | Flag::RequestToJoin - | Flag::Forum; + | Flag::Forum + | ((!minimal && !data.is_stories_hidden_min()) + ? Flag::StoriesHidden + : Flag()); + const auto storiesState = minimal + ? std::optional() + : data.is_stories_unavailable() + ? Data::Stories::PeerSourceState() + : !data.vstories_max_id() + ? std::optional() + : stories().peerSourceState(channel, data.vstories_max_id()->v); const auto flagsSet = (data.is_broadcast() ? Flag::Broadcast : Flag()) | (data.is_verified() ? Flag::Verified : Flag()) | (data.is_scam() ? Flag::Scam : Flag()) @@ -935,8 +945,20 @@ not_null Session::processChat(const MTPChat &data) { | (data.is_join_request() ? Flag::RequestToJoin : Flag()) | ((data.is_forum() && data.is_megagroup()) ? Flag::Forum + : Flag()) + | ((!minimal + && !data.is_stories_hidden_min() + && data.is_stories_hidden()) + ? Flag::StoriesHidden : Flag()); channel->setFlags((channel->flags() & ~flagsMask) | flagsSet); + if (!minimal && storiesState) { + result->setStoriesState(!storiesState->maxId + ? UserData::StoriesState::None + : (storiesState->maxId > storiesState->readTill) + ? UserData::StoriesState::HasUnread + : UserData::StoriesState::HasRead); + } channel->setPhoto(data.vphoto()); @@ -3345,12 +3367,12 @@ void Session::webpageApplyFields( for (const auto &attribute : attributes->v) { attribute.match([&](const MTPDwebPageAttributeStory &data) { storyId = FullStoryId{ - peerFromUser(data.vuser_id()), + peerFromMTP(data.vpeer()), data.vid().v, }; if (const auto embed = data.vstory()) { story = stories().applyFromWebpage( - peerFromUser(data.vuser_id()), + peerFromMTP(data.vpeer()), *embed); } else if (const auto maybe = stories().lookup(storyId)) { story = *maybe; diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 661c28777..7272fbb5d 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "core/application.h" #include "data/data_changes.h" +#include "data/data_channel.h" #include "data/data_document.h" #include "data/data_folder.h" #include "data/data_photo.h" @@ -78,11 +79,11 @@ using UpdateFlag = StoryUpdate::Flag; StoriesSourceInfo StoriesSource::info() const { return { - .id = user->id, + .id = peer->id, .last = ids.empty() ? 0 : ids.back().date, .count = uint32(std::min(int(ids.size()), kMaxSegmentsCount)), .unreadCount = uint32(std::min(unreadCount(), kMaxSegmentsCount)), - .premium = user->isPremium() ? 1U : 0U, + .premium = (peer->isUser() && peer->asUser()->isPremium()) ? 1U : 0, }; } @@ -122,10 +123,10 @@ Main::Session &Stories::session() const { } void Stories::apply(const MTPDupdateStory &data) { - const auto peerId = peerFromUser(data.vuser_id()); - const auto user = not_null(_owner->peer(peerId)->asUser()); + const auto peerId = peerFromMTP(data.vpeer()); + const auto peer = _owner->peer(peerId); const auto now = base::unixtime::now(); - const auto idDates = parseAndApply(user, data.vstory(), now); + const auto idDates = parseAndApply(peer, data.vstory(), now); if (!idDates) { return; } @@ -136,7 +137,7 @@ void Stories::apply(const MTPDupdateStory &data) { } const auto i = _all.find(peerId); if (i == end(_all)) { - requestUserStories(user); + requestPeerStories(peer); return; } else if (i->second.ids.contains(idDates)) { return; @@ -144,8 +145,8 @@ void Stories::apply(const MTPDupdateStory &data) { const auto wasInfo = i->second.info(); i->second.ids.emplace(idDates); const auto nowInfo = i->second.info(); - if (user->isSelf() && i->second.readTill < idDates.id) { - _readTill[user->id] = i->second.readTill = idDates.id; + if (peer->isSelf() && i->second.readTill < idDates.id) { + _readTill[peerId] = i->second.readTill = idDates.id; } if (wasInfo == nowInfo) { return; @@ -161,17 +162,17 @@ void Stories::apply(const MTPDupdateStory &data) { sort(list); } }; - if (user->hasStoriesHidden()) { + if (peer->hasStoriesHidden()) { refreshInList(StorySourcesList::Hidden); } else { refreshInList(StorySourcesList::NotHidden); } _sourceChanged.fire_copy(peerId); - updateUserStoriesState(user); + updatePeerStoriesState(peer); } void Stories::apply(const MTPDupdateReadStories &data) { - bumpReadTill(peerFromUser(data.vuser_id()), data.vmax_id().v); + bumpReadTill(peerFromMTP(data.vpeer()), data.vmax_id().v); } void Stories::apply(const MTPStoriesStealthMode &stealthMode) { @@ -182,13 +183,13 @@ void Stories::apply(const MTPStoriesStealthMode &stealthMode) { }; } -void Stories::apply(not_null peer, const MTPUserStories *data) { +void Stories::apply(not_null peer, const MTPPeerStories *data) { if (!data) { applyDeletedFromSources(peer->id, StorySourcesList::NotHidden); applyDeletedFromSources(peer->id, StorySourcesList::Hidden); _all.erase(peer->id); _sourceChanged.fire_copy(peer->id); - updateUserStoriesState(peer); + updatePeerStoriesState(peer); } else { parseAndApply(*data); } @@ -205,10 +206,10 @@ Story *Stories::applyFromWebpage(PeerId peerId, const MTPstoryItem &story) { return value ? value->get() : nullptr; } -void Stories::requestUserStories( - not_null user, +void Stories::requestPeerStories( + not_null peer, Fn done) { - const auto [i, ok] = _requestingUserStories.emplace(user); + const auto [i, ok] = _requestingPeerStories.emplace(peer); if (done) { i->second.push_back(std::move(done)); } @@ -216,22 +217,23 @@ void Stories::requestUserStories( return; } const auto finish = [=] { - if (const auto callbacks = _requestingUserStories.take(user)) { + if (const auto callbacks = _requestingPeerStories.take(peer)) { for (const auto &callback : *callbacks) { callback(); } } }; - _owner->session().api().request(MTPstories_GetUserStories( - user->inputUser - )).done([=](const MTPstories_UserStories &result) { + _owner->session().api().request(MTPstories_GetPeerStories( + peer->input + )).done([=](const MTPstories_PeerStories &result) { const auto &data = result.data(); _owner->processUsers(data.vusers()); + _owner->processChats(data.vchats()); parseAndApply(data.vstories()); finish(); }).fail([=] { - applyDeletedFromSources(user->id, StorySourcesList::NotHidden); - applyDeletedFromSources(user->id, StorySourcesList::Hidden); + applyDeletedFromSources(peer->id, StorySourcesList::NotHidden); + applyDeletedFromSources(peer->id, StorySourcesList::Hidden); finish(); }).send(); } @@ -291,33 +293,33 @@ void Stories::processExpired() { } } -void Stories::parseAndApply(const MTPUserStories &stories) { +void Stories::parseAndApply(const MTPPeerStories &stories) { const auto &data = stories.data(); - const auto peerId = peerFromUser(data.vuser_id()); + const auto peerId = peerFromMTP(data.vpeer()); const auto already = _readTill.find(peerId); const auto readTill = std::max( data.vmax_read_id().value_or_empty(), (already != end(_readTill) ? already->second : 0)); - const auto user = _owner->peer(peerId)->asUser(); + const auto peer = _owner->peer(peerId); auto result = StoriesSource{ - .user = user, + .peer = peer, .readTill = readTill, - .hidden = user->hasStoriesHidden(), + .hidden = peer->hasStoriesHidden(), }; const auto &list = data.vstories().v; const auto now = base::unixtime::now(); result.ids.reserve(list.size()); for (const auto &story : list) { - if (const auto id = parseAndApply(result.user, story, now)) { + if (const auto id = parseAndApply(result.peer, story, now)) { result.ids.emplace(id); } } if (result.ids.empty()) { applyDeletedFromSources(peerId, StorySourcesList::NotHidden); applyDeletedFromSources(peerId, StorySourcesList::Hidden); - user->setStoriesState(UserData::StoriesState::None); + peer->setStoriesState(PeerData::StoriesState::None); return; - } else if (user->isSelf()) { + } else if (peer->isSelf()) { result.readTill = result.ids.back().id; } _readTill[peerId] = result.readTill; @@ -345,11 +347,13 @@ void Stories::parseAndApply(const MTPUserStories &stories) { } sort(list); }; - if (result.user->isSelf() - || result.user->isBot() - || result.user->isServiceUser() - || result.user->isContact()) { - const auto hidden = result.user->hasStoriesHidden(); + if (result.peer->isSelf() + || (result.peer->isChannel() && result.peer->asChannel()->amIn()) + || (result.peer->isUser() + && (result.peer->asUser()->isBot() + || result.peer->asUser()->isContact())) + || result.peer->isServiceUser()) { + const auto hidden = result.peer->hasStoriesHidden(); using List = StorySourcesList; add(hidden ? List::Hidden : List::NotHidden); applyDeletedFromSources( @@ -360,7 +364,7 @@ void Stories::parseAndApply(const MTPUserStories &stories) { applyDeletedFromSources(peerId, StorySourcesList::Hidden); } _sourceChanged.fire_copy(peerId); - updateUserStoriesState(result.user); + updatePeerStoriesState(result.peer); } Story *Stories::parseAndApply( @@ -539,9 +543,10 @@ void Stories::loadMore(StorySourcesList list) { result.match([&](const MTPDstories_allStories &data) { _owner->processUsers(data.vusers()); + _owner->processChats(data.vchats()); _sourcesStates[index] = qs(data.vstate()); _sourcesLoaded[index] = !data.is_has_more(); - for (const auto &single : data.vuser_stories().v) { + for (const auto &single : data.vpeer_stories().v) { parseAndApply(single); } }, [](const MTPDstories_allStoriesNotModified &) { @@ -654,18 +659,15 @@ void Stories::sendResolveRequests() { crl::on_main(&session(), [=] { sendResolveRequests(); }); } }; - const auto user = _owner->session().data().peer(peerId)->asUser(); - if (!user) { - finish(peerId); - continue; - } + const auto peer = _owner->session().data().peer(peerId); api->request(MTPstories_GetStoriesByID( - user->inputUser, + peer->input, MTP_vector(prepared) )).done([=](const MTPstories_Stories &result) { owner().processUsers(result.data().vusers()); - processResolvedStories(user, result.data().vstories().v); - finish(user->id); + owner().processChats(result.data().vchats()); + processResolvedStories(peer, result.data().vstories().v); + finish(peer->id); }).fail([=] { finish(peerId); }).send(); @@ -786,14 +788,14 @@ void Stories::applyRemovedFromActive(FullStoryId id) { const auto j = i->second.ids.lower_bound(StoryIdDates{ id.story }); if (j != end(i->second.ids) && j->id == id.story) { i->second.ids.erase(j); - const auto user = i->second.user; + const auto peer = i->second.peer; if (i->second.ids.empty()) { _all.erase(i); removeFromList(StorySourcesList::NotHidden); removeFromList(StorySourcesList::Hidden); } _sourceChanged.fire_copy(id.peer); - updateUserStoriesState(user); + updatePeerStoriesState(peer); } } } @@ -881,7 +883,7 @@ void Stories::sendReaction(FullStoryId id, Data::ReactionId reaction) { const auto api = &session().api(); api->request(MTPstories_SendReaction( MTP_flags(0), - story->peer()->asUser()->inputUser, + story->peer()->input, MTP_int(id.story), ReactionToMTP(reaction) )).send(); @@ -1054,7 +1056,7 @@ bool Stories::bumpReadTill(PeerId peerId, StoryId maxReadTill) { if (till < maxReadTill) { const auto from = till; till = maxReadTill; - updateUserStoriesState(_owner->peer(peerId)); + updatePeerStoriesState(_owner->peer(peerId)); const auto i = _stories.find(peerId); if (i != end(_stories)) { refreshItems = ranges::make_subrange( @@ -1097,19 +1099,16 @@ void Stories::toggleHidden( PeerId peerId, bool hidden, std::shared_ptr show) { - const auto user = _owner->peer(peerId)->asUser(); - Assert(user != nullptr); - if (user->hasStoriesHidden() != hidden) { - user->setFlags(hidden - ? (user->flags() | UserDataFlag::StoriesHidden) - : (user->flags() & ~UserDataFlag::StoriesHidden)); - session().api().request(MTPcontacts_ToggleStoriesHidden( - user->inputUser, + const auto peer = _owner->peer(peerId); + if (peer->hasStoriesHidden() != hidden) { + peer->setStoriesHidden(hidden); + session().api().request(MTPstories_TogglePeerStoriesHidden( + peer->input, MTP_bool(hidden) )).send(); } - const auto name = user->shortName(); + const auto name = peer->shortName(); const auto guard = gsl::finally([&] { if (show) { const auto phrase = hidden @@ -1166,8 +1165,6 @@ void Stories::toggleHidden( void Stories::sendMarkAsReadRequest( not_null peer, StoryId tillId) { - Expects(peer->isUser()); - const auto peerId = peer->id; _markReadRequests.emplace(peerId); const auto finish = [=] { @@ -1181,7 +1178,7 @@ void Stories::sendMarkAsReadRequest( const auto api = &_owner->session().api(); api->request(MTPstories_ReadStories( - peer->asUser()->inputUser, + peer->input, MTP_int(tillId) )).done(finish).fail(finish).send(); } @@ -1205,7 +1202,7 @@ void Stories::sendMarkAsReadRequests() { } const auto j = _all.find(peerId); if (j != end(_all)) { - sendMarkAsReadRequest(j->second.user, j->second.readTill); + sendMarkAsReadRequest(j->second.peer, j->second.readTill); } i = _markReadPending.erase(i); } @@ -1243,7 +1240,7 @@ void Stories::sendIncrementViewsRequests() { checkQuitPreventFinished(); }; api->request(MTPstories_IncrementStoryViews( - _owner->peer(peer)->asUser()->inputUser, + _owner->peer(peer)->input, MTP_vector(std::move(ids)) )).done(finish).fail(finish).send(); _incrementViewsPending.remove(peer); @@ -1272,6 +1269,7 @@ void Stories::loadViewsSlice( using Flag = MTPstories_GetStoryViewsList::Flag; _viewsRequestId = api->request(MTPstories_GetStoryViewsList( MTP_flags(Flag::f_reactions_first), + MTP_inputPeerSelf(), MTPstring(), // q MTP_int(id), MTP_string(offset), @@ -1364,6 +1362,7 @@ void Stories::archiveLoadMore() { } const auto api = &_owner->session().api(); _archiveRequestId = api->request(MTPstories_GetStoriesArchive( + MTP_inputPeerSelf(), MTP_int(_archiveLastId), MTP_int(_archiveLastId ? kArchivePerPage : kArchiveFirstPerPage) )).done([=](const MTPstories_Stories &result) { @@ -1399,8 +1398,6 @@ void Stories::archiveLoadMore() { } void Stories::savedLoadMore(PeerId peerId) { - Expects(peerIsUser(peerId)); - auto &saved = _saved[peerId]; if (saved.requestId || saved.loaded) { return; @@ -1408,7 +1405,7 @@ void Stories::savedLoadMore(PeerId peerId) { const auto api = &_owner->session().api(); const auto peer = _owner->peer(peerId); saved.requestId = api->request(MTPstories_GetPinnedStories( - peer->asUser()->inputUser, + peer->input, MTP_int(saved.lastId), MTP_int(saved.lastId ? kSavedPerPage : kSavedFirstPerPage) )).done([=](const MTPstories_Stories &result) { @@ -1456,6 +1453,7 @@ void Stories::deleteList(const std::vector &ids) { if (!list.empty()) { const auto api = &_owner->session().api(); api->request(MTPstories_DeleteStories( + MTP_inputPeerSelf(), MTP_vector(list) )).done([=](const MTPVector &result) { for (const auto &id : result.v) { @@ -1481,6 +1479,7 @@ void Stories::togglePinnedList( } const auto api = &_owner->session().api(); api->request(MTPstories_TogglePinned( + MTP_inputPeerSelf(), MTP_vector(list), MTP_bool(pinned) )).done([=](const MTPVector &result) { @@ -1608,7 +1607,7 @@ std::optional Stories::peerSourceState( }; } requestReadTills(); - _pendingUserStateMaxId[peer] = storyMaxId; + _pendingPeerStateMaxId[peer] = storyMaxId; return std::nullopt; } @@ -1617,12 +1616,12 @@ void Stories::requestReadTills() { return; } const auto api = &_owner->session().api(); - _readTillsRequestId = api->request(MTPstories_GetAllReadUserStories( + _readTillsRequestId = api->request(MTPstories_GetAllReadPeerStories( )).done([=](const MTPUpdates &result) { _readTillReceived = true; api->applyUpdates(result); - for (auto &[peer, maxId] : base::take(_pendingUserStateMaxId)) { - updateUserStoriesState(peer); + for (auto &[peer, maxId] : base::take(_pendingPeerStateMaxId)) { + updatePeerStoriesState(peer); } for (const auto &storyId : base::take(_pendingReadTillItems)) { _owner->refreshStoryItemViews(storyId); @@ -1745,24 +1744,22 @@ void Stories::sendPollingViewsRequests() { _pollingViewsTimer.callOnce(kPollViewsInterval); } -void Stories::updateUserStoriesState(not_null peer) { +void Stories::updatePeerStoriesState(not_null peer) { const auto till = _readTill.find(peer->id); const auto readTill = (till != end(_readTill)) ? till->second : 0; const auto pendingMaxId = [&] { - const auto j = _pendingUserStateMaxId.find(peer); - return (j != end(_pendingUserStateMaxId)) ? j->second : 0; + const auto j = _pendingPeerStateMaxId.find(peer); + return (j != end(_pendingPeerStateMaxId)) ? j->second : 0; }; const auto i = _all.find(peer->id); const auto max = (i != end(_all)) ? (i->second.ids.empty() ? 0 : i->second.ids.back().id) : pendingMaxId(); - if (const auto user = peer->asUser()) { - user->setStoriesState(!max - ? UserData::StoriesState::None - : (max <= readTill) - ? UserData::StoriesState::HasRead - : UserData::StoriesState::HasUnread); - } + peer->setStoriesState(!max + ? PeerData::StoriesState::None + : (max <= readTill) + ? PeerData::StoriesState::HasRead + : PeerData::StoriesState::HasUnread); } void Stories::preloadSourcesChanged(StorySourcesList list) { diff --git a/Telegram/SourceFiles/data/data_stories.h b/Telegram/SourceFiles/data/data_stories.h index 8d8b23da4..b0d8e3707 100644 --- a/Telegram/SourceFiles/data/data_stories.h +++ b/Telegram/SourceFiles/data/data_stories.h @@ -52,7 +52,7 @@ struct StoriesSourceInfo { }; struct StoriesSource { - not_null user; + not_null peer; base::flat_set ids; StoryId readTill = 0; bool hidden = false; @@ -148,7 +148,7 @@ public: void apply(const MTPDupdateStory &data); void apply(const MTPDupdateReadStories &data); void apply(const MTPStoriesStealthMode &stealthMode); - void apply(not_null peer, const MTPUserStories *data); + void apply(not_null peer, const MTPPeerStories *data); Story *applyFromWebpage(PeerId peerId, const MTPstoryItem &story); void loadAround(FullStoryId id, StoriesContext context); @@ -228,8 +228,8 @@ public: [[nodiscard]] bool registerPolling(FullStoryId id, Polling polling); void unregisterPolling(FullStoryId id, Polling polling); - void requestUserStories( - not_null user, + void requestPeerStories( + not_null peer, Fn done = nullptr); void savedStateChanged(not_null story); @@ -255,7 +255,7 @@ private: int viewer = 0; }; - void parseAndApply(const MTPUserStories &stories); + void parseAndApply(const MTPPeerStories &stories); [[nodiscard]] Story *parseAndApply( not_null peer, const MTPDstoryItem &data, @@ -269,7 +269,7 @@ private: const QVector &list); void sendResolveRequests(); void finalizeResolve(FullStoryId id); - void updateUserStoriesState(not_null peer); + void updatePeerStoriesState(not_null peer); void applyDeleted(FullStoryId id); void applyExpired(FullStoryId id); @@ -360,8 +360,8 @@ private: base::Timer _markReadTimer; base::flat_set _markReadRequests; base::flat_map< - not_null, - std::vector>> _requestingUserStories; + not_null, + std::vector>> _requestingPeerStories; base::flat_map> _incrementViewsPending; base::Timer _incrementViewsTimer; @@ -381,7 +381,7 @@ private: base::flat_map _readTill; base::flat_set _pendingReadTillItems; - base::flat_map, StoryId> _pendingUserStateMaxId; + base::flat_map, StoryId> _pendingPeerStateMaxId; mtpRequestId _readTillsRequestId = 0; bool _readTillReceived = false; diff --git a/Telegram/SourceFiles/data/data_story.cpp b/Telegram/SourceFiles/data/data_story.cpp index fa344d24f..70a2c9ee5 100644 --- a/Telegram/SourceFiles/data/data_story.cpp +++ b/Telegram/SourceFiles/data/data_story.cpp @@ -66,6 +66,25 @@ using UpdateFlag = StoryUpdate::Flag; }); }, [](const MTPDgeoPointEmpty &) { }); + }, [&](const MTPDmediaAreaSuggestedReaction &data) { + }, [&](const MTPDinputMediaAreaVenue &data) { + LOG(("API Error: Unexpected inputMediaAreaVenue in API data.")); + }); + return result; +} + +[[nodiscard]] auto ParseSuggestedReaction(const MTPMediaArea &area) +-> std::optional { + auto result = std::optional(); + area.match([&](const MTPDmediaAreaVenue &data) { + }, [&](const MTPDmediaAreaGeoPoint &data) { + }, [&](const MTPDmediaAreaSuggestedReaction &data) { + result.emplace(SuggestedReaction{ + .area = ParseArea(data.vcoordinates()), + .reaction = Data::ReactionFromMTP(data.vreaction()), + .flipped = data.is_flipped(), + .dark = data.is_dark(), + }); }, [&](const MTPDinputMediaAreaVenue &data) { LOG(("API Error: Unexpected inputMediaAreaVenue in API data.")); }); @@ -317,6 +336,10 @@ bool Story::edited() const { return _edited; } +bool Story::out() const { + return _out; +} + bool Story::canDownloadIfPremium() const { return !forbidsForward() || _peer->isSelf(); } @@ -455,6 +478,10 @@ const std::vector &Story::locations() const { return _locations; } +const std::vector &Story::suggestedReactions() const { + return _suggestedReactions; +} + void Story::applyChanges( StoryMedia media, const MTPDstoryItem &data, @@ -486,6 +513,7 @@ void Story::applyFields( ? StoryPrivacy::SelectedContacts : StoryPrivacy::Other; const auto noForwards = data.is_noforwards(); + const auto out = data.is_min() ? _out : data.is_out(); auto caption = TextWithEntities{ data.vcaption().value_or_empty(), Api::EntitiesFromMTP( @@ -497,7 +525,7 @@ void Story::applyFields( auto viewers = std::vector>(); if (const auto info = data.vviews()) { views = info->data().vviews_count().v; - reactions = info->data().vreactions_count().v; + reactions = info->data().vreactions_count().value_or_empty(); if (const auto list = info->data().vrecent_viewers()) { viewers.reserve(list->v.size()); auto &owner = _peer->owner(); @@ -511,11 +539,15 @@ void Story::applyFields( viewers = _recentViewers; } auto locations = std::vector(); + auto suggestedReactions = std::vector(); if (const auto areas = data.vmedia_areas()) { locations.reserve(areas->v.size()); + suggestedReactions.reserve(areas->v.size()); for (const auto &area : areas->v) { if (const auto location = ParseLocation(area)) { locations.push_back(*location); + } else if (const auto reaction = ParseSuggestedReaction(area)) { + suggestedReactions.push_back(*reaction); } } } @@ -528,13 +560,15 @@ void Story::applyFields( || (_views.reactions != reactions) || (_recentViewers != viewers); const auto locationsChanged = (_locations != locations); + const auto suggestedReactionsChanged + = (_suggestedReactions != suggestedReactions); const auto reactionChanged = (_sentReactionId != reaction); + _out = out; _privacyPublic = (privacy == StoryPrivacy::Public); _privacyCloseFriends = (privacy == StoryPrivacy::CloseFriends); _privacyContacts = (privacy == StoryPrivacy::Contacts); _privacySelectedContacts = (privacy == StoryPrivacy::SelectedContacts); - _noForwards = noForwards; _edited = edited; _pinned = pinned; _noForwards = noForwards; @@ -553,6 +587,9 @@ void Story::applyFields( if (locationsChanged) { _locations = std::move(locations); } + if (suggestedReactionsChanged) { + _suggestedReactions = std::move(suggestedReactions); + } if (reactionChanged) { _sentReactionId = reaction; } @@ -560,7 +597,8 @@ void Story::applyFields( const auto changed = editedChanged || captionChanged || mediaChanged - || locationsChanged; + || locationsChanged + || suggestedReactionsChanged; if (!initial && (changed || viewsChanged || reactionChanged)) { _peer->session().changes().storyUpdated(this, UpdateFlag() | (changed ? UpdateFlag::Edited : UpdateFlag()) diff --git a/Telegram/SourceFiles/data/data_story.h b/Telegram/SourceFiles/data/data_story.h index dcfe4495c..342d5b03a 100644 --- a/Telegram/SourceFiles/data/data_story.h +++ b/Telegram/SourceFiles/data/data_story.h @@ -96,6 +96,17 @@ struct StoryLocation { const StoryLocation &) = default; }; +struct SuggestedReaction { + StoryArea area; + Data::ReactionId reaction; + bool flipped = false; + bool dark = false; + + friend inline bool operator==( + const SuggestedReaction &, + const SuggestedReaction &) = default; +}; + class Story final { public: Story( @@ -132,6 +143,7 @@ public: [[nodiscard]] StoryPrivacy privacy() const; [[nodiscard]] bool forbidsForward() const; [[nodiscard]] bool edited() const; + [[nodiscard]] bool out() const; [[nodiscard]] bool canDownloadIfPremium() const; [[nodiscard]] bool canDownloadChecked() const; @@ -157,6 +169,8 @@ public: void applyViewsSlice(const QString &offset, const StoryViews &slice); [[nodiscard]] const std::vector &locations() const; + [[nodiscard]] auto suggestedReactions() const + -> const std::vector &; void applyChanges( StoryMedia media, @@ -178,10 +192,12 @@ private: TextWithEntities _caption; std::vector> _recentViewers; std::vector _locations; + std::vector _suggestedReactions; StoryViews _views; const TimeId _date = 0; const TimeId _expires = 0; TimeId _lastUpdateTime = 0; + bool _out : 1 = false; bool _pinned : 1 = false; bool _privacyPublic : 1 = false; bool _privacyCloseFriends : 1 = false; diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 09c66a922..f385b8c13 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -127,18 +127,17 @@ void UserData::setPrivateForwardName(const QString &name) { } bool UserData::hasActiveStories() const { - return flags() & UserDataFlag::HasActiveStories; + return flags() & Flag::HasActiveStories; } bool UserData::hasUnreadStories() const { - return flags() & UserDataFlag::HasUnreadStories; + return flags() & Flag::HasUnreadStories; } void UserData::setStoriesState(StoriesState state) { Expects(state != StoriesState::Unknown); const auto was = flags(); - using Flag = UserDataFlag; switch (state) { case StoriesState::None: _flags.remove(Flag::HasActiveStories | Flag::HasUnreadStories); diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index ad6d0b7ae..96811051e 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -176,12 +176,6 @@ public: [[nodiscard]] QString privateForwardName() const; void setPrivateForwardName(const QString &name); - enum class StoriesState { - Unknown, - None, - HasRead, - HasUnread, - }; [[nodiscard]] bool hasActiveStories() const; [[nodiscard]] bool hasUnreadStories() const; void setStoriesState(StoriesState state); diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp index f737d1615..b4df07d99 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp @@ -134,7 +134,7 @@ private: const not_null _data; const Data::StorySourcesList _list; base::flat_map< - not_null, + not_null, std::shared_ptr> _userpics; }; @@ -338,20 +338,20 @@ Content State::next() { Assert(source != nullptr); auto userpic = std::shared_ptr(); - const auto user = source->user; - if (const auto i = _userpics.find(user); i != end(_userpics)) { + const auto peer = source->peer; + if (const auto i = _userpics.find(peer); i != end(_userpics)) { userpic = i->second; } else { - userpic = MakeUserpicThumbnail(user); - _userpics.emplace(user, userpic); + userpic = MakeUserpicThumbnail(peer); + _userpics.emplace(peer, userpic); } result.elements.push_back({ - .id = uint64(user->id.value), - .name = user->shortName(), + .id = uint64(peer->id.value), + .name = peer->shortName(), .thumbnail = std::move(userpic), .count = info.count, .unreadCount = info.unreadCount, - .skipSmall = user->isSelf() ? 1U : 0U, + .skipSmall = peer->isSelf() ? 1U : 0U, }); } return result; diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp index 1ff8d6774..5ed8addd9 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.cpp +++ b/Telegram/SourceFiles/export/export_api_wrap.cpp @@ -504,6 +504,7 @@ void ApiWrap::requestStoriesCount() { Expects(_startProcess != nullptr); mainRequest(MTPstories_GetStoriesArchive( + MTP_inputPeerSelf(), MTP_int(0), // offset_id MTP_int(0) // limit )).done([=](const MTPstories_Stories &result) { @@ -907,6 +908,7 @@ void ApiWrap::requestStories( _storiesProcess->finish = std::move(finish); mainRequest(MTPstories_GetStoriesArchive( + MTP_inputPeerSelf(), MTP_int(_storiesProcess->offsetId), MTP_int(kStoriesSliceLimit) )).done([=](const MTPstories_Stories &result) mutable { @@ -993,6 +995,7 @@ void ApiWrap::finishStoriesSlice() { } mainRequest(MTPstories_GetStoriesArchive( + MTP_inputPeerSelf(), MTP_int(_storiesProcess->offsetId), MTP_int(kStoriesSliceLimit) )).done([=](const MTPstories_Stories &result) { @@ -2186,7 +2189,7 @@ void ApiWrap::filePartRefreshReference(int64 offset) { const auto &origin = _fileProcess->origin; if (origin.storyId) { _fileProcess->requestId = mainRequest(MTPstories_GetStoriesByID( - MTP_inputUserSelf(), + MTP_inputPeerSelf(), MTP_vector(1, MTP_int(origin.storyId)) )).fail([=](const MTP::Error &error) { _fileProcess->requestId = 0; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 448254a42..c4c7e3546 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -287,7 +287,7 @@ std::unique_ptr HistoryItem::CreateMedia( media.vvalue().v); }, [&](const MTPDmessageMediaStory &media) -> Result { return std::make_unique(item, FullStoryId{ - peerFromUser(media.vuser_id()), + peerFromMTP(media.vpeer()), media.vid().v, }, media.is_via_mention()); }, [](const MTPDmessageMediaEmpty &) -> Result { @@ -1981,7 +1981,7 @@ bool HistoryItem::canBeEdited() const { return true; } else if (out()) { if (isPost()) { - return channel->canPublish(); + return channel->canPostMessages(); } else if (const auto topic = this->topic()) { return Data::CanSendAnything(topic); } else { @@ -2033,9 +2033,8 @@ bool HistoryItem::canDelete() const { } if (channel->canDeleteMessages()) { return true; - } - if (out() && !isService()) { - return isPost() ? channel->canPublish() : true; + } else if (out() && !isService()) { + return isPost() ? channel->canPostMessages() : true; } return false; } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 4e5661a63..c1dbc9911 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -4575,7 +4575,7 @@ bool HistoryWidget::isChoosingTheme() const { bool HistoryWidget::isMuteUnmute() const { return _peer - && ((_peer->isBroadcast() && !_peer->asChannel()->canPublish()) + && ((_peer->isBroadcast() && !_peer->asChannel()->canPostMessages()) || (_peer->isGigagroup() && !Data::CanSendAnything(_peer)) || _peer->isRepliesChat()); } diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 0e776caaa..75ed5584b 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -18,9 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_document.h" #include "data/data_file_origin.h" +#include "data/data_peer.h" #include "data/data_session.h" #include "data/data_stories.h" -#include "data/data_user.h" #include "history/view/reactions/history_view_reactions_strip.h" #include "lang/lang_keys.h" #include "main/main_session.h" @@ -62,7 +62,7 @@ constexpr auto kSiblingMultiplierMax = 0.72; constexpr auto kSiblingOutsidePart = 0.24; constexpr auto kSiblingUserpicSize = 0.3; constexpr auto kInnerHeightMultiplier = 1.6; -constexpr auto kPreloadUsersCount = 3; +constexpr auto kPreloadPeersCount = 3; constexpr auto kPreloadStoriesCount = 5; constexpr auto kPreloadNextMediaCount = 3; constexpr auto kPreloadPreviousMediaCount = 1; @@ -140,10 +140,10 @@ private: class Controller::Unsupported final { public: - Unsupported(not_null controller, not_null user); + Unsupported(not_null controller, not_null peer); private: - void setup(not_null user); + void setup(not_null peer); const not_null _controller; std::unique_ptr _bg; @@ -206,13 +206,13 @@ void Controller::PhotoPlayback::callback() { Controller::Unsupported::Unsupported( not_null controller, - not_null user) + not_null peer) : _controller(controller) , _bgRound(st::storiesRadius, st::storiesComposeBg) { - setup(user); + setup(peer); } -void Controller::Unsupported::setup(not_null user) { +void Controller::Unsupported::setup(not_null peer) { const auto wrap = _controller->wrap(); _bg = std::make_unique(wrap); @@ -596,8 +596,8 @@ void Controller::toggleLiked() { void Controller::reactionChosen(ReactionsMode mode, ChosenReaction chosen) { if (mode == ReactionsMode::Message) { _replyArea->sendReaction(chosen.id); - } else if (const auto user = shownUser()) { - user->owner().stories().sendReaction(_shown, chosen.id); + } else if (const auto peer = shownPeer()) { + peer->owner().stories().sendReaction(_shown, chosen.id); } unfocusReply(); } @@ -638,11 +638,11 @@ auto Controller::cachedReactionIconFactory() const } void Controller::rebuildFromContext( - not_null user, + not_null peer, FullStoryId storyId) { using namespace Data; - auto &stories = user->owner().stories(); + auto &stories = peer->owner().stories(); auto list = std::optional(); auto source = (const StoriesSource*)nullptr; const auto peerId = storyId.peer; @@ -659,7 +659,7 @@ void Controller::rebuildFromContext( const auto i = ids.find(id); if (i != end(ids)) { list = StoriesList{ - .user = user, + .peer = peer, .ids = *saved, .total = stories.savedCount(peerId), }; @@ -673,7 +673,7 @@ void Controller::rebuildFromContext( } hideSiblings(); }, [&](StoriesContextArchive) { - Expects(user->isSelf()); + Expects(peer->isSelf()); if (stories.archiveCountKnown()) { const auto &archive = stories.archive(); @@ -681,7 +681,7 @@ void Controller::rebuildFromContext( const auto i = ids.find(id); if (i != end(ids)) { list = StoriesList{ - .user = user, + .peer = peer, .ids = archive, .total = stories.archiveCount(), }; @@ -706,8 +706,8 @@ void Controller::rebuildFromContext( } rebuildCachedSourcesList(sources, (i - begin(sources))); _cachedSourcesList[_cachedSourceIndex].shownId = storyId.story; - showSiblings(&user->session()); - if (int(sources.end() - i) < kPreloadUsersCount) { + showSiblings(&peer->session()); + if (int(sources.end() - i) < kPreloadPeersCount) { stories.loadMore(list); } } @@ -719,7 +719,7 @@ void Controller::rebuildFromContext( if (_list != list) { _list = std::move(list); } - if (const auto maybe = user->owner().stories().lookup(storyId)) { + if (const auto maybe = peer->owner().stories().lookup(storyId)) { const auto now = *maybe; const auto range = ComputeSameDayRange(now, _list->ids, _index); _sliderCount = range.till - range.from + 1; @@ -737,7 +737,7 @@ void Controller::rebuildFromContext( if (!source) { _source = std::nullopt; _list = StoriesList{ - .user = user, + .peer = peer, .ids = { { id } }, .total = 1, }; @@ -761,17 +761,17 @@ void Controller::preloadNext() { auto ids = std::vector(); ids.reserve(kPreloadPreviousMediaCount + kPreloadNextMediaCount); - const auto user = shownUser(); + const auto peer = shownPeer(); const auto count = shownCount(); const auto till = std::min(_index + kPreloadNextMediaCount, count); for (auto i = _index + 1; i != till; ++i) { - ids.push_back({ .peer = user->id, .story = shownId(i) }); + ids.push_back({ .peer = peer->id, .story = shownId(i) }); } const auto from = std::max(_index - kPreloadPreviousMediaCount, 0); for (auto i = _index; i != from;) { - ids.push_back({ .peer = user->id, .story = shownId(--i) }); + ids.push_back({ .peer = peer->id, .story = shownId(--i) }); } - user->owner().stories().setPreloadingInViewer(std::move(ids)); + peer->owner().stories().setPreloadingInViewer(std::move(ids)); } void Controller::checkMoveByDelta() { @@ -786,18 +786,18 @@ void Controller::show( Data::StoriesContext context) { auto &stories = story->owner().stories(); const auto storyId = story->fullId(); - const auto user = story->peer()->asUser(); + const auto peer = story->peer(); _context = context; _waitingForId = {}; _waitingForDelta = 0; - rebuildFromContext(user, storyId); + rebuildFromContext(peer, storyId); _contextLifetime.destroy(); const auto subscribeToSource = [&] { stories.sourceChanged() | rpl::filter( rpl::mappers::_1 == storyId.peer ) | rpl::start_with_next([=] { - rebuildFromContext(user, storyId); + rebuildFromContext(peer, storyId); }, _contextLifetime); }; v::match(_context.data, [&](Data::StoriesContextSingle) { @@ -807,13 +807,13 @@ void Controller::show( stories.savedChanged() | rpl::filter( rpl::mappers::_1 == storyId.peer ) | rpl::start_with_next([=] { - rebuildFromContext(user, storyId); + rebuildFromContext(peer, storyId); checkMoveByDelta(); }, _contextLifetime); }, [&](Data::StoriesContextArchive) { stories.archiveChanged( ) | rpl::start_with_next([=] { - rebuildFromContext(user, storyId); + rebuildFromContext(peer, storyId); checkMoveByDelta(); }, _contextLifetime); }, [&](Data::StorySourcesList) { @@ -834,7 +834,7 @@ void Controller::show( if (!unsupported) { _unsupported = nullptr; } else { - _unsupported = std::make_unique(this, user); + _unsupported = std::make_unique(this, peer); _header->raise(); _slider->raise(); } @@ -845,7 +845,7 @@ void Controller::show( _contentFadeAnimation.stop(); const auto document = story->document(); _header->show({ - .user = user, + .peer = peer, .date = story->date(), .fullIndex = _sliderCount ? _index : 0, .fullCount = _sliderCount ? shownCount() : 0, @@ -866,7 +866,7 @@ void Controller::show( } _replyArea->show({ - .user = unsupported ? nullptr : user, + .peer = unsupported ? nullptr : peer.get(), .id = story->id(), }, _reactions->likedValue()); @@ -874,13 +874,13 @@ void Controller::show( .list = story->recentViewers(), .reactions = story->reactions(), .total = story->views(), - .valid = user->isSelf(), + .valid = peer->isSelf(), }); stories.loadAround(storyId, context); updatePlayingAllowed(); - user->updateFull(); + peer->updateFull(); } bool Controller::changeShown(Data::Story *story) { @@ -1129,7 +1129,7 @@ void Controller::markAsRead() { return; } _viewed = true; - shownUser()->owner().stories().markAsRead(_shown, _started); + shownPeer()->owner().stories().markAsRead(_shown, _started); } bool Controller::subjumpAvailable(int delta) const { @@ -1169,12 +1169,12 @@ void Controller::subjumpTo(int index) { Expects(shown()); Expects(index >= 0 && index < shownCount()); - const auto user = shownUser(); + const auto peer = shownPeer(); const auto id = FullStoryId{ - .peer = user->id, + .peer = peer->id, .story = shownId(index), }; - auto &stories = user->owner().stories(); + auto &stories = peer->owner().stories(); if (!id.story) { const auto delta = index - _index; if (_waitingForDelta != delta) { @@ -1183,7 +1183,7 @@ void Controller::subjumpTo(int index) { loadMoreToList(); } } else if (stories.lookup(id)) { - _delegate->storiesJumpTo(&user->session(), id, _context); + _delegate->storiesJumpTo(&peer->session(), id, _context); } else if (_waitingForId != id) { _waitingForId = id; _waitingForDelta = 0; @@ -1195,8 +1195,8 @@ void Controller::checkWaitingFor() { Expects(_waitingForId.valid()); Expects(shown()); - const auto user = shownUser(); - auto &stories = user->owner().stories(); + const auto peer = shownPeer(); + auto &stories = peer->owner().stories(); const auto maybe = stories.lookup(_waitingForId); if (!maybe) { if (maybe.error() == Data::NoStory::Deleted) { @@ -1205,7 +1205,7 @@ void Controller::checkWaitingFor() { return; } _delegate->storiesJumpTo( - &user->session(), + &peer->session(), base::take(_waitingForId), _context); } @@ -1290,8 +1290,8 @@ const Data::StoryViews &Controller::views(int limit, bool initial) { if (_viewsSlice.total > _viewsSlice.list.size() && _viewsSlice.list.size() < limit) { const auto done = viewsGotMoreCallback(); - const auto user = shownUser(); - auto &stories = user->owner().stories(); + const auto peer = shownPeer(); + auto &stories = peer->owner().stories(); stories.loadViewsSlice(_shown.story, _viewsSlice.nextOffset, done); } return _viewsSlice; @@ -1304,8 +1304,8 @@ rpl::producer<> Controller::moreViewsLoaded() const { Fn Controller::viewsGotMoreCallback() { return crl::guard(&_viewsLoadGuard, [=](Data::StoryViews result) { if (_viewsSlice.list.empty()) { - const auto user = shownUser(); - auto &stories = user->owner().stories(); + const auto peer = shownPeer(); + auto &stories = peer->owner().stories(); if (const auto maybeStory = stories.lookup(_shown)) { _viewsSlice = (*maybeStory)->viewsList(); } else { @@ -1329,11 +1329,11 @@ bool Controller::shown() const { return _source || _list; } -UserData *Controller::shownUser() const { +PeerData *Controller::shownPeer() const { return _source - ? _source->user.get() + ? _source->peer.get() : _list - ? _list->user.get() + ? _list->peer.get() : nullptr; } @@ -1356,13 +1356,13 @@ void Controller::loadMoreToList() { using namespace Data; - const auto user = shownUser(); + const auto peer = shownPeer(); const auto peerId = _shown.peer; - auto &stories = user->owner().stories(); + auto &stories = peer->owner().stories(); v::match(_context.data, [&](StoriesContextSaved) { stories.savedLoadMore(peerId); }, [&](StoriesContextArchive) { - Expects(user->isSelf()); + Expects(peer->isSelf()); stories.archiveLoadMore(); }, [](const auto &) { @@ -1462,10 +1462,10 @@ void Controller::rebuildCachedSourcesList( void Controller::refreshViewsFromData() { Expects(shown()); - const auto user = shownUser(); - auto &stories = user->owner().stories(); + const auto peer = shownPeer(); + auto &stories = peer->owner().stories(); const auto maybeStory = stories.lookup(_shown); - if (!maybeStory || !user->isSelf()) { + if (!maybeStory || !peer->isSelf()) { _viewsSlice = {}; } else { _viewsSlice = (*maybeStory)->viewsList(); diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.h b/Telegram/SourceFiles/media/stories/media_stories_controller.h index f932c40a6..9dc6ab657 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.h +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.h @@ -181,7 +181,7 @@ private: class Unsupported; using ChosenReaction = HistoryView::Reactions::ChosenReaction; struct StoriesList { - not_null user; + not_null peer; Data::StoriesIds ids; int total = 0; @@ -233,10 +233,10 @@ private: -> Fn; [[nodiscard]] bool shown() const; - [[nodiscard]] UserData *shownUser() const; + [[nodiscard]] PeerData *shownPeer() const; [[nodiscard]] int shownCount() const; [[nodiscard]] StoryId shownId(int index) const; - void rebuildFromContext(not_null user, FullStoryId storyId); + void rebuildFromContext(not_null peer, FullStoryId storyId); void checkMoveByDelta(); void loadMoreToList(); void preloadNext(); diff --git a/Telegram/SourceFiles/media/stories/media_stories_header.cpp b/Telegram/SourceFiles/media/stories/media_stories_header.cpp index 6b624c3d7..3440f4018 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_header.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_header.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "chat_helpers/compose/compose_show.h" -#include "data/data_user.h" +#include "data/data_peer.h" #include "media/stories/media_stories_controller.h" #include "lang/lang_keys.h" #include "ui/controls/userpic_button.h" @@ -268,7 +268,7 @@ void Header::show(HeaderData data) { if (_data == data) { return; } - const auto userChanged = !_data || (_data->user != data.user); + const auto peerChanged = !_data || (_data->peer != data.peer); _data = data; const auto updateInfoGeometry = [=] { if (_name && _date) { @@ -282,7 +282,7 @@ void Header::show(HeaderData data) { }; _tooltip = nullptr; _tooltipShown = false; - if (userChanged) { + if (peerChanged) { _volume = nullptr; _date = nullptr; _name = nullptr; @@ -298,12 +298,12 @@ void Header::show(HeaderData data) { _info = std::make_unique(raw); _info->setClickedCallback([=] { - _controller->uiShow()->show(PrepareShortInfoBox(_data->user)); + _controller->uiShow()->show(PrepareShortInfoBox(_data->peer)); }); _userpic = std::make_unique( raw, - data.user, + data.peer, st::storiesHeaderPhoto); _userpic->setAttribute(Qt::WA_TransparentForMouseEvents); _userpic->show(); @@ -313,9 +313,9 @@ void Header::show(HeaderData data) { _name = std::make_unique( raw, - rpl::single(data.user->isSelf() + rpl::single(data.peer->isSelf() ? tr::lng_stories_my_name(tr::now) - : data.user->name()), + : data.peer->name()), st::storiesHeaderName); _name->setAttribute(Qt::WA_TransparentForMouseEvents); _name->setOpacity(kNameOpacity); @@ -605,8 +605,8 @@ void Header::toggleTooltip(Tooltip type, bool show) { } const auto text = [&]() -> TextWithEntities { using Privacy = Data::StoryPrivacy; - const auto boldName = Ui::Text::Bold(_data->user->shortName()); - const auto self = _data->user->isSelf(); + const auto boldName = Ui::Text::Bold(_data->peer->shortName()); + const auto self = _data->peer->isSelf(); switch (type) { case Tooltip::SilentVideo: return { tr::lng_stories_about_silent(tr::now) }; diff --git a/Telegram/SourceFiles/media/stories/media_stories_header.h b/Telegram/SourceFiles/media/stories/media_stories_header.h index c10df3ec2..1da36174f 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_header.h +++ b/Telegram/SourceFiles/media/stories/media_stories_header.h @@ -31,7 +31,7 @@ class Controller; enum class PauseState; struct HeaderData { - not_null user; + not_null peer; TimeId date = 0; int fullIndex = 0; int fullCount = 0; diff --git a/Telegram/SourceFiles/media/stories/media_stories_reply.cpp b/Telegram/SourceFiles/media/stories/media_stories_reply.cpp index 48ee62d2e..6bc7b5413 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_reply.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_reply.cpp @@ -171,13 +171,13 @@ void ReplyArea::initGeometry() { } void ReplyArea::sendReaction(const Data::ReactionId &id) { - Expects(_data.user != nullptr); + Expects(_data.peer != nullptr); auto message = Api::MessageToSend(prepareSendAction({})); if (const auto emoji = id.emoji(); !emoji.isEmpty()) { message.textWithTags = { emoji }; } else if (const auto customId = id.custom()) { - const auto document = _data.user->owner().document(customId); + const auto document = _data.peer->owner().document(customId); if (const auto sticker = document->sticker()) { const auto text = sticker->alt; const auto id = Data::SerializeCustomEmojiId(customId); @@ -207,7 +207,7 @@ void ReplyArea::send( Api::SendOptions options, bool skipToast) { const auto error = GetErrorTextForSending( - _data.user, + _data.peer, { .topicRootId = MsgId(0), .text = &message.textWithTags, @@ -239,11 +239,11 @@ bool ReplyArea::sendExistingDocument( not_null document, Api::SendOptions options, std::optional localId) { - Expects(_data.user != nullptr); + Expects(_data.peer != nullptr); const auto show = _controller->uiShow(); const auto error = Data::RestrictionError( - _data.user, + _data.peer, ChatRestriction::SendStickers); if (error) { show->showToast(*error); @@ -269,11 +269,11 @@ void ReplyArea::sendExistingPhoto(not_null photo) { bool ReplyArea::sendExistingPhoto( not_null photo, Api::SendOptions options) { - Expects(_data.user != nullptr); + Expects(_data.peer != nullptr); const auto show = _controller->uiShow(); const auto error = Data::RestrictionError( - _data.user, + _data.peer, ChatRestriction::SendPhotos); if (error) { show->showToast(*error); @@ -348,7 +348,7 @@ bool ReplyArea::showSendingFilesError( const Ui::PreparedList &list, std::optional compress) const { const auto text = [&] { - const auto peer = _data.user; + const auto peer = _data.peer; const auto error = Data::FileRestrictionError(peer, list, compress); if (error) { return *error; @@ -383,29 +383,29 @@ bool ReplyArea::showSendingFilesError( } not_null ReplyArea::history() const { - Expects(_data.user != nullptr); + Expects(_data.peer != nullptr); - return _data.user->owner().history(_data.user); + return _data.peer->owner().history(_data.peer); } Api::SendAction ReplyArea::prepareSendAction( Api::SendOptions options) const { - Expects(_data.user != nullptr); + Expects(_data.peer != nullptr); auto result = Api::SendAction(history(), options); result.options.sendAs = _controls->sendAsPeer(); - result.replyTo.storyId = { .peer = _data.user->id, .story = _data.id }; + result.replyTo.storyId = { .peer = _data.peer->id, .story = _data.id }; return result; } void ReplyArea::chooseAttach( std::optional overrideSendImagesAsPhotos) { _chooseAttachRequest = false; - if (!_data.user) { + if (!_data.peer) { return; } - const auto user = not_null(_data.user); - if (const auto error = Data::AnyFileRestrictionError(user)) { + const auto peer = not_null(_data.peer); + if (const auto error = Data::AnyFileRestrictionError(peer)) { _controller->uiShow()->showToast(*error); return; } @@ -413,7 +413,7 @@ void ReplyArea::chooseAttach( const auto filter = (overrideSendImagesAsPhotos == true) ? FileDialog::ImagesOrAllFilter() : FileDialog::AllOrImagesFilter(); - const auto weak = make_weak(&_shownUserGuard); + const auto weak = make_weak(&_shownPeerGuard); const auto callback = [=](FileDialog::OpenResult &&result) { const auto guard = gsl::finally([&] { _choosingAttach = false; @@ -504,8 +504,8 @@ bool ReplyArea::confirmSendingFiles( .show = show, .list = std::move(list), .caption = _controls->getTextWithAppliedMarkdown(), - .limits = DefaultLimitsForPeer(_data.user), - .check = DefaultCheckForPeer(show, _data.user), + .limits = DefaultLimitsForPeer(_data.peer), + .check = DefaultCheckForPeer(show, _data.peer), .sendType = Api::SendType::Normal, .sendMenuType = SendMenu::Type::SilentOnly, .stOverride = &st::storiesComposeControls, @@ -533,7 +533,7 @@ void ReplyArea::sendingFilesConfirmed( auto groups = DivideByGroups( std::move(list), way, - _data.user->slowmodeApplied()); + _data.peer->slowmodeApplied()); const auto type = way.sendImagesAsPhotos() ? SendMediaType::Photo : SendMediaType::File; @@ -655,17 +655,17 @@ void ReplyArea::show( if (_data == data) { return; } - const auto userChanged = (_data.user != data.user); + const auto peerChanged = (_data.peer != data.peer); _data = data; - if (!userChanged) { - if (_data.user) { + if (!peerChanged) { + if (_data.peer) { _controls->clear(); } return; } - invalidate_weak_ptrs(&_shownUserGuard); - const auto user = data.user; - const auto history = user ? user->owner().history(user).get() : nullptr; + invalidate_weak_ptrs(&_shownPeerGuard); + const auto peer = data.peer; + const auto history = peer ? peer->owner().history(peer).get() : nullptr; _controls->setHistory({ .history = history, .liked = std::move( @@ -675,8 +675,8 @@ void ReplyArea::show( }), }); _controls->clear(); - const auto hidden = user && user->isSelf(); - const auto cant = !user || user->isServiceUser(); + const auto hidden = peer && peer->isSelf(); + const auto cant = !peer || peer->isServiceUser(); if (!hidden && !cant) { _controls->show(); } else { @@ -698,9 +698,9 @@ void ReplyArea::show( } Main::Session &ReplyArea::session() const { - Expects(_data.user != nullptr); + Expects(_data.peer != nullptr); - return _data.user->session(); + return _data.peer->session(); } bool ReplyArea::focused() const { diff --git a/Telegram/SourceFiles/media/stories/media_stories_reply.h b/Telegram/SourceFiles/media/stories/media_stories_reply.h index 34f40b856..bb5a58e70 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_reply.h +++ b/Telegram/SourceFiles/media/stories/media_stories_reply.h @@ -49,7 +49,7 @@ namespace Media::Stories { class Controller; struct ReplyAreaData { - UserData *user = nullptr; + PeerData *peer = nullptr; StoryId id = 0; friend inline auto operator<=>(ReplyAreaData, ReplyAreaData) = default; @@ -148,7 +148,7 @@ private: std::unique_ptr _cant; ReplyAreaData _data; - base::has_weak_ptr _shownUserGuard; + base::has_weak_ptr _shownPeerGuard; bool _chooseAttachRequest = false; rpl::variable _choosingAttach; diff --git a/Telegram/SourceFiles/media/stories/media_stories_share.cpp b/Telegram/SourceFiles/media/stories/media_stories_share.cpp index 413fbf3d1..91fc29002 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_share.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_share.cpp @@ -15,10 +15,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat_participant_status.h" #include "data/data_forum_topic.h" #include "data/data_histories.h" +#include "data/data_peer.h" #include "data/data_session.h" #include "data/data_stories.h" #include "data/data_thread.h" -#include "data/data_user.h" #include "history/history.h" #include "history/history_item_helpers.h" // GetErrorTextForSending. #include "history/view/history_view_context_menu.h" // CopyStoryLink. @@ -79,9 +79,7 @@ namespace Media::Stories { if (!story) { return; } - const auto user = story->peer()->asUser(); - Assert(user != nullptr); - + const auto peer = story->peer(); const auto error = [&] { for (const auto thread : result) { const auto error = GetErrorTextForSending( @@ -115,14 +113,16 @@ namespace Media::Stories { message.action.clearDraft = false; api->sendMessage(std::move(message)); } - const auto peer = thread->peer(); + const auto threadPeer = thread->peer(); const auto threadHistory = thread->owningHistory(); const auto randomId = base::RandomValue(); auto sendFlags = MTPmessages_SendMedia::Flags(0); if (action.replyTo) { sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to; } - const auto silentPost = ShouldSendSilent(peer, action.options); + const auto silentPost = ShouldSendSilent( + threadPeer, + action.options); if (silentPost) { sendFlags |= MTPmessages_SendMedia::Flag::f_silent; } @@ -140,23 +140,23 @@ namespace Media::Stories { randomId, Data::Histories::PrepareMessage( MTP_flags(sendFlags), - peer->input, + threadPeer->input, Data::Histories::ReplyToPlaceholder(), - MTP_inputMediaStory( - user->inputUser, - MTP_int(id.story)), + MTP_inputMediaStory(peer->input, MTP_int(id.story)), MTPstring(), MTP_long(randomId), MTPReplyMarkup(), MTPVector(), MTP_int(action.options.scheduled), MTP_inputPeerEmpty() - ), [=](const MTPUpdates &result, const MTP::Response &response) { - done(); - }, [=](const MTP::Error &error, const MTP::Response &response) { - api->sendMessageFail(error, peer, randomId); - done(); - }); + ), [=]( + const MTPUpdates &result, + const MTP::Response &response) { + done(); + }, [=](const MTP::Error &error, const MTP::Response &response) { + api->sendMessageFail(error, threadPeer, randomId); + done(); + }); ++state->requests; } }; diff --git a/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp b/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp index 791c8235f..f314a255c 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_sibling.cpp @@ -11,10 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_document.h" #include "data/data_document_media.h" #include "data/data_file_origin.h" +#include "data/data_peer.h" #include "data/data_photo.h" #include "data/data_photo_media.h" #include "data/data_session.h" -#include "data/data_user.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "media/stories/media_stories_controller.h" @@ -244,8 +244,8 @@ Sibling::Sibling( const Data::StoriesSource &source, StoryId suggestedId) : _controller(controller) -, _id{ source.user->id, LookupShownId(source, suggestedId) } -, _peer(source.user) { +, _id{ source.peer->id, LookupShownId(source, suggestedId) } +, _peer(source.peer) { checkStory(); _goodShown.stop(); } @@ -305,7 +305,7 @@ bool Sibling::shows( const Data::StoriesSource &source, StoryId suggestedId) const { const auto fullId = FullStoryId{ - source.user->id, + source.peer->id, LookupShownId(source, suggestedId), }; return (_id == fullId); diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 42471d70b..93ee43704 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -42,7 +42,7 @@ inputMediaInvoice#8eb5a6d5 flags:# title:string description:string photo:flags.0 inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia; inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector solution:flags.1?string solution_entities:flags.1?Vector = InputMedia; inputMediaDice#e66fbf7b emoticon:string = InputMedia; -inputMediaStory#9a86b58f user_id:InputUser id:int = InputMedia; +inputMediaStory#89fdd778 peer:InputPeer id:int = InputMedia; inputChatPhotoEmpty#1ca48f57 = InputChatPhoto; inputChatUploadedPhoto#bdcdaec0 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.3?VideoSize = InputChatPhoto; @@ -96,11 +96,11 @@ userStatusLastMonth#77ebc742 = UserStatus; chatEmpty#29562865 id:long = Chat; chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat; chatForbidden#6592a1a7 id:long title:string = Chat; -channel#83259464 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector = Chat; +channel#94f592db flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector stories_max_id:flags2.4?int = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions = ChatFull; -channelFull#f2355507 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull; +channelFull#723027bd flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories = ChatFull; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; @@ -129,7 +129,7 @@ messageMediaInvoice#f6a548d3 flags:# shipping_address_requested:flags.1?true tes messageMediaGeoLive#b940c666 flags:# geo:GeoPoint heading:flags.0?int period:int proximity_notification_radius:flags.1?int = MessageMedia; messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia; messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia; -messageMediaStory#cbb20d88 flags:# via_mention:flags.1?true user_id:long id:int story:flags.0?StoryItem = MessageMedia; +messageMediaStory#68cb6283 flags:# via_mention:flags.1?true peer:Peer id:int story:flags.0?StoryItem = MessageMedia; messageActionEmpty#b6aef7b0 = MessageAction; messageActionChatCreate#bd47cbad title:string users:Vector = MessageAction; @@ -221,7 +221,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason; -userFull#4fe1cc86 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector wallpaper:flags.24?WallPaper stories:flags.25?UserStories = UserFull; +userFull#b9b12c6c flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector wallpaper:flags.24?WallPaper stories:flags.25?PeerStories = UserFull; contact#145ade0b user_id:long mutual:Bool = Contact; @@ -383,11 +383,11 @@ updateChannelPinnedTopics#fe198602 flags:# channel_id:long order:flags.0?Vector< updateUser#20529438 user_id:long = Update; updateAutoSaveSettings#ec05b097 = Update; updateGroupInvitePrivacyForbidden#ccf08ad6 user_id:long = Update; -updateStory#205a4133 user_id:long story:StoryItem = Update; -updateReadStories#feb5345a user_id:long max_id:int = Update; +updateStory#75b3b798 peer:Peer story:StoryItem = Update; +updateReadStories#f74e932b peer:Peer max_id:int = Update; updateStoryID#1bf335b9 id:int random_id:long = Update; updateStoriesStealthMode#2c084dc1 stealth_mode:StoriesStealthMode = Update; -updateSentStoryReaction#e3a73d20 user_id:long story_id:int reaction:Reaction = Update; +updateSentStoryReaction#7d627683 peer:Peer story_id:int reaction:Reaction = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -843,7 +843,7 @@ dataJSON#7d748d04 data:string = DataJSON; labeledPrice#cb296bf8 label:string amount:long = LabeledPrice; -invoice#3e85a91b flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true recurring:flags.9?true currency:string prices:Vector max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector recurring_terms_url:flags.9?string = Invoice; +invoice#5db95a15 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true recurring:flags.9?true currency:string prices:Vector max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector terms_url:flags.10?string = Invoice; paymentCharge#ea02c27e id:string provider_charge_id:string = PaymentCharge; @@ -1123,7 +1123,7 @@ chatOnlines#f041e250 onlines:int = ChatOnlines; statsURL#47a971e0 url:string = StatsURL; -chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true other:flags.12?true manage_topics:flags.13?true = ChatAdminRights; +chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true other:flags.12?true manage_topics:flags.13?true post_stories:flags.14?true edit_stories:flags.15?true delete_stories:flags.16?true = ChatAdminRights; chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true manage_topics:flags.18?true send_photos:flags.19?true send_videos:flags.20?true send_roundvideos:flags.21?true send_audios:flags.22?true send_voices:flags.23?true send_docs:flags.24?true send_plain:flags.25?true until_date:int = ChatBannedRights; @@ -1198,7 +1198,7 @@ inputThemeSettings#8fde504f flags:# message_colors_animated:flags.2?true base_th themeSettings#fa58b6d4 flags:# message_colors_animated:flags.2?true base_theme:BaseTheme accent_color:int outbox_accent_color:flags.3?int message_colors:flags.0?Vector wallpaper:flags.1?WallPaper = ThemeSettings; webPageAttributeTheme#54b56617 flags:# documents:flags.0?Vector settings:flags.1?ThemeSettings = WebPageAttribute; -webPageAttributeStory#939a4671 flags:# user_id:long id:int story:flags.0?StoryItem = WebPageAttribute; +webPageAttributeStory#2e94c3e7 flags:# peer:Peer id:int story:flags.0?StoryItem = WebPageAttribute; messages.votesList#4899484e flags:# count:int votes:Vector chats:Vector users:Vector next_offset:flags.0?string = messages.VotesList; @@ -1529,20 +1529,16 @@ messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector date:int = Mess sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage; -storyViews#c64c0b97 flags:# has_viewers:flags.1?true views_count:int reactions_count:int recent_viewers:flags.0?Vector = StoryViews; +storyViews#8d595cd6 flags:# has_viewers:flags.1?true views_count:int forwards_count:flags.2?int reactions:flags.3?Vector reactions_count:flags.4?int recent_viewers:flags.0?Vector = StoryViews; storyItemDeleted#51e6ee4f id:int = StoryItem; storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem; -storyItem#44c457ce flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector media:MessageMedia media_areas:flags.14?Vector privacy:flags.2?Vector views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem; - -userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector = UserStories; +storyItem#44c457ce flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true out:flags.16?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector media:MessageMedia media_areas:flags.14?Vector privacy:flags.2?Vector views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem; stories.allStoriesNotModified#1158fe3e flags:# state:string stealth_mode:StoriesStealthMode = stories.AllStories; -stories.allStories#519d899e flags:# has_more:flags.0?true count:int state:string user_stories:Vector users:Vector stealth_mode:StoriesStealthMode = stories.AllStories; +stories.allStories#6efc5e81 flags:# has_more:flags.0?true count:int state:string peer_stories:Vector chats:Vector users:Vector stealth_mode:StoriesStealthMode = stories.AllStories; -stories.stories#4fe57df1 count:int stories:Vector users:Vector = stories.Stories; - -stories.userStories#37a6ff5f stories:UserStories users:Vector = stories.UserStories; +stories.stories#5dd8c3c8 count:int stories:Vector chats:Vector users:Vector = stories.Stories; storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView; @@ -1562,6 +1558,20 @@ mediaAreaCoordinates#3d1ea4e x:double y:double w:double h:double rotation:double mediaAreaVenue#be82db9c coordinates:MediaAreaCoordinates geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MediaArea; inputMediaAreaVenue#b282217f coordinates:MediaAreaCoordinates query_id:long result_id:string = MediaArea; mediaAreaGeoPoint#df8b3b22 coordinates:MediaAreaCoordinates geo:GeoPoint = MediaArea; +mediaAreaSuggestedReaction#14455871 flags:# dark:flags.0?true flipped:flags.1?true coordinates:MediaAreaCoordinates reaction:Reaction = MediaArea; + +peerStories#9a35e999 flags:# peer:Peer max_read_id:flags.0?int stories:Vector = PeerStories; + +stories.peerStories#cae68768 stories:PeerStories chats:Vector users:Vector = stories.PeerStories; + +stories.boostsStatus#66ea1fef flags:# my_boost:flags.2?true level:int current_level_boosts:int boosts:int next_level_boosts:flags.0?int premium_audience:flags.1?StatsPercentValue = stories.BoostsStatus; + +stories.canApplyBoostOk#c3173587 = stories.CanApplyBoostResult; +stories.canApplyBoostReplace#712c4655 current_boost:Peer chats:Vector = stories.CanApplyBoostResult; + +booster#e9e6380 user_id:long expires:int = Booster; + +stories.boostersList#f3dd3d1d flags:# count:int boosters:Vector next_offset:flags.0?string users:Vector = stories.BoostersList; ---functions--- @@ -1688,7 +1698,6 @@ account.invalidateSignInCodes#ca8ae8ba codes:Vector = Bool; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#b60f5918 id:InputUser = users.UserFull; users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector = Bool; -users.getStoriesMaxIDs#ca1cb9ab id:Vector = Vector; contacts.getContactIDs#7adc669d hash:long = Vector; contacts.getStatuses#c4a353ee = Vector; @@ -1714,7 +1723,6 @@ contacts.resolvePhone#8af94344 phone:string = contacts.ResolvedPeer; contacts.exportContactToken#f8654027 = ExportedContactToken; contacts.importContactToken#13005788 token:string = User; contacts.editCloseFriends#ba6705f0 id:Vector = Bool; -contacts.toggleStoriesHidden#753fb865 id:InputUser hidden:Bool = Bool; contacts.setBlocked#94c65c76 flags:# my_stories_from:flags.0?true id:Vector limit:int = Bool; messages.getMessages#63c66506 id:Vector = messages.Messages; @@ -2103,23 +2111,30 @@ chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool; chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector; chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector = Updates; -stories.canSendStory#b100d45d = Bool; -stories.sendStory#d455fcec flags:# pinned:flags.2?true noforwards:flags.4?true media:InputMedia media_areas:flags.5?Vector caption:flags.0?string entities:flags.1?Vector privacy_rules:Vector random_id:long period:flags.3?int = Updates; -stories.editStory#a9b91ae4 flags:# id:int media:flags.0?InputMedia media_areas:flags.3?Vector caption:flags.1?string entities:flags.1?Vector privacy_rules:flags.2?Vector = Updates; -stories.deleteStories#b5d501d7 id:Vector = Vector; -stories.togglePinned#51602944 id:Vector pinned:Bool = Vector; +stories.canSendStory#c7dfdfdd peer:InputPeer = Bool; +stories.sendStory#bcb73644 flags:# pinned:flags.2?true noforwards:flags.4?true peer:InputPeer media:InputMedia media_areas:flags.5?Vector caption:flags.0?string entities:flags.1?Vector privacy_rules:Vector random_id:long period:flags.3?int = Updates; +stories.editStory#b583ba46 flags:# peer:InputPeer id:int media:flags.0?InputMedia media_areas:flags.3?Vector caption:flags.1?string entities:flags.1?Vector privacy_rules:flags.2?Vector = Updates; +stories.deleteStories#ae59db5f peer:InputPeer id:Vector = Vector; +stories.togglePinned#9a75a1ef peer:InputPeer id:Vector pinned:Bool = Vector; stories.getAllStories#eeb0d625 flags:# next:flags.1?true hidden:flags.2?true state:flags.0?string = stories.AllStories; -stories.getUserStories#96d528e0 user_id:InputUser = stories.UserStories; -stories.getPinnedStories#b471137 user_id:InputUser offset_id:int limit:int = stories.Stories; -stories.getStoriesArchive#1f5bc5d2 offset_id:int limit:int = stories.Stories; -stories.getStoriesByID#6a15cf46 user_id:InputUser id:Vector = stories.Stories; +stories.getPinnedStories#5821a5dc peer:InputPeer offset_id:int limit:int = stories.Stories; +stories.getStoriesArchive#b4352016 peer:InputPeer offset_id:int limit:int = stories.Stories; +stories.getStoriesByID#5774ca74 peer:InputPeer id:Vector = stories.Stories; stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool; -stories.getAllReadUserStories#729c562c = Updates; -stories.readStories#edc5105b user_id:InputUser max_id:int = Vector; -stories.incrementStoryViews#22126127 user_id:InputUser id:Vector = Bool; -stories.getStoryViewsList#f95f61a4 flags:# just_contacts:flags.0?true reactions_first:flags.2?true q:flags.1?string id:int offset:string limit:int = stories.StoryViewsList; -stories.getStoriesViews#9a75d6a6 id:Vector = stories.StoryViews; -stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink; -stories.report#c95be06a user_id:InputUser id:Vector reason:ReportReason message:string = Bool; +stories.readStories#a556dac8 peer:InputPeer max_id:int = Vector; +stories.incrementStoryViews#b2028afb peer:InputPeer id:Vector = Bool; +stories.getStoryViewsList#7ed23c57 flags:# just_contacts:flags.0?true reactions_first:flags.2?true peer:InputPeer q:flags.1?string id:int offset:string limit:int = stories.StoryViewsList; +stories.getStoriesViews#28e16cc8 peer:InputPeer id:Vector = stories.StoryViews; +stories.exportStoryLink#7b8def20 peer:InputPeer id:int = ExportedStoryLink; +stories.report#1923fa8c peer:InputPeer id:Vector reason:ReportReason message:string = Bool; stories.activateStealthMode#57bbd166 flags:# past:flags.0?true future:flags.1?true = Updates; -stories.sendReaction#49aaa9b3 flags:# add_to_recent:flags.0?true user_id:InputUser story_id:int reaction:Reaction = Updates; +stories.sendReaction#7fd736b2 flags:# add_to_recent:flags.0?true peer:InputPeer story_id:int reaction:Reaction = Updates; +stories.getPeerStories#2c4ada50 peer:InputPeer = stories.PeerStories; +stories.getAllReadPeerStories#9b5ae7f9 = Updates; +stories.getPeerMaxIDs#535983c3 id:Vector = Vector; +stories.getChatsToSend#a56a8b60 = messages.Chats; +stories.togglePeerStoriesHidden#bd0415c4 peer:InputPeer hidden:Bool = Bool; +stories.getBoostsStatus#4c449472 peer:InputPeer = stories.BoostsStatus; +stories.getBoostersList#337ef980 peer:InputPeer offset:string limit:int = stories.BoostersList; +stories.canApplyBoost#db05c1bd peer:InputPeer = stories.CanApplyBoostResult; +stories.applyBoost#f29d7c2b peer:InputPeer = Bool; diff --git a/Telegram/SourceFiles/mtproto/scheme/layer.tl b/Telegram/SourceFiles/mtproto/scheme/layer.tl index 7c0a0f612..dcdebd9f5 100644 --- a/Telegram/SourceFiles/mtproto/scheme/layer.tl +++ b/Telegram/SourceFiles/mtproto/scheme/layer.tl @@ -1 +1 @@ -// LAYER 163 +// LAYER 164 diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index d92eeea34..937358f1f 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -529,10 +529,12 @@ void CheckoutProcess::panelSubmit() { } else if (!method.newCredentials && method.savedCredentialsIndex >= method.savedCredentials.size()) { editPaymentMethod(); - } else if (invoice.isRecurring && !_form->details().termsAccepted) { + } else if (!invoice.termsUrl.isEmpty() + && !_form->details().termsAccepted) { _panel->requestTermsAcceptance( _form->details().termsBotUsername, - invoice.recurringTermsUrl); + invoice.termsUrl, + invoice.isRecurring); } else { RegisterPaymentStart(this, { _form->invoice().cover.title }); _submitState = SubmitState::Finishing; diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index b10ee9b4a..62682b9db 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -384,8 +384,7 @@ void Form::processInvoice(const MTPDinvoice &data) { .isFlexible = data.is_flexible(), .isTest = data.is_test(), - .recurringTermsUrl = qs( - data.vrecurring_terms_url().value_or_empty()), + .termsUrl = qs(data.vterms_url().value_or_empty()), .phoneSentToProvider = data.is_phone_to_provider(), .emailSentToProvider = data.is_email_to_provider(), diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.cpp b/Telegram/SourceFiles/payments/ui/payments_panel.cpp index 541683c64..cb36c5887 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_panel.cpp @@ -704,15 +704,18 @@ void Panel::showWarning(const QString &bot, const QString &provider) { void Panel::requestTermsAcceptance( const QString &username, - const QString &url) { + const QString &url, + bool recurring) { showBox(Box([=](not_null box) { box->setTitle(tr::lng_payments_terms_title()); box->addRow(object_ptr( box.get(), - tr::lng_payments_terms_text( - lt_bot, - rpl::single(Ui::Text::Bold('@' + username)), - Ui::Text::WithEntities), + (recurring + ? tr::lng_payments_terms_text + : tr::lng_payments_terms_text_once)( + lt_bot, + rpl::single(Ui::Text::Bold('@' + username)), + Ui::Text::WithEntities), st::boxLabel)); const auto update = std::make_shared>(); auto checkView = std::make_unique( diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.h b/Telegram/SourceFiles/payments/ui/payments_panel.h index 1c97355da..6136dace4 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel.h @@ -78,7 +78,10 @@ public: void askSetPassword(); void showCloseConfirm(); void showWarning(const QString &bot, const QString &provider); - void requestTermsAcceptance(const QString &username, const QString &url); + void requestTermsAcceptance( + const QString &username, + const QString &url, + bool recurring); bool showWebview( const QString &url, diff --git a/Telegram/SourceFiles/payments/ui/payments_panel_data.h b/Telegram/SourceFiles/payments/ui/payments_panel_data.h index 40d91f44e..1021e7b56 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel_data.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel_data.h @@ -56,7 +56,7 @@ struct Invoice { bool isTest = false; QString provider; - QString recurringTermsUrl; + QString termsUrl; bool phoneSentToProvider = false; bool emailSentToProvider = false; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 3a45ff8f7..d67e7d8e0 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -2557,19 +2557,17 @@ void SessionController::openPeerStories( if (const auto source = stories.source(peerId)) { if (const auto idDates = source->toOpen()) { openPeerStory( - source->user, + source->peer, idDates.id, (list ? StoriesContext{ *list } : StoriesContext{ StoriesContextPeer() })); } - } else if (const auto userId = peerToUser(peerId)) { - if (const auto user = session().data().userLoaded(userId)) { - const auto done = crl::guard(&_storyOpenGuard, [=] { - openPeerStories(peerId, list); - }); - stories.requestUserStories(user, done); - } + } else if (const auto peer = session().data().peerLoaded(peerId)) { + const auto done = crl::guard(&_storyOpenGuard, [=] { + openPeerStories(peerId, list); + }); + stories.requestPeerStories(peer, done); } }