From 70f3568e1623fdce5e1b9d151d1422ac569ea4f6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 8 Apr 2015 02:03:32 +0300 Subject: [PATCH] version 0.8.2.dev ready --- Telegram/PrepareWin.bat | 8 +- Telegram/Resources/style.txt | 2 +- Telegram/SourceFiles/apiwrap.cpp | 2 +- Telegram/SourceFiles/app.cpp | 41 +--- Telegram/SourceFiles/app.h | 3 +- Telegram/SourceFiles/application.cpp | 6 +- Telegram/SourceFiles/boxes/passcodebox.cpp | 4 +- Telegram/SourceFiles/config.h | 4 +- Telegram/SourceFiles/gui/emoji_config.h | 2 +- Telegram/SourceFiles/gui/flatinput.cpp | 13 +- Telegram/SourceFiles/gui/flatinput.h | 3 +- Telegram/SourceFiles/gui/text.cpp | 28 ++- Telegram/SourceFiles/gui/text.h | 21 +- Telegram/SourceFiles/history.cpp | 233 +++++++++++++------ Telegram/SourceFiles/history.h | 18 +- Telegram/SourceFiles/historywidget.cpp | 37 ++- Telegram/SourceFiles/historywidget.h | 2 + Telegram/SourceFiles/intro/intropwdcheck.cpp | 2 +- Telegram/SourceFiles/mainwidget.cpp | 54 +++-- Telegram/SourceFiles/mainwidget.h | 9 +- Telegram/SourceFiles/overviewwidget.cpp | 8 +- Telegram/Telegram.plist | 2 +- Telegram/Telegram.rc | Bin 5532 -> 5532 bytes Telegram/Telegram.xcodeproj/project.pbxproj | 12 +- Telegram/Version.sh | 2 +- 25 files changed, 326 insertions(+), 190 deletions(-) diff --git a/Telegram/PrepareWin.bat b/Telegram/PrepareWin.bat index 01c84cfb4..f0206b843 100644 --- a/Telegram/PrepareWin.bat +++ b/Telegram/PrepareWin.bat @@ -1,9 +1,9 @@ @echo OFF -set "AppVersion=8001" -set "AppVersionStrSmall=0.8.1" -set "AppVersionStr=0.8.1" -set "AppVersionStrFull=0.8.1.0" +set "AppVersion=8002" +set "AppVersionStrSmall=0.8.2" +set "AppVersionStr=0.8.2" +set "AppVersionStrFull=0.8.2.0" set "DevChannel=1" if %DevChannel% neq 0 goto preparedev diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 4f1833d9f..010b66b0f 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -984,7 +984,7 @@ btnAttachEmoji: iconedButton(btnAttachDocument) { width: 32px; } -replySkip: 52px; +replySkip: 51px; replyColor: #377aae; replyHeight: 49px; replyTop: 8px; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 106aef844..9640de333 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -262,7 +262,7 @@ void ApiWrap::gotWebPages(const MTPmessages_Messages &msgs, mtpRequestId req) { } const WebPageItems &items(App::webPageItems()); - for (WebPagesPending::iterator i = _webPagesPending.begin(); i != _webPagesPending.cend(); ++i) { + for (WebPagesPending::iterator i = _webPagesPending.begin(); i != _webPagesPending.cend();) { if (i.value() == req) { if (i.key()->pendingTill > 0) { i.key()->pendingTill = -1; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 7cf0d78bf..5641b061d 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -747,19 +747,6 @@ namespace App { } } - void feedMessageMedia(MsgId msgId, const MTPMessage &msg) { - const MTPMessageMedia *media = 0; - switch (msg.type()) { - case mtpc_message: media = &msg.c_message().vmedia; break; - } - if (media) { - MsgsData::iterator i = msgsData.find(msgId); - if (i != msgsData.cend()) { - i.value()->updateMedia(*media); - } - } - } - PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert) { switch (photo.type()) { case mtpc_photo: { @@ -906,7 +893,7 @@ namespace App { } WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) { - return App::webPage(webpage.vid.v, convert, webpage.has_type() ? qs(webpage.vtype) : qsl("article"), qs(webpage.vurl), qs(webpage.vdisplay_url), webpage.has_site_name() ? qs(webpage.vsite_name) : QString(), webpage.has_title() ? qs(webpage.vtitle) : QString(), webpage.has_description() ? qs(webpage.vdescription) : QString(), webpage.has_photo() ? App::feedPhoto(webpage.vphoto) : 0, webpage.has_duration() ? webpage.vduration.v : 0, webpage.has_author() ? qs(webpage.vauthor) : QString()); + return App::webPage(webpage.vid.v, convert, webpage.has_type() ? qs(webpage.vtype) : qsl("article"), qs(webpage.vurl), qs(webpage.vdisplay_url), webpage.has_site_name() ? qs(webpage.vsite_name) : QString(), webpage.has_title() ? qs(webpage.vtitle) : QString(), webpage.has_description() ? qs(webpage.vdescription) : QString(), webpage.has_photo() ? App::feedPhoto(webpage.vphoto) : 0, webpage.has_duration() ? webpage.vduration.v : 0, webpage.has_author() ? qs(webpage.vauthor) : QString(), 0); } WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert) { @@ -1211,7 +1198,7 @@ namespace App { } convert->id = webPage; } - if ((convert->url.isEmpty() && !url.isEmpty()) || (convert->pendingTill && convert->pendingTill != pendingTill)) { + if ((convert->url.isEmpty() && !url.isEmpty()) || (convert->pendingTill && convert->pendingTill != pendingTill && pendingTill >= -1)) { convert->type = toWebPageType(type); convert->url = url; convert->displayUrl = displayUrl; @@ -1223,15 +1210,7 @@ namespace App { convert->author = author; if (convert->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(convert); convert->pendingTill = pendingTill; - - MainWidget *m = App::main(); - WebPageItems::const_iterator j = ::webPageItems.constFind(convert); - if (j != ::webPageItems.cend()) { - for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) { - k.key()->initDimensions(); - if (m) m->itemResized(k.key()); - } - } + if (App::main()) App::main()->webPageUpdated(convert); } } WebPagesData::const_iterator i = webPagesData.constFind(webPage); @@ -1240,7 +1219,7 @@ namespace App { if (convert) { result = convert; } else { - result = new WebPageData(webPage, toWebPageType(type), url, displayUrl, siteName, title, description, photo, duration, author, pendingTill); + result = new WebPageData(webPage, toWebPageType(type), url, displayUrl, siteName, title, description, photo, duration, author, (pendingTill >= -1) ? pendingTill : -1); if (pendingTill > 0 && api()) { api()->requestWebPageDelayed(result); } @@ -1249,7 +1228,7 @@ namespace App { } else { result = i.value(); if (result != convert) { - if ((result->url.isEmpty() && !url.isEmpty()) || (result->pendingTill && result->pendingTill != pendingTill)) { + if ((result->url.isEmpty() && !url.isEmpty()) || (result->pendingTill && result->pendingTill != pendingTill && pendingTill >= -1)) { result->type = toWebPageType(type); result->url = url; result->displayUrl = displayUrl; @@ -1261,15 +1240,7 @@ namespace App { result->author = author; if (result->pendingTill > 0 && pendingTill <= 0 && api()) api()->clearWebPageRequest(result); result->pendingTill = pendingTill; - - MainWidget *m = App::main(); - WebPageItems::const_iterator j = ::webPageItems.constFind(result); - if (j != ::webPageItems.cend()) { - for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) { - k.key()->initDimensions(); - if (m) m->itemResized(k.key()); - } - } + if (App::main()) App::main()->webPageUpdated(result); } } } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index c0187c256..2dc5a103f 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -84,7 +84,6 @@ namespace App { void feedWereDeleted(const QVector &msgsIds); void feedUserLinks(const MTPVector &links); void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink); - void feedMessageMedia(MsgId msgId, const MTPMessage &msg); int32 maxMsgId(); ImagePtr image(const MTPPhotoSize &size); @@ -119,7 +118,7 @@ namespace App { VideoData *video(const VideoId &video, VideoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); AudioData *audio(const AudioId &audio, AudioData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0); DocumentData *document(const DocumentId &document, DocumentData *convert = 0, const uint64 &access = 0, int32 date = 0, const QVector &attributes = QVector(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); - WebPageData *webPage(const WebPageId &webPage, WebPageData *convert = 0, const QString &type = QString(), const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = 0); + WebPageData *webPage(const WebPageId &webPage, WebPageData *convert = 0, const QString &type = QString(), const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = -2); ImageLinkData *imageLink(const QString &imageLink, ImageLinkType type = InvalidImageLink, const QString &url = QString()); void forgetMedia(); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 114375ddd..33c88235a 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -654,9 +654,9 @@ void Application::checkMapVersion() { psRegisterCustomScheme(); if (Local::oldMapVersion()) { QString versionFeatures; - if (DevChannel && Local::oldMapVersion() < 8001) { - versionFeatures = QString::fromUtf8("\xe2\x80\x94 Link previews for Twitter, YouTube, Instagram and certain other links\n\xe2\x80\x94 Two-step verification\n\xe2\x80\x94 View all your Telegram sessions, terminate specific sessions\n\xe2\x80\x94 Text is pasted from clipboard when clipboard has both text and image and image sending was cancelled").replace('@', qsl("@") + QChar(0x200D)); - } else if (!DevChannel && Local::oldMapVersion() < 8002) { + if (DevChannel && Local::oldMapVersion() < 8002) { + versionFeatures = QString::fromUtf8("\xe2\x80\x94 Link previews bugfixes\n\xe2\x80\x94 Links in preview descriptions are now clickable\n\xe2\x80\x94 Twitter and Instagram mentions and hashtags in previews are clickable\n\xe2\x80\x94 Fixed file uploading\n\xe2\x80\x94 Fixed photo, document and sticker forwarding").replace('@', qsl("@") + QChar(0x200D)); + } else if (!DevChannel && Local::oldMapVersion() < 8003) { versionFeatures = lang(lng_new_version_text).trimmed(); } if (!versionFeatures.isEmpty()) { diff --git a/Telegram/SourceFiles/boxes/passcodebox.cpp b/Telegram/SourceFiles/boxes/passcodebox.cpp index fba856c10..0dad83ccc 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.cpp +++ b/Telegram/SourceFiles/boxes/passcodebox.cpp @@ -459,7 +459,7 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) { } RecoverBox::RecoverBox(const QString &pattern) : -_submitRequest(0), _pattern(lng_signin_recover_hint(lt_recover_email, pattern)), +_submitRequest(0), _pattern(st::usernameFont->m.elidedText(lng_signin_recover_hint(lt_recover_email, pattern), Qt::ElideRight, st::boxWidth - st::addContactPadding.left() - st::addContactPadding.right())), _saveButton(this, lang(lng_passcode_submit), st::btnSelectDone), _cancelButton(this, lang(lng_cancel), st::btnSelectCancel), _recoverCode(this, st::inpAddContact, lang(lng_signin_code)) { @@ -509,7 +509,7 @@ void RecoverBox::paintEvent(QPaintEvent *e) { p.setFont(st::usernameFont->f); int32 w = width() - st::addContactPadding.left() - st::addContactPadding.right(); - p.drawText(QRect(st::addContactPadding.left(), _recoverCode.y() - st::usernameSkip - st::addContactPadding.top(), w, st::addContactPadding.top() + st::usernameSkip), st::usernameFont->m.elidedText(_pattern, Qt::ElideRight, w), style::al_center); + p.drawText(QRect(st::addContactPadding.left(), _recoverCode.y() - st::usernameSkip - st::addContactPadding.top(), w, st::addContactPadding.top() + st::usernameSkip), _pattern, style::al_center); if (!_error.isEmpty()) { p.setPen(st::setErrColor->p); diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 81bfa0668..d8b9d2482 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 8001; -static const wchar_t *AppVersionStr = L"0.8.1"; +static const int32 AppVersion = 8002; +static const wchar_t *AppVersionStr = L"0.8.2"; static const bool DevChannel = true; static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)"; diff --git a/Telegram/SourceFiles/gui/emoji_config.h b/Telegram/SourceFiles/gui/emoji_config.h index 543be3ba6..757859d49 100644 --- a/Telegram/SourceFiles/gui/emoji_config.h +++ b/Telegram/SourceFiles/gui/emoji_config.h @@ -40,7 +40,7 @@ inline bool emojiEdge(const QChar *ch) { inline QString replaceEmojis(const QString &text) { QString result; - LinkRanges lnkRanges = textParseLinks(text); + LinkRanges lnkRanges = textParseLinks(text, TextParseLinks | TextParseMentions | TextParseHashtags); int32 currentLink = 0, lnkCount = lnkRanges.size(); const QChar *emojiStart = text.unicode(), *emojiEnd = emojiStart, *e = text.cend(); bool canFindEmoji = true, consumePrevious = false; diff --git a/Telegram/SourceFiles/gui/flatinput.cpp b/Telegram/SourceFiles/gui/flatinput.cpp index 30689d52d..e2432d844 100644 --- a/Telegram/SourceFiles/gui/flatinput.cpp +++ b/Telegram/SourceFiles/gui/flatinput.cpp @@ -42,15 +42,13 @@ namespace { FlatInputStyle _flatInputStyle; } -FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent), _oldtext(v), _kev(0), _customUpDown(false), _phVisible(!v.length()), +FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent), _fullph(pholder), _oldtext(v), _kev(0), _customUpDown(false), _phVisible(!v.length()), a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c), a_borderColor(st.borderColor->c), a_bgColor(st.bgColor->c), _notingBene(0), _st(st) { resize(_st.width, _st.height); setFont(_st.font->f); setAlignment(_st.align); - - _ph = _st.font->m.elidedText(pholder, Qt::ElideRight, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1); QPalette p(palette()); p.setColor(QPalette::Text, _st.textColor->c); @@ -184,6 +182,15 @@ void FlatInput::focusOutEvent(QFocusEvent *e) { emit blurred(); } +void FlatInput::resizeEvent(QResizeEvent *e) { + int32 availw = width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1; + if (_st.font->m.width(_fullph) > availw) { + _ph = _st.font->m.elidedText(_fullph, Qt::ElideRight, availw); + } else { + _ph = _fullph; + } +} + QSize FlatInput::sizeHint() const { return geometry().size(); } diff --git a/Telegram/SourceFiles/gui/flatinput.h b/Telegram/SourceFiles/gui/flatinput.h index d219152bf..b0502c7a1 100644 --- a/Telegram/SourceFiles/gui/flatinput.h +++ b/Telegram/SourceFiles/gui/flatinput.h @@ -34,6 +34,7 @@ public: void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); void keyPressEvent(QKeyEvent *e); + void resizeEvent(QResizeEvent *e); void notaBene(); @@ -69,7 +70,7 @@ protected: private: - QString _ph, _oldtext; + QString _ph, _fullph, _oldtext; QKeyEvent *_kev; bool _customUpDown; diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 66aec9b1b..9ac74f9cb 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -547,7 +547,7 @@ public: end = start + src.size(); if (options.flags & TextParseLinks) { - lnkRanges = textParseLinks(src, rich); + lnkRanges = textParseLinks(src, options.flags, rich); } while (start != end && chIsTrimmed(*start, rich)) { @@ -593,9 +593,21 @@ public: const TextLinkData &data(links[lnkIndex - maxLnkIndex - 1]); TextLinkPtr lnk; if (data.fullDisplayed < -2) { // mention - lnk = TextLinkPtr(new MentionLink(data.url)); + if (options.flags & TextTwitterMentions) { + lnk = TextLinkPtr(new TextLink(qsl("https://twitter.com/") + data.url.mid(1), true)); + } else if (options.flags & TextInstagramMentions) { + lnk = TextLinkPtr(new TextLink(qsl("https://instagram.com/") + data.url.mid(1) + '/', true)); + } else { + lnk = TextLinkPtr(new MentionLink(data.url)); + } } else if (data.fullDisplayed < -1) { // hashtag - lnk = TextLinkPtr(new HashtagLink(data.url)); + if (options.flags & TextTwitterMentions) { + lnk = TextLinkPtr(new TextLink(qsl("https://twitter.com/hashtag/") + data.url.mid(1) + qsl("?src=hash"), true)); + } else if (options.flags & TextInstagramMentions) { + lnk = TextLinkPtr(new TextLink(qsl("https://instagram.com/explore/tags/") + data.url.mid(1) + '/', true)); + } else { + lnk = TextLinkPtr(new HashtagLink(data.url)); + } } else if (data.fullDisplayed < 0) { // email lnk = TextLinkPtr(new EmailLink(data.url)); } else { @@ -3993,7 +4005,7 @@ QString textSearchKey(const QString &text) { bool textSplit(QString &sendingText, QString &leftText, int32 limit) { if (leftText.isEmpty() || !limit) return false; - LinkRanges lnkRanges = textParseLinks(leftText); + LinkRanges lnkRanges = textParseLinks(leftText, TextParseLinks | TextParseMentions | TextParseHashtags); int32 currentLink = 0, lnkCount = lnkRanges.size(); int32 s = 0, half = limit / 2, goodLevel = 0; @@ -4070,9 +4082,11 @@ bool textSplit(QString &sendingText, QString &leftText, int32 limit) { return true; } -LinkRanges textParseLinks(const QString &text, bool rich) { // some code is duplicated in flattextarea.cpp! +LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some code is duplicated in flattextarea.cpp! LinkRanges lnkRanges; + bool withHashtags = (flags & TextParseHashtags), withMentions = (flags & TextParseMentions); + initLinkSets(); int32 len = text.size(), nextCmd = rich ? 0 : len; const QChar *start = text.unicode(), *end = start + text.size(); @@ -4086,8 +4100,8 @@ LinkRanges textParseLinks(const QString &text, bool rich) { // some code is dupl } QRegularExpressionMatch mDomain = _reDomain.match(text, matchOffset); QRegularExpressionMatch mExplicitDomain = _reExplicitDomain.match(text, matchOffset); - QRegularExpressionMatch mHashtag = _reHashtag.match(text, matchOffset); - QRegularExpressionMatch mMention = _reMention.match(text, matchOffset); + QRegularExpressionMatch mHashtag = withHashtags ? _reHashtag.match(text, matchOffset) : QRegularExpressionMatch(); + QRegularExpressionMatch mMention = withMentions ? _reMention.match(text, matchOffset) : QRegularExpressionMatch(); if (!mDomain.hasMatch() && !mExplicitDomain.hasMatch() && !mHashtag.hasMatch() && !mMention.hasMatch()) break; LinkRange link; diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index e9b42e3d5..0de70f355 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -25,6 +25,19 @@ QString textAccentFold(const QString &text); QString textSearchKey(const QString &text); bool textSplit(QString &sendingText, QString &leftText, int32 limit); +enum { + TextParseMultiline = 0x001, + TextParseLinks = 0x002, + TextParseRichText = 0x004, + TextParseMentions = 0x008, + TextParseHashtags = 0x010, + + TextTwitterMentions = 0x020, + TextTwitterHashtags = 0x040, + TextInstagramMentions = 0x080, + TextInstagramHashtags = 0x100, +}; + struct LinkRange { LinkRange() : from(0), len(0) { } @@ -32,7 +45,7 @@ struct LinkRange { int32 len; }; typedef QVector LinkRanges; -LinkRanges textParseLinks(const QString &text, bool rich = false); +LinkRanges textParseLinks(const QString &text, int32 flags, bool rich = false); #include "gui/emoji_config.h" @@ -387,12 +400,6 @@ enum TextCommands { TextCommandLangTag = 0x20, }; -enum { - TextParseMultiline = 0x01, - TextParseLinks = 0x02, - TextParseRichText = 0x04, -}; - struct TextParseOptions { int32 flags; int32 maxw; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index ca81865d6..0f24e7460 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -44,13 +44,13 @@ TextParseOptions _textDlgOptions = { namespace { TextParseOptions _historyTextOptions = { - TextParseLinks | TextParseMultiline | TextParseRichText, // flags + TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText, // flags 0, // maxw 0, // maxh Qt::LayoutDirectionAuto, // dir }; TextParseOptions _historySrvOptions = { - TextParseLinks | TextParseMultiline | TextParseRichText, // flags + TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText, // flags 0, // maxw 0, // maxh Qt::LayoutDirectionAuto, // lang-dependent @@ -62,7 +62,19 @@ namespace { Qt::LayoutDirectionAuto, // dir }; TextParseOptions _webpageDescriptionOptions = { - /*TextParseLinks | */TextParseMultiline | TextParseRichText, // flags + TextParseLinks | TextParseMultiline | TextParseRichText, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir + }; + TextParseOptions _twitterDescriptionOptions = { + TextParseLinks | TextParseMentions | TextTwitterMentions | TextParseHashtags | TextTwitterHashtags | TextParseMultiline | TextParseRichText, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir + }; + TextParseOptions _instagramDescriptionOptions = { + TextParseLinks | TextParseMentions | TextInstagramMentions | TextParseHashtags | TextInstagramHashtags | TextParseMultiline | TextParseRichText, // flags 0, // maxw 0, // maxh Qt::LayoutDirectionAuto, // dir @@ -718,7 +730,17 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, boo } break; } - return regItem(result, returnExisting); + HistoryItem *existing = regItem(result, true); + if (existing && result != existing) { + const MTPMessageMedia *media = 0; + switch (msg.type()) { + case mtpc_message: media = &msg.c_message().vmedia; break; + } + if (media) { + existing->updateMedia(*media); + } + } + return (returnExisting || existing == result) ? existing : 0; } HistoryItem *History::createItemForwarded(HistoryBlock *block, MsgId id, HistoryMessage *msg) { @@ -1710,8 +1732,10 @@ bool HistoryPhoto::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 w return (x >= 0 && y >= 0 && x < width && y < _height); } -TextLinkPtr HistoryPhoto::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryPhoto::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; + if (width < 1) return; + int skipx = 0, skipy = 0, height = _height; if (const HistoryReply *reply = toHistoryReply(parent)) { skipx = st::mediaPadding.left(); @@ -1722,18 +1746,20 @@ TextLinkPtr HistoryPhoto::getLink(int32 x, int32 y, const HistoryItem *parent, i replyFrom = st::msgPadding.top() + st::msgNameFont->height; skipy += replyFrom; if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - return parent->from()->lnk; + lnk = parent->from()->lnk; + return; } } if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom() - st::mediaPadding.top()) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } width -= st::mediaPadding.left() + st::mediaPadding.right(); } if (x >= skipx && y >= skipy && x < skipx + width && y < height) { - return openl; + lnk = openl; + return; } - return TextLinkPtr(); } HistoryMedia *HistoryPhoto::clone() const { @@ -1984,9 +2010,9 @@ bool HistoryVideo::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 w return (x >= 0 && y >= 0 && x < width && y < _height); } -TextLinkPtr HistoryVideo::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryVideo::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; - if (width < 1) return TextLinkPtr(); + if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); int skipy = 0, replyFrom = 0; @@ -2006,7 +2032,8 @@ TextLinkPtr HistoryVideo::getLink(int32 x, int32 y, const HistoryItem *parent, i if (!out) { // draw Download / Save As button int32 btnw = _buttonWidth, btnh = st::mediaSaveButton.height, btnx = width - _buttonWidth, btny = skipy + (_height - skipy - btnh) / 2; if (x >= btnx && y >= btny && x < btnx + btnw && y < btny + btnh) { - return data->loader ? _cancell : _savel; + lnk = data->loader ? _cancell : _savel; + return; } width -= btnw + st::mediaSaveDelta; } @@ -2014,18 +2041,20 @@ TextLinkPtr HistoryVideo::getLink(int32 x, int32 y, const HistoryItem *parent, i if (reply) { if (!parent->out() && parent->history()->peer->chat) { if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - return parent->from()->lnk; + lnk = parent->from()->lnk; + return; } } if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } } if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { - return _openl; + lnk = _openl; + return; } - return TextLinkPtr(); } HistoryMedia *HistoryVideo::clone() const { @@ -2367,9 +2396,9 @@ bool HistoryAudio::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 w return (x >= 0 && y >= 0 && x < width && y < _height); } -TextLinkPtr HistoryAudio::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryAudio::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; - if (width < 1) return TextLinkPtr(); + if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); int skipy = 0, replyFrom = 0; @@ -2389,7 +2418,8 @@ TextLinkPtr HistoryAudio::getLink(int32 x, int32 y, const HistoryItem *parent, i if (!out) { // draw Download / Save As button int32 btnw = _buttonWidth, btnh = st::mediaSaveButton.height, btnx = width - _buttonWidth, btny = skipy + (_height - skipy - btnh) / 2; if (x >= btnx && y >= btny && x < btnx + btnw && y < btny + btnh) { - return data->loader ? _cancell : _savel; + lnk = data->loader ? _cancell : _savel; + return; } width -= btnw + st::mediaSaveDelta; } @@ -2397,18 +2427,20 @@ TextLinkPtr HistoryAudio::getLink(int32 x, int32 y, const HistoryItem *parent, i if (reply) { if (!parent->out() && parent->history()->peer->chat) { if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - return parent->from()->lnk; + lnk = parent->from()->lnk; + return; } } if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } } if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { - return _openl; + lnk = _openl; + return; } - return TextLinkPtr(); } HistoryMedia *HistoryAudio::clone() const { @@ -2689,9 +2721,9 @@ int32 HistoryDocument::countHeight(const HistoryItem *parent, int32 width) const return _height; } -TextLinkPtr HistoryDocument::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryDocument::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; - if (width < 1) return TextLinkPtr(); + if (width < 1) return; bool out = parent->out(), hovered, pressed; if (width >= _maxw) { @@ -2700,7 +2732,8 @@ TextLinkPtr HistoryDocument::getLink(int32 x, int32 y, const HistoryItem *parent if (parent == animated.msg) { int32 h = (width == w) ? _height : (width * animated.h / animated.w); if (h < 1) h = 1; - return (x >= 0 && y >= 0 && x < width && y < h) ? _openl : TextLinkPtr(); + lnk = (x >= 0 && y >= 0 && x < width && y < h) ? _openl : TextLinkPtr(); + return; } const HistoryReply *reply = toHistoryReply(parent); @@ -2716,7 +2749,8 @@ TextLinkPtr HistoryDocument::getLink(int32 x, int32 y, const HistoryItem *parent if (!out) { // draw Download / Save As button int32 btnw = _buttonWidth, btnh = st::mediaSaveButton.height, btnx = width - _buttonWidth, btny = skipy + (_height - skipy - btnh) / 2; if (x >= btnx && y >= btny && x < btnx + btnw && y < btny + btnh) { - return data->loader ? _cancell : _savel; + lnk = data->loader ? _cancell : _savel; + return; } width -= btnw + st::mediaSaveDelta; } @@ -2724,18 +2758,20 @@ TextLinkPtr HistoryDocument::getLink(int32 x, int32 y, const HistoryItem *parent if (reply) { if (!parent->out() && parent->history()->peer->chat) { if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - return parent->from()->lnk; + lnk = parent->from()->lnk; + return; } } if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } } if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { - return _openl; + lnk = _openl; + return; } - return TextLinkPtr(); } HistoryMedia *HistoryDocument::clone() const { @@ -2926,9 +2962,10 @@ int32 HistorySticker::countHeight(const HistoryItem *parent, int32 width) const return _minh; } -TextLinkPtr HistorySticker::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistorySticker::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; - if (width < 1) return TextLinkPtr(); + if (width < 1) return; + if (width > _maxw) width = _maxw; int32 usew = _maxw, usex = 0; @@ -2938,10 +2975,10 @@ TextLinkPtr HistorySticker::getLink(int32 x, int32 y, const HistoryItem *parent, int32 rw = width - usew, rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); int32 rx = parent->out() ? 0 : usew, ry = _height - rh; if (x >= rx && y >= ry && x < rx + rw && y < ry + rh) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } } - return TextLinkPtr(); } HistoryMedia *HistorySticker::clone() const { @@ -3002,7 +3039,7 @@ bool HistoryContact::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 return (x >= 0 && y <= 0 && x < w && y < _height); } -TextLinkPtr HistoryContact::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryContact::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; const HistoryReply *reply = toHistoryReply(parent); @@ -3018,18 +3055,20 @@ TextLinkPtr HistoryContact::getLink(int32 x, int32 y, const HistoryItem *parent, if (reply) { if (!parent->out() && parent->history()->peer->chat) { if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - return parent->from()->lnk; + lnk = parent->from()->lnk; + return; } } if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } } if (x >= 0 && y >= skipy && x < w && y < _height && contact) { - return contact->lnk; + lnk = contact->lnk; + return; } - return TextLinkPtr(); } HistoryMedia *HistoryContact::clone() const { @@ -3214,16 +3253,22 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { _maxw = qMax(_maxw, int32(st::webPageLeft + _title.maxWidth() + st::webPagePhotoDelta + st::webPagePhotoSize)); } else { _maxw = qMax(_maxw, int32(st::webPageLeft + _title.maxWidth() + parent->timeWidth())); - _minh += st::webPageTitleFont->height; + _minh += qMin(_title.minHeight(), 2 * st::webPageTitleFont->height); } } if (!data->description.isEmpty()) { - _description.setText(st::webPageDescriptionFont, textClean(data->description), _webpageDescriptionOptions); + if (data->siteName == QLatin1String("Twitter")) { + _description.setText(st::webPageDescriptionFont, textClean(data->description), _twitterDescriptionOptions); + } else if (data->siteName == QLatin1String("Instagram")) { + _description.setText(st::webPageDescriptionFont, textClean(data->description), _instagramDescriptionOptions); + } else { + _description.setText(st::webPageDescriptionFont, textClean(data->description), _webpageDescriptionOptions); + } if (_asArticle) { _maxw = qMax(_maxw, int32(st::webPageLeft + _description.maxWidth() + st::webPagePhotoDelta + st::webPagePhotoSize)); } else { _maxw = qMax(_maxw, int32(st::webPageLeft + _description.maxWidth() + parent->timeWidth())); - _minh += st::webPageTitleFont->height; + _minh += qMin(_description.minHeight(), 3 * st::webPageTitleFont->height); } } if (!_asArticle && data->photo && (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty())) { @@ -3505,33 +3550,63 @@ bool HistoryWebPage::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 return (x >= 0 && y >= 0 && x < width && y < _height); } -TextLinkPtr HistoryWebPage::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryWebPage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; - if (width < 1) return TextLinkPtr(); + if (width < 1) return; - TextLinkPtr result = (x >= 0 && y >= 0 && x < width && y < _height) ? _openl : TextLinkPtr(); - if (_photol) { - width -= st::webPageLeft; + width -= st::webPageLeft; + x -= st::webPageLeft; - if (_siteNameWidth) { - y -= st::webPageTitleFont->height; - } - if (!_title.isEmpty()) { - y -= qMin(_title.countHeight(width), st::webPageTitleFont->height * 2); - } - if (!_description.isEmpty()) { - y -= qMin(_description.countHeight(width), st::webPageDescriptionFont->height * 3); - } - if (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty()) { - y -= st::webPagePhotoSkip; - } - - int32 pixwidth = qMax(_pixw, int16(st::minPhotoSize)), pixheight = qMax(_pixh, int16(st::minPhotoSize)); - if (x >= 0 && y >= 0 && x < pixwidth && y < pixheight) { - return _photol; + if (_asArticle) { + int32 pixwidth = st::webPagePhotoSize, pixheight = st::webPagePhotoSize; + if (x >= width - pixwidth && x < width && y >= 0 && y < pixheight) { + lnk = _openl; + return; + } + } + int32 articleLines = 5; + if (_siteNameWidth) { + y -= st::webPageTitleFont->height; + --articleLines; + } + if (!_title.isEmpty()) { + int32 availw = width; + if (_asArticle) { + availw -= st::webPagePhotoSize + st::webPagePhotoDelta; + } + int32 h = _title.countHeight(availw); + if (h > st::webPageTitleFont->height) { + articleLines -= 2; + y -= st::webPageTitleFont->height * 2; + } else { + --articleLines; + y -= h; + } + } + if (!_description.isEmpty()) { + int32 availw = width; + if (_asArticle) { + availw -= st::webPagePhotoSize + st::webPagePhotoDelta; + if (articleLines > 3) articleLines = 3; + } else if (!data->photo) { + articleLines = 3; + } + if (y >= 0 && y < st::webPageDescriptionFont->height * articleLines) { + _description.getState(lnk, inText, x, y, availw); + return; + } + y -= qMin(_description.countHeight(width), st::webPageDescriptionFont->height * articleLines); + } + if (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty()) { + y -= st::webPagePhotoSkip; + } + if (!_asArticle) { + int32 pixwidth = qMax(_pixw, int16(st::minPhotoSize)), pixheight = qMax(_pixh, int16(st::minPhotoSize)); + if (x >= 0 && y >= 0 && x < pixwidth && y < pixheight) { + lnk = _photol ? _photol : _openl; + return; } } - return result; } HistoryMedia *HistoryWebPage::clone() const { @@ -4150,7 +4225,7 @@ bool HistoryImageLink::hasPoint(int32 x, int32 y, const HistoryItem *parent, int return (x >= 0 && y >= 0 && x < width && y < _height); } -TextLinkPtr HistoryImageLink::getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryImageLink::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const { if (width < 0) width = w; int skipx = 0, skipy = 0, height = _height; if (const HistoryReply *reply = toHistoryReply(parent)) { @@ -4162,18 +4237,20 @@ TextLinkPtr HistoryImageLink::getLink(int32 x, int32 y, const HistoryItem *paren replyFrom = st::msgPadding.top() + st::msgNameFont->height; skipy += replyFrom; if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - return parent->from()->lnk; + lnk = parent->from()->lnk; + return; } } if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom() - st::mediaPadding.top()) { - return reply->replyToLink(); + lnk = reply->replyToLink(); + return; } width -= st::mediaPadding.left() + st::mediaPadding.right(); } if (x >= skipx && y >= skipy && x < skipx + width && y < height && data) { - return link; + lnk = link; + return; } - return TextLinkPtr(); } HistoryMedia *HistoryImageLink::clone() const { @@ -4366,7 +4443,11 @@ HistoryMedia *HistoryMessage::getMedia(bool inOverview) const { } void HistoryMessage::setMedia(const MTPmessageMedia &media) { - if (_media) return; + if (!_media && media.type() == mtpc_messageMediaEmpty) return; + if (_media) { + delete _media; + _media = 0; + } QString t; initMedia(media, t); if (_media) { @@ -4578,7 +4659,7 @@ void HistoryMessage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) width = _maxw; } if (justMedia()) { - lnk = _media->getLink(x - left, y - st::msgMargin.top(), this); + _media->getState(lnk, inText, x - left, y - st::msgMargin.top(), this); return; } QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom()); @@ -4593,12 +4674,12 @@ void HistoryMessage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) TextLinkPtr medialnk; if (_media) { if (y >= trect.bottom() - _media->height() && y < trect.bottom()) { - medialnk = _media->getLink(x - trect.left(), y + _media->height() - trect.bottom(), this); + _media->getState(lnk, inText, x - trect.left(), y + _media->height() - trect.bottom(), this); + return; } trect.setBottom(trect.bottom() - _media->height() - st::msgPadding.bottom()); } _text.getState(lnk, inText, x - trect.x(), y - trect.y(), trect.width()); - if (!lnk && medialnk) lnk = medialnk; } void HistoryMessage::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { @@ -4691,7 +4772,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const fwdNameUpdated(); } -HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, (history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0, ::date(unixtime()), MTP::authedId(), msg->HistoryMessage::selectedText(FullItemSel), msg->getMedia()) +HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, (history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0, ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->getMedia()) , fwdDate(msg->dateForwarded()) , fwdFrom(msg->fromForwarded()) , fwdFromVersion(fwdFrom->nameVersion) @@ -5371,7 +5452,7 @@ void HistoryServiceMsg::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 return _text.getState(lnk, inText, x - trect.x(), y - trect.y(), trect.width(), Qt::AlignCenter); } if (_media) { - lnk = _media->getLink(x - st::msgServiceMargin.left() - (width - _media->maxWidth()) / 2, y - st::msgServiceMargin.top() - height - st::msgServiceMargin.top(), this); + _media->getState(lnk, inText, x - st::msgServiceMargin.left() - (width - _media->maxWidth()) / 2, y - st::msgServiceMargin.top() - height - st::msgServiceMargin.top(), this); } } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 3a90b5a1e..642a53c4b 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -786,7 +786,7 @@ public: w = qMin(width, _maxw); return _height; } - virtual TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; + virtual void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; virtual void draw(QPainter &p, const HistoryItem *parent, bool selected, int32 width = -1) const = 0; virtual bool uploading() const { return false; @@ -844,7 +844,7 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; HistoryMedia *clone() const; PhotoData *photo() const { @@ -889,7 +889,7 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; bool uploading() const { return (data->status == FileUploading); } @@ -927,7 +927,7 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; bool uploading() const { return (data->status == FileUploading); } @@ -964,7 +964,7 @@ public: bool uploading() const { return (data->status == FileUploading); } - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; HistoryMedia *clone() const; DocumentData *document() { @@ -1009,7 +1009,7 @@ public: const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; int32 countHeight(const HistoryItem *parent, int32 width = -1) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; HistoryMedia *clone() const; DocumentData *document() { @@ -1044,7 +1044,7 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const; HistoryMedia *clone() const; void updateFrom(const MTPMessageMedia &media); @@ -1071,7 +1071,7 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; HistoryMedia *clone() const; void regItem(HistoryItem *item); @@ -1164,7 +1164,7 @@ public: const QString inDialogsText() const; const QString inHistoryText() const; bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; HistoryMedia *clone() const; private: diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 766c20935..f01f53f7d 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -1567,6 +1567,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : QWidget(parent) , _previewData(0) , _previewRequest(0) , _previewCancelled(false) +, _replyForwardPressed(false) , _replyReturn(0) , _lastStickersUpdate(0) , _stickersUpdateRequest(0) @@ -2573,7 +2574,8 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) { App::main()->readServerHistory(hist, false); hist->loadAround(0); - App::main()->sendPreparedText(hist, text, replyTo, _previewCancelled); + WebPageId webPageId = _previewCancelled ? 0xFFFFFFFFFFFFFFFFULL : ((_previewData && _previewData->pendingTill >= 0) ? _previewData->id : 0); + App::main()->sendPreparedText(hist, text, replyTo, webPageId); setFieldText(QString()); _saveDraftText = true; @@ -2802,6 +2804,10 @@ void HistoryWidget::leaveEvent(QEvent *e) { } void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) { + if (_replyForwardPressed) { + _replyForwardPressed = false; + update(0, _field.y() - st::sendPadding - st::replyHeight, width(), st::replyHeight); + } if (_attachDrag != DragStateNone || !_attachDragPhoto.isHidden() || !_attachDragDocument.isHidden()) { _attachDrag = DragStateNone; updateDragAreas(); @@ -3510,6 +3516,10 @@ void HistoryWidget::addMessagesToBack(const QVector &messages) { } void HistoryWidget::mousePressEvent(QMouseEvent *e) { + _replyForwardPressed = QRect(0, _field.y() - st::replyHeight, st::replySkip, st::replyHeight).contains(e->pos()); + if (_replyForwardPressed && !_replyForwardPreviewCancel.isHidden()) { + update(0, _field.y() - st::sendPadding - st::replyHeight, width(), st::replyHeight); + } } void HistoryWidget::keyPressEvent(QKeyEvent *e) { @@ -3664,6 +3674,7 @@ void HistoryWidget::cancelForwarding() { } void HistoryWidget::onReplyForwardPreviewCancel() { + _replyForwardPressed = false; if (_previewData && _previewData->pendingTill >= 0) { _previewCancelled = true; previewCancel(); @@ -3755,8 +3766,26 @@ void HistoryWidget::updatePreview() { if (t <= 0) t = 1; _previewTimer.start(t); } else { - _previewTitle.setText(st::msgServiceNameFont, _previewData->siteName, _textNameOptions); - _previewDescription.setText(st::msgFont, _previewData->title.isEmpty() ? (_previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? _previewData->url : _previewData->author) : _previewData->description) : _previewData->title, _textDlgOptions); + QString title, desc; + if (_previewData->siteName.isEmpty()) { + if (_previewData->title.isEmpty()) { + if (_previewData->description.isEmpty()) { + title = _previewData->author; + desc = _previewData->url; + } else { + title = _previewData->description; + desc = _previewData->author.isEmpty() ? _previewData->url : _previewData->author; + } + } else { + title = _previewData->title; + desc = _previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? _previewData->url : _previewData->author) : _previewData->description; + } + } else { + title = _previewData->siteName; + desc = _previewData->title.isEmpty() ? (_previewData->description.isEmpty() ? (_previewData->author.isEmpty() ? _previewData->url : _previewData->author) : _previewData->description) : _previewData->title; + } + _previewTitle.setText(st::msgServiceNameFont, title, _textNameOptions); + _previewDescription.setText(st::msgFont, desc, _textDlgOptions); } } else if (!App::main()->hasForwardingItems() && !_replyToId) { _replyForwardPreviewCancel.hide(); @@ -3941,7 +3970,7 @@ void HistoryWidget::drawFieldBackground(QPainter &p) { backy -= st::replyHeight; backh += st::replyHeight; } - bool drawPreview = (_previewData && _previewData->pendingTill >= 0); + bool drawPreview = (_previewData && _previewData->pendingTill >= 0) && !_replyForwardPressed; p.fillRect(0, backy, width(), backh, st::taMsgField.bgColor->b); if (_replyToId) { int32 replyLeft = st::replySkip; diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index bc241c0e9..5eea3ff7a 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -460,6 +460,8 @@ private: bool _previewCancelled; void gotPreview(QString links, const MTPMessageMedia &media, mtpRequestId req); + bool _replyForwardPressed; + HistoryItem *_replyReturn; QList _replyReturns; diff --git a/Telegram/SourceFiles/intro/intropwdcheck.cpp b/Telegram/SourceFiles/intro/intropwdcheck.cpp index 0b411cf44..e24b4527e 100644 --- a/Telegram/SourceFiles/intro/intropwdcheck.cpp +++ b/Telegram/SourceFiles/intro/intropwdcheck.cpp @@ -249,7 +249,7 @@ bool IntroPwdCheck::codeSubmitFail(const RPCError &error) { } void IntroPwdCheck::recoverStarted(const MTPauth_PasswordRecovery &result) { - _emailPattern = lng_signin_recover_hint(lt_recover_email, qs(result.c_auth_passwordRecovery().vemail_pattern)); + _emailPattern = st::introFont->m.elidedText(lng_signin_recover_hint(lt_recover_email, qs(result.c_auth_passwordRecovery().vemail_pattern)), Qt::ElideRight, textRect.width()); update(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 45f45dec9..f36cec797 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -377,6 +377,9 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr connect(audioVoice(), SIGNAL(stopped(AudioData*)), this, SLOT(audioPlayProgress(AudioData*))); } + _webPageUpdater.setSingleShot(true); + connect(&_webPageUpdater, SIGNAL(timeout()), this, SLOT(webPagesUpdate())); + connect(&_cacheBackgroundTimer, SIGNAL(timeout()), this, SLOT(onCacheBackground())); dialogs.show(); @@ -516,6 +519,25 @@ void MainWidget::finishForwarding(History *hist) { history.peerMessagesUpdated(hist->peer->id); } +void MainWidget::webPageUpdated(WebPageData *data) { + _webPagesUpdated.insert(data->id, true); + _webPageUpdater.start(0); +} + +void MainWidget::webPagesUpdate() { + const WebPageItems &items(App::webPageItems()); + for (QMap::const_iterator i = _webPagesUpdated.cbegin(), e = _webPagesUpdated.cend(); i != e; ++i) { + WebPageItems::const_iterator j = items.constFind(App::webPage(i.key())); + if (j != items.cend()) { + for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) { + k.key()->initDimensions(); + itemResized(k.key()); + } + } + } + _webPagesUpdated.clear(); +} + void MainWidget::onShareContact(const PeerId &peer, UserData *contact) { history.onShareContact(peer, contact); } @@ -887,7 +909,7 @@ DialogsIndexed &MainWidget::contactsList() { return dialogs.contactsList(); } -void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId replyTo, bool noPreview) { +void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId replyTo, WebPageId webPageId) { saveRecentHashtags(text); QString sendingText, leftText = text; if (replyTo < 0) replyTo = history.replyToId(); @@ -904,8 +926,14 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl flags |= MTPDmessage::flag_reply_to_msg_id; sendFlags |= MTPmessages_SendMessage::flag_reply_to_msg_id; } - if (noPreview) sendFlags |= MTPmessages_SendMessage_flag_skipWebPage; - hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, MTP_messageMediaEmpty())); + MTPMessageMedia media = MTP_messageMediaEmpty(); + if (webPageId == 0xFFFFFFFFFFFFFFFFULL) { + sendFlags |= MTPmessages_SendMessage_flag_skipWebPage; + } else if (webPageId) { + WebPageData *page = App::webPage(webPageId); + media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill))); + } + hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media)); hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } @@ -1884,11 +1912,9 @@ void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage } } - if (d.vmedia.type() != mtpc_messageMediaEmpty) { - HistoryItem *item = App::histItemById(d.vid.v); - if (item) { - item->setMedia(d.vmedia); - } + HistoryItem *item = App::histItemById(d.vid.v); + if (item) { + item->setMedia(d.vmedia); } } break; @@ -2773,7 +2799,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) { case mtpc_updateShortMessage: { const MTPDupdateShortMessage &d(updates.c_updateShortMessage()); - if (!App::userLoaded(d.vuser_id.v)) { + if (!App::userLoaded(d.vuser_id.v) || (d.has_fwd_from_id() && !App::userLoaded(d.vfwd_from_id.v))) { return getDifference(); } if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { @@ -2895,15 +2921,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateWebPage: { const MTPDupdateWebPage &d(update.c_updateWebPage()); - WebPageData *page = App::feedWebPage(d.vwebpage); - const WebPageItems &items(App::webPageItems()); - WebPageItems::const_iterator i = items.constFind(page); - if (i != items.cend()) { - for (HistoryItemsMap::const_iterator j = i.value().cbegin(), e = i.value().cend(); j != e; ++j) { - j.key()->initDimensions(); - itemResized(j.key()); - } - } + App::feedWebPage(d.vwebpage); history.updatePreview(); } break; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 7fb9198ef..7a675848d 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -283,7 +283,7 @@ public: DialogsIndexed &contactsList(); void sendMessage(History *history, const QString &text, MsgId replyTo); - void sendPreparedText(History *hist, const QString &text, MsgId replyTo, bool noPreview = false); + void sendPreparedText(History *hist, const QString &text, MsgId replyTo, WebPageId webPageId = 0); void saveRecentHashtags(const QString &text); void readServerHistory(History *history, bool force = true); @@ -333,6 +333,8 @@ public: void cancelForwarding(); void finishForwarding(History *hist); // send them + void webPageUpdated(WebPageData *page); + ~MainWidget(); signals: @@ -347,6 +349,8 @@ signals: public slots: + void webPagesUpdate(); + void videoLoadProgress(mtpFileLoader *loader); void videoLoadFailed(mtpFileLoader *loader, bool started); void videoLoadRetry(); @@ -405,6 +409,9 @@ private: Text _toForwardFrom, _toForwardText; int32 _toForwardNameVersion; + QMap _webPagesUpdated; + QTimer _webPageUpdater; + void gotDifference(const MTPupdates_Difference &diff); bool failDifference(const RPCError &e); void feedDifference(const MTPVector &users, const MTPVector &chats, const MTPVector &msgs, const MTPVector &other); diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index c78bfc329..980fb4fb4 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -825,10 +825,10 @@ void OverviewInner::onUpdateSelected() { } left += st::msgPhotoSkip; } - TextLinkPtr mediaLink = media->getLink(m.x() - left, m.y() - y - st::msgMargin.top(), item, w); - if (mediaLink) { - lnk = mediaLink; - } + bool inText = false; + TextLinkPtr link; + media->getState(link, inText, m.x() - left, m.y() - y - st::msgMargin.top(), item, w); + if (link) lnk = link; } } else { return; diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index 797327637..212c509b0 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.8.1 + 0.8.2 CFBundleSignature ???? CFBundleURLTypes diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index 803cd72baa9ced1d693531a8aa4ceee5423378cb..c373ef89d8e0fccda1dc30009fae22bd28556e74 100644 GIT binary patch delta 50 zcmbQEJx6;(0WYJ`