diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index a03f48663..be3832f2a 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -555,7 +555,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_channel_public_link_copied" = "Link copied to clipboard."; -"lng_forwarded_from" = "Forwarded from"; +"lng_forwarded" = "Forwarded from {original}"; +"lng_forwarded_via" = "Forwarded from {original} via {inline_bot}"; +"lng_forwarded_signed" = "{channel} ({user})"; "lng_in_reply_to" = "In reply to"; "lng_attach_failed" = "Failed"; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index d06880d61..3a9794fe1 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -1163,6 +1163,24 @@ outTextStyle: textStyle(defaultTextStyle) { selectBg: msgOutBgSelected; selectOverlay: msgSelectOverlay; } +inFwdTextStyle: textStyle(defaultTextStyle) { + linkFlags: semiboldFont; + linkFlagsOver: semiboldFont; + linkFg: msgInServiceFg; + linkFgDown: msgInServiceFg; +} +outFwdTextStyle: textStyle(inFwdTextStyle) { + linkFg: msgOutServiceFg; + linkFgDown: msgOutServiceFg; +} +inFwdTextStyleSelected: textStyle(inFwdTextStyle) { + linkFg: msgInServiceFgSelected; + linkFgDown: msgInServiceFgSelected; +} +outFwdTextStyleSelected: textStyle(inFwdTextStyle) { + linkFg: msgOutServiceFgSelected; + linkFgDown: msgOutServiceFgSelected; +} medviewSaveAsTextStyle: textStyle(defaultTextStyle) { linkFg: #91d9ff; linkFgDown: #91d9ff; diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 6e7a772c8..3939945ad 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -994,7 +994,7 @@ public: return _blockEnd(t, i, e) - (*i)->from(); } - TextPainter(QPainter *p, const Text *t) : _p(p), _t(t), _elideLast(false), _elideRemoveFromEnd(0), _str(0), _elideSavedBlock(0), _lnkResult(0), _inTextFlag(0), _getSymbol(0), _getSymbolAfter(0), _getSymbolUpon(0) { + TextPainter(QPainter *p, const Text *t) : _p(p), _t(t), _elideLast(false), _breakEverywhere(false), _elideRemoveFromEnd(0), _str(0), _elideSavedBlock(0), _lnkResult(0), _inTextFlag(0), _getSymbol(0), _getSymbolAfter(0), _getSymbolUpon(0) { } void initNextParagraph(Text::TextBlocks::const_iterator i) { @@ -1192,7 +1192,7 @@ public: bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yToElide); if (elidedLine) { _lineHeight = elidedLineHeight; - } else if (f != j) { + } else if (f != j && !_breakEverywhere) { // word did not fit completely, so we roll back the state to the beginning of this long word j = f; _wLeft = f_wLeft; @@ -1251,7 +1251,7 @@ public: } } - void drawElided(int32 left, int32 top, int32 w, style::align align, int32 lines, int32 yFrom, int32 yTo, int32 removeFromEnd) { + void drawElided(int32 left, int32 top, int32 w, style::align align, int32 lines, int32 yFrom, int32 yTo, int32 removeFromEnd, bool breakEverywhere) { if (lines <= 0 || _t->isNull()) return; if (yTo < 0 || (lines - 1) * _t->_font->height < yTo) { @@ -1259,6 +1259,7 @@ public: _elideLast = true; _elideRemoveFromEnd = removeFromEnd; } + _breakEverywhere = breakEverywhere; draw(left, top, w, align, yFrom, yTo); } @@ -1272,7 +1273,7 @@ public: return *_lnkResult; } - void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 w, style::align align) { + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 w, style::align align, bool breakEverywhere) { lnk = TextLinkPtr(); inText = false; @@ -1281,6 +1282,7 @@ public: _lnkY = y; _lnkResult = &lnk; _inTextFlag = &inText; + _breakEverywhere = breakEverywhere; draw(0, 0, w, align, _lnkY, _lnkY + 1); lnk = *_lnkResult; } @@ -2437,7 +2439,7 @@ private: QPainter *_p; const Text *_t; - bool _elideLast; + bool _elideLast, _breakEverywhere; int32 _elideRemoveFromEnd; style::align _align; QPen _originalPen; @@ -2984,10 +2986,10 @@ void Text::draw(QPainter &painter, int32 left, int32 top, int32 w, style::align p.draw(left, top, w, align, yFrom, yTo, selectedFrom, selectedTo); } -void Text::drawElided(QPainter &painter, int32 left, int32 top, int32 w, int32 lines, style::align align, int32 yFrom, int32 yTo, int32 removeFromEnd) const { +void Text::drawElided(QPainter &painter, int32 left, int32 top, int32 w, int32 lines, style::align align, int32 yFrom, int32 yTo, int32 removeFromEnd, bool breakEverywhere) const { // painter.fillRect(QRect(left, top, w, countHeight(w)), QColor(0, 0, 0, 32)); // debug TextPainter p(&painter, this); - p.drawElided(left, top, w, align, lines, yFrom, yTo, removeFromEnd); + p.drawElided(left, top, w, align, lines, yFrom, yTo, removeFromEnd, breakEverywhere); } const TextLinkPtr &Text::link(int32 x, int32 y, int32 width, style::align align) const { @@ -2995,9 +2997,9 @@ const TextLinkPtr &Text::link(int32 x, int32 y, int32 width, style::align align) return p.link(x, y, width, align); } -void Text::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 width, style::align align) const { +void Text::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 width, style::align align, bool breakEverywhere) const { TextPainter p(0, this); - p.getState(lnk, inText, x, y, width, align); + p.getState(lnk, inText, x, y, width, align, breakEverywhere); } void Text::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 width, style::align align) const { diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index 341ebb903..731e99621 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -604,27 +604,27 @@ public: void replaceFont(style::font f); // does not recount anything, use at your own risk! void draw(QPainter &p, int32 left, int32 top, int32 width, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const; - void drawElided(QPainter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0) const; + void drawElided(QPainter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false) const; void drawLeft(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const { draw(p, rtl() ? (outerw - left - width) : left, top, width, align, yFrom, yTo, selectedFrom, selectedTo); } - void drawLeftElided(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0) const { - drawElided(p, rtl() ? (outerw - left - width) : left, top, width, lines, align, yFrom, yTo, removeFromEnd); + void drawLeftElided(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false) const { + drawElided(p, rtl() ? (outerw - left - width) : left, top, width, lines, align, yFrom, yTo, removeFromEnd, breakEverywhere); } void drawRight(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const { draw(p, rtl() ? right : (outerw - right - width), top, width, align, yFrom, yTo, selectedFrom, selectedTo); } - void drawRightElided(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0) const { - drawElided(p, rtl() ? right : (outerw - right - width), top, width, lines, align, yFrom, yTo, removeFromEnd); + void drawRightElided(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false) const { + drawElided(p, rtl() ? right : (outerw - right - width), top, width, lines, align, yFrom, yTo, removeFromEnd, breakEverywhere); } const TextLinkPtr &link(int32 x, int32 y, int32 width, style::align align = style::al_left) const; const TextLinkPtr &linkLeft(int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left) const { return link(rtl() ? (outerw - x - width) : x, y, width, align); } - void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 width, style::align align = style::al_left) const; - void getStateLeft(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left) const { - return getState(lnk, inText, rtl() ? (outerw - x - width) : x, y, width, align); + void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 width, style::align align = style::al_left, bool breakEverywhere = false) const; + void getStateLeft(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left, bool breakEverywhere = false) const { + return getState(lnk, inText, rtl() ? (outerw - x - width) : x, y, width, align, breakEverywhere); } void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 width, style::align align = style::al_left) const; void getSymbolLeft(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left) const { diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 3ebc83230..6ef6b30c5 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -6018,14 +6018,30 @@ int32 HistoryMessageSigned::maxWidth() const { HistoryMessageForwarded::HistoryMessageForwarded(Interfaces *) : _authorOriginal(0) , _fromOriginal(0) -, _authorOriginalVersion(0) -, _fromWidth(st::msgServiceFont->width(lang(lng_forwarded_from)) + st::msgServiceFont->spacew) { +, _originalId(0) +, _text(1) { } -void HistoryMessageForwarded::authorNameUpdated(bool hasVia) const { - QString name((hasVia && _authorOriginal->isUser()) ? _authorOriginal->asUser()->firstName : App::peerName(_authorOriginal)); - _authorOriginalName.setText(st::msgServiceNameFont, name, _textNameOptions); - _authorOriginalVersion = _authorOriginal->nameVersion; +void HistoryMessageForwarded::create(const HistoryMessageVia *via) const { + QString text; + if (_authorOriginal != _fromOriginal) { + text = lng_forwarded_signed(lt_channel, App::peerName(_authorOriginal), lt_user, App::peerName(_fromOriginal)); + } else { + text = App::peerName(_authorOriginal); + } + if (via) { + text = lng_forwarded_via(lt_original, textcmdLink(1, text), lt_inline_bot, textcmdLink(2, '@' + via->_bot->username)); + } else { + text = lng_forwarded(lt_original, textcmdLink(1, text)); + } + TextParseOptions opts = { TextParseRichText, 0, 0, Qt::LayoutDirectionAuto }; + textstyleSet(&st::inFwdTextStyle); + _text.setText(st::msgServiceNameFont, text, opts); + textstyleRestore(); + _text.setLink(1, (_originalId && _authorOriginal->isChannel()) ? TextLinkPtr(new MessageLink(_authorOriginal->id, _originalId)) : _authorOriginal->lnk); + if (via) { + _text.setLink(2, via->_lnk); + } } HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg) : @@ -6034,15 +6050,17 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPD , _textWidth(0) , _textHeight(0) , _media(0) { - PeerId fwdAuthorId = 0, fwdFromId = 0; + PeerId authorOriginalId = 0, fromOriginalId = 0; + MsgId originalId = 0; if (msg.has_fwd_from() && msg.vfwd_from.type() == mtpc_messageFwdHeader) { const MTPDmessageFwdHeader &f(msg.vfwd_from.c_messageFwdHeader()); if (f.has_from_id() || f.has_channel_id()) { - fwdAuthorId = f.has_channel_id() ? peerFromChannel(f.vchannel_id) : peerFromUser(f.vfrom_id); - fwdFromId = f.has_from_id() ? peerFromUser(f.vfrom_id) : peerFromChannel(f.vchannel_id); + authorOriginalId = f.has_channel_id() ? peerFromChannel(f.vchannel_id) : peerFromUser(f.vfrom_id); + fromOriginalId = f.has_from_id() ? peerFromUser(f.vfrom_id) : peerFromChannel(f.vchannel_id); + if (f.has_channel_post()) originalId = f.vchannel_post.v; } } - create(msg.has_via_bot_id() ? msg.vvia_bot_id.v : 0, msg.has_views() ? msg.vviews.v : -1, fwdAuthorId, fwdFromId); + create(msg.has_via_bot_id() ? msg.vvia_bot_id.v : 0, msg.has_views() ? msg.vviews.v : -1, authorOriginalId, fromOriginalId, originalId); QString text(textClean(qs(msg.vmessage))); initMedia(msg.has_media() ? (&msg.vmedia) : 0, text); @@ -6058,7 +6076,7 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId id, UserData *fwdViaBot = fwd->viaBot(); int32 viaBotId = fwdViaBot ? peerToUser(fwdViaBot->id) : 0; int32 fwdViewsCount = fwd->viewsCount(), views = (fwdViewsCount > 0) ? fwdViewsCount : (isPost() ? 1 : -1); - create(viaBotId, views, fwd->authorOriginal()->id, fwd->fromOriginal()->id); + create(viaBotId, views, fwd->authorOriginal()->id, fwd->fromOriginal()->id, fwd->authorOriginal()->isChannel() ? fwd->id : 0); if (HistoryMedia *mediaOriginal = fwd->getMedia()) { _media = mediaOriginal->clone(); @@ -6073,7 +6091,7 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId id, , _textWidth(0) , _textHeight(0) , _media(0) { - create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1, 0, 0); + create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); setText(msg, entities); } @@ -6084,7 +6102,7 @@ HistoryItem(history, block, msgId, flags, date, (flags & MTPDmessage::flag_from_ , _textWidth(0) , _textHeight(0) , _media(0) { - create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1, 0, 0); + create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); initMediaFromDocument(doc, caption); setText(QString(), EntitiesInText()); @@ -6096,14 +6114,14 @@ HistoryItem(history, block, msgId, flags, date, (flags & MTPDmessage::flag_from_ , _textWidth(0) , _textHeight(0) , _media(0) { - create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1, 0, 0); + create((flags & MTPDmessage::flag_via_bot_id) ? viaBotId : 0, isPost() ? 1 : -1); _media = new HistoryPhoto(photo, caption, this); _media->regItem(this); setText(QString(), EntitiesInText()); } -void HistoryMessage::create(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal, const PeerId &fromIdOriginal) { +void HistoryMessage::create(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal, const PeerId &fromIdOriginal, MsgId originalId) { uint64 mask = 0; if (viaBotId) { mask |= HistoryMessageVia::Bit(); @@ -6116,9 +6134,6 @@ void HistoryMessage::create(int32 viaBotId, int32 viewsCount, const PeerId &auth } if (authorIdOriginal && fromIdOriginal) { mask |= HistoryMessageForwarded::Bit(); - if (authorIdOriginal != fromIdOriginal) { - mask |= HistoryMessageSigned::Bit(); - } } UpdateInterfaces(mask); if (HistoryMessageVia *via = Get()) { @@ -6133,6 +6148,7 @@ void HistoryMessage::create(int32 viaBotId, int32 viewsCount, const PeerId &auth if (HistoryMessageForwarded *fwd = Get()) { fwd->_authorOriginal = App::peer(authorIdOriginal); fwd->_fromOriginal = App::peer(fromIdOriginal); + fwd->_originalId = originalId; } initTime(); } @@ -6239,7 +6255,7 @@ void HistoryMessage::initDimensions() { HistoryMessageForwarded *fwd = Get(); HistoryMessageVia *via = Get(); if (fwd) { - fwd->authorNameUpdated(via != 0); + fwd->create(via); } if (_media) { @@ -6281,7 +6297,7 @@ void HistoryMessage::initDimensions() { } } if (fwd) { - int32 _namew = st::msgPadding.left() + fwd->_fromWidth + fwd->_authorOriginalName.maxWidth() + st::msgPadding.right(); + int32 _namew = st::msgPadding.left() + fwd->_text.maxWidth() + st::msgPadding.right(); if (via) { _namew += st::msgServiceFont->spacew + via->_maxWidth; } @@ -6374,9 +6390,9 @@ QString HistoryMessage::selectedText(uint32 selection) const { } if (const HistoryMessageForwarded *fwd = Get()) { if (selection == FullSelection) { - QString wrapped; - wrapped.reserve(lang(lng_forwarded_from).size() + fwd->_authorOriginal->name.size() + 4 + result.size()); - wrapped.append('[').append(lang(lng_forwarded_from)).append(' ').append(fwd->_authorOriginal->name).append(qsl("]\n")).append(result); + QString fwdinfo = fwd->_text.original(0, 0xFFFF, Text::ExpandLinksAll), wrapped; + wrapped.reserve(fwdinfo.size() + 4 + result.size()); + wrapped.append('[').append(fwdinfo).append(qsl("]\n")).append(result); result = wrapped; } } @@ -6592,12 +6608,6 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m if (displayFromName() && author()->nameVersion > _authorNameVersion) { fromNameUpdated(width); } - if (fwd && fwd->_authorOriginal->nameVersion > fwd->_authorOriginalVersion) { - fwd->authorNameUpdated(via != 0); - if (via) { - via->resize(width - st::msgPadding.left() - st::msgPadding.right() - fwd->_fromWidth - fwd->_authorOriginalName.maxWidth() - st::msgServiceFont->spacew); - } - } QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom()); @@ -6649,8 +6659,19 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m void HistoryMessage::drawMessageText(Painter &p, QRect trect, uint32 selection) const { if (displayForwardedFrom()) { - paintForwardedInfo(p, trect.x(), trect.y(), trect.width(), (selection == FullSelection)); - trect.setY(trect.y() + st::msgServiceNameFont->height); + style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont); + + bool outbg = out() && !isPost(); + p.setPen((selection == FullSelection) ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg)); + p.setFont(serviceFont); + + const HistoryMessageForwarded *fwd = Get(); + bool breakEverywhere = (fwd->_text.countHeight(trect.width()) > 2 * serviceFont->height); + textstyleSet(&((selection == FullSelection) ? (outbg ? st::outFwdTextStyleSelected : st::inFwdTextStyleSelected) : (outbg ? st::outFwdTextStyle : st::inFwdTextStyle))); + fwd->_text.drawElided(p, trect.x(), trect.y(), trect.width(), 2, style::al_left, 0, -1, 0, breakEverywhere); + textstyleRestore(); + + trect.setY(trect.y() + (((fwd->_text.maxWidth() > trect.width()) ? 2 : 1) * serviceFont->height)); } bool outbg = out() && !isPost(), selected = (selection == FullSelection); @@ -6729,15 +6750,14 @@ int32 HistoryMessage::resize(int32 width) { } if (displayForwardedFrom()) { + int32 l = 0, w = 0; + countPositionAndSize(l, w); + int32 fwdheight = ((fwd->_text.maxWidth() > (w - st::msgPadding.left() - st::msgPadding.right())) ? 2 : 1) * st::semiboldFont->height; + if (emptyText() && !displayFromName()) { - _height += st::msgPadding.top() + st::msgServiceNameFont->height + st::mediaHeaderSkip; + _height += st::msgPadding.top() + fwdheight + st::mediaHeaderSkip; } else { - _height += st::msgServiceNameFont->height; - } - if (via) { - int32 l = 0, w = 0; - countPositionAndSize(l, w); - via->resize(w - st::msgPadding.left() - st::msgPadding.right() - fwd->_fromWidth - fwd->_authorOriginalName.maxWidth() - st::msgServiceFont->spacew); + _height += fwdheight; } } } else { @@ -6753,10 +6773,6 @@ bool HistoryMessage::hasPoint(int32 x, int32 y) const { if (width < 1) return false; if (drawBubble()) { - if (displayForwardedFrom()) { - QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom()); - return r.contains(x, y); - } QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom()); return r.contains(x, y); } else { @@ -6817,18 +6833,20 @@ void HistoryMessage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 } if (displayForwardedFrom()) { QRect trect(r.marginsAdded(-st::msgPadding)); - if (y >= trect.top() && y < trect.top() + st::msgServiceNameFont->height) { - if (x >= trect.left() + fwd->_fromWidth && x < trect.right() && x < trect.left() + fwd->_fromWidth + fwd->_authorOriginalName.maxWidth()) { - lnk = fwd->_authorOriginal->lnk; - } else if (via && x >= trect.left() + fwd->_fromWidth + fwd->_authorOriginalName.maxWidth() + st::msgServiceFont->spacew && x < trect.right() && x < trect.left() + fwd->_fromWidth + fwd->_authorOriginalName.maxWidth() + st::msgServiceFont->spacew + via->_maxWidth) { - lnk = via->_lnk; - } else { - lnk = TextLinkPtr(); + int32 fwdheight = ((fwd->_text.maxWidth() > trect.width()) ? 2 : 1) * st::semiboldFont->height; + if (y >= trect.top() && y < trect.top() + fwdheight) { + bool inText = false; + bool breakEverywhere = (fwd->_text.countHeight(trect.width()) > 2 * st::semiboldFont->height); + textstyleSet(&st::inFwdTextStyle); + fwd->_text.getState(lnk, inText, x - trect.left(), y - trect.top(), trect.right() - trect.left(), style::al_left, breakEverywhere); + textstyleRestore(); + if (breakEverywhere) { + state = HistoryInForwardedCursorState; } return; } - y -= st::msgServiceNameFont->height; - r.setHeight(r.height() - st::msgServiceNameFont->height); + y -= fwdheight; + r.setHeight(r.height() - fwdheight); } getStateFromMessageText(lnk, state, x, y, r); } else { @@ -6899,11 +6917,12 @@ void HistoryMessage::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, } else if (via && !fwd) { r.setTop(r.top() + st::msgNameFont->height); } - if (displayForwardedFrom()) { - y -= st::msgServiceNameFont->height; - r.setHeight(r.height() - st::msgServiceNameFont->height); - } QRect trect(r.marginsAdded(-st::msgPadding)); + if (displayForwardedFrom()) { + int32 fwdheight = ((fwd->_text.maxWidth() > trect.width()) ? 2 : 1) * st::semiboldFont->height; + y -= fwdheight; + r.setHeight(r.height() - fwdheight); + } if (_media && _media->isDisplayed()) { trect.setBottom(trect.bottom() - _media->height()); } @@ -6956,32 +6975,6 @@ HistoryMessage::~HistoryMessage() { } } -void HistoryMessage::paintForwardedInfo(Painter &p, int32 x, int32 y, int32 w, bool selected) const { - style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont); - - bool outbg = out() && !isPost(); - p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p); - p.setFont(serviceFont); - - const HistoryMessageForwarded *fwd = Get(); - const HistoryMessageVia *via = Get(); - if (via && w > fwd->_fromWidth + fwd->_authorOriginalName.maxWidth() + serviceFont->spacew) { - p.drawText(x, y + serviceFont->ascent, lang(lng_forwarded_from)); - - p.setFont(serviceName); - fwd->_authorOriginalName.draw(p, x + fwd->_fromWidth, y, w - fwd->_fromWidth); - - p.drawText(x + fwd->_fromWidth + fwd->_authorOriginalName.maxWidth() + serviceFont->spacew, y + serviceFont->ascent, via->_text); - } else if (w > fwd->_fromWidth) { - p.drawText(x, y + serviceFont->ascent, lang(lng_forwarded_from)); - - p.setFont(serviceName); - fwd->_authorOriginalName.drawElided(p, x + fwd->_fromWidth, y, w - fwd->_fromWidth); - } else { - p.drawText(x, y + serviceFont->ascent, serviceFont->elided(lang(lng_forwarded_from), w)); - } -} - HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg) , replyToMsgId(msg.vreply_to_msg_id.v) , replyToMsg(0) diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index fbcc1e7da..6b20310be 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -769,7 +769,8 @@ class HistoryMessage; // dynamic_cast optimize enum HistoryCursorState { HistoryDefaultCursorState, HistoryInTextCursorState, - HistoryInDateCursorState + HistoryInDateCursorState, + HistoryInForwardedCursorState, }; enum InfoDisplayType { @@ -819,13 +820,12 @@ struct HistoryMessageSigned : public BasicInterface { struct HistoryMessageForwarded : public BasicInterface { HistoryMessageForwarded(Interfaces *); - void authorNameUpdated(bool hasVia) const; + void create(const HistoryMessageVia *via) const; bool display(bool hasVia) const; PeerData *_authorOriginal, *_fromOriginal; - mutable Text _authorOriginalName; - mutable int32 _authorOriginalVersion; - int32 _fromWidth; + MsgId _originalId; + mutable Text _text; }; class HistoryMedia; @@ -2116,7 +2116,7 @@ public: protected: - void create(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal, const PeerId &fromIdOriginal); + void create(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal = 0, const PeerId &fromIdOriginal = 0, MsgId originalId = 0); bool displayForwardedFrom() const { if (const HistoryMessageForwarded *fwd = Get()) { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 99e07198d..30048f24f 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -1610,10 +1610,10 @@ void HistoryInner::onUpdateSelected() { } } } - if (_dragCursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) { + if (cursorState != _dragCursorState) { PopupTooltip::Hide(); } - if (lnk || cursorState == HistoryInDateCursorState) { + if (lnk || cursorState == HistoryInDateCursorState || cursorState == HistoryInForwardedCursorState) { PopupTooltip::Show(1000, this); } @@ -1859,6 +1859,12 @@ QString HistoryInner::tooltipText() const { if (App::hoveredItem()) { return App::hoveredItem()->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)); } + } else if (_dragCursorState == HistoryInForwardedCursorState && _dragAction == NoDrag) { + if (App::hoveredItem()) { + if (HistoryMessageForwarded *fwd = App::hoveredItem()->Get()) { + return fwd->_text.original(0, 0xFFFF, Text::ExpandLinksNone); + } + } } return QString(); } @@ -5532,14 +5538,14 @@ void HistoryWidget::confirmSendFile(const FileLoadResultPtr &file, bool ctrlShif flags |= MTPDmessage::flag_from_id; } if (file->type == PreparePhoto) { - h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(showFromName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPnullFwdHeader, MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(file->photo, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1), MTPint()), NewMessageUnread); + h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(showFromName ? MTP::authedId() : 0), peerToMTP(file->to.peer), MTPnullFwdHeader, MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(file->photo, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1), MTPint()), NewMessageUnread); } else if (file->type == PrepareDocument) { - h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(showFromName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPnullFwdHeader, MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(file->document, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1), MTPint()), NewMessageUnread); + h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(showFromName ? MTP::authedId() : 0), peerToMTP(file->to.peer), MTPnullFwdHeader, MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(file->document, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1), MTPint()), NewMessageUnread); } else if (file->type == PrepareAudio) { if (!h->peer->isChannel()) { flags |= MTPDmessage::flag_media_unread; } - h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(showFromName ? 0 : MTP::authedId()), peerToMTP(file->to.peer), MTPnullFwdHeader, MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(file->document, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1), MTPint()), NewMessageUnread); + h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(showFromName ? MTP::authedId() : 0), peerToMTP(file->to.peer), MTPnullFwdHeader, MTPint(), MTP_int(file->to.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(file->document, MTP_string(file->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1), MTPint()), NewMessageUnread); } if (_peer && file->to.peer == _peer->id) { diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index 90f1415c6..3e792b014 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -700,7 +700,7 @@ void LayoutOverviewVoice::getState(TextLinkPtr &link, HistoryCursorState &cursor void LayoutOverviewVoice::updateName() const { int32 version = 0; if (const HistoryMessageForwarded *fwd = _parent->Get()) { - _name.setText(st::semiboldFont, lang(lng_forwarded_from) + ' ' + App::peerName(_parent->fromOriginal()), _textNameOptions); + _name.setText(st::semiboldFont, lng_forwarded(lt_original, App::peerName(_parent->fromOriginal())), _textNameOptions); } else { _name.setText(st::semiboldFont, App::peerName(_parent->from()), _textNameOptions); }