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

View File

@ -2129,9 +2129,9 @@ namespace App {
prepareCorners(ServiceSelectedCorners, st::msgRadius, st::msgServiceSelectBg);
prepareCorners(SelectedOverlayCorners, st::msgRadius, st::msgSelectOverlay);
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(InSelectedShadowCorners, st::msgRadius, st::msgInSelectShadow);
prepareCorners(InSelectedShadowCorners, st::msgRadius, st::msgInShadowSelected);
prepareCorners(ForwardCorners, st::msgRadius, st::forwardBg);
prepareCorners(MediaviewSaveCorners, st::msgRadius, st::medviewSaveMsg);
prepareCorners(EmojiHoverCorners, st::msgRadius, st::emojiPanHover);
@ -2147,9 +2147,9 @@ namespace App {
prepareCorners(DocBlueCorners, st::msgRadius, st::mvDocBlueColor);
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(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.setFont(st::normalFont->f);
p.setPen(st::black->c);
p.setFont(st::normalFont);
p.setPen(st::black);
if (twidth < _namew) {
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::normalFont->ascent, st::normalFont->elided(_name, twidth));
} else {
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);
}
}

View File

@ -96,15 +96,19 @@ namespace Ui {
namespace Notify {
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) {
if (MainWidget *m = App::main()) m->notifyBotCommandsChanged(user);
if (MainWidget *m = App::main()) m->notify_botCommandsChanged(user);
}
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 botCommandsChanged(UserData *user);
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) {
frame = f;
if (timer) {
if (msg && App::main()) {
App::main()->msgUpdated(msg);
if (msg) {
Notify::redrawHistoryItem(msg);
} else {
emit updated();
}

View File

@ -284,6 +284,57 @@ AnimationCallbacks *animation(Type *obj, typename AnimationCallbacksAbsolute<Typ
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 {
Q_OBJECT

View File

@ -304,6 +304,14 @@ namespace style {
typedef Font font;
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 stopManager();

View File

@ -38,8 +38,8 @@ namespace {
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 _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 _reCode(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])(`)[^\\n]+?(`)([\\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);
QSet<int32> _validProtocols, _validTopDomains;
const style::textStyle *_textStyle = 0;
@ -103,6 +103,10 @@ const TextLinkPtr &textlnkDown() {
return _downLnk;
}
bool textlnkDrawOver(const TextLinkPtr &lnk) {
return (_overLnk == lnk) && (!_downLnk || _downLnk == lnk);
}
QString textOneLine(const QString &text, bool trim, bool rich) {
QString result(text);
const QChar *s = text.unicode(), *ch = s, *e = text.unicode() + text.size();
@ -1385,6 +1389,7 @@ public:
return true;
}
int skipIndex = -1;
QVarLengthArray<int> visualOrder(nItems);
QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i) {
@ -1396,6 +1401,7 @@ public:
TextBlockType _type = currentBlock->type();
if (_type == TextBlockTSkip) {
levels[i] = si.analysis.bidiLevel = 0;
skipIndex = i;
} else {
levels[i] = si.analysis.bidiLevel;
}
@ -1406,6 +1412,13 @@ public:
}
}
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;
currentBlock = _t->_blocks[blockIndex];

View File

@ -680,6 +680,8 @@ const TextLinkPtr &textlnkOver();
void textlnkDown(const TextLinkPtr &lnk);
const TextLinkPtr &textlnkDown();
bool textlnkDrawOver(const TextLinkPtr &lnk);
// textcmd
QString textcmdSkipBlock(ushort w, ushort h);
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();) {
const HistoryItem *item = i.key();
if (item->animating()) {
if (timer) App::main()->msgUpdated(item);
if (timer) Notify::redrawHistoryItem(item);
++i;
} else {
i = _animations.erase(i);
@ -3100,6 +3100,72 @@ HistoryItem *regItem(HistoryItem *item, bool returnExisting) {
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()
, _data(App::feedPhoto(photo))
, _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 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) {
skipx = st::mediaPadding.left();
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();
}
} 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);
@ -3322,7 +3389,7 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, bool selected, in
p.drawPixmap(skipx, skipy, pix);
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 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());
if (_caption.isEmpty()) {
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 {
p.setPen(st::black);
_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);
}
void HistoryVideo::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
int32 height = _height;
if (width < 0) {
width = w;
} else if (!_caption.isEmpty()) {
height = countHeight(parent, width);
}
if (width < 1) return;
int skipy = 0, replyFrom = 0, fwdFrom = 0;
void HistoryVideo::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;
data->thumb->checkload();
@ -3546,8 +3606,8 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, bool selected, in
width = _maxw;
}
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow));
style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
style::color sh(outbg ? (selected ? st::msgOutShadowSelected : st::msgOutShadow) : (selected ? st::msgInShadowSelected : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
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;
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);
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) {
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
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.setRenderHint(QPainter::HighQualityAntialiasing, false);
}
}
p.setFont(st::msgDateFont->f);
if (!_caption.isEmpty()) {
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());
}
int32 fullRight = width, fullBottom = height;
parent->drawInfo(p, fullRight, fullBottom, selected, InfoDisplayDefault);
}
int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) {
@ -3660,12 +3715,10 @@ void HistoryAudio::initDimensions(const HistoryItem *parent) {
_height = _minh;
}
void HistoryAudio::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
if (width < 0) width = w;
void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
int32 width = w, skipy = 0, replyFrom = 0, fwdFrom = 0;
if (width < 1) return;
int skipy = 0, replyFrom = 0, fwdFrom = 0;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
bool already = !data->already().isEmpty(), hasdata = !data->data.isEmpty();
if (width >= _maxw) {
@ -3676,8 +3729,8 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, bool selected, in
data->save(QString());
}
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow));
style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
style::color sh(outbg ? (selected ? st::msgOutShadowSelected : st::msgOutShadow) : (selected ? st::msgInShadowSelected : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
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.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);
int32 texty = skipy + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height;
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) {
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
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.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) {
@ -3848,9 +3894,10 @@ HistoryDocument::HistoryDocument(DocumentData *document) : HistoryMedia()
, _savel(new DocumentSaveLink(_data))
, _thumbsavel(new DocumentSaveLink(_data))
, _cancell(new DocumentCancelLink(_data))
, _name(documentName(_data)) {
, _name(documentName(_data))
, _animation(0) {
if (_name.isEmpty()) _name = qsl("Unknown File");
_namew = st::normalFont->width(_name);
_namew = st::semiboldFont->width(_name);
setStatusSize(FileStatusSizeReady);
@ -3862,10 +3909,8 @@ HistoryDocument::HistoryDocument(DocumentData *document) : HistoryMedia()
} else {
_thumbw = st::msgFileThumbSize;
}
_height = _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
} else {
_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 = 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 {
if (width < 0) width = w;
if (width < 1) return;
void HistoryDocument::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;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
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 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;
bool wthumb = withThumb();
@ -3981,29 +4040,47 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, bool selected,
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
}
if (already || hasdata) {
if (!radial && (already || hasdata)) {
} 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);
p.setPen(Qt::NoPen);
p.setBrush(selected ? st::msgDateImgSelectBg : st::msgDateImgBg);
p.drawEllipse(inner);
if (selected) {
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);
style::sprite icon;
if (_data->loader) {
if (already || hasdata || _data->loader) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
}
p.setOpacity(radial ? _animation->radial.opacity() : 1);
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) {
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.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg));
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();
statustop = st::msgFileStatusTop;
p.setRenderHint(QPainter::HighQualityAntialiasing);
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width));
p.setPen(Qt::NoPen);
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg));
p.drawEllipse(inner);
if (selected) {
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);
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;
if (showPause) {
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);
}
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.setPen(status);
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();
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);
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);
}
style::color status(selected ? st::mediaInSelectColor : st::mediaInColor);
style::color status(selected ? st::mediaInFgSelected : st::mediaInFg);
p.setPen(status->p);
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 {
return new HistoryDocument(*this);
}
@ -4217,6 +4364,11 @@ ImagePtr HistoryDocument::replyPreview() {
return _data->makeReplyPreview();
}
HistoryDocument::~HistoryDocument() {
delete _animation;
_animation = 0;
}
HistoryGif::HistoryGif(DocumentData *document) : HistoryMedia()
, _data(document)
, _openl(new DocumentOpenLink(_data))
@ -4237,9 +4389,9 @@ void HistoryGif::initDimensions(const HistoryItem *parent) {
_height = _minh;
}
void HistoryGif::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
void HistoryGif::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;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
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;
}
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));
if (selected) {
@ -4387,9 +4539,10 @@ void HistorySticker::initDimensions(const HistoryItem *parent) {
w = qMin(lastw, _maxw);
}
void HistorySticker::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
void HistorySticker::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;
if (width > _maxw) width = _maxw;
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) {
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);
}
void HistoryContact::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
int skipy = 0, replyFrom = 0, fwdFrom = 0;
void HistoryContact::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;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
if (width >= _maxw) {
width = _maxw;
}
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow));
style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg));
style::color sh(outbg ? (selected ? st::msgOutShadowSelected : st::msgOutShadow) : (selected ? st::msgInShadowSelected : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
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);
}
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);
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) {
@ -4795,9 +4943,9 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
_height = _minh;
}
void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
if (width < 0) width = w;
if (width < 1 || data->pendingTill) return;
void HistoryWebPage::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;
int16 animw = 0, animh = 0;
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;
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 regular = (selected ? (outbg ? st::msgOutSelectDateColor : st::msgInSelectDateColor) : (outbg ? st::msgOutDateColor : st::msgInDateColor));
style::color semibold = (selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg));
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.save();
@ -4911,7 +5059,7 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, bool selected,
}
p.drawPixmap(0, 0, pix);
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 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 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.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);
}
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.drawText(tleft, st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->descent, statusText);
@ -5709,16 +5857,17 @@ void HistoryImageLink::initDimensions(const HistoryItem *parent) {
_height = _minh;
}
void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, bool selected, int32 width) const {
if (width < 0) width = w;
int skipx = 0, skipy = 0, height = _height;
void HistoryImageLink::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;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
if (!_title.isEmpty() || !_description.isEmpty()) {
skipx = st::mediaPadding.left();
style::color bg(selected ? (outbg ? st::msgOutSelectBg : st::msgInSelectBg) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow));
style::color bg(selected ? (outbg ? st::msgOutBgSelected : st::msgInBgSelected) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutShadowSelected : st::msgInShadowSelected) : (outbg ? st::msgOutShadow : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
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();
} 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();
@ -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);
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) {
@ -6188,8 +6337,8 @@ bool HistoryMessage::textHasLinks() {
return emptyText() ? false : _text.hasLinks();
}
void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, bool selected, InfoDisplayType type) const {
p.setFont(st::msgDateFont->f);
void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
p.setFont(st::msgDateFont);
bool outbg = out() && !fromChannel(), overimg = (type == InfoDisplayOverImage);
int32 infoRight = right, infoBottom = bottom;
@ -6197,7 +6346,7 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, bool select
case InfoDisplayDefault:
infoRight -= st::msgPadding.right() - st::msgDateDelta.x();
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;
case InfoDisplayOverImage:
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();
if (rtl()) infoRight = width - infoRight + infoW;
int32 dateX = infoRight - infoW;
int32 dateY = infoBottom - st::msgDateFont->height;
if (type == InfoDisplayOverImage) {
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();
@ -6265,7 +6416,7 @@ void HistoryMessage::setViewsCount(int32 count) {
_viewsText = (_views >= 0) ? formatViewsCount(_views) : QString();
_viewsWidth = _viewsText.isEmpty() ? 0 : st::msgDateFont->width(_viewsText);
if (was == _viewsWidth) {
if (App::main()) App::main()->msgUpdated(this);
Notify::redrawHistoryItem(this);
} else {
if (_text.hasSkipBlock()) {
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
@ -6281,7 +6432,7 @@ void HistoryMessage::setId(MsgId newId) {
bool wasPositive = (id > 0), positive = (newId > 0);
HistoryItem::setId(newId);
if (wasPositive == positive) {
if (App::main()) App::main()->msgUpdated(this);
Notify::redrawHistoryItem(this);
} else {
if (_text.hasSkipBlock()) {
_text.setSkipBlock(HistoryMessage::skipBlockWidth(), HistoryMessage::skipBlockHeight());
@ -6293,17 +6444,18 @@ void HistoryMessage::setId(MsgId newId) {
}
}
void HistoryMessage::draw(Painter &p, uint32 selection) const {
bool outbg = out() && !fromChannel(), bubble = drawBubble();
void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
bool outbg = out() && !fromChannel(), bubble = drawBubble(), selected = (selection == FullItemSel);
textstyleSet(&(outbg ? st::outTextStyle : st::inTextStyle));
uint64 ms = App::main() ? App::main()->animActiveTime(this) : 0;
if (ms) {
if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) {
uint64 animms = App::main() ? App::main()->animActiveTimeStart(this) : 0;
if (animms > 0 && animms <= ms) {
animms = ms - animms;
if (animms > st::activeFadeInDuration + st::activeFadeOutDuration) {
App::main()->stopAnimActive();
} 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();
p.setOpacity(o * dt);
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) {
fromNameUpdated();
_fromVersion = _from->nameVersion;
@ -6327,15 +6478,15 @@ void HistoryMessage::draw(Painter &p, uint32 selection) const {
if (bubble) {
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 sh(selected ? (outbg ? st::msgOutSelectShadow : st::msgInSelectShadow) : (outbg ? st::msgOutShadow : st::msgInShadow));
style::color bg(selected ? (outbg ? st::msgOutBgSelected : st::msgInBgSelected) : (outbg ? st::msgOutBg : st::msgInBg));
style::color sh(selected ? (outbg ? st::msgOutShadowSelected : st::msgInShadowSelected) : (outbg ? st::msgOutShadow : st::msgInShadow));
RoundCorners cors(selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners));
App::roundRect(p, r, bg, cors, &sh);
if (displayFromName()) {
p.setFont(st::msgNameFont->f);
if (fromChannel()) {
p.setPen(selected ? st::msgInServiceSelColor : st::msgInServiceColor);
p.setPen(selected ? st::msgInServiceFgSelected : st::msgInServiceFg);
} else {
p.setPen(_from->color);
}
@ -6347,19 +6498,21 @@ void HistoryMessage::draw(Painter &p, uint32 selection) const {
if (_media && _media->isDisplayed()) {
p.save();
p.translate(left, _height - st::msgMargin.bottom() - _media->height());
_media->draw(p, this, selected);
int32 top = _height - st::msgMargin.bottom() - _media->height();
p.translate(left, top);
_media->draw(p, this, r.translated(-left, -top), selected, ms);
p.restore();
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 {
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 {
p.save();
p.translate(left, st::msgMargin.top());
_media->draw(p, this, selected);
int32 top = st::msgMargin.top();
p.translate(left, top);
_media->draw(p, this, r.translated(-left, -top), selected, ms);
p.restore();
}
@ -6580,8 +6733,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const
, fwdDate(::date(msg.vfwd_date))
, fwdFrom(App::peer(peerFromMTP(msg.vfwd_from_id)))
, 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();
}
@ -6589,8 +6741,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId
, fwdDate(msg->dateForwarded())
, fwdFrom(msg->fromForwarded())
, 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();
}
@ -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) {
fwdNameUpdated();
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 {
style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont);
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);
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) {
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 {
@ -6881,14 +7032,14 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec
if (likeService) {
p.setPen(st::white->p);
} 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);
HistoryMessage *replyToAsMsg = replyToMsg->toHistoryMessage();
if (likeService) {
} 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);
} else {
p.setPen(st::msgColor->p);
@ -6897,7 +7048,7 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec
}
} else {
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) {
p.setPen(st::white->p);
} else {
@ -7210,14 +7361,15 @@ void HistoryServiceMsg::setServiceText(const QString &text) {
initDimensions();
}
void HistoryServiceMsg::draw(Painter &p, uint32 selection) const {
uint64 ms = App::main() ? App::main()->animActiveTime(this) : 0;
if (ms) {
if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) {
void HistoryServiceMsg::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const {
uint64 animms = App::main() ? App::main()->animActiveTimeStart(this) : 0;
if (animms > 0 && animms <= ms) {
animms = ms - animms;
if (animms > st::activeFadeInDuration + st::activeFadeOutDuration) {
App::main()->stopAnimActive();
} else {
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();
p.setOpacity(o * dt);
p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b);
@ -7233,8 +7385,9 @@ void HistoryServiceMsg::draw(Painter &p, uint32 selection) const {
if (_media) {
height -= st::msgServiceMargin.top() + _media->height();
p.save();
p.translate(st::msgServiceMargin.left() + (width - _media->maxWidth()) / 2, st::msgServiceMargin.top() + height + st::msgServiceMargin.top());
_media->draw(p, this, selection == FullItemSel);
int32 left = st::msgServiceMargin.left() + (width - _media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top();
p.translate(left, top);
_media->draw(p, this, r.translated(-left, -top), selection == FullItemSel, ms);
p.restore();
}
@ -7435,7 +7588,7 @@ HistoryServiceMsg(history, block, clientMsgId(), date, qsl("-")),
_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 {
@ -7471,7 +7624,7 @@ void HistoryUnreadBar::setCount(int32 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::unreadBarHeight - st::lineWidth, _history->width, st::lineWidth, st::unreadBarBorder->b);
p.setFont(st::unreadBarFont->f);

View File

@ -845,7 +845,7 @@ public:
virtual void initDimensions() = 0;
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() {
return _history;
@ -933,6 +933,10 @@ public:
virtual uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
return (from << 16) | to;
}
virtual void linkOver(const TextLinkPtr &lnk) {
}
virtual void linkOut(const TextLinkPtr &lnk) {
}
virtual HistoryItemType type() const {
return HistoryItemMsg;
}
@ -955,7 +959,7 @@ public:
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) {
}
@ -1112,6 +1116,34 @@ private:
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 {
public:
@ -1136,7 +1168,11 @@ public:
return _height;
}
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 {
return false;
}
@ -1196,7 +1232,7 @@ public:
void init();
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);
HistoryMediaType type() const {
return MediaTypePhoto;
@ -1268,7 +1304,7 @@ public:
HistoryVideo(const MTPDvideo &video, const QString &caption, 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);
HistoryMediaType type() const {
return MediaTypeVideo;
@ -1323,7 +1359,7 @@ public:
HistoryAudio(const MTPDaudio &audio);
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 {
return MediaTypeAudio;
}
@ -1372,7 +1408,7 @@ public:
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);
HistoryMediaType type() const {
return MediaTypeDocument;
@ -1385,6 +1421,8 @@ public:
return (_data->status == FileUploading);
}
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;
DocumentData *document() {
@ -1414,6 +1452,8 @@ public:
return _data->song();
}
~HistoryDocument();
private:
DocumentData *_data;
@ -1433,6 +1473,25 @@ private:
void setStatusSize(int32 newSize, qint64 realDuration = 0) const;
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 {
@ -1441,7 +1500,7 @@ public:
HistoryGif(DocumentData *document);
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);
HistoryMediaType type() const {
return MediaTypeGif;
@ -1500,7 +1559,7 @@ public:
HistorySticker(DocumentData *document);
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);
HistoryMediaType type() const {
return MediaTypeSticker;
@ -1544,7 +1603,7 @@ public:
HistoryContact(int32 userId, const QString &fullname, const QString &phone);
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 {
return MediaTypeContact;
}
@ -1577,7 +1636,7 @@ public:
HistoryWebPage(WebPageData *data);
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 {
return !data->pendingTill;
}
@ -1691,7 +1750,7 @@ public:
int32 fullHeight() const;
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);
HistoryMediaType type() const {
return MediaTypeImageLink;
@ -1751,10 +1810,11 @@ public:
}
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 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;
int32 resize(int32 width);
@ -1768,6 +1828,12 @@ public:
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
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;
QString notificationHeader() const;
@ -1867,7 +1933,7 @@ public:
void initDimensions();
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 drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width);
@ -1923,7 +1989,7 @@ public:
HistoryItem *replyToMessage() const;
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 drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width);
@ -1966,7 +2032,7 @@ public:
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);
bool hasPoint(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:
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 getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const {
symbol = 0xFFFF;
@ -2119,7 +2185,7 @@ public:
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);
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) {
if (!msg || msg->detached() || !_history) return;
int32 msgy = itemTop(msg);
void HistoryInner::redrawItem(const HistoryItem *item) {
if (!item || item->detached() || !_history) return;
int32 msgy = itemTop(item);
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;
Painter p(this);
QRect r(e->rect());
bool trivial = (rect() == r);
Painter p(this);
if (!trivial) {
p.setClipRect(r);
}
uint64 ms = getms();
if (!_firstLoading && _botInfo && !_botInfo->text.isEmpty() && _botDescHeight > 0) {
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();
}
}
item->draw(p, sel);
item->draw(p, r.translated(0, -y), sel, ms);
if (item->hasViews()) {
App::main()->scheduleViewIncrement(item);
@ -233,7 +233,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
sel = i.value();
}
}
item->draw(p, sel);
item->draw(p, r.translated(0, -y), sel, ms);
if (item->hasViews()) {
App::main()->scheduleViewIncrement(item);
@ -475,16 +475,16 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
if (button != Qt::LeftButton) return;
if (App::pressedItem() != App::hoveredItem()) {
updateMsg(App::pressedItem());
redrawItem(App::pressedItem());
App::pressedItem(App::hoveredItem());
updateMsg(App::pressedItem());
redrawItem(App::pressedItem());
}
if (textlnkDown() != textlnkOver()) {
updateMsg(App::pressedLinkItem());
redrawItem(App::pressedLinkItem());
textlnkDown(textlnkOver());
App::pressedLinkItem(App::hoveredLinkItem());
updateMsg(App::pressedLinkItem());
updateMsg(App::pressedItem());
redrawItem(App::pressedLinkItem());
redrawItem(App::pressedItem());
}
_dragAction = NoDrag;
@ -512,7 +512,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
uint32 selStatus = (symbol << 16) | symbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key());
redrawItem(_selected.cbegin().key());
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
@ -553,12 +553,12 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key());
redrawItem(_selected.cbegin().key());
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
_dragAction = Selecting;
updateMsg(_dragItem);
redrawItem(_dragItem);
} else {
_dragAction = PrepareSelect;
}
@ -731,7 +731,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
}
}
if (textlnkDown()) {
updateMsg(App::pressedLinkItem());
redrawItem(App::pressedLinkItem());
textlnkDown(TextLinkPtr());
App::pressedLinkItem(0);
if (!textlnkOver() && _cursor != style::cur_default) {
@ -740,7 +740,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
}
}
if (App::pressedItem()) {
updateMsg(App::pressedItem());
redrawItem(App::pressedItem());
App::pressedItem(0);
}
@ -764,16 +764,16 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
} else {
_selected.erase(i);
}
updateMsg(_dragItem);
redrawItem(_dragItem);
} else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_dragItem);
if (i != _selected.cend() && i.value() == FullItemSel) {
_selected.erase(i);
updateMsg(_dragItem);
redrawItem(_dragItem);
} else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
if (_selected.size() < MaxSelectedItems) {
_selected.insert(_dragItem, FullItemSel);
updateMsg(_dragItem);
redrawItem(_dragItem);
}
} else {
_selected.clear();
@ -818,7 +818,7 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
_dragAction = Selecting;
uint32 selStatus = (symbol << 16) | symbol;
if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key());
redrawItem(_selected.cbegin().key());
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
@ -1348,12 +1348,17 @@ void HistoryInner::enterEvent(QEvent *e) {
}
void HistoryInner::leaveEvent(QEvent *e) {
if (textlnkOver()) {
updateMsg(App::hoveredItem());
updateMsg(App::hoveredLinkItem());
textlnkOver(TextLinkPtr());
App::hoveredLinkItem(0);
if (HistoryItem *item = App::hoveredItem()) {
redrawItem(item);
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) {
_cursor = style::cur_default;
setCursor(_cursor);
@ -1522,11 +1527,11 @@ void HistoryInner::onUpdateSelected() {
App::mousedItem(item);
m = mapMouseToItem(point, item);
if (item->hasPoint(m.x(), m.y())) {
updateMsg(App::hoveredItem());
redrawItem(App::hoveredItem());
App::hoveredItem(item);
updateMsg(App::hoveredItem());
redrawItem(App::hoveredItem());
} else if (App::hoveredItem()) {
updateMsg(App::hoveredItem());
redrawItem(App::hoveredItem());
App::hoveredItem(0);
}
}
@ -1552,8 +1557,9 @@ void HistoryInner::onUpdateSelected() {
if (lnk != textlnkOver()) {
lnkChanged = true;
if (textlnkOver()) {
if (App::hoveredLinkItem()) {
updateMsg(App::hoveredLinkItem());
if (HistoryItem *item = App::hoveredLinkItem()) {
item->linkOut(textlnkOver());
redrawItem(item);
} else {
update(_botDescRect);
}
@ -1562,8 +1568,9 @@ void HistoryInner::onUpdateSelected() {
QToolTip::hideText();
App::hoveredLinkItem((lnk && !lnkInDesc) ? item : 0);
if (textlnkOver()) {
if (App::hoveredLinkItem()) {
updateMsg(App::hoveredLinkItem());
if (HistoryItem *item = App::hoveredLinkItem()) {
item->linkOver(textlnkOver());
redrawItem(item);
} else {
update(_botDescRect);
}
@ -2947,7 +2954,7 @@ void HistoryWidget::updateStickers() {
_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 (_attachMention.clearFilteredCommands()) {
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) {
_list->notifyIsBotChanged();
_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 == peer) {
if (peer->migrateTo()) {
@ -5442,7 +5449,7 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadPhoto, 0);
}
// msgUpdated(item);
// Notify::redrawHistoryItem(item);
}
}
@ -5464,7 +5471,7 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
if (!item->fromChannel()) {
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()) {
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()) {
updateSendAction(item->history(), SendActionUploadPhoto, -1);
}
// msgUpdated(item);
// Notify::redrawHistoryItem(item);
}
}
@ -5497,7 +5504,7 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadFile, -1);
}
msgUpdated(item);
Notify::redrawHistoryItem(item);
}
}
@ -5508,7 +5515,7 @@ void HistoryWidget::onAudioFailed(const FullMsgId &newId) {
if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadAudio, -1);
}
msgUpdated(item);
Notify::redrawHistoryItem(item);
}
}
@ -5595,9 +5602,9 @@ void HistoryWidget::peerMessagesUpdated() {
if (_list) peerMessagesUpdated(_peer->id);
}
void HistoryWidget::msgUpdated(const HistoryItem *msg) {
if (_peer && _list && (msg->history() == _history || (_migrated && msg->history() == _migrated))) {
_list->updateMsg(msg);
void HistoryWidget::notify_redrawHistoryItem(const HistoryItem *item) {
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
_list->redrawItem(item);
}
}
@ -6528,14 +6535,14 @@ void HistoryWidget::onAnimActiveStep() {
if (getms() - _animActiveStart > st::activeFadeInDuration + st::activeFadeOutDuration) {
stopAnimActive();
} 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->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;
}
@ -6645,11 +6652,11 @@ void HistoryWidget::drawField(Painter &p) {
}
p.setPen(st::replyColor->p);
_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());
} else {
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()));
}
}
@ -6669,7 +6676,7 @@ void HistoryWidget::drawField(Painter &p) {
}
p.setPen(st::replyColor->p);
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());
}
}

