document new design done with radial progress, ? char added to monospace blocks edges, redraw history item through Notify::

This commit is contained in:
John Preston 2015-12-11 21:11:38 +03:00
parent 92c31324b0
commit 603fb63c91
20 changed files with 649 additions and 337 deletions

View File

@ -1015,25 +1015,25 @@ msgPadding: margins(13px, 7px, 13px, 8px);
msgMargin: margins(13px, 4px, 53px, 4px); msgMargin: margins(13px, 4px, 53px, 4px);
msgLnkPadding: 2px; // for media open / save links msgLnkPadding: 2px; // for media open / save links
msgBorder: #f0f0f0; msgBorder: #f0f0f0;
msgOutBg: #effdde;
msgInBg: #fff; msgInBg: #fff;
msgOutSelectBg: #b7dbdb; msgInBgSelected: #c2dcf2; // #358cd4 with 30% opacity
msgInSelectBg: #c2dcf2; // #358cd4 with 30% opacity msgOutBg: #effdde;
msgOutBgSelected: #b7dbdb;
msgSelectOverlay: #358cd44c; msgSelectOverlay: #358cd44c;
msgStickerOverlay: #358cd47f; msgStickerOverlay: #358cd47f;
msgOutServiceColor: #3a8e26; msgInServiceFg: #0e7acd;
msgInServiceColor: #0e7acd; msgInServiceFgSelected: #0e7acd;
msgOutServiceSelColor: #367570; msgOutServiceFg: #3a8e26;
msgInServiceSelColor: #0e7acd; msgOutServiceFgSelected: #367570;
msgShadow: 2px; msgShadow: 2px;
msgInShadow: #748ea229; msgInShadow: #748ea229;
msgInShadowSelected: #548dbb29;
msgOutShadow: #3ac34740; msgOutShadow: #3ac34740;
msgInSelectShadow: #548dbb29; msgOutShadowSelected: #37a78e40;
msgOutSelectShadow: #37a78e40; msgInDateFg: #a0acb6;
msgInDateColor: #a0acb6; msgInDateFgSelected: #6a9cc5;
msgOutDateColor: #6cc264; msgOutDateFg: #6cc264;
msgInSelectDateColor: #6a9cc5; msgOutDateFgSelected: #50a79c;
msgOutSelectDateColor: #50a79c;
msgReplyPadding: margins(6px, 6px, 11px, 6px); msgReplyPadding: margins(6px, 6px, 11px, 6px);
msgReplyBarPos: point(1px, 0px); msgReplyBarPos: point(1px, 0px);
@ -1086,7 +1086,8 @@ msgDateDelta: point(2px, 5px);
msgDateImgDelta: 4px; msgDateImgDelta: 4px;
msgDateImgColor: #fff; msgDateImgColor: #fff;
msgDateImgBg: #00000054; msgDateImgBg: #00000054;
msgDateImgSelectBg: #1c4a7187; msgDateImgBgOver: #00000074;
msgDateImgBgSelected: #1c4a7187;
msgDateImgPadding: point(8px, 2px); msgDateImgPadding: point(8px, 2px);
msgDateImgCheckSpace: 4px; msgDateImgCheckSpace: 4px;
@ -1117,7 +1118,7 @@ defaultTextStyle: textStyle {
linkFg: btnYesColor; linkFg: btnYesColor;
linkFgDown: btnYesHover; linkFgDown: btnYesHover;
monoFg: #777; monoFg: #777;
selectBg: msgInSelectBg; selectBg: msgInBgSelected;
selectOverlay: msgSelectOverlay; selectOverlay: msgSelectOverlay;
lineHeight: 0px; lineHeight: 0px;
} }
@ -1135,12 +1136,12 @@ serviceTextStyle: textStyle(defaultTextStyle) {
} }
inTextStyle: textStyle(defaultTextStyle) { inTextStyle: textStyle(defaultTextStyle) {
monoFg: #4e7391; monoFg: #4e7391;
selectBg: msgInSelectBg; selectBg: msgInBgSelected;
selectOverlay: msgSelectOverlay; selectOverlay: msgSelectOverlay;
} }
outTextStyle: textStyle(defaultTextStyle) { outTextStyle: textStyle(defaultTextStyle) {
monoFg: #469165; monoFg: #469165;
selectBg: msgOutSelectBg; selectBg: msgOutBgSelected;
selectOverlay: msgSelectOverlay; selectOverlay: msgSelectOverlay;
} }
medviewSaveAsTextStyle: textStyle(defaultTextStyle) { medviewSaveAsTextStyle: textStyle(defaultTextStyle) {
@ -1177,14 +1178,14 @@ mediaPlayOutImg: sprite(122px, 341px, 48px, 48px);
mediaPlayInImg: sprite(172px, 341px, 48px, 48px); mediaPlayInImg: sprite(172px, 341px, 48px, 48px);
mediaPauseOutImg: sprite(222px, 341px, 48px, 48px); mediaPauseOutImg: sprite(222px, 341px, 48px, 48px);
mediaPauseInImg: sprite(272px, 341px, 48px, 48px); mediaPauseInImg: sprite(272px, 341px, 48px, 48px);
mediaInColor: msgInDateColor; mediaInFg: msgInDateFg;
mediaOutColor: msgOutDateColor; mediaInFgSelected: msgInDateFgSelected;
mediaInSelectColor: msgInSelectDateColor; mediaOutFg: msgOutDateFg;
mediaOutSelectColor: msgOutSelectDateColor; mediaOutFgSelected: msgOutDateFgSelected;
mediaOutUnreadColor: #6aad60; mediaInUnreadFg: #999;
mediaOutUnreadSelectColor: #5aa382; mediaInUnreadFgSelected: #7b95aa;
mediaInUnreadColor: #999; mediaOutUnreadFg: #6aad60;
mediaInUnreadSelectColor: #7b95aa; mediaOutUnreadFgSelected: #5aa382;
mediaUnreadSize: 4px; mediaUnreadSize: 4px;
mediaUnreadSkip: 5px; mediaUnreadSkip: 5px;
@ -1235,6 +1236,9 @@ msgFileOutPlaySelected: sprite(180px, 146px, 20px, 18px);
msgFileInPlay: sprite(160px, 164px, 20px, 18px); msgFileInPlay: sprite(160px, 164px, 20px, 18px);
msgFileInPlaySelected: sprite(180px, 164px, 20px, 18px); msgFileInPlaySelected: sprite(180px, 164px, 20px, 18px);
msgFileOverDuration: 200;
msgFileRadialLine: 4px;
sendPadding: 9px; sendPadding: 9px;
btnSend: flatButton(btnDefFlat) { btnSend: flatButton(btnDefFlat) {
color: btnYesColor; color: btnYesColor;

View File

@ -2129,9 +2129,9 @@ namespace App {
prepareCorners(ServiceSelectedCorners, st::msgRadius, st::msgServiceSelectBg); prepareCorners(ServiceSelectedCorners, st::msgRadius, st::msgServiceSelectBg);
prepareCorners(SelectedOverlayCorners, st::msgRadius, st::msgSelectOverlay); prepareCorners(SelectedOverlayCorners, st::msgRadius, st::msgSelectOverlay);
prepareCorners(DateCorners, st::msgRadius, st::msgDateImgBg); prepareCorners(DateCorners, st::msgRadius, st::msgDateImgBg);
prepareCorners(DateSelectedCorners, st::msgRadius, st::msgDateImgSelectBg); prepareCorners(DateSelectedCorners, st::msgRadius, st::msgDateImgBgSelected);
prepareCorners(InShadowCorners, st::msgRadius, st::msgInShadow); prepareCorners(InShadowCorners, st::msgRadius, st::msgInShadow);
prepareCorners(InSelectedShadowCorners, st::msgRadius, st::msgInSelectShadow); prepareCorners(InSelectedShadowCorners, st::msgRadius, st::msgInShadowSelected);
prepareCorners(ForwardCorners, st::msgRadius, st::forwardBg); prepareCorners(ForwardCorners, st::msgRadius, st::forwardBg);
prepareCorners(MediaviewSaveCorners, st::msgRadius, st::medviewSaveMsg); prepareCorners(MediaviewSaveCorners, st::msgRadius, st::medviewSaveMsg);
prepareCorners(EmojiHoverCorners, st::msgRadius, st::emojiPanHover); prepareCorners(EmojiHoverCorners, st::msgRadius, st::emojiPanHover);
@ -2147,9 +2147,9 @@ namespace App {
prepareCorners(DocBlueCorners, st::msgRadius, st::mvDocBlueColor); prepareCorners(DocBlueCorners, st::msgRadius, st::mvDocBlueColor);
prepareCorners(MessageInCorners, st::msgRadius, st::msgInBg, &st::msgInShadow); prepareCorners(MessageInCorners, st::msgRadius, st::msgInBg, &st::msgInShadow);
prepareCorners(MessageInSelectedCorners, st::msgRadius, st::msgInSelectBg, &st::msgInSelectShadow); prepareCorners(MessageInSelectedCorners, st::msgRadius, st::msgInBgSelected, &st::msgInShadowSelected);
prepareCorners(MessageOutCorners, st::msgRadius, st::msgOutBg, &st::msgOutShadow); prepareCorners(MessageOutCorners, st::msgRadius, st::msgOutBg, &st::msgOutShadow);
prepareCorners(MessageOutSelectedCorners, st::msgRadius, st::msgOutSelectBg, &st::msgOutSelectShadow); prepareCorners(MessageOutSelectedCorners, st::msgRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
} }

View File

@ -210,15 +210,15 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) {
p.drawPixmap(x + st::mediaPadding.left(), y + st::mediaPadding.top(), userDefPhoto(1)->pix(st::mediaThumbSize)); p.drawPixmap(x + st::mediaPadding.left(), y + st::mediaPadding.top(), userDefPhoto(1)->pix(st::mediaThumbSize));
} }
p.setFont(st::normalFont->f); p.setFont(st::normalFont);
p.setPen(st::black->c); p.setPen(st::black);
if (twidth < _namew) { if (twidth < _namew) {
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, st::normalFont->elided(_name, twidth)); p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, st::normalFont->elided(_name, twidth));
} else { } else {
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, _name); p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, _name);
} }
p.setPen(st::mediaOutColor->p); p.setPen(st::mediaOutFg);
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->descent, _size); p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->descent, _size);
} }
} }

View File

@ -96,15 +96,19 @@ namespace Ui {
namespace Notify { namespace Notify {
void userIsBotChanged(UserData *user) { void userIsBotChanged(UserData *user) {
if (MainWidget *m = App::main()) m->notifyUserIsBotChanged(user); if (MainWidget *m = App::main()) m->notify_userIsBotChanged(user);
} }
void botCommandsChanged(UserData *user) { void botCommandsChanged(UserData *user) {
if (MainWidget *m = App::main()) m->notifyBotCommandsChanged(user); if (MainWidget *m = App::main()) m->notify_botCommandsChanged(user);
} }
void migrateUpdated(PeerData *peer) { void migrateUpdated(PeerData *peer) {
if (MainWidget *m = App::main()) m->notifyMigrateUpdated(peer); if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
}
void redrawHistoryItem(const HistoryItem *item) {
if (MainWidget *m = App::main()) m->notify_redrawHistoryItem(item);
} }
} }

View File

@ -53,5 +53,6 @@ namespace Notify {
void userIsBotChanged(UserData *user); void userIsBotChanged(UserData *user);
void botCommandsChanged(UserData *user); void botCommandsChanged(UserData *user);
void migrateUpdated(PeerData *peer); void migrateUpdated(PeerData *peer);
void redrawHistoryItem(const HistoryItem *item);
}; };

View File

