diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index f1d274190f..1dc366a170 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -808,6 +808,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "Choose images"; +"lng_game_tag" = "Game"; "lng_context_view_profile" = "View profile"; "lng_context_view_group" = "View group info"; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index b7758130ef..16c3bb7000 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1791,15 +1791,15 @@ namespace { } if ((convert->url.isEmpty() && !url.isEmpty()) || (convert->pendingTill && convert->pendingTill != pendingTill && pendingTill >= -1)) { convert->type = toWebPageType(type); - convert->url = url; - convert->displayUrl = displayUrl; - convert->siteName = siteName; - convert->title = title; - convert->description = description; + convert->url = textClean(url); + convert->displayUrl = textClean(displayUrl); + convert->siteName = textClean(siteName); + convert->title = textOneLine(textClean(title)); + convert->description = textClean(description); convert->photo = photo; convert->document = document; convert->duration = duration; - convert->author = author; + convert->author = textClean(author); if (convert->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(convert); convert->pendingTill = pendingTill; if (App::main()) App::main()->webPageUpdated(convert); @@ -1822,15 +1822,15 @@ namespace { if (result != convert) { if ((result->url.isEmpty() && !url.isEmpty()) || (result->pendingTill && result->pendingTill != pendingTill && pendingTill >= -1)) { result->type = toWebPageType(type); - result->url = url; - result->displayUrl = displayUrl; - result->siteName = siteName; - result->title = title; - result->description = description; + result->url = textClean(url); + result->displayUrl = textClean(displayUrl); + result->siteName = textClean(siteName); + result->title = textOneLine(textClean(title)); + result->description = textClean(description); result->photo = photo; result->document = document; result->duration = duration; - result->author = author; + result->author = textClean(author); if (result->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(result); result->pendingTill = pendingTill; if (App::main()) App::main()->webPageUpdated(result); @@ -1859,9 +1859,9 @@ namespace { } if (convert->shortName.isEmpty() && !shortName.isEmpty()) { convert->accessHash = accessHash; - convert->shortName = shortName; - convert->title = title; - convert->description = description; + convert->shortName = textClean(shortName); + convert->title = textOneLine(textClean(title)); + convert->description = textClean(description); convert->photo = photo; convert->document = document; if (App::main()) App::main()->gameUpdated(convert); @@ -1881,9 +1881,9 @@ namespace { if (result != convert) { if (result->shortName.isEmpty() && !shortName.isEmpty()) { result->accessHash = accessHash; - result->shortName = shortName; - result->title = title; - result->description = description; + result->shortName = textClean(shortName); + result->title = textOneLine(textClean(title)); + result->description = textClean(description); result->photo = photo; result->document = document; if (App::main()) App::main()->gameUpdated(result); diff --git a/Telegram/SourceFiles/history/history_media.h b/Telegram/SourceFiles/history/history_media.h index c60e407482..b823dcb6ae 100644 --- a/Telegram/SourceFiles/history/history_media.h +++ b/Telegram/SourceFiles/history/history_media.h @@ -79,6 +79,9 @@ public: virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const { return selection; } + virtual bool consumeMessageText(const TextWithEntities &textWithEntities) { + return false; + } // if we press and drag this link should we drag the item virtual bool dragItemByHandler(const ClickHandlerPtr &p) const = 0; diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 5b1d7bcc70..d2e371f0fd 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -2481,36 +2481,24 @@ void HistoryWebPage::initDimensions() { // init strings if (_description.isEmpty() && !_data->description.isEmpty()) { - QString text = textClean(_data->description); - if (text.isEmpty()) { - _data->description = QString(); - } else { - if (!_asArticle && !_attach) { - text += _parent->skipBlock(); - } - const TextParseOptions *opts = &_webpageDescriptionOptions; - if (_data->siteName == qstr("Twitter")) { - opts = &_twitterDescriptionOptions; - } else if (_data->siteName == qstr("Instagram")) { - opts = &_instagramDescriptionOptions; - } - _description.setText(st::webPageDescriptionFont, text, *opts); + auto text = _data->description; + + if (!_asArticle && !_attach) { + text += _parent->skipBlock(); } + const TextParseOptions *opts = &_webpageDescriptionOptions; + if (_data->siteName == qstr("Twitter")) { + opts = &_twitterDescriptionOptions; + } else if (_data->siteName == qstr("Instagram")) { + opts = &_instagramDescriptionOptions; + } + _description.setText(st::webPageDescriptionFont, text, *opts); } if (_title.isEmpty() && !title.isEmpty()) { - title = textOneLine(textClean(title)); - if (title.isEmpty()) { - if (_data->title.isEmpty()) { - _data->author = QString(); - } else { - _data->title = QString(); - } - } else { - if (!_asArticle && !_attach && _description.isEmpty()) { - title += _parent->skipBlock(); - } - _title.setText(st::webPageTitleFont, title, _webpageTitleOptions); + if (!_asArticle && !_attach && _description.isEmpty()) { + title += _parent->skipBlock(); } + _title.setText(st::webPageTitleFont, title, _webpageTitleOptions); } if (!_siteNameWidth && !_data->siteName.isEmpty()) { _siteNameWidth = st::webPageTitleFont->width(_data->siteName); @@ -2964,20 +2952,13 @@ void HistoryGame::initDimensions() { // init strings if (_description.isEmpty() && !_data->description.isEmpty()) { - auto text = textClean(_data->description); - if (text.isEmpty()) { - _data->description = QString(); - } else { + auto text = _data->description; + if (!text.isEmpty()) { _description.setText(st::webPageDescriptionFont, text, _webpageDescriptionOptions); } } if (_title.isEmpty() && !title.isEmpty()) { - title = textOneLine(textClean(title)); - if (title.isEmpty()) { - _data->title = QString(); - } else { - _title.setText(st::webPageTitleFont, title, _webpageTitleOptions); - } + _title.setText(st::webPageTitleFont, title, _webpageTitleOptions); } // init dimensions @@ -3014,13 +2995,18 @@ void HistoryGame::initDimensions() { _maxw += st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); auto padding = inBubblePadding(); _minh += padding.top() + padding.bottom(); + + if (!_gameTagWidth) { + _gameTagWidth = st::msgDateFont->width(lang(lng_game_tag).toUpper()); + } } int HistoryGame::resizeGetHeight(int width) { _width = qMin(width, _maxw); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); - int linesMax = 5; + // enable any count of lines in game description / message + int linesMax = 4096; _height = 0; if (_title.isEmpty()) { _titleLines = 0; @@ -3116,6 +3102,19 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, uint p.translate(attachLeft, attachTop); _attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms); + auto pixwidth = _attach->currentWidth(); + + auto gameX = st::msgDateImgDelta; + auto gameY = st::msgDateImgDelta; + auto gameW = _gameTagWidth + 2 * st::msgDateImgPadding.x(); + auto gameH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y(); + + App::roundRect(p, rtlrect(gameX, gameY, gameW, gameH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); + + p.setFont(st::msgDateFont); + p.setPen(st::msgDateImgColor); + p.drawTextLeft(gameX + st::msgDateImgPadding.x(), gameY + st::msgDateImgPadding.y(), pixwidth, lang(lng_game_tag).toUpper()); + p.translate(-attachLeft, -attachTop); } } @@ -3188,6 +3187,11 @@ TextSelection HistoryGame::adjustSelection(TextSelection selection, TextSelectTy return { titleSelection.from, fromDescriptionSelection(descriptionSelection).to }; } +bool HistoryGame::consumeMessageText(const TextWithEntities &textWithEntities) { + _description.setMarkedText(st::webPageDescriptionFont, textWithEntities, itemTextOptions(_parent)); + return true; +} + void HistoryGame::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { if (_attach) { _attach->clickHandlerActiveChanged(p, active); @@ -3210,6 +3214,14 @@ void HistoryGame::detachFromParent() { if (_attach) _attach->detachFromParent(); } +QString HistoryGame::notificationText() const { + return _data->title; +} + +QString HistoryGame::inDialogsText() const { + return textcmdLink(1, _data->title); +} + TextWithEntities HistoryGame::selectedText(TextSelection selection) const { if (selection == FullSelection) { return TextWithEntities(); diff --git a/Telegram/SourceFiles/history/history_media_types.h b/Telegram/SourceFiles/history/history_media_types.h index 18c18dd604..2d457231ca 100644 --- a/Telegram/SourceFiles/history/history_media_types.h +++ b/Telegram/SourceFiles/history/history_media_types.h @@ -752,6 +752,7 @@ public: bool hasTextForCopy() const override { return false; // we do not add _title and _description in FullSelection text copy. } + bool consumeMessageText(const TextWithEntities &textWithEntities) override; bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override { return _attach && _attach->toggleSelectionByHandlerClick(p); @@ -760,6 +761,8 @@ public: return _attach && _attach->dragItemByHandler(p); } + QString notificationText() const override; + QString inDialogsText() const override; TextWithEntities selectedText(TextSelection selection) const override; void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; @@ -819,6 +822,8 @@ private: Text _title, _description; + int _gameTagWidth = 0; + }; struct LocationCoords; diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 5c4d538c9a..99def6c55c 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -347,8 +347,8 @@ int HistoryMessage::KeyboardStyle::minButtonWidth(HistoryMessageReplyMarkup::But int result = 2 * buttonPadding(), iconWidth = 0; switch (type) { case Button::Type::Url: iconWidth = st::msgBotKbUrlIcon.pxWidth(); break; - //case Button::Type::RequestPhone: iconWidth = st::msgBotKbRequestPhoneIcon.pxWidth(); break; - //case Button::Type::RequestLocation: iconWidth = st::msgBotKbRequestLocationIcon.pxWidth(); break; + //case Button::Type::RequestPhone: iconWidth = st::msgBotKbRequestPhoneIcon.pxWidth(); break; + //case Button::Type::RequestLocation: iconWidth = st::msgBotKbRequestLocationIcon.pxWidth(); break; case Button::Type::SwitchInlineSame: case Button::Type::SwitchInline: iconWidth = st::msgBotKbSwitchPmIcon.pxWidth(); break; case Button::Type::Callback: @@ -380,13 +380,12 @@ HistoryMessage::HistoryMessage(History *history, const MTPDmessage &msg) createComponents(config); - QString text(textClean(qs(msg.vmessage))); - initMedia(msg.has_media() ? (&msg.vmedia) : nullptr, text); + initMedia(msg.has_media() ? (&msg.vmedia) : nullptr); - TextWithEntities textWithEntities = { text, EntitiesInText() }; - if (msg.has_entities()) { - textWithEntities.entities = entitiesFromMTP(msg.ventities.c_vector().v); - } + TextWithEntities textWithEntities = { + textClean(qs(msg.vmessage)), + msg.has_entities() ? entitiesFromMTP(msg.ventities.c_vector().v) : EntitiesInText(), + }; setText(textWithEntities); } @@ -620,7 +619,7 @@ void HistoryMessage::initTime() { } } -void HistoryMessage::initMedia(const MTPMessageMedia *media, QString ¤tText) { +void HistoryMessage::initMedia(const MTPMessageMedia *media) { switch (media ? media->type() : mtpc_messageMediaEmpty) { case mtpc_messageMediaContact: { auto &d = media->c_messageMediaContact(); @@ -961,16 +960,16 @@ void HistoryMessage::setMedia(const MTPMessageMedia *media) { bool mediaRemovedSkipBlock = false; if (_media) { - mediaRemovedSkipBlock = _media->isDisplayed() && !_media->isAboveMessage(); + mediaRemovedSkipBlock = _media->isDisplayed() && _media->isBubbleBottom(); _media.clear(); } - QString t; - initMedia(media, t); - if (_media && _media->isDisplayed() && !_media->isAboveMessage() && !mediaRemovedSkipBlock) { + initMedia(media); + auto mediaDisplayed = _media && _media->isDisplayed(); + if (mediaDisplayed && _media->isBubbleBottom() && !mediaRemovedSkipBlock) { _text.removeSkipBlock(); _textWidth = -1; _textHeight = 0; - } else if (mediaRemovedSkipBlock && (!_media || !_media->isDisplayed() || _media->isAboveMessage())) { + } else if (mediaRemovedSkipBlock && (!mediaDisplayed || !_media->isBubbleBottom())) { _text.setSkipBlock(skipBlockWidth(), skipBlockHeight()); _textWidth = -1; _textHeight = 0; @@ -978,14 +977,6 @@ void HistoryMessage::setMedia(const MTPMessageMedia *media) { } void HistoryMessage::setText(const TextWithEntities &textWithEntities) { - textstyleSet(&((out() && !isPost()) ? st::outTextStyle : st::inTextStyle)); - if (_media && _media->isDisplayed() && !_media->isAboveMessage()) { - _text.setMarkedText(st::msgFont, textWithEntities, itemTextOptions(this)); - } else { - _text.setMarkedText(st::msgFont, { textWithEntities.text + skipBlock(), textWithEntities.entities }, itemTextOptions(this)); - } - textstyleRestore(); - for_const (auto &entity, textWithEntities.entities) { auto type = entity.type(); if (type == EntityInTextUrl || type == EntityInTextCustomUrl || type == EntityInTextEmail) { @@ -993,8 +984,21 @@ void HistoryMessage::setText(const TextWithEntities &textWithEntities) { break; } } - _textWidth = -1; - _textHeight = 0; + + auto mediaDisplayed = _media && _media->isDisplayed(); + if (mediaDisplayed && _media->consumeMessageText(textWithEntities)) { + setEmptyText(); + } else { + textstyleSet(&((out() && !isPost()) ? st::outTextStyle : st::inTextStyle)); + if (_media && _media->isDisplayed() && !_media->isAboveMessage()) { + _text.setMarkedText(st::msgFont, textWithEntities, itemTextOptions(this)); + } else { + _text.setMarkedText(st::msgFont, { textWithEntities.text + skipBlock(), textWithEntities.entities }, itemTextOptions(this)); + } + textstyleRestore(); + _textWidth = -1; + _textHeight = 0; + } } void HistoryMessage::setEmptyText() { diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index 7c3a1a14f1..1bcd8c4e5e 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -41,7 +41,7 @@ public: } void initTime(); - void initMedia(const MTPMessageMedia *media, QString ¤tText); + void initMedia(const MTPMessageMedia *media); void initMediaFromDocument(DocumentData *doc, const QString &caption); void fromNameUpdated(int32 width) const; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 9845a07180..86d604a884 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -4507,6 +4507,7 @@ void HistoryWidget::updateControlsVisibility() { if (!_a_show.animating()) { _topShadow.setVisible(_peer ? true : false); } + updateToEndVisibility(); if (!_history || _a_show.animating()) { _reportSpamPanel.hide(); _scroll.hide(); @@ -4537,7 +4538,6 @@ void HistoryWidget::updateControlsVisibility() { return; } - updateToEndVisibility(); if (_pinnedBar) { _pinnedBar->cancel.show(); _pinnedBar->shadow.show(); @@ -7380,6 +7380,8 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) { } void HistoryWidget::updateToEndVisibility() { + if (_a_show.animating()) return; + auto haveUnreadBelowBottom = [this](History *history) { if (!_list || !history || history->unreadCount() <= 0) { return false; @@ -7390,7 +7392,7 @@ void HistoryWidget::updateToEndVisibility() { return (_list->itemTop(history->showFrom) >= _scroll.scrollTop() + _scroll.height()); }; auto isToEndVisible = [this, &haveUnreadBelowBottom]() { - if (!_history || _a_show.animating() || _firstLoadRequest) { + if (!_history || _firstLoadRequest) { return false; } if (!_history->loadedAtBottom() || _replyReturn) {