Pay button and messageMediaInvoice supported.

New button type keyboardButtonBuy just shows a box with information.
WebDocument photo type is not supported yet, 'photo' is ignored.
Also HistoryMediaPtr is now implemented as a std::unique_ptr wrapper.
This commit is contained in:
John Preston 2017-03-05 16:39:10 +03:00
parent 0cc7cdd212
commit 2019c24e08
11 changed files with 584 additions and 110 deletions

View File

@ -182,6 +182,16 @@ inFwdTextPaletteSelected: TextPalette(defaultTextPalette) {
outFwdTextPaletteSelected: TextPalette(defaultTextPalette) { outFwdTextPaletteSelected: TextPalette(defaultTextPalette) {
linkFg: msgOutServiceFgSelected; linkFg: msgOutServiceFgSelected;
} }
inSemiboldPalette: TextPalette(inTextPalette) {
linkFg: msgInServiceFg;
selectFg: msgInServiceFgSelected;
selectLinkFg: msgInServiceFgSelected;
}
outSemiboldPalette: TextPalette(outTextPalette) {
linkFg: msgOutServiceFg;
selectFg: msgOutServiceFgSelected;
selectLinkFg: msgOutServiceFgSelected;
}
mediaPadding: margins(0px, 0px, 0px, 0px); mediaPadding: margins(0px, 0px, 0px, 0px);
mediaCaptionSkip: 5px; mediaCaptionSkip: 5px;

View File

@ -1102,6 +1102,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_theme_editor_title" = "Edit color palette"; "lng_theme_editor_title" = "Edit color palette";
"lng_theme_editor_export_button" = "Export theme"; "lng_theme_editor_export_button" = "Export theme";
"lng_payments_not_supported" = "Sorry, Telegram Desktop doesn't support payments yet. Please use one of our mobile apps to do this.";
// Not used // Not used
"lng_topbar_info" = "Info"; "lng_topbar_info" = "Info";

View File

@ -89,6 +89,10 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
} }
} break; } break;
case ButtonType::Buy: {
Ui::show(Box<InformBox>(lang(lng_payments_not_supported)));
} break;
case ButtonType::Url: { case ButtonType::Url: {
auto url = QString::fromUtf8(button->data); auto url = QString::fromUtf8(button->data);
auto skipConfirmation = false; auto skipConfirmation = false;

View File

@ -813,6 +813,8 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
default: badMedia = MediaCheckResult::Unsupported; break; default: badMedia = MediaCheckResult::Unsupported; break;
} }
break; break;
case mtpc_messageMediaInvoice:
break;
case mtpc_messageMediaUnsupported: case mtpc_messageMediaUnsupported:
default: badMedia = MediaCheckResult::Unsupported; break; default: badMedia = MediaCheckResult::Unsupported; break;
} }

View File

@ -118,6 +118,7 @@ enum HistoryMediaType {
MediaTypeMusicFile, MediaTypeMusicFile,
MediaTypeVoiceFile, MediaTypeVoiceFile,
MediaTypeGame, MediaTypeGame,
MediaTypeInvoice,
MediaTypeCount MediaTypeCount
}; };

View File

@ -438,6 +438,10 @@ void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardBu
auto &buttonData = button.c_keyboardButtonGame(); auto &buttonData = button.c_keyboardButtonGame();
buttonRow.push_back({ Button::Type::Game, qs(buttonData.vtext), QByteArray(), 0 }); buttonRow.push_back({ Button::Type::Game, qs(buttonData.vtext), QByteArray(), 0 });
} break; } break;
case mtpc_keyboardButtonBuy: {
auto &buttonData = button.c_keyboardButtonBuy();
buttonRow.push_back({ Button::Type::Buy, qs(buttonData.vtext), QByteArray(), 0 });
}
} }
} }
if (!buttonRow.isEmpty()) rows.push_back(buttonRow); if (!buttonRow.isEmpty()) rows.push_back(buttonRow);
@ -537,15 +541,21 @@ void HistoryMessageDate::paint(Painter &p, int y, int w) const {
HistoryLayout::ServiceMessagePainter::paintDate(p, _text, _width, y, w); HistoryLayout::ServiceMessagePainter::paintDate(p, _text, _width, y, w);
} }
void HistoryMediaPtr::reset(HistoryMedia *p) { HistoryMediaPtr::HistoryMediaPtr(std::unique_ptr<HistoryMedia> pointer) : _pointer(std::move(pointer)) {
if (_p) { if (_pointer) {
_p->detachFromParent(); _pointer->attachToParent();
delete _p;
} }
_p = p; }
if (_p) {
_p->attachToParent(); HistoryMediaPtr &HistoryMediaPtr::operator=(std::unique_ptr<HistoryMedia> pointer) {
if (_pointer) {
_pointer->detachFromParent();
} }
_pointer = std::move(pointer);
if (_pointer) {
_pointer->attachToParent();
}
return *this;
} }
namespace internal { namespace internal {

View File

@ -215,6 +215,7 @@ struct HistoryMessageReplyMarkup : public RuntimeComponent<HistoryMessageReplyMa
SwitchInline, SwitchInline,
SwitchInlineSame, SwitchInlineSame,
Game, Game,
Buy,
}; };
Type type; Type type;
QString text; QString text;
@ -420,33 +421,35 @@ public:
HistoryMediaPtr() = default; HistoryMediaPtr() = default;
HistoryMediaPtr(const HistoryMediaPtr &other) = delete; HistoryMediaPtr(const HistoryMediaPtr &other) = delete;
HistoryMediaPtr &operator=(const HistoryMediaPtr &other) = delete; HistoryMediaPtr &operator=(const HistoryMediaPtr &other) = delete;
HistoryMedia *data() const { HistoryMediaPtr(std::unique_ptr<HistoryMedia> other);
return _p; HistoryMediaPtr &operator=(std::unique_ptr<HistoryMedia> other);
HistoryMedia *get() const {
return _pointer.get();
} }
void reset(HistoryMedia *p = nullptr); void reset(std::unique_ptr<HistoryMedia> pointer = nullptr) {
void clear() { *this = std::move(pointer);
reset();
} }
bool isNull() const { bool isNull() const {
return data() == nullptr; return !_pointer;
} }
HistoryMedia *operator->() const { HistoryMedia *operator->() const {
return data(); return get();
} }
HistoryMedia &operator*() const { HistoryMedia &operator*() const {
t_assert(!isNull()); t_assert(!isNull());
return *data(); return *get();
} }
explicit operator bool() const { explicit operator bool() const {
return !isNull(); return !isNull();
} }
~HistoryMediaPtr() { ~HistoryMediaPtr() {
clear(); reset();
} }
private: private:
HistoryMedia *_p = nullptr; std::unique_ptr<HistoryMedia> _pointer;
}; };
@ -726,7 +729,7 @@ public:
} }
HistoryMedia *getMedia() const { HistoryMedia *getMedia() const {
return _media.data(); return _media.get();
} }
virtual void setText(const TextWithEntities &textWithEntities) { virtual void setText(const TextWithEntities &textWithEntities) {
} }

