| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #pragma once
- #include "base/flags.h"
- class History;
- class PeerData;
- class HistoryItem;
- namespace Dialogs {
- class Entry;
- } // namespace Dialogs
- namespace Main {
- class Session;
- } // namespace Main
- namespace Data::details {
- template <typename Flag>
- inline constexpr int CountBit(Flag Last = Flag::LastUsedBit) {
- auto i = 0;
- while ((1ULL << i) != static_cast<uint64>(Last)) {
- ++i;
- Assert(i != 64);
- }
- return i;
- }
- } // namespace Data::details
- namespace Data {
- class ForumTopic;
- class Story;
- struct NameUpdate {
- NameUpdate(
- not_null<PeerData*> peer,
- base::flat_set<QChar> oldFirstLetters)
- : peer(peer)
- , oldFirstLetters(std::move(oldFirstLetters)) {
- }
- not_null<PeerData*> peer;
- base::flat_set<QChar> oldFirstLetters;
- };
- struct PeerUpdate {
- enum class Flag : uint64 {
- None = 0,
- // Common flags
- Name = (1ULL << 0),
- Username = (1ULL << 1),
- Photo = (1ULL << 2),
- About = (1ULL << 3),
- Notifications = (1ULL << 4),
- Migration = (1ULL << 5),
- UnavailableReason = (1ULL << 6),
- ChatThemeEmoji = (1ULL << 7),
- ChatWallPaper = (1ULL << 8),
- IsBlocked = (1ULL << 9),
- MessagesTTL = (1ULL << 10),
- FullInfo = (1ULL << 11),
- Usernames = (1ULL << 12),
- TranslationDisabled = (1ULL << 13),
- Color = (1ULL << 14),
- BackgroundEmoji = (1ULL << 15),
- StoriesState = (1ULL << 16),
- VerifyInfo = (1ULL << 17),
- StarsPerMessage = (1ULL << 18),
- // For users
- CanShareContact = (1ULL << 19),
- IsContact = (1ULL << 20),
- PhoneNumber = (1ULL << 21),
- OnlineStatus = (1ULL << 22),
- BotCommands = (1ULL << 23),
- BotCanBeInvited = (1ULL << 24),
- BotStartToken = (1ULL << 25),
- CommonChats = (1ULL << 26),
- PeerGifts = (1ULL << 27),
- HasCalls = (1ULL << 28),
- SupportInfo = (1ULL << 29),
- IsBot = (1ULL << 30),
- EmojiStatus = (1ULL << 31),
- BusinessDetails = (1ULL << 32),
- Birthday = (1ULL << 33),
- PersonalChannel = (1ULL << 34),
- StarRefProgram = (1ULL << 35),
- PaysPerMessage = (1ULL << 36),
- // For chats and channels
- InviteLinks = (1ULL << 37),
- Members = (1ULL << 38),
- Admins = (1ULL << 39),
- BannedUsers = (1ULL << 40),
- Rights = (1ULL << 41),
- PendingRequests = (1ULL << 42),
- Reactions = (1ULL << 43),
- // For channels
- ChannelAmIn = (1ULL << 44),
- StickersSet = (1ULL << 45),
- EmojiSet = (1ULL << 46),
- ChannelLinkedChat = (1ULL << 47),
- ChannelLocation = (1ULL << 48),
- Slowmode = (1ULL << 49),
- GroupCall = (1ULL << 50),
- // For iteration
- LastUsedBit = (1ULL << 50),
- };
- using Flags = base::flags<Flag>;
- friend inline constexpr auto is_flag_type(Flag) { return true; }
- not_null<PeerData*> peer;
- Flags flags = 0;
- };
- struct HistoryUpdate {
- enum class Flag : uint32 {
- None = 0,
- IsPinned = (1U << 0),
- UnreadView = (1U << 1),
- TopPromoted = (1U << 2),
- Folder = (1U << 3),
- UnreadMentions = (1U << 4),
- UnreadReactions = (1U << 5),
- ClientSideMessages = (1U << 6),
- ChatOccupied = (1U << 7),
- MessageSent = (1U << 8),
- ScheduledSent = (1U << 9),
- OutboxRead = (1U << 10),
- BotKeyboard = (1U << 11),
- CloudDraft = (1U << 12),
- TranslateFrom = (1U << 13),
- TranslatedTo = (1U << 14),
- LastUsedBit = (1U << 14),
- };
- using Flags = base::flags<Flag>;
- friend inline constexpr auto is_flag_type(Flag) { return true; }
- not_null<History*> history;
- Flags flags = 0;
- };
- struct TopicUpdate {
- enum class Flag : uint32 {
- None = 0,
- UnreadView = (1U << 1),
- UnreadMentions = (1U << 2),
- UnreadReactions = (1U << 3),
- Notifications = (1U << 4),
- Title = (1U << 5),
- IconId = (1U << 6),
- ColorId = (1U << 7),
- CloudDraft = (1U << 8),
- Closed = (1U << 9),
- Creator = (1U << 10),
- Destroyed = (1U << 11),
- LastUsedBit = (1U << 11),
- };
- using Flags = base::flags<Flag>;
- friend inline constexpr auto is_flag_type(Flag) { return true; }
- not_null<ForumTopic*> topic;
- Flags flags = 0;
- };
- struct MessageUpdate {
- enum class Flag : uint32 {
- None = 0,
- Edited = (1U << 0),
- Destroyed = (1U << 1),
- DialogRowRepaint = (1U << 2),
- DialogRowRefresh = (1U << 3),
- NewAdded = (1U << 4),
- ReplyMarkup = (1U << 5),
- BotCallbackSent = (1U << 6),
- NewMaybeAdded = (1U << 7),
- ReplyToTopAdded = (1U << 8),
- NewUnreadReaction = (1U << 9),
- LastUsedBit = (1U << 9),
- };
- using Flags = base::flags<Flag>;
- friend inline constexpr auto is_flag_type(Flag) { return true; }
- not_null<HistoryItem*> item;
- Flags flags = 0;
- };
- struct EntryUpdate {
- enum class Flag : uint32 {
- None = 0,
- Repaint = (1U << 0),
- HasPinnedMessages = (1U << 1),
- ForwardDraft = (1U << 2),
- LocalDraftSet = (1U << 3),
- Height = (1U << 4),
- Destroyed = (1U << 5),
- LastUsedBit = (1U << 5),
- };
- using Flags = base::flags<Flag>;
- friend inline constexpr auto is_flag_type(Flag) { return true; }
- not_null<Dialogs::Entry*> entry;
- Flags flags = 0;
- };
- struct StoryUpdate {
- enum class Flag : uint32 {
- None = 0,
- Edited = (1U << 0),
- Destroyed = (1U << 1),
- NewAdded = (1U << 2),
- ViewsChanged = (1U << 3),
- MarkRead = (1U << 4),
- Reaction = (1U << 5),
- LastUsedBit = (1U << 5),
- };
- using Flags = base::flags<Flag>;
- friend inline constexpr auto is_flag_type(Flag) { return true; }
- not_null<Story*> story;
- Flags flags = 0;
- };
- class Changes final {
- public:
- explicit Changes(not_null<Main::Session*> session);
- [[nodiscard]] Main::Session &session() const;
- void nameUpdated(
- not_null<PeerData*> peer,
- base::flat_set<QChar> oldFirstLetters);
- [[nodiscard]] rpl::producer<NameUpdate> realtimeNameUpdates() const;
- [[nodiscard]] rpl::producer<NameUpdate> realtimeNameUpdates(
- not_null<PeerData*> peer) const;
- void peerUpdated(not_null<PeerData*> peer, PeerUpdate::Flags flags);
- [[nodiscard]] rpl::producer<PeerUpdate> peerUpdates(
- PeerUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<PeerUpdate> peerUpdates(
- not_null<PeerData*> peer,
- PeerUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<PeerUpdate> peerFlagsValue(
- not_null<PeerData*> peer,
- PeerUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<PeerUpdate> realtimePeerUpdates(
- PeerUpdate::Flag flag) const;
- void historyUpdated(
- not_null<History*> history,
- HistoryUpdate::Flags flags);
- [[nodiscard]] rpl::producer<HistoryUpdate> historyUpdates(
- HistoryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<HistoryUpdate> historyUpdates(
- not_null<History*> history,
- HistoryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<HistoryUpdate> historyFlagsValue(
- not_null<History*> history,
- HistoryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<HistoryUpdate> realtimeHistoryUpdates(
- HistoryUpdate::Flag flag) const;
- void topicUpdated(
- not_null<ForumTopic*> topic,
- TopicUpdate::Flags flags);
- [[nodiscard]] rpl::producer<TopicUpdate> topicUpdates(
- TopicUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<TopicUpdate> topicUpdates(
- not_null<ForumTopic*> topic,
- TopicUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<TopicUpdate> topicFlagsValue(
- not_null<ForumTopic*> topic,
- TopicUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<TopicUpdate> realtimeTopicUpdates(
- TopicUpdate::Flag flag) const;
- void topicRemoved(not_null<ForumTopic*> topic);
- void messageUpdated(
- not_null<HistoryItem*> item,
- MessageUpdate::Flags flags);
- [[nodiscard]] rpl::producer<MessageUpdate> messageUpdates(
- MessageUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<MessageUpdate> messageUpdates(
- not_null<HistoryItem*> item,
- MessageUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<MessageUpdate> messageFlagsValue(
- not_null<HistoryItem*> item,
- MessageUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<MessageUpdate> realtimeMessageUpdates(
- MessageUpdate::Flag flag) const;
- void entryUpdated(
- not_null<Dialogs::Entry*> entry,
- EntryUpdate::Flags flags);
- [[nodiscard]] rpl::producer<EntryUpdate> entryUpdates(
- EntryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<EntryUpdate> entryUpdates(
- not_null<Dialogs::Entry*> entry,
- EntryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<EntryUpdate> entryFlagsValue(
- not_null<Dialogs::Entry*> entry,
- EntryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<EntryUpdate> realtimeEntryUpdates(
- EntryUpdate::Flag flag) const;
- void entryRemoved(not_null<Dialogs::Entry*> entry);
- void storyUpdated(
- not_null<Story*> story,
- StoryUpdate::Flags flags);
- [[nodiscard]] rpl::producer<StoryUpdate> storyUpdates(
- StoryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<StoryUpdate> storyUpdates(
- not_null<Story*> story,
- StoryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<StoryUpdate> storyFlagsValue(
- not_null<Story*> story,
- StoryUpdate::Flags flags) const;
- [[nodiscard]] rpl::producer<StoryUpdate> realtimeStoryUpdates(
- StoryUpdate::Flag flag) const;
- void sendNotifications();
- private:
- template <typename DataType, typename UpdateType>
- class Manager final {
- public:
- using Flag = typename UpdateType::Flag;
- using Flags = typename UpdateType::Flags;
- void updated(
- not_null<DataType*> data,
- Flags flags,
- bool dropScheduled = false);
- [[nodiscard]] rpl::producer<UpdateType> updates(Flags flags) const;
- [[nodiscard]] rpl::producer<UpdateType> updates(
- not_null<DataType*> data,
- Flags flags) const;
- [[nodiscard]] rpl::producer<UpdateType> flagsValue(
- not_null<DataType*> data,
- Flags flags) const;
- [[nodiscard]] rpl::producer<UpdateType> realtimeUpdates(
- Flag flag) const;
- void drop(not_null<DataType*> data);
- void sendNotifications();
- private:
- static constexpr auto kCount = details::CountBit<Flag>() + 1;
- void sendRealtimeNotifications(
- not_null<DataType*> data,
- Flags flags);
- std::array<rpl::event_stream<UpdateType>, kCount> _realtimeStreams;
- base::flat_map<not_null<DataType*>, Flags> _updates;
- rpl::event_stream<UpdateType> _stream;
- };
- void scheduleNotifications();
- const not_null<Main::Session*> _session;
- rpl::event_stream<NameUpdate> _nameStream;
- Manager<PeerData, PeerUpdate> _peerChanges;
- Manager<History, HistoryUpdate> _historyChanges;
- Manager<ForumTopic, TopicUpdate> _topicChanges;
- Manager<HistoryItem, MessageUpdate> _messageChanges;
- Manager<Dialogs::Entry, EntryUpdate> _entryChanges;
- Manager<Story, StoryUpdate> _storyChanges;
- bool _notify = false;
- };
- } // namespace Data
|