/* 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 "mtproto/sender.h" #include "data/stickers/data_stickers_set.h" #include "settings.h" class HistoryItem; class DocumentData; namespace Main { class Session; } // namespace Main namespace Window { class SessionController; } // namespace Window namespace Data { class Session; class DocumentMedia; class Stickers final { public: explicit Stickers(not_null owner); [[nodiscard]] Session &owner() const; [[nodiscard]] Main::Session &session() const; // for backward compatibility static constexpr auto DefaultSetId = 0; static constexpr auto CustomSetId = 0xFFFFFFFFFFFFFFFFULL; // For stickers panel, should not appear in Sets. static constexpr auto RecentSetId = 0xFFFFFFFFFFFFFFFEULL; static constexpr auto NoneSetId = 0xFFFFFFFFFFFFFFFDULL; static constexpr auto FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL; static constexpr auto PremiumSetId = 0xFFFFFFFFFFFFFFF8ULL; // For cloud-stored recent stickers. static constexpr auto CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; static constexpr auto CloudRecentAttachedSetId = 0xFFFFFFFFFFFFFFF9ULL; // For cloud-stored faved stickers. static constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL; // For setting up megagroup sticker set. static constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL; enum Recent { Regular, Attached, }; void notifyUpdated(); [[nodiscard]] rpl::producer<> updated() const; void notifyRecentUpdated(Recent recent = Recent::Regular); [[nodiscard]] rpl::producer recentUpdated() const; void notifySavedGifsUpdated(); [[nodiscard]] rpl::producer<> savedGifsUpdated() const; void notifyStickerSetInstalled(uint64 setId); [[nodiscard]] rpl::producer stickerSetInstalled() const; void incrementSticker(not_null document); bool updateNeeded(crl::time now) const { return updateNeeded(_lastUpdate, now); } void setLastUpdate(crl::time update) { _lastUpdate = update; } bool recentUpdateNeeded(crl::time now) const { return updateNeeded(_lastRecentUpdate, now); } void setLastRecentUpdate(crl::time update) { if (update) { notifyRecentUpdated(); } _lastRecentUpdate = update; } bool masksUpdateNeeded(crl::time now) const { return updateNeeded(_lastMasksUpdate, now); } void setLastMasksUpdate(crl::time update) { _lastMasksUpdate = update; } bool recentAttachedUpdateNeeded(crl::time now) const { return updateNeeded(_lastRecentAttachedUpdate, now); } void setLastRecentAttachedUpdate(crl::time update) { if (update) { notifyRecentUpdated(Recent::Attached); } _lastRecentAttachedUpdate = update; } bool favedUpdateNeeded(crl::time now) const { return updateNeeded(_lastFavedUpdate, now); } void setLastFavedUpdate(crl::time update) { _lastFavedUpdate = update; } bool featuredUpdateNeeded(crl::time now) const { return updateNeeded(_lastFeaturedUpdate, now); } void setLastFeaturedUpdate(crl::time update) { _lastFeaturedUpdate = update; } bool savedGifsUpdateNeeded(crl::time now) const { return updateNeeded(_lastSavedGifsUpdate, now); } void setLastSavedGifsUpdate(crl::time update) { _lastSavedGifsUpdate = update; } int featuredSetsUnreadCount() const { return _featuredSetsUnreadCount.current(); } void setFeaturedSetsUnreadCount(int count) { _featuredSetsUnreadCount = count; } [[nodiscard]] rpl::producer featuredSetsUnreadCountValue() const { return _featuredSetsUnreadCount.value(); } const StickersSets &sets() const { return _sets; } StickersSets &setsRef() { return _sets; } const StickersSetsOrder &setsOrder() const { return _setsOrder; } StickersSetsOrder &setsOrderRef() { return _setsOrder; } const StickersSetsOrder &maskSetsOrder() const { return _maskSetsOrder; } StickersSetsOrder &maskSetsOrderRef() { return _maskSetsOrder; } const StickersSetsOrder &featuredSetsOrder() const { return _featuredSetsOrder; } StickersSetsOrder &featuredSetsOrderRef() { return _featuredSetsOrder; } const StickersSetsOrder &archivedSetsOrder() const { return _archivedSetsOrder; } StickersSetsOrder &archivedSetsOrderRef() { return _archivedSetsOrder; } const StickersSetsOrder &archivedMaskSetsOrder() const { return _archivedMaskSetsOrder; } StickersSetsOrder &archivedMaskSetsOrderRef() { return _archivedMaskSetsOrder; } const SavedGifs &savedGifs() const { return _savedGifs; } SavedGifs &savedGifsRef() { return _savedGifs; } void removeFromRecentSet(not_null document); void addSavedGif( Window::SessionController *controller, not_null document); void checkSavedGif(not_null item); void applyArchivedResult( const MTPDmessages_stickerSetInstallResultArchive &d); void installLocally(uint64 setId); void undoInstallLocally(uint64 setId); bool isFaved(not_null document); void setFaved( Window::SessionController *controller, not_null document, bool faved); void setsReceived(const QVector &data, uint64 hash); void masksReceived(const QVector &data, uint64 hash); void specialSetReceived( uint64 setId, const QString &setTitle, const QVector &items, uint64 hash, const QVector &packs = QVector(), const QVector &usageDates = QVector()); void featuredSetsReceived( const QVector &list, const QVector &unread, uint64 hash); void gifsReceived(const QVector &items, uint64 hash); std::vector> getListByEmoji( not_null emoji, uint64 seed); std::optional>> getEmojiListFromSet( not_null document); StickersSet *feedSet(const MTPDstickerSet &data); StickersSet *feedSetFull(const MTPDmessages_stickerSet &d); void newSetReceived(const MTPDmessages_stickerSet &set); QString getSetTitle(const MTPDstickerSet &s); RecentStickerPack &getRecentPack() const; private: bool updateNeeded(crl::time lastUpdate, crl::time now) const { constexpr auto kUpdateTimeout = crl::time(3600'000); return (lastUpdate == 0) || (now >= lastUpdate + kUpdateTimeout); } void checkFavedLimit( StickersSet &set, Window::SessionController *controller = nullptr); void setIsFaved( Window::SessionController *controller, not_null document, std::optional>> emojiList = std::nullopt); void setIsNotFaved(not_null document); void pushFavedToFront( StickersSet &set, Window::SessionController *controller, not_null document, const std::vector> &emojiList); void moveFavedToFront(StickersSet &set, int index); void requestSetToPushFaved( Window::SessionController *controller, not_null document); void setPackAndEmoji( StickersSet &set, StickersPack &&pack, const std::vector &&dates, const QVector &packs); void setsOrMasksReceived( const QVector &data, uint64 hash, bool masks); const not_null _owner; rpl::event_stream<> _updated; rpl::event_stream _recentUpdated; rpl::event_stream<> _savedGifsUpdated; rpl::event_stream _stickerSetInstalled; crl::time _lastUpdate = 0; crl::time _lastRecentUpdate = 0; crl::time _lastFavedUpdate = 0; crl::time _lastFeaturedUpdate = 0; crl::time _lastSavedGifsUpdate = 0; crl::time _lastMasksUpdate = 0; crl::time _lastRecentAttachedUpdate = 0; rpl::variable _featuredSetsUnreadCount = 0; StickersSets _sets; StickersSetsOrder _setsOrder; StickersSetsOrder _maskSetsOrder; StickersSetsOrder _featuredSetsOrder; StickersSetsOrder _archivedSetsOrder; StickersSetsOrder _archivedMaskSetsOrder; SavedGifs _savedGifs; }; } // namespace Data