@ -153,8 +153,8 @@ void AnimatedGif::step_frame(float64 ms, bool timer) {
if (frame != f) { if (frame != f) {
frame = f; frame = f;
if (timer) { if (timer) {
if (msg && App::main()) { if (msg) {
App::main()->msgUpdated(msg); Notify::redrawHistoryItem(msg);
} else { } else {
emit updated(); emit updated();
} }

View File

@ -284,6 +284,57 @@ AnimationCallbacks *animation(Type *obj, typename AnimationCallbacksAbsolute<Typ
return new AnimationCallbacksAbsolute<Type>(obj, method); return new AnimationCallbacksAbsolute<Type>(obj, method);
} }
template <typename Type, typename Param>
class AnimationCallbacksRelativeWithParam : public AnimationCallbacks {
public:
typedef void (Type::*Method)(Param, float64, bool);
AnimationCallbacksRelativeWithParam(Param param, Type *obj, Method method) : _started(0), _param(param), _obj(obj), _method(method) {
}
void start() {
_started = float64(getms());
}
void step(Animation *a, uint64 ms, bool timer) {
(_obj->*_method)(_param, ms - _started, timer);
}
private:
float64 _started;
Param _param;
Type *_obj;
Method _method;
};
template <typename Type, typename Param>
AnimationCallbacks *animation(Param param, Type *obj, typename AnimationCallbacksRelativeWithParam<Type, Param>::Method method) {
return new AnimationCallbacksRelativeWithParam<Type, Param>(param, obj, method);
}
template <typename Type, typename Param>
class AnimationCallbacksAbsoluteWithParam : public AnimationCallbacks {
public:
typedef void (Type::*Method)(Param, uint64, bool);
AnimationCallbacksAbsoluteWithParam(Param param, Type *obj, Method method) : _param(param), _obj(obj), _method(method) {
}
void step(Animation *a, uint64 ms, bool timer) {
(_obj->*_method)(_param, ms, timer);
}
private:
Param _param;
Type *_obj;
Method _method;
};
template <typename Type, typename Param>
AnimationCallbacks *animation(Param param, Type *obj, typename AnimationCallbacksAbsoluteWithParam<Type, Param>::Method method) {
return new AnimationCallbacksAbsoluteWithParam<Type, Param>(param, obj, method);
}
class AnimationManager : public QObject { class AnimationManager : public QObject {
Q_OBJECT Q_OBJECT

View File

@ -304,6 +304,14 @@ namespace style {
typedef Font font; typedef Font font;
typedef Color color; typedef Color color;
inline QColor interpolate(const style::color &a, const style::color &b, float64 opacity_b) {
QColor result;
result.setRedF((a->c.redF() * (1. - opacity_b)) + (b->c.redF() * opacity_b));
result.setGreenF((a->c.greenF() * (1. - opacity_b)) + (b->c.greenF() * opacity_b));
result.setBlueF((a->c.blueF() * (1. - opacity_b)) + (b->c.blueF() * opacity_b));
return result;
}
void startManager(); void startManager();
void stopManager(); void stopManager();

View File

@ -38,8 +38,8 @@ namespace {
const QRegularExpression _reHashtag(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])#[\\w]{2,64}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption); const QRegularExpression _reHashtag(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])#[\\w]{2,64}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression _reMention(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])@[A-Za-z_0-9]{5,32}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption); const QRegularExpression _reMention(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])@[A-Za-z_0-9]{5,32}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression _reBotCommand(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])/[A-Za-z_0-9]{1,64}(@[A-Za-z_0-9]{5,32})?([\\W]|$)")); const QRegularExpression _reBotCommand(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])/[A-Za-z_0-9]{1,64}(@[A-Za-z_0-9]{5,32})?([\\W]|$)"));
const QRegularExpression _rePre(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])(````?)[\\s\\S]+?(````?)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption); const QRegularExpression _rePre(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10])(````?)[\\s\\S]+?(````?)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption);
const QRegularExpression _reCode(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])(`)[^\\n]+?(`)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption); const QRegularExpression _reCode(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10])(`)[^\\n]+?(`)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption);
QSet<int32> _validProtocols, _validTopDomains; QSet<int32> _validProtocols, _validTopDomains;
const style::textStyle *_textStyle = 0; const style::textStyle *_textStyle = 0;
@ -103,6 +103,10 @@ const TextLinkPtr &textlnkDown() {
return _downLnk; return _downLnk;
} }
bool textlnkDrawOver(const TextLinkPtr &lnk) {
return (_overLnk == lnk) && (!_downLnk || _downLnk == lnk);
}
QString textOneLine(const QString &text, bool trim, bool rich) { QString textOneLine(const QString &text, bool trim, bool rich) {
QString result(text); QString result(text);
const QChar *s = text.unicode(), *ch = s, *e = text.unicode() + text.size(); const QChar *s = text.unicode(), *ch = s, *e = text.unicode() + text.size();
@ -1385,6 +1389,7 @@ public:
return true; return true;
} }
int skipIndex = -1;
QVarLengthArray<int> visualOrder(nItems); QVarLengthArray<int> visualOrder(nItems);
QVarLengthArray<uchar> levels(nItems); QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i) { for (int i = 0; i < nItems; ++i) {
@ -1396,6 +1401,7 @@ public:
TextBlockType _type = currentBlock->type(); TextBlockType _type = currentBlock->type();
if (_type == TextBlockTSkip) { if (_type == TextBlockTSkip) {
levels[i] = si.analysis.bidiLevel = 0; levels[i] = si.analysis.bidiLevel = 0;
skipIndex = i;
} else { } else {
levels[i] = si.analysis.bidiLevel; levels[i] = si.analysis.bidiLevel;
} }
@ -1406,6 +1412,13 @@ public:
} }
} }
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data()); QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
if (rtl() && skipIndex == nItems - 1) {
for (int32 i = nItems; i > 1;) {
--i;
visualOrder[i] = visualOrder[i - 1];
}
visualOrder[0] = skipIndex;
}
blockIndex = _lineStartBlock; blockIndex = _lineStartBlock;
currentBlock = _t->_blocks[blockIndex]; currentBlock = _t->_blocks[blockIndex];

View File

@ -680,6 +680,8 @@ const TextLinkPtr &textlnkOver();
void textlnkDown(const TextLinkPtr &lnk); void textlnkDown(const TextLinkPtr &lnk);
const TextLinkPtr &textlnkDown(); const TextLinkPtr &textlnkDown();
bool textlnkDrawOver(const TextLinkPtr &lnk);
// textcmd // textcmd
QString textcmdSkipBlock(ushort w, ushort h); QString textcmdSkipBlock(ushort w, ushort h);
QString textcmdStartLink(ushort lnkIndex); QString textcmdStartLink(ushort lnkIndex);

View File