View File

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

View File

@ -683,18 +683,6 @@ void MainWidget::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() {
App::updateMuted();
}
@ -758,6 +746,27 @@ void MainWidget::ui_hideStickerPreview() {
_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) {
if (_hider == destroyed) {
_hider = 0;
@ -1303,8 +1312,8 @@ void MainWidget::readServerHistory(History *hist, bool force) {
}
}
uint64 MainWidget::animActiveTime(const HistoryItem *msg) const {
return history.animActiveTime(msg);
uint64 MainWidget::animActiveTimeStart(const HistoryItem *msg) const {
return history.animActiveTimeStart(msg);
}
void MainWidget::stopAnimActive() {
@ -1474,7 +1483,7 @@ void MainWidget::itemResized(HistoryItem *row, bool scrollToIt) {
if (overview) {
overview->itemResized(row, scrollToIt);
}
if (row) msgUpdated(row);
if (row) Notify::redrawHistoryItem(row);
}
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);
if (i != items.cend()) {
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);
if (i != items.cend()) {
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)) {
msgUpdated(item);
Notify::redrawHistoryItem(item);
}
}
@ -1797,7 +1806,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
}
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);
if (i != items.cend()) {
for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) {
msgUpdated(j.key());
Notify::redrawHistoryItem(j.key());
}
}
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) {
history.historyToDown(hist);
}
@ -4227,7 +4227,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
msgRow->history()->unregTyping(App::self());
}
if (!App::historyRegItem(msgRow)) {
msgUpdated(msgRow);
Notify::redrawHistoryItem(msgRow);
} else {
History *h = msgRow->history();
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 (item->isMediaUnread()) {
item->markMediaRead();
msgUpdated(item);
Notify::redrawHistoryItem(item);
if (item->out() && item->history()->peer->isUser()) {
item->history()->peer->asUser()->madeAction();
}

View File

@ -237,7 +237,6 @@ public:
return sentUpdatesReceived(0, updates);
}
void inviteToChannelDone(ChannelData *channel, const MTPUpdates &updates);
void msgUpdated(const HistoryItem *msg);
void historyToDown(History *hist);
void dialogsToUp();
void newUnreadMsg(History *history, HistoryItem *item);
@ -328,7 +327,7 @@ public:
void readServerHistory(History *history, bool force = true);
uint64 animActiveTime(const HistoryItem *msg) const;
uint64 animActiveTimeStart(const HistoryItem *msg) const;
void stopAnimActive();
void sendBotCommand(const QString &cmd, MsgId msgId);
@ -386,9 +385,11 @@ public:
void updateMutedIn(int32 seconds);
void updateStickers();
void notifyBotCommandsChanged(UserData *bot);
void notifyUserIsBotChanged(UserData *bot);
void notifyMigrateUpdated(PeerData *peer);
void notify_botCommandsChanged(UserData *bot);
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 clearBotStartToken(PeerData *peer);

View File

@ -527,13 +527,7 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32
}
}
void OverviewInner::updateMsg(HistoryItem *item) {
if (App::main() && item) {
App::main()->msgUpdated(item);
}
}
void OverviewInner::updateMsg(MsgId itemId, int32 itemIndex) {
void OverviewInner::redrawItem(MsgId itemId, int32 itemIndex) {
fixItemIndex(itemIndex, itemId);
if (itemIndex >= 0) {
if (_type == OverviewPhotos) {
@ -665,15 +659,15 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
if (button != Qt::LeftButton) return;
if (textlnkDown() != textlnkOver()) {
updateMsg(App::pressedLinkItem());
redrawItem(App::pressedLinkItem());
textlnkDown(textlnkOver());
App::pressedLinkItem(App::hoveredLinkItem());
updateMsg(App::pressedLinkItem());
redrawItem(App::pressedLinkItem());
}
if (_lnkDownIndex != _lnkOverIndex) {
if (_dragItem) updateMsg(_dragItem, _dragItemIndex);
if (_dragItem) redrawItem(_dragItem, _dragItemIndex);
_lnkDownIndex = _lnkOverIndex;
if (_mousedItem) updateMsg(_mousedItem, _mousedItemIndex);
if (_mousedItem) redrawItem(_mousedItem, _mousedItemIndex);
}
_dragAction = NoDrag;
@ -702,12 +696,12 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key(), -1);
redrawItem(_selected.cbegin().key(), -1);
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
_dragAction = Selecting;
updateMsg(_dragItem, _dragItemIndex);
redrawItem(_dragItem, _dragItemIndex);
_overview->updateTopBarSelection();
} else {
_dragAction = PrepareSelect;
@ -752,7 +746,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
}
}
if (textlnkDown()) {
updateMsg(App::pressedLinkItem());
redrawItem(App::pressedLinkItem());
textlnkDown(TextLinkPtr());
App::pressedLinkItem(0);
if (!textlnkOver() && _cursor != style::cur_default) {
@ -761,7 +755,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
}
}
if (_lnkDownIndex) {
updateMsg(_dragItem, _dragItemIndex);
redrawItem(_dragItem, _dragItemIndex);
_lnkDownIndex = 0;
if (!_lnkOverIndex && _cursor != style::cur_default) {
_cursor = style::cur_default;
@ -795,16 +789,16 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
} else {
_selected.erase(i);
}
updateMsg(_dragItem, _dragItemIndex);
redrawItem(_dragItem, _dragItemIndex);
} else if (_dragAction == PrepareDrag && !needClick && !_dragWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_dragItem);
if (i != _selected.cend() && i.value() == FullItemSel) {
_selected.erase(i);
updateMsg(_dragItem, _dragItemIndex);
redrawItem(_dragItem, _dragItemIndex);
} else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
if (_selected.size() < MaxSelectedItems) {
_selected.insert(_dragItem, FullItemSel);
updateMsg(_dragItem, _dragItemIndex);
redrawItem(_dragItem, _dragItemIndex);
}
} else {
_selected.clear();
@ -1074,7 +1068,11 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
Painter p(this);
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())) {
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);
p.drawPixmap(pos, it->pix);
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 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.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();
}
} else {
@ -1451,9 +1449,9 @@ void OverviewInner::onUpdateSelected() {
}
}
if (newsel != _selectedMsgId) {
if (_selectedMsgId) updateMsg(_selectedMsgId, -1);
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
_selectedMsgId = newsel;
updateMsg(item);
redrawItem(item);
}
} else if (_type == OverviewLinks) {
int32 w = _width - st::msgMargin.left() - st::msgMargin.right();
@ -1558,19 +1556,19 @@ void OverviewInner::onUpdateSelected() {
bool lnkChanged = false;
if (lnk != textlnkOver()) {
lnkChanged = true;
updateMsg(App::hoveredLinkItem());
redrawItem(App::hoveredLinkItem());
textlnkOver(lnk);
App::hoveredLinkItem(lnk ? item : 0);
updateMsg(App::hoveredLinkItem());
redrawItem(App::hoveredLinkItem());
QToolTip::hideText();
} else {
App::mousedItem(item);
}
if (lnkIndex != _lnkOverIndex || _mousedItem != oldMousedItem) {
lnkChanged = true;
if (oldMousedItem) updateMsg(oldMousedItem, oldMousedItemIndex);
if (oldMousedItem) redrawItem(oldMousedItem, oldMousedItemIndex);
_lnkOverIndex = lnkIndex;
if (item) updateMsg(item);
if (item) redrawItem(item);
QToolTip::hideText();
}
if (_cursorState == HistoryInDateCursorState && cursorState != HistoryInDateCursorState) {
@ -1794,11 +1792,11 @@ void OverviewInner::enterEvent(QEvent *e) {
void OverviewInner::leaveEvent(QEvent *e) {
if (_selectedMsgId) {
updateMsg(_selectedMsgId, -1);
redrawItem(_selectedMsgId, -1);
_selectedMsgId = 0;
}
if (textlnkOver()) {
updateMsg(App::hoveredLinkItem());
redrawItem(App::hoveredLinkItem());
textlnkOver(TextLinkPtr());
App::hoveredLinkItem(0);
if (!textlnkDown() && _cursor != style::cur_default) {
@ -1826,8 +1824,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (_menu) {
_menu->deleteLater();
_menu = 0;
updateMsg(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1);
redrawItem(App::contextItem());
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
}
if (e->reason() == QContextMenuEvent::Mouse) {
dragActionUpdate(e->globalPos());
@ -1904,8 +1902,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
}
App::contextItem(App::hoveredLinkItem());
updateMsg(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1);
redrawItem(App::contextItem());
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
} else if (!ignoreMousedItem && App::mousedItem() && App::mousedItem()->channelId() == itemChannel(_mousedItem) && App::mousedItem()->id == itemMsgId(_mousedItem)) {
_contextMenuUrl = _lnkOverIndex ? urlByIndex(_mousedItem, _mousedItemIndex, _lnkOverIndex) : QString();
_menu = new PopupMenu();
@ -1944,8 +1942,8 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
}
App::contextItem(App::mousedItem());
updateMsg(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1);
redrawItem(App::contextItem());
if (_selectedMsgId) redrawItem(_selectedMsgId, -1);
}
if (_menu) {
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
@ -2197,8 +2195,8 @@ void OverviewInner::onMenuDestroy(QObject *obj) {
if (_menu == obj) {
_menu = 0;
dragActionUpdate(QCursor::pos());
updateMsg(App::contextItem());
if (_selectedMsgId) updateMsg(_selectedMsgId, -1);
redrawItem(App::contextItem());
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;
History *history = (msg->history() == _history) ? _history : (msg->history() == _migrated ? _migrated : 0);
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) {
_inner.msgUpdated(msg);
_inner.redrawItem(msg);
}
}

View File

@ -69,7 +69,7 @@ public:
void mediaOverviewUpdated(bool fromResize = false);
void changingMsgId(HistoryItem *row, MsgId newId);
void msgUpdated(const HistoryItem *msg);
void redrawItem(const HistoryItem *msg);
void itemRemoved(HistoryItem *item);
void itemResized(HistoryItem *item, bool scrollToIt);
@ -123,8 +123,7 @@ private:
void updateDragSelection(MsgId dragSelFrom, int32 dragSelFromIndex, MsgId dragSelTo, int32 dragSelToIndex, bool dragSelecting);
void updateMsg(HistoryItem *item);
void updateMsg(MsgId itemId, int32 itemIndex);
void redrawItem(MsgId itemId, int32 itemIndex);
void touchResetSpeed();
void touchUpdateSpeed();
@ -314,7 +313,7 @@ public:
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
void changingMsgId(HistoryItem *row, MsgId newId);
void msgUpdated(const HistoryItem *msg);
void notify_redrawHistoryItem(const HistoryItem *msg);
void itemRemoved(HistoryItem *item);
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 "lang.h"
bool gRtl = false;
bool gRtl = true;// false;
Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight;
mtpDcOptions gDcOptions;

View File

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