View File

@ -96,7 +96,7 @@ public:
virtual bool uploading() const { virtual bool uploading() const {
return false; return false;
} }
virtual HistoryMedia *clone(HistoryItem *newParent) const = 0; virtual std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const = 0;
virtual DocumentData *getDocument() { virtual DocumentData *getDocument() {
return nullptr; return nullptr;

View File

@ -2530,7 +2530,9 @@ int32 articleThumbHeight(PhotoData *thumb, int32 width) {
return qMax(thumb->medium->height() * width / thumb->medium->width(), 1); return qMax(thumb->medium->height() * width / thumb->medium->width(), 1);
} }
int32 _lineHeight = 0; int unitedLineHeight() {
return qMax(st::webPageTitleFont->height, st::webPageDescriptionFont->height);
}
} // namespace } // namespace
@ -2557,7 +2559,7 @@ void HistoryWebPage::initDimensions() {
_maxw = _minh = _height = 0; _maxw = _minh = _height = 0;
return; return;
} }
if (!_lineHeight) _lineHeight = qMax(st::webPageTitleFont->height, st::webPageDescriptionFont->height); auto lineHeight = unitedLineHeight();
if (!_openl && !_data->url.isEmpty()) { if (!_openl && !_data->url.isEmpty()) {
_openl = MakeShared<UrlClickHandler>(_data->url, true); _openl = MakeShared<UrlClickHandler>(_data->url, true);
@ -2631,14 +2633,14 @@ void HistoryWebPage::initDimensions() {
_maxw = skipBlockWidth; _maxw = skipBlockWidth;
_minh = 0; _minh = 0;
int32 siteNameHeight = _data->siteName.isEmpty() ? 0 : _lineHeight; int32 siteNameHeight = _data->siteName.isEmpty() ? 0 : lineHeight;
int32 titleMinHeight = _title.isEmpty() ? 0 : _lineHeight; int32 titleMinHeight = _title.isEmpty() ? 0 : lineHeight;
int32 descMaxLines = (3 + (siteNameHeight ? 0 : 1) + (titleMinHeight ? 0 : 1)); int32 descMaxLines = (3 + (siteNameHeight ? 0 : 1) + (titleMinHeight ? 0 : 1));
int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * _lineHeight); int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight);
int32 articleMinHeight = siteNameHeight + titleMinHeight + descriptionMinHeight; int32 articleMinHeight = siteNameHeight + titleMinHeight + descriptionMinHeight;
int32 articlePhotoMaxWidth = 0; int32 articlePhotoMaxWidth = 0;
if (_asArticle) { if (_asArticle) {
articlePhotoMaxWidth = st::webPagePhotoDelta + qMax(articleThumbWidth(_data->photo, articleMinHeight), _lineHeight); articlePhotoMaxWidth = st::webPagePhotoDelta + qMax(articleThumbWidth(_data->photo, articleMinHeight), lineHeight);
} }
if (_siteNameWidth) { if (_siteNameWidth) {
@ -2647,7 +2649,7 @@ void HistoryWebPage::initDimensions() {
} else { } else {
accumulate_max(_maxw, _siteNameWidth + articlePhotoMaxWidth); accumulate_max(_maxw, _siteNameWidth + articlePhotoMaxWidth);
} }
_minh += _lineHeight; _minh += lineHeight;
} }
if (!_title.isEmpty()) { if (!_title.isEmpty()) {
accumulate_max(_maxw, _title.maxWidth() + articlePhotoMaxWidth); accumulate_max(_maxw, _title.maxWidth() + articlePhotoMaxWidth);
@ -2693,13 +2695,15 @@ int HistoryWebPage::resizeGetHeight(int width) {
_width = width/* = qMin(width, _maxw)*/; _width = width/* = qMin(width, _maxw)*/;
width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right();
int32 linesMax = 5; auto lineHeight = unitedLineHeight();
int32 siteNameLines = _siteNameWidth ? 1 : 0, siteNameHeight = _siteNameWidth ? _lineHeight : 0; auto linesMax = 5;
auto siteNameLines = _siteNameWidth ? 1 : 0;
auto siteNameHeight = _siteNameWidth ? lineHeight : 0;
if (_asArticle) { if (_asArticle) {
_pixh = linesMax * _lineHeight; _pixh = linesMax * lineHeight;
do { do {
_pixw = articleThumbWidth(_data->photo, _pixh); _pixw = articleThumbWidth(_data->photo, _pixh);
int32 wleft = width - st::webPagePhotoDelta - qMax(_pixw, int16(_lineHeight)); int32 wleft = width - st::webPagePhotoDelta - qMax(_pixw, int16(lineHeight));
_height = siteNameHeight; _height = siteNameHeight;
@ -2711,23 +2715,23 @@ int HistoryWebPage::resizeGetHeight(int width) {
} else { } else {
_titleLines = 2; _titleLines = 2;
} }
_height += _titleLines * _lineHeight; _height += _titleLines * lineHeight;
} }
int32 descriptionHeight = _description.countHeight(wleft); auto descriptionHeight = _description.countHeight(wleft);
if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) { if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
_descriptionLines = (descriptionHeight / st::webPageDescriptionFont->height); _descriptionLines = (descriptionHeight / st::webPageDescriptionFont->height);
} else { } else {
_descriptionLines = (linesMax - siteNameLines - _titleLines); _descriptionLines = (linesMax - siteNameLines - _titleLines);
} }
_height += _descriptionLines * _lineHeight; _height += _descriptionLines * lineHeight;
if (_height >= _pixh) { if (_height >= _pixh) {
break; break;
} }
_pixh -= _lineHeight; _pixh -= lineHeight;
} while (_pixh > _lineHeight); } while (_pixh > lineHeight);
_height += bottomInfoPadding(); _height += bottomInfoPadding();
} else { } else {
_height = siteNameHeight; _height = siteNameHeight;
@ -2740,7 +2744,7 @@ int HistoryWebPage::resizeGetHeight(int width) {
} else { } else {
_titleLines = 2; _titleLines = 2;
} }
_height += _titleLines * _lineHeight; _height += _titleLines * lineHeight;
} }
if (_description.isEmpty()) { if (_description.isEmpty()) {
@ -2752,7 +2756,7 @@ int HistoryWebPage::resizeGetHeight(int width) {
} else { } else {
_descriptionLines = (linesMax - siteNameLines - _titleLines); _descriptionLines = (linesMax - siteNameLines - _titleLines);
} }
_height += _descriptionLines * _lineHeight; _height += _descriptionLines * lineHeight;
} }
if (_attach) { if (_attach) {
@ -2797,11 +2801,12 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
QRect bar(rtlrect(st::msgPadding.left(), tshift, st::webPageBar, _height - tshift - bshift, _width)); QRect bar(rtlrect(st::msgPadding.left(), tshift, st::webPageBar, _height - tshift - bshift, _width));
p.fillRect(bar, barfg); p.fillRect(bar, barfg);
auto lineHeight = unitedLineHeight();
if (_asArticle) { if (_asArticle) {
_data->photo->medium->load(false, false); _data->photo->medium->load(false, false);
bool full = _data->photo->medium->loaded(); bool full = _data->photo->medium->loaded();
QPixmap pix; QPixmap pix;
int32 pw = qMax(_pixw, int16(_lineHeight)), ph = _pixh; int32 pw = qMax(_pixw, int16(lineHeight)), ph = _pixh;
int32 pixw = _pixw, pixh = articleThumbHeight(_data->photo, _pixw); int32 pixw = _pixw, pixh = articleThumbHeight(_data->photo, _pixw);
int32 maxw = convertScale(_data->photo->medium->width()), maxh = convertScale(_data->photo->medium->height()); int32 maxw = convertScale(_data->photo->medium->width()), maxh = convertScale(_data->photo->medium->height());
if (pixw * ph != pixh * pw) { if (pixw * ph != pixh * pw) {
@ -2824,7 +2829,7 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
p.setFont(st::webPageTitleFont); p.setFont(st::webPageTitleFont);
p.setPen(semibold); p.setPen(semibold);
p.drawTextLeft(padding.left(), tshift, _width, (width >= _siteNameWidth) ? _data->siteName : st::webPageTitleFont->elided(_data->siteName, width)); p.drawTextLeft(padding.left(), tshift, _width, (width >= _siteNameWidth) ? _data->siteName : st::webPageTitleFont->elided(_data->siteName, width));
tshift += _lineHeight; tshift += lineHeight;
} }
if (_titleLines) { if (_titleLines) {
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg); p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
@ -2833,7 +2838,7 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_title.drawLeftElided(p, padding.left(), tshift, width, _width, _titleLines, style::al_left, 0, -1, endskip, false, selection); _title.drawLeftElided(p, padding.left(), tshift, width, _width, _titleLines, style::al_left, 0, -1, endskip, false, selection);
tshift += _titleLines * _lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg); p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
@ -2842,7 +2847,7 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_description.drawLeftElided(p, padding.left(), tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection)); _description.drawLeftElided(p, padding.left(), tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
tshift += _descriptionLines * _lineHeight; tshift += _descriptionLines * lineHeight;
} }
if (_attach) { if (_attach) {
auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines; auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines;
@ -2899,9 +2904,10 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ
} }
width -= padding.left() + padding.right(); width -= padding.left() + padding.right();
bool inThumb = false; auto lineHeight = unitedLineHeight();
auto inThumb = false;
if (_asArticle) { if (_asArticle) {
int32 pw = qMax(_pixw, int16(_lineHeight)); int32 pw = qMax(_pixw, int16(lineHeight));
if (rtlrect(padding.left() + width - pw, 0, pw, _pixh, _width).contains(x, y)) { if (rtlrect(padding.left() + width - pw, 0, pw, _pixh, _width).contains(x, y)) {
inThumb = true; inThumb = true;
} }
@ -2909,27 +2915,27 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ
} }
int symbolAdd = 0; int symbolAdd = 0;
if (_siteNameWidth) { if (_siteNameWidth) {
tshift += _lineHeight; tshift += lineHeight;
} }
if (_titleLines) { if (_titleLines) {
if (y >= tshift && y < tshift + _titleLines * _lineHeight) { if (y >= tshift && y < tshift + _titleLines * lineHeight) {
Text::StateRequestElided titleRequest = request.forText(); Text::StateRequestElided titleRequest = request.forText();
titleRequest.lines = _titleLines; titleRequest.lines = _titleLines;
result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest);
} else if (y >= tshift + _titleLines * _lineHeight) { } else if (y >= tshift + _titleLines * lineHeight) {
symbolAdd += _title.length(); symbolAdd += _title.length();
} }
tshift += _titleLines * _lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
if (y >= tshift && y < tshift + _descriptionLines * _lineHeight) { if (y >= tshift && y < tshift + _descriptionLines * lineHeight) {
Text::StateRequestElided descriptionRequest = request.forText(); Text::StateRequestElided descriptionRequest = request.forText();
descriptionRequest.lines = _descriptionLines; descriptionRequest.lines = _descriptionLines;
result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest); result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest);
} else if (y >= tshift + _descriptionLines * _lineHeight) { } else if (y >= tshift + _descriptionLines * lineHeight) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
tshift += _descriptionLines * _lineHeight; tshift += _descriptionLines * lineHeight;
} }
if (inThumb) { if (inThumb) {
result.link = _openl; result.link = _openl;
@ -3054,9 +3060,11 @@ HistoryGame::HistoryGame(HistoryItem *parent, const HistoryGame &other) : Histor
} }
void HistoryGame::initDimensions() { void HistoryGame::initDimensions() {
if (!_lineHeight) _lineHeight = qMax(st::webPageTitleFont->height, st::webPageDescriptionFont->height); auto lineHeight = unitedLineHeight();
if (!_openl) _openl.reset(new ReplyMarkupClickHandler(_parent, 0, 0)); if (!_openl) {
_openl = MakeShared<ReplyMarkupClickHandler>(_parent, 0, 0);
}
auto title = _data->title; auto title = _data->title;
@ -3081,6 +3089,9 @@ void HistoryGame::initDimensions() {
if (_description.isEmpty() && !_data->description.isEmpty()) { if (_description.isEmpty() && !_data->description.isEmpty()) {
auto text = _data->description; auto text = _data->description;
if (!text.isEmpty()) { if (!text.isEmpty()) {
if (!_attach) {
text += _parent->skipBlock();
}
_description.setText(st::webPageDescriptionStyle, text, _webpageDescriptionOptions); _description.setText(st::webPageDescriptionStyle, text, _webpageDescriptionOptions);
} }
} }
@ -3094,10 +3105,10 @@ void HistoryGame::initDimensions() {
_maxw = skipBlockWidth; _maxw = skipBlockWidth;
_minh = 0; _minh = 0;
int32 titleMinHeight = _title.isEmpty() ? 0 : _lineHeight; int32 titleMinHeight = _title.isEmpty() ? 0 : lineHeight;
// enable any count of lines in game description / message // enable any count of lines in game description / message
int descMaxLines = 4096; int descMaxLines = 4096;
int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * _lineHeight); int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight);
if (!_title.isEmpty()) { if (!_title.isEmpty()) {
accumulate_max(_maxw, _title.maxWidth()); accumulate_max(_maxw, _title.maxWidth());
@ -3134,7 +3145,8 @@ int HistoryGame::resizeGetHeight(int width) {
width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right();
// enable any count of lines in game description / message // enable any count of lines in game description / message
int linesMax = 4096; auto linesMax = 4096;
auto lineHeight = unitedLineHeight();
_height = 0; _height = 0;
if (_title.isEmpty()) { if (_title.isEmpty()) {
_titleLines = 0; _titleLines = 0;
@ -3144,7 +3156,7 @@ int HistoryGame::resizeGetHeight(int width) {
} else { } else {
_titleLines = 2; _titleLines = 2;
} }
_height += _titleLines * _lineHeight; _height += _titleLines * lineHeight;
} }
if (_description.isEmpty()) { if (_description.isEmpty()) {
@ -3156,7 +3168,7 @@ int HistoryGame::resizeGetHeight(int width) {
} else { } else {
_descriptionLines = (linesMax - _titleLines); _descriptionLines = (linesMax - _titleLines);
} }
_height += _descriptionLines * _lineHeight; _height += _descriptionLines * lineHeight;
} }
if (_attach) { if (_attach) {
@ -3200,6 +3212,7 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, Time
QRect bar(rtlrect(st::msgPadding.left(), tshift, st::webPageBar, _height - tshift - bshift, _width)); QRect bar(rtlrect(st::msgPadding.left(), tshift, st::webPageBar, _height - tshift - bshift, _width));
p.fillRect(bar, barfg); p.fillRect(bar, barfg);
auto lineHeight = unitedLineHeight();
if (_titleLines) { if (_titleLines) {
p.setPen(semibold); p.setPen(semibold);
int32 endskip = 0; int32 endskip = 0;
@ -3207,7 +3220,7 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, Time
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_title.drawLeftElided(p, padding.left(), tshift, width, _width, _titleLines, style::al_left, 0, -1, endskip, false, selection); _title.drawLeftElided(p, padding.left(), tshift, width, _width, _titleLines, style::al_left, 0, -1, endskip, false, selection);
tshift += _titleLines * _lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg); p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
@ -3216,7 +3229,7 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, Time
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_description.drawLeftElided(p, padding.left(), tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection)); _description.drawLeftElided(p, padding.left(), tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
tshift += _descriptionLines * _lineHeight; tshift += _descriptionLines * lineHeight;
} }
if (_attach) { if (_attach) {
auto attachAtTop = !_titleLines && !_descriptionLines; auto attachAtTop = !_titleLines && !_descriptionLines;
@ -3263,27 +3276,28 @@ HistoryTextState HistoryGame::getState(int x, int y, HistoryStateRequest request
} }
width -= padding.left() + padding.right(); width -= padding.left() + padding.right();
bool inThumb = false; auto inThumb = false;
int symbolAdd = 0; auto symbolAdd = 0;
auto lineHeight = unitedLineHeight();
if (_titleLines) { if (_titleLines) {
if (y >= tshift && y < tshift + _titleLines * _lineHeight) { if (y >= tshift && y < tshift + _titleLines * lineHeight) {
Text::StateRequestElided titleRequest = request.forText(); Text::StateRequestElided titleRequest = request.forText();
titleRequest.lines = _titleLines; titleRequest.lines = _titleLines;
result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest);
} else if (y >= tshift + _titleLines * _lineHeight) { } else if (y >= tshift + _titleLines * lineHeight) {
symbolAdd += _title.length(); symbolAdd += _title.length();
} }
tshift += _titleLines * _lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
if (y >= tshift && y < tshift + _descriptionLines * _lineHeight) { if (y >= tshift && y < tshift + _descriptionLines * lineHeight) {
Text::StateRequestElided descriptionRequest = request.forText(); Text::StateRequestElided descriptionRequest = request.forText();
descriptionRequest.lines = _descriptionLines; descriptionRequest.lines = _descriptionLines;
result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest); result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest);
} else if (y >= tshift + _descriptionLines * _lineHeight) { } else if (y >= tshift + _descriptionLines * lineHeight) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
tshift += _descriptionLines * _lineHeight; tshift += _descriptionLines * lineHeight;
} }
if (inThumb) { if (inThumb) {
result.link = _openl; result.link = _openl;
@ -3411,6 +3425,353 @@ int HistoryGame::bottomInfoPadding() const {
return result; return result;
} }
HistoryInvoice::HistoryInvoice(HistoryItem *parent, const MTPDmessageMediaInvoice &data) : HistoryMedia(parent)
, _title(st::msgMinWidth)
, _description(st::msgMinWidth)
, _status(st::msgMinWidth) {
fillFromData(data);
}
HistoryInvoice::HistoryInvoice(HistoryItem *parent, const HistoryInvoice &other) : HistoryMedia(parent)
, _attach(other._attach ? other._attach->clone(parent) : nullptr)
, _titleHeight(other._titleHeight)
, _descriptionHeight(other._descriptionHeight)
, _title(other._title)
, _description(other._description)
, _status(other._status) {
}
namespace {
QString fillAmountAndCurrency(int amount, const QString &currency) {
static auto shortCurrencyNames = QMap<QString, QString> {
{ qsl("USD"), qsl("$") },
{ qsl("GBP"), qsl("£") },
{ qsl("EUR"), qsl("") },
{ qsl("JPY"), qsl("¥") },
};
auto amountBucks = amount / 100;
auto amountCents = amount % 100;
auto amountText = qsl("%1,%2").arg(amountBucks).arg(amountCents, 2, 10, QChar('0'));
auto currencyText = shortCurrencyNames.value(currency, currency);
return currencyText + amountText;
}
} // namespace
void HistoryInvoice::fillFromData(const MTPDmessageMediaInvoice &data) {
// init attach
if (data.has_photo()) {
// _attach = std::make_unique<HistoryPhoto>(_parent, data.vphoto.c_webDocument(), QString());
}
auto statusText = TextWithEntities { fillAmountAndCurrency(data.vtotal_amount.v, qs(data.vcurrency)), EntitiesInText() };
statusText.entities.push_back(EntityInText(EntityInTextBold, 0, statusText.text.size()));
if (data.is_test()) {
statusText.text += " TEST";
}
_status.setMarkedText(st::defaultTextStyle, statusText, itemTextOptions(_parent));
// init strings
auto description = qs(data.vdescription);
if (!description.isEmpty()) {
_description.setText(st::webPageDescriptionStyle, description, _webpageDescriptionOptions);
}
auto title = qs(data.vtitle);
if (!title.isEmpty()) {
_title.setText(st::webPageTitleStyle, title, _webpageTitleOptions);
}
}
void HistoryInvoice::initDimensions() {
auto lineHeight = unitedLineHeight();
if (_attach) {
if (_status.hasSkipBlock()) {
_status.removeSkipBlock();
}
} else if (!_status.hasSkipBlock()) {
_status.setSkipBlock(_parent->skipBlockWidth(), _parent->skipBlockHeight());
}
// init dimensions
int32 l = st::msgPadding.left(), r = st::msgPadding.right();
int32 skipBlockWidth = _parent->skipBlockWidth();
_maxw = skipBlockWidth;
_minh = 0;
int32 titleMinHeight = _title.isEmpty() ? 0 : lineHeight;
// enable any count of lines in game description / message
int descMaxLines = 4096;
int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight);
if (!_title.isEmpty()) {
accumulate_max(_maxw, _title.maxWidth());
_minh += titleMinHeight;
}
if (!_description.isEmpty()) {
accumulate_max(_maxw, _description.maxWidth());
_minh += descriptionMinHeight;
}
if (_attach) {
auto attachAtTop = _title.isEmpty() && _description.isEmpty();
if (!attachAtTop) _minh += st::mediaInBubbleSkip;
_attach->initDimensions();
auto bubble = _attach->bubbleMargins();
auto maxMediaWidth = _attach->maxWidth() - bubble.left() - bubble.right();
if (isBubbleBottom() && _attach->customInfoLayout()) {
maxMediaWidth += skipBlockWidth;
}
accumulate_max(_maxw, maxMediaWidth);
_minh += _attach->minHeight() - bubble.top() - bubble.bottom();
} else {
accumulate_max(_maxw, _status.maxWidth());
_minh += st::mediaInBubbleSkip + _status.minHeight();
}
auto padding = inBubblePadding();
_maxw += padding.left() + padding.right();
_minh += padding.top() + padding.bottom();
}
int HistoryInvoice::resizeGetHeight(int width) {
_width = width = qMin(width, _maxw);
width -= st::msgPadding.left() + st::msgPadding.right();
auto lineHeight = unitedLineHeight();
_height = 0;
if (_title.isEmpty()) {
_titleHeight = 0;
} else {
if (_title.countHeight(width) < 2 * st::webPageTitleFont->height) {
_titleHeight = lineHeight;
} else {
_titleHeight = 2 * lineHeight;
}
_height += _titleHeight;
}
if (_description.isEmpty()) {
_descriptionHeight = 0;
} else {
_descriptionHeight = _description.countHeight(width);
_height += _descriptionHeight;
}
if (_attach) {
auto attachAtTop = !_title.isEmpty() && _description.isEmpty();
if (!attachAtTop) _height += st::mediaInBubbleSkip;
QMargins bubble(_attach->bubbleMargins());
_attach->resizeGetHeight(width + bubble.left() + bubble.right());
_height += _attach->height() - bubble.top() - bubble.bottom();
if (isBubbleBottom() && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
_height += bottomInfoPadding();
}
} else {
_height += st::mediaInBubbleSkip + _status.countHeight(width);
}
auto padding = inBubblePadding();
_height += padding.top() + padding.bottom();
return _height;
}
void HistoryInvoice::draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
int32 width = _width, height = _height;
bool out = _parent->out(), isPost = _parent->isPost(), outbg = out && !isPost;
bool selected = (selection == FullSelection);
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
auto &regular = selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg);
QMargins bubble(_attach ? _attach->bubbleMargins() : QMargins());
auto padding = inBubblePadding();
auto tshift = padding.top();
auto bshift = padding.bottom();
width -= padding.left() + padding.right();
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
bshift += bottomInfoPadding();
}
auto lineHeight = unitedLineHeight();
if (_titleHeight) {
p.setPen(semibold);
p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outSemiboldPalette : st::inSemiboldPalette));
int32 endskip = 0;
if (_title.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_title.drawLeftElided(p, padding.left(), tshift, width, _width, _titleHeight / lineHeight, style::al_left, 0, -1, endskip, false, selection);
tshift += _titleHeight;
p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
}
if (_descriptionHeight) {
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
_description.drawLeft(p, padding.left(), tshift, width, _width, style::al_left, 0, -1, toDescriptionSelection(selection));
tshift += _descriptionHeight;
}
if (_attach) {
auto attachAtTop = !_titleHeight && !_descriptionHeight;
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
auto attachLeft = padding.left() - bubble.left();
auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
p.translate(attachLeft, attachTop);
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
auto pixwidth = _attach->currentWidth();
auto pixheight = _attach->height();
auto available = _status.maxWidth();
auto statusW = available + 2 * st::msgDateImgPadding.x();
auto statusH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
auto statusX = st::msgDateImgDelta;
auto statusY = st::msgDateImgDelta;
App::roundRect(p, rtlrect(statusX, statusY, statusW, statusH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
p.setFont(st::msgDateFont);
p.setPen(st::msgDateImgFg);
_status.drawLeftElided(p, statusX + st::msgDateImgPadding.x(), statusY + st::msgDateImgPadding.y(), available, pixwidth);
p.translate(-attachLeft, -attachTop);
} else {
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
_status.drawLeft(p, padding.left(), tshift + st::mediaInBubbleSkip, width, _width);
}
}
HistoryTextState HistoryInvoice::getState(int x, int y, HistoryStateRequest request) const {
HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result;
int32 width = _width, height = _height;
QMargins bubble(_attach ? _attach->bubbleMargins() : QMargins());
auto padding = inBubblePadding();
auto tshift = padding.top();
auto bshift = padding.bottom();
if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) {
bshift += bottomInfoPadding();
}
width -= padding.left() + padding.right();
auto lineHeight = unitedLineHeight();
auto symbolAdd = 0;
if (_titleHeight) {
if (y >= tshift && y < tshift + _titleHeight) {
Text::StateRequestElided titleRequest = request.forText();
titleRequest.lines = _titleHeight / lineHeight;
result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest);
} else if (y >= tshift + _titleHeight) {
symbolAdd += _title.length();
}
tshift += _titleHeight;
}
if (_descriptionHeight) {
if (y >= tshift && y < tshift + _descriptionHeight) {
result = _description.getStateLeft(x - padding.left(), y - tshift, width, _width, request.forText());
} else if (y >= tshift + _descriptionHeight) {
symbolAdd += _description.length();
}
tshift += _descriptionHeight;
}
if (_attach) {
auto attachAtTop = !_titleHeight && !_descriptionHeight;
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
auto attachLeft = padding.left() - bubble.left();
auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
if (x >= attachLeft && x < attachLeft + _attach->currentWidth() && y >= tshift && y < _height - bshift) {
result = _attach->getState(x - attachLeft, y - attachTop, request);
}
}
result.symbol += symbolAdd;
return result;
}
TextSelection HistoryInvoice::adjustSelection(TextSelection selection, TextSelectType type) const {
if (!_descriptionHeight || selection.to <= _title.length()) {
return _title.adjustSelection(selection, type);
}
auto descriptionSelection = _description.adjustSelection(toDescriptionSelection(selection), type);
if (selection.from >= _title.length()) {
return fromDescriptionSelection(descriptionSelection);
}
auto titleSelection = _title.adjustSelection(selection, type);
return { titleSelection.from, fromDescriptionSelection(descriptionSelection).to };
}
void HistoryInvoice::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
if (_attach) {
_attach->clickHandlerActiveChanged(p, active);
}
}
void HistoryInvoice::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
if (_attach) {
_attach->clickHandlerPressedChanged(p, pressed);
}
}
void HistoryInvoice::attachToParent() {
if (_attach) _attach->attachToParent();
}
void HistoryInvoice::detachFromParent() {
if (_attach) _attach->detachFromParent();
}
QString HistoryInvoice::notificationText() const {
return _title.originalText();
}
TextWithEntities HistoryInvoice::selectedText(TextSelection selection) const {
if (selection == FullSelection) {
return TextWithEntities();
}
auto titleResult = _title.originalTextWithEntities(selection, ExpandLinksAll);
auto descriptionResult = _description.originalTextWithEntities(toDescriptionSelection(selection), ExpandLinksAll);
if (titleResult.text.isEmpty()) {
return descriptionResult;
} else if (descriptionResult.text.isEmpty()) {
return titleResult;
}
titleResult.text += '\n';
appendTextWithEntities(titleResult, std::move(descriptionResult));
return titleResult;
}
QMargins HistoryInvoice::inBubblePadding() const {
auto lshift = st::msgPadding.left();
auto rshift = st::msgPadding.right();
auto bshift = isBubbleBottom() ? st::msgPadding.top() : st::mediaInBubbleSkip;
auto tshift = isBubbleTop() ? st::msgPadding.bottom() : st::mediaInBubbleSkip;
return QMargins(lshift, tshift, rshift, bshift);
}
int HistoryInvoice::bottomInfoPadding() const {
if (!isBubbleBottom()) return 0;
auto result = st::msgDateFont->height;
return result;
}
HistoryLocation::HistoryLocation(HistoryItem *parent, const LocationCoords &coords, const QString &title, const QString &description) : HistoryMedia(parent) HistoryLocation::HistoryLocation(HistoryItem *parent, const LocationCoords &coords, const QString &title, const QString &description) : HistoryMedia(parent)
, _data(App::location(coords)) , _data(App::location(coords))
, _title(st::msgMinWidth) , _title(st::msgMinWidth)