@ -2973,7 +2973,7 @@ void ItemAnimations::step_animate(float64 ms, bool timer) {
for (Animations::iterator i = _animations.begin(); i != _animations.end();) { for (Animations::iterator i = _animations.begin(); i != _animations.end();) {
const HistoryItem *item = i.key(); const HistoryItem *item = i.key();
if (item->animating()) { if (item->animating()) {
if (timer) App::main()->msgUpdated(item); if (timer) Notify::redrawHistoryItem(item);
++i; ++i;
} else { } else {
i = _animations.erase(i); i = _animations.erase(i);
@ -3100,6 +3100,72 @@ HistoryItem *regItem(HistoryItem *item, bool returnExisting) {
return item; return item;
} }
RadialAnimation::RadialAnimation(int32 thickness, AnimationCallbacks *callbacks) : _thickness(thickness)
, _firstStart(0)
, _lastStart(0)
, _lastTime(0)
, _opacity(0)
, a_arcEnd(0, 0)
, a_arcStart(0, 1)
, _animation(callbacks) {
}
void RadialAnimation::start(float64 prg) {
_firstStart = _lastStart = _lastTime = getms();
a_arcEnd = anim::fvalue(prg, qMax(prg, 0.0001));
_animation.start();
}
void RadialAnimation::update(float64 prg, bool finished, uint64 ms) {
if (prg < 0.0001) prg = 0.0001;
if (prg != a_arcEnd.to()) {
a_arcEnd.start(prg);
_lastStart = _lastTime;
}
_lastTime = ms;
float64 dt = float64(ms - _lastStart), fulldt = float64(ms - _firstStart);
_opacity = qMin(fulldt / st::radialDuration, 1.);
if (!finished) {
a_arcEnd.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear);
} else if (dt >= st::radialDuration) {
a_arcEnd.update(1, anim::linear);
stop();
} else {
float64 r = dt / st::radialDuration;
a_arcEnd.update(r, anim::linear);
_opacity *= 1 - r;
}
float64 fromstart = fulldt / st::radialPeriod;
a_arcStart.update(fromstart - qFloor(fromstart), anim::linear);
}
void RadialAnimation::stop() {
_firstStart = _lastStart = _lastTime = 0;
a_arcEnd = anim::fvalue(0, 0);
_animation.stop();
}
void RadialAnimation::draw(Painter &p, const QRect &inner, const style::color &color) {
p.setRenderHint(QPainter::HighQualityAntialiasing);
float64 o = p.opacity();
p.setOpacity(o * _opacity);
QPen pen(color->p), was(p.pen());
pen.setWidth(_thickness);
p.setPen(pen);
int32 len = 16 + a_arcEnd.current() * 5744;
p.drawArc(inner, 1440 - a_arcStart.current() * 5760 - len, len);
p.setPen(was);
p.setOpacity(o);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
}
HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent) : HistoryMedia() HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent) : HistoryMedia()
, _data(App::feedPhoto(photo)) , _data(App::feedPhoto(photo))
, _openl(new PhotoLink(_data)) , _openl(new PhotoLink(_data))
@ -3291,13 +3357,14 @@ void HistoryPhoto::updateFrom(const MTPMessageMedia &media) {
} }
} }
void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
int32 width = w, height = _height, skipx = 0, skipy = 0;
int32 captionw = width - st::msgPadding.left() - st::msgPadding.right();
bool bubble = parent->hasBubble(); bool bubble = parent->hasBubble();
bool fromChannel = parent->fromChannel(), out = parent->out(), outbg = out && !fromChannel; bool fromChannel = parent->fromChannel(), out = parent->out(), outbg = out && !fromChannel;
if (width < 0) width = w;
int skipx = 0, skipy = 0, height = _height;
int32 captionw = width - st::msgPadding.left() - st::msgPadding.right();
if (bubble) { if (bubble) {
skipx = st::mediaPadding.left(); skipx = st::mediaPadding.left();
skipy = st::mediaPadding.top(); skipy = st::mediaPadding.top();
@ -3308,7 +3375,7 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, bool selected, in
height -= st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); height -= st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom();
} }
} else { } else {
App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInSelectShadow : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
} }
_data->full->load(false, false); _data->full->load(false, false);
@ -3322,7 +3389,7 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, bool selected, in
p.drawPixmap(skipx, skipy, pix); p.drawPixmap(skipx, skipy, pix);
if (!full) { if (!full) {
uint64 dt = itemAnimations().animate(parent, getms()); uint64 dt = itemAnimations().animate(parent, ms);
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta); int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = (width - st::photoLoader.width()) / 2, y = (height - st::photoLoader.height()) / 2; int32 x = (width - st::photoLoader.width()) / 2, y = (height - st::photoLoader.height()) / 2;
@ -3350,7 +3417,7 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, bool selected, in
QString time(parent->timeText()); QString time(parent->timeText());
if (_caption.isEmpty()) { if (_caption.isEmpty()) {
int32 fullRight = skipx + width, fullBottom = skipy + height; int32 fullRight = skipx + width, fullBottom = skipy + height;
parent->drawInfo(p, fullRight, fullBottom, selected, InfoDisplayOverImage); parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
} else { } else {
p.setPen(st::black); p.setPen(st::black);
_caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw); _caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw);
@ -3528,16 +3595,9 @@ HistoryMedia *HistoryVideo::clone() const {
return new HistoryVideo(*this); return new HistoryVideo(*this);
} }
void HistoryVideo::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
int32 height = _height; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
if (width < 0) { int32 width = w, height = _height, skipx = 0, skipy = 0;
width = w;
} else if (!_caption.isEmpty()) {
height = countHeight(parent, width);
}
if (width < 1) return;
int skipy = 0, replyFrom = 0, fwdFrom = 0;
data->thumb->checkload(); data->thumb->checkload();
@ -3546,8 +3606,8 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, bool selected, in
width = _maxw; width = _maxw;
} }
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg)); style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow)); style::color sh(outbg ? (selected ? st::msgOutShadowSelected : st::msgOutShadow) : (selected ? st::msgInShadowSelected : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners)); RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
App::roundRect(p, 0, 0, width, height, bg, cors, &sh); App::roundRect(p, 0, 0, width, height, bg, cors, &sh);
@ -3570,7 +3630,7 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, bool selected, in
QString statusText; QString statusText;
style::color status(selected ? (outbg ? st::mediaOutSelectColor : st::mediaInSelectColor) : (outbg ? st::mediaOutColor : st::mediaInColor)); style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
p.setPen(status->p); p.setPen(status->p);
if (data->loader) { if (data->loader) {
@ -3600,20 +3660,15 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, bool selected, in
if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= twidth) { if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= twidth) {
p.setRenderHint(QPainter::HighQualityAntialiasing, true); p.setRenderHint(QPainter::HighQualityAntialiasing, true);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush((outbg ? (selected ? st::mediaOutUnreadSelectColor : st::mediaOutUnreadColor) : (selected ? st::mediaInUnreadSelectColor : st::mediaInUnreadColor))->b); p.setBrush((outbg ? (selected ? st::mediaOutUnreadFgSelected : st::mediaOutUnreadFg) : (selected ? st::mediaInUnreadFgSelected : st::mediaInUnreadFg))->b);
p.drawEllipse(QRect(tleft + w + st::mediaUnreadSkip, texty + ((st::normalFont->height - st::mediaUnreadSize) / 2), st::mediaUnreadSize, st::mediaUnreadSize)); p.drawEllipse(QRect(tleft + w + st::mediaUnreadSkip, texty + ((st::normalFont->height - st::mediaUnreadSize) / 2), st::mediaUnreadSize, st::mediaUnreadSize));
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
} }
} }
p.setFont(st::msgDateFont->f);
if (!_caption.isEmpty()) { if (!_caption.isEmpty()) {
p.setPen(st::black->p); p.setPen(st::black->p);
_caption.draw(p, st::mediaPadding.left(), skipy + st::mediaPadding.top() + st::mediaThumbSize + st::webPagePhotoSkip, width - st::mediaPadding.left() - st::mediaPadding.right()); _caption.draw(p, st::mediaPadding.left(), skipy + st::mediaPadding.top() + st::mediaThumbSize + st::webPagePhotoSkip, width - st::mediaPadding.left() - st::mediaPadding.right());
} }
int32 fullRight = width, fullBottom = height;
parent->drawInfo(p, fullRight, fullBottom, selected, InfoDisplayDefault);
} }
int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) { int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) {
@ -3660,12 +3715,10 @@ void HistoryAudio::initDimensions(const HistoryItem *parent) {
_height = _minh; _height = _minh;
} }
void HistoryAudio::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; int32 width = w, skipy = 0, replyFrom = 0, fwdFrom = 0;
if (width < 1) return; if (width < 1) return;
int skipy = 0, replyFrom = 0, fwdFrom = 0;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
bool already = !data->already().isEmpty(), hasdata = !data->data.isEmpty(); bool already = !data->already().isEmpty(), hasdata = !data->data.isEmpty();
if (width >= _maxw) { if (width >= _maxw) {
@ -3676,8 +3729,8 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, bool selected, in
data->save(QString()); data->save(QString());
} }
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg)); style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow)); style::color sh(outbg ? (selected ? st::msgOutShadowSelected : st::msgOutShadow) : (selected ? st::msgInShadowSelected : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners)); RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
App::roundRect(p, 0, 0, width, _height, bg, cors, &sh); App::roundRect(p, 0, 0, width, _height, bg, cors, &sh);
@ -3737,7 +3790,7 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, bool selected, in
p.setPen(st::black->c); p.setPen(st::black->c);
p.drawText(tleft, skipy + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, lang(lng_media_audio)); p.drawText(tleft, skipy + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, lang(lng_media_audio));
style::color status(selected ? (outbg ? st::mediaOutSelectColor : st::mediaInSelectColor) : (outbg ? st::mediaOutColor : st::mediaInColor)); style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
p.setPen(status->p); p.setPen(status->p);
int32 texty = skipy + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height; int32 texty = skipy + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height;
p.drawText(tleft, texty + st::normalFont->ascent, statusText); p.drawText(tleft, texty + st::normalFont->ascent, statusText);
@ -3746,18 +3799,11 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, bool selected, in
if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= twidth) { if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= twidth) {
p.setRenderHint(QPainter::HighQualityAntialiasing, true); p.setRenderHint(QPainter::HighQualityAntialiasing, true);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush((outbg ? (selected ? st::mediaOutUnreadSelectColor : st::mediaOutUnreadColor) : (selected ? st::mediaInUnreadSelectColor : st::mediaInUnreadColor))->b); p.setBrush((outbg ? (selected ? st::mediaOutUnreadFgSelected : st::mediaOutUnreadFg) : (selected ? st::mediaInUnreadFgSelected : st::mediaInUnreadFg))->b);
p.drawEllipse(QRect(tleft + w + st::mediaUnreadSkip, texty + ((st::normalFont->height - st::mediaUnreadSize) / 2), st::mediaUnreadSize, st::mediaUnreadSize)); p.drawEllipse(QRect(tleft + w + st::mediaUnreadSkip, texty + ((st::normalFont->height - st::mediaUnreadSize) / 2), st::mediaUnreadSize, st::mediaUnreadSize));
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
} }
} }
p.setFont(st::msgDateFont->f);
style::color date(selected ? (outbg ? st::msgOutSelectDateColor : st::msgInSelectDateColor) : (outbg ? st::msgOutDateColor : st::msgInDateColor));
p.setPen(date->p);
int32 fullRight = width, fullBottom = _height;
parent->drawInfo(p, fullRight, fullBottom, selected, InfoDisplayDefault);
} }
void HistoryAudio::regItem(HistoryItem *item) { void HistoryAudio::regItem(HistoryItem *item) {
@ -3848,9 +3894,10 @@ HistoryDocument::HistoryDocument(DocumentData *document) : HistoryMedia()
, _savel(new DocumentSaveLink(_data)) , _savel(new DocumentSaveLink(_data))
, _thumbsavel(new DocumentSaveLink(_data)) , _thumbsavel(new DocumentSaveLink(_data))
, _cancell(new DocumentCancelLink(_data)) , _cancell(new DocumentCancelLink(_data))
, _name(documentName(_data)) { , _name(documentName(_data))
, _animation(0) {
if (_name.isEmpty()) _name = qsl("Unknown File"); if (_name.isEmpty()) _name = qsl("Unknown File");
_namew = st::normalFont->width(_name); _namew = st::semiboldFont->width(_name);
setStatusSize(FileStatusSizeReady); setStatusSize(FileStatusSizeReady);
@ -3862,10 +3909,8 @@ HistoryDocument::HistoryDocument(DocumentData *document) : HistoryMedia()
} else { } else {
_thumbw = st::msgFileThumbSize; _thumbw = st::msgFileThumbSize;
} }
_height = _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
} else { } else {
_thumbw = 0; _thumbw = 0;
_height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
} }
} }
@ -3946,11 +3991,17 @@ void HistoryDocument::initDimensions(const HistoryItem *parent) {
_maxw = qMax(tleft + _namew + tright, _maxw); _maxw = qMax(tleft + _namew + tright, _maxw);
_maxw = qMin(_maxw, int(st::msgMaxWidth)); _maxw = qMin(_maxw, int(st::msgMaxWidth));
if (withThumb()) {
_height = _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
} else {
_height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
}
} }
void HistoryDocument::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
if (width < 1) return; int32 width = w, height = _height, skipx = 0, skipy = 0;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty();
@ -3960,6 +4011,14 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, bool selected,
} }
bool showPause = updateStatusText(parent); bool showPause = updateStatusText(parent);
bool radial = _animation && _animation->radial.animating();
if (_data->loader) {
ensureAnimation(parent);
if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress());
}
}
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
bool wthumb = withThumb(); bool wthumb = withThumb();
@ -3981,29 +4040,47 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, bool selected,
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
} }
if (already || hasdata) { if (!radial && (already || hasdata)) {
} else { } else {
p.setRenderHint(QPainter::HighQualityAntialiasing);
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(selected ? st::msgDateImgSelectBg : st::msgDateImgBg); if (selected) {
p.drawEllipse(inner); p.setBrush(st::msgDateImgBgSelected);
} else if (radial && (already || hasdata)) {
p.setOpacity(st::msgDateImgBg->c.alphaF() * _animation->radial.opacity());
p.setBrush(st::black);
} else if (_animation && _animation->_a_thumbOver.animating()) {
float64 over = _animation->a_thumbOver.current();
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black);
} else {
bool over = textlnkDrawOver(_thumbsavel);
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
}
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
style::sprite icon; style::sprite icon;
if (_data->loader) { if (already || hasdata || _data->loader) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else { } else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
p.setOpacity(radial ? _animation->radial.opacity() : 1);
p.drawSpriteCenter(inner, icon); p.drawSpriteCenter(inner, icon);
if (radial) {
p.setOpacity(1);
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
_animation->radial.draw(p, rinner, selected ? st::msgInBgSelected : st::msgInBg);
}
} }
if (_data->status != FileUploadFailed) { if (_data->status != FileUploadFailed) {
const TextLinkPtr &lnk((_data->loader || _data->status == FileUploading) ? _cancell : _savel); const TextLinkPtr &lnk((_data->loader || _data->status == FileUploading) ? _cancell : _savel);
bool over = (textlnkOver() == lnk) && (!textlnkDown() || textlnkDown() == lnk); bool over = textlnkDrawOver(lnk);
p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont); p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont);
p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg)); p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg));
p.drawTextLeft(nameleft, linktop, width, _link, _linkw); p.drawTextLeft(nameleft, linktop, width, _link, _linkw);
@ -4014,15 +4091,28 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, bool selected,
nameright = st::msgFilePadding.left(); nameright = st::msgFilePadding.left();
statustop = st::msgFileStatusTop; statustop = st::msgFileStatusTop;
p.setRenderHint(QPainter::HighQualityAntialiasing);
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width)); QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width));
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg)); if (selected) {
p.drawEllipse(inner); p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
} else if (_animation && _animation->_a_thumbOver.animating()) {
float64 over = _animation->a_thumbOver.current();
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
} else {
bool over = textlnkDrawOver(_thumbsavel);
p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg));
}
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
if (radial) {
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
_animation->radial.draw(p, rinner, bg);
}
style::sprite icon; style::sprite icon;
if (showPause) { if (showPause) {
icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause);
@ -4051,7 +4141,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, bool selected,
p.drawTextLeft(nameleft, nametop, width, _name, _namew); p.drawTextLeft(nameleft, nametop, width, _name, _namew);
} }
style::color status(selected ? (outbg ? st::mediaOutSelectColor : st::mediaInSelectColor) : (outbg ? st::mediaOutColor : st::mediaInColor)); style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
p.setFont(st::normalFont); p.setFont(st::normalFont);
p.setPen(status); p.setPen(status);
p.drawTextLeft(nameleft, statustop, width, _statusText); p.drawTextLeft(nameleft, statustop, width, _statusText);
@ -4062,7 +4152,7 @@ void HistoryDocument::drawInPlaylist(Painter &p, const HistoryItem *parent, bool
bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty();
int32 height = st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom(); int32 height = st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom();
style::color bg(selected ? st::msgInSelectBg : (over ? st::playlistHoverBg : st::msgInBg)); style::color bg(selected ? st::msgInBgSelected : (over ? st::playlistHoverBg : st::msgInBg));
p.fillRect(0, 0, width, height, bg->b); p.fillRect(0, 0, width, height, bg->b);
style::sprite img = st::mediaMusicInImg; style::sprite img = st::mediaMusicInImg;
@ -4105,7 +4195,7 @@ void HistoryDocument::drawInPlaylist(Painter &p, const HistoryItem *parent, bool
p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaNameTop, width, _name, _namew); p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaNameTop, width, _name, _namew);
} }
style::color status(selected ? st::mediaInSelectColor : st::mediaInColor); style::color status(selected ? st::mediaInFgSelected : st::mediaInFg);
p.setPen(status->p); p.setPen(status->p);
p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height, width, _statusText); p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height, width, _statusText);
} }
@ -4209,6 +4299,63 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
} }
} }
void HistoryDocument::linkOver(HistoryItem *parent, const TextLinkPtr &lnk) {
if (lnk == _thumbsavel && _data->already().isEmpty() && _data->data.isEmpty()) {
ensureAnimation(parent);
_animation->a_thumbOver.start(1);
_animation->_a_thumbOver.start();
}
}
void HistoryDocument::linkOut(HistoryItem *parent, const TextLinkPtr &lnk) {
if (_animation && lnk == _thumbsavel) {
_animation->a_thumbOver.start(0);
_animation->_a_thumbOver.start();
}
}
void HistoryDocument::step_thumbOver(const HistoryItem *parent, float64 ms, bool timer) {
float64 dt = ms / st::msgFileOverDuration;
if (dt >= 1) {
_animation->a_thumbOver.finish();
_animation->_a_thumbOver.stop();
checkAnimationFinished();
} else {
_animation->a_thumbOver.update(dt, anim::linear);
}
if (timer) {
Notify::redrawHistoryItem(parent);
}
}
void HistoryDocument::step_radial(const HistoryItem *parent, uint64 ms, bool timer) {
_animation->radial.update(_data->progress(), !_data->loader, ms);
if (!_animation->radial.animating()) {
checkAnimationFinished();
}
if (timer) {
Notify::redrawHistoryItem(parent);
}
}
void HistoryDocument::ensureAnimation(const HistoryItem *parent) const {
if (!_animation) {
_animation = new AnimationData(
animation(parent, const_cast<HistoryDocument*>(this), &HistoryDocument::step_thumbOver),
animation(parent, const_cast<HistoryDocument*>(this), &HistoryDocument::step_radial)
);
}
}
void HistoryDocument::checkAnimationFinished() {
if (_animation && !_animation->_a_thumbOver.animating() && !_animation->radial.animating()) {
if (!_data->already().isEmpty() || !_data->data.isEmpty()) {
delete _animation;
_animation = 0;
}
}
}
HistoryMedia *HistoryDocument::clone() const { HistoryMedia *HistoryDocument::clone() const {
return new HistoryDocument(*this); return new HistoryDocument(*this);
} }
@ -4217,6 +4364,11 @@ ImagePtr HistoryDocument::replyPreview() {
return _data->makeReplyPreview(); return _data->makeReplyPreview();
} }
HistoryDocument::~HistoryDocument() {
delete _animation;
_animation = 0;
}
HistoryGif::HistoryGif(DocumentData *document) : HistoryMedia() HistoryGif::HistoryGif(DocumentData *document) : HistoryMedia()
, _data(document) , _data(document)
, _openl(new DocumentOpenLink(_data)) , _openl(new DocumentOpenLink(_data))
@ -4237,9 +4389,9 @@ void HistoryGif::initDimensions(const HistoryItem *parent) {
_height = _minh; _height = _minh;
} }
void HistoryGif::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
if (width < 1) return; int32 width = w, height = _height, skipx = 0, skipy = 0;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty();
@ -4251,7 +4403,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, bool selected, int3
if (ph < 1) ph = 1; if (ph < 1) ph = 1;
} }
App::roundShadow(p, 0, 0, pw, ph, selected ? st::msgInSelectShadow : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); App::roundShadow(p, 0, 0, pw, ph, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
p.drawPixmap(0, 0, animated.current(pw * cIntRetinaFactor(), ph * cIntRetinaFactor(), true)); p.drawPixmap(0, 0, animated.current(pw * cIntRetinaFactor(), ph * cIntRetinaFactor(), true));
if (selected) { if (selected) {
@ -4387,9 +4539,10 @@ void HistorySticker::initDimensions(const HistoryItem *parent) {
w = qMin(lastw, _maxw); w = qMin(lastw, _maxw);
} }
void HistorySticker::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
if (width < 1) return; int32 width = w, height = _height, skipx = 0, skipy = 0;
if (width > _maxw) width = _maxw; if (width > _maxw) width = _maxw;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
@ -4429,7 +4582,7 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, bool selected,
} }
} }
parent->drawInfo(p, usex + usew, _height, selected, InfoDisplayOverImage); parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverImage);
if (reply) { if (reply) {
int32 rw = width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); int32 rw = width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
@ -4593,19 +4746,17 @@ HistoryMedia *HistoryContact::clone() const {
return new HistoryContact(userId, name.original(), phone); return new HistoryContact(userId, name.original(), phone);
} }
void HistoryContact::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryContact::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
if (width < 1) return; int32 width = w, height = _height, skipx = 0, skipy = 0;
int skipy = 0, replyFrom = 0, fwdFrom = 0;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
if (width >= _maxw) { if (width >= _maxw) {
width = _maxw; width = _maxw;
} }
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg)); style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow)); style::color sh(outbg ? (selected ? st::msgOutShadowSelected : st::msgOutShadow) : (selected ? st::msgInShadowSelected : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners)); RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
App::roundRect(p, 0, 0, width, _height, bg, cors, &sh); App::roundRect(p, 0, 0, width, _height, bg, cors, &sh);
@ -4626,13 +4777,10 @@ void HistoryContact::draw(Painter &p, const HistoryItem *parent, bool selected,
p.drawText(tleft, skipy + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, phone); p.drawText(tleft, skipy + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, phone);
} }
style::color status(selected ? (outbg ? st::mediaOutSelectColor : st::mediaInSelectColor) : (outbg ? st::mediaOutColor : st::mediaInColor)); style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
p.setPen(status->p); p.setPen(status->p);
name.drawElided(p, tleft, skipy + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height, secondwidth); name.drawElided(p, tleft, skipy + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height, secondwidth);
int32 fullRight = width, fullBottom = _height;
parent->drawInfo(p, fullRight, fullBottom, selected, InfoDisplayDefault);
} }
void HistoryContact::updateFrom(const MTPMessageMedia &media) { void HistoryContact::updateFrom(const MTPMessageMedia &media) {
@ -4795,9 +4943,9 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
_height = _minh; _height = _minh;
} }
void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
if (width < 1 || data->pendingTill) return; int32 width = w, height = _height, skipx = 0, skipy = 0;
int16 animw = 0, animh = 0; int16 animw = 0, animh = 0;
if (data->doc && animated.msg == parent) { if (data->doc && animated.msg == parent) {
@ -4826,8 +4974,8 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected,
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
style::color bar = (selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor)); style::color bar = (selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor));
style::color semibold = (selected ? (outbg ? st::msgOutServiceSelColor : st::msgInServiceSelColor) : (outbg ? st::msgOutServiceColor : st::msgInServiceColor)); style::color semibold = (selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg));
style::color regular = (selected ? (outbg ? st::msgOutSelectDateColor : st::msgInSelectDateColor) : (outbg ? st::msgOutDateColor : st::msgInDateColor)); style::color regular = (selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg));
p.fillRect(0, 0, st::webPageBar, _height - bottomSkip, bar->b); p.fillRect(0, 0, st::webPageBar, _height - bottomSkip, bar->b);
p.save(); p.save();
@ -4911,7 +5059,7 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected,
} }
p.drawPixmap(0, 0, pix); p.drawPixmap(0, 0, pix);
if (!full) { if (!full) {
uint64 dt = itemAnimations().animate(parent, getms()); uint64 dt = itemAnimations().animate(parent, ms);
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta); int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = (pixwidth - st::photoLoader.width()) / 2, y = (pixheight - st::photoLoader.height()) / 2; int32 x = (pixwidth - st::photoLoader.width()) / 2, y = (pixheight - st::photoLoader.height()) / 2;
@ -4947,7 +5095,7 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected,
int32 dateW = pixwidth - dateX - st::msgDateImgDelta; int32 dateW = pixwidth - dateX - st::msgDateImgDelta;
int32 dateH = pixheight - dateY - st::msgDateImgDelta; int32 dateH = pixheight - dateY - st::msgDateImgDelta;
App::roundRect(p, dateX, dateY, dateW, dateH, selected ? st::msgDateImgSelectBg : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); App::roundRect(p, dateX, dateY, dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
p.setFont(st::msgDateFont->f); p.setFont(st::msgDateFont->f);
p.setPen(st::msgDateImgColor->p); p.setPen(st::msgDateImgColor->p);
@ -5044,7 +5192,7 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected,
p.drawText(tleft, st::mediaNameTop + st::normalFont->ascent, _docName); p.drawText(tleft, st::mediaNameTop + st::normalFont->ascent, _docName);
} }
style::color status(selected ? (outbg ? st::mediaOutSelectColor : st::mediaInSelectColor) : (outbg ? st::mediaOutColor : st::mediaInColor)); style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg));
p.setPen(status->p); p.setPen(status->p);
p.drawText(tleft, st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->descent, statusText); p.drawText(tleft, st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->descent, statusText);
@ -5709,16 +5857,17 @@ void HistoryImageLink::initDimensions(const HistoryItem *parent) {
_height = _minh; _height = _minh;
} }
void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const { void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (width < 0) width = w; if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
int skipx = 0, skipy = 0, height = _height; int32 width = w, height = _height, skipx = 0, skipy = 0;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
if (!_title.isEmpty() || !_description.isEmpty()) { if (!_title.isEmpty() || !_description.isEmpty()) {
skipx = st::mediaPadding.left(); skipx = st::mediaPadding.left();
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg)); style::color bg(selected ? (outbg ? st::msgOutBgSelected : st::msgInBgSelected) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow)); style::color sh(selected ? (outbg ? st::msgOutShadowSelected : st::msgInShadowSelected) : (outbg ? st::msgOutShadow : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners)); RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
App::roundRect(p, 0, 0, width, _height, bg, cors, &sh); App::roundRect(p, 0, 0, width, _height, bg, cors, &sh);
@ -5743,7 +5892,7 @@ void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, bool selected
} }
height -= skipy + st::mediaPadding.bottom(); height -= skipy + st::mediaPadding.bottom();
} else { } else {
App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInSelectShadow : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
} }
data->load(); data->load();
@ -5789,7 +5938,7 @@ void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, bool selected
} }
int32 fullRight = skipx + width, fullBottom = _height - (skipx ? st::mediaPadding.bottom() : 0); int32 fullRight = skipx + width, fullBottom = _height - (skipx ? st::mediaPadding.bottom() : 0);
parent->drawInfo(p, fullRight, fullBottom, selected, InfoDisplayOverImage); parent->drawInfo(p, fullRight, fullBottom, skipx * 2 + width, selected, InfoDisplayOverImage);
} }
int32 HistoryImageLink::resize(int32 width, const HistoryItem *parent) { int32 HistoryImageLink::resize(int32 width, const HistoryItem *parent) {
@ -6188,8 +6337,8 @@ bool HistoryMessage::textHasLinks() {
return emptyText() ? false : _text.hasLinks(); return emptyText() ? false : _text.hasLinks();
} }
void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, bool selected, InfoDisplayType type) const { void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
p.setFont(st::msgDateFont->f); p.setFont(st::msgDateFont);
bool outbg = out() && !fromChannel(), overimg = (type == InfoDisplayOverImage); bool outbg = out() && !fromChannel(), overimg = (type == InfoDisplayOverImage);
int32 infoRight = right, infoBottom = bottom; int32 infoRight = right, infoBottom = bottom;
@ -6197,7 +6346,7 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, bool select
case InfoDisplayDefault: case InfoDisplayDefault:
infoRight -= st::msgPadding.right() - st::msgDateDelta.x(); infoRight -= st::msgPadding.right() - st::msgDateDelta.x();
infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y(); infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y();
p.setPen((selected ? (outbg ? st::msgOutSelectDateColor : st::msgInSelectDateColor) : (outbg ? st::msgOutDateColor : st::msgInDateColor))->p); p.setPen((selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg))->p);
break; break;
case InfoDisplayOverImage: case InfoDisplayOverImage:
infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x(); infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
@ -6207,11 +6356,13 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, bool select
} }
int32 infoW = HistoryMessage::infoWidth(); int32 infoW = HistoryMessage::infoWidth();
if (rtl()) infoRight = width - infoRight + infoW;
int32 dateX = infoRight - infoW; int32 dateX = infoRight - infoW;
int32 dateY = infoBottom - st::msgDateFont->height; int32 dateY = infoBottom - st::msgDateFont->height;
if (type == InfoDisplayOverImage) { if (type == InfoDisplayOverImage) {
int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y(); int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgSelectBg : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
} }
dateX += HistoryMessage::timeLeft(); dateX += HistoryMessage::timeLeft();
@ -6265,7 +6416,7 @@ void HistoryMessage::setViewsCount(int32 count) {
_viewsText = (_views >= 0) ? formatViewsCount(_views) : QString(); _viewsText = (_views >= 0) ? formatViewsCount(_views) : QString();
_viewsWidth = _viewsText.isEmpty() ? 0 : st::msgDateFont->width(_viewsText); _viewsWidth = _viewsText.isEmpty() ? 0 : st::msgDateFont->width(_viewsText);
if (was == _viewsWidth) { if (was == _viewsWidth) {
if (App::main()) App::main()->msgUpdated(this); Notify::redrawHistoryItem(this);
} else { } else {
if (_text.hasSkipBlock()) { if (_text.hasSkipBlock()) {
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight()); _text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
@ -6281,7 +6432,7 @@ void HistoryMessage::setId(MsgId newId) {
bool wasPositive = (id > 0), positive = (newId > 0); bool wasPositive = (id > 0), positive = (newId > 0);
HistoryItem::setId(newId); HistoryItem::setId(newId);
if (wasPositive == positive) { if (wasPositive == positive) {
if (App::main()) App::main()->msgUpdated(this); Notify::redrawHistoryItem(this);
} else { } else {
if (_text.hasSkipBlock()) { if (_text.hasSkipBlock()) {
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight()); _text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
@ -6293,17 +6444,18 @@ void HistoryMessage::setId(MsgId newId) {
} }
} }
void HistoryMessage::draw(Painter &p, uint32 selection) const { void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
bool outbg = out() && !fromChannel(), bubble = drawBubble(); bool outbg = out() && !fromChannel(), bubble = drawBubble(), selected = (selection == FullItemSel);
textstyleSet(&(outbg ? st::outTextStyle : st::inTextStyle)); textstyleSet(&(outbg ? st::outTextStyle : st::inTextStyle));
uint64 ms = App::main() ? App::main()->animActiveTime(this) : 0; uint64 animms = App::main() ? App::main()->animActiveTimeStart(this) : 0;
if (ms) { if (animms > 0 && animms <= ms) {
if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) { animms = ms - animms;
if (animms > st::activeFadeInDuration + st::activeFadeOutDuration) {
App::main()->stopAnimActive(); App::main()->stopAnimActive();
} else { } else {
float64 dt = (ms > st::activeFadeInDuration) ? (1 - (ms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (ms / float64(st::activeFadeInDuration)); float64 dt = (animms > st::activeFadeInDuration) ? (1 - (animms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (animms / float64(st::activeFadeInDuration));
float64 o = p.opacity(); float64 o = p.opacity();
p.setOpacity(o * dt); p.setOpacity(o * dt);
p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b); p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b);
@ -6311,7 +6463,6 @@ void HistoryMessage::draw(Painter &p, uint32 selection) const {
} }
} }
bool selected = (selection == FullItemSel);
if (_from->nameVersion > _fromVersion) { if (_from->nameVersion > _fromVersion) {
fromNameUpdated(); fromNameUpdated();
_fromVersion = _from->nameVersion; _fromVersion = _from->nameVersion;
@ -6327,15 +6478,15 @@ void HistoryMessage::draw(Painter &p, uint32 selection) const {
if (bubble) { if (bubble) {
QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom()); QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom());
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg)); style::color bg(selected ? (outbg ? st::msgOutBgSelected : st::msgInBgSelected) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow)); style::color sh(selected ? (outbg ? st::msgOutShadowSelected : st::msgInShadowSelected) : (outbg ? st::msgOutShadow : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners)); RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
App::roundRect(p, r, bg, cors, &sh); App::roundRect(p, r, bg, cors, &sh);
if (displayFromName()) { if (displayFromName()) {
p.setFont(st::msgNameFont->f); p.setFont(st::msgNameFont->f);
if (fromChannel()) { if (fromChannel()) {
p.setPen(selected ? st::msgInServiceSelColor : st::msgInServiceColor); p.setPen(selected ? st::msgInServiceFgSelected : st::msgInServiceFg);
} else { } else {
p.setPen(_from->color); p.setPen(_from->color);
} }
@ -6347,19 +6498,21 @@ void HistoryMessage::draw(Painter &p, uint32 selection) const {
if (_media && _media->isDisplayed()) { if (_media && _media->isDisplayed()) {
p.save(); p.save();
p.translate(left, _height - st::msgMargin.bottom() - _media->height()); int32 top = _height - st::msgMargin.bottom() - _media->height();
_media->draw(p, this, selected); p.translate(left, top);
_media->draw(p, this, r.translated(-left, -top), selected, ms);
p.restore(); p.restore();
if (!_media->customInfoLayout()) { if (!_media->customInfoLayout()) {
HistoryMessage::drawInfo(p, r.x() + r.width(), r.y() + r.height(), selected, InfoDisplayDefault); HistoryMessage::drawInfo(p, r.x() + r.width(), r.y() + r.height(), 2 * r.x() + r.width(), selected, InfoDisplayDefault);
} }
} else { } else {
HistoryMessage::drawInfo(p, r.x() + r.width(), r.y() + r.height(), selected, InfoDisplayDefault); HistoryMessage::drawInfo(p, r.x() + r.width(), r.y() + r.height(), 2 * r.x() + r.width(), selected, InfoDisplayDefault);
} }
} else { } else {
p.save(); p.save();
p.translate(left, st::msgMargin.top()); int32 top = st::msgMargin.top();
_media->draw(p, this, selected); p.translate(left, top);
_media->draw(p, this, r.translated(-left, -top), selected, ms);
p.restore(); p.restore();
} }
@ -6580,8 +6733,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const
, fwdDate(::date(msg.vfwd_date)) , fwdDate(::date(msg.vfwd_date))
, fwdFrom(App::peer(peerFromMTP(msg.vfwd_from_id))) , fwdFrom(App::peer(peerFromMTP(msg.vfwd_from_id)))
, fwdFromVersion(fwdFrom->nameVersion) , fwdFromVersion(fwdFrom->nameVersion)
, fromWidth(st::msgServiceFont->width(lang(lng_forwarded_from)) + st::msgServiceFont->spacew) , fromWidth(st::msgServiceFont->width(lang(lng_forwarded_from)) + st::msgServiceFont->spacew) {
{
fwdNameUpdated(); fwdNameUpdated();
} }
@ -6589,8 +6741,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId
, fwdDate(msg->dateForwarded()) , fwdDate(msg->dateForwarded())
, fwdFrom(msg->fromForwarded()) , fwdFrom(msg->fromForwarded())
, fwdFromVersion(fwdFrom->nameVersion) , fwdFromVersion(fwdFrom->nameVersion)
, fromWidth(st::msgServiceFont->width(lang(lng_forwarded_from)) + st::msgServiceFont->spacew) , fromWidth(st::msgServiceFont->width(lang(lng_forwarded_from)) + st::msgServiceFont->spacew) {
{
fwdNameUpdated(); fwdNameUpdated();
} }
@ -6615,19 +6766,19 @@ void HistoryForwarded::fwdNameUpdated() const {
} }
} }
void HistoryForwarded::draw(Painter &p, uint32 selection) const { void HistoryForwarded::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
if (drawBubble() && fwdFrom->nameVersion > fwdFromVersion) { if (drawBubble() && fwdFrom->nameVersion > fwdFromVersion) {
fwdNameUpdated(); fwdNameUpdated();
fwdFromVersion = fwdFrom->nameVersion; fwdFromVersion = fwdFrom->nameVersion;
} }
HistoryMessage::draw(p, selection); HistoryMessage::draw(p, r, selection, ms);
} }
void HistoryForwarded::drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w, bool selected) const { void HistoryForwarded::drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w, bool selected) const {
style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont); style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont);
bool outbg = out() && !fromChannel(); bool outbg = out() && !fromChannel();
p.setPen((selected ? (outbg ? st::msgOutServiceSelColor : st::msgInServiceSelColor) : (outbg ? st::msgOutServiceColor : st::msgInServiceColor))->p); p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p);
p.setFont(serviceFont->f); p.setFont(serviceFont->f);
if (w >= fromWidth) { if (w >= fromWidth) {
@ -6845,11 +6996,11 @@ void HistoryReply::replyToReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
} }
} }
void HistoryReply::draw(Painter &p, uint32 selection) const { void HistoryReply::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
if (replyToMsg && replyToMsg->from()->nameVersion > replyToVersion) { if (replyToMsg && replyToMsg->from()->nameVersion > replyToVersion) {
replyToNameUpdated(); replyToNameUpdated();
} }
HistoryMessage::draw(p, selection); HistoryMessage::draw(p, r, selection, ms);
} }
void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService) const { void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService) const {
@ -6881,14 +7032,14 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec
if (likeService) { if (likeService) {
p.setPen(st::white->p); p.setPen(st::white->p);
} else { } else {
p.setPen((selected ? (outbg ? st::msgOutServiceSelColor : st::msgInServiceSelColor) : (outbg ? st::msgOutServiceColor : st::msgInServiceColor))->p); p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p);
} }
replyToName.drawElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top(), w - st::msgReplyBarSkip - previewSkip); replyToName.drawElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top(), w - st::msgReplyBarSkip - previewSkip);
HistoryMessage *replyToAsMsg = replyToMsg->toHistoryMessage(); HistoryMessage *replyToAsMsg = replyToMsg->toHistoryMessage();
if (likeService) { if (likeService) {
} else if ((replyToAsMsg && replyToAsMsg->emptyText()) || replyToMsg->serviceMsg()) { } else if ((replyToAsMsg && replyToAsMsg->emptyText()) || replyToMsg->serviceMsg()) {
style::color date(selected ? (outbg ? st::msgOutSelectDateColor : st::msgInSelectDateColor) : (outbg ? st::msgOutDateColor : st::msgInDateColor)); style::color date(outbg ? (selected ? st::msgOutDateFgSelected : st::msgOutDateFg) : (selected ? st::msgInDateFgSelected : st::msgInDateFg));
p.setPen(date->p); p.setPen(date->p);
} else { } else {
p.setPen(st::msgColor->p); p.setPen(st::msgColor->p);
@ -6897,7 +7048,7 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec
} }
} else { } else {
p.setFont(st::msgDateFont->f); p.setFont(st::msgDateFont->f);
style::color date(selected ? (outbg ? st::msgOutSelectDateColor : st::msgInSelectDateColor) : (outbg ? st::msgOutDateColor : st::msgInDateColor)); style::color date(outbg ? (selected ? st::msgOutDateFgSelected : st::msgOutDateFg) : (selected ? st::msgInDateFgSelected : st::msgInDateFg));
if (likeService) { if (likeService) {
p.setPen(st::white->p); p.setPen(st::white->p);
} else { } else {
@ -7210,14 +7361,15 @@ void HistoryServiceMsg::setServiceText(const QString &text) {
initDimensions(); initDimensions();
} }
void HistoryServiceMsg::draw(Painter &p, uint32 selection) const { void HistoryServiceMsg::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
uint64 ms = App::main() ? App::main()->animActiveTime(this) : 0; uint64 animms = App::main() ? App::main()->animActiveTimeStart(this) : 0;
if (ms) { if (animms > 0 && animms <= ms) {
if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) { animms = ms - animms;
if (animms > st::activeFadeInDuration + st::activeFadeOutDuration) {
App::main()->stopAnimActive(); App::main()->stopAnimActive();
} else { } else {
textstyleSet(&st::inTextStyle); textstyleSet(&st::inTextStyle);
float64 dt = (ms > st::activeFadeInDuration) ? (1 - (ms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (ms / float64(st::activeFadeInDuration)); float64 dt = (animms > st::activeFadeInDuration) ? (1 - (animms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (animms / float64(st::activeFadeInDuration));
float64 o = p.opacity(); float64 o = p.opacity();
p.setOpacity(o * dt); p.setOpacity(o * dt);
p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b); p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b);
@ -7233,8 +7385,9 @@ void HistoryServiceMsg::draw(Painter &p, uint32 selection) const {
if (_media) { if (_media) {
height -= st::msgServiceMargin.top() + _media->height(); height -= st::msgServiceMargin.top() + _media->height();
p.save(); p.save();
p.translate(st::msgServiceMargin.left() + (width - _media->maxWidth()) / 2, st::msgServiceMargin.top() + height + st::msgServiceMargin.top()); int32 left = st::msgServiceMargin.left() + (width - _media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top();
_media->draw(p, this, selection == FullItemSel); p.translate(left, top);
_media->draw(p, this, r.translated(-left, -top), selection == FullItemSel, ms);
p.restore(); p.restore();
} }
@ -7435,7 +7588,7 @@ HistoryServiceMsg(history, block, clientMsgId(), date, qsl("-")),
_wasMinId(wasMinId) { _wasMinId(wasMinId) {
} }
void HistoryCollapse::draw(Painter &p, uint32 selection) const { void HistoryCollapse::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
} }
void HistoryCollapse::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const { void HistoryCollapse::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
@ -7471,7 +7624,7 @@ void HistoryUnreadBar::setCount(int32 count) {
text = lng_unread_bar(lt_count, count); text = lng_unread_bar(lt_count, count);
} }
void HistoryUnreadBar::draw(Painter &p, uint32 selection) const { void HistoryUnreadBar::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
p.fillRect(0, st::lineWidth, _history->width, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG->b); p.fillRect(0, st::lineWidth, _history->width, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG->b);
p.fillRect(0, st::unreadBarHeight - st::lineWidth, _history->width, st::lineWidth, st::unreadBarBorder->b); p.fillRect(0, st::unreadBarHeight - st::lineWidth, _history->width, st::lineWidth, st::unreadBarBorder->b);
p.setFont(st::unreadBarFont->f); p.setFont(st::unreadBarFont->f);

View File

@ -845,7 +845,7 @@ public:
virtual void initDimensions() = 0; virtual void initDimensions() = 0;
virtual int32 resize(int32 width) = 0; // return new height virtual int32 resize(int32 width) = 0; // return new height
virtual void draw(Painter &p, uint32 selection) const = 0; virtual void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const = 0;
History *history() { History *history() {
return _history; return _history;
@ -933,6 +933,10 @@ public:
virtual uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const { virtual uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
return (from << 16) | to; return (from << 16) | to;
} }
virtual void linkOver(const TextLinkPtr &lnk) {
}
virtual void linkOut(const TextLinkPtr &lnk) {
}
virtual HistoryItemType type() const { virtual HistoryItemType type() const {
return HistoryItemMsg; return HistoryItemMsg;
} }
@ -955,7 +959,7 @@ public:
return inDialogsText(); return inDialogsText();
} }
virtual void drawInfo(Painter &p, int32 right, int32 bottom, bool selected, InfoDisplayType type) const { virtual void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
} }
virtual void setViewsCount(int32 count) { virtual void setViewsCount(int32 count) {
} }
@ -1112,6 +1116,34 @@ private:
HistoryItem *regItem(HistoryItem *item, bool returnExisting = false); HistoryItem *regItem(HistoryItem *item, bool returnExisting = false);
class RadialAnimation {
public:
RadialAnimation(int32 thickness, AnimationCallbacks *callbacks);
float64 opacity() const {
return _opacity;
}
bool animating() const {
return _animation.animating();
}
void start(float64 prg);
void update(float64 prg, bool finished, uint64 ms);
void stop();
void draw(Painter &p, const QRect &inner, const style::color &color);
private:
int32 _thickness;
uint64 _firstStart, _lastStart, _lastTime;
float64 _opacity;
anim::fvalue a_arcEnd, a_arcStart;
Animation _animation;
};
class HistoryMedia : public HistoryElem { class HistoryMedia : public HistoryElem {
public: public:
@ -1136,7 +1168,11 @@ public:
return _height; return _height;
} }
virtual void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; virtual void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0;
virtual void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const = 0; virtual void linkOver(HistoryItem *parent, const TextLinkPtr &lnk) {
}
virtual void linkOut(HistoryItem *parent, const TextLinkPtr &lnk) {
}
virtual void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const = 0;
virtual bool uploading() const { virtual bool uploading() const {
return false; return false;
} }
@ -1196,7 +1232,7 @@ public:
void init(); void init();
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
int32 resize(int32 width, const HistoryItem *parent); int32 resize(int32 width, const HistoryItem *parent);
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypePhoto; return MediaTypePhoto;
@ -1268,7 +1304,7 @@ public:
HistoryVideo(const MTPDvideo &video, const QString &caption, HistoryItem *parent); HistoryVideo(const MTPDvideo &video, const QString &caption, HistoryItem *parent);
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
int32 resize(int32 width, const HistoryItem *parent); int32 resize(int32 width, const HistoryItem *parent);
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeVideo; return MediaTypeVideo;
@ -1323,7 +1359,7 @@ public:
HistoryAudio(const MTPDaudio &audio); HistoryAudio(const MTPDaudio &audio);
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeAudio; return MediaTypeAudio;
} }
@ -1372,7 +1408,7 @@ public:
return !_data->song() && !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height(); return !_data->song() && !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
} }
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
int32 resize(int32 width, const HistoryItem *parent); int32 resize(int32 width, const HistoryItem *parent);
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeDocument; return MediaTypeDocument;
@ -1385,6 +1421,8 @@ public:
return (_data->status == FileUploading); return (_data->status == FileUploading);
} }
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void linkOver(HistoryItem *parent, const TextLinkPtr &lnk);
void linkOut(HistoryItem *parent, const TextLinkPtr &lnk);
HistoryMedia *clone() const; HistoryMedia *clone() const;
DocumentData *document() { DocumentData *document() {
@ -1414,6 +1452,8 @@ public:
return _data->song(); return _data->song();
} }
~HistoryDocument();
private: private:
DocumentData *_data; DocumentData *_data;
@ -1433,6 +1473,25 @@ private:
void setStatusSize(int32 newSize, qint64 realDuration = 0) const; void setStatusSize(int32 newSize, qint64 realDuration = 0) const;
bool updateStatusText(const HistoryItem *parent) const; // returns showPause bool updateStatusText(const HistoryItem *parent) const; // returns showPause
void step_thumbOver(const HistoryItem *parent, float64 ms, bool timer);
void step_radial(const HistoryItem *parent, uint64 ms, bool timer);
void ensureAnimation(const HistoryItem *parent) const;
void checkAnimationFinished();
struct AnimationData {
AnimationData(AnimationCallbacks *thumbOverCallbacks, AnimationCallbacks *radialCallbacks) : a_thumbOver(0, 0)
, _a_thumbOver(thumbOverCallbacks)
, radial(st::msgFileRadialLine, radialCallbacks) {
}
anim::fvalue a_thumbOver;
Animation _a_thumbOver;
RadialAnimation radial;
};
mutable AnimationData *_animation;
}; };
class HistoryGif : public HistoryMedia { class HistoryGif : public HistoryMedia {
@ -1441,7 +1500,7 @@ public:
HistoryGif(DocumentData *document); HistoryGif(DocumentData *document);
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
int32 resize(int32 width, const HistoryItem *parent); int32 resize(int32 width, const HistoryItem *parent);
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeGif; return MediaTypeGif;
@ -1500,7 +1559,7 @@ public:
HistorySticker(DocumentData *document); HistorySticker(DocumentData *document);
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
int32 resize(int32 width, const HistoryItem *parent); int32 resize(int32 width, const HistoryItem *parent);
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeSticker; return MediaTypeSticker;
@ -1544,7 +1603,7 @@ public:
HistoryContact(int32 userId, const QString &fullname, const QString &phone); HistoryContact(int32 userId, const QString &fullname, const QString &phone);
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeContact; return MediaTypeContact;
} }
@ -1577,7 +1636,7 @@ public:
HistoryWebPage(WebPageData *data); HistoryWebPage(WebPageData *data);
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
bool isDisplayed() const { bool isDisplayed() const {
return !data->pendingTill; return !data->pendingTill;
} }
@ -1691,7 +1750,7 @@ public:
int32 fullHeight() const; int32 fullHeight() const;
void initDimensions(const HistoryItem *parent); void initDimensions(const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
int32 resize(int32 width, const HistoryItem *parent); int32 resize(int32 width, const HistoryItem *parent);
HistoryMediaType type() const { HistoryMediaType type() const {
return MediaTypeImageLink; return MediaTypeImageLink;
@ -1751,10 +1810,11 @@ public:
} }
bool uploading() const; bool uploading() const;
void drawInfo(Painter &p, int32 right, int32 bottom, bool selected, InfoDisplayType type) const; void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const;
void setViewsCount(int32 count); void setViewsCount(int32 count);
void setId(MsgId newId); void setId(MsgId newId);
void draw(Painter &p, uint32 selection) const; void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
virtual void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const; virtual void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width); int32 resize(int32 width);
@ -1768,6 +1828,12 @@ public:
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const { uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
return _text.adjustSelection(from, to, type); return _text.adjustSelection(from, to, type);
} }
void linkOver(const TextLinkPtr &lnk) {
if (_media) _media->linkOver(this, lnk);
}
void linkOut(const TextLinkPtr &lnk) {
if (_media) _media->linkOut(this, lnk);
}
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const; void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const;
QString notificationHeader() const; QString notificationHeader() const;
@ -1867,7 +1933,7 @@ public:
void initDimensions(); void initDimensions();
void fwdNameUpdated() const; void fwdNameUpdated() const;
void draw(Painter &p, uint32 selection) const; void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
void drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w, bool selected) const; void drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w, bool selected) const;
void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const; void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width); int32 resize(int32 width);
@ -1923,7 +1989,7 @@ public:
HistoryItem *replyToMessage() const; HistoryItem *replyToMessage() const;
void replyToReplaced(HistoryItem *oldItem, HistoryItem *newItem); void replyToReplaced(HistoryItem *oldItem, HistoryItem *newItem);
void draw(Painter &p, uint32 selection) const; void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
void drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService = false) const; void drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService = false) const;
void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const; void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width); int32 resize(int32 width);
@ -1966,7 +2032,7 @@ public:
void initDimensions(); void initDimensions();
void draw(Painter &p, uint32 selection) const; void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
int32 resize(int32 width); int32 resize(int32 width);
bool hasPoint(int32 x, int32 y) const; bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const; void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
@ -2077,7 +2143,7 @@ class HistoryCollapse : public HistoryServiceMsg {
public: public:
HistoryCollapse(History *history, HistoryBlock *block, MsgId wasMinId, const QDateTime &date); HistoryCollapse(History *history, HistoryBlock *block, MsgId wasMinId, const QDateTime &date);
void draw(Painter &p, uint32 selection) const; void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const; void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const {
symbol = 0xFFFF; symbol = 0xFFFF;
@ -2119,7 +2185,7 @@ public:
void setCount(int32 count); void setCount(int32 count);
void draw(Painter &p, uint32 selection) const; void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
int32 resize(int32 width); int32 resize(int32 width);
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const; void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const;

View File

@ -116,11 +116,11 @@ void HistoryInner::messagesReceivedDown(PeerData *peer, const QVector<MTPMessage
} }
} }
void HistoryInner::updateMsg(const HistoryItem *msg) { void HistoryInner::redrawItem(const HistoryItem *item) {
if (!msg || msg->detached() || !_history) return; if (!item || item->detached() || !_history) return;
int32 msgy = itemTop(msg); int32 msgy = itemTop(item);
if (msgy >= 0) { if (msgy >= 0) {
update(0, msgy, width(), msg->height()); update(0, msgy, width(), item->height());
} }
} }
@ -129,13 +129,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
if (!App::main()) return; if (!App::main()) return;
Painter p(this);
QRect r(e->rect()); QRect r(e->rect());
bool trivial = (rect() == r); bool trivial = (rect() == r);
Painter p(this);
if (!trivial) { if (!trivial) {
p.setClipRect(r); p.setClipRect(r);
} }
uint64 ms = getms();
if (!_firstLoading && _botInfo && !_botInfo->text.isEmpty() && _botDescHeight > 0) { if (!_firstLoading && _botInfo && !_botInfo->text.isEmpty() && _botDescHeight > 0) {
if (r.y() < _botDescRect.y() + _botDescRect.height() && r.y() + r.height() > _botDescRect.y()) { if (r.y() < _botDescRect.y() + _botDescRect.height() && r.y() + r.height() > _botDescRect.y()) {
@ -189,7 +189,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
sel = i.value(); sel = i.value();
} }
} }
item->draw(p, sel); item->draw(p, r.translated(0, -y), sel, ms);
if (item->hasViews()) { if (item->hasViews()) {
App::main()->scheduleViewIncrement(item); App::main()->scheduleViewIncrement(item);
@ -233,7 +233,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
sel = i.value(); sel = i.value();
} }
} }
item->draw(p, sel); item->draw(p, r.translated(0, -y), sel, ms);
if (item->hasViews()) { if (item->hasViews()) {
App::main()->scheduleViewIncrement(item); App::main()->scheduleViewIncrement(item);
@ -475,16 +475,16 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
if (button != Qt::LeftButton) return; if (button != Qt::LeftButton) return;
if (App::pressedItem() != App::hoveredItem()) { if (App::pressedItem() != App::hoveredItem()) {
updateMsg(App::pressedItem()); redrawItem(App::pressedItem());
App::pressedItem(App::hoveredItem()); App::pressedItem(App::hoveredItem());
updateMsg(App::pressedItem()); redrawItem(App::pressedItem());
} }
if (textlnkDown() != textlnkOver()) { if (textlnkDown() != textlnkOver()) {
updateMsg(App::pressedLinkItem()); redrawItem(App::pressedLinkItem());
textlnkDown(textlnkOver()); textlnkDown(textlnkOver());
App::pressedLinkItem(App::hoveredLinkItem()); App::pressedLinkItem(App::hoveredLinkItem());
updateMsg(App::pressedLinkItem()); redrawItem(App::pressedLinkItem());
updateMsg(App::pressedItem()); redrawItem(App::pressedItem());
} }
_dragAction = NoDrag; _dragAction = NoDrag;
@ -512,7 +512,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
uint32 selStatus = (symbol << 16) | symbol; uint32 selStatus = (symbol << 16) | symbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) { if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key()); redrawItem(_selected.cbegin().key());
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_dragItem, selStatus);
@ -553,12 +553,12 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol; uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) { if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key()); redrawItem(_selected.cbegin().key());
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_dragItem, selStatus);
_dragAction = Selecting; _dragAction = Selecting;
updateMsg(_dragItem); redrawItem(_dragItem);
} else { } else {
_dragAction = PrepareSelect; _dragAction = PrepareSelect;
} }
@ -731,7 +731,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
} }
} }
if (textlnkDown()) { if (textlnkDown()) {
updateMsg(App::pressedLinkItem()); redrawItem(App::pressedLinkItem());
textlnkDown(TextLinkPtr()); textlnkDown(TextLinkPtr());
App::pressedLinkItem(0); App::pressedLinkItem(0);
if (!textlnkOver() && _cursor != style::cur_default) { if (!textlnkOver() && _cursor != style::cur_default) {
@ -740,7 +740,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
} }
} }
if (App::pressedItem()) { if (App::pressedItem()) {
updateMsg(App::pressedItem()); redrawItem(App::pressedItem());
App::pressedItem(0); App::pressedItem(0);
} }
@ -764,16 +764,16 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
} else { } else {
_selected.erase(i); _selected.erase(i);
} }
updateMsg(_dragItem); redrawItem(_dragItem);
} else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) { } else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_dragItem); SelectedItems::iterator i = _selected.find(_dragItem);
if (i != _selected.cend() && i.value() == FullItemSel) { if (i != _selected.cend() && i.value() == FullItemSel) {
_selected.erase(i); _selected.erase(i);
updateMsg(_dragItem); redrawItem(_dragItem);
} else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { } else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
if (_selected.size() < MaxSelectedItems) { if (_selected.size() < MaxSelectedItems) {
_selected.insert(_dragItem, FullItemSel); _selected.insert(_dragItem, FullItemSel);
updateMsg(_dragItem); redrawItem(_dragItem);
} }
} else { } else {
_selected.clear(); _selected.clear();
@ -818,7 +818,7 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
_dragAction = Selecting; _dragAction = Selecting;
uint32 selStatus = (symbol << 16) | symbol; uint32 selStatus = (symbol << 16) | symbol;
if (!_selected.isEmpty()) { if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key()); redrawItem(_selected.cbegin().key());
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_dragItem, selStatus);
@ -1348,12 +1348,17 @@ void HistoryInner::enterEvent(QEvent *e) {
} }
void HistoryInner::leaveEvent(QEvent *e) { void HistoryInner::leaveEvent(QEvent *e) {
if (textlnkOver()) { if (HistoryItem *item = App::hoveredItem()) {
updateMsg(App::hoveredItem()); redrawItem(item);
updateMsg(App::hoveredLinkItem());
textlnkOver(TextLinkPtr());
App::hoveredLinkItem(0);
App::hoveredItem(0); App::hoveredItem(0);
}
if (textlnkOver()) {
if (HistoryItem *item = App::hoveredLinkItem()) {
item->linkOut(textlnkOver());
redrawItem(item);
App::hoveredLinkItem(0);
}
textlnkOver(TextLinkPtr());
if (!textlnkDown() && _cursor != style::cur_default) { if (!textlnkDown() && _cursor != style::cur_default) {
_cursor = style::cur_default; _cursor = style::cur_default;
setCursor(_cursor); setCursor(_cursor);
@ -1522,11 +1527,11 @@ void HistoryInner::onUpdateSelected() {
App::mousedItem(item); App::mousedItem(item);
m = mapMouseToItem(point, item); m = mapMouseToItem(point, item);
if (item->hasPoint(m.x(), m.y())) { if (item->hasPoint(m.x(), m.y())) {
updateMsg(App::hoveredItem()); redrawItem(App::hoveredItem());
App::hoveredItem(item); App::hoveredItem(item);
updateMsg(App::hoveredItem()); redrawItem(App::hoveredItem());
} else if (App::hoveredItem()) { } else if (App::hoveredItem()) {
updateMsg(App::hoveredItem()); redrawItem(App::hoveredItem());
App::hoveredItem(0); App::hoveredItem(0);
} }
} }
@ -1552,8 +1557,9 @@ void HistoryInner::onUpdateSelected() {
if (lnk != textlnkOver()) { if (lnk != textlnkOver()) {
lnkChanged = true; lnkChanged = true;
if (textlnkOver()) { if (textlnkOver()) {
if (App::hoveredLinkItem()) { if (HistoryItem *item = App::hoveredLinkItem()) {
updateMsg(App::hoveredLinkItem()); item->linkOut(textlnkOver());
redrawItem(item);
} else { } else {
update(_botDescRect); update(_botDescRect);
} }
@ -1562,8 +1568,9 @@ void HistoryInner::onUpdateSelected() {
QToolTip::hideText(); QToolTip::hideText();
App::hoveredLinkItem((lnk && !lnkInDesc) ? item : 0); App::hoveredLinkItem((lnk && !lnkInDesc) ? item : 0);
if (textlnkOver()) { if (textlnkOver()) {
if (App::hoveredLinkItem()) { if (HistoryItem *item = App::hoveredLinkItem()) {
updateMsg(App::hoveredLinkItem()); item->linkOver(textlnkOver());
redrawItem(item);
} else { } else {
update(_botDescRect); update(_botDescRect);
} }
@ -2947,7 +2954,7 @@ void HistoryWidget::updateStickers() {
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed)); _stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
} }
void HistoryWidget::notifyBotCommandsChanged(UserData *user) { void HistoryWidget::notify_botCommandsChanged(UserData *user) {
if (_peer && (_peer == user || !_peer->isUser())) { if (_peer && (_peer == user || !_peer->isUser())) {
if (_attachMention.clearFilteredCommands()) { if (_attachMention.clearFilteredCommands()) {
checkMentionDropdown(); checkMentionDropdown();
@ -2955,7 +2962,7 @@ void HistoryWidget::notifyBotCommandsChanged(UserData *user) {
} }
} }
void HistoryWidget::notifyUserIsBotChanged(UserData *user) { void HistoryWidget::notify_userIsBotChanged(UserData *user) {
if (_peer && _peer == user) { if (_peer && _peer == user) {
_list->notifyIsBotChanged(); _list->notifyIsBotChanged();
_list->updateBotInfo(); _list->updateBotInfo();
@ -2964,7 +2971,7 @@ void HistoryWidget::notifyUserIsBotChanged(UserData *user) {
} }
} }
void HistoryWidget::notifyMigrateUpdated(PeerData *peer) { void HistoryWidget::notify_migrateUpdated(PeerData *peer) {
if (_peer) { if (_peer) {
if (_peer == peer) { if (_peer == peer) {
if (peer->migrateTo()) { if (peer->migrateTo()) {
@ -5442,7 +5449,7 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadPhoto, 0); updateSendAction(item->history(), SendActionUploadPhoto, 0);
} }
// msgUpdated(item); // Notify::redrawHistoryItem(item);
} }
} }
@ -5464,7 +5471,7 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0); updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0);
} }
msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
@ -5475,7 +5482,7 @@ void HistoryWidget::onAudioProgress(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0); updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0);
} }
msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
@ -5486,7 +5493,7 @@ void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadPhoto, -1); updateSendAction(item->history(), SendActionUploadPhoto, -1);
} }
// msgUpdated(item); // Notify::redrawHistoryItem(item);
} }
} }
@ -5497,7 +5504,7 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadFile, -1); updateSendAction(item->history(), SendActionUploadFile, -1);
} }
msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
@ -5508,7 +5515,7 @@ void HistoryWidget::onAudioFailed(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadAudio, -1); updateSendAction(item->history(), SendActionUploadAudio, -1);
} }
msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
@ -5595,9 +5602,9 @@ void HistoryWidget::peerMessagesUpdated() {
if (_list) peerMessagesUpdated(_peer->id); if (_list) peerMessagesUpdated(_peer->id);
} }
void HistoryWidget::msgUpdated(const HistoryItem *msg) { void HistoryWidget::notify_redrawHistoryItem(const HistoryItem *item) {
if (_peer && _list && (msg->history() == _history || (_migrated && msg->history() == _migrated))) { if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
_list->updateMsg(msg); _list->redrawItem(item);
} }
} }
@ -6528,14 +6535,14 @@ void HistoryWidget::onAnimActiveStep() {
if (getms() - _animActiveStart > st::activeFadeInDuration + st::activeFadeOutDuration) { if (getms() - _animActiveStart > st::activeFadeInDuration + st::activeFadeOutDuration) {
stopAnimActive(); stopAnimActive();
} else { } else {
App::main()->msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
uint64 HistoryWidget::animActiveTime(const HistoryItem *msg) const { uint64 HistoryWidget::animActiveTimeStart(const HistoryItem *msg) const {
if (!msg) return 0; if (!msg) return 0;
if ((msg->history() == _history && msg->id == _activeAnimMsgId) || (_migrated && msg->history() == _migrated && msg->id == -_activeAnimMsgId)) { if ((msg->history() == _history && msg->id == _activeAnimMsgId) || (_migrated && msg->history() == _migrated && msg->id == -_activeAnimMsgId)) {
return _animActiveTimer.isActive() ? (getms() - _animActiveStart) : 0; return _animActiveTimer.isActive() ? _animActiveStart : 0;
} }
return 0; return 0;
} }
@ -6645,11 +6652,11 @@ void HistoryWidget::drawField(Painter &p) {
} }
p.setPen(st::replyColor->p); p.setPen(st::replyColor->p);
_replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right()); _replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
p.setPen((((drawReplyTo->toHistoryMessage() && drawReplyTo->toHistoryMessage()->emptyText()) || drawReplyTo->serviceMsg()) ? st::msgInDateColor : st::msgColor)->p); p.setPen((((drawReplyTo->toHistoryMessage() && drawReplyTo->toHistoryMessage()->emptyText()) || drawReplyTo->serviceMsg()) ? st::msgInDateFg : st::msgColor)->p);
_replyToText.drawElided(p, replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right()); _replyToText.drawElided(p, replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
} else { } else {
p.setFont(st::msgDateFont->f); p.setFont(st::msgDateFont->f);
p.setPen(st::msgInDateColor->p); p.setPen(st::msgInDateFg->p);
p.drawText(replyLeft, backy + st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right())); p.drawText(replyLeft, backy + st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right()));
} }
} }
@ -6669,7 +6676,7 @@ void HistoryWidget::drawField(Painter &p) {
} }
p.setPen(st::replyColor->p); p.setPen(st::replyColor->p);
from->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top(), width() - forwardLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right()); from->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top(), width() - forwardLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
p.setPen((serviceColor ? st::msgInDateColor : st::msgColor)->p); p.setPen((serviceColor ? st::msgInDateFg : st::msgColor)->p);
text->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - forwardLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right()); text->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - forwardLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
} }
} }

