mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Update API scheme to layer 164.
This commit is contained in:
parent
1bde096417
commit
d5b429e910
37 changed files with 586 additions and 358 deletions
|
@ -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";
|
||||
|
|
|
@ -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<MTPint>(1, MTP_int(id)),
|
||||
ReasonToTL(reason),
|
||||
MTP_string(comment)
|
||||
|
|
|
@ -789,7 +789,7 @@ QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> 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<MTPint>(1, MTP_int(data.storyId))));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
request(MTPstories_GetStoriesByID(
|
||||
_session->data().peer(data.peerId)->input,
|
||||
MTP_vector<MTPint>(1, MTP_int(data.storyId))));
|
||||
}, [&](v::null_t) {
|
||||
fail();
|
||||
});
|
||||
|
|
|
@ -51,13 +51,14 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
|
|||
}
|
||||
|
||||
[[nodiscard]] auto NestedRestrictionLabelsList(
|
||||
Data::RestrictionsSetOptions options) {
|
||||
Data::RestrictionsSetOptions options)
|
||||
-> std::vector<NestedEditFlagsLabels<ChatRestrictions>> {
|
||||
using Flag = ChatRestriction;
|
||||
|
||||
auto first = std::vector<RestrictionLabel>{
|
||||
{ Flag::SendOther, tr::lng_rights_chat_send_text(tr::now) },
|
||||
};
|
||||
auto inner = std::vector<RestrictionLabel>{
|
||||
auto media = std::vector<RestrictionLabel>{
|
||||
{ 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<NestedEditFlagsLabels<ChatRestrictions>>{
|
||||
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<NestedEditFlagsLabels<ChatAdminRights>> {
|
||||
using Flag = ChatAdminRight;
|
||||
|
||||
if (options.isGroup) {
|
||||
auto result = std::vector<AdminRightLabel>{
|
||||
{ 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<AdminRightLabel>{
|
||||
{ Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) },
|
||||
};
|
||||
auto messages = std::vector<AdminRightLabel>{
|
||||
{ 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<AdminRightLabel>{
|
||||
{ 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<AdminRightLabel>{
|
||||
{ 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<RestrictionLabel> RestrictionLabels(
|
|||
|
||||
std::vector<AdminRightLabel> AdminRightLabels(
|
||||
Data::AdminRightsSetOptions options) {
|
||||
using Flag = ChatAdminRight;
|
||||
|
||||
if (options.isGroup) {
|
||||
auto result = std::vector<AdminRightLabel>{
|
||||
{ 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<AdminRightLabel>();
|
||||
for (const auto &[_, r] : NestedAdminRightLabels(options)) {
|
||||
result.insert(result.end(), r.begin(), r.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
||||
|
@ -1107,7 +1132,7 @@ EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
|
|||
rights,
|
||||
{
|
||||
.header = std::move(header),
|
||||
.labels = { { std::nullopt, AdminRightLabels(options) } },
|
||||
.labels = NestedAdminRightLabels(options),
|
||||
.disabledMessages = std::move(disabledMessages),
|
||||
});
|
||||
result.widget = std::move(widget);
|
||||
|
|
|
@ -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<MTPForumTopic> &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(),
|
||||
|
|
|
@ -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<ChannelDataFlag>;
|
||||
|
@ -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<PeerData*> 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<ChatAdminRight>;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Data::WallPaper> 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();
|
||||
|
||||
|
|
|
@ -909,7 +909,17 @@ not_null<PeerData*> 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::Stories::PeerSourceState>()
|
||||
: data.is_stories_unavailable()
|
||||
? Data::Stories::PeerSourceState()
|
||||
: !data.vstories_max_id()
|
||||
? std::optional<Data::Stories::PeerSourceState>()
|
||||
: 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<PeerData*> 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;
|
||||
|
|
|
@ -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<PeerData*> peer, const MTPUserStories *data) {
|
||||
void Stories::apply(not_null<PeerData*> 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<UserData*> user,
|
||||
void Stories::requestPeerStories(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> 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<MTPint>(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<Ui::Show> 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<PeerData*> 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<MTPint>(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<FullStoryId> &ids) {
|
|||
if (!list.empty()) {
|
||||
const auto api = &_owner->session().api();
|
||||
api->request(MTPstories_DeleteStories(
|
||||
MTP_inputPeerSelf(),
|
||||
MTP_vector<MTPint>(list)
|
||||
)).done([=](const MTPVector<MTPint> &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<MTPint>(list),
|
||||
MTP_bool(pinned)
|
||||
)).done([=](const MTPVector<MTPint> &result) {
|
||||
|
@ -1608,7 +1607,7 @@ std::optional<Stories::PeerSourceState> 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<PeerData*> peer) {
|
||||
void Stories::updatePeerStoriesState(not_null<PeerData*> 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) {
|
||||
|
|
|
@ -52,7 +52,7 @@ struct StoriesSourceInfo {
|
|||
};
|
||||
|
||||
struct StoriesSource {
|
||||
not_null<UserData*> user;
|
||||
not_null<PeerData*> peer;
|
||||
base::flat_set<StoryIdDates> 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<PeerData*> peer, const MTPUserStories *data);
|
||||
void apply(not_null<PeerData*> 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<UserData*> user,
|
||||
void requestPeerStories(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> done = nullptr);
|
||||
|
||||
void savedStateChanged(not_null<Story*> story);
|
||||
|
@ -255,7 +255,7 @@ private:
|
|||
int viewer = 0;
|
||||
};
|
||||
|
||||
void parseAndApply(const MTPUserStories &stories);
|
||||
void parseAndApply(const MTPPeerStories &stories);
|
||||
[[nodiscard]] Story *parseAndApply(
|
||||
not_null<PeerData*> peer,
|
||||
const MTPDstoryItem &data,
|
||||
|
@ -269,7 +269,7 @@ private:
|
|||
const QVector<MTPStoryItem> &list);
|
||||
void sendResolveRequests();
|
||||
void finalizeResolve(FullStoryId id);
|
||||
void updateUserStoriesState(not_null<PeerData*> peer);
|
||||
void updatePeerStoriesState(not_null<PeerData*> peer);
|
||||
|
||||
void applyDeleted(FullStoryId id);
|
||||
void applyExpired(FullStoryId id);
|
||||
|
@ -360,8 +360,8 @@ private:
|
|||
base::Timer _markReadTimer;
|
||||
base::flat_set<PeerId> _markReadRequests;
|
||||
base::flat_map<
|
||||
not_null<UserData*>,
|
||||
std::vector<Fn<void()>>> _requestingUserStories;
|
||||
not_null<PeerData*>,
|
||||
std::vector<Fn<void()>>> _requestingPeerStories;
|
||||
|
||||
base::flat_map<PeerId, base::flat_set<StoryId>> _incrementViewsPending;
|
||||
base::Timer _incrementViewsTimer;
|
||||
|
@ -381,7 +381,7 @@ private:
|
|||
|
||||
base::flat_map<PeerId, StoryId> _readTill;
|
||||
base::flat_set<FullStoryId> _pendingReadTillItems;
|
||||
base::flat_map<not_null<PeerData*>, StoryId> _pendingUserStateMaxId;
|
||||
base::flat_map<not_null<PeerData*>, StoryId> _pendingPeerStateMaxId;
|
||||
mtpRequestId _readTillsRequestId = 0;
|
||||
bool _readTillReceived = false;
|
||||
|
||||
|
|
|
@ -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<SuggestedReaction> {
|
||||
auto result = std::optional<SuggestedReaction>();
|
||||
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<StoryLocation> &Story::locations() const {
|
|||
return _locations;
|
||||
}
|
||||
|
||||
const std::vector<SuggestedReaction> &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<not_null<PeerData*>>();
|
||||
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<StoryLocation>();
|
||||
auto suggestedReactions = std::vector<SuggestedReaction>();
|
||||
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())
|
||||
|
|
|
@ -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<StoryLocation> &locations() const;
|
||||
[[nodiscard]] auto suggestedReactions() const
|
||||
-> const std::vector<SuggestedReaction> &;
|
||||
|
||||
void applyChanges(
|
||||
StoryMedia media,
|
||||
|
@ -178,10 +192,12 @@ private:
|
|||
TextWithEntities _caption;
|
||||
std::vector<not_null<PeerData*>> _recentViewers;
|
||||
std::vector<StoryLocation> _locations;
|
||||
std::vector<SuggestedReaction> _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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -134,7 +134,7 @@ private:
|
|||
const not_null<Data::Stories*> _data;
|
||||
const Data::StorySourcesList _list;
|
||||
base::flat_map<
|
||||
not_null<UserData*>,
|
||||
not_null<PeerData*>,
|
||||
std::shared_ptr<Thumbnail>> _userpics;
|
||||
|
||||
};
|
||||
|
@ -338,20 +338,20 @@ Content State::next() {
|
|||
Assert(source != nullptr);
|
||||
|
||||
auto userpic = std::shared_ptr<Thumbnail>();
|
||||
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;
|
||||
|
|
|
@ -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<MTPint>(1, MTP_int(origin.storyId))
|
||||
)).fail([=](const MTP::Error &error) {
|
||||
_fileProcess->requestId = 0;
|
||||
|
|
|
@ -287,7 +287,7 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
|
|||
media.vvalue().v);
|
||||
}, [&](const MTPDmessageMediaStory &media) -> Result {
|
||||
return std::make_unique<Data::MediaStory>(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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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*> controller, not_null<UserData*> user);
|
||||
Unsupported(not_null<Controller*> controller, not_null<PeerData*> peer);
|
||||
|
||||
private:
|
||||
void setup(not_null<UserData*> user);
|
||||
void setup(not_null<PeerData*> peer);
|
||||
|
||||
const not_null<Controller*> _controller;
|
||||
std::unique_ptr<Ui::RpWidget> _bg;
|
||||
|
@ -206,13 +206,13 @@ void Controller::PhotoPlayback::callback() {
|
|||
|
||||
Controller::Unsupported::Unsupported(
|
||||
not_null<Controller*> controller,
|
||||
not_null<UserData*> user)
|
||||
not_null<PeerData*> peer)
|
||||
: _controller(controller)
|
||||
, _bgRound(st::storiesRadius, st::storiesComposeBg) {
|
||||
setup(user);
|
||||
setup(peer);
|
||||
}
|
||||
|
||||
void Controller::Unsupported::setup(not_null<UserData*> user) {
|
||||
void Controller::Unsupported::setup(not_null<PeerData*> peer) {
|
||||
const auto wrap = _controller->wrap();
|
||||
|
||||
_bg = std::make_unique<Ui::RpWidget>(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<UserData*> user,
|
||||
not_null<PeerData*> peer,
|
||||
FullStoryId storyId) {
|
||||
using namespace Data;
|
||||
|
||||
auto &stories = user->owner().stories();
|
||||
auto &stories = peer->owner().stories();
|
||||
auto list = std::optional<StoriesList>();
|
||||
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<FullStoryId>();
|
||||
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<Unsupported>(this, user);
|
||||
_unsupported = std::make_unique<Unsupported>(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<void(Data::StoryViews)> 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();
|
||||
|
|
|
@ -181,7 +181,7 @@ private:
|
|||
class Unsupported;
|
||||
using ChosenReaction = HistoryView::Reactions::ChosenReaction;
|
||||
struct StoriesList {
|
||||
not_null<UserData*> user;
|
||||
not_null<PeerData*> peer;
|
||||
Data::StoriesIds ids;
|
||||
int total = 0;
|
||||
|
||||
|
@ -233,10 +233,10 @@ private:
|
|||
-> Fn<void(Data::StoryViews)>;
|
||||
|
||||
[[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<UserData*> user, FullStoryId storyId);
|
||||
void rebuildFromContext(not_null<PeerData*> peer, FullStoryId storyId);
|
||||
void checkMoveByDelta();
|
||||
void loadMoreToList();
|
||||
void preloadNext();
|
||||
|
|
|
@ -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<Ui::AbstractButton>(raw);
|
||||
_info->setClickedCallback([=] {
|
||||
_controller->uiShow()->show(PrepareShortInfoBox(_data->user));
|
||||
_controller->uiShow()->show(PrepareShortInfoBox(_data->peer));
|
||||
});
|
||||
|
||||
_userpic = std::make_unique<Ui::UserpicButton>(
|
||||
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<Ui::FlatLabel>(
|
||||
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) };
|
||||
|
|
|
@ -31,7 +31,7 @@ class Controller;
|
|||
enum class PauseState;
|
||||
|
||||
struct HeaderData {
|
||||
not_null<UserData*> user;
|
||||
not_null<PeerData*> peer;
|
||||
TimeId date = 0;
|
||||
int fullIndex = 0;
|
||||
int fullCount = 0;
|
||||
|
|
|
@ -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<DocumentData*> document,
|
||||
Api::SendOptions options,
|
||||
std::optional<MsgId> 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<PhotoData*> photo) {
|
|||
bool ReplyArea::sendExistingPhoto(
|
||||
not_null<PhotoData*> 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<bool> 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<History*> 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<bool> 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 {
|
||||
|
|
|
@ -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> _cant;
|
||||
|
||||
ReplyAreaData _data;
|
||||
base::has_weak_ptr _shownUserGuard;
|
||||
base::has_weak_ptr _shownPeerGuard;
|
||||
bool _chooseAttachRequest = false;
|
||||
rpl::variable<bool> _choosingAttach;
|
||||
|
||||
|
|
|
@ -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<uint64>();
|
||||
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<MTPmessages_SendMedia>(
|
||||
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<MTPMessageEntity>(),
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = 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<RestrictionReason> 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<Username> = 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<RestrictionReason> 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<Username> 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<BotInfo> 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<long> 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<BotInfo> 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<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> 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<BotInfo> 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<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> 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<long> = 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<PremiumGiftOption> 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<PremiumGiftOption> 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<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> 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<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> 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<int> wallpaper:flags.1?WallPaper = ThemeSettings;
|
||||
|
||||
webPageAttributeTheme#54b56617 flags:# documents:flags.0?Vector<Document> 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<MessagePeerVote> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
|
||||
|
||||
|
@ -1529,20 +1529,16 @@ messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector<bytes> 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<long> = StoryViews;
|
||||
storyViews#8d595cd6 flags:# has_viewers:flags.1?true views_count:int forwards_count:flags.2?int reactions:flags.3?Vector<ReactionCount> reactions_count:flags.4?int recent_viewers:flags.0?Vector<long> = 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<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem;
|
||||
|
||||
userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = 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<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> 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<UserStories> users:Vector<User> stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
stories.allStories#6efc5e81 flags:# has_more:flags.0?true count:int state:string peer_stories:Vector<PeerStories> chats:Vector<Chat> users:Vector<User> stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
|
||||
stories.stories#4fe57df1 count:int stories:Vector<StoryItem> users:Vector<User> = stories.Stories;
|
||||
|
||||
stories.userStories#37a6ff5f stories:UserStories users:Vector<User> = stories.UserStories;
|
||||
stories.stories#5dd8c3c8 count:int stories:Vector<StoryItem> chats:Vector<Chat> users:Vector<User> = 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<StoryItem> = PeerStories;
|
||||
|
||||
stories.peerStories#cae68768 stories:PeerStories chats:Vector<Chat> users:Vector<User> = 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<Chat> = stories.CanApplyBoostResult;
|
||||
|
||||
booster#e9e6380 user_id:long expires:int = Booster;
|
||||
|
||||
stories.boostersList#f3dd3d1d flags:# count:int boosters:Vector<Booster> next_offset:flags.0?string users:Vector<User> = stories.BoostersList;
|
||||
|
||||
---functions---
|
||||
|
||||
|
@ -1688,7 +1698,6 @@ account.invalidateSignInCodes#ca8ae8ba codes:Vector<string> = Bool;
|
|||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
|
||||
users.getStoriesMaxIDs#ca1cb9ab id:Vector<InputUser> = Vector<int>;
|
||||
|
||||
contacts.getContactIDs#7adc669d hash:long = Vector<int>;
|
||||
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
||||
|
@ -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<long> = Bool;
|
||||
contacts.toggleStoriesHidden#753fb865 id:InputUser hidden:Bool = Bool;
|
||||
contacts.setBlocked#94c65c76 flags:# my_stories_from:flags.0?true id:Vector<InputPeer> limit:int = Bool;
|
||||
|
||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
||||
|
@ -2103,23 +2111,30 @@ chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool;
|
|||
chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector<Peer>;
|
||||
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = Updates;
|
||||
|
||||
stories.canSendStory#b100d45d = Bool;
|
||||
stories.sendStory#d455fcec flags:# pinned:flags.2?true noforwards:flags.4?true media:InputMedia media_areas:flags.5?Vector<MediaArea> caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> random_id:long period:flags.3?int = Updates;
|
||||
stories.editStory#a9b91ae4 flags:# id:int media:flags.0?InputMedia media_areas:flags.3?Vector<MediaArea> caption:flags.1?string entities:flags.1?Vector<MessageEntity> privacy_rules:flags.2?Vector<InputPrivacyRule> = Updates;
|
||||
stories.deleteStories#b5d501d7 id:Vector<int> = Vector<int>;
|
||||
stories.togglePinned#51602944 id:Vector<int> pinned:Bool = Vector<int>;
|
||||
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<MediaArea> caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> 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<MediaArea> caption:flags.1?string entities:flags.1?Vector<MessageEntity> privacy_rules:flags.2?Vector<InputPrivacyRule> = Updates;
|
||||
stories.deleteStories#ae59db5f peer:InputPeer id:Vector<int> = Vector<int>;
|
||||
stories.togglePinned#9a75a1ef peer:InputPeer id:Vector<int> pinned:Bool = Vector<int>;
|
||||
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<int> = 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<int> = stories.Stories;
|
||||
stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool;
|
||||
stories.getAllReadUserStories#729c562c = Updates;
|
||||
stories.readStories#edc5105b user_id:InputUser max_id:int = Vector<int>;
|
||||
stories.incrementStoryViews#22126127 user_id:InputUser id:Vector<int> = 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<int> = stories.StoryViews;
|
||||
stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink;
|
||||
stories.report#c95be06a user_id:InputUser id:Vector<int> reason:ReportReason message:string = Bool;
|
||||
stories.readStories#a556dac8 peer:InputPeer max_id:int = Vector<int>;
|
||||
stories.incrementStoryViews#b2028afb peer:InputPeer id:Vector<int> = 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<int> = stories.StoryViews;
|
||||
stories.exportStoryLink#7b8def20 peer:InputPeer id:int = ExportedStoryLink;
|
||||
stories.report#1923fa8c peer:InputPeer id:Vector<int> 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<InputPeer> = Vector<int>;
|
||||
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;
|
||||
|
|
|
@ -1 +1 @@
|
|||
// LAYER 163
|
||||
// LAYER 164
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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<GenericBox*> box) {
|
||||
box->setTitle(tr::lng_payments_terms_title());
|
||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
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<Fn<void()>>();
|
||||
auto checkView = std::make_unique<Ui::CheckView>(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -56,7 +56,7 @@ struct Invoice {
|
|||
bool isTest = false;
|
||||
|
||||
QString provider;
|
||||
QString recurringTermsUrl;
|
||||
QString termsUrl;
|
||||
bool phoneSentToProvider = false;
|
||||
bool emailSentToProvider = false;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue