| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- /*
- 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 "ui/cached_round_corners.h"
- #include "ui/chat/message_bubble.h"
- #include "ui/chat/chat_style_radius.h"
- #include "ui/controls/swipe_handler_data.h"
- #include "ui/style/style_core_palette.h"
- #include "layout/layout_selection.h"
- #include "styles/style_basic.h"
- enum class ImageRoundRadius;
- namespace style {
- struct TwoIconButton;
- struct ScrollArea;
- } // namespace style
- namespace Ui::Text {
- class CustomEmoji;
- } // namespace Ui::Text
- namespace Ui {
- class ChatTheme;
- class ChatStyle;
- struct BubblePattern;
- inline constexpr auto kColorPatternsCount = Text::kMaxQuoteOutlines;
- inline constexpr auto kColorIndexCount = uint8(1 << 6);
- inline constexpr auto kSimpleColorIndexCount = uint8(7);
- inline constexpr auto kDefaultBgOpacity = 0.12;
- inline constexpr auto kDefaultOutline1Opacity = 0.9;
- inline constexpr auto kDefaultOutline2Opacity = 0.3;
- inline constexpr auto kDefaultOutline3Opacity = 0.6;
- inline constexpr auto kDefaultOutlineOpacitySecond = 0.5;
- struct MessageStyle {
- CornersPixmaps msgBgCornersSmall;
- CornersPixmaps msgBgCornersLarge;
- style::color msgBg;
- style::color msgShadow;
- style::color msgServiceFg;
- style::color msgDateFg;
- style::color msgFileThumbLinkFg;
- style::color msgFileBg;
- style::color msgReplyBarColor;
- style::color msgWaveformActive;
- style::color msgWaveformInactive;
- style::color historyTextFg;
- style::color historyFileNameFg;
- style::color historyFileRadialFg;
- style::color mediaFg;
- style::TextPalette textPalette;
- style::TextPalette semiboldPalette;
- style::TextPalette fwdTextPalette;
- style::TextPalette replyTextPalette;
- style::icon tailLeft = { Qt::Uninitialized };
- style::icon tailRight = { Qt::Uninitialized };
- style::icon historyRepliesIcon = { Qt::Uninitialized };
- style::icon historyViewsIcon = { Qt::Uninitialized };
- style::icon historyPinIcon = { Qt::Uninitialized };
- style::icon historySentIcon = { Qt::Uninitialized };
- style::icon historyReceivedIcon = { Qt::Uninitialized };
- style::icon historyPsaIcon = { Qt::Uninitialized };
- style::icon historyCommentsOpen = { Qt::Uninitialized };
- style::icon historyComments = { Qt::Uninitialized };
- style::icon historyCallArrow = { Qt::Uninitialized };
- style::icon historyCallArrowMissed = { Qt::Uninitialized };
- style::icon historyCallIcon = { Qt::Uninitialized };
- style::icon historyCallCameraIcon = { Qt::Uninitialized };
- style::icon historyFilePlay = { Qt::Uninitialized };
- style::icon historyFileWaiting = { Qt::Uninitialized };
- style::icon historyFileDownload = { Qt::Uninitialized };
- style::icon historyFileCancel = { Qt::Uninitialized };
- style::icon historyFilePause = { Qt::Uninitialized };
- style::icon historyFileImage = { Qt::Uninitialized };
- style::icon historyFileDocument = { Qt::Uninitialized };
- style::icon historyAudioDownload = { Qt::Uninitialized };
- style::icon historyAudioCancel = { Qt::Uninitialized };
- style::icon historyQuizTimer = { Qt::Uninitialized };
- style::icon historyQuizExplain = { Qt::Uninitialized };
- style::icon historyPollChosen = { Qt::Uninitialized };
- style::icon historyPollChoiceRight = { Qt::Uninitialized };
- style::icon historyTranscribeIcon = { Qt::Uninitialized };
- style::icon historyTranscribeLock = { Qt::Uninitialized };
- style::icon historyTranscribeHide = { Qt::Uninitialized };
- style::icon historyVoiceMessageTTL = { Qt::Uninitialized };
- style::icon liveLocationLongIcon = { Qt::Uninitialized };
- std::array<
- std::unique_ptr<Text::QuotePaintCache>,
- kColorPatternsCount> quoteCache;
- std::array<
- std::unique_ptr<Text::QuotePaintCache>,
- kColorPatternsCount> replyCache;
- std::unique_ptr<Text::QuotePaintCache> preCache;
- };
- struct MessageImageStyle {
- CornersPixmaps msgDateImgBgCorners;
- CornersPixmaps msgServiceBgCornersSmall;
- CornersPixmaps msgServiceBgCornersLarge;
- CornersPixmaps msgShadowCornersSmall;
- CornersPixmaps msgShadowCornersLarge;
- style::color msgServiceBg;
- style::color msgDateImgBg;
- style::color msgShadow;
- style::color historyFileThumbRadialFg;
- style::icon historyFileThumbPlay = { Qt::Uninitialized };
- style::icon historyFileThumbWaiting = { Qt::Uninitialized };
- style::icon historyFileThumbDownload = { Qt::Uninitialized };
- style::icon historyFileThumbCancel = { Qt::Uninitialized };
- style::icon historyFileThumbPause = { Qt::Uninitialized };
- style::icon historyVideoDownload = { Qt::Uninitialized };
- style::icon historyVideoCancel = { Qt::Uninitialized };
- style::icon historyVideoMessageMute = { Qt::Uninitialized };
- style::icon historyVideoMessageTtlIcon = { Qt::Uninitialized };
- style::icon historyPageEnlarge = { Qt::Uninitialized };
- };
- struct ReactionPaintInfo {
- QPoint position;
- QPoint effectOffset;
- Fn<QRect(QPainter&)> effectPaint;
- };
- struct BackgroundEmojiCache {
- QColor color;
- std::array<QImage, 3> frames;
- };
- struct BackgroundEmojiData {
- std::unique_ptr<Text::CustomEmoji> emoji;
- QImage firstFrameMask;
- std::array<BackgroundEmojiCache, 2 * (3 + kColorIndexCount)> caches;
- [[nodiscard]] static int CacheIndex(
- bool selected,
- bool outbg,
- bool inbubble,
- uint8 colorIndexPlusOne);
- };
- struct ChatPaintHighlight {
- float64 opacity = 0.;
- float64 collapsion = 0.;
- TextSelection range;
- };
- struct ChatPaintContext {
- not_null<const ChatStyle*> st;
- const BubblePattern *bubblesPattern = nullptr;
- ReactionPaintInfo *reactionInfo = nullptr;
- QRect viewport;
- QRect clip;
- TextSelection selection;
- ChatPaintHighlight highlight;
- QPainterPath *highlightPathCache = nullptr;
- mutable QRect highlightInterpolateTo;
- crl::time now = 0;
- Ui::Controls::SwipeContextData gestureHorizontal;
- void translate(int x, int y) {
- viewport.translate(x, y);
- clip.translate(x, y);
- highlightInterpolateTo.translate(x, y);
- }
- void translate(QPoint point) {
- translate(point.x(), point.y());
- }
- [[nodiscard]] bool selected() const {
- return (selection == FullSelection);
- }
- [[nodiscard]] not_null<const MessageStyle*> messageStyle() const;
- [[nodiscard]] not_null<const MessageImageStyle*> imageStyle() const;
- [[nodiscard]] not_null<Text::QuotePaintCache*> quoteCache(
- uint8 colorIndex) const;
- [[nodiscard]] ChatPaintContext translated(int x, int y) const {
- auto result = *this;
- result.translate(x, y);
- return result;
- }
- [[nodiscard]] ChatPaintContext translated(QPoint point) const {
- return translated(point.x(), point.y());
- }
- [[nodiscard]] ChatPaintContext withSelection(
- TextSelection selection) const {
- auto result = *this;
- result.selection = selection;
- return result;
- }
- [[nodiscard]] auto computeHighlightCache() const
- -> std::optional<Ui::Text::HighlightInfoRequest> {
- if (highlight.range.empty() || highlight.collapsion <= 0.) {
- return {};
- }
- return Ui::Text::HighlightInfoRequest{
- .range = highlight.range,
- .interpolateTo = highlightInterpolateTo,
- .interpolateProgress = (1. - highlight.collapsion),
- .outPath = highlightPathCache,
- };
- };
- // This is supported only in unwrapped media for now.
- enum class SkipDrawingParts {
- None,
- Content,
- Surrounding,
- };
- SkipDrawingParts skipDrawingParts = SkipDrawingParts::None;
- bool outbg = false;
- bool paused = false;
- };
- struct ChatPaintContextArgs {
- not_null<ChatTheme*> theme;
- QRect clip;
- QPoint visibleAreaPositionGlobal;
- int visibleAreaTop = 0;
- int visibleAreaWidth = 0;
- };
- [[nodiscard]] int HistoryServiceMsgRadius();
- [[nodiscard]] int HistoryServiceMsgInvertedRadius();
- [[nodiscard]] int HistoryServiceMsgInvertedShrink();
- struct ColorIndexData {
- std::array<uint32, kColorPatternsCount> light = {};
- std::array<uint32, kColorPatternsCount> dark = {};
- friend inline bool operator==(
- const ColorIndexData&,
- const ColorIndexData&) = default;
- };
- struct ColorIndicesCompressed {
- std::shared_ptr<std::array<ColorIndexData, kColorIndexCount>> colors;
- };
- [[nodiscard]] int ColorPatternIndex(
- const ColorIndicesCompressed &indices,
- uint8 colorIndex,
- bool dark);
- struct ColorIndexValues {
- std::array<QColor, kColorPatternsCount> outlines;
- QColor name;
- QColor bg;
- };
- [[nodiscard]] ColorIndexValues SimpleColorIndexValues(
- QColor color,
- int patternIndex);
- class ChatStyle final : public style::palette {
- public:
- explicit ChatStyle(rpl::producer<ColorIndicesCompressed> colorIndices);
- explicit ChatStyle(not_null<const style::palette*> isolated);
- ChatStyle(const ChatStyle &other) = delete;
- ChatStyle &operator=(const ChatStyle &other) = delete;
- ~ChatStyle();
- void apply(not_null<ChatTheme*> theme);
- void applyCustomPalette(const style::palette *palette);
- void applyAdjustedServiceBg(QColor serviceBg);
- [[nodiscard]] bool dark() const {
- return _dark;
- }
- [[nodiscard]] std::span<Text::SpecialColor> highlightColors() const;
- [[nodiscard]] rpl::producer<> paletteChanged() const {
- return _paletteChanged.events();
- }
- template <typename Type>
- [[nodiscard]] Type value(const Type &original) const {
- auto my = Type();
- make(my, original);
- return my;
- }
- template <typename Type>
- [[nodiscard]] const Type &value(
- rpl::lifetime &parentLifetime,
- const Type &original) const {
- const auto my = parentLifetime.make_state<Type>();
- make(*my, original);
- return *my;
- }
- [[nodiscard]] const CornersPixmaps &serviceBgCornersNormal() const;
- [[nodiscard]] const CornersPixmaps &serviceBgCornersInverted() const;
- [[nodiscard]] const MessageStyle &messageStyle(
- bool outbg,
- bool selected) const;
- [[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const;
- [[nodiscard]] int colorPatternIndex(uint8 colorIndex) const;
- [[nodiscard]] ColorIndexValues computeColorIndexValues(
- bool selected,
- uint8 colorIndex) const;
- [[nodiscard]] auto serviceQuoteCache(bool twoColored) const
- -> not_null<Text::QuotePaintCache*>;
- [[nodiscard]] auto serviceReplyCache(bool twoColored) const
- -> not_null<Text::QuotePaintCache*>;
- [[nodiscard]] const ColorIndexValues &coloredValues(
- bool selected,
- uint8 colorIndex) const;
- [[nodiscard]] not_null<Text::QuotePaintCache*> coloredQuoteCache(
- bool selected,
- uint8 colorIndex) const;
- [[nodiscard]] not_null<Text::QuotePaintCache*> coloredReplyCache(
- bool selected,
- uint8 colorIndex) const;
- [[nodiscard]] const style::TextPalette &coloredTextPalette(
- bool selected,
- uint8 colorIndex) const;
- [[nodiscard]] not_null<BackgroundEmojiData*> backgroundEmojiData(
- uint64 id) const;
- [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersSmall() const;
- [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersLarge() const;
- [[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners(
- CachedCornerRadius radius) const;
- [[nodiscard]] const style::TextPalette &historyPsaForwardPalette() const {
- return _historyPsaForwardPalette;
- }
- [[nodiscard]] const style::TextPalette &imgReplyTextPalette() const {
- return _imgReplyTextPalette;
- }
- [[nodiscard]] const style::TextPalette &serviceTextPalette() const {
- return _serviceTextPalette;
- }
- [[nodiscard]] const style::TextPalette &priceTagTextPalette() const {
- return _priceTagTextPalette;
- }
- [[nodiscard]] const style::icon &historyRepliesInvertedIcon() const {
- return _historyRepliesInvertedIcon;
- }
- [[nodiscard]] const style::icon &historyViewsInvertedIcon() const {
- return _historyViewsInvertedIcon;
- }
- [[nodiscard]] const style::icon &historyViewsSendingIcon() const {
- return _historyViewsSendingIcon;
- }
- [[nodiscard]] const style::icon &historyViewsSendingInvertedIcon() const {
- return _historyViewsSendingInvertedIcon;
- }
- [[nodiscard]] const style::icon &historyPinInvertedIcon() const {
- return _historyPinInvertedIcon;
- }
- [[nodiscard]] const style::icon &historySendingIcon() const {
- return _historySendingIcon;
- }
- [[nodiscard]] const style::icon &historySendingInvertedIcon() const {
- return _historySendingInvertedIcon;
- }
- [[nodiscard]] const style::icon &historySentInvertedIcon() const {
- return _historySentInvertedIcon;
- }
- [[nodiscard]] const style::icon &historyReceivedInvertedIcon() const {
- return _historyReceivedInvertedIcon;
- }
- [[nodiscard]] const style::icon &msgBotKbUrlIcon() const {
- return _msgBotKbUrlIcon;
- }
- [[nodiscard]] const style::icon &msgBotKbPaymentIcon() const {
- return _msgBotKbPaymentIcon;
- }
- [[nodiscard]] const style::icon &msgBotKbSwitchPmIcon() const {
- return _msgBotKbSwitchPmIcon;
- }
- [[nodiscard]] const style::icon &msgBotKbWebviewIcon() const {
- return _msgBotKbWebviewIcon;
- }
- [[nodiscard]] const style::icon &msgBotKbCopyIcon() const {
- return _msgBotKbCopyIcon;
- }
- [[nodiscard]] const style::icon &historyFastCommentsIcon() const {
- return _historyFastCommentsIcon;
- }
- [[nodiscard]] const style::icon &historyFastShareIcon() const {
- return _historyFastShareIcon;
- }
- [[nodiscard]] const style::icon &historyFastTranscribeIcon() const {
- return _historyFastTranscribeIcon;
- }
- [[nodiscard]] const style::icon &historyFastTranscribeLock() const {
- return _historyFastTranscribeLock;
- }
- [[nodiscard]] const style::icon &historyGoToOriginalIcon() const {
- return _historyGoToOriginalIcon;
- }
- [[nodiscard]] const style::icon &historyFastCloseIcon() const {
- return _historyFastCloseIcon;
- }
- [[nodiscard]] const style::icon &historyFastMoreIcon() const {
- return _historyFastMoreIcon;
- }
- [[nodiscard]] const style::icon &historyMapPoint() const {
- return _historyMapPoint;
- }
- [[nodiscard]] const style::icon &historyMapPointInner() const {
- return _historyMapPointInner;
- }
- [[nodiscard]] const style::icon &youtubeIcon() const {
- return _youtubeIcon;
- }
- [[nodiscard]] const style::icon &videoIcon() const {
- return _videoIcon;
- }
- [[nodiscard]] const style::icon &historyPollChoiceRight() const {
- return _historyPollChoiceRight;
- }
- [[nodiscard]] const style::icon &historyPollChoiceWrong() const {
- return _historyPollChoiceWrong;
- }
- private:
- using ColoredQuotePaintCaches = std::array<
- std::unique_ptr<Text::QuotePaintCache>,
- kColorIndexCount * 2>;
- struct ColoredPalette {
- std::optional<style::owned_color> linkFg;
- style::TextPalette data;
- };
- void assignPalette(not_null<const style::palette*> palette);
- void clearColorIndexCaches();
- void updateDarkValue();
- [[nodiscard]] not_null<Text::QuotePaintCache*> coloredCache(
- ColoredQuotePaintCaches &caches,
- bool selected,
- uint8 colorIndex) const;
- void make(style::color &my, const style::color &original) const;
- void make(style::icon &my, const style::icon &original) const;
- void make(
- style::TextPalette &my,
- const style::TextPalette &original) const;
- void make(
- style::TwoIconButton &my,
- const style::TwoIconButton &original) const;
- void make(
- style::ScrollArea &my,
- const style::ScrollArea &original) const;
- [[nodiscard]] MessageStyle &messageStyleRaw(
- bool outbg,
- bool selected) const;
- [[nodiscard]] MessageStyle &messageIn();
- [[nodiscard]] MessageStyle &messageInSelected();
- [[nodiscard]] MessageStyle &messageOut();
- [[nodiscard]] MessageStyle &messageOutSelected();
- [[nodiscard]] MessageImageStyle &imageStyleRaw(bool selected) const;
- [[nodiscard]] MessageImageStyle &image();
- [[nodiscard]] MessageImageStyle &imageSelected();
- template <typename Type>
- void make(
- Type MessageStyle::*my,
- const Type &originalIn,
- const Type &originalInSelected,
- const Type &originalOut,
- const Type &originalOutSelected);
- template <typename Type>
- void make(
- Type MessageImageStyle::*my,
- const Type &original,
- const Type &originalSelected);
- mutable CornersPixmaps _serviceBgCornersNormal;
- mutable CornersPixmaps _serviceBgCornersInverted;
- mutable std::array<MessageStyle, 4> _messageStyles;
- mutable std::array<MessageImageStyle, 2> _imageStyles;
- mutable CornersPixmaps _msgBotKbOverBgAddCornersSmall;
- mutable CornersPixmaps _msgBotKbOverBgAddCornersLarge;
- mutable CornersPixmaps _msgSelectOverlayCorners[
- int(CachedCornerRadius::kCount)];
- mutable std::vector<Text::SpecialColor> _highlightColors;
- mutable std::array<
- std::unique_ptr<Text::QuotePaintCache>,
- 2> _serviceQuoteCache;
- mutable std::array<
- std::unique_ptr<Text::QuotePaintCache>,
- 2> _serviceReplyCache;
- mutable std::array<
- std::optional<ColorIndexValues>,
- 2 * kColorIndexCount> _coloredValues;
- mutable ColoredQuotePaintCaches _coloredQuoteCaches;
- mutable ColoredQuotePaintCaches _coloredReplyCaches;
- mutable std::array<
- ColoredPalette,
- 2 * kColorIndexCount> _coloredTextPalettes;
- mutable base::flat_map<uint64, BackgroundEmojiData> _backgroundEmojis;
- style::TextPalette _historyPsaForwardPalette;
- style::TextPalette _imgReplyTextPalette;
- style::TextPalette _serviceTextPalette;
- style::TextPalette _priceTagTextPalette;
- style::icon _historyRepliesInvertedIcon = { Qt::Uninitialized };
- style::icon _historyViewsInvertedIcon = { Qt::Uninitialized };
- style::icon _historyViewsSendingIcon = { Qt::Uninitialized };
- style::icon _historyViewsSendingInvertedIcon = { Qt::Uninitialized };
- style::icon _historyPinInvertedIcon = { Qt::Uninitialized };
- style::icon _historySendingIcon = { Qt::Uninitialized };
- style::icon _historySendingInvertedIcon = { Qt::Uninitialized };
- style::icon _historySentInvertedIcon = { Qt::Uninitialized };
- style::icon _historyReceivedInvertedIcon = { Qt::Uninitialized };
- style::icon _msgBotKbUrlIcon = { Qt::Uninitialized };
- style::icon _msgBotKbPaymentIcon = { Qt::Uninitialized };
- style::icon _msgBotKbSwitchPmIcon = { Qt::Uninitialized };
- style::icon _msgBotKbWebviewIcon = { Qt::Uninitialized };
- style::icon _msgBotKbCopyIcon = { Qt::Uninitialized };
- style::icon _historyFastCommentsIcon = { Qt::Uninitialized };
- style::icon _historyFastShareIcon = { Qt::Uninitialized };
- style::icon _historyFastMoreIcon = { Qt::Uninitialized };
- style::icon _historyFastTranscribeIcon = { Qt::Uninitialized };
- style::icon _historyFastTranscribeLock = { Qt::Uninitialized };
- style::icon _historyGoToOriginalIcon = { Qt::Uninitialized };
- style::icon _historyFastCloseIcon = { Qt::Uninitialized };
- style::icon _historyMapPoint = { Qt::Uninitialized };
- style::icon _historyMapPointInner = { Qt::Uninitialized };
- style::icon _youtubeIcon = { Qt::Uninitialized };
- style::icon _videoIcon = { Qt::Uninitialized };
- style::icon _historyPollChoiceRight = { Qt::Uninitialized };
- style::icon _historyPollChoiceWrong = { Qt::Uninitialized };
- ColorIndicesCompressed _colorIndices;
- bool _dark = false;
- rpl::event_stream<> _paletteChanged;
- rpl::lifetime _defaultPaletteChangeLifetime;
- rpl::lifetime _colorIndicesLifetime;
- };
- [[nodiscard]] uint8 DecideColorIndex(uint64 id);
- [[nodiscard]] uint8 ColorIndexToPaletteIndex(uint8 colorIndex);
- [[nodiscard]] QColor FromNameFg(
- not_null<const ChatStyle*> st,
- bool selected,
- uint8 colorIndex);
- [[nodiscard]] inline QColor FromNameFg(
- const ChatPaintContext &context,
- uint8 colorIndex) {
- return FromNameFg(context.st, context.selected(), colorIndex);
- }
- void FillComplexOverlayRect(
- QPainter &p,
- QRect rect,
- const style::color &color,
- const CornersPixmaps &corners);
- void FillComplexEllipse(
- QPainter &p,
- not_null<const ChatStyle*> st,
- QRect rect);
- } // namespace Ui
|