View File

@ -69,7 +69,7 @@ public:
int32 recountHeight(HistoryItem *resizedItem); int32 recountHeight(HistoryItem *resizedItem);
void updateSize(); void updateSize();
void updateMsg(const HistoryItem *msg); void redrawItem(const HistoryItem *item);
bool canCopySelected() const; bool canCopySelected() const;
bool canDeleteSelected() const; bool canDeleteSelected() const;
@ -430,7 +430,7 @@ public:
void peerMessagesUpdated(PeerId peer); void peerMessagesUpdated(PeerId peer);
void peerMessagesUpdated(); void peerMessagesUpdated();
void msgUpdated(const HistoryItem *msg); void notify_redrawHistoryItem(const HistoryItem *item);
void newUnreadMsg(History *history, HistoryItem *item); void newUnreadMsg(History *history, HistoryItem *item);
void historyToDown(History *history); void historyToDown(History *history);
void historyWasRead(bool force = true); void historyWasRead(bool force = true);
@ -487,7 +487,7 @@ public:
bool touchScroll(const QPoint &delta); bool touchScroll(const QPoint &delta);
uint64 animActiveTime(const HistoryItem *msg) const; uint64 animActiveTimeStart(const HistoryItem *msg) const;
void stopAnimActive(); void stopAnimActive();
void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true); void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true);
@ -558,9 +558,9 @@ public:
resizeEvent(0); resizeEvent(0);
} }
void notifyBotCommandsChanged(UserData *user); void notify_botCommandsChanged(UserData *user);
void notifyUserIsBotChanged(UserData *user); void notify_userIsBotChanged(UserData *user);
void notifyMigrateUpdated(PeerData *peer); void notify_migrateUpdated(PeerData *peer);
~HistoryWidget(); ~HistoryWidget();

