mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +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_title" = "Terms of Service";
|
||||||
"lng_payments_terms_text" = "Subscribe and accept terms of service of {bot}?";
|
"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_agree" = "I agree to {link}";
|
||||||
"lng_payments_terms_link" = "Terms of Service";
|
"lng_payments_terms_link" = "Terms of Service";
|
||||||
"lng_payments_terms_accept" = "Accept";
|
"lng_payments_terms_accept" = "Accept";
|
||||||
|
@ -3091,9 +3092,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_gigagroup_suggest_more" = "Learn more";
|
"lng_gigagroup_suggest_more" = "Learn more";
|
||||||
|
|
||||||
"lng_rights_channel_info" = "Change channel info";
|
"lng_rights_channel_info" = "Change channel info";
|
||||||
|
"lng_rights_channel_manage" = "Manage messages";
|
||||||
"lng_rights_channel_post" = "Post messages";
|
"lng_rights_channel_post" = "Post messages";
|
||||||
"lng_rights_channel_edit" = "Edit messages of others";
|
"lng_rights_channel_edit" = "Edit messages of others";
|
||||||
"lng_rights_channel_delete" = "Delete 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_channel_manage_calls" = "Manage live streams";
|
||||||
"lng_rights_group_info" = "Change group info";
|
"lng_rights_group_info" = "Change group info";
|
||||||
"lng_rights_group_ban" = "Ban users";
|
"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_post_messages" = "Post messages";
|
||||||
"lng_admin_log_admin_edit_messages" = "Edit messages";
|
"lng_admin_log_admin_edit_messages" = "Edit messages";
|
||||||
"lng_admin_log_admin_delete_messages" = "Delete 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_remain_anonymous" = "Remain anonymous";
|
||||||
"lng_admin_log_admin_ban_users" = "Ban users";
|
"lng_admin_log_admin_ban_users" = "Ban users";
|
||||||
"lng_admin_log_admin_invite_users" = "Add members";
|
"lng_admin_log_admin_invite_users" = "Add members";
|
||||||
|
|
|
@ -78,12 +78,8 @@ void SendReport(
|
||||||
MTP_string(comment)
|
MTP_string(comment)
|
||||||
)).done(std::move(done)).send();
|
)).done(std::move(done)).send();
|
||||||
}, [&](StoryId id) {
|
}, [&](StoryId id) {
|
||||||
const auto user = peer->asUser();
|
|
||||||
if (!user) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
peer->session().api().request(MTPstories_Report(
|
peer->session().api().request(MTPstories_Report(
|
||||||
user->inputUser,
|
peer->input,
|
||||||
MTP_vector<MTPint>(1, MTP_int(id)),
|
MTP_vector<MTPint>(1, MTP_int(id)),
|
||||||
ReasonToTL(reason),
|
ReasonToTL(reason),
|
||||||
MTP_string(comment)
|
MTP_string(comment)
|
||||||
|
|
|
@ -789,7 +789,7 @@ QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
||||||
? i->second
|
? i->second
|
||||||
: fallback();
|
: fallback();
|
||||||
request(MTPstories_ExportStoryLink(
|
request(MTPstories_ExportStoryLink(
|
||||||
story->peer()->asUser()->inputUser,
|
story->peer()->input,
|
||||||
MTP_int(story->id())
|
MTP_int(story->id())
|
||||||
)).done([=](const MTPExportedStoryLink &result) {
|
)).done([=](const MTPExportedStoryLink &result) {
|
||||||
const auto link = qs(result.data().vlink());
|
const auto link = qs(result.data().vlink());
|
||||||
|
@ -2533,14 +2533,9 @@ void ApiWrap::refreshFileReference(
|
||||||
}, [&](Data::FileOriginPremiumPreviews data) {
|
}, [&](Data::FileOriginPremiumPreviews data) {
|
||||||
request(MTPhelp_GetPremiumPromo());
|
request(MTPhelp_GetPremiumPromo());
|
||||||
}, [&](Data::FileOriginStory data) {
|
}, [&](Data::FileOriginStory data) {
|
||||||
const auto user = _session->data().peer(data.peerId)->asUser();
|
request(MTPstories_GetStoriesByID(
|
||||||
if (user) {
|
_session->data().peer(data.peerId)->input,
|
||||||
request(MTPstories_GetStoriesByID(
|
MTP_vector<MTPint>(1, MTP_int(data.storyId))));
|
||||||
user->inputUser,
|
|
||||||
MTP_vector<MTPint>(1, MTP_int(data.storyId))));
|
|
||||||
} else {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}, [&](v::null_t) {
|
}, [&](v::null_t) {
|
||||||
fail();
|
fail();
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,13 +51,14 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto NestedRestrictionLabelsList(
|
[[nodiscard]] auto NestedRestrictionLabelsList(
|
||||||
Data::RestrictionsSetOptions options) {
|
Data::RestrictionsSetOptions options)
|
||||||
|
-> std::vector<NestedEditFlagsLabels<ChatRestrictions>> {
|
||||||
using Flag = ChatRestriction;
|
using Flag = ChatRestriction;
|
||||||
|
|
||||||
auto first = std::vector<RestrictionLabel>{
|
auto first = std::vector<RestrictionLabel>{
|
||||||
{ Flag::SendOther, tr::lng_rights_chat_send_text(tr::now) },
|
{ 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::SendPhotos, tr::lng_rights_chat_photos(tr::now) },
|
||||||
{ Flag::SendVideos, tr::lng_rights_chat_videos(tr::now) },
|
{ Flag::SendVideos, tr::lng_rights_chat_videos(tr::now) },
|
||||||
{ Flag::SendVideoMessages, tr::lng_rights_chat_video_messages(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),
|
&RestrictionLabel::flags),
|
||||||
end(second));
|
end(second));
|
||||||
}
|
}
|
||||||
return std::vector<NestedEditFlagsLabels<ChatRestrictions>>{
|
return {
|
||||||
{ std::nullopt, std::move(first) },
|
{ 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) },
|
{ std::nullopt, std::move(second) },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1031,42 +1087,11 @@ std::vector<RestrictionLabel> RestrictionLabels(
|
||||||
|
|
||||||
std::vector<AdminRightLabel> AdminRightLabels(
|
std::vector<AdminRightLabel> AdminRightLabels(
|
||||||
Data::AdminRightsSetOptions options) {
|
Data::AdminRightsSetOptions options) {
|
||||||
using Flag = ChatAdminRight;
|
auto result = std::vector<AdminRightLabel>();
|
||||||
|
for (const auto &[_, r] : NestedAdminRightLabels(options)) {
|
||||||
if (options.isGroup) {
|
result.insert(result.end(), r.begin(), r.end());
|
||||||
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) }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
||||||
|
@ -1107,7 +1132,7 @@ EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
|
||||||
rights,
|
rights,
|
||||||
{
|
{
|
||||||
.header = std::move(header),
|
.header = std::move(header),
|
||||||
.labels = { { std::nullopt, AdminRightLabels(options) } },
|
.labels = NestedAdminRightLabels(options),
|
||||||
.disabledMessages = std::move(disabledMessages),
|
.disabledMessages = std::move(disabledMessages),
|
||||||
});
|
});
|
||||||
result.widget = std::move(widget);
|
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_user.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_stories.h"
|
||||||
#include "data/data_folder.h"
|
#include "data/data_folder.h"
|
||||||
#include "data/data_forum.h"
|
#include "data/data_forum.h"
|
||||||
#include "data/data_forum_icons.h"
|
#include "data/data_forum_icons.h"
|
||||||
|
@ -530,6 +531,11 @@ bool ChannelData::canBanMembers() const {
|
||||||
|| (adminRights() & AdminRight::BanUsers);
|
|| (adminRights() & AdminRight::BanUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChannelData::canPostMessages() const {
|
||||||
|
return amCreator()
|
||||||
|
|| (adminRights() & AdminRight::PostMessages);
|
||||||
|
}
|
||||||
|
|
||||||
bool ChannelData::canEditMessages() const {
|
bool ChannelData::canEditMessages() const {
|
||||||
return amCreator()
|
return amCreator()
|
||||||
|| (adminRights() & AdminRight::EditMessages);
|
|| (adminRights() & AdminRight::EditMessages);
|
||||||
|
@ -559,11 +565,6 @@ bool ChannelData::canAddAdmins() const {
|
||||||
|| (adminRights() & AdminRight::AddAdmins);
|
|| (adminRights() & AdminRight::AddAdmins);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChannelData::canPublish() const {
|
|
||||||
return amCreator()
|
|
||||||
|| (adminRights() & AdminRight::PostMessages);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelData::allowsForwarding() const {
|
bool ChannelData::allowsForwarding() const {
|
||||||
return !(flags() & Flag::NoForwards);
|
return !(flags() & Flag::NoForwards);
|
||||||
}
|
}
|
||||||
|
@ -877,6 +878,38 @@ const Data::AllowedReactions &ChannelData::allowedReactions() const {
|
||||||
return _allowedReactions;
|
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) {
|
void ChannelData::processTopics(const MTPVector<MTPForumTopic> &topics) {
|
||||||
if (const auto forum = this->forum()) {
|
if (const auto forum = this->forum()) {
|
||||||
forum->applyReceivedTopics(topics);
|
forum->applyReceivedTopics(topics);
|
||||||
|
@ -1046,6 +1079,7 @@ void ApplyChannelUpdate(
|
||||||
} else {
|
} else {
|
||||||
channel->setAllowedReactions({});
|
channel->setAllowedReactions({});
|
||||||
}
|
}
|
||||||
|
channel->owner().stories().apply(channel, update.vstories());
|
||||||
channel->fullUpdated();
|
channel->fullUpdated();
|
||||||
channel->setPendingRequestsCount(
|
channel->setPendingRequestsCount(
|
||||||
update.vrequests_pending().value_or_empty(),
|
update.vrequests_pending().value_or_empty(),
|
||||||
|
|
|
@ -59,6 +59,9 @@ enum class ChannelDataFlag {
|
||||||
Forum = (1 << 23),
|
Forum = (1 << 23),
|
||||||
AntiSpam = (1 << 24),
|
AntiSpam = (1 << 24),
|
||||||
ParticipantsHidden = (1 << 25),
|
ParticipantsHidden = (1 << 25),
|
||||||
|
StoriesHidden = (1 << 26),
|
||||||
|
HasActiveStories = (1 << 27),
|
||||||
|
HasUnreadStories = (1 << 28),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(ChannelDataFlag) { return true; };
|
inline constexpr bool is_flag_type(ChannelDataFlag) { return true; };
|
||||||
using ChannelDataFlags = base::flags<ChannelDataFlag>;
|
using ChannelDataFlags = base::flags<ChannelDataFlag>;
|
||||||
|
@ -226,6 +229,9 @@ public:
|
||||||
[[nodiscard]] bool isFake() const {
|
[[nodiscard]] bool isFake() const {
|
||||||
return flags() & Flag::Fake;
|
return flags() & Flag::Fake;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] bool hasStoriesHidden() const {
|
||||||
|
return flags() & Flag::StoriesHidden;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights(
|
[[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights(
|
||||||
not_null<PeerData*> participant);
|
not_null<PeerData*> participant);
|
||||||
|
@ -329,10 +335,13 @@ public:
|
||||||
[[nodiscard]] bool canBanMembers() const;
|
[[nodiscard]] bool canBanMembers() const;
|
||||||
[[nodiscard]] bool anyoneCanAddMembers() const;
|
[[nodiscard]] bool anyoneCanAddMembers() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool canPostMessages() const;
|
||||||
[[nodiscard]] bool canEditMessages() const;
|
[[nodiscard]] bool canEditMessages() const;
|
||||||
[[nodiscard]] bool canDeleteMessages() const;
|
[[nodiscard]] bool canDeleteMessages() const;
|
||||||
|
[[nodiscard]] bool canPostStories() const;
|
||||||
|
[[nodiscard]] bool canEditStories() const;
|
||||||
|
[[nodiscard]] bool canDeleteStories() const;
|
||||||
[[nodiscard]] bool hiddenPreHistory() const;
|
[[nodiscard]] bool hiddenPreHistory() const;
|
||||||
[[nodiscard]] bool canPublish() const;
|
|
||||||
[[nodiscard]] bool canViewMembers() const;
|
[[nodiscard]] bool canViewMembers() const;
|
||||||
[[nodiscard]] bool canViewAdmins() const;
|
[[nodiscard]] bool canViewAdmins() const;
|
||||||
[[nodiscard]] bool canViewBanned() const;
|
[[nodiscard]] bool canViewBanned() const;
|
||||||
|
@ -437,6 +446,10 @@ public:
|
||||||
void setAllowedReactions(Data::AllowedReactions value);
|
void setAllowedReactions(Data::AllowedReactions value);
|
||||||
[[nodiscard]] const Data::AllowedReactions &allowedReactions() const;
|
[[nodiscard]] const Data::AllowedReactions &allowedReactions() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasActiveStories() const;
|
||||||
|
[[nodiscard]] bool hasUnreadStories() const;
|
||||||
|
void setStoriesState(StoriesState state);
|
||||||
|
|
||||||
[[nodiscard]] Data::Forum *forum() const {
|
[[nodiscard]] Data::Forum *forum() const {
|
||||||
return mgInfo ? mgInfo->forum() : nullptr;
|
return mgInfo ? mgInfo->forum() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ bool CanSendAnyOf(
|
||||||
&& !(channel->flags() & Flag::JoinToWrite));
|
&& !(channel->flags() & Flag::JoinToWrite));
|
||||||
if (!allowed || (forbidInForums && channel->isForum())) {
|
if (!allowed || (forbidInForums && channel->isForum())) {
|
||||||
return false;
|
return false;
|
||||||
} else if (channel->canPublish()) {
|
} else if (channel->canPostMessages()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (channel->isBroadcast()) {
|
} else if (channel->isBroadcast()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -25,6 +25,9 @@ enum class ChatAdminRight {
|
||||||
ManageCall = (1 << 11),
|
ManageCall = (1 << 11),
|
||||||
Other = (1 << 12),
|
Other = (1 << 12),
|
||||||
ManageTopics = (1 << 13),
|
ManageTopics = (1 << 13),
|
||||||
|
PostStories = (1 << 14),
|
||||||
|
EditStories = (1 << 15),
|
||||||
|
DeleteStories = (1 << 16),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(ChatAdminRight) { return true; }
|
inline constexpr bool is_flag_type(ChatAdminRight) { return true; }
|
||||||
using ChatAdminRights = base::flags<ChatAdminRight>;
|
using ChatAdminRights = base::flags<ChatAdminRight>;
|
||||||
|
|
|
@ -898,6 +898,33 @@ bool PeerData::isRepliesChat() const {
|
||||||
: kTestId) == id;
|
: 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 {
|
Data::Forum *PeerData::forum() const {
|
||||||
if (const auto channel = asChannel()) {
|
if (const auto channel = asChannel()) {
|
||||||
return channel->forum();
|
return channel->forum();
|
||||||
|
@ -1108,6 +1135,34 @@ const Data::WallPaper *PeerData::wallPaper() const {
|
||||||
return _wallPaper.get();
|
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) {
|
void PeerData::setIsBlocked(bool is) {
|
||||||
const auto status = is
|
const auto status = is
|
||||||
? BlockStatus::Blocked
|
? BlockStatus::Blocked
|
||||||
|
|
|
@ -183,9 +183,9 @@ public:
|
||||||
[[nodiscard]] bool isForum() const;
|
[[nodiscard]] bool isForum() const;
|
||||||
[[nodiscard]] bool isGigagroup() const;
|
[[nodiscard]] bool isGigagroup() const;
|
||||||
[[nodiscard]] bool isRepliesChat() const;
|
[[nodiscard]] bool isRepliesChat() const;
|
||||||
[[nodiscard]] bool sharedMediaInfo() const {
|
[[nodiscard]] bool sharedMediaInfo() const;
|
||||||
return isSelf() || isRepliesChat();
|
[[nodiscard]] bool hasStoriesHidden() const;
|
||||||
}
|
void setStoriesHidden(bool hidden);
|
||||||
|
|
||||||
[[nodiscard]] bool isNotificationsUser() const {
|
[[nodiscard]] bool isNotificationsUser() const {
|
||||||
return (id == peerFromUser(333000))
|
return (id == peerFromUser(333000))
|
||||||
|
@ -407,6 +407,16 @@ public:
|
||||||
void setWallPaper(std::optional<Data::WallPaper> paper);
|
void setWallPaper(std::optional<Data::WallPaper> paper);
|
||||||
[[nodiscard]] const Data::WallPaper *wallPaper() const;
|
[[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;
|
const PeerId id;
|
||||||
MTPinputPeer input = MTP_inputPeerEmpty();
|
MTPinputPeer input = MTP_inputPeerEmpty();
|
||||||
|
|
||||||
|
|
|
@ -909,7 +909,17 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
||||||
| Flag::NoForwards
|
| Flag::NoForwards
|
||||||
| Flag::JoinToWrite
|
| Flag::JoinToWrite
|
||||||
| Flag::RequestToJoin
|
| 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())
|
const auto flagsSet = (data.is_broadcast() ? Flag::Broadcast : Flag())
|
||||||
| (data.is_verified() ? Flag::Verified : Flag())
|
| (data.is_verified() ? Flag::Verified : Flag())
|
||||||
| (data.is_scam() ? Flag::Scam : 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_join_request() ? Flag::RequestToJoin : Flag())
|
||||||
| ((data.is_forum() && data.is_megagroup())
|
| ((data.is_forum() && data.is_megagroup())
|
||||||
? Flag::Forum
|
? Flag::Forum
|
||||||
|
: Flag())
|
||||||
|
| ((!minimal
|
||||||
|
&& !data.is_stories_hidden_min()
|
||||||
|
&& data.is_stories_hidden())
|
||||||
|
? Flag::StoriesHidden
|
||||||
: Flag());
|
: Flag());
|
||||||
channel->setFlags((channel->flags() & ~flagsMask) | flagsSet);
|
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());
|
channel->setPhoto(data.vphoto());
|
||||||
|
|
||||||
|
@ -3345,12 +3367,12 @@ void Session::webpageApplyFields(
|
||||||
for (const auto &attribute : attributes->v) {
|
for (const auto &attribute : attributes->v) {
|
||||||
attribute.match([&](const MTPDwebPageAttributeStory &data) {
|
attribute.match([&](const MTPDwebPageAttributeStory &data) {
|
||||||
storyId = FullStoryId{
|
storyId = FullStoryId{
|
||||||
peerFromUser(data.vuser_id()),
|
peerFromMTP(data.vpeer()),
|
||||||
data.vid().v,
|
data.vid().v,
|
||||||
};
|
};
|
||||||
if (const auto embed = data.vstory()) {
|
if (const auto embed = data.vstory()) {
|
||||||
story = stories().applyFromWebpage(
|
story = stories().applyFromWebpage(
|
||||||
peerFromUser(data.vuser_id()),
|
peerFromMTP(data.vpeer()),
|
||||||
*embed);
|
*embed);
|
||||||
} else if (const auto maybe = stories().lookup(storyId)) {
|
} else if (const auto maybe = stories().lookup(storyId)) {
|
||||||
story = *maybe;
|
story = *maybe;
|
||||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_folder.h"
|
#include "data/data_folder.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
|
@ -78,11 +79,11 @@ using UpdateFlag = StoryUpdate::Flag;
|
||||||
|
|
||||||
StoriesSourceInfo StoriesSource::info() const {
|
StoriesSourceInfo StoriesSource::info() const {
|
||||||
return {
|
return {
|
||||||
.id = user->id,
|
.id = peer->id,
|
||||||
.last = ids.empty() ? 0 : ids.back().date,
|
.last = ids.empty() ? 0 : ids.back().date,
|
||||||
.count = uint32(std::min(int(ids.size()), kMaxSegmentsCount)),
|
.count = uint32(std::min(int(ids.size()), kMaxSegmentsCount)),
|
||||||
.unreadCount = uint32(std::min(unreadCount(), 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) {
|
void Stories::apply(const MTPDupdateStory &data) {
|
||||||
const auto peerId = peerFromUser(data.vuser_id());
|
const auto peerId = peerFromMTP(data.vpeer());
|
||||||
const auto user = not_null(_owner->peer(peerId)->asUser());
|
const auto peer = _owner->peer(peerId);
|
||||||
const auto now = base::unixtime::now();
|
const auto now = base::unixtime::now();
|
||||||
const auto idDates = parseAndApply(user, data.vstory(), now);
|
const auto idDates = parseAndApply(peer, data.vstory(), now);
|
||||||
if (!idDates) {
|
if (!idDates) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +137,7 @@ void Stories::apply(const MTPDupdateStory &data) {
|
||||||
}
|
}
|
||||||
const auto i = _all.find(peerId);
|
const auto i = _all.find(peerId);
|
||||||
if (i == end(_all)) {
|
if (i == end(_all)) {
|
||||||
requestUserStories(user);
|
requestPeerStories(peer);
|
||||||
return;
|
return;
|
||||||
} else if (i->second.ids.contains(idDates)) {
|
} else if (i->second.ids.contains(idDates)) {
|
||||||
return;
|
return;
|
||||||
|
@ -144,8 +145,8 @@ void Stories::apply(const MTPDupdateStory &data) {
|
||||||
const auto wasInfo = i->second.info();
|
const auto wasInfo = i->second.info();
|
||||||
i->second.ids.emplace(idDates);
|
i->second.ids.emplace(idDates);
|
||||||
const auto nowInfo = i->second.info();
|
const auto nowInfo = i->second.info();
|
||||||
if (user->isSelf() && i->second.readTill < idDates.id) {
|
if (peer->isSelf() && i->second.readTill < idDates.id) {
|
||||||
_readTill[user->id] = i->second.readTill = idDates.id;
|
_readTill[peerId] = i->second.readTill = idDates.id;
|
||||||
}
|
}
|
||||||
if (wasInfo == nowInfo) {
|
if (wasInfo == nowInfo) {
|
||||||
return;
|
return;
|
||||||
|
@ -161,17 +162,17 @@ void Stories::apply(const MTPDupdateStory &data) {
|
||||||
sort(list);
|
sort(list);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (user->hasStoriesHidden()) {
|
if (peer->hasStoriesHidden()) {
|
||||||
refreshInList(StorySourcesList::Hidden);
|
refreshInList(StorySourcesList::Hidden);
|
||||||
} else {
|
} else {
|
||||||
refreshInList(StorySourcesList::NotHidden);
|
refreshInList(StorySourcesList::NotHidden);
|
||||||
}
|
}
|
||||||
_sourceChanged.fire_copy(peerId);
|
_sourceChanged.fire_copy(peerId);
|
||||||
updateUserStoriesState(user);
|
updatePeerStoriesState(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stories::apply(const MTPDupdateReadStories &data) {
|
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) {
|
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) {
|
if (!data) {
|
||||||
applyDeletedFromSources(peer->id, StorySourcesList::NotHidden);
|
applyDeletedFromSources(peer->id, StorySourcesList::NotHidden);
|
||||||
applyDeletedFromSources(peer->id, StorySourcesList::Hidden);
|
applyDeletedFromSources(peer->id, StorySourcesList::Hidden);
|
||||||
_all.erase(peer->id);
|
_all.erase(peer->id);
|
||||||
_sourceChanged.fire_copy(peer->id);
|
_sourceChanged.fire_copy(peer->id);
|
||||||
updateUserStoriesState(peer);
|
updatePeerStoriesState(peer);
|
||||||
} else {
|
} else {
|
||||||
parseAndApply(*data);
|
parseAndApply(*data);
|
||||||
}
|
}
|
||||||
|
@ -205,10 +206,10 @@ Story *Stories::applyFromWebpage(PeerId peerId, const MTPstoryItem &story) {
|
||||||
return value ? value->get() : nullptr;
|
return value ? value->get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stories::requestUserStories(
|
void Stories::requestPeerStories(
|
||||||
not_null<UserData*> user,
|
not_null<PeerData*> peer,
|
||||||
Fn<void()> done) {
|
Fn<void()> done) {
|
||||||
const auto [i, ok] = _requestingUserStories.emplace(user);
|
const auto [i, ok] = _requestingPeerStories.emplace(peer);
|
||||||
if (done) {
|
if (done) {
|
||||||
i->second.push_back(std::move(done));
|
i->second.push_back(std::move(done));
|
||||||
}
|
}
|
||||||
|
@ -216,22 +217,23 @@ void Stories::requestUserStories(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto finish = [=] {
|
const auto finish = [=] {
|
||||||
if (const auto callbacks = _requestingUserStories.take(user)) {
|
if (const auto callbacks = _requestingPeerStories.take(peer)) {
|
||||||
for (const auto &callback : *callbacks) {
|
for (const auto &callback : *callbacks) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_owner->session().api().request(MTPstories_GetUserStories(
|
_owner->session().api().request(MTPstories_GetPeerStories(
|
||||||
user->inputUser
|
peer->input
|
||||||
)).done([=](const MTPstories_UserStories &result) {
|
)).done([=](const MTPstories_PeerStories &result) {
|
||||||
const auto &data = result.data();
|
const auto &data = result.data();
|
||||||
_owner->processUsers(data.vusers());
|
_owner->processUsers(data.vusers());
|
||||||
|
_owner->processChats(data.vchats());
|
||||||
parseAndApply(data.vstories());
|
parseAndApply(data.vstories());
|
||||||
finish();
|
finish();
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
applyDeletedFromSources(user->id, StorySourcesList::NotHidden);
|
applyDeletedFromSources(peer->id, StorySourcesList::NotHidden);
|
||||||
applyDeletedFromSources(user->id, StorySourcesList::Hidden);
|
applyDeletedFromSources(peer->id, StorySourcesList::Hidden);
|
||||||
finish();
|
finish();
|
||||||
}).send();
|
}).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 &data = stories.data();
|
||||||
const auto peerId = peerFromUser(data.vuser_id());
|
const auto peerId = peerFromMTP(data.vpeer());
|
||||||
const auto already = _readTill.find(peerId);
|
const auto already = _readTill.find(peerId);
|
||||||
const auto readTill = std::max(
|
const auto readTill = std::max(
|
||||||
data.vmax_read_id().value_or_empty(),
|
data.vmax_read_id().value_or_empty(),
|
||||||
(already != end(_readTill) ? already->second : 0));
|
(already != end(_readTill) ? already->second : 0));
|
||||||
const auto user = _owner->peer(peerId)->asUser();
|
const auto peer = _owner->peer(peerId);
|
||||||
auto result = StoriesSource{
|
auto result = StoriesSource{
|
||||||
.user = user,
|
.peer = peer,
|
||||||
.readTill = readTill,
|
.readTill = readTill,
|
||||||
.hidden = user->hasStoriesHidden(),
|
.hidden = peer->hasStoriesHidden(),
|
||||||
};
|
};
|
||||||
const auto &list = data.vstories().v;
|
const auto &list = data.vstories().v;
|
||||||
const auto now = base::unixtime::now();
|
const auto now = base::unixtime::now();
|
||||||
result.ids.reserve(list.size());
|
result.ids.reserve(list.size());
|
||||||
for (const auto &story : list) {
|
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);
|
result.ids.emplace(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.ids.empty()) {
|
if (result.ids.empty()) {
|
||||||
applyDeletedFromSources(peerId, StorySourcesList::NotHidden);
|
applyDeletedFromSources(peerId, StorySourcesList::NotHidden);
|
||||||
applyDeletedFromSources(peerId, StorySourcesList::Hidden);
|
applyDeletedFromSources(peerId, StorySourcesList::Hidden);
|
||||||
user->setStoriesState(UserData::StoriesState::None);
|
peer->setStoriesState(PeerData::StoriesState::None);
|
||||||
return;
|
return;
|
||||||
} else if (user->isSelf()) {
|
} else if (peer->isSelf()) {
|
||||||
result.readTill = result.ids.back().id;
|
result.readTill = result.ids.back().id;
|
||||||
}
|
}
|
||||||
_readTill[peerId] = result.readTill;
|
_readTill[peerId] = result.readTill;
|
||||||
|
@ -345,11 +347,13 @@ void Stories::parseAndApply(const MTPUserStories &stories) {
|
||||||
}
|
}
|
||||||
sort(list);
|
sort(list);
|
||||||
};
|
};
|
||||||
if (result.user->isSelf()
|
if (result.peer->isSelf()
|
||||||
|| result.user->isBot()
|
|| (result.peer->isChannel() && result.peer->asChannel()->amIn())
|
||||||
|| result.user->isServiceUser()
|
|| (result.peer->isUser()
|
||||||
|| result.user->isContact()) {
|
&& (result.peer->asUser()->isBot()
|
||||||
const auto hidden = result.user->hasStoriesHidden();
|
|| result.peer->asUser()->isContact()))
|
||||||
|
|| result.peer->isServiceUser()) {
|
||||||
|
const auto hidden = result.peer->hasStoriesHidden();
|
||||||
using List = StorySourcesList;
|
using List = StorySourcesList;
|
||||||
add(hidden ? List::Hidden : List::NotHidden);
|
add(hidden ? List::Hidden : List::NotHidden);
|
||||||
applyDeletedFromSources(
|
applyDeletedFromSources(
|
||||||
|
@ -360,7 +364,7 @@ void Stories::parseAndApply(const MTPUserStories &stories) {
|
||||||
applyDeletedFromSources(peerId, StorySourcesList::Hidden);
|
applyDeletedFromSources(peerId, StorySourcesList::Hidden);
|
||||||
}
|
}
|
||||||
_sourceChanged.fire_copy(peerId);
|
_sourceChanged.fire_copy(peerId);
|
||||||
updateUserStoriesState(result.user);
|
updatePeerStoriesState(result.peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Story *Stories::parseAndApply(
|
Story *Stories::parseAndApply(
|
||||||
|
@ -539,9 +543,10 @@ void Stories::loadMore(StorySourcesList list) {
|
||||||
|
|
||||||
result.match([&](const MTPDstories_allStories &data) {
|
result.match([&](const MTPDstories_allStories &data) {
|
||||||
_owner->processUsers(data.vusers());
|
_owner->processUsers(data.vusers());
|
||||||
|
_owner->processChats(data.vchats());
|
||||||
_sourcesStates[index] = qs(data.vstate());
|
_sourcesStates[index] = qs(data.vstate());
|
||||||
_sourcesLoaded[index] = !data.is_has_more();
|
_sourcesLoaded[index] = !data.is_has_more();
|
||||||
for (const auto &single : data.vuser_stories().v) {
|
for (const auto &single : data.vpeer_stories().v) {
|
||||||
parseAndApply(single);
|
parseAndApply(single);
|
||||||
}
|
}
|
||||||
}, [](const MTPDstories_allStoriesNotModified &) {
|
}, [](const MTPDstories_allStoriesNotModified &) {
|
||||||
|
@ -654,18 +659,15 @@ void Stories::sendResolveRequests() {
|
||||||
crl::on_main(&session(), [=] { sendResolveRequests(); });
|
crl::on_main(&session(), [=] { sendResolveRequests(); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto user = _owner->session().data().peer(peerId)->asUser();
|
const auto peer = _owner->session().data().peer(peerId);
|
||||||
if (!user) {
|
|
||||||
finish(peerId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
api->request(MTPstories_GetStoriesByID(
|
api->request(MTPstories_GetStoriesByID(
|
||||||
user->inputUser,
|
peer->input,
|
||||||
MTP_vector<MTPint>(prepared)
|
MTP_vector<MTPint>(prepared)
|
||||||
)).done([=](const MTPstories_Stories &result) {
|
)).done([=](const MTPstories_Stories &result) {
|
||||||
owner().processUsers(result.data().vusers());
|
owner().processUsers(result.data().vusers());
|
||||||
processResolvedStories(user, result.data().vstories().v);
|
owner().processChats(result.data().vchats());
|
||||||
finish(user->id);
|
processResolvedStories(peer, result.data().vstories().v);
|
||||||
|
finish(peer->id);
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
finish(peerId);
|
finish(peerId);
|
||||||
}).send();
|
}).send();
|
||||||
|
@ -786,14 +788,14 @@ void Stories::applyRemovedFromActive(FullStoryId id) {
|
||||||
const auto j = i->second.ids.lower_bound(StoryIdDates{ id.story });
|
const auto j = i->second.ids.lower_bound(StoryIdDates{ id.story });
|
||||||
if (j != end(i->second.ids) && j->id == id.story) {
|
if (j != end(i->second.ids) && j->id == id.story) {
|
||||||
i->second.ids.erase(j);
|
i->second.ids.erase(j);
|
||||||
const auto user = i->second.user;
|
const auto peer = i->second.peer;
|
||||||
if (i->second.ids.empty()) {
|
if (i->second.ids.empty()) {
|
||||||
_all.erase(i);
|
_all.erase(i);
|
||||||
removeFromList(StorySourcesList::NotHidden);
|
removeFromList(StorySourcesList::NotHidden);
|
||||||
removeFromList(StorySourcesList::Hidden);
|
removeFromList(StorySourcesList::Hidden);
|
||||||
}
|
}
|
||||||
_sourceChanged.fire_copy(id.peer);
|
_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();
|
const auto api = &session().api();
|
||||||
api->request(MTPstories_SendReaction(
|
api->request(MTPstories_SendReaction(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
story->peer()->asUser()->inputUser,
|
story->peer()->input,
|
||||||
MTP_int(id.story),
|
MTP_int(id.story),
|
||||||
ReactionToMTP(reaction)
|
ReactionToMTP(reaction)
|
||||||
)).send();
|
)).send();
|
||||||
|
@ -1054,7 +1056,7 @@ bool Stories::bumpReadTill(PeerId peerId, StoryId maxReadTill) {
|
||||||
if (till < maxReadTill) {
|
if (till < maxReadTill) {
|
||||||
const auto from = till;
|
const auto from = till;
|
||||||
till = maxReadTill;
|
till = maxReadTill;
|
||||||
updateUserStoriesState(_owner->peer(peerId));
|
updatePeerStoriesState(_owner->peer(peerId));
|
||||||
const auto i = _stories.find(peerId);
|
const auto i = _stories.find(peerId);
|
||||||
if (i != end(_stories)) {
|
if (i != end(_stories)) {
|
||||||
refreshItems = ranges::make_subrange(
|
refreshItems = ranges::make_subrange(
|
||||||
|
@ -1097,19 +1099,16 @@ void Stories::toggleHidden(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
bool hidden,
|
bool hidden,
|
||||||
std::shared_ptr<Ui::Show> show) {
|
std::shared_ptr<Ui::Show> show) {
|
||||||
const auto user = _owner->peer(peerId)->asUser();
|
const auto peer = _owner->peer(peerId);
|
||||||
Assert(user != nullptr);
|
if (peer->hasStoriesHidden() != hidden) {
|
||||||
if (user->hasStoriesHidden() != hidden) {
|
peer->setStoriesHidden(hidden);
|
||||||
user->setFlags(hidden
|
session().api().request(MTPstories_TogglePeerStoriesHidden(
|
||||||
? (user->flags() | UserDataFlag::StoriesHidden)
|
peer->input,
|
||||||
: (user->flags() & ~UserDataFlag::StoriesHidden));
|
|
||||||
session().api().request(MTPcontacts_ToggleStoriesHidden(
|
|
||||||
user->inputUser,
|
|
||||||
MTP_bool(hidden)
|
MTP_bool(hidden)
|
||||||
)).send();
|
)).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto name = user->shortName();
|
const auto name = peer->shortName();
|
||||||
const auto guard = gsl::finally([&] {
|
const auto guard = gsl::finally([&] {
|
||||||
if (show) {
|
if (show) {
|
||||||
const auto phrase = hidden
|
const auto phrase = hidden
|
||||||
|
@ -1166,8 +1165,6 @@ void Stories::toggleHidden(
|
||||||
void Stories::sendMarkAsReadRequest(
|
void Stories::sendMarkAsReadRequest(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
StoryId tillId) {
|
StoryId tillId) {
|
||||||
Expects(peer->isUser());
|
|
||||||
|
|
||||||
const auto peerId = peer->id;
|
const auto peerId = peer->id;
|
||||||
_markReadRequests.emplace(peerId);
|
_markReadRequests.emplace(peerId);
|
||||||
const auto finish = [=] {
|
const auto finish = [=] {
|
||||||
|
@ -1181,7 +1178,7 @@ void Stories::sendMarkAsReadRequest(
|
||||||
|
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
api->request(MTPstories_ReadStories(
|
api->request(MTPstories_ReadStories(
|
||||||
peer->asUser()->inputUser,
|
peer->input,
|
||||||
MTP_int(tillId)
|
MTP_int(tillId)
|
||||||
)).done(finish).fail(finish).send();
|
)).done(finish).fail(finish).send();
|
||||||
}
|
}
|
||||||
|
@ -1205,7 +1202,7 @@ void Stories::sendMarkAsReadRequests() {
|
||||||
}
|
}
|
||||||
const auto j = _all.find(peerId);
|
const auto j = _all.find(peerId);
|
||||||
if (j != end(_all)) {
|
if (j != end(_all)) {
|
||||||
sendMarkAsReadRequest(j->second.user, j->second.readTill);
|
sendMarkAsReadRequest(j->second.peer, j->second.readTill);
|
||||||
}
|
}
|
||||||
i = _markReadPending.erase(i);
|
i = _markReadPending.erase(i);
|
||||||
}
|
}
|
||||||
|
@ -1243,7 +1240,7 @@ void Stories::sendIncrementViewsRequests() {
|
||||||
checkQuitPreventFinished();
|
checkQuitPreventFinished();
|
||||||
};
|
};
|
||||||
api->request(MTPstories_IncrementStoryViews(
|
api->request(MTPstories_IncrementStoryViews(
|
||||||
_owner->peer(peer)->asUser()->inputUser,
|
_owner->peer(peer)->input,
|
||||||
MTP_vector<MTPint>(std::move(ids))
|
MTP_vector<MTPint>(std::move(ids))
|
||||||
)).done(finish).fail(finish).send();
|
)).done(finish).fail(finish).send();
|
||||||
_incrementViewsPending.remove(peer);
|
_incrementViewsPending.remove(peer);
|
||||||
|
@ -1272,6 +1269,7 @@ void Stories::loadViewsSlice(
|
||||||
using Flag = MTPstories_GetStoryViewsList::Flag;
|
using Flag = MTPstories_GetStoryViewsList::Flag;
|
||||||
_viewsRequestId = api->request(MTPstories_GetStoryViewsList(
|
_viewsRequestId = api->request(MTPstories_GetStoryViewsList(
|
||||||
MTP_flags(Flag::f_reactions_first),
|
MTP_flags(Flag::f_reactions_first),
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTPstring(), // q
|
MTPstring(), // q
|
||||||
MTP_int(id),
|
MTP_int(id),
|
||||||
MTP_string(offset),
|
MTP_string(offset),
|
||||||
|
@ -1364,6 +1362,7 @@ void Stories::archiveLoadMore() {
|
||||||
}
|
}
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
_archiveRequestId = api->request(MTPstories_GetStoriesArchive(
|
_archiveRequestId = api->request(MTPstories_GetStoriesArchive(
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTP_int(_archiveLastId),
|
MTP_int(_archiveLastId),
|
||||||
MTP_int(_archiveLastId ? kArchivePerPage : kArchiveFirstPerPage)
|
MTP_int(_archiveLastId ? kArchivePerPage : kArchiveFirstPerPage)
|
||||||
)).done([=](const MTPstories_Stories &result) {
|
)).done([=](const MTPstories_Stories &result) {
|
||||||
|
@ -1399,8 +1398,6 @@ void Stories::archiveLoadMore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stories::savedLoadMore(PeerId peerId) {
|
void Stories::savedLoadMore(PeerId peerId) {
|
||||||
Expects(peerIsUser(peerId));
|
|
||||||
|
|
||||||
auto &saved = _saved[peerId];
|
auto &saved = _saved[peerId];
|
||||||
if (saved.requestId || saved.loaded) {
|
if (saved.requestId || saved.loaded) {
|
||||||
return;
|
return;
|
||||||
|
@ -1408,7 +1405,7 @@ void Stories::savedLoadMore(PeerId peerId) {
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
const auto peer = _owner->peer(peerId);
|
const auto peer = _owner->peer(peerId);
|
||||||
saved.requestId = api->request(MTPstories_GetPinnedStories(
|
saved.requestId = api->request(MTPstories_GetPinnedStories(
|
||||||
peer->asUser()->inputUser,
|
peer->input,
|
||||||
MTP_int(saved.lastId),
|
MTP_int(saved.lastId),
|
||||||
MTP_int(saved.lastId ? kSavedPerPage : kSavedFirstPerPage)
|
MTP_int(saved.lastId ? kSavedPerPage : kSavedFirstPerPage)
|
||||||
)).done([=](const MTPstories_Stories &result) {
|
)).done([=](const MTPstories_Stories &result) {
|
||||||
|
@ -1456,6 +1453,7 @@ void Stories::deleteList(const std::vector<FullStoryId> &ids) {
|
||||||
if (!list.empty()) {
|
if (!list.empty()) {
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
api->request(MTPstories_DeleteStories(
|
api->request(MTPstories_DeleteStories(
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTP_vector<MTPint>(list)
|
MTP_vector<MTPint>(list)
|
||||||
)).done([=](const MTPVector<MTPint> &result) {
|
)).done([=](const MTPVector<MTPint> &result) {
|
||||||
for (const auto &id : result.v) {
|
for (const auto &id : result.v) {
|
||||||
|
@ -1481,6 +1479,7 @@ void Stories::togglePinnedList(
|
||||||
}
|
}
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
api->request(MTPstories_TogglePinned(
|
api->request(MTPstories_TogglePinned(
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTP_vector<MTPint>(list),
|
MTP_vector<MTPint>(list),
|
||||||
MTP_bool(pinned)
|
MTP_bool(pinned)
|
||||||
)).done([=](const MTPVector<MTPint> &result) {
|
)).done([=](const MTPVector<MTPint> &result) {
|
||||||
|
@ -1608,7 +1607,7 @@ std::optional<Stories::PeerSourceState> Stories::peerSourceState(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
requestReadTills();
|
requestReadTills();
|
||||||
_pendingUserStateMaxId[peer] = storyMaxId;
|
_pendingPeerStateMaxId[peer] = storyMaxId;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1617,12 +1616,12 @@ void Stories::requestReadTills() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto api = &_owner->session().api();
|
const auto api = &_owner->session().api();
|
||||||
_readTillsRequestId = api->request(MTPstories_GetAllReadUserStories(
|
_readTillsRequestId = api->request(MTPstories_GetAllReadPeerStories(
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
_readTillReceived = true;
|
_readTillReceived = true;
|
||||||
api->applyUpdates(result);
|
api->applyUpdates(result);
|
||||||
for (auto &[peer, maxId] : base::take(_pendingUserStateMaxId)) {
|
for (auto &[peer, maxId] : base::take(_pendingPeerStateMaxId)) {
|
||||||
updateUserStoriesState(peer);
|
updatePeerStoriesState(peer);
|
||||||
}
|
}
|
||||||
for (const auto &storyId : base::take(_pendingReadTillItems)) {
|
for (const auto &storyId : base::take(_pendingReadTillItems)) {
|
||||||
_owner->refreshStoryItemViews(storyId);
|
_owner->refreshStoryItemViews(storyId);
|
||||||
|
@ -1745,24 +1744,22 @@ void Stories::sendPollingViewsRequests() {
|
||||||
_pollingViewsTimer.callOnce(kPollViewsInterval);
|
_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 till = _readTill.find(peer->id);
|
||||||
const auto readTill = (till != end(_readTill)) ? till->second : 0;
|
const auto readTill = (till != end(_readTill)) ? till->second : 0;
|
||||||
const auto pendingMaxId = [&] {
|
const auto pendingMaxId = [&] {
|
||||||
const auto j = _pendingUserStateMaxId.find(peer);
|
const auto j = _pendingPeerStateMaxId.find(peer);
|
||||||
return (j != end(_pendingUserStateMaxId)) ? j->second : 0;
|
return (j != end(_pendingPeerStateMaxId)) ? j->second : 0;
|
||||||
};
|
};
|
||||||
const auto i = _all.find(peer->id);
|
const auto i = _all.find(peer->id);
|
||||||
const auto max = (i != end(_all))
|
const auto max = (i != end(_all))
|
||||||
? (i->second.ids.empty() ? 0 : i->second.ids.back().id)
|
? (i->second.ids.empty() ? 0 : i->second.ids.back().id)
|
||||||
: pendingMaxId();
|
: pendingMaxId();
|
||||||
if (const auto user = peer->asUser()) {
|
peer->setStoriesState(!max
|
||||||
user->setStoriesState(!max
|
? PeerData::StoriesState::None
|
||||||
? UserData::StoriesState::None
|
: (max <= readTill)
|
||||||
: (max <= readTill)
|
? PeerData::StoriesState::HasRead
|
||||||
? UserData::StoriesState::HasRead
|
: PeerData::StoriesState::HasUnread);
|
||||||
: UserData::StoriesState::HasUnread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stories::preloadSourcesChanged(StorySourcesList list) {
|
void Stories::preloadSourcesChanged(StorySourcesList list) {
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct StoriesSourceInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StoriesSource {
|
struct StoriesSource {
|
||||||
not_null<UserData*> user;
|
not_null<PeerData*> peer;
|
||||||
base::flat_set<StoryIdDates> ids;
|
base::flat_set<StoryIdDates> ids;
|
||||||
StoryId readTill = 0;
|
StoryId readTill = 0;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
|
@ -148,7 +148,7 @@ public:
|
||||||
void apply(const MTPDupdateStory &data);
|
void apply(const MTPDupdateStory &data);
|
||||||
void apply(const MTPDupdateReadStories &data);
|
void apply(const MTPDupdateReadStories &data);
|
||||||
void apply(const MTPStoriesStealthMode &stealthMode);
|
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);
|
Story *applyFromWebpage(PeerId peerId, const MTPstoryItem &story);
|
||||||
void loadAround(FullStoryId id, StoriesContext context);
|
void loadAround(FullStoryId id, StoriesContext context);
|
||||||
|
|
||||||
|
@ -228,8 +228,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] bool registerPolling(FullStoryId id, Polling polling);
|
[[nodiscard]] bool registerPolling(FullStoryId id, Polling polling);
|
||||||
void unregisterPolling(FullStoryId id, Polling polling);
|
void unregisterPolling(FullStoryId id, Polling polling);
|
||||||
void requestUserStories(
|
void requestPeerStories(
|
||||||
not_null<UserData*> user,
|
not_null<PeerData*> peer,
|
||||||
Fn<void()> done = nullptr);
|
Fn<void()> done = nullptr);
|
||||||
|
|
||||||
void savedStateChanged(not_null<Story*> story);
|
void savedStateChanged(not_null<Story*> story);
|
||||||
|
@ -255,7 +255,7 @@ private:
|
||||||
int viewer = 0;
|
int viewer = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void parseAndApply(const MTPUserStories &stories);
|
void parseAndApply(const MTPPeerStories &stories);
|
||||||
[[nodiscard]] Story *parseAndApply(
|
[[nodiscard]] Story *parseAndApply(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const MTPDstoryItem &data,
|
const MTPDstoryItem &data,
|
||||||
|
@ -269,7 +269,7 @@ private:
|
||||||
const QVector<MTPStoryItem> &list);
|
const QVector<MTPStoryItem> &list);
|
||||||
void sendResolveRequests();
|
void sendResolveRequests();
|
||||||
void finalizeResolve(FullStoryId id);
|
void finalizeResolve(FullStoryId id);
|
||||||
void updateUserStoriesState(not_null<PeerData*> peer);
|
void updatePeerStoriesState(not_null<PeerData*> peer);
|
||||||
|
|
||||||
void applyDeleted(FullStoryId id);
|
void applyDeleted(FullStoryId id);
|
||||||
void applyExpired(FullStoryId id);
|
void applyExpired(FullStoryId id);
|
||||||
|
@ -360,8 +360,8 @@ private:
|
||||||
base::Timer _markReadTimer;
|
base::Timer _markReadTimer;
|
||||||
base::flat_set<PeerId> _markReadRequests;
|
base::flat_set<PeerId> _markReadRequests;
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
not_null<UserData*>,
|
not_null<PeerData*>,
|
||||||
std::vector<Fn<void()>>> _requestingUserStories;
|
std::vector<Fn<void()>>> _requestingPeerStories;
|
||||||
|
|
||||||
base::flat_map<PeerId, base::flat_set<StoryId>> _incrementViewsPending;
|
base::flat_map<PeerId, base::flat_set<StoryId>> _incrementViewsPending;
|
||||||
base::Timer _incrementViewsTimer;
|
base::Timer _incrementViewsTimer;
|
||||||
|
@ -381,7 +381,7 @@ private:
|
||||||
|
|
||||||
base::flat_map<PeerId, StoryId> _readTill;
|
base::flat_map<PeerId, StoryId> _readTill;
|
||||||
base::flat_set<FullStoryId> _pendingReadTillItems;
|
base::flat_set<FullStoryId> _pendingReadTillItems;
|
||||||
base::flat_map<not_null<PeerData*>, StoryId> _pendingUserStateMaxId;
|
base::flat_map<not_null<PeerData*>, StoryId> _pendingPeerStateMaxId;
|
||||||
mtpRequestId _readTillsRequestId = 0;
|
mtpRequestId _readTillsRequestId = 0;
|
||||||
bool _readTillReceived = false;
|
bool _readTillReceived = false;
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,25 @@ using UpdateFlag = StoryUpdate::Flag;
|
||||||
});
|
});
|
||||||
}, [](const MTPDgeoPointEmpty &) {
|
}, [](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) {
|
}, [&](const MTPDinputMediaAreaVenue &data) {
|
||||||
LOG(("API Error: Unexpected inputMediaAreaVenue in API data."));
|
LOG(("API Error: Unexpected inputMediaAreaVenue in API data."));
|
||||||
});
|
});
|
||||||
|
@ -317,6 +336,10 @@ bool Story::edited() const {
|
||||||
return _edited;
|
return _edited;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Story::out() const {
|
||||||
|
return _out;
|
||||||
|
}
|
||||||
|
|
||||||
bool Story::canDownloadIfPremium() const {
|
bool Story::canDownloadIfPremium() const {
|
||||||
return !forbidsForward() || _peer->isSelf();
|
return !forbidsForward() || _peer->isSelf();
|
||||||
}
|
}
|
||||||
|
@ -455,6 +478,10 @@ const std::vector<StoryLocation> &Story::locations() const {
|
||||||
return _locations;
|
return _locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<SuggestedReaction> &Story::suggestedReactions() const {
|
||||||
|
return _suggestedReactions;
|
||||||
|
}
|
||||||
|
|
||||||
void Story::applyChanges(
|
void Story::applyChanges(
|
||||||
StoryMedia media,
|
StoryMedia media,
|
||||||
const MTPDstoryItem &data,
|
const MTPDstoryItem &data,
|
||||||
|
@ -486,6 +513,7 @@ void Story::applyFields(
|
||||||
? StoryPrivacy::SelectedContacts
|
? StoryPrivacy::SelectedContacts
|
||||||
: StoryPrivacy::Other;
|
: StoryPrivacy::Other;
|
||||||
const auto noForwards = data.is_noforwards();
|
const auto noForwards = data.is_noforwards();
|
||||||
|
const auto out = data.is_min() ? _out : data.is_out();
|
||||||
auto caption = TextWithEntities{
|
auto caption = TextWithEntities{
|
||||||
data.vcaption().value_or_empty(),
|
data.vcaption().value_or_empty(),
|
||||||
Api::EntitiesFromMTP(
|
Api::EntitiesFromMTP(
|
||||||
|
@ -497,7 +525,7 @@ void Story::applyFields(
|
||||||
auto viewers = std::vector<not_null<PeerData*>>();
|
auto viewers = std::vector<not_null<PeerData*>>();
|
||||||
if (const auto info = data.vviews()) {
|
if (const auto info = data.vviews()) {
|
||||||
views = info->data().vviews_count().v;
|
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()) {
|
if (const auto list = info->data().vrecent_viewers()) {
|
||||||
viewers.reserve(list->v.size());
|
viewers.reserve(list->v.size());
|
||||||
auto &owner = _peer->owner();
|
auto &owner = _peer->owner();
|
||||||
|
@ -511,11 +539,15 @@ void Story::applyFields(
|
||||||
viewers = _recentViewers;
|
viewers = _recentViewers;
|
||||||
}
|
}
|
||||||
auto locations = std::vector<StoryLocation>();
|
auto locations = std::vector<StoryLocation>();
|
||||||
|
auto suggestedReactions = std::vector<SuggestedReaction>();
|
||||||
if (const auto areas = data.vmedia_areas()) {
|
if (const auto areas = data.vmedia_areas()) {
|
||||||
locations.reserve(areas->v.size());
|
locations.reserve(areas->v.size());
|
||||||
|
suggestedReactions.reserve(areas->v.size());
|
||||||
for (const auto &area : areas->v) {
|
for (const auto &area : areas->v) {
|
||||||
if (const auto location = ParseLocation(area)) {
|
if (const auto location = ParseLocation(area)) {
|
||||||
locations.push_back(*location);
|
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)
|
|| (_views.reactions != reactions)
|
||||||
|| (_recentViewers != viewers);
|
|| (_recentViewers != viewers);
|
||||||
const auto locationsChanged = (_locations != locations);
|
const auto locationsChanged = (_locations != locations);
|
||||||
|
const auto suggestedReactionsChanged
|
||||||
|
= (_suggestedReactions != suggestedReactions);
|
||||||
const auto reactionChanged = (_sentReactionId != reaction);
|
const auto reactionChanged = (_sentReactionId != reaction);
|
||||||
|
|
||||||
|
_out = out;
|
||||||
_privacyPublic = (privacy == StoryPrivacy::Public);
|
_privacyPublic = (privacy == StoryPrivacy::Public);
|
||||||
_privacyCloseFriends = (privacy == StoryPrivacy::CloseFriends);
|
_privacyCloseFriends = (privacy == StoryPrivacy::CloseFriends);
|
||||||
_privacyContacts = (privacy == StoryPrivacy::Contacts);
|
_privacyContacts = (privacy == StoryPrivacy::Contacts);
|
||||||
_privacySelectedContacts = (privacy == StoryPrivacy::SelectedContacts);
|
_privacySelectedContacts = (privacy == StoryPrivacy::SelectedContacts);
|
||||||
_noForwards = noForwards;
|
|
||||||
_edited = edited;
|
_edited = edited;
|
||||||
_pinned = pinned;
|
_pinned = pinned;
|
||||||
_noForwards = noForwards;
|
_noForwards = noForwards;
|
||||||
|
@ -553,6 +587,9 @@ void Story::applyFields(
|
||||||
if (locationsChanged) {
|
if (locationsChanged) {
|
||||||
_locations = std::move(locations);
|
_locations = std::move(locations);
|
||||||
}
|
}
|
||||||
|
if (suggestedReactionsChanged) {
|
||||||
|
_suggestedReactions = std::move(suggestedReactions);
|
||||||
|
}
|
||||||
if (reactionChanged) {
|
if (reactionChanged) {
|
||||||
_sentReactionId = reaction;
|
_sentReactionId = reaction;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +597,8 @@ void Story::applyFields(
|
||||||
const auto changed = editedChanged
|
const auto changed = editedChanged
|
||||||
|| captionChanged
|
|| captionChanged
|
||||||
|| mediaChanged
|
|| mediaChanged
|
||||||
|| locationsChanged;
|
|| locationsChanged
|
||||||
|
|| suggestedReactionsChanged;
|
||||||
if (!initial && (changed || viewsChanged || reactionChanged)) {
|
if (!initial && (changed || viewsChanged || reactionChanged)) {
|
||||||
_peer->session().changes().storyUpdated(this, UpdateFlag()
|
_peer->session().changes().storyUpdated(this, UpdateFlag()
|
||||||
| (changed ? UpdateFlag::Edited : UpdateFlag())
|
| (changed ? UpdateFlag::Edited : UpdateFlag())
|
||||||
|
|
|
@ -96,6 +96,17 @@ struct StoryLocation {
|
||||||
const StoryLocation &) = default;
|
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 {
|
class Story final {
|
||||||
public:
|
public:
|
||||||
Story(
|
Story(
|
||||||
|
@ -132,6 +143,7 @@ public:
|
||||||
[[nodiscard]] StoryPrivacy privacy() const;
|
[[nodiscard]] StoryPrivacy privacy() const;
|
||||||
[[nodiscard]] bool forbidsForward() const;
|
[[nodiscard]] bool forbidsForward() const;
|
||||||
[[nodiscard]] bool edited() const;
|
[[nodiscard]] bool edited() const;
|
||||||
|
[[nodiscard]] bool out() const;
|
||||||
|
|
||||||
[[nodiscard]] bool canDownloadIfPremium() const;
|
[[nodiscard]] bool canDownloadIfPremium() const;
|
||||||
[[nodiscard]] bool canDownloadChecked() const;
|
[[nodiscard]] bool canDownloadChecked() const;
|
||||||
|
@ -157,6 +169,8 @@ public:
|
||||||
void applyViewsSlice(const QString &offset, const StoryViews &slice);
|
void applyViewsSlice(const QString &offset, const StoryViews &slice);
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<StoryLocation> &locations() const;
|
[[nodiscard]] const std::vector<StoryLocation> &locations() const;
|
||||||
|
[[nodiscard]] auto suggestedReactions() const
|
||||||
|
-> const std::vector<SuggestedReaction> &;
|
||||||
|
|
||||||
void applyChanges(
|
void applyChanges(
|
||||||
StoryMedia media,
|
StoryMedia media,
|
||||||
|
@ -178,10 +192,12 @@ private:
|
||||||
TextWithEntities _caption;
|
TextWithEntities _caption;
|
||||||
std::vector<not_null<PeerData*>> _recentViewers;
|
std::vector<not_null<PeerData*>> _recentViewers;
|
||||||
std::vector<StoryLocation> _locations;
|
std::vector<StoryLocation> _locations;
|
||||||
|
std::vector<SuggestedReaction> _suggestedReactions;
|
||||||
StoryViews _views;
|
StoryViews _views;
|
||||||
const TimeId _date = 0;
|
const TimeId _date = 0;
|
||||||
const TimeId _expires = 0;
|
const TimeId _expires = 0;
|
||||||
TimeId _lastUpdateTime = 0;
|
TimeId _lastUpdateTime = 0;
|
||||||
|
bool _out : 1 = false;
|
||||||
bool _pinned : 1 = false;
|
bool _pinned : 1 = false;
|
||||||
bool _privacyPublic : 1 = false;
|
bool _privacyPublic : 1 = false;
|
||||||
bool _privacyCloseFriends : 1 = false;
|
bool _privacyCloseFriends : 1 = false;
|
||||||
|
|
|
@ -127,18 +127,17 @@ void UserData::setPrivateForwardName(const QString &name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserData::hasActiveStories() const {
|
bool UserData::hasActiveStories() const {
|
||||||
return flags() & UserDataFlag::HasActiveStories;
|
return flags() & Flag::HasActiveStories;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserData::hasUnreadStories() const {
|
bool UserData::hasUnreadStories() const {
|
||||||
return flags() & UserDataFlag::HasUnreadStories;
|
return flags() & Flag::HasUnreadStories;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserData::setStoriesState(StoriesState state) {
|
void UserData::setStoriesState(StoriesState state) {
|
||||||
Expects(state != StoriesState::Unknown);
|
Expects(state != StoriesState::Unknown);
|
||||||
|
|
||||||
const auto was = flags();
|
const auto was = flags();
|
||||||
using Flag = UserDataFlag;
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case StoriesState::None:
|
case StoriesState::None:
|
||||||
_flags.remove(Flag::HasActiveStories | Flag::HasUnreadStories);
|
_flags.remove(Flag::HasActiveStories | Flag::HasUnreadStories);
|
||||||
|
|
|
@ -176,12 +176,6 @@ public:
|
||||||
[[nodiscard]] QString privateForwardName() const;
|
[[nodiscard]] QString privateForwardName() const;
|
||||||
void setPrivateForwardName(const QString &name);
|
void setPrivateForwardName(const QString &name);
|
||||||
|
|
||||||
enum class StoriesState {
|
|
||||||
Unknown,
|
|
||||||
None,
|
|
||||||
HasRead,
|
|
||||||
HasUnread,
|
|
||||||
};
|
|
||||||
[[nodiscard]] bool hasActiveStories() const;
|
[[nodiscard]] bool hasActiveStories() const;
|
||||||
[[nodiscard]] bool hasUnreadStories() const;
|
[[nodiscard]] bool hasUnreadStories() const;
|
||||||
void setStoriesState(StoriesState state);
|
void setStoriesState(StoriesState state);
|
||||||
|
|
|
@ -134,7 +134,7 @@ private:
|
||||||
const not_null<Data::Stories*> _data;
|
const not_null<Data::Stories*> _data;
|
||||||
const Data::StorySourcesList _list;
|
const Data::StorySourcesList _list;
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
not_null<UserData*>,
|
not_null<PeerData*>,
|
||||||
std::shared_ptr<Thumbnail>> _userpics;
|
std::shared_ptr<Thumbnail>> _userpics;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -338,20 +338,20 @@ Content State::next() {
|
||||||
Assert(source != nullptr);
|
Assert(source != nullptr);
|
||||||
|
|
||||||
auto userpic = std::shared_ptr<Thumbnail>();
|
auto userpic = std::shared_ptr<Thumbnail>();
|
||||||
const auto user = source->user;
|
const auto peer = source->peer;
|
||||||
if (const auto i = _userpics.find(user); i != end(_userpics)) {
|
if (const auto i = _userpics.find(peer); i != end(_userpics)) {
|
||||||
userpic = i->second;
|
userpic = i->second;
|
||||||
} else {
|
} else {
|
||||||
userpic = MakeUserpicThumbnail(user);
|
userpic = MakeUserpicThumbnail(peer);
|
||||||
_userpics.emplace(user, userpic);
|
_userpics.emplace(peer, userpic);
|
||||||
}
|
}
|
||||||
result.elements.push_back({
|
result.elements.push_back({
|
||||||
.id = uint64(user->id.value),
|
.id = uint64(peer->id.value),
|
||||||
.name = user->shortName(),
|
.name = peer->shortName(),
|
||||||
.thumbnail = std::move(userpic),
|
.thumbnail = std::move(userpic),
|
||||||
.count = info.count,
|
.count = info.count,
|
||||||
.unreadCount = info.unreadCount,
|
.unreadCount = info.unreadCount,
|
||||||
.skipSmall = user->isSelf() ? 1U : 0U,
|
.skipSmall = peer->isSelf() ? 1U : 0U,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -504,6 +504,7 @@ void ApiWrap::requestStoriesCount() {
|
||||||
Expects(_startProcess != nullptr);
|
Expects(_startProcess != nullptr);
|
||||||
|
|
||||||
mainRequest(MTPstories_GetStoriesArchive(
|
mainRequest(MTPstories_GetStoriesArchive(
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTP_int(0), // offset_id
|
MTP_int(0), // offset_id
|
||||||
MTP_int(0) // limit
|
MTP_int(0) // limit
|
||||||
)).done([=](const MTPstories_Stories &result) {
|
)).done([=](const MTPstories_Stories &result) {
|
||||||
|
@ -907,6 +908,7 @@ void ApiWrap::requestStories(
|
||||||
_storiesProcess->finish = std::move(finish);
|
_storiesProcess->finish = std::move(finish);
|
||||||
|
|
||||||
mainRequest(MTPstories_GetStoriesArchive(
|
mainRequest(MTPstories_GetStoriesArchive(
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTP_int(_storiesProcess->offsetId),
|
MTP_int(_storiesProcess->offsetId),
|
||||||
MTP_int(kStoriesSliceLimit)
|
MTP_int(kStoriesSliceLimit)
|
||||||
)).done([=](const MTPstories_Stories &result) mutable {
|
)).done([=](const MTPstories_Stories &result) mutable {
|
||||||
|
@ -993,6 +995,7 @@ void ApiWrap::finishStoriesSlice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
mainRequest(MTPstories_GetStoriesArchive(
|
mainRequest(MTPstories_GetStoriesArchive(
|
||||||
|
MTP_inputPeerSelf(),
|
||||||
MTP_int(_storiesProcess->offsetId),
|
MTP_int(_storiesProcess->offsetId),
|
||||||
MTP_int(kStoriesSliceLimit)
|
MTP_int(kStoriesSliceLimit)
|
||||||
)).done([=](const MTPstories_Stories &result) {
|
)).done([=](const MTPstories_Stories &result) {
|
||||||
|
@ -2186,7 +2189,7 @@ void ApiWrap::filePartRefreshReference(int64 offset) {
|
||||||
const auto &origin = _fileProcess->origin;
|
const auto &origin = _fileProcess->origin;
|
||||||
if (origin.storyId) {
|
if (origin.storyId) {
|
||||||
_fileProcess->requestId = mainRequest(MTPstories_GetStoriesByID(
|
_fileProcess->requestId = mainRequest(MTPstories_GetStoriesByID(
|
||||||
MTP_inputUserSelf(),
|
MTP_inputPeerSelf(),
|
||||||
MTP_vector<MTPint>(1, MTP_int(origin.storyId))
|
MTP_vector<MTPint>(1, MTP_int(origin.storyId))
|
||||||
)).fail([=](const MTP::Error &error) {
|
)).fail([=](const MTP::Error &error) {
|
||||||
_fileProcess->requestId = 0;
|
_fileProcess->requestId = 0;
|
||||||
|
|
|
@ -287,7 +287,7 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
|
||||||
media.vvalue().v);
|
media.vvalue().v);
|
||||||
}, [&](const MTPDmessageMediaStory &media) -> Result {
|
}, [&](const MTPDmessageMediaStory &media) -> Result {
|
||||||
return std::make_unique<Data::MediaStory>(item, FullStoryId{
|
return std::make_unique<Data::MediaStory>(item, FullStoryId{
|
||||||
peerFromUser(media.vuser_id()),
|
peerFromMTP(media.vpeer()),
|
||||||
media.vid().v,
|
media.vid().v,
|
||||||
}, media.is_via_mention());
|
}, media.is_via_mention());
|
||||||
}, [](const MTPDmessageMediaEmpty &) -> Result {
|
}, [](const MTPDmessageMediaEmpty &) -> Result {
|
||||||
|
@ -1981,7 +1981,7 @@ bool HistoryItem::canBeEdited() const {
|
||||||
return true;
|
return true;
|
||||||
} else if (out()) {
|
} else if (out()) {
|
||||||
if (isPost()) {
|
if (isPost()) {
|
||||||
return channel->canPublish();
|
return channel->canPostMessages();
|
||||||
} else if (const auto topic = this->topic()) {
|
} else if (const auto topic = this->topic()) {
|
||||||
return Data::CanSendAnything(topic);
|
return Data::CanSendAnything(topic);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2033,9 +2033,8 @@ bool HistoryItem::canDelete() const {
|
||||||
}
|
}
|
||||||
if (channel->canDeleteMessages()) {
|
if (channel->canDeleteMessages()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (out() && !isService()) {
|
||||||
if (out() && !isService()) {
|
return isPost() ? channel->canPostMessages() : true;
|
||||||
return isPost() ? channel->canPublish() : true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4575,7 +4575,7 @@ bool HistoryWidget::isChoosingTheme() const {
|
||||||
|
|
||||||
bool HistoryWidget::isMuteUnmute() const {
|
bool HistoryWidget::isMuteUnmute() const {
|
||||||
return _peer
|
return _peer
|
||||||
&& ((_peer->isBroadcast() && !_peer->asChannel()->canPublish())
|
&& ((_peer->isBroadcast() && !_peer->asChannel()->canPostMessages())
|
||||||
|| (_peer->isGigagroup() && !Data::CanSendAnything(_peer))
|
|| (_peer->isGigagroup() && !Data::CanSendAnything(_peer))
|
||||||
|| _peer->isRepliesChat());
|
|| _peer->isRepliesChat());
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_stories.h"
|
#include "data/data_stories.h"
|
||||||
#include "data/data_user.h"
|
|
||||||
#include "history/view/reactions/history_view_reactions_strip.h"
|
#include "history/view/reactions/history_view_reactions_strip.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -62,7 +62,7 @@ constexpr auto kSiblingMultiplierMax = 0.72;
|
||||||
constexpr auto kSiblingOutsidePart = 0.24;
|
constexpr auto kSiblingOutsidePart = 0.24;
|
||||||
constexpr auto kSiblingUserpicSize = 0.3;
|
constexpr auto kSiblingUserpicSize = 0.3;
|
||||||
constexpr auto kInnerHeightMultiplier = 1.6;
|
constexpr auto kInnerHeightMultiplier = 1.6;
|
||||||
constexpr auto kPreloadUsersCount = 3;
|
constexpr auto kPreloadPeersCount = 3;
|
||||||
constexpr auto kPreloadStoriesCount = 5;
|
constexpr auto kPreloadStoriesCount = 5;
|
||||||
constexpr auto kPreloadNextMediaCount = 3;
|
constexpr auto kPreloadNextMediaCount = 3;
|
||||||
constexpr auto kPreloadPreviousMediaCount = 1;
|
constexpr auto kPreloadPreviousMediaCount = 1;
|
||||||
|
@ -140,10 +140,10 @@ private:
|
||||||
|
|
||||||
class Controller::Unsupported final {
|
class Controller::Unsupported final {
|
||||||
public:
|
public:
|
||||||
Unsupported(not_null<Controller*> controller, not_null<UserData*> user);
|
Unsupported(not_null<Controller*> controller, not_null<PeerData*> peer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setup(not_null<UserData*> user);
|
void setup(not_null<PeerData*> peer);
|
||||||
|
|
||||||
const not_null<Controller*> _controller;
|
const not_null<Controller*> _controller;
|
||||||
std::unique_ptr<Ui::RpWidget> _bg;
|
std::unique_ptr<Ui::RpWidget> _bg;
|
||||||
|
@ -206,13 +206,13 @@ void Controller::PhotoPlayback::callback() {
|
||||||
|
|
||||||
Controller::Unsupported::Unsupported(
|
Controller::Unsupported::Unsupported(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
not_null<UserData*> user)
|
not_null<PeerData*> peer)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _bgRound(st::storiesRadius, st::storiesComposeBg) {
|
, _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();
|
const auto wrap = _controller->wrap();
|
||||||
|
|
||||||
_bg = std::make_unique<Ui::RpWidget>(wrap);
|
_bg = std::make_unique<Ui::RpWidget>(wrap);
|
||||||
|
@ -596,8 +596,8 @@ void Controller::toggleLiked() {
|
||||||
void Controller::reactionChosen(ReactionsMode mode, ChosenReaction chosen) {
|
void Controller::reactionChosen(ReactionsMode mode, ChosenReaction chosen) {
|
||||||
if (mode == ReactionsMode::Message) {
|
if (mode == ReactionsMode::Message) {
|
||||||
_replyArea->sendReaction(chosen.id);
|
_replyArea->sendReaction(chosen.id);
|
||||||
} else if (const auto user = shownUser()) {
|
} else if (const auto peer = shownPeer()) {
|
||||||
user->owner().stories().sendReaction(_shown, chosen.id);
|
peer->owner().stories().sendReaction(_shown, chosen.id);
|
||||||
}
|
}
|
||||||
unfocusReply();
|
unfocusReply();
|
||||||
}
|
}
|
||||||
|
@ -638,11 +638,11 @@ auto Controller::cachedReactionIconFactory() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::rebuildFromContext(
|
void Controller::rebuildFromContext(
|
||||||
not_null<UserData*> user,
|
not_null<PeerData*> peer,
|
||||||
FullStoryId storyId) {
|
FullStoryId storyId) {
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
|
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
auto list = std::optional<StoriesList>();
|
auto list = std::optional<StoriesList>();
|
||||||
auto source = (const StoriesSource*)nullptr;
|
auto source = (const StoriesSource*)nullptr;
|
||||||
const auto peerId = storyId.peer;
|
const auto peerId = storyId.peer;
|
||||||
|
@ -659,7 +659,7 @@ void Controller::rebuildFromContext(
|
||||||
const auto i = ids.find(id);
|
const auto i = ids.find(id);
|
||||||
if (i != end(ids)) {
|
if (i != end(ids)) {
|
||||||
list = StoriesList{
|
list = StoriesList{
|
||||||
.user = user,
|
.peer = peer,
|
||||||
.ids = *saved,
|
.ids = *saved,
|
||||||
.total = stories.savedCount(peerId),
|
.total = stories.savedCount(peerId),
|
||||||
};
|
};
|
||||||
|
@ -673,7 +673,7 @@ void Controller::rebuildFromContext(
|
||||||
}
|
}
|
||||||
hideSiblings();
|
hideSiblings();
|
||||||
}, [&](StoriesContextArchive) {
|
}, [&](StoriesContextArchive) {
|
||||||
Expects(user->isSelf());
|
Expects(peer->isSelf());
|
||||||
|
|
||||||
if (stories.archiveCountKnown()) {
|
if (stories.archiveCountKnown()) {
|
||||||
const auto &archive = stories.archive();
|
const auto &archive = stories.archive();
|
||||||
|
@ -681,7 +681,7 @@ void Controller::rebuildFromContext(
|
||||||
const auto i = ids.find(id);
|
const auto i = ids.find(id);
|
||||||
if (i != end(ids)) {
|
if (i != end(ids)) {
|
||||||
list = StoriesList{
|
list = StoriesList{
|
||||||
.user = user,
|
.peer = peer,
|
||||||
.ids = archive,
|
.ids = archive,
|
||||||
.total = stories.archiveCount(),
|
.total = stories.archiveCount(),
|
||||||
};
|
};
|
||||||
|
@ -706,8 +706,8 @@ void Controller::rebuildFromContext(
|
||||||
}
|
}
|
||||||
rebuildCachedSourcesList(sources, (i - begin(sources)));
|
rebuildCachedSourcesList(sources, (i - begin(sources)));
|
||||||
_cachedSourcesList[_cachedSourceIndex].shownId = storyId.story;
|
_cachedSourcesList[_cachedSourceIndex].shownId = storyId.story;
|
||||||
showSiblings(&user->session());
|
showSiblings(&peer->session());
|
||||||
if (int(sources.end() - i) < kPreloadUsersCount) {
|
if (int(sources.end() - i) < kPreloadPeersCount) {
|
||||||
stories.loadMore(list);
|
stories.loadMore(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -719,7 +719,7 @@ void Controller::rebuildFromContext(
|
||||||
if (_list != list) {
|
if (_list != list) {
|
||||||
_list = std::move(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 now = *maybe;
|
||||||
const auto range = ComputeSameDayRange(now, _list->ids, _index);
|
const auto range = ComputeSameDayRange(now, _list->ids, _index);
|
||||||
_sliderCount = range.till - range.from + 1;
|
_sliderCount = range.till - range.from + 1;
|
||||||
|
@ -737,7 +737,7 @@ void Controller::rebuildFromContext(
|
||||||
if (!source) {
|
if (!source) {
|
||||||
_source = std::nullopt;
|
_source = std::nullopt;
|
||||||
_list = StoriesList{
|
_list = StoriesList{
|
||||||
.user = user,
|
.peer = peer,
|
||||||
.ids = { { id } },
|
.ids = { { id } },
|
||||||
.total = 1,
|
.total = 1,
|
||||||
};
|
};
|
||||||
|
@ -761,17 +761,17 @@ void Controller::preloadNext() {
|
||||||
|
|
||||||
auto ids = std::vector<FullStoryId>();
|
auto ids = std::vector<FullStoryId>();
|
||||||
ids.reserve(kPreloadPreviousMediaCount + kPreloadNextMediaCount);
|
ids.reserve(kPreloadPreviousMediaCount + kPreloadNextMediaCount);
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
const auto count = shownCount();
|
const auto count = shownCount();
|
||||||
const auto till = std::min(_index + kPreloadNextMediaCount, count);
|
const auto till = std::min(_index + kPreloadNextMediaCount, count);
|
||||||
for (auto i = _index + 1; i != till; ++i) {
|
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);
|
const auto from = std::max(_index - kPreloadPreviousMediaCount, 0);
|
||||||
for (auto i = _index; i != from;) {
|
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() {
|
void Controller::checkMoveByDelta() {
|
||||||
|
@ -786,18 +786,18 @@ void Controller::show(
|
||||||
Data::StoriesContext context) {
|
Data::StoriesContext context) {
|
||||||
auto &stories = story->owner().stories();
|
auto &stories = story->owner().stories();
|
||||||
const auto storyId = story->fullId();
|
const auto storyId = story->fullId();
|
||||||
const auto user = story->peer()->asUser();
|
const auto peer = story->peer();
|
||||||
_context = context;
|
_context = context;
|
||||||
_waitingForId = {};
|
_waitingForId = {};
|
||||||
_waitingForDelta = 0;
|
_waitingForDelta = 0;
|
||||||
|
|
||||||
rebuildFromContext(user, storyId);
|
rebuildFromContext(peer, storyId);
|
||||||
_contextLifetime.destroy();
|
_contextLifetime.destroy();
|
||||||
const auto subscribeToSource = [&] {
|
const auto subscribeToSource = [&] {
|
||||||
stories.sourceChanged() | rpl::filter(
|
stories.sourceChanged() | rpl::filter(
|
||||||
rpl::mappers::_1 == storyId.peer
|
rpl::mappers::_1 == storyId.peer
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
rebuildFromContext(user, storyId);
|
rebuildFromContext(peer, storyId);
|
||||||
}, _contextLifetime);
|
}, _contextLifetime);
|
||||||
};
|
};
|
||||||
v::match(_context.data, [&](Data::StoriesContextSingle) {
|
v::match(_context.data, [&](Data::StoriesContextSingle) {
|
||||||
|
@ -807,13 +807,13 @@ void Controller::show(
|
||||||
stories.savedChanged() | rpl::filter(
|
stories.savedChanged() | rpl::filter(
|
||||||
rpl::mappers::_1 == storyId.peer
|
rpl::mappers::_1 == storyId.peer
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
rebuildFromContext(user, storyId);
|
rebuildFromContext(peer, storyId);
|
||||||
checkMoveByDelta();
|
checkMoveByDelta();
|
||||||
}, _contextLifetime);
|
}, _contextLifetime);
|
||||||
}, [&](Data::StoriesContextArchive) {
|
}, [&](Data::StoriesContextArchive) {
|
||||||
stories.archiveChanged(
|
stories.archiveChanged(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
rebuildFromContext(user, storyId);
|
rebuildFromContext(peer, storyId);
|
||||||
checkMoveByDelta();
|
checkMoveByDelta();
|
||||||
}, _contextLifetime);
|
}, _contextLifetime);
|
||||||
}, [&](Data::StorySourcesList) {
|
}, [&](Data::StorySourcesList) {
|
||||||
|
@ -834,7 +834,7 @@ void Controller::show(
|
||||||
if (!unsupported) {
|
if (!unsupported) {
|
||||||
_unsupported = nullptr;
|
_unsupported = nullptr;
|
||||||
} else {
|
} else {
|
||||||
_unsupported = std::make_unique<Unsupported>(this, user);
|
_unsupported = std::make_unique<Unsupported>(this, peer);
|
||||||
_header->raise();
|
_header->raise();
|
||||||
_slider->raise();
|
_slider->raise();
|
||||||
}
|
}
|
||||||
|
@ -845,7 +845,7 @@ void Controller::show(
|
||||||
_contentFadeAnimation.stop();
|
_contentFadeAnimation.stop();
|
||||||
const auto document = story->document();
|
const auto document = story->document();
|
||||||
_header->show({
|
_header->show({
|
||||||
.user = user,
|
.peer = peer,
|
||||||
.date = story->date(),
|
.date = story->date(),
|
||||||
.fullIndex = _sliderCount ? _index : 0,
|
.fullIndex = _sliderCount ? _index : 0,
|
||||||
.fullCount = _sliderCount ? shownCount() : 0,
|
.fullCount = _sliderCount ? shownCount() : 0,
|
||||||
|
@ -866,7 +866,7 @@ void Controller::show(
|
||||||
}
|
}
|
||||||
|
|
||||||
_replyArea->show({
|
_replyArea->show({
|
||||||
.user = unsupported ? nullptr : user,
|
.peer = unsupported ? nullptr : peer.get(),
|
||||||
.id = story->id(),
|
.id = story->id(),
|
||||||
}, _reactions->likedValue());
|
}, _reactions->likedValue());
|
||||||
|
|
||||||
|
@ -874,13 +874,13 @@ void Controller::show(
|
||||||
.list = story->recentViewers(),
|
.list = story->recentViewers(),
|
||||||
.reactions = story->reactions(),
|
.reactions = story->reactions(),
|
||||||
.total = story->views(),
|
.total = story->views(),
|
||||||
.valid = user->isSelf(),
|
.valid = peer->isSelf(),
|
||||||
});
|
});
|
||||||
|
|
||||||
stories.loadAround(storyId, context);
|
stories.loadAround(storyId, context);
|
||||||
|
|
||||||
updatePlayingAllowed();
|
updatePlayingAllowed();
|
||||||
user->updateFull();
|
peer->updateFull();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::changeShown(Data::Story *story) {
|
bool Controller::changeShown(Data::Story *story) {
|
||||||
|
@ -1129,7 +1129,7 @@ void Controller::markAsRead() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_viewed = true;
|
_viewed = true;
|
||||||
shownUser()->owner().stories().markAsRead(_shown, _started);
|
shownPeer()->owner().stories().markAsRead(_shown, _started);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::subjumpAvailable(int delta) const {
|
bool Controller::subjumpAvailable(int delta) const {
|
||||||
|
@ -1169,12 +1169,12 @@ void Controller::subjumpTo(int index) {
|
||||||
Expects(shown());
|
Expects(shown());
|
||||||
Expects(index >= 0 && index < shownCount());
|
Expects(index >= 0 && index < shownCount());
|
||||||
|
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
const auto id = FullStoryId{
|
const auto id = FullStoryId{
|
||||||
.peer = user->id,
|
.peer = peer->id,
|
||||||
.story = shownId(index),
|
.story = shownId(index),
|
||||||
};
|
};
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
if (!id.story) {
|
if (!id.story) {
|
||||||
const auto delta = index - _index;
|
const auto delta = index - _index;
|
||||||
if (_waitingForDelta != delta) {
|
if (_waitingForDelta != delta) {
|
||||||
|
@ -1183,7 +1183,7 @@ void Controller::subjumpTo(int index) {
|
||||||
loadMoreToList();
|
loadMoreToList();
|
||||||
}
|
}
|
||||||
} else if (stories.lookup(id)) {
|
} else if (stories.lookup(id)) {
|
||||||
_delegate->storiesJumpTo(&user->session(), id, _context);
|
_delegate->storiesJumpTo(&peer->session(), id, _context);
|
||||||
} else if (_waitingForId != id) {
|
} else if (_waitingForId != id) {
|
||||||
_waitingForId = id;
|
_waitingForId = id;
|
||||||
_waitingForDelta = 0;
|
_waitingForDelta = 0;
|
||||||
|
@ -1195,8 +1195,8 @@ void Controller::checkWaitingFor() {
|
||||||
Expects(_waitingForId.valid());
|
Expects(_waitingForId.valid());
|
||||||
Expects(shown());
|
Expects(shown());
|
||||||
|
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
const auto maybe = stories.lookup(_waitingForId);
|
const auto maybe = stories.lookup(_waitingForId);
|
||||||
if (!maybe) {
|
if (!maybe) {
|
||||||
if (maybe.error() == Data::NoStory::Deleted) {
|
if (maybe.error() == Data::NoStory::Deleted) {
|
||||||
|
@ -1205,7 +1205,7 @@ void Controller::checkWaitingFor() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_delegate->storiesJumpTo(
|
_delegate->storiesJumpTo(
|
||||||
&user->session(),
|
&peer->session(),
|
||||||
base::take(_waitingForId),
|
base::take(_waitingForId),
|
||||||
_context);
|
_context);
|
||||||
}
|
}
|
||||||
|
@ -1290,8 +1290,8 @@ const Data::StoryViews &Controller::views(int limit, bool initial) {
|
||||||
if (_viewsSlice.total > _viewsSlice.list.size()
|
if (_viewsSlice.total > _viewsSlice.list.size()
|
||||||
&& _viewsSlice.list.size() < limit) {
|
&& _viewsSlice.list.size() < limit) {
|
||||||
const auto done = viewsGotMoreCallback();
|
const auto done = viewsGotMoreCallback();
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
stories.loadViewsSlice(_shown.story, _viewsSlice.nextOffset, done);
|
stories.loadViewsSlice(_shown.story, _viewsSlice.nextOffset, done);
|
||||||
}
|
}
|
||||||
return _viewsSlice;
|
return _viewsSlice;
|
||||||
|
@ -1304,8 +1304,8 @@ rpl::producer<> Controller::moreViewsLoaded() const {
|
||||||
Fn<void(Data::StoryViews)> Controller::viewsGotMoreCallback() {
|
Fn<void(Data::StoryViews)> Controller::viewsGotMoreCallback() {
|
||||||
return crl::guard(&_viewsLoadGuard, [=](Data::StoryViews result) {
|
return crl::guard(&_viewsLoadGuard, [=](Data::StoryViews result) {
|
||||||
if (_viewsSlice.list.empty()) {
|
if (_viewsSlice.list.empty()) {
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
if (const auto maybeStory = stories.lookup(_shown)) {
|
if (const auto maybeStory = stories.lookup(_shown)) {
|
||||||
_viewsSlice = (*maybeStory)->viewsList();
|
_viewsSlice = (*maybeStory)->viewsList();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1329,11 +1329,11 @@ bool Controller::shown() const {
|
||||||
return _source || _list;
|
return _source || _list;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserData *Controller::shownUser() const {
|
PeerData *Controller::shownPeer() const {
|
||||||
return _source
|
return _source
|
||||||
? _source->user.get()
|
? _source->peer.get()
|
||||||
: _list
|
: _list
|
||||||
? _list->user.get()
|
? _list->peer.get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1356,13 +1356,13 @@ void Controller::loadMoreToList() {
|
||||||
|
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
|
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
const auto peerId = _shown.peer;
|
const auto peerId = _shown.peer;
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
v::match(_context.data, [&](StoriesContextSaved) {
|
v::match(_context.data, [&](StoriesContextSaved) {
|
||||||
stories.savedLoadMore(peerId);
|
stories.savedLoadMore(peerId);
|
||||||
}, [&](StoriesContextArchive) {
|
}, [&](StoriesContextArchive) {
|
||||||
Expects(user->isSelf());
|
Expects(peer->isSelf());
|
||||||
|
|
||||||
stories.archiveLoadMore();
|
stories.archiveLoadMore();
|
||||||
}, [](const auto &) {
|
}, [](const auto &) {
|
||||||
|
@ -1462,10 +1462,10 @@ void Controller::rebuildCachedSourcesList(
|
||||||
void Controller::refreshViewsFromData() {
|
void Controller::refreshViewsFromData() {
|
||||||
Expects(shown());
|
Expects(shown());
|
||||||
|
|
||||||
const auto user = shownUser();
|
const auto peer = shownPeer();
|
||||||
auto &stories = user->owner().stories();
|
auto &stories = peer->owner().stories();
|
||||||
const auto maybeStory = stories.lookup(_shown);
|
const auto maybeStory = stories.lookup(_shown);
|
||||||
if (!maybeStory || !user->isSelf()) {
|
if (!maybeStory || !peer->isSelf()) {
|
||||||
_viewsSlice = {};
|
_viewsSlice = {};
|
||||||
} else {
|
} else {
|
||||||
_viewsSlice = (*maybeStory)->viewsList();
|
_viewsSlice = (*maybeStory)->viewsList();
|
||||||
|
|
|
@ -181,7 +181,7 @@ private:
|
||||||
class Unsupported;
|
class Unsupported;
|
||||||
using ChosenReaction = HistoryView::Reactions::ChosenReaction;
|
using ChosenReaction = HistoryView::Reactions::ChosenReaction;
|
||||||
struct StoriesList {
|
struct StoriesList {
|
||||||
not_null<UserData*> user;
|
not_null<PeerData*> peer;
|
||||||
Data::StoriesIds ids;
|
Data::StoriesIds ids;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
|
@ -233,10 +233,10 @@ private:
|
||||||
-> Fn<void(Data::StoryViews)>;
|
-> Fn<void(Data::StoryViews)>;
|
||||||
|
|
||||||
[[nodiscard]] bool shown() const;
|
[[nodiscard]] bool shown() const;
|
||||||
[[nodiscard]] UserData *shownUser() const;
|
[[nodiscard]] PeerData *shownPeer() const;
|
||||||
[[nodiscard]] int shownCount() const;
|
[[nodiscard]] int shownCount() const;
|
||||||
[[nodiscard]] StoryId shownId(int index) 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 checkMoveByDelta();
|
||||||
void loadMoreToList();
|
void loadMoreToList();
|
||||||
void preloadNext();
|
void preloadNext();
|
||||||
|
|
|
@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "chat_helpers/compose/compose_show.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 "media/stories/media_stories_controller.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/controls/userpic_button.h"
|
#include "ui/controls/userpic_button.h"
|
||||||
|
@ -268,7 +268,7 @@ void Header::show(HeaderData data) {
|
||||||
if (_data == data) {
|
if (_data == data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto userChanged = !_data || (_data->user != data.user);
|
const auto peerChanged = !_data || (_data->peer != data.peer);
|
||||||
_data = data;
|
_data = data;
|
||||||
const auto updateInfoGeometry = [=] {
|
const auto updateInfoGeometry = [=] {
|
||||||
if (_name && _date) {
|
if (_name && _date) {
|
||||||
|
@ -282,7 +282,7 @@ void Header::show(HeaderData data) {
|
||||||
};
|
};
|
||||||
_tooltip = nullptr;
|
_tooltip = nullptr;
|
||||||
_tooltipShown = false;
|
_tooltipShown = false;
|
||||||
if (userChanged) {
|
if (peerChanged) {
|
||||||
_volume = nullptr;
|
_volume = nullptr;
|
||||||
_date = nullptr;
|
_date = nullptr;
|
||||||
_name = nullptr;
|
_name = nullptr;
|
||||||
|
@ -298,12 +298,12 @@ void Header::show(HeaderData data) {
|
||||||
|
|
||||||
_info = std::make_unique<Ui::AbstractButton>(raw);
|
_info = std::make_unique<Ui::AbstractButton>(raw);
|
||||||
_info->setClickedCallback([=] {
|
_info->setClickedCallback([=] {
|
||||||
_controller->uiShow()->show(PrepareShortInfoBox(_data->user));
|
_controller->uiShow()->show(PrepareShortInfoBox(_data->peer));
|
||||||
});
|
});
|
||||||
|
|
||||||
_userpic = std::make_unique<Ui::UserpicButton>(
|
_userpic = std::make_unique<Ui::UserpicButton>(
|
||||||
raw,
|
raw,
|
||||||
data.user,
|
data.peer,
|
||||||
st::storiesHeaderPhoto);
|
st::storiesHeaderPhoto);
|
||||||
_userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
_userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
_userpic->show();
|
_userpic->show();
|
||||||
|
@ -313,9 +313,9 @@ void Header::show(HeaderData data) {
|
||||||
|
|
||||||
_name = std::make_unique<Ui::FlatLabel>(
|
_name = std::make_unique<Ui::FlatLabel>(
|
||||||
raw,
|
raw,
|
||||||
rpl::single(data.user->isSelf()
|
rpl::single(data.peer->isSelf()
|
||||||
? tr::lng_stories_my_name(tr::now)
|
? tr::lng_stories_my_name(tr::now)
|
||||||
: data.user->name()),
|
: data.peer->name()),
|
||||||
st::storiesHeaderName);
|
st::storiesHeaderName);
|
||||||
_name->setAttribute(Qt::WA_TransparentForMouseEvents);
|
_name->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
_name->setOpacity(kNameOpacity);
|
_name->setOpacity(kNameOpacity);
|
||||||
|
@ -605,8 +605,8 @@ void Header::toggleTooltip(Tooltip type, bool show) {
|
||||||
}
|
}
|
||||||
const auto text = [&]() -> TextWithEntities {
|
const auto text = [&]() -> TextWithEntities {
|
||||||
using Privacy = Data::StoryPrivacy;
|
using Privacy = Data::StoryPrivacy;
|
||||||
const auto boldName = Ui::Text::Bold(_data->user->shortName());
|
const auto boldName = Ui::Text::Bold(_data->peer->shortName());
|
||||||
const auto self = _data->user->isSelf();
|
const auto self = _data->peer->isSelf();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Tooltip::SilentVideo:
|
case Tooltip::SilentVideo:
|
||||||
return { tr::lng_stories_about_silent(tr::now) };
|
return { tr::lng_stories_about_silent(tr::now) };
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Controller;
|
||||||
enum class PauseState;
|
enum class PauseState;
|
||||||
|
|
||||||
struct HeaderData {
|
struct HeaderData {
|
||||||
not_null<UserData*> user;
|
not_null<PeerData*> peer;
|
||||||
TimeId date = 0;
|
TimeId date = 0;
|
||||||
int fullIndex = 0;
|
int fullIndex = 0;
|
||||||
int fullCount = 0;
|
int fullCount = 0;
|
||||||
|
|
|
@ -171,13 +171,13 @@ void ReplyArea::initGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyArea::sendReaction(const Data::ReactionId &id) {
|
void ReplyArea::sendReaction(const Data::ReactionId &id) {
|
||||||
Expects(_data.user != nullptr);
|
Expects(_data.peer != nullptr);
|
||||||
|
|
||||||
auto message = Api::MessageToSend(prepareSendAction({}));
|
auto message = Api::MessageToSend(prepareSendAction({}));
|
||||||
if (const auto emoji = id.emoji(); !emoji.isEmpty()) {
|
if (const auto emoji = id.emoji(); !emoji.isEmpty()) {
|
||||||
message.textWithTags = { emoji };
|
message.textWithTags = { emoji };
|
||||||
} else if (const auto customId = id.custom()) {
|
} 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()) {
|
if (const auto sticker = document->sticker()) {
|
||||||
const auto text = sticker->alt;
|
const auto text = sticker->alt;
|
||||||
const auto id = Data::SerializeCustomEmojiId(customId);
|
const auto id = Data::SerializeCustomEmojiId(customId);
|
||||||
|
@ -207,7 +207,7 @@ void ReplyArea::send(
|
||||||
Api::SendOptions options,
|
Api::SendOptions options,
|
||||||
bool skipToast) {
|
bool skipToast) {
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorTextForSending(
|
||||||
_data.user,
|
_data.peer,
|
||||||
{
|
{
|
||||||
.topicRootId = MsgId(0),
|
.topicRootId = MsgId(0),
|
||||||
.text = &message.textWithTags,
|
.text = &message.textWithTags,
|
||||||
|
@ -239,11 +239,11 @@ bool ReplyArea::sendExistingDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
Api::SendOptions options,
|
Api::SendOptions options,
|
||||||
std::optional<MsgId> localId) {
|
std::optional<MsgId> localId) {
|
||||||
Expects(_data.user != nullptr);
|
Expects(_data.peer != nullptr);
|
||||||
|
|
||||||
const auto show = _controller->uiShow();
|
const auto show = _controller->uiShow();
|
||||||
const auto error = Data::RestrictionError(
|
const auto error = Data::RestrictionError(
|
||||||
_data.user,
|
_data.peer,
|
||||||
ChatRestriction::SendStickers);
|
ChatRestriction::SendStickers);
|
||||||
if (error) {
|
if (error) {
|
||||||
show->showToast(*error);
|
show->showToast(*error);
|
||||||
|
@ -269,11 +269,11 @@ void ReplyArea::sendExistingPhoto(not_null<PhotoData*> photo) {
|
||||||
bool ReplyArea::sendExistingPhoto(
|
bool ReplyArea::sendExistingPhoto(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
Api::SendOptions options) {
|
Api::SendOptions options) {
|
||||||
Expects(_data.user != nullptr);
|
Expects(_data.peer != nullptr);
|
||||||
|
|
||||||
const auto show = _controller->uiShow();
|
const auto show = _controller->uiShow();
|
||||||
const auto error = Data::RestrictionError(
|
const auto error = Data::RestrictionError(
|
||||||
_data.user,
|
_data.peer,
|
||||||
ChatRestriction::SendPhotos);
|
ChatRestriction::SendPhotos);
|
||||||
if (error) {
|
if (error) {
|
||||||
show->showToast(*error);
|
show->showToast(*error);
|
||||||
|
@ -348,7 +348,7 @@ bool ReplyArea::showSendingFilesError(
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress) const {
|
std::optional<bool> compress) const {
|
||||||
const auto text = [&] {
|
const auto text = [&] {
|
||||||
const auto peer = _data.user;
|
const auto peer = _data.peer;
|
||||||
const auto error = Data::FileRestrictionError(peer, list, compress);
|
const auto error = Data::FileRestrictionError(peer, list, compress);
|
||||||
if (error) {
|
if (error) {
|
||||||
return *error;
|
return *error;
|
||||||
|
@ -383,29 +383,29 @@ bool ReplyArea::showSendingFilesError(
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<History*> ReplyArea::history() const {
|
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::SendAction ReplyArea::prepareSendAction(
|
||||||
Api::SendOptions options) const {
|
Api::SendOptions options) const {
|
||||||
Expects(_data.user != nullptr);
|
Expects(_data.peer != nullptr);
|
||||||
|
|
||||||
auto result = Api::SendAction(history(), options);
|
auto result = Api::SendAction(history(), options);
|
||||||
result.options.sendAs = _controls->sendAsPeer();
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyArea::chooseAttach(
|
void ReplyArea::chooseAttach(
|
||||||
std::optional<bool> overrideSendImagesAsPhotos) {
|
std::optional<bool> overrideSendImagesAsPhotos) {
|
||||||
_chooseAttachRequest = false;
|
_chooseAttachRequest = false;
|
||||||
if (!_data.user) {
|
if (!_data.peer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto user = not_null(_data.user);
|
const auto peer = not_null(_data.peer);
|
||||||
if (const auto error = Data::AnyFileRestrictionError(user)) {
|
if (const auto error = Data::AnyFileRestrictionError(peer)) {
|
||||||
_controller->uiShow()->showToast(*error);
|
_controller->uiShow()->showToast(*error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ void ReplyArea::chooseAttach(
|
||||||
const auto filter = (overrideSendImagesAsPhotos == true)
|
const auto filter = (overrideSendImagesAsPhotos == true)
|
||||||
? FileDialog::ImagesOrAllFilter()
|
? FileDialog::ImagesOrAllFilter()
|
||||||
: FileDialog::AllOrImagesFilter();
|
: FileDialog::AllOrImagesFilter();
|
||||||
const auto weak = make_weak(&_shownUserGuard);
|
const auto weak = make_weak(&_shownPeerGuard);
|
||||||
const auto callback = [=](FileDialog::OpenResult &&result) {
|
const auto callback = [=](FileDialog::OpenResult &&result) {
|
||||||
const auto guard = gsl::finally([&] {
|
const auto guard = gsl::finally([&] {
|
||||||
_choosingAttach = false;
|
_choosingAttach = false;
|
||||||
|
@ -504,8 +504,8 @@ bool ReplyArea::confirmSendingFiles(
|
||||||
.show = show,
|
.show = show,
|
||||||
.list = std::move(list),
|
.list = std::move(list),
|
||||||
.caption = _controls->getTextWithAppliedMarkdown(),
|
.caption = _controls->getTextWithAppliedMarkdown(),
|
||||||
.limits = DefaultLimitsForPeer(_data.user),
|
.limits = DefaultLimitsForPeer(_data.peer),
|
||||||
.check = DefaultCheckForPeer(show, _data.user),
|
.check = DefaultCheckForPeer(show, _data.peer),
|
||||||
.sendType = Api::SendType::Normal,
|
.sendType = Api::SendType::Normal,
|
||||||
.sendMenuType = SendMenu::Type::SilentOnly,
|
.sendMenuType = SendMenu::Type::SilentOnly,
|
||||||
.stOverride = &st::storiesComposeControls,
|
.stOverride = &st::storiesComposeControls,
|
||||||
|
@ -533,7 +533,7 @@ void ReplyArea::sendingFilesConfirmed(
|
||||||
auto groups = DivideByGroups(
|
auto groups = DivideByGroups(
|
||||||
std::move(list),
|
std::move(list),
|
||||||
way,
|
way,
|
||||||
_data.user->slowmodeApplied());
|
_data.peer->slowmodeApplied());
|
||||||
const auto type = way.sendImagesAsPhotos()
|
const auto type = way.sendImagesAsPhotos()
|
||||||
? SendMediaType::Photo
|
? SendMediaType::Photo
|
||||||
: SendMediaType::File;
|
: SendMediaType::File;
|
||||||
|
@ -655,17 +655,17 @@ void ReplyArea::show(
|
||||||
if (_data == data) {
|
if (_data == data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto userChanged = (_data.user != data.user);
|
const auto peerChanged = (_data.peer != data.peer);
|
||||||
_data = data;
|
_data = data;
|
||||||
if (!userChanged) {
|
if (!peerChanged) {
|
||||||
if (_data.user) {
|
if (_data.peer) {
|
||||||
_controls->clear();
|
_controls->clear();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
invalidate_weak_ptrs(&_shownUserGuard);
|
invalidate_weak_ptrs(&_shownPeerGuard);
|
||||||
const auto user = data.user;
|
const auto peer = data.peer;
|
||||||
const auto history = user ? user->owner().history(user).get() : nullptr;
|
const auto history = peer ? peer->owner().history(peer).get() : nullptr;
|
||||||
_controls->setHistory({
|
_controls->setHistory({
|
||||||
.history = history,
|
.history = history,
|
||||||
.liked = std::move(
|
.liked = std::move(
|
||||||
|
@ -675,8 +675,8 @@ void ReplyArea::show(
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
_controls->clear();
|
_controls->clear();
|
||||||
const auto hidden = user && user->isSelf();
|
const auto hidden = peer && peer->isSelf();
|
||||||
const auto cant = !user || user->isServiceUser();
|
const auto cant = !peer || peer->isServiceUser();
|
||||||
if (!hidden && !cant) {
|
if (!hidden && !cant) {
|
||||||
_controls->show();
|
_controls->show();
|
||||||
} else {
|
} else {
|
||||||
|
@ -698,9 +698,9 @@ void ReplyArea::show(
|
||||||
}
|
}
|
||||||
|
|
||||||
Main::Session &ReplyArea::session() const {
|
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 {
|
bool ReplyArea::focused() const {
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace Media::Stories {
|
||||||
class Controller;
|
class Controller;
|
||||||
|
|
||||||
struct ReplyAreaData {
|
struct ReplyAreaData {
|
||||||
UserData *user = nullptr;
|
PeerData *peer = nullptr;
|
||||||
StoryId id = 0;
|
StoryId id = 0;
|
||||||
|
|
||||||
friend inline auto operator<=>(ReplyAreaData, ReplyAreaData) = default;
|
friend inline auto operator<=>(ReplyAreaData, ReplyAreaData) = default;
|
||||||
|
@ -148,7 +148,7 @@ private:
|
||||||
std::unique_ptr<Cant> _cant;
|
std::unique_ptr<Cant> _cant;
|
||||||
|
|
||||||
ReplyAreaData _data;
|
ReplyAreaData _data;
|
||||||
base::has_weak_ptr _shownUserGuard;
|
base::has_weak_ptr _shownPeerGuard;
|
||||||
bool _chooseAttachRequest = false;
|
bool _chooseAttachRequest = false;
|
||||||
rpl::variable<bool> _choosingAttach;
|
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_chat_participant_status.h"
|
||||||
#include "data/data_forum_topic.h"
|
#include "data/data_forum_topic.h"
|
||||||
#include "data/data_histories.h"
|
#include "data/data_histories.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_stories.h"
|
#include "data/data_stories.h"
|
||||||
#include "data/data_thread.h"
|
#include "data/data_thread.h"
|
||||||
#include "data/data_user.h"
|
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
||||||
#include "history/view/history_view_context_menu.h" // CopyStoryLink.
|
#include "history/view/history_view_context_menu.h" // CopyStoryLink.
|
||||||
|
@ -79,9 +79,7 @@ namespace Media::Stories {
|
||||||
if (!story) {
|
if (!story) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto user = story->peer()->asUser();
|
const auto peer = story->peer();
|
||||||
Assert(user != nullptr);
|
|
||||||
|
|
||||||
const auto error = [&] {
|
const auto error = [&] {
|
||||||
for (const auto thread : result) {
|
for (const auto thread : result) {
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorTextForSending(
|
||||||
|
@ -115,14 +113,16 @@ namespace Media::Stories {
|
||||||
message.action.clearDraft = false;
|
message.action.clearDraft = false;
|
||||||
api->sendMessage(std::move(message));
|
api->sendMessage(std::move(message));
|
||||||
}
|
}
|
||||||
const auto peer = thread->peer();
|
const auto threadPeer = thread->peer();
|
||||||
const auto threadHistory = thread->owningHistory();
|
const auto threadHistory = thread->owningHistory();
|
||||||
const auto randomId = base::RandomValue<uint64>();
|
const auto randomId = base::RandomValue<uint64>();
|
||||||
auto sendFlags = MTPmessages_SendMedia::Flags(0);
|
auto sendFlags = MTPmessages_SendMedia::Flags(0);
|
||||||
if (action.replyTo) {
|
if (action.replyTo) {
|
||||||
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
||||||
}
|
}
|
||||||
const auto silentPost = ShouldSendSilent(peer, action.options);
|
const auto silentPost = ShouldSendSilent(
|
||||||
|
threadPeer,
|
||||||
|
action.options);
|
||||||
if (silentPost) {
|
if (silentPost) {
|
||||||
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||||
}
|
}
|
||||||
|
@ -140,23 +140,23 @@ namespace Media::Stories {
|
||||||
randomId,
|
randomId,
|
||||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||||
MTP_flags(sendFlags),
|
MTP_flags(sendFlags),
|
||||||
peer->input,
|
threadPeer->input,
|
||||||
Data::Histories::ReplyToPlaceholder(),
|
Data::Histories::ReplyToPlaceholder(),
|
||||||
MTP_inputMediaStory(
|
MTP_inputMediaStory(peer->input, MTP_int(id.story)),
|
||||||
user->inputUser,
|
|
||||||
MTP_int(id.story)),
|
|
||||||
MTPstring(),
|
MTPstring(),
|
||||||
MTP_long(randomId),
|
MTP_long(randomId),
|
||||||
MTPReplyMarkup(),
|
MTPReplyMarkup(),
|
||||||
MTPVector<MTPMessageEntity>(),
|
MTPVector<MTPMessageEntity>(),
|
||||||
MTP_int(action.options.scheduled),
|
MTP_int(action.options.scheduled),
|
||||||
MTP_inputPeerEmpty()
|
MTP_inputPeerEmpty()
|
||||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
), [=](
|
||||||
done();
|
const MTPUpdates &result,
|
||||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
const MTP::Response &response) {
|
||||||
api->sendMessageFail(error, peer, randomId);
|
done();
|
||||||
done();
|
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||||
});
|
api->sendMessageFail(error, threadPeer, randomId);
|
||||||
|
done();
|
||||||
|
});
|
||||||
++state->requests;
|
++state->requests;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_document_media.h"
|
#include "data/data_document_media.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_photo_media.h"
|
#include "data/data_photo_media.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_user.h"
|
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "media/stories/media_stories_controller.h"
|
#include "media/stories/media_stories_controller.h"
|
||||||
|
@ -244,8 +244,8 @@ Sibling::Sibling(
|
||||||
const Data::StoriesSource &source,
|
const Data::StoriesSource &source,
|
||||||
StoryId suggestedId)
|
StoryId suggestedId)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _id{ source.user->id, LookupShownId(source, suggestedId) }
|
, _id{ source.peer->id, LookupShownId(source, suggestedId) }
|
||||||
, _peer(source.user) {
|
, _peer(source.peer) {
|
||||||
checkStory();
|
checkStory();
|
||||||
_goodShown.stop();
|
_goodShown.stop();
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ bool Sibling::shows(
|
||||||
const Data::StoriesSource &source,
|
const Data::StoriesSource &source,
|
||||||
StoryId suggestedId) const {
|
StoryId suggestedId) const {
|
||||||
const auto fullId = FullStoryId{
|
const auto fullId = FullStoryId{
|
||||||
source.user->id,
|
source.peer->id,
|
||||||
LookupShownId(source, suggestedId),
|
LookupShownId(source, suggestedId),
|
||||||
};
|
};
|
||||||
return (_id == fullId);
|
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;
|
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;
|
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;
|
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
|
||||||
inputMediaStory#9a86b58f user_id:InputUser id:int = InputMedia;
|
inputMediaStory#89fdd778 peer:InputPeer id:int = InputMedia;
|
||||||
|
|
||||||
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
|
||||||
chatParticipantCreator#e46bcee4 user_id:long = 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;
|
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;
|
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
|
||||||
messageMediaDice#3f7ee58b value:int emoticon:string = 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;
|
messageActionEmpty#b6aef7b0 = MessageAction;
|
||||||
messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction;
|
messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction;
|
||||||
|
@ -221,7 +221,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
|
||||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||||
inputReportReasonPersonalDetails#9ec7863d = 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;
|
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;
|
updateUser#20529438 user_id:long = Update;
|
||||||
updateAutoSaveSettings#ec05b097 = Update;
|
updateAutoSaveSettings#ec05b097 = Update;
|
||||||
updateGroupInvitePrivacyForbidden#ccf08ad6 user_id:long = Update;
|
updateGroupInvitePrivacyForbidden#ccf08ad6 user_id:long = Update;
|
||||||
updateStory#205a4133 user_id:long story:StoryItem = Update;
|
updateStory#75b3b798 peer:Peer story:StoryItem = Update;
|
||||||
updateReadStories#feb5345a user_id:long max_id:int = Update;
|
updateReadStories#f74e932b peer:Peer max_id:int = Update;
|
||||||
updateStoryID#1bf335b9 id:int random_id:long = Update;
|
updateStoryID#1bf335b9 id:int random_id:long = Update;
|
||||||
updateStoriesStealthMode#2c084dc1 stealth_mode:StoriesStealthMode = 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;
|
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;
|
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;
|
paymentCharge#ea02c27e id:string provider_charge_id:string = PaymentCharge;
|
||||||
|
|
||||||
|
@ -1123,7 +1123,7 @@ chatOnlines#f041e250 onlines:int = ChatOnlines;
|
||||||
|
|
||||||
statsURL#47a971e0 url:string = StatsURL;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
storyItemDeleted#51e6ee4f id:int = StoryItem;
|
||||||
storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date: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;
|
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;
|
||||||
|
|
||||||
userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = UserStories;
|
|
||||||
|
|
||||||
stories.allStoriesNotModified#1158fe3e flags:# state:string stealth_mode:StoriesStealthMode = stories.AllStories;
|
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.stories#5dd8c3c8 count:int stories:Vector<StoryItem> chats:Vector<Chat> users:Vector<User> = stories.Stories;
|
||||||
|
|
||||||
stories.userStories#37a6ff5f stories:UserStories users:Vector<User> = stories.UserStories;
|
|
||||||
|
|
||||||
storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView;
|
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;
|
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;
|
inputMediaAreaVenue#b282217f coordinates:MediaAreaCoordinates query_id:long result_id:string = MediaArea;
|
||||||
mediaAreaGeoPoint#df8b3b22 coordinates:MediaAreaCoordinates geo:GeoPoint = 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---
|
---functions---
|
||||||
|
|
||||||
|
@ -1688,7 +1698,6 @@ account.invalidateSignInCodes#ca8ae8ba codes:Vector<string> = Bool;
|
||||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||||
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
|
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.getContactIDs#7adc669d hash:long = Vector<int>;
|
||||||
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
||||||
|
@ -1714,7 +1723,6 @@ contacts.resolvePhone#8af94344 phone:string = contacts.ResolvedPeer;
|
||||||
contacts.exportContactToken#f8654027 = ExportedContactToken;
|
contacts.exportContactToken#f8654027 = ExportedContactToken;
|
||||||
contacts.importContactToken#13005788 token:string = User;
|
contacts.importContactToken#13005788 token:string = User;
|
||||||
contacts.editCloseFriends#ba6705f0 id:Vector<long> = Bool;
|
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;
|
contacts.setBlocked#94c65c76 flags:# my_stories_from:flags.0?true id:Vector<InputPeer> limit:int = Bool;
|
||||||
|
|
||||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
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.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector<Peer>;
|
||||||
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = Updates;
|
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = Updates;
|
||||||
|
|
||||||
stories.canSendStory#b100d45d = Bool;
|
stories.canSendStory#c7dfdfdd peer:InputPeer = 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.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#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.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#b5d501d7 id:Vector<int> = Vector<int>;
|
stories.deleteStories#ae59db5f peer:InputPeer id:Vector<int> = Vector<int>;
|
||||||
stories.togglePinned#51602944 id:Vector<int> pinned:Bool = 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.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#5821a5dc peer:InputPeer offset_id:int limit:int = stories.Stories;
|
||||||
stories.getPinnedStories#b471137 user_id:InputUser offset_id:int limit:int = stories.Stories;
|
stories.getStoriesArchive#b4352016 peer:InputPeer offset_id:int limit:int = stories.Stories;
|
||||||
stories.getStoriesArchive#1f5bc5d2 offset_id:int limit:int = stories.Stories;
|
stories.getStoriesByID#5774ca74 peer:InputPeer id:Vector<int> = stories.Stories;
|
||||||
stories.getStoriesByID#6a15cf46 user_id:InputUser id:Vector<int> = stories.Stories;
|
|
||||||
stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool;
|
stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool;
|
||||||
stories.getAllReadUserStories#729c562c = Updates;
|
stories.readStories#a556dac8 peer:InputPeer max_id:int = Vector<int>;
|
||||||
stories.readStories#edc5105b user_id:InputUser max_id:int = Vector<int>;
|
stories.incrementStoryViews#b2028afb peer:InputPeer id:Vector<int> = Bool;
|
||||||
stories.incrementStoryViews#22126127 user_id:InputUser 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.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#28e16cc8 peer:InputPeer id:Vector<int> = stories.StoryViews;
|
||||||
stories.getStoriesViews#9a75d6a6 id:Vector<int> = stories.StoryViews;
|
stories.exportStoryLink#7b8def20 peer:InputPeer id:int = ExportedStoryLink;
|
||||||
stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink;
|
stories.report#1923fa8c peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
|
||||||
stories.report#c95be06a user_id:InputUser id:Vector<int> reason:ReportReason message:string = Bool;
|
|
||||||
stories.activateStealthMode#57bbd166 flags:# past:flags.0?true future:flags.1?true = Updates;
|
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
|
} else if (!method.newCredentials
|
||||||
&& method.savedCredentialsIndex >= method.savedCredentials.size()) {
|
&& method.savedCredentialsIndex >= method.savedCredentials.size()) {
|
||||||
editPaymentMethod();
|
editPaymentMethod();
|
||||||
} else if (invoice.isRecurring && !_form->details().termsAccepted) {
|
} else if (!invoice.termsUrl.isEmpty()
|
||||||
|
&& !_form->details().termsAccepted) {
|
||||||
_panel->requestTermsAcceptance(
|
_panel->requestTermsAcceptance(
|
||||||
_form->details().termsBotUsername,
|
_form->details().termsBotUsername,
|
||||||
invoice.recurringTermsUrl);
|
invoice.termsUrl,
|
||||||
|
invoice.isRecurring);
|
||||||
} else {
|
} else {
|
||||||
RegisterPaymentStart(this, { _form->invoice().cover.title });
|
RegisterPaymentStart(this, { _form->invoice().cover.title });
|
||||||
_submitState = SubmitState::Finishing;
|
_submitState = SubmitState::Finishing;
|
||||||
|
|
|
@ -384,8 +384,7 @@ void Form::processInvoice(const MTPDinvoice &data) {
|
||||||
.isFlexible = data.is_flexible(),
|
.isFlexible = data.is_flexible(),
|
||||||
.isTest = data.is_test(),
|
.isTest = data.is_test(),
|
||||||
|
|
||||||
.recurringTermsUrl = qs(
|
.termsUrl = qs(data.vterms_url().value_or_empty()),
|
||||||
data.vrecurring_terms_url().value_or_empty()),
|
|
||||||
|
|
||||||
.phoneSentToProvider = data.is_phone_to_provider(),
|
.phoneSentToProvider = data.is_phone_to_provider(),
|
||||||
.emailSentToProvider = data.is_email_to_provider(),
|
.emailSentToProvider = data.is_email_to_provider(),
|
||||||
|
|
|
@ -704,15 +704,18 @@ void Panel::showWarning(const QString &bot, const QString &provider) {
|
||||||
|
|
||||||
void Panel::requestTermsAcceptance(
|
void Panel::requestTermsAcceptance(
|
||||||
const QString &username,
|
const QString &username,
|
||||||
const QString &url) {
|
const QString &url,
|
||||||
|
bool recurring) {
|
||||||
showBox(Box([=](not_null<GenericBox*> box) {
|
showBox(Box([=](not_null<GenericBox*> box) {
|
||||||
box->setTitle(tr::lng_payments_terms_title());
|
box->setTitle(tr::lng_payments_terms_title());
|
||||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||||
box.get(),
|
box.get(),
|
||||||
tr::lng_payments_terms_text(
|
(recurring
|
||||||
lt_bot,
|
? tr::lng_payments_terms_text
|
||||||
rpl::single(Ui::Text::Bold('@' + username)),
|
: tr::lng_payments_terms_text_once)(
|
||||||
Ui::Text::WithEntities),
|
lt_bot,
|
||||||
|
rpl::single(Ui::Text::Bold('@' + username)),
|
||||||
|
Ui::Text::WithEntities),
|
||||||
st::boxLabel));
|
st::boxLabel));
|
||||||
const auto update = std::make_shared<Fn<void()>>();
|
const auto update = std::make_shared<Fn<void()>>();
|
||||||
auto checkView = std::make_unique<Ui::CheckView>(
|
auto checkView = std::make_unique<Ui::CheckView>(
|
||||||
|
|
|
@ -78,7 +78,10 @@ public:
|
||||||
void askSetPassword();
|
void askSetPassword();
|
||||||
void showCloseConfirm();
|
void showCloseConfirm();
|
||||||
void showWarning(const QString &bot, const QString &provider);
|
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(
|
bool showWebview(
|
||||||
const QString &url,
|
const QString &url,
|
||||||
|
|
|
@ -56,7 +56,7 @@ struct Invoice {
|
||||||
bool isTest = false;
|
bool isTest = false;
|
||||||
|
|
||||||
QString provider;
|
QString provider;
|
||||||
QString recurringTermsUrl;
|
QString termsUrl;
|
||||||
bool phoneSentToProvider = false;
|
bool phoneSentToProvider = false;
|
||||||
bool emailSentToProvider = false;
|
bool emailSentToProvider = false;
|
||||||
|
|
||||||
|
|
|
@ -2557,19 +2557,17 @@ void SessionController::openPeerStories(
|
||||||
if (const auto source = stories.source(peerId)) {
|
if (const auto source = stories.source(peerId)) {
|
||||||
if (const auto idDates = source->toOpen()) {
|
if (const auto idDates = source->toOpen()) {
|
||||||
openPeerStory(
|
openPeerStory(
|
||||||
source->user,
|
source->peer,
|
||||||
idDates.id,
|
idDates.id,
|
||||||
(list
|
(list
|
||||||
? StoriesContext{ *list }
|
? StoriesContext{ *list }
|
||||||
: StoriesContext{ StoriesContextPeer() }));
|
: StoriesContext{ StoriesContextPeer() }));
|
||||||
}
|
}
|
||||||
} else if (const auto userId = peerToUser(peerId)) {
|
} else if (const auto peer = session().data().peerLoaded(peerId)) {
|
||||||
if (const auto user = session().data().userLoaded(userId)) {
|
const auto done = crl::guard(&_storyOpenGuard, [=] {
|
||||||
const auto done = crl::guard(&_storyOpenGuard, [=] {
|
openPeerStories(peerId, list);
|
||||||
openPeerStories(peerId, list);
|
});
|
||||||
});
|
stories.requestPeerStories(peer, done);
|
||||||
stories.requestUserStories(user, done);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue