From 8dff205949ee51af3e7f8c5eeda1333ea0d7bd1e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 21 Aug 2015 14:23:44 +0300 Subject: [PATCH] links support started --- Telegram/SourceFiles/gui/text.cpp | 55 ++++++++++++++------ Telegram/SourceFiles/gui/text.h | 23 ++++++++ Telegram/SourceFiles/history.cpp | 53 +++++++++++++++---- Telegram/SourceFiles/history.h | 13 +++-- Telegram/SourceFiles/mtproto/mtpConnection.h | 1 + 5 files changed, 116 insertions(+), 29 deletions(-) diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 5e7d50bdc..5bda612d5 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -2299,7 +2299,10 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions { TextParser parser(this, text, options); } + recountNaturalSize(true, options.dir); +} +void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) { NewlineBlock *lastNewline = 0; int32 lineHeight = 0; @@ -2313,14 +2316,16 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions if (_btype == TextBlockNewline) { if (!lineHeight) lineHeight = blockHeight; - Qt::LayoutDirection dir = options.dir; - if (dir == Qt::LayoutDirectionAuto) { - dir = TextParser::stringDirection(_text, lastNewlineStart, b->from()); - } - if (lastNewline) { - lastNewline->_nextDir = dir; - } else { - _startDir = dir; + if (initial) { + Qt::LayoutDirection dir = optionsDir; + if (dir == Qt::LayoutDirectionAuto) { + dir = TextParser::stringDirection(_text, lastNewlineStart, b->from()); + } + if (lastNewline) { + lastNewline->_nextDir = dir; + } else { + _startDir = dir; + } } lastNewlineStart = b->from(); lastNewline = static_cast(b); @@ -2344,14 +2349,16 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions last_rPadding = b->f_rpadding(); continue; } - Qt::LayoutDirection dir = options.dir; - if (dir == Qt::LayoutDirectionAuto) { - dir = TextParser::stringDirection(_text, lastNewlineStart, _text.size()); - } - if (lastNewline) { - lastNewline->_nextDir = dir; - } else { - _startDir = dir; + if (initial) { + Qt::LayoutDirection dir = optionsDir; + if (dir == Qt::LayoutDirectionAuto) { + dir = TextParser::stringDirection(_text, lastNewlineStart, _text.size()); + } + if (lastNewline) { + lastNewline->_nextDir = dir; + } else { + _startDir = dir; + } } if (_width > 0) { if (!lineHeight) lineHeight = _blockHeight(_blocks.back(), _font); @@ -2362,6 +2369,10 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions } } +void Text::setMarkedText(style::font font, const QString &text, const LinksInText &links) { + +} + void Text::setRichText(style::font font, const QString &text, TextParseOptions options, const TextCustomTagsMap &custom) { QString parsed; parsed.reserve(text.size()); @@ -2449,6 +2460,18 @@ bool Text::hasLinks() const { return !_links.isEmpty(); } +void Text::setSkipBlock(int32 width) { + +} + +void Text::removeSkipBlock() { + +} + +LinksInText Text::calcLinksInText() const { + return LinksInText(); +} + int32 Text::countHeight(int32 w) const { QFixed width = w; if (width < _minResizeWidth) width = _minResizeWidth; diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index 84d7da3aa..6d165bdbd 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -464,6 +464,23 @@ enum TextSelectType { typedef QPair TextCustomTag; // open str and close str typedef QMap TextCustomTagsMap; +enum LinkInTextType { + LinkInTextUrl, + LinkInTextCustomUrl, + LinkInTextEmail, + LinkInTextHashtag, + LinkInTextMention, + LinkInTextBotCommand, +}; +struct LinkInText { + LinkInText(LinkInTextType type, int32 offset, int32 length, const QString &text = QString()) : type(type), offset(offset), length(length), text(text) { + } + LinkInTextType type; + int32 offset, length; + QString text; +}; +typedef QList LinksInText; + class Text { public: @@ -475,6 +492,7 @@ public: int32 countHeight(int32 width) const; void setText(style::font font, const QString &text, const TextParseOptions &options = _defaultOptions); void setRichText(style::font font, const QString &text, TextParseOptions options = _defaultOptions, const TextCustomTagsMap &custom = TextCustomTagsMap()); + void setMarkedText(style::font font, const QString &text, const LinksInText &links); void setLink(uint16 lnkIndex, const TextLinkPtr &lnk); bool hasLinks() const; @@ -482,6 +500,9 @@ public: bool hasSkipBlock() const { return _blocks.isEmpty() ? false : _blocks.back()->type() == TextBlockSkip; } + void setSkipBlock(int32 width); + void removeSkipBlock(); + LinksInText calcLinksInText() const; int32 maxWidth() const { return _maxWidth.ceil().toInt(); @@ -534,6 +555,8 @@ public: private: + void recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir = Qt::LayoutDirectionAuto); + QFixed _minResizeWidth, _maxWidth; int32 _minHeight; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index a486510a7..e19699468 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -943,6 +943,15 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem * } } } + if (adding->hasTextLinks()) { + MediaOverviewType t = OverviewLinks; + if (_overviewIds[t].constFind(adding->id) == _overviewIds[t].cend()) { + _overview[t].push_back(adding->id); + _overviewIds[t].insert(adding->id, NullType()); + if (_overviewCount[t] > 0) ++_overviewCount[t]; + if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, t); + } + } if (adding->from()->id) { if (peer->chat) { QList *lastAuthors = &(peer->asChat()->lastAuthors); @@ -1098,6 +1107,14 @@ void History::addToFront(const QVector &slice) { } } } + if (item->hasTextLinks()) { + MediaOverviewType t = OverviewLinks; + if (_overviewIds[t].constFind(item->id) == _overviewIds[t].cend()) { + _overview[t].push_front(item->id); + _overviewIds[t].insert(item->id, NullType()); + mask |= (1 << t); + } + } if (item->from()->id) { if (lastAuthors) { // chats if (!lastAuthors->contains(item->from())) { @@ -1249,6 +1266,14 @@ void History::addToBack(const QVector &slice) { } } } + if (item->hasTextLinks()) { + MediaOverviewType t = OverviewLinks; + if (_overviewCount[t] != 0) { + _overview[t].push_back(item->id); + _overviewIds[t].insert(item->id, NullType()); + mask |= (1 << t); + } + } } } for (int32 t = 0; t < OverviewCount; ++t) { @@ -1760,6 +1785,9 @@ void HistoryItem::destroy() { history()->eraseFromOverview(OverviewAudioDocuments, id); } } + if (hasTextLinks()) { + history()->eraseFromOverview(OverviewLinks, id); + } delete this; } @@ -4994,13 +5022,14 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPD , _textHeight(0) , _media(0) { + //if (msg.has_entities()) msg.ventities.c_vector().v.size() QString text(textClean(qs(msg.vmessage))); initTime(); initMedia(msg.vmedia, text); - initDimensions(text); + initDimensions(text, msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText()); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const MTPMessageMedia &media) : +HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, const MTPMessageMedia &media) : HistoryItem(history, block, msgId, flags, date, from) , _text(st::msgMinWidth) , _textWidth(0) @@ -5010,10 +5039,10 @@ HistoryItem(history, block, msgId, flags, date, from) QString text(msg); initTime(); initMedia(media, text); - initDimensions(text); + initDimensions(text, links); } -HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, HistoryMedia *fromMedia) : +HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, HistoryMedia *fromMedia) : HistoryItem(history, block, msgId, flags, date, from) , _text(st::msgMinWidth) , _textWidth(0) @@ -5025,7 +5054,7 @@ HistoryItem(history, block, msgId, flags, date, from) _media = fromMedia->clone(); _media->regItem(this); } - initDimensions(msg); + initDimensions(msg, links); } HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, DocumentData *doc) : @@ -5037,7 +5066,7 @@ HistoryItem(history, block, msgId, flags, date, from) { initTime(); initMediaFromDocument(doc); - initDimensions(QString()); + initDimensions(QString(), LinksInText()); } void HistoryMessage::initTime() { @@ -5125,12 +5154,18 @@ void HistoryMessage::initMediaFromDocument(DocumentData *doc) { _media->regItem(this); } -void HistoryMessage::initDimensions(const QString &text) { +void HistoryMessage::initDimensions(const QString &text, const LinksInText &links) { if (!_media || !text.isEmpty()) { // !justMedia() if (_media && _media->isDisplayed()) { - _text.setText(st::msgFont, text, itemTextParseOptions(this)); + _text.setMarkedText(st::msgFont, text, links, itemTextParseOptions(this)); } else { - _text.setText(st::msgFont, text + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), itemTextParseOptions(this)); + _text.setMarkedText(st::msgFont, text + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), links, itemTextParseOptions(this)); + } + for (int32 i = 0, l = links.size(); i != l; ++i) { + if (links.at(i).type == LinkInTextUrl || links.at(i).type == LinkInTextCustomUrl || links.at(i).type == LinkInTextEmail) { + _flags |= MTPDmessage_flag_HAS_TEXT_LINKS; + break; + } } } } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 1379928b5..e07994c8e 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -107,6 +107,7 @@ enum MediaOverviewType { OverviewDocuments, OverviewAudios, OverviewAudioDocuments, + OverviewLinks, OverviewCount }; @@ -116,7 +117,7 @@ inline MediaOverviewType mediaToOverviewType(HistoryMediaType t) { case MediaTypePhoto: return OverviewPhotos; case MediaTypeVideo: return OverviewVideos; case MediaTypeDocument: return OverviewDocuments; - // case MediaTypeSticker: return OverviewDocuments; +// case MediaTypeSticker: return OverviewDocuments; case MediaTypeAudio: return OverviewAudios; } return OverviewCount; @@ -129,6 +130,7 @@ inline MTPMessagesFilter typeToMediaFilter(MediaOverviewType &type) { case OverviewDocuments: return MTP_inputMessagesFilterDocument(); case OverviewAudios: return MTP_inputMessagesFilterAudio(); case OverviewAudioDocuments: return MTP_inputMessagesFilterAudioDocuments(); + case OverviewLinks: return MTP_inputMessagesFilterUrl(); default: type = OverviewCount; break; } return MTPMessagesFilter(); @@ -723,6 +725,9 @@ public: bool hasReplyMarkup() const { return _flags & MTPDmessage::flag_reply_markup; } + bool hasTextLinks() const { + return _flags & MTPDmessage_flag_HAS_TEXT_LINKS; + } virtual bool needCheck() const { return true; } @@ -1274,8 +1279,8 @@ class HistoryMessage : public HistoryItem { public: HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg); - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const MTPMessageMedia &media); - HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, HistoryMedia *media); + HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, const MTPMessageMedia &media); + HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, HistoryMedia *media); HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, DocumentData *doc); void initTime(); @@ -1283,7 +1288,7 @@ public: void initMediaFromText(QString ¤tText); void initMediaFromDocument(DocumentData *doc); void initDimensions(const HistoryItem *parent = 0); - void initDimensions(const QString &text); + void initDimensions(const QString &text, const LinksInText &links); void fromNameUpdated() const; bool justMedia() const { diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.h b/Telegram/SourceFiles/mtproto/mtpConnection.h index 2b600b60f..0ce618f1d 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.h +++ b/Telegram/SourceFiles/mtproto/mtpConnection.h @@ -25,6 +25,7 @@ enum { MTPDmessage_flag_out = (1 << 1), MTPDmessage_flag_notify_by_from = (1 << 4), MTPDmessage_flag_media_unread = (1 << 5), + MTPDmessage_flag_HAS_TEXT_LINKS = (1 << 31), // client side flag for having links MTPmessages_SendMessage_flag_skipWebPage = (1 << 1),