View File

@ -683,18 +683,6 @@ void MainWidget::updateStickers() {
history.updateStickers(); history.updateStickers();
} }
void MainWidget::notifyBotCommandsChanged(UserData *bot) {
history.notifyBotCommandsChanged(bot);
}
void MainWidget::notifyUserIsBotChanged(UserData *bot) {
history.notifyUserIsBotChanged(bot);
}
void MainWidget::notifyMigrateUpdated(PeerData *peer) {
history.notifyMigrateUpdated(peer);
}
void MainWidget::onUpdateMuted() { void MainWidget::onUpdateMuted() {
App::updateMuted(); App::updateMuted();
} }
@ -758,6 +746,27 @@ void MainWidget::ui_hideStickerPreview() {
_stickerPreview->hidePreview(); _stickerPreview->hidePreview();
} }
void MainWidget::notify_botCommandsChanged(UserData *bot) {
history.notify_botCommandsChanged(bot);
}
void MainWidget::notify_userIsBotChanged(UserData *bot) {
history.notify_userIsBotChanged(bot);
}
void MainWidget::notify_migrateUpdated(PeerData *peer) {
history.notify_migrateUpdated(peer);
}
void MainWidget::notify_redrawHistoryItem(const HistoryItem *msg) {
if (!msg) return;
history.notify_redrawHistoryItem(msg);
if (!msg->history()->dialogs.isEmpty() && msg->history()->lastMsg == msg) {
dialogs.dlgUpdated(msg->history()->dialogs[0]);
}
if (overview) overview->notify_redrawHistoryItem(msg);
}
void MainWidget::noHider(HistoryHider *destroyed) { void MainWidget::noHider(HistoryHider *destroyed) {
if (_hider == destroyed) { if (_hider == destroyed) {
_hider = 0; _hider = 0;
@ -1303,8 +1312,8 @@ void MainWidget::readServerHistory(History *hist, bool force) {
} }
} }
uint64 MainWidget::animActiveTime(const HistoryItem *msg) const { uint64 MainWidget::animActiveTimeStart(const HistoryItem *msg) const {
return history.animActiveTime(msg); return history.animActiveTimeStart(msg);
} }
void MainWidget::stopAnimActive() { void MainWidget::stopAnimActive() {
@ -1474,7 +1483,7 @@ void MainWidget::itemResized(HistoryItem *row, bool scrollToIt) {
if (overview) { if (overview) {
overview->itemResized(row, scrollToIt); overview->itemResized(row, scrollToIt);
} }
if (row) msgUpdated(row); if (row) Notify::redrawHistoryItem(row);
} }
bool MainWidget::overviewFailed(PeerData *peer, const RPCError &error, mtpRequestId req) { bool MainWidget::overviewFailed(PeerData *peer, const RPCError &error, mtpRequestId req) {
@ -1624,7 +1633,7 @@ void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
VideoItems::const_iterator i = items.constFind(video); VideoItems::const_iterator i = items.constFind(video);
if (i != items.cend()) { if (i != items.cend()) {
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) { for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
msgUpdated(j.key()); Notify::redrawHistoryItem(j.key());
} }
} }
} }
@ -1701,7 +1710,7 @@ void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
AudioItems::const_iterator i = items.constFind(audio); AudioItems::const_iterator i = items.constFind(audio);
if (i != items.cend()) { if (i != items.cend()) {
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) { for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
msgUpdated(j.key()); Notify::redrawHistoryItem(j.key());
} }
} }
} }
@ -1736,7 +1745,7 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
} }
if (HistoryItem *item = App::histItemById(audioId.msgId)) { if (HistoryItem *item = App::histItemById(audioId.msgId)) {
msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
@ -1797,7 +1806,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
} }
if (HistoryItem *item = App::histItemById(songId.msgId)) { if (HistoryItem *item = App::histItemById(songId.msgId)) {
msgUpdated(item); Notify::redrawHistoryItem(item);
} }
} }
@ -1884,7 +1893,7 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
DocumentItems::const_iterator i = items.constFind(document); DocumentItems::const_iterator i = items.constFind(document);
if (i != items.cend()) { if (i != items.cend()) {
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) { for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
msgUpdated(j.key()); Notify::redrawHistoryItem(j.key());
} }
} }
App::wnd()->documentUpdated(document); App::wnd()->documentUpdated(document);
@ -2630,15 +2639,6 @@ void MainWidget::onActiveChannelUpdateFull() {
} }
} }
void MainWidget::msgUpdated(const HistoryItem *msg) {
if (!msg) return;
history.msgUpdated(msg);
if (!msg->history()->dialogs.isEmpty() && msg->history()->lastMsg == msg) {
dialogs.dlgUpdated(msg->history()->dialogs[0]);
}
if (overview) overview->msgUpdated(msg);
}
void MainWidget::historyToDown(History *hist) { void MainWidget::historyToDown(History *hist) {
history.historyToDown(hist); history.historyToDown(hist);
} }
@ -4227,7 +4227,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
msgRow->history()->unregTyping(App::self()); msgRow->history()->unregTyping(App::self());
} }
if (!App::historyRegItem(msgRow)) { if (!App::historyRegItem(msgRow)) {
msgUpdated(msgRow); Notify::redrawHistoryItem(msgRow);
} else { } else {
History *h = msgRow->history(); History *h = msgRow->history();
bool wasLast = (h->lastMsg == msgRow); bool wasLast = (h->lastMsg == msgRow);
@ -4256,7 +4256,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
if (HistoryItem *item = App::histItemById(NoChannel, v.at(i).v)) { if (HistoryItem *item = App::histItemById(NoChannel, v.at(i).v)) {
if (item->isMediaUnread()) { if (item->isMediaUnread()) {
item->markMediaRead(); item->markMediaRead();
msgUpdated(item); Notify::redrawHistoryItem(item);
if (item->out() && item->history()->peer->isUser()) { if (item->out() && item->history()->peer->isUser()) {
item->history()->peer->asUser()->madeAction(); item->history()->peer->asUser()->madeAction();
} }

View File

@ -237,7 +237,6 @@ public:
return sentUpdatesReceived(0, updates); return sentUpdatesReceived(0, updates);
} }
void inviteToChannelDone(ChannelData *channel, const MTPUpdates &updates); void inviteToChannelDone(ChannelData *channel, const MTPUpdates &updates);
void msgUpdated(const HistoryItem *msg);
void historyToDown(History *hist); void historyToDown(History *hist);
void dialogsToUp(); void dialogsToUp();
void newUnreadMsg(History *history, HistoryItem *item); void newUnreadMsg(History *history, HistoryItem *item);
@ -328,7 +327,7 @@ public:
void readServerHistory(History *history, bool force = true); void readServerHistory(History *history, bool force = true);
uint64 animActiveTime(const HistoryItem *msg) const; uint64 animActiveTimeStart(const HistoryItem *msg) const;
void stopAnimActive(); void stopAnimActive();
void sendBotCommand(const QString &cmd, MsgId msgId); void sendBotCommand(const QString &cmd, MsgId msgId);
@ -386,9 +385,11 @@ public:
void updateMutedIn(int32 seconds); void updateMutedIn(int32 seconds);
void updateStickers(); void updateStickers();
void notifyBotCommandsChanged(UserData *bot);
void notifyUserIsBotChanged(UserData *bot); void notify_botCommandsChanged(UserData *bot);
void notifyMigrateUpdated(PeerData *peer); void notify_userIsBotChanged(UserData *bot);
void notify_migrateUpdated(PeerData *peer);
void notify_redrawHistoryItem(const HistoryItem *msg);
void choosePeer(PeerId peerId, MsgId showAtMsgId); // does offerPeer or showPeerHistory void choosePeer(PeerId peerId, MsgId showAtMsgId); // does offerPeer or showPeerHistory
void clearBotStartToken(PeerData *peer); void clearBotStartToken(PeerData *peer);

View File

@ -527,13 +527,7 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32
} }
} }
void OverviewInner::updateMsg(HistoryItem *item) { void OverviewInner::redrawItem(MsgId itemId, int32 itemIndex) {
if (App::main() && item) {
App::main()->msgUpdated(item);
}
}
void OverviewInner::updateMsg(MsgId itemId, int32 itemIndex) {
fixItemIndex(itemIndex, itemId); fixItemIndex(itemIndex, itemId);
if (itemIndex >= 0) { if (itemIndex >= 0) {
if (_type == OverviewPhotos) { if (_type == OverviewPhotos) {
@ -665,15 +659,15 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
if (button != Qt::LeftButton) return; if (button != Qt::LeftButton) return;
if (textlnkDown() != textlnkOver()) { if (textlnkDown() != textlnkOver()) {
updateMsg(App::pressedLinkItem()); redrawItem(App::pressedLinkItem());
textlnkDown(textlnkOver()); textlnkDown(textlnkOver());
App::pressedLinkItem(App::hoveredLinkItem()); App::pressedLinkItem(App::hoveredLinkItem());
updateMsg(App::pressedLinkItem()); redrawItem(App::pressedLinkItem());
} }
if (_lnkDownIndex != _lnkOverIndex) { if (_lnkDownIndex != _lnkOverIndex) {
if (_dragItem) updateMsg(_dragItem, _dragItemIndex); if (_dragItem) redrawItem(_dragItem, _dragItemIndex);
_lnkDownIndex = _lnkOverIndex; _lnkDownIndex = _lnkOverIndex;
if (_mousedItem) updateMsg(_mousedItem, _mousedItemIndex); if (_mousedItem) redrawItem(_mousedItem, _mousedItemIndex);
} }
_dragAction = NoDrag; _dragAction = NoDrag;
@ -702,12 +696,12 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol; uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) { if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key(), -1); redrawItem(_selected.cbegin().key(), -1);
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_dragItem, selStatus);
_dragAction = Selecting; _dragAction = Selecting;
updateMsg(_dragItem, _dragItemIndex); redrawItem(_dragItem, _dragItemIndex);
_overview->updateTopBarSelection(); _overview->updateTopBarSelection();
} else { } else {
_dragAction = PrepareSelect; _dragAction = PrepareSelect;
@ -752,7 +746,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
} }
} }
if (textlnkDown()) { if (textlnkDown()) {
updateMsg(App::pressedLinkItem()); redrawItem(App::pressedLinkItem());
textlnkDown(TextLinkPtr()); textlnkDown(TextLinkPtr());
App::pressedLinkItem(0); App::pressedLinkItem(0);
if (!textlnkOver() && _cursor != style::cur_default) { if (!textlnkOver() && _cursor != style::cur_default) {
@ -761,7 +755,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
} }
} }
if (_lnkDownIndex) { if (_lnkDownIndex) {
updateMsg(_dragItem, _dragItemIndex); redrawItem(_dragItem, _dragItemIndex);
_lnkDownIndex = 0; _lnkDownIndex = 0;
if (!_lnkOverIndex && _cursor != style::cur_default) { if (!_lnkOverIndex && _cursor != style::cur_default) {
_cursor = style::cur_default; _cursor = style::cur_default;
@ -795,16 +789,16 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
} else { } else {
_selected.erase(i); _selected.erase(i);
} }
updateMsg(_dragItem, _dragItemIndex); redrawItem(_dragItem, _dragItemIndex);
} else if (_dragAction == PrepareDrag && !needClick && !_dragWasInactive && button != Qt::RightButton) { } else if (_dragAction == PrepareDrag && !needClick && !_dragWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_dragItem); SelectedItems::iterator i = _selected.find(_dragItem);
if (i != _selected.cend() && i.value() == FullItemSel) { if (i != _selected.cend() && i.value() == FullItemSel) {
_selected.erase(i); _selected.erase(i);
updateMsg(_dragItem, _dragItemIndex); redrawItem(_dragItem, _dragItemIndex);
} else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { } else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
if (_selected.size() < MaxSelectedItems) { if (_selected.size() < MaxSelectedItems) {
_selected.insert(_dragItem, FullItemSel); _selected.insert(_dragItem, FullItemSel);
updateMsg(_dragItem, _dragItemIndex); redrawItem(_dragItem, _dragItemIndex);
} }
} else { } else {
_selected.clear(); _selected.clear();
@ -1074,7 +1068,11 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
QRect r(e->rect()); QRect r(e->rect());
p.setClipRect(r); bool trivial = (r == rect());
if (!trivial) {
p.setClipRect(r);
}
uint64 ms = getms();
if (_history->overview[_type].isEmpty() && (!_migrated || !_history->overviewLoaded(_type) || _migrated->overview[_type].isEmpty())) { if (_history->overview[_type].isEmpty() && (!_migrated || !_history->overviewLoaded(_type) || _migrated->overview[_type].isEmpty())) {
QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9); QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9);
@ -1144,7 +1142,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
QPoint pos(int32(i * w + st::overviewPhotoSkip), _addToY + row * (_vsize + st::overviewPhotoSkip) + st::overviewPhotoSkip); QPoint pos(int32(i * w + st::overviewPhotoSkip), _addToY + row * (_vsize + st::overviewPhotoSkip) + st::overviewPhotoSkip);
p.drawPixmap(pos, it->pix); p.drawPixmap(pos, it->pix);
if (!quality) { if (!quality) {
uint64 dt = itemAnimations().animate(item, getms()); uint64 dt = itemAnimations().animate(item, ms);
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta); int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = pos.x() + (_vsize - st::overviewLoader.width()) / 2, y = pos.y() + (_vsize - st::overviewLoader.height()) / 2; int32 x = pos.x() + (_vsize - st::overviewLoader.width()) / 2, y = pos.y() + (_vsize - st::overviewLoader.height()) / 2;
@ -1338,7 +1336,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
p.save(); p.save();
p.translate(left, 0); p.translate(left, 0);
media->draw(p, item, (sel == FullItemSel), w); media->draw(p, item, r.translated(-left, -curY - (st::msgMargin.top() + _addToY)), (sel == FullItemSel), ms);
p.restore(); p.restore();
} }
} else { } else {
@ -1451,9 +1449,9 @@ void OverviewInner::onUpdateSelected() {
} }
} }
if (newsel != _selectedMsgId) { if (newsel != _selectedMsgId) {
if (_selectedMsgId) updateMsg(_selectedMsgId, -1); if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
_selectedMsgId = newsel; _selectedMsgId = newsel;
updateMsg(item); redrawItem(item);
} }
} else if (_type == OverviewLinks) { } else if (_type == OverviewLinks) {
int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); int32 w = _width - st::msgMargin.left() - st::msgMargin.right();
@ -1558,19 +1556,19 @@ void OverviewInner::onUpdateSelected() {
bool lnkChanged = false; bool lnkChanged = false;
if (lnk != textlnkOver()) { if (lnk != textlnkOver()) {
lnkChanged = true; lnkChanged = true;
updateMsg(App::hoveredLinkItem()); redrawItem(App::hoveredLinkItem());
textlnkOver(lnk); textlnkOver(lnk);
App::hoveredLinkItem(lnk ? item : 0); App::hoveredLinkItem(lnk ? item : 0);
updateMsg(App::hoveredLinkItem()); redrawItem(App::hoveredLinkItem());
QToolTip::hideText(); QToolTip::hideText();
} else { } else {
App::mousedItem(item); App::mousedItem(item);
} }
if (lnkIndex != _lnkOverIndex || _mousedItem != oldMousedItem) { if (lnkIndex != _lnkOverIndex || _mousedItem != oldMousedItem) {
lnkChanged = true; lnkChanged = true;
if (oldMousedItem) updateMsg(oldMousedItem, oldMousedItemIndex); if (oldMousedItem) redrawItem(oldMousedItem, oldMousedItemIndex);
_lnkOverIndex = lnkIndex; _lnkOverIndex = lnkIndex;
if (item) updateMsg(item); if (item) redrawItem(item);
QToolTip::hideText(); QToolTip::hideText();
} }
if (_cursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) { if (_cursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) {
@ -1794,11 +1792,11 @@ void OverviewInner::enterEvent(QEvent *e) {
void OverviewInner::leaveEvent(QEvent *e) { void OverviewInner::leaveEvent(QEvent *e) {
if (_selectedMsgId) { if (_selectedMsgId) {
updateMsg(_selectedMsgId, -1); redrawItem(_selectedMsgId, -1);
_selectedMsgId = 0; _selectedMsgId = 0;
} }
if (textlnkOver()) { if (textlnkOver()) {
updateMsg(App::hoveredLinkItem()); redrawItem(App::hoveredLinkItem());
textlnkOver(TextLinkPtr()); textlnkOver(TextLinkPtr());
App::hoveredLinkItem(0); App::hoveredLinkItem(0);
if (!textlnkDown() && _cursor != style::cur_default) { if (!textlnkDown() && _cursor != style::cur_default) {
@ -1826,8 +1824,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (_menu) { if (_menu) {
_menu->deleteLater(); _menu->deleteLater();
_menu = 0; _menu = 0;
updateMsg(App::contextItem()); redrawItem(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1); if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
} }
if (e->reason() == QContextMenuEvent::Mouse) { if (e->reason() == QContextMenuEvent::Mouse) {
dragActionUpdate(e->globalPos()); dragActionUpdate(e->globalPos());
@ -1904,8 +1902,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
} }
} }
App::contextItem(App::hoveredLinkItem()); App::contextItem(App::hoveredLinkItem());
updateMsg(App::contextItem()); redrawItem(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1); if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
} else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->channelId() == itemChannel(_mousedItem) && App::mousedItem()->id == itemMsgId(_mousedItem)) { } else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->channelId() == itemChannel(_mousedItem) && App::mousedItem()->id == itemMsgId(_mousedItem)) {
_contextMenuUrl = _lnkOverIndex ? urlByIndex(_mousedItem, _mousedItemIndex, _lnkOverIndex) : QString(); _contextMenuUrl = _lnkOverIndex ? urlByIndex(_mousedItem, _mousedItemIndex, _lnkOverIndex) : QString();
_menu = new PopupMenu(); _menu = new PopupMenu();
@ -1944,8 +1942,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
} }
} }
App::contextItem(App::mousedItem()); App::contextItem(App::mousedItem());
updateMsg(App::contextItem()); redrawItem(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1); if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
} }
if (_menu) { if (_menu) {
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*))); connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
@ -2197,8 +2195,8 @@ void OverviewInner::onMenuDestroy(QObject *obj) {
if (_menu == obj) { if (_menu == obj) {
_menu = 0; _menu = 0;
dragActionUpdate(QCursor::pos()); dragActionUpdate(QCursor::pos());
updateMsg(App::contextItem()); redrawItem(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1); if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
} }
} }
@ -2570,8 +2568,9 @@ void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) {
} }
} }
void OverviewInner::msgUpdated(const HistoryItem *msg) { void OverviewInner::redrawItem(const HistoryItem *msg) {
if (!msg) return; if (!msg) return;
History *history = (msg->history() == _history) ? _history : (msg->history() == _migrated ? _migrated : 0); History *history = (msg->history() == _history) ? _history : (msg->history() == _migrated ? _migrated : 0);
if (!history) return; if (!history) return;
@ -2998,9 +2997,9 @@ void OverviewWidget::changingMsgId(HistoryItem *row, MsgId newId) {
} }
} }
void OverviewWidget::msgUpdated(const HistoryItem *msg) { void OverviewWidget::notify_redrawHistoryItem(const HistoryItem *msg) {
if (peer() == msg->history()->peer || migratePeer() == msg->history()->peer) { if (peer() == msg->history()->peer || migratePeer() == msg->history()->peer) {
_inner.msgUpdated(msg); _inner.redrawItem(msg);
} }
} }

