/* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once #include "base/runtime_composer.h" namespace Ui { class RippleAnimation; } // namespace Ui namespace style { struct BotKeyboardButton; struct RippleAnimation; } // namespace style class HistoryElement { public: HistoryElement() = default; HistoryElement(const HistoryElement &other) = delete; HistoryElement &operator=(const HistoryElement &other) = delete; int maxWidth() const { return _maxw; } int minHeight() const { return _minh; } int height() const { return _height; } virtual ~HistoryElement() = default; protected: mutable int _maxw = 0; mutable int _minh = 0; mutable int _height = 0; }; class HistoryMessage; enum HistoryCursorState { HistoryDefaultCursorState, HistoryInTextCursorState, HistoryInDateCursorState, HistoryInForwardedCursorState, }; struct HistoryTextState { HistoryTextState() = default; HistoryTextState(const Text::StateResult &state) : cursor(state.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState) , link(state.link) , afterSymbol(state.afterSymbol) , symbol(state.symbol) { } HistoryTextState &operator=(const Text::StateResult &state) { cursor = state.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState; link = state.link; afterSymbol = state.afterSymbol; symbol = state.symbol; return *this; } HistoryCursorState cursor = HistoryDefaultCursorState; ClickHandlerPtr link; bool afterSymbol = false; uint16 symbol = 0; }; struct HistoryStateRequest { Text::StateRequest::Flags flags = Text::StateRequest::Flag::LookupLink; Text::StateRequest forText() const { Text::StateRequest result; result.flags = flags; return result; } }; enum InfoDisplayType { InfoDisplayDefault, InfoDisplayOverImage, InfoDisplayOverBackground, }; struct HistoryMessageVia : public RuntimeComponent { void create(int32 userId); void resize(int32 availw) const; UserData *_bot = nullptr; mutable QString _text; mutable int _width = 0; mutable int _maxWidth = 0; ClickHandlerPtr _lnk; }; struct HistoryMessageViews : public RuntimeComponent { QString _viewsText; int _views = 0; int _viewsWidth = 0; }; struct HistoryMessageSigned : public RuntimeComponent { void create(const QString &author, const QString &date); int maxWidth() const; QString _author; Text _signature; }; struct HistoryMessageEdited : public RuntimeComponent { void create(const QDateTime &editDate, const QString &date); int maxWidth() const; QDateTime _editDate; Text _edited; }; struct HistoryMessageForwarded : public RuntimeComponent { void create(const HistoryMessageVia *via) const; QDateTime _originalDate; PeerData *_originalSender = nullptr; QString _originalAuthor; MsgId _originalId = 0; mutable Text _text = { 1 }; }; struct HistoryMessageReply : public RuntimeComponent { HistoryMessageReply &operator=(HistoryMessageReply &&other) { replyToMsgId = other.replyToMsgId; std::swap(replyToMsg, other.replyToMsg); replyToLnk = std::move(other.replyToLnk); replyToName = std::move(other.replyToName); replyToText = std::move(other.replyToText); replyToVersion = other.replyToVersion; _maxReplyWidth = other._maxReplyWidth; _replyToVia = std::move(other._replyToVia); return *this; } ~HistoryMessageReply() { // clearData() should be called by holder Expects(replyToMsg == nullptr); Expects(_replyToVia == nullptr); } bool updateData(HistoryMessage *holder, bool force = false); void clearData(HistoryMessage *holder); // must be called before destructor bool isNameUpdated() const; void updateName() const; void resize(int width) const; void itemRemoved(HistoryMessage *holder, HistoryItem *removed); enum PaintFlag { PaintInBubble = 0x01, PaintSelected = 0x02, }; Q_DECLARE_FLAGS(PaintFlags, PaintFlag); void paint(Painter &p, const HistoryItem *holder, int x, int y, int w, PaintFlags flags) const; MsgId replyToId() const { return replyToMsgId; } int replyToWidth() const { return _maxReplyWidth; } ClickHandlerPtr replyToLink() const { return replyToLnk; } MsgId replyToMsgId = 0; HistoryItem *replyToMsg = nullptr; ClickHandlerPtr replyToLnk; mutable Text replyToName, replyToText; mutable int replyToVersion = 0; mutable int _maxReplyWidth = 0; std::unique_ptr _replyToVia; int toWidth = 0; }; Q_DECLARE_OPERATORS_FOR_FLAGS(HistoryMessageReply::PaintFlags); class ReplyKeyboard; struct HistoryMessageReplyMarkup : public RuntimeComponent { HistoryMessageReplyMarkup() = default; HistoryMessageReplyMarkup(MTPDreplyKeyboardMarkup::Flags f) : flags(f) { } void create(const MTPReplyMarkup &markup); void create(const HistoryMessageReplyMarkup &markup); struct Button { enum class Type { Default, Url, Callback, RequestPhone, RequestLocation, SwitchInline, SwitchInlineSame, Game, Buy, }; Type type; QString text; QByteArray data; mutable mtpRequestId requestId; }; using ButtonRow = QVector