/* 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 "media/clip/media_clip_reader.h" #include "chat_helpers/tabbed_selector.h" #include "ui/round_rect.h" namespace Ui { class InputField; class CrossButton; } // namespace Ui namespace Data { class StickersSet; class StickersSetThumbnailView; class DocumentMedia; class CloudImageView; } // namespace Data namespace Lottie { class SinglePlayer; class FrameRenderer; } // namespace Lottie namespace Window { class SessionController; } // namespace Window namespace ChatHelpers { enum class ValidateIconAnimations { Full, Scroll, None, }; [[nodiscard]] uint64 EmojiSectionSetId(Ui::Emoji::Section section); [[nodiscard]] uint64 RecentEmojiSectionSetId(); [[nodiscard]] uint64 AllEmojiSectionSetId(); [[nodiscard]] std::optional SetIdEmojiSection(uint64 id); struct StickerIcon { explicit StickerIcon(uint64 setId); StickerIcon( not_null set, DocumentData *sticker, int pixw, int pixh); StickerIcon(StickerIcon&&); StickerIcon &operator=(StickerIcon&&); ~StickerIcon(); void ensureMediaCreated() const; uint64 setId = 0; Data::StickersSet *set = nullptr; mutable std::unique_ptr lottie; mutable Media::Clip::ReaderPointer webm; mutable QPixmap savedFrame; DocumentData *sticker = nullptr; ChannelData *megagroup = nullptr; mutable std::shared_ptr thumbnailMedia; mutable std::shared_ptr stickerMedia; mutable std::shared_ptr megagroupUserpic; int pixw = 0; int pixh = 0; mutable rpl::lifetime lifetime; }; class StickersListFooter final : public TabbedSelector::InnerFooter { public: struct Descriptor { not_null controller; not_null parent; bool searchButtonVisible = false; bool settingsButtonVisible = false; bool barSelection = false; }; explicit StickersListFooter(Descriptor &&descriptor); void preloadImages(); void validateSelectedIcon( uint64 setId, ValidateIconAnimations animations); void refreshIcons( std::vector icons, Fn()> renderer, ValidateIconAnimations animations); [[nodiscard]] bool hasOnlyFeaturedSets() const; void leaveToChildEvent(QEvent *e, QWidget *child) override; void stealFocus(); void returnFocus(); void setLoading(bool loading); void clearHeavyData(); [[nodiscard]] rpl::producer setChosen() const; [[nodiscard]] rpl::producer<> openSettingsRequests() const; struct SearchRequest { QString text; bool forced = false; }; [[nodiscard]] rpl::producer searchRequests() const; protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; bool eventHook(QEvent *e) override; void processHideFinished() override; private: enum class SpecialOver { None, Search, Settings, }; struct IconId { int index = 0; int subindex = 0; friend inline bool operator==(IconId a, IconId b) { return (a.index == b.index) && (a.subindex == b.subindex); } }; using OverState = std::variant; struct IconInfo { int index = 0; int left = 0; int adjustedLeft = 0; int width = 0; bool visible = false; }; struct ScrollState { template explicit ScrollState(UpdateCallback &&callback); bool animationCallback(crl::time now); int selected = 0; int max = 0; int draggingStartX = 0; bool dragging = false; anim::value x; anim::value selectionX; anim::value selectionWidth; crl::time animationStart = 0; Ui::Animations::Basic animation; }; void enumerateVisibleIcons(Fn callback) const; void enumerateIcons(Fn callback) const; void enumerateSubicons(Fn callback) const; [[nodiscard]] IconInfo iconInfo(int index) const; [[nodiscard]] IconInfo subiconInfo(int index) const; [[nodiscard]] std::shared_ptr getLottieRenderer(); void setSelectedIcon( int newSelected, ValidateIconAnimations animations); void setSelectedSubicon( int newSelected, ValidateIconAnimations animations); void validateIconLottieAnimation(const StickerIcon &icon); void validateIconWebmAnimation(const StickerIcon &icon); void validateIconAnimation(const StickerIcon &icon); void refreshIconsGeometry(ValidateIconAnimations animations); void refreshSubiconsGeometry(); void refreshScrollableDimensions(); void updateSelected(); void updateSetIcon(uint64 setId); void updateSetIconAt(int left); void checkDragging(ScrollState &state); bool finishDragging(ScrollState &state); bool finishDragging(); void paintStickerSettingsIcon(Painter &p) const; void paintSearchIcon(Painter &p) const; void paintSetIcon( Painter &p, const IconInfo &info, crl::time now, bool paused) const; void paintSelectionBg(Painter &p) const; void paintSelectionBar(Painter &p) const; void paintLeftRightFading(Painter &p) const; void validatePremiumIcon() const; void updateEmojiSectionWidth(); void updateEmojiWidthCallback(); void initSearch(); void toggleSearch(bool visible); void resizeSearchControls(); void scrollByWheelEvent(not_null e); void clipCallback(Media::Clip::Notification notification, uint64 setId); const not_null _controller; const bool _searchButtonVisible = false; const bool _settingsButtonVisible = false; static constexpr auto kVisibleIconsCount = 8; std::weak_ptr _lottieRenderer; std::vector _icons; Fn()> _renderer; uint64 _activeByScrollId = 0; OverState _selected = SpecialOver::None; OverState _pressed = SpecialOver::None; QPoint _iconsMousePos, _iconsMouseDown; mutable QImage _premiumIcon; int _iconsLeft = 0; int _iconsRight = 0; int _iconsTop = 0; ScrollState _iconState; ScrollState _subiconState; Ui::RoundRect _selectionBg; Ui::Animations::Simple _subiconsWidthAnimation; int _subiconsWidth = 0; bool _subiconsExpanded = false; bool _barSelection = false; bool _horizontal = false; bool _searchShown = false; object_ptr _searchField = { nullptr }; object_ptr _searchCancel = { nullptr }; QPointer _focusTakenFrom; rpl::event_stream<> _openSettingsRequests; rpl::event_stream _setChosen; rpl::event_stream _searchRequests; }; } // namespace ChatHelpers