tdesktop/Telegram/SourceFiles/history/history_item.h

346 lines
8.2 KiB
C
Raw Normal View History

/*
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
2017-04-06 14:38:10 +00:00
#include "base/runtime_composer.h"
2017-08-31 16:28:58 +00:00
#include "base/flags.h"
2017-12-13 18:10:48 +00:00
#include "base/value_ordering.h"
#include "history/view/history_view_cursor_state.h"
enum class UnreadMentionType;
struct HistoryMessageReplyMarkup;
class ReplyKeyboard;
class HistoryMessage;
class HistoryMedia;
namespace base {
template <typename Enum>
class enum_mask;
} // namespace base
namespace Storage {
enum class SharedMediaType : char;
using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
} // namespace Storage
namespace Ui {
class RippleAnimation;
} // namespace Ui
namespace style {
struct BotKeyboardButton;
struct RippleAnimation;
} // namespace style
2018-01-09 17:08:31 +00:00
namespace Data {
struct MessagePosition;
class Media;
2018-01-09 17:08:31 +00:00
} // namespace Data
namespace Window {
class Controller;
} // namespace Window
namespace HistoryView {
enum class Context : char;
class ElementDelegate;
} // namespace HistoryView
class HistoryItem : public RuntimeComposer<HistoryItem> {
public:
static not_null<HistoryItem*> Create(
not_null<History*> history,
const MTPMessage &message);
virtual void dependencyItemRemoved(HistoryItem *dependency) {
}
virtual bool updateDependencyItem() {
return true;
}
virtual MsgId dependencyMsgId() const {
return 0;
}
virtual bool notificationReady() const {
return true;
}
virtual void applyGroupAdminChanges(
const base::flat_map<UserId, bool> &changes) {
}
UserData *viaBot() const;
UserData *getMessageBot() const;
bool isLogEntry() const {
return (id > ServerMaxMsgId);
}
void addLogEntryOriginal(
WebPageId localId,
const QString &label,
const TextWithEntities &content);
not_null<History*> history() const {
return _history;
}
not_null<PeerData*> from() const {
return _from;
}
HistoryView::Element *mainView() const {
return _mainView;
}
void setMainView(HistoryView::Element *view) {
_mainView = view;
}
void clearMainView();
void removeMainView();
void destroy();
bool out() const {
return _flags & MTPDmessage::Flag::f_out;
}
bool unread() const;
bool mentionsMe() const {
return _flags & MTPDmessage::Flag::f_mentioned;
}
2017-11-20 19:54:05 +00:00
bool isMediaUnread() const;
void markMediaRead();
// Zero result means this message is not self-destructing right now.
virtual TimeMs getSelfDestructIn(TimeMs now) {
return 0;
}
bool definesReplyKeyboard() const;
MTPDreplyKeyboardMarkup::Flags replyKeyboardFlags() const;
bool hasSwitchInlineButton() const {
return _flags & MTPDmessage_ClientFlag::f_has_switch_inline_button;
}
bool hasTextLinks() const {
return _flags & MTPDmessage_ClientFlag::f_has_text_links;
}
bool isGroupMigrate() const {
return _flags & MTPDmessage_ClientFlag::f_is_group_migrate;
}
bool hasViews() const {
return _flags & MTPDmessage::Flag::f_views;
}
bool isPost() const {
return _flags & MTPDmessage::Flag::f_post;
}
bool isSilent() const {
return _flags & MTPDmessage::Flag::f_silent;
}
virtual int viewsCount() const {
return hasViews() ? 1 : -1;
}
virtual bool needCheck() const;
virtual bool serviceMsg() const {
return false;
}
virtual void applyEdition(const MTPDmessage &message) {
}
virtual void applyEdition(const MTPDmessageService &message) {
}
virtual void updateSentMedia(const MTPMessageMedia *media) {
}
virtual void updateReplyMarkup(const MTPReplyMarkup *markup) {
}
virtual void addToUnreadMentions(UnreadMentionType type);
2017-12-08 18:27:28 +00:00
virtual void eraseFromUnreadMentions() {
}
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const = 0;
void indexAsNewItem();
virtual QString notificationHeader() const {
return QString();
}
virtual QString notificationText() const;
enum class DrawInDialog {
Normal,
WithoutSender,
};
// Returns text with link-start and link-end commands for service-color highlighting.
// Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text"
virtual QString inDialogsText(DrawInDialog way) const;
virtual QString inReplyText() const {
return notificationText();
}
virtual TextWithEntities originalText() const {
return { QString(), EntitiesInText() };
}
virtual void setViewsCount(int32 count) {
}
virtual void setRealId(MsgId newId);
void drawInDialog(
Painter &p,
const QRect &r,
bool active,
bool selected,
DrawInDialog way,
const HistoryItem *&cacheFor,
Text &cache) const;
bool emptyText() const {
return _text.isEmpty();
}
2017-11-21 13:23:56 +00:00
bool isPinned() const;
bool canPin() const;
virtual bool allowsForward() const;
virtual bool allowsEdit(const QDateTime &now) const;
bool canDelete() const;
bool canDeleteForEveryone(const QDateTime &cur) const;
2017-06-04 11:09:29 +00:00
bool suggestBanReport() const;
bool suggestDeleteAllReport() const;
bool hasDirectLink() const;
QString directLink() const;
MsgId id;
QDateTime date;
ChannelId channelId() const;
FullMsgId fullId() const {
return FullMsgId(channelId(), id);
}
2018-01-09 17:08:31 +00:00
Data::MessagePosition position() const;
Data::Media *media() const {
return _media.get();
}
virtual void setText(const TextWithEntities &textWithEntities) {
}
virtual bool textHasLinks() const {
return false;
}
virtual HistoryMessage *toHistoryMessage() { // dynamic_cast optimize
return nullptr;
}
virtual const HistoryMessage *toHistoryMessage() const { // dynamic_cast optimize
return nullptr;
}
MsgId replyToId() const;
not_null<PeerData*> author() const;
QDateTime dateOriginal() const;
not_null<PeerData*> senderOriginal() const;
not_null<PeerData*> fromOriginal() const;
QString authorOriginal() const;
MsgId idOriginal() const;
// count > 0 - creates the unread bar if necessary and
// sets unread messages count if bar is not freezed yet
// count <= 0 - destroys the unread bar
void setUnreadBarCount(int count);
void destroyUnreadBar();
// marks the unread bar as freezed so that unread
// messages count will not change for this bar
// when the new messages arrive in this chat history
void setUnreadBarFreezed();
int displayedDateHeight() const;
bool displayDate() const;
bool isInOneDayWithPrevious() const {
return !isEmpty() && !displayDate();
}
bool isEmpty() const;
2017-12-13 18:10:48 +00:00
MessageGroupId groupId() const;
void audioTrackUpdated();
HistoryItem *previousItem() const;
HistoryItem *nextItem() const;
2017-12-19 22:58:17 +00:00
virtual std::unique_ptr<HistoryView::Element> createView(
not_null<HistoryView::ElementDelegate*> delegate) = 0;
virtual ~HistoryItem();
protected:
HistoryItem(
not_null<History*> history,
MsgId id,
MTPDmessage::Flags flags,
QDateTime date,
UserId from);
// To completely create history item we need to call
// a virtual method, it can not be done from constructor.
virtual void finishCreate();
virtual void markMediaAsReadHook() {
}
void finishEdition(int oldKeyboardTop);
void finishEditionToEmpty();
const not_null<History*> _history;
not_null<PeerData*> _from;
MTPDmessage::Flags _flags = 0;
const HistoryMessageReplyMarkup *inlineReplyMarkup() const {
return const_cast<HistoryItem*>(this)->inlineReplyMarkup();
}
const ReplyKeyboard *inlineReplyKeyboard() const {
return const_cast<HistoryItem*>(this)->inlineReplyKeyboard();
}
HistoryMessageReplyMarkup *inlineReplyMarkup();
ReplyKeyboard *inlineReplyKeyboard();
void invalidateChatsListEntry();
void setGroupId(MessageGroupId groupId);
Text _text = { int(st::msgMinWidth) };
int _textWidth = -1;
int _textHeight = 0;
std::unique_ptr<Data::Media> _media;
private:
HistoryView::Element *_mainView = nullptr;
friend class HistoryView::Element;
MessageGroupId _groupId = MessageGroupId::None;
};
// make all the constructors in HistoryItem children protected
// and wrapped with a static create() call with the same args
// so that history item can not be created directly, without
// calling a virtual finishCreate() method
template <typename T>
class HistoryItemInstantiated {
public:
template <typename ...Args>
static not_null<T*> _create(Args &&... args) {
auto result = new T(std::forward<Args>(args)...);
result->finishCreate();
return result;
}
2017-04-27 21:17:00 +00:00
};
ClickHandlerPtr goToMessageClickHandler(
not_null<PeerData*> peer,
MsgId msgId);
ClickHandlerPtr goToMessageClickHandler(not_null<HistoryItem*> item);