View File

@ -46,16 +46,16 @@ protected:
void setDocumentLinks(DocumentData *document, bool inlinegif = false) { void setDocumentLinks(DocumentData *document, bool inlinegif = false) {
ClickHandlerPtr open, save; ClickHandlerPtr open, save;
if (inlinegif) { if (inlinegif) {
open.reset(new GifOpenClickHandler(document)); open = MakeShared<GifOpenClickHandler>(document);
} else { } else {
open.reset(new DocumentOpenClickHandler(document)); open = MakeShared<DocumentOpenClickHandler>(document);
} }
if (inlinegif) { if (inlinegif) {
save.reset(new GifOpenClickHandler(document)); save = MakeShared<GifOpenClickHandler>(document);
} else if (document->voice()) { } else if (document->voice()) {
save.reset(new DocumentOpenClickHandler(document)); save = MakeShared<DocumentOpenClickHandler>(document);
} else { } else {
save.reset(new DocumentSaveClickHandler(document)); save = MakeShared<DocumentSaveClickHandler>(document);
} }
setLinks(std::move(open), std::move(save), MakeShared<DocumentCancelClickHandler>(document)); setLinks(std::move(open), std::move(save), MakeShared<DocumentCancelClickHandler>(document));
} }
@ -118,8 +118,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypePhoto; return MediaTypePhoto;
} }
HistoryPhoto *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryPhoto(newParent, *this); return std::make_unique<HistoryPhoto>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;
@ -205,8 +205,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeVideo; return MediaTypeVideo;
} }
HistoryVideo *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryVideo(newParent, *this); return std::make_unique<HistoryVideo>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;
@ -357,8 +357,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return _data->voice() ? MediaTypeVoiceFile : (_data->song() ? MediaTypeMusicFile : MediaTypeFile); return _data->voice() ? MediaTypeVoiceFile : (_data->song() ? MediaTypeMusicFile : MediaTypeFile);
} }
HistoryDocument *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryDocument(newParent, *this); return std::make_unique<HistoryDocument>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;
@ -456,8 +456,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeGif; return MediaTypeGif;
} }
HistoryGif *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryGif(newParent, *this); return std::make_unique<HistoryGif>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;
@ -553,8 +553,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeSticker; return MediaTypeSticker;
} }
HistorySticker *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistorySticker(newParent, _data); return std::make_unique<HistorySticker>(newParent, _data);
} }
void initDimensions() override; void initDimensions() override;
@ -617,8 +617,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeContact; return MediaTypeContact;
} }
HistoryContact *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryContact(newParent, _userId, _fname, _lname, _phone); return std::make_unique<HistoryContact>(newParent, _userId, _fname, _lname, _phone);
} }
void initDimensions() override; void initDimensions() override;
@ -680,8 +680,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeWebPage; return MediaTypeWebPage;
} }
HistoryWebPage *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryWebPage(newParent, *this); return std::make_unique<HistoryWebPage>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;
@ -778,8 +778,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeGame; return MediaTypeGame;
} }
HistoryGame *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryGame(newParent, *this); return std::make_unique<HistoryGame>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;
@ -871,6 +871,84 @@ private:
}; };
class HistoryInvoice : public HistoryMedia {
public:
HistoryInvoice(HistoryItem *parent, const MTPDmessageMediaInvoice &data);
HistoryInvoice(HistoryItem *parent, const HistoryInvoice &other);
HistoryMediaType type() const override {
return MediaTypeGame;
}
std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return std::make_unique<HistoryInvoice>(newParent, *this);
}
void initDimensions() override;
int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
bool hasTextForCopy() const override {
return false; // we do not add _title and _description in FullSelection text copy.
}
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
return _attach && _attach->toggleSelectionByHandlerClick(p);
}
bool dragItemByHandler(const ClickHandlerPtr &p) const override {
return _attach && _attach->dragItemByHandler(p);
}
QString notificationText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
void attachToParent() override;
void detachFromParent() override;
bool hasReplyPreview() const override {
return _attach && _attach->hasReplyPreview();
}
ImagePtr replyPreview() override {
return _attach ? _attach->replyPreview() : ImagePtr();
}
bool needsBubble() const override {
return true;
}
bool customInfoLayout() const override {
return false;
}
HistoryMedia *attach() const {
return _attach.get();
}
private:
void fillFromData(const MTPDmessageMediaInvoice &data);
TextSelection toDescriptionSelection(TextSelection selection) const {
return internal::unshiftSelection(selection, _title);
}
TextSelection fromDescriptionSelection(TextSelection selection) const {
return internal::shiftSelection(selection, _title);
}
QMargins inBubblePadding() const;
int bottomInfoPadding() const;
std::unique_ptr<HistoryMedia> _attach;
int _titleHeight;
int _descriptionHeight;
Text _title;
Text _description;
Text _status;
};
class LocationCoords; class LocationCoords;
struct LocationData; struct LocationData;
@ -881,8 +959,8 @@ public:
HistoryMediaType type() const override { HistoryMediaType type() const override {
return MediaTypeLocation; return MediaTypeLocation;
} }
HistoryLocation *clone(HistoryItem *newParent) const override { std::unique_ptr<HistoryMedia> clone(HistoryItem *newParent) const override {
return new HistoryLocation(newParent, *this); return std::make_unique<HistoryLocation>(newParent, *this);
} }
void initDimensions() override; void initDimensions() override;

