/* 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; namespace Dialogs { class MainList; class Key; } // namespace Dialogs namespace Data { class Session; class ChatFilter final { public: enum class Flag : uchar { Contacts = 0x01, NonContacts = 0x02, Groups = 0x04, Channels = 0x08, Bots = 0x10, NoMuted = 0x20, NoRead = 0x40, NoArchived = 0x80, }; friend constexpr inline bool is_flag_type(Flag) { return true; }; using Flags = base::flags; ChatFilter() = default; ChatFilter( FilterId id, const QString &title, const QString &iconEmoji, Flags flags, base::flat_set> always, std::vector> pinned, base::flat_set> never); [[nodiscard]] static ChatFilter FromTL( const MTPDialogFilter &data, not_null owner); [[nodiscard]] MTPDialogFilter tl(FilterId replaceId = 0) const; [[nodiscard]] FilterId id() const; [[nodiscard]] QString title() const; [[nodiscard]] QString iconEmoji() const; [[nodiscard]] Flags flags() const; [[nodiscard]] const base::flat_set> &always() const; [[nodiscard]] const std::vector> &pinned() const; [[nodiscard]] const base::flat_set> &never() const; [[nodiscard]] bool contains(not_null history) const; private: FilterId _id = 0; QString _title; QString _iconEmoji; base::flat_set> _always; std::vector> _pinned; base::flat_set> _never; Flags _flags; }; inline bool operator==(const ChatFilter &a, const ChatFilter &b) { return (a.title() == b.title()) && (a.iconEmoji() == b.iconEmoji()) && (a.flags() == b.flags()) && (a.always() == b.always()) && (a.never() == b.never()); } inline bool operator!=(const ChatFilter &a, const ChatFilter &b) { return !(a == b); } struct SuggestedFilter { ChatFilter filter; QString description; }; class ChatFilters final { public: explicit ChatFilters(not_null owner); ~ChatFilters(); void setPreloaded(const QVector &result); void load(); void apply(const MTPUpdate &update); void set(ChatFilter filter); void remove(FilterId id); void moveAllToFront(); [[nodiscard]] const std::vector &list() const; [[nodiscard]] rpl::producer<> changed() const; [[nodiscard]] bool has() const; bool loadNextExceptions(bool chatsListLoaded); void refreshHistory(not_null history); [[nodiscard]] not_null chatsList(FilterId filterId); const ChatFilter &applyUpdatedPinned( FilterId id, const std::vector &dialogs); void saveOrder( const std::vector &order, mtpRequestId after = 0); [[nodiscard]] bool archiveNeeded() const; void requestSuggested(); [[nodiscard]] bool suggestedLoaded() const; [[nodiscard]] auto suggestedFilters() const -> const std::vector &; [[nodiscard]] rpl::producer<> suggestedUpdated() const; private: void load(bool force); void received(const QVector &list); bool applyOrder(const QVector &order); bool applyChange(ChatFilter &filter, ChatFilter &&updated); void applyInsert(ChatFilter filter, int position); void applyRemove(int position); const not_null _owner; std::vector _list; base::flat_map> _chatsLists; rpl::event_stream<> _listChanged; mtpRequestId _loadRequestId = 0; mtpRequestId _saveOrderRequestId = 0; mtpRequestId _saveOrderAfterId = 0; bool _loaded = false; mtpRequestId _suggestedRequestId = 0; std::vector _suggested; rpl::event_stream<> _suggestedUpdated; crl::time _suggestedLastReceived = 0; std::deque _exceptionsToLoad; mtpRequestId _exceptionsLoadRequestId = 0; }; } // namespace Data