2016-09-27 17:20:49 +03: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
2017-01-11 22:31:31 +04:00
Copyright ( c ) 2014 - 2017 John Preston , https : //desktop.telegram.org
2016-09-27 17:20:49 +03:00
*/
# pragma once
void historyInitMessages ( ) ;
class HistoryMessage : public HistoryItem , private HistoryItemInstantiated < HistoryMessage > {
public :
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , const MTPDmessage & msg ) {
2016-09-27 17:20:49 +03:00
return _create ( history , msg ) ;
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , const MTPDmessageService & msg ) {
2017-04-28 00:17:00 +03:00
return _create ( history , msg ) ;
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , QDateTime date , int32 from , HistoryMessage * fwd ) {
2016-09-27 17:20:49 +03:00
return _create ( history , msgId , flags , date , from , fwd ) ;
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , const TextWithEntities & textWithEntities ) {
2016-09-27 17:20:49 +03:00
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , textWithEntities ) ;
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , DocumentData * doc , const QString & caption , const MTPReplyMarkup & markup ) {
2016-09-27 17:20:49 +03:00
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , doc , caption , markup ) ;
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , PhotoData * photo , const QString & caption , const MTPReplyMarkup & markup ) {
2016-09-27 17:20:49 +03:00
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , photo , caption , markup ) ;
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryMessage * > create ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , GameData * game , const MTPReplyMarkup & markup ) {
2016-09-28 19:23:25 +03:00
return _create ( history , msgId , flags , replyTo , viaBotId , date , from , game , markup ) ;
}
2016-09-27 17:20:49 +03:00
void initTime ( ) ;
2016-09-28 14:38:35 +03:00
void initMedia ( const MTPMessageMedia * media ) ;
2016-09-27 17:20:49 +03:00
void initMediaFromDocument ( DocumentData * doc , const QString & caption ) ;
void fromNameUpdated ( int32 width ) const ;
int32 plainMaxWidth ( ) const ;
2017-06-21 11:53:14 +03:00
QRect countGeometry ( ) const ;
2016-09-27 17:20:49 +03:00
2017-06-20 22:48:53 +03:00
bool drawBubble ( ) const ;
2016-09-27 17:20:49 +03:00
bool hasBubble ( ) const override {
return drawBubble ( ) ;
}
bool displayFromName ( ) const {
if ( ! hasFromName ( ) ) return false ;
if ( isAttachedToPrevious ( ) ) return false ;
2017-02-09 17:34:19 +03:00
return true ;
2016-09-27 17:20:49 +03:00
}
2016-10-07 10:58:34 +03:00
bool displayEditedBadge ( bool hasViaBotOrInlineMarkup ) const ;
2016-09-27 17:20:49 +03: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 ;
2017-06-21 11:53:14 +03:00
void draw ( Painter & p , QRect clip , TextSelection selection , TimeMs ms ) const override ;
2016-09-27 17:20:49 +03: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 ;
2017-02-11 01:37:37 +03:00
void updatePressed ( int x , int y ) override ;
2016-09-27 17:20:49 +03:00
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 18:26:55 +03:00
void updateReplyMarkup ( const MTPReplyMarkup * markup ) override {
setReplyMarkup ( markup ) ;
}
2016-09-27 17:20:49 +03: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 15:52:03 +03:00
int infoWidth ( ) const override ;
int timeLeft ( ) const override ;
int timeWidth ( ) const override {
2016-09-27 17:20:49 +03:00
return _timeWidth ;
}
2016-09-30 15:52:03 +03:00
int viewsCount ( ) const override {
if ( auto views = Get < HistoryMessageViews > ( ) ) {
2016-09-27 17:20:49 +03: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 :
2017-06-21 11:53:14 +03:00
HistoryMessage ( gsl : : not_null < History * > history , const MTPDmessage & msg ) ;
HistoryMessage ( gsl : : not_null < History * > history , const MTPDmessageService & msg ) ;
HistoryMessage ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , QDateTime date , int32 from , HistoryMessage * fwd ) ; // local forwarded
HistoryMessage ( gsl : : not_null < History * > history , MsgId msgId , MTPDmessage : : Flags flags , MsgId replyTo , int32 viaBotId , QDateTime date , int32 from , const TextWithEntities & textWithEntities ) ; // local message
HistoryMessage ( gsl : : not_null < 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 ( gsl : : not_null < 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
HistoryMessage ( gsl : : not_null < 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 17:20:49 +03:00
friend class HistoryItemInstantiated < HistoryMessage > ;
void setEmptyText ( ) ;
2017-03-06 18:00:59 +03:00
// For an invoice button we replace the button text with a "Receipt" key.
// It should show the receipt for the payed invoice. Still let mobile apps do that.
void replaceBuyWithReceiptInMarkup ( ) ;
2016-09-27 17:20:49 +03:00
void initDimensions ( ) override ;
2017-06-21 11:53:14 +03:00
int resizeContentGetHeight ( ) override ;
int performResizeGetHeight ( ) ;
2016-09-27 17:20:49 +03:00
void applyEditionToEmpty ( ) ;
bool displayForwardedFrom ( ) const {
2017-04-30 15:44:17 +03:00
if ( auto forwarded = Get < HistoryMessageForwarded > ( ) ) {
return Has < HistoryMessageVia > ( )
| | ! _media
| | ! _media - > isDisplayed ( )
| | ! _media - > hideForwardedFrom ( )
| | forwarded - > _authorOriginal - > isChannel ( ) ;
2016-09-27 17:20:49 +03:00
}
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 13:15:03 +03: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 17:20:49 +03: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 ;
2017-06-21 01:05:38 +03:00
QDateTime originalDate ;
2016-09-27 17:20:49 +03:00
QDateTime editDate ;
2016-10-07 10:58:34 +03: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 17:20:49 +03: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 19:04:25 +03:00
int buttonRadius ( ) const override ;
2016-09-27 17:20:49 +03:00
void startPaint ( Painter & p ) const override ;
2016-12-23 16:21:01 +03:00
const style : : TextStyle & textStyle ( ) const override ;
2016-09-27 17:20:49 +03:00
void repaint ( const HistoryItem * item ) const override ;
protected :
2016-11-16 19:04:25 +03:00
void paintButtonBg ( Painter & p , const QRect & rect , float64 howMuchOver ) const override ;
2016-10-26 15:24:21 +03:00
void paintButtonIcon ( Painter & p , const QRect & rect , int outerWidth , HistoryMessageReplyMarkup : : Button : : Type type ) const override ;
2016-09-27 17:20:49 +03:00
void paintButtonLoading ( Painter & p , const QRect & rect ) const override ;
int minButtonWidth ( HistoryMessageReplyMarkup : : Button : : Type type ) const override ;
} ;
2016-09-28 13:15:03 +03:00
void updateMediaInBubbleState ( ) ;
2016-09-27 17:20:49 +03: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 14:37:16 +03:00
struct HistoryServicePinned : public RuntimeComponent < HistoryServicePinned > , public HistoryServiceDependentData {
2016-09-27 17:20:49 +03:00
} ;
2016-09-29 14:37:16 +03:00
struct HistoryServiceGameScore : public RuntimeComponent < HistoryServiceGameScore > , public HistoryServiceDependentData {
2016-09-27 17:20:49 +03:00
int score = 0 ;
} ;
2017-03-05 18:41:58 +03:00
struct HistoryServicePayment : public RuntimeComponent < HistoryServicePayment > , public HistoryServiceDependentData {
QString amount ;
} ;
2016-09-27 17:20:49 +03:00
namespace HistoryLayout {
class ServiceMessagePainter ;
} // namespace HistoryLayout
class HistoryService : public HistoryItem , private HistoryItemInstantiated < HistoryService > {
public :
2017-06-18 16:08:49 +03:00
struct PreparedText {
QString text ;
QList < ClickHandlerPtr > links ;
} ;
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryService * > create ( gsl : : not_null < History * > history , const MTPDmessageService & message ) {
2017-06-18 16:08:49 +03:00
return _create ( history , message ) ;
2016-09-27 17:20:49 +03:00
}
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryService * > create ( gsl : : not_null < History * > history , MsgId msgId , QDateTime date , const PreparedText & message , MTPDmessage : : Flags flags = 0 , UserId from = 0 , PhotoData * photo = nullptr ) {
2017-06-20 19:03:18 +03:00
return _create ( history , msgId , date , message , flags , from , photo ) ;
2016-09-27 17:20:49 +03:00
}
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 ;
}
2017-06-21 11:53:14 +03:00
QRect countGeometry ( ) const ;
2016-09-27 17:20:49 +03:00
2017-06-21 11:53:14 +03:00
void draw ( Painter & p , QRect clip , TextSelection selection , TimeMs ms ) const override ;
2016-09-27 17:20:49 +03: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 ;
2017-06-21 11:53:14 +03:00
HistoryService ( gsl : : not_null < History * > history , const MTPDmessageService & message ) ;
HistoryService ( gsl : : not_null < History * > history , MsgId msgId , QDateTime date , const PreparedText & message , MTPDmessage : : Flags flags = 0 , UserId from = 0 , PhotoData * photo = 0 ) ;
2016-09-27 17:20:49 +03:00
friend class HistoryItemInstantiated < HistoryService > ;
void initDimensions ( ) override ;
2017-06-21 11:53:14 +03:00
int resizeContentGetHeight ( ) override ;
2016-09-27 17:20:49 +03:00
2017-03-05 13:37:32 +03:00
void setServiceText ( const PreparedText & prepared ) ;
QString fromLinkText ( ) const {
return textcmdLink ( 1 , _from - > name ) ;
} ;
ClickHandlerPtr fromLink ( ) const {
return peerOpenClickHandler ( _from ) ;
} ;
2016-09-27 17:20:49 +03:00
void removeMedia ( ) ;
private :
HistoryServiceDependentData * GetDependentData ( ) {
if ( auto pinned = Get < HistoryServicePinned > ( ) ) {
return pinned ;
} else if ( auto gamescore = Get < HistoryServiceGameScore > ( ) ) {
return gamescore ;
2017-03-05 18:41:58 +03:00
} else if ( auto payment = Get < HistoryServicePayment > ( ) ) {
return payment ;
2016-09-27 17:20:49 +03:00
}
return nullptr ;
}
const HistoryServiceDependentData * GetDependentData ( ) const {
return const_cast < HistoryService * > ( this ) - > GetDependentData ( ) ;
}
bool updateDependent ( bool force = false ) ;
2017-03-05 13:37:32 +03:00
void updateDependentText ( ) ;
2016-09-27 17:20:49 +03:00
void clearDependency ( ) ;
void createFromMtp ( const MTPDmessageService & message ) ;
void setMessageByAction ( const MTPmessageAction & action ) ;
2017-03-05 13:37:32 +03:00
PreparedText preparePinnedText ( ) ;
PreparedText prepareGameScoreText ( ) ;
2017-03-05 18:41:58 +03:00
PreparedText preparePaymentSentText ( ) ;
2016-09-27 17:20:49 +03:00
} ;
class HistoryJoined : public HistoryService , private HistoryItemInstantiated < HistoryJoined > {
public :
2017-06-21 11:53:14 +03:00
static gsl : : not_null < HistoryJoined * > create ( gsl : : not_null < History * > history , const QDateTime & inviteDate , gsl : : not_null < UserData * > inviter , MTPDmessage : : Flags flags ) {
2017-06-18 16:08:49 +03:00
return _create ( history , inviteDate , inviter , flags ) ;
2016-09-27 17:20:49 +03:00
}
protected :
2017-06-18 16:08:49 +03:00
HistoryJoined ( gsl : : not_null < History * > history , const QDateTime & inviteDate , gsl : : not_null < UserData * > inviter , MTPDmessage : : Flags flags ) ;
2016-09-27 17:20:49 +03:00
using HistoryItemInstantiated < HistoryJoined > : : _create ;
friend class HistoryItemInstantiated < HistoryJoined > ;
2017-06-18 16:08:49 +03:00
private :
static PreparedText GenerateText ( gsl : : not_null < History * > history , gsl : : not_null < UserData * > inviter ) ;
2016-09-27 17:20:49 +03:00
} ;