forwarded display improved

This commit is contained in:
John Preston 2016-02-19 14:53:49 +03:00
parent c3845ead85
commit 6d42350691
8 changed files with 132 additions and 111 deletions

View File

@ -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";

View File

@ -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;

View File

@ -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 {

View File

@ -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 {

View File

@ -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<HistoryMessageVia>()) {
@ -6133,6 +6148,7 @@ void HistoryMessage::create(int32 viaBotId, int32 viewsCount, const PeerId &auth
if (HistoryMessageForwarded *fwd = Get<HistoryMessageForwarded>()) {
fwd->_authorOriginal = App::peer(authorIdOriginal);
fwd->_fromOriginal = App::peer(fromIdOriginal);
fwd->_originalId = originalId;
}
initTime();
}
@ -6239,7 +6255,7 @@ void HistoryMessage::initDimensions() {
HistoryMessageForwarded *fwd = Get<HistoryMessageForwarded>();
HistoryMessageVia *via = Get<HistoryMessageVia>();
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<HistoryMessageForwarded>()) {
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<HistoryMessageForwarded>();
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<HistoryMessageForwarded>();
const HistoryMessageVia *via = Get<HistoryMessageVia>();
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)

View File

@ -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<HistoryMessageSigned> {
struct HistoryMessageForwarded : public BasicInterface<HistoryMessageForwarded> {
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<HistoryMessageForwarded>()) {

View File

@ -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<HistoryMessageForwarded>()) {
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) {

View File

@ -700,7 +700,7 @@ void LayoutOverviewVoice::getState(TextLinkPtr &link, HistoryCursorState &cursor
void LayoutOverviewVoice::updateName() const {
int32 version = 0;
if (const HistoryMessageForwarded *fwd = _parent->Get<HistoryMessageForwarded>()) {
_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);
}