View File

@ -210,7 +210,7 @@ bool HistoryMessageReply::updateData(HistoryMessage *holder, bool force) {
replyToLnk = goToMessageClickHandler(replyToMsg); replyToLnk = goToMessageClickHandler(replyToMsg);
if (!replyToMsg->Has<HistoryMessageForwarded>()) { if (!replyToMsg->Has<HistoryMessageForwarded>()) {
if (auto bot = replyToMsg->viaBot()) { if (auto bot = replyToMsg->viaBot()) {
_replyToVia.reset(new HistoryMessageVia()); _replyToVia = std::make_unique<HistoryMessageVia>();
_replyToVia->create(peerToUser(bot->id)); _replyToVia->create(peerToUser(bot->id));
} }
} }
@ -474,7 +474,7 @@ HistoryMessage::HistoryMessage(History *history, MsgId id, MTPDmessage::Flags fl
createComponents(config); createComponents(config);
if (mediaOriginal) { if (mediaOriginal) {
_media.reset(mediaOriginal->clone(this)); _media = mediaOriginal->clone(this);
} }
setText(fwd->originalText()); setText(fwd->originalText());
} }
@ -498,7 +498,7 @@ HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags
: HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) { : HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
createComponentsHelper(flags, replyTo, viaBotId, markup); createComponentsHelper(flags, replyTo, viaBotId, markup);
_media.reset(new HistoryPhoto(this, photo, caption)); _media = std::make_unique<HistoryPhoto>(this, photo, caption);
setText(TextWithEntities()); setText(TextWithEntities());
} }
@ -506,7 +506,7 @@ HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags
: HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) { : HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
createComponentsHelper(flags, replyTo, viaBotId, markup); createComponentsHelper(flags, replyTo, viaBotId, markup);
_media.reset(new HistoryGame(this, game)); _media = std::make_unique<HistoryGame>(this, game);
setText(TextWithEntities()); setText(TextWithEntities());
} }
@ -682,24 +682,24 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media) {
switch (media ? media->type() : mtpc_messageMediaEmpty) { switch (media ? media->type() : mtpc_messageMediaEmpty) {
case mtpc_messageMediaContact: { case mtpc_messageMediaContact: {
auto &d = media->c_messageMediaContact(); auto &d = media->c_messageMediaContact();
_media.reset(new HistoryContact(this, d.vuser_id.v, qs(d.vfirst_name), qs(d.vlast_name), qs(d.vphone_number))); _media = std::make_unique<HistoryContact>(this, d.vuser_id.v, qs(d.vfirst_name), qs(d.vlast_name), qs(d.vphone_number));
} break; } break;
case mtpc_messageMediaGeo: { case mtpc_messageMediaGeo: {
auto &point = media->c_messageMediaGeo().vgeo; auto &point = media->c_messageMediaGeo().vgeo;
if (point.type() == mtpc_geoPoint) { if (point.type() == mtpc_geoPoint) {
_media.reset(new HistoryLocation(this, LocationCoords(point.c_geoPoint()))); _media = std::make_unique<HistoryLocation>(this, LocationCoords(point.c_geoPoint()));
} }
} break; } break;
case mtpc_messageMediaVenue: { case mtpc_messageMediaVenue: {
auto &d = media->c_messageMediaVenue(); auto &d = media->c_messageMediaVenue();
if (d.vgeo.type() == mtpc_geoPoint) { if (d.vgeo.type() == mtpc_geoPoint) {
_media.reset(new HistoryLocation(this, LocationCoords(d.vgeo.c_geoPoint()), qs(d.vtitle), qs(d.vaddress))); _media = std::make_unique<HistoryLocation>(this, LocationCoords(d.vgeo.c_geoPoint()), qs(d.vtitle), qs(d.vaddress));
} }
} break; } break;
case mtpc_messageMediaPhoto: { case mtpc_messageMediaPhoto: {
auto &photo = media->c_messageMediaPhoto(); auto &photo = media->c_messageMediaPhoto();
if (photo.vphoto.type() == mtpc_photo) { if (photo.vphoto.type() == mtpc_photo) {
_media.reset(new HistoryPhoto(this, App::feedPhoto(photo.vphoto.c_photo()), qs(photo.vcaption))); _media = std::make_unique<HistoryPhoto>(this, App::feedPhoto(photo.vphoto.c_photo()), qs(photo.vcaption));
} }
} break; } break;
case mtpc_messageMediaDocument: { case mtpc_messageMediaDocument: {
@ -713,10 +713,10 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media) {
switch (d.type()) { switch (d.type()) {
case mtpc_webPageEmpty: break; case mtpc_webPageEmpty: break;
case mtpc_webPagePending: { case mtpc_webPagePending: {
_media.reset(new HistoryWebPage(this, App::feedWebPage(d.c_webPagePending()))); _media = std::make_unique<HistoryWebPage>(this, App::feedWebPage(d.c_webPagePending()));
} break; } break;
case mtpc_webPage: { case mtpc_webPage: {
_media.reset(new HistoryWebPage(this, App::feedWebPage(d.c_webPage()))); _media = std::make_unique<HistoryWebPage>(this, App::feedWebPage(d.c_webPage()));
} break; } break;
case mtpc_webPageNotModified: LOG(("API Error: webPageNotModified is unexpected in message media.")); break; case mtpc_webPageNotModified: LOG(("API Error: webPageNotModified is unexpected in message media.")); break;
} }
@ -724,21 +724,24 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media) {
case mtpc_messageMediaGame: { case mtpc_messageMediaGame: {
auto &d = media->c_messageMediaGame().vgame; auto &d = media->c_messageMediaGame().vgame;
if (d.type() == mtpc_game) { if (d.type() == mtpc_game) {
_media.reset(new HistoryGame(this, App::feedGame(d.c_game()))); _media = std::make_unique<HistoryGame>(this, App::feedGame(d.c_game()));
} }
} break; } break;
case mtpc_messageMediaInvoice: {
_media = std::make_unique<HistoryInvoice>(this, media->c_messageMediaInvoice());
} break;
}; };
} }
void HistoryMessage::initMediaFromDocument(DocumentData *doc, const QString &caption) { void HistoryMessage::initMediaFromDocument(DocumentData *doc, const QString &caption) {
if (doc->sticker()) { if (doc->sticker()) {
_media.reset(new HistorySticker(this, doc)); _media = std::make_unique<HistorySticker>(this, doc);
} else if (doc->isAnimation()) { } else if (doc->isAnimation()) {
_media.reset(new HistoryGif(this, doc, caption)); _media = std::make_unique<HistoryGif>(this, doc, caption);
} else if (doc->isVideo()) { } else if (doc->isVideo()) {
_media.reset(new HistoryVideo(this, doc, caption)); _media = std::make_unique<HistoryVideo>(this, doc, caption);
} else { } else {
_media.reset(new HistoryDocument(this, doc, caption)); _media = std::make_unique<HistoryDocument>(this, doc, caption);
} }
} }
@ -1026,7 +1029,7 @@ void HistoryMessage::setMedia(const MTPMessageMedia *media) {
if (_media->type() == MediaTypeGame) return; if (_media->type() == MediaTypeGame) return;
mediaRemovedSkipBlock = _media->isDisplayed() && _media->isBubbleBottom(); mediaRemovedSkipBlock = _media->isDisplayed() && _media->isBubbleBottom();
_media.clear(); _media.reset();
} }
initMedia(media); initMedia(media);
auto mediaDisplayed = _media && _media->isDisplayed(); auto mediaDisplayed = _media && _media->isDisplayed();
@ -1834,7 +1837,7 @@ bool HistoryMessage::hasFromPhoto() const {
} }
HistoryMessage::~HistoryMessage() { HistoryMessage::~HistoryMessage() {
_media.clear(); _media.reset();
if (auto reply = Get<HistoryMessageReply>()) { if (auto reply = Get<HistoryMessageReply>()) {
reply->clearData(this); reply->clearData(this);
} }
@ -2036,7 +2039,7 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
case mtpc_messageActionChatEditPhoto: { case mtpc_messageActionChatEditPhoto: {
auto &photo = action.c_messageActionChatEditPhoto().vphoto; auto &photo = action.c_messageActionChatEditPhoto().vphoto;
if (photo.type() == mtpc_photo) { if (photo.type() == mtpc_photo) {
_media.reset(new HistoryPhoto(this, history()->peer, photo.c_photo(), st::msgServicePhotoWidth)); _media = std::make_unique<HistoryPhoto>(this, history()->peer, photo.c_photo(), st::msgServicePhotoWidth);
} }
} break; } break;
@ -2407,7 +2410,7 @@ void HistoryService::removeMedia() {
if (!_media) return; if (!_media) return;
bool mediaWasDisplayed = _media->isDisplayed(); bool mediaWasDisplayed = _media->isDisplayed();
_media.clear(); _media.reset();
if (mediaWasDisplayed) { if (mediaWasDisplayed) {
_textWidth = -1; _textWidth = -1;
_textHeight = 0; _textHeight = 0;
@ -2468,7 +2471,7 @@ void HistoryService::clearDependency() {
HistoryService::~HistoryService() { HistoryService::~HistoryService() {
clearDependency(); clearDependency();
_media.clear(); _media.reset();
} }
HistoryJoined::HistoryJoined(History *history, const QDateTime &inviteDate, UserData *inviter, MTPDmessage::Flags flags) HistoryJoined::HistoryJoined(History *history, const QDateTime &inviteDate, UserData *inviter, MTPDmessage::Flags flags)