2016-09-27 14:20:49 +00:00
/*
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 - 2016 John Preston , https : //desktop.telegram.org
*/
# pragma once
void historyInitMessages ( ) ;
class HistoryMessage : public HistoryItem , private HistoryItemInstantiated < HistoryMessage > {
public :
static HistoryMessage * create ( History * history , const MTPDmessage & msg ) {
return _create ( history , msg ) ;
}
static HistoryMessage * create ( History * history , MsgId msgId , MTPDmessage : : Flags flags , QDateTime date , int32 from , HistoryMessage * fwd ) {
return _create ( history , msgId , flags , date , from , fwd ) ;
}
static HistoryMessage * create ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , const TextWithEntities & textWithEntities ) {
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , textWithEntities ) ;
}
static HistoryMessage * create ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , DocumentData * doc , const QString & caption , const MTPReplyMarkup & markup ) {
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , doc , caption , markup ) ;
}
static HistoryMessage * create ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , PhotoData * photo , const QString & caption , const MTPReplyMarkup & markup ) {
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , photo , caption , markup ) ;
}
2016-09-28 16:23:25 +00:00
static HistoryMessage * create ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , GameData * game , const MTPReplyMarkup & markup ) {
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , game , markup ) ;
}
2016-09-27 14:20:49 +00:00
void initTime ( ) ;
2016-09-28 11:38:35 +00:00
void initMedia ( const MTPMessageMedia * media ) ;
2016-09-27 14:20:49 +00:00
void initMediaFromDocument ( DocumentData * doc , const QString & caption ) ;
void fromNameUpdated ( int32 width ) const ;
int32 plainMaxWidth ( ) const ;
void countPositionAndSize ( int32 & left , int32 & width ) const ;
bool drawBubble ( ) const {
return _media ? ( ! emptyText ( ) | | _media - > needsBubble ( ) ) : ! isEmpty ( ) ;
}
bool hasBubble ( ) const override {
return drawBubble ( ) ;
}
bool displayFromName ( ) const {
if ( ! hasFromName ( ) ) return false ;
if ( isAttachedToPrevious ( ) ) return false ;
return ( ! emptyText ( ) | | ! _media | | ! _media - > isDisplayed ( ) | | Has < HistoryMessageReply > ( ) | | Has < HistoryMessageForwarded > ( ) | | viaBot ( ) | | ! _media - > hideFromName ( ) ) ;
}
2016-10-07 07:58:34 +00:00
bool displayEditedBadge ( bool hasViaBotOrInlineMarkup ) const ;
2016-09-27 14:20:49 +00:00
bool uploading ( ) const {
return _media & & _media - > uploading ( ) ;
}
void drawInfo ( Painter & p , int32 right , int32 bottom , int32 width , bool selected , InfoDisplayType type ) const override ;
void setViewsCount ( int32 count ) override ;
void setId ( MsgId newId ) override ;
2016-12-01 19:20:33 +00:00
void draw ( Painter & p , const QRect & r , TextSelection selection , TimeMs ms ) const override ;
2016-09-27 14:20:49 +00:00
void dependencyItemRemoved ( HistoryItem * dependency ) override ;
bool hasPoint ( int x , int y ) const override ;
bool pointInTime ( int32 right , int32 bottom , int x , int y , InfoDisplayType type ) const override ;
HistoryTextState getState ( int x , int y , HistoryStateRequest request ) const override ;
TextSelection adjustSelection ( TextSelection selection , TextSelectType type ) const override ;
// ClickHandlerHost interface
void clickHandlerActiveChanged ( const ClickHandlerPtr & p , bool active ) override {
if ( _media ) _media - > clickHandlerActiveChanged ( p , active ) ;
HistoryItem : : clickHandlerActiveChanged ( p , active ) ;
}
void clickHandlerPressedChanged ( const ClickHandlerPtr & p , bool pressed ) override {
if ( _media ) _media - > clickHandlerPressedChanged ( p , pressed ) ;
HistoryItem : : clickHandlerPressedChanged ( p , pressed ) ;
}
QString notificationHeader ( ) const override ;
void applyEdition ( const MTPDmessage & message ) override ;
void applyEdition ( const MTPDmessageService & message ) override ;
void updateMedia ( const MTPMessageMedia * media ) override ;
2016-10-20 15:26:55 +00:00
void updateReplyMarkup ( const MTPReplyMarkup * markup ) override {
setReplyMarkup ( markup ) ;
}
2016-09-27 14:20:49 +00:00
int32 addToOverview ( AddToOverviewMethod method ) override ;
void eraseFromOverview ( ) override ;
TextWithEntities selectedText ( TextSelection selection ) const override ;
void setText ( const TextWithEntities & textWithEntities ) override ;
TextWithEntities originalText ( ) const override ;
bool textHasLinks ( ) const override ;
2016-09-30 12:52:03 +00:00
int infoWidth ( ) const override ;
int timeLeft ( ) const override ;
int timeWidth ( ) const override {
2016-09-27 14:20:49 +00:00
return _timeWidth ;
}
2016-09-30 12:52:03 +00:00
int viewsCount ( ) const override {
if ( auto views = Get < HistoryMessageViews > ( ) ) {
2016-09-27 14:20:49 +00:00
return views - > _views ;
}
return HistoryItem : : viewsCount ( ) ;
}
bool updateDependencyItem ( ) override {
if ( auto reply = Get < HistoryMessageReply > ( ) ) {
return reply - > updateData ( this , true ) ;
}
return true ;
}
MsgId dependencyMsgId ( ) const override {
return replyToId ( ) ;
}
HistoryMessage * toHistoryMessage ( ) override { // dynamic_cast optimize
return this ;
}
const HistoryMessage * toHistoryMessage ( ) const override { // dynamic_cast optimize
return this ;
}
// hasFromPhoto() returns true even if we don't display the photo
// but we need to skip a place at the left side for this photo
bool displayFromPhoto ( ) const ;
bool hasFromPhoto ( ) const ;
~ HistoryMessage ( ) ;
private :
HistoryMessage ( History * history , const MTPDmessage & msg ) ;
HistoryMessage ( History * history , MsgId msgId , MTPDmessage : : Flags flags , QDateTime date , int32 from , HistoryMessage * fwd ) ; // local forwarded
HistoryMessage ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , const TextWithEntities & textWithEntities ) ; // local message
HistoryMessage ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , DocumentData * doc , const QString & caption , const MTPReplyMarkup & markup ) ; // local document
HistoryMessage ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , PhotoData * photo , const QString & caption , const MTPReplyMarkup & markup ) ; // local photo
2016-09-28 16:23:25 +00:00
HistoryMessage ( History * history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , GameData * game , const MTPReplyMarkup & markup ) ; // local game
2016-09-27 14:20:49 +00:00
friend class HistoryItemInstantiated < HistoryMessage > ;
void setEmptyText ( ) ;
void initDimensions ( ) override ;
int resizeGetHeight_ ( int width ) override ;
int performResizeGetHeight ( int width ) ;
void applyEditionToEmpty ( ) ;
bool displayForwardedFrom ( ) const {
2016-09-28 10:15:03 +00:00
if ( auto fwd = Get < HistoryMessageForwarded > ( ) ) {
2016-09-27 14:20:49 +00:00
return Has < HistoryMessageVia > ( ) | | ! _media | | ! _media - > isDisplayed ( ) | | fwd - > _authorOriginal - > isChannel ( ) | | ! _media - > hideForwardedFrom ( ) ;
}
return false ;
}
void paintFromName ( Painter & p , QRect & trect , bool selected ) const ;
void paintForwardedInfo ( Painter & p , QRect & trect , bool selected ) const ;
void paintReplyInfo ( Painter & p , QRect & trect , bool selected ) const ;
// this method draws "via @bot" if it is not painted in forwarded info or in from name
void paintViaBotIdInfo ( Painter & p , QRect & trect , bool selected ) const ;
void paintText ( Painter & p , QRect & trect , TextSelection selection ) const ;
2016-09-28 10:15:03 +00:00
bool getStateFromName ( int x , int y , QRect & trect , HistoryTextState * outResult ) const ;
bool getStateForwardedInfo ( int x , int y , QRect & trect , HistoryTextState * outResult , const HistoryStateRequest & request ) const ;
bool getStateReplyInfo ( int x , int y , QRect & trect , HistoryTextState * outResult ) const ;
bool getStateViaBotIdInfo ( int x , int y , QRect & trect , HistoryTextState * outResult ) const ;
bool getStateText ( int x , int y , QRect & trect , HistoryTextState * outResult , const HistoryStateRequest & request ) const ;
2016-09-27 14:20:49 +00:00
void setMedia ( const MTPMessageMedia * media ) ;
void setReplyMarkup ( const MTPReplyMarkup * markup ) ;
QString _timeText ;
int _timeWidth = 0 ;
struct CreateConfig {
MsgId replyTo = 0 ;
UserId viaBotId = 0 ;
int viewsCount = - 1 ;
PeerId authorIdOriginal = 0 ;
PeerId fromIdOriginal = 0 ;
MsgId originalId = 0 ;
QDateTime editDate ;
2016-10-07 07:58:34 +00:00
// For messages created from MTP structs.
const MTPReplyMarkup * mtpMarkup = nullptr ;
// For messages created from existing messages (forwarded).
const HistoryMessageReplyMarkup * inlineMarkup = nullptr ;
2016-09-27 14:20:49 +00:00
} ;
void createComponentsHelper ( MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , const MTPReplyMarkup & markup ) ;
void createComponents ( const CreateConfig & config ) ;
class KeyboardStyle : public ReplyKeyboard : : Style {
public :
using ReplyKeyboard : : Style : : Style ;
2016-11-16 16:04:25 +00:00
int buttonRadius ( ) const override ;
2016-09-27 14:20:49 +00:00
void startPaint ( Painter & p ) const override ;
style : : font textFont ( ) const override ;
void repaint ( const HistoryItem * item ) const override ;
protected :
2016-11-16 16:04:25 +00:00
void paintButtonBg ( Painter & p , const QRect & rect , float64 howMuchOver ) const override ;
2016-10-26 12:24:21 +00:00
void paintButtonIcon ( Painter & p , const QRect & rect , int outerWidth , HistoryMessageReplyMarkup : : Button : : Type type ) const override ;
2016-09-27 14:20:49 +00:00
void paintButtonLoading ( Painter & p , const QRect & rect ) const override ;
int minButtonWidth ( HistoryMessageReplyMarkup : : Button : : Type type ) const override ;
} ;
2016-09-28 10:15:03 +00:00
void updateMediaInBubbleState ( ) ;
2016-09-27 14:20:49 +00:00
} ;
inline MTPDmessage : : Flags newMessageFlags ( PeerData * p ) {
MTPDmessage : : Flags result = 0 ;
if ( ! p - > isSelf ( ) ) {
result | = MTPDmessage : : Flag : : f_out ;
//if (p->isChat() || (p->isUser() && !p->asUser()->botInfo)) {
// result |= MTPDmessage::Flag::f_unread;
//}
}
return result ;
}
struct HistoryServiceDependentData {
MsgId msgId = 0 ;
HistoryItem * msg = nullptr ;
ClickHandlerPtr lnk ;
} ;
2016-09-29 11:37:16 +00:00
struct HistoryServicePinned : public RuntimeComponent < HistoryServicePinned > , public HistoryServiceDependentData {
2016-09-27 14:20:49 +00:00
} ;
2016-09-29 11:37:16 +00:00
struct HistoryServiceGameScore : public RuntimeComponent < HistoryServiceGameScore > , public HistoryServiceDependentData {
2016-09-27 14:20:49 +00:00
int score = 0 ;
} ;
namespace HistoryLayout {
class ServiceMessagePainter ;
} // namespace HistoryLayout
class HistoryService : public HistoryItem , private HistoryItemInstantiated < HistoryService > {
public :
static HistoryService * create ( History * history , const MTPDmessageService & msg ) {
return _create ( history , msg ) ;
}
static HistoryService * create ( History * history , MsgId msgId , QDateTime date , const QString & msg , MTPDmessage : : Flags flags = 0 , int32 from = 0 ) {
return _create ( history , msgId , date , msg , flags , from ) ;
}
bool updateDependencyItem ( ) override ;
MsgId dependencyMsgId ( ) const override {
if ( auto dependent = GetDependentData ( ) ) {
return dependent - > msgId ;
}
return 0 ;
}
bool notificationReady ( ) const override {
if ( auto dependent = GetDependentData ( ) ) {
return ( dependent - > msg | | ! dependent - > msgId ) ;
}
return true ;
}
void countPositionAndSize ( int32 & left , int32 & width ) const ;
2016-12-01 19:20:33 +00:00
void draw ( Painter & p , const QRect & r , TextSelection selection , TimeMs ms ) const override ;
2016-09-27 14:20:49 +00:00
bool hasPoint ( int x , int y ) const override ;
HistoryTextState getState ( int x , int y , HistoryStateRequest request ) const override ;
TextSelection adjustSelection ( TextSelection selection , TextSelectType type ) const override {
return _text . adjustSelection ( selection , type ) ;
}
void clickHandlerActiveChanged ( const ClickHandlerPtr & p , bool active ) override {
if ( _media ) _media - > clickHandlerActiveChanged ( p , active ) ;
HistoryItem : : clickHandlerActiveChanged ( p , active ) ;
}
void clickHandlerPressedChanged ( const ClickHandlerPtr & p , bool pressed ) override {
if ( _media ) _media - > clickHandlerPressedChanged ( p , pressed ) ;
HistoryItem : : clickHandlerPressedChanged ( p , pressed ) ;
}
void applyEdition ( const MTPDmessageService & message ) override ;
int32 addToOverview ( AddToOverviewMethod method ) override ;
void eraseFromOverview ( ) override ;
bool needCheck ( ) const override {
return false ;
}
bool serviceMsg ( ) const override {
return true ;
}
TextWithEntities selectedText ( TextSelection selection ) const override ;
QString inDialogsText ( ) const override ;
QString inReplyText ( ) const override ;
~ HistoryService ( ) ;
protected :
friend class HistoryLayout : : ServiceMessagePainter ;
HistoryService ( History * history , const MTPDmessageService & msg ) ;
HistoryService ( History * history , MsgId msgId , QDateTime date , const QString & msg , MTPDmessage : : Flags flags = 0 , int32 from = 0 ) ;
friend class HistoryItemInstantiated < HistoryService > ;
void initDimensions ( ) override ;
int resizeGetHeight_ ( int width ) override ;
using Links = QList < ClickHandlerPtr > ;
void setServiceText ( const QString & text , const Links & links ) ;
void removeMedia ( ) ;
private :
HistoryServiceDependentData * GetDependentData ( ) {
if ( auto pinned = Get < HistoryServicePinned > ( ) ) {
return pinned ;
} else if ( auto gamescore = Get < HistoryServiceGameScore > ( ) ) {
return gamescore ;
}
return nullptr ;
}
const HistoryServiceDependentData * GetDependentData ( ) const {
return const_cast < HistoryService * > ( this ) - > GetDependentData ( ) ;
}
bool updateDependent ( bool force = false ) ;
bool updateDependentText ( ) ;
void clearDependency ( ) ;
void createFromMtp ( const MTPDmessageService & message ) ;
void setMessageByAction ( const MTPmessageAction & action ) ;
bool preparePinnedText ( const QString & from , QString * outText , Links * outLinks ) ;
bool prepareGameScoreText ( const QString & from , QString * outText , Links * outLinks ) ;
} ;
class HistoryJoined : public HistoryService , private HistoryItemInstantiated < HistoryJoined > {
public :
static HistoryJoined * create ( History * history , const QDateTime & date , UserData * from , MTPDmessage : : Flags flags ) {
return _create ( history , date , from , flags ) ;
}
HistoryItemType type ( ) const {
return HistoryItemJoined ;
}
protected :
HistoryJoined ( History * history , const QDateTime & date , UserData * from , MTPDmessage : : Flags flags ) ;
using HistoryItemInstantiated < HistoryJoined > : : _create ;
friend class HistoryItemInstantiated < HistoryJoined > ;
} ;