View File

@ -69,7 +69,7 @@ public:
void mediaOverviewUpdated(bool fromResize = false); void mediaOverviewUpdated(bool fromResize = false);
void changingMsgId(HistoryItem *row, MsgId newId); void changingMsgId(HistoryItem *row, MsgId newId);
void msgUpdated(const HistoryItem *msg); void redrawItem(const HistoryItem *msg);
void itemRemoved(HistoryItem *item); void itemRemoved(HistoryItem *item);
void itemResized(HistoryItem *item, bool scrollToIt); void itemResized(HistoryItem *item, bool scrollToIt);
@ -123,8 +123,7 @@ private:
void updateDragSelection(MsgId dragSelFrom, int32 dragSelFromIndex, MsgId dragSelTo, int32 dragSelToIndex, bool dragSelecting); void updateDragSelection(MsgId dragSelFrom, int32 dragSelFromIndex, MsgId dragSelTo, int32 dragSelToIndex, bool dragSelecting);
void updateMsg(HistoryItem *item); void redrawItem(MsgId itemId, int32 itemIndex);
void updateMsg(MsgId itemId, int32 itemIndex);
void touchResetSpeed(); void touchResetSpeed();
void touchUpdateSpeed(); void touchUpdateSpeed();
@ -314,7 +313,7 @@ public:
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type); void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
void changingMsgId(HistoryItem *row, MsgId newId); void changingMsgId(HistoryItem *row, MsgId newId);
void msgUpdated(const HistoryItem *msg); void notify_redrawHistoryItem(const HistoryItem *msg);
void itemRemoved(HistoryItem *item); void itemRemoved(HistoryItem *item);
void itemResized(HistoryItem *row, bool scrollToIt); void itemResized(HistoryItem *row, bool scrollToIt);

View File

@ -23,7 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "settings.h" #include "settings.h"
#include "lang.h" #include "lang.h"
bool gRtl = false; bool gRtl = true;// false;
Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight; Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight;
mtpDcOptions gDcOptions; mtpDcOptions gDcOptions;

View File

@ -1123,6 +1123,10 @@ struct DocumentData {
} }
void recountIsImage(); void recountIsImage();
float64 progress() const {
return loader ? loader->currentProgress() : ((status == FileDownloadFailed || (_location.name().isEmpty() && data.isEmpty())) ? 0 : 1);
}
DocumentId id; DocumentId id;
DocumentType type; DocumentType type;
QSize dimensions; QSize dimensions;