tdesktop/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h

376 lines
9.5 KiB
C++

/*
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 "chat_helpers/tabbed_selector.h"
#include "data/stickers/data_stickers.h"
#include "base/variant.h"
#include "base/timer.h"
namespace Main {
class Session;
} // namespace Main
namespace Window {
class SessionController;
} // namespace Window
namespace Ui {
class LinkButton;
class PopupMenu;
class RippleAnimation;
class BoxContent;
} // namespace Ui
namespace Lottie {
class Animation;
class MultiPlayer;
class FrameRenderer;
} // namespace Lottie
namespace Data {
class DocumentMedia;
class StickersSet;
} // namespace Data
namespace ChatHelpers {
struct StickerIcon;
class StickersListWidget
: public TabbedSelector::Inner
, private base::Subscriber {
public:
StickersListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller);
Main::Session &session() const;
rpl::producer<TabbedSelector::FileChosen> chosen() const;
rpl::producer<> scrollUpdated() const;
rpl::producer<> checkForHide() const;
void refreshRecent() override;
void preloadImages() override;
void clearSelection() override;
object_ptr<TabbedSelector::InnerFooter> createFooter() override;
void showStickerSet(uint64 setId);
void showMegagroupSet(ChannelData *megagroup);
void afterShown() override;
void beforeHiding() override;
void refreshStickers();
std::vector<StickerIcon> fillIcons();
bool preventAutoHide();
uint64 currentSet(int yOffset) const;
void installedLocally(uint64 setId);
void notInstalledLocally(uint64 setId);
void clearInstalledLocally();
void sendSearchRequest();
void searchForSets(const QString &query);
std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
void fillContextMenu(
not_null<Ui::PopupMenu*> menu,
SendMenu::Type type) override;
~StickersListWidget();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void leaveEventHook(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override;
TabbedSelector::InnerFooter *getFooter() const override;
void processHideFinished() override;
void processPanelHideFinished() override;
int countDesiredHeight(int newWidth) override;
private:
class Footer;
enum class Section {
Featured,
Stickers,
Search,
};
struct OverSticker {
int section = 0;
int index = 0;
bool overDelete = false;
};
struct OverSet {
int section = 0;
};
struct OverButton {
int section = 0;
};
struct OverGroupAdd {
};
friend inline bool operator==(OverSticker a, OverSticker b) {
return (a.section == b.section)
&& (a.index == b.index)
&& (a.overDelete == b.overDelete);
}
friend inline bool operator==(OverSet a, OverSet b) {
return (a.section == b.section);
}
friend inline bool operator==(OverButton a, OverButton b) {
return (a.section == b.section);
}
friend inline bool operator==(OverGroupAdd a, OverGroupAdd b) {
return true;
}
using OverState = std::variant<
v::null_t,
OverSticker,
OverSet,
OverButton,
OverGroupAdd>;
struct SectionInfo {
int section = 0;
int count = 0;
int top = 0;
int rowsCount = 0;
int rowsTop = 0;
int rowsBottom = 0;
};
struct Sticker {
not_null<DocumentData*> document;
std::shared_ptr<Data::DocumentMedia> documentMedia;
Lottie::Animation *animated = nullptr;
QPixmap savedFrame;
void ensureMediaCreated();
};
struct Set {
Set(
uint64 id,
Data::StickersSet *set,
MTPDstickerSet::Flags flags,
const QString &title,
const QString &shortName,
int count,
bool externalLayout,
std::vector<Sticker> &&stickers = {});
Set(Set &&other);
Set &operator=(Set &&other);
~Set();
uint64 id = 0;
Data::StickersSet *set = nullptr;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
QString title;
QString shortName;
std::vector<Sticker> stickers;
std::unique_ptr<Ui::RippleAnimation> ripple;
std::unique_ptr<Lottie::MultiPlayer> lottiePlayer;
rpl::lifetime lottieLifetime;
int count = 0;
bool externalLayout = false;
};
struct FeaturedSet {
uint64 id = 0;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
std::vector<Sticker> stickers;
};
static std::vector<Sticker> PrepareStickers(
const QVector<DocumentData*> &pack);
void preloadMoreOfficial();
QSize boundingBoxSize() const;
template <typename Callback>
bool enumerateSections(Callback callback) const;
SectionInfo sectionInfo(int section) const;
SectionInfo sectionInfoByOffset(int yOffset) const;
void setSection(Section section);
void displaySet(uint64 setId);
void checkHideWithBox(QPointer<Ui::BoxContent> box);
void installSet(uint64 setId);
void removeMegagroupSet(bool locally);
void removeSet(uint64 setId);
void sendInstallRequest(
uint64 setId,
const MTPInputStickerSet &input);
void refreshMySets();
void refreshFeaturedSets();
void refreshSearchSets();
void refreshSearchIndex();
bool setHasTitle(const Set &set) const;
bool stickerHasDeleteButton(const Set &set, int index) const;
std::vector<Sticker> collectRecentStickers();
void refreshRecentStickers(bool resize = true);
void refreshFavedStickers();
enum class GroupStickersPlace {
Visible,
Hidden,
};
void refreshMegagroupStickers(GroupStickersPlace place);
void refreshSettingsVisibility();
void updateSelected();
void setSelected(OverState newSelected);
void setPressed(OverState newPressed);
std::unique_ptr<Ui::RippleAnimation> createButtonRipple(int section);
QPoint buttonRippleTopLeft(int section) const;
enum class ValidateIconAnimations {
Full,
Scroll,
None,
};
void validateSelectedIcon(ValidateIconAnimations animations);
std::vector<Set> &shownSets();
const std::vector<Set> &shownSets() const;
int featuredRowHeight() const;
void checkVisibleFeatured(int visibleTop, int visibleBottom);
void readVisibleFeatured(int visibleTop, int visibleBottom);
void paintStickers(Painter &p, QRect clip);
void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected);
void paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected);
void paintEmptySearchResults(Painter &p);
void ensureLottiePlayer(Set &set);
void setupLottie(Set &set, int section, int index);
void markLottieFrameShown(Set &set);
void checkVisibleLottie();
void pauseInvisibleLottieIn(const SectionInfo &info);
void takeHeavyData(std::vector<Set> &to, std::vector<Set> &from);
void takeHeavyData(Set &to, Set &from);
void takeHeavyData(Sticker &to, Sticker &from);
void clearHeavyIn(Set &set, bool clearSavedFrames = true);
void clearHeavyData();
int stickersRight() const;
bool featuredHasAddButton(int index) const;
QRect featuredAddRect(int index) const;
bool hasRemoveButton(int index) const;
QRect removeButtonRect(int index) const;
int megagroupSetInfoLeft() const;
void refreshMegagroupSetGeometry();
QRect megagroupSetButtonRectFinal() const;
enum class AppendSkip {
None,
Archived,
Installed,
};
bool appendSet(
std::vector<Set> &to,
uint64 setId,
bool externalLayout,
AppendSkip skip = AppendSkip::None);
void selectEmoji(EmojiPtr emoji);
int stickersLeft() const;
QRect stickerRect(int section, int sel);
void removeRecentSticker(int section, int index);
void removeFavedSticker(int section, int index);
void setColumnCount(int count);
void refreshFooterIcons();
void showStickerSetBox(not_null<DocumentData*> document);
void cancelSetsSearch();
void showSearchResults();
void searchResultsDone(const MTPmessages_FoundStickerSets &result);
void refreshSearchRows();
void refreshSearchRows(const std::vector<uint64> *cloudSets);
void fillLocalSearchRows(const QString &query);
void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
void addSearchRow(not_null<Data::StickersSet*> set);
void showPreview();
MTP::Sender _api;
ChannelData *_megagroupSet = nullptr;
uint64 _megagroupSetIdRequested = 0;
std::vector<Set> _mySets;
std::vector<Set> _officialSets;
std::vector<Set> _searchSets;
int _featuredSetsCount = 0;
base::flat_set<uint64> _installedLocallySets;
std::vector<bool> _custom;
base::flat_set<not_null<DocumentData*>> _favedStickersMap;
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
mtpRequestId _officialRequestId = 0;
int _officialOffset = 0;
Section _section = Section::Stickers;
bool _displayingSet = false;
uint64 _removingSetId = 0;
Footer *_footer = nullptr;
int _rowsLeft = 0;
int _columnCount = 1;
QSize _singleSize;
OverState _selected;
OverState _pressed;
QPoint _lastMousePosition;
Ui::Text::String _megagroupSetAbout;
QString _megagroupSetButtonText;
int _megagroupSetButtonTextWidth = 0;
QRect _megagroupSetButtonRect;
std::unique_ptr<Ui::RippleAnimation> _megagroupSetButtonRipple;
QString _addText;
int _addWidth;
object_ptr<Ui::LinkButton> _settings;
base::Timer _previewTimer;
bool _previewShown = false;
std::map<QString, std::vector<uint64>> _searchCache;
std::vector<std::pair<uint64, QStringList>> _searchIndex;
base::Timer _searchRequestTimer;
QString _searchQuery, _searchNextQuery;
mtpRequestId _searchRequestId = 0;
rpl::event_stream<TabbedSelector::FileChosen> _chosen;
rpl::event_stream<> _scrollUpdated;
rpl::event_stream<> _checkForHide;
};
} // namespace ChatHelpers