From 61d1574023ed6ad8746375a492c2e10626d80a0f Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 23 Apr 2015 18:50:11 +0300 Subject: [PATCH] added forwarded and from names in files / audios / videos / contacts display, grouped notification for many forwarded messages, fix of getDifference() for new_session_created --- Telegram/Resources/style.txt | 1 + Telegram/SourceFiles/app.cpp | 19 +- Telegram/SourceFiles/app.h | 2 +- Telegram/SourceFiles/boxes/backgroundbox.cpp | 4 +- Telegram/SourceFiles/config.h | 2 + Telegram/SourceFiles/history.cpp | 335 ++++++++++++------ Telegram/SourceFiles/history.h | 31 +- Telegram/SourceFiles/localstorage.cpp | 31 +- Telegram/SourceFiles/mainwidget.cpp | 28 +- .../SourceFiles/mtproto/mtpConnection.cpp | 5 +- Telegram/SourceFiles/mtproto/mtpSession.cpp | 4 +- Telegram/SourceFiles/pspecific_linux.cpp | 2 +- Telegram/SourceFiles/pspecific_linux.h | 2 +- Telegram/SourceFiles/pspecific_mac.cpp | 4 +- Telegram/SourceFiles/pspecific_mac.h | 2 +- Telegram/SourceFiles/pspecific_wnd.cpp | 2 +- Telegram/SourceFiles/pspecific_wnd.h | 2 +- Telegram/SourceFiles/telegram.qrc | 1 + Telegram/SourceFiles/window.cpp | 100 ++++-- Telegram/SourceFiles/window.h | 3 +- 20 files changed, 384 insertions(+), 196 deletions(-) diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 55d135daf..18ce6aba0 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -832,6 +832,7 @@ msgPressedLinkColor: #004bad; msgSkip: 40px; msgPtr: 8px; msgBG: ':/gui/art/bg.jpg'; +msgBG0: ':/gui/art/bg0.png'; msgSendingRect: sprite(260px, 20px, 20px, 20px); msgCheckRect: sprite(320px, 0px, 20px, 20px); diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 32bcf2140..5b978c39b 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1814,8 +1814,17 @@ namespace App { QImage img(p); bool remove = false; if (p.isNull()) { - img.load(st::msgBG); - id = 0; + if (id == DefaultChatBackground) { + img.load(st::msgBG); + } else { + img.load(st::msgBG0); + if (cRetina()) { + img = img.scaledToWidth(img.width() * 2, Qt::SmoothTransformation); + } else if (cScale() != dbisOne) { + img = img.scaledToWidth(convertScale(img.width()), Qt::SmoothTransformation); + } + id = 0; + } remove = true; } if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied && img.format() != QImage::Format_RGB32) { @@ -1823,10 +1832,8 @@ namespace App { } img.setDevicePixelRatio(cRetinaFactor()); - if (remove) { - Local::writeBackground(0, QImage()); - } else if (!nowrite) { - Local::writeBackground(id, img); + if (!nowrite) { + Local::writeBackground(id, remove ? QImage() : img); } delete cChatBackground(); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index fdec443c3..1f32f206f 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -196,7 +196,7 @@ namespace App { void openUserByName(const QString &username, bool toProfile = false); void openLocalUrl(const QString &url); - void initBackground(int32 id = 0, const QImage &p = QImage(), bool nowrite = false); + void initBackground(int32 id = DefaultChatBackground, const QImage &p = QImage(), bool nowrite = false); style::color msgServiceBG(); style::color historyScrollBarColor(); diff --git a/Telegram/SourceFiles/boxes/backgroundbox.cpp b/Telegram/SourceFiles/boxes/backgroundbox.cpp index 082047d51..35343e2a8 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.cpp +++ b/Telegram/SourceFiles/boxes/backgroundbox.cpp @@ -37,7 +37,7 @@ _bgCount(0), _rows(0), _over(-1), _overDown(-1) { void BackgroundInner::gotWallpapers(const MTPVector &result) { App::WallPapers wallpapers; - wallpapers.push_back(App::WallPaper(0, ImagePtr(st::msgBG), ImagePtr(st::msgBG))); + wallpapers.push_back(App::WallPaper(0, ImagePtr(st::msgBG0), ImagePtr(st::msgBG0))); const QVector &v(result.c_vector().v); for (int i = 0, l = v.size(); i < l; ++i) { const MTPWallPaper w(v.at(i)); @@ -210,7 +210,7 @@ void BackgroundBox::onBackgroundChosen(int index) { if (index >= 0 && index < App::cServerBackgrounds().size()) { const App::WallPaper &paper(App::cServerBackgrounds().at(index)); if (App::main()) App::main()->setChatBackground(paper); - if (App::settings()) App::settings()->needBackgroundUpdate(false); + if (App::settings()) App::settings()->needBackgroundUpdate(!paper.id); } emit closed(); } diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index b538ece3e..bd1ff2344 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -255,6 +255,8 @@ static const char *DefaultCountry = "US"; static const char *DefaultLanguage = "en"; enum { + DefaultChatBackground = 21, + DialogsFirstLoad = 20, // first dialogs part size requested DialogsPerPage = 40, // next dialogs part size diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 3c6d11b34..888a0a468 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -97,6 +97,12 @@ namespace { inline const HistoryReply *toHistoryReply(const HistoryItem *item) { return item ? item->toHistoryReply() : 0; } + inline HistoryForwarded *toHistoryForwarded(HistoryItem *item) { + return item ? item->toHistoryForwarded() : 0; + } + inline const HistoryForwarded *toHistoryForwarded(const HistoryItem *item) { + return item ? item->toHistoryForwarded() : 0; + } } void historyInit() { @@ -1855,12 +1861,16 @@ void HistoryVideo::initDimensions(const HistoryItem *parent) { _maxw += st::mediaSaveDelta + _buttonWidth; } _minh = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom(); + if (!parent->out() && parent->history()->peer->chat) { + _minh += st::msgPadding.top() + st::msgNameFont->height; + } if (const HistoryReply *reply = toHistoryReply(parent)) { - _maxw += st::mediaPadding.left() + st::mediaPadding.right(); _minh += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - _minh += st::msgPadding.top() + st::msgNameFont->height; + } else if (const HistoryForwarded *fwd = toHistoryForwarded(parent)) { + if (parent->out() || !parent->history()->peer->chat) { + _minh += st::msgPadding.top(); } + _minh += st::msgServiceNameFont->height; } _height = _minh; } @@ -1894,13 +1904,20 @@ void HistoryVideo::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } bool out = parent->out(), hovered, pressed; @@ -1917,17 +1934,21 @@ void HistoryVideo::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co width -= btnw + st::mediaSaveDelta; } - if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - lnk = parent->from()->lnk; - return; - } + if (!parent->out() && parent->history()->peer->chat) { + if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { + lnk = parent->from()->lnk; + return; } + } + if (reply) { if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { lnk = reply->replyToLink(); return; } + } else if (fwd) { + if (y >= fwdFrom && y < skipy) { + return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } } if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { @@ -1945,13 +1966,20 @@ void HistoryVideo::draw(QPainter &p, const HistoryItem *parent, bool selected, i if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } data->thumb->checkload(); @@ -1986,13 +2014,15 @@ void HistoryVideo::draw(QPainter &p, const HistoryItem *parent, bool selected, i style::color shadow(selected ? (out ? st::msgOutSelectShadow : st::msgInSelectShadow) : (out ? st::msgOutShadow : st::msgInShadow)); p.fillRect(0, _height, width, st::msgShadow, shadow->b); + if (!parent->out() && parent->history()->peer->chat) { + p.setFont(st::msgNameFont->f); + p.setPen(parent->from()->color->p); + parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - p.setFont(st::msgNameFont->f); - p.setPen(parent->from()->color->p); - parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); - } reply->drawReplyTo(p, st::msgReplyPadding.left(), replyFrom, width - st::msgReplyPadding.left() - st::msgReplyPadding.right(), selected); + } else if (fwd) { + fwd->drawForwardedFrom(p, st::mediaPadding.left(), fwdFrom, width - st::mediaPadding.left() - st::mediaPadding.right(), selected); } if (_thumbw) { @@ -2102,12 +2132,16 @@ void HistoryAudio::initDimensions(const HistoryItem *parent) { } _minh = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom(); + if (!parent->out() && parent->history()->peer->chat) { + _minh += st::msgPadding.top() + st::msgNameFont->height; + } if (const HistoryReply *reply = toHistoryReply(parent)) { - _maxw += st::mediaPadding.left() + st::mediaPadding.right(); _minh += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - _minh += st::msgPadding.top() + st::msgNameFont->height; + } else if (const HistoryForwarded *fwd = toHistoryForwarded(parent)) { + if (parent->out() || !parent->history()->peer->chat) { + _minh += st::msgPadding.top(); } + _minh += st::msgServiceNameFont->height; } _height = _minh; } @@ -2117,13 +2151,20 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } bool out = parent->out(), hovered, pressed, already = !data->already().isEmpty(), hasdata = !data->data.isEmpty(); @@ -2161,13 +2202,15 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i style::color shadow(selected ? (out ? st::msgOutSelectShadow : st::msgInSelectShadow) : (out ? st::msgOutShadow : st::msgInShadow)); p.fillRect(0, _height, width, st::msgShadow, shadow->b); + if (!parent->out() && parent->history()->peer->chat) { + p.setFont(st::msgNameFont->f); + p.setPen(parent->from()->color->p); + parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - p.setFont(st::msgNameFont->f); - p.setPen(parent->from()->color->p); - parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); - } reply->drawReplyTo(p, st::msgReplyPadding.left(), replyFrom, width - st::msgReplyPadding.left() - st::msgReplyPadding.right(), selected); + } else if (fwd) { + fwd->drawForwardedFrom(p, st::mediaPadding.left(), fwdFrom, width - st::mediaPadding.left() - st::mediaPadding.right(), selected); } AudioData *playing = 0; @@ -2280,13 +2323,20 @@ void HistoryAudio::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } bool out = parent->out(), hovered, pressed; @@ -2303,17 +2353,21 @@ void HistoryAudio::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co width -= btnw + st::mediaSaveDelta; } - if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - lnk = parent->from()->lnk; - return; - } + if (!parent->out() && parent->history()->peer->chat) { + if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { + lnk = parent->from()->lnk; + return; } + } + if (reply) { if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { lnk = reply->replyToLink(); return; } + } else if (fwd) { + if (y >= fwdFrom && y < skipy) { + return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } } if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { @@ -2379,12 +2433,16 @@ void HistoryDocument::initDimensions(const HistoryItem *parent) { } _minh = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom(); + if (!parent->out() && parent->history()->peer->chat) { + _minh += st::msgPadding.top() + st::msgNameFont->height; + } if (const HistoryReply *reply = toHistoryReply(parent)) { - _maxw += st::mediaPadding.left() + st::mediaPadding.right(); _minh += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - _minh += st::msgPadding.top() + st::msgNameFont->height; + } else if (const HistoryForwarded *fwd = toHistoryForwarded(parent)) { + if (parent->out() || !parent->history()->peer->chat) { + _minh += st::msgPadding.top(); } + _minh += st::msgServiceNameFont->height; } } _height = _minh; @@ -2416,13 +2474,20 @@ void HistoryDocument::draw(QPainter &p, const HistoryItem *parent, bool selected } const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } data->thumb->checkload(); @@ -2456,15 +2521,16 @@ void HistoryDocument::draw(QPainter &p, const HistoryItem *parent, bool selected style::color shadow(selected ? (out ? st::msgOutSelectShadow : st::msgInSelectShadow) : (out ? st::msgOutShadow : st::msgInShadow)); p.fillRect(0, _height, width, st::msgShadow, shadow->b); - if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - p.setFont(st::msgNameFont->f); - p.setPen(parent->from()->color->p); - parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); - } - reply->drawReplyTo(p, st::msgReplyPadding.left(), replyFrom, width - st::msgReplyPadding.left() - st::msgReplyPadding.right(), selected); + if (!parent->out() && parent->history()->peer->chat) { + p.setFont(st::msgNameFont->f); + p.setPen(parent->from()->color->p); + parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } + if (reply) { + reply->drawReplyTo(p, st::msgReplyPadding.left(), replyFrom, width - st::msgReplyPadding.left() - st::msgReplyPadding.right(), selected); + } else if (fwd) { + fwd->drawForwardedFrom(p, st::mediaPadding.left(), fwdFrom, width - st::mediaPadding.left() - st::mediaPadding.right(), selected); } - if (_thumbw) { int32 rf(cIntRetinaFactor()); p.drawPixmap(QPoint(st::mediaPadding.left(), skipy + st::mediaPadding.top()), data->thumb->pix(_thumbw), QRect(_thumbx * rf, _thumby * rf, st::mediaThumbSize * rf, st::mediaThumbSize * rf)); @@ -2617,13 +2683,20 @@ void HistoryDocument::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, } const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } if (!out) { // draw Download / Save As button @@ -2635,17 +2708,21 @@ void HistoryDocument::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, width -= btnw + st::mediaSaveDelta; } - if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - lnk = parent->from()->lnk; - return; - } + if (!parent->out() && parent->history()->peer->chat) { + if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { + lnk = parent->from()->lnk; + return; } + } + if (reply) { if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { lnk = reply->replyToLink(); return; } + } else if (fwd) { + if (y >= fwdFrom && y < skipy) { + return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } } if (x >= 0 && y >= skipy && x < width && y < _height && !data->loader && data->access) { @@ -2896,12 +2973,16 @@ void HistoryContact::initDimensions(const HistoryItem *parent) { _maxw = phonew + tleft + st::mediaPadding.right(); } _minh = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom(); + if (!parent->out() && parent->history()->peer->chat) { + _minh += st::msgPadding.top() + st::msgNameFont->height; + } if (const HistoryReply *reply = toHistoryReply(parent)) { - _maxw += st::mediaPadding.left() + st::mediaPadding.right(); _minh += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - _minh += st::msgPadding.top() + st::msgNameFont->height; + } else if (const HistoryForwarded *fwd = toHistoryForwarded(parent)) { + if (parent->out() || !parent->history()->peer->chat) { + _minh += st::msgPadding.top(); } + _minh += st::msgServiceNameFont->height; } _height = _minh; } @@ -2923,26 +3004,37 @@ void HistoryContact::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, if (width < 0) width = w; const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } - if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { - lnk = parent->from()->lnk; - return; - } + if (!parent->out() && parent->history()->peer->chat) { + if (x >= st::mediaPadding.left() && y >= st::msgPadding.top() && x < width - st::mediaPadding.left() - st::mediaPadding.right() && x < st::mediaPadding.left() + parent->from()->nameText.maxWidth() && y < replyFrom) { + lnk = parent->from()->lnk; + return; } + } + if (reply) { if (x >= 0 && y >= replyFrom + st::msgReplyPadding.top() && x < width && y < skipy - st::msgReplyPadding.bottom()) { lnk = reply->replyToLink(); return; } + } else if (fwd) { + if (y >= fwdFrom && y < skipy) { + return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } } if (x >= 0 && y >= skipy && x < w && y < _height && contact) { @@ -2967,13 +3059,20 @@ void HistoryContact::draw(QPainter &p, const HistoryItem *parent, bool selected, if (width < 1) return; const HistoryReply *reply = toHistoryReply(parent); - int skipy = 0, replyFrom = 0; + const HistoryForwarded *fwd = reply ? 0 : toHistoryForwarded(parent); + int skipy = 0, replyFrom = 0, fwdFrom = 0; if (reply) { skipy = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (!parent->out() && parent->history()->peer->chat) { - replyFrom = st::msgPadding.top() + st::msgNameFont->height; - skipy += replyFrom; - } + } else if (fwd) { + skipy = st::msgServiceNameFont->height; + } + if (!parent->out() && parent->history()->peer->chat) { + replyFrom = st::msgPadding.top() + st::msgNameFont->height; + fwdFrom = st::msgPadding.top() + st::msgNameFont->height; + skipy += replyFrom; + } else if (fwd) { + fwdFrom = st::msgPadding.top(); + skipy += fwdFrom; } bool out = parent->out(); @@ -2987,13 +3086,15 @@ void HistoryContact::draw(QPainter &p, const HistoryItem *parent, bool selected, style::color shadow(selected ? (out ? st::msgOutSelectShadow : st::msgInSelectShadow) : (out ? st::msgOutShadow : st::msgInShadow)); p.fillRect(0, _height, width, st::msgShadow, shadow->b); + if (!parent->out() && parent->history()->peer->chat) { + p.setFont(st::msgNameFont->f); + p.setPen(parent->from()->color->p); + parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); + } if (reply) { - if (!parent->out() && parent->history()->peer->chat) { - p.setFont(st::msgNameFont->f); - p.setPen(parent->from()->color->p); - parent->from()->nameText.drawElided(p, st::mediaPadding.left(), st::msgPadding.top(), width - st::mediaPadding.left() - st::mediaPadding.right()); - } reply->drawReplyTo(p, st::msgReplyPadding.left(), replyFrom, width - st::msgReplyPadding.left() - st::msgReplyPadding.right(), selected); + } else if (fwd) { + fwd->drawForwardedFrom(p, st::mediaPadding.left(), fwdFrom, width - st::mediaPadding.left() - st::mediaPadding.right(), selected); } p.drawPixmap(st::mediaPadding.left(), skipy + st::mediaPadding.top(), (contact ? contact->photo : userDefPhoto(1))->pix(st::mediaThumbSize)); @@ -4680,8 +4781,8 @@ void HistoryForwarded::initDimensions(const HistoryItem *parent) { } void HistoryForwarded::fwdNameUpdated() const { - if (justMedia()) return; fwdFromName.setText(st::msgServiceNameFont, App::peerName(fwdFrom), _textNameOptions); + if (justMedia()) return; int32 _namew = fromWidth + fwdFromName.maxWidth() + st::msgPadding.left() + st::msgPadding.right(); if (_namew > _maxw) _maxw = _namew; } @@ -4694,22 +4795,26 @@ void HistoryForwarded::draw(QPainter &p, uint32 selection) const { HistoryMessage::draw(p, selection); } -void HistoryForwarded::drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const { +void HistoryForwarded::drawForwardedFrom(QPainter &p, int32 x, int32 y, int32 w, bool selected) const { style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont); - bool selected = (selection == FullItemSel); + p.setPen((selected ? (out() ? st::msgOutServiceSelColor : st::msgInServiceSelColor) : (out() ? st::msgOutServiceColor : st::msgInServiceColor))->p); p.setFont(serviceFont->f); - int32 h1 = 0, h2 = serviceName->height, h = h1 + (h1 > h2 ? h1 : h2); - - if (trect.width() >= fromWidth) { - p.drawText(trect.x(), trect.y() + h1 + serviceFont->ascent, lang(lng_forwarded_from)); + if (w >= fromWidth) { + p.drawText(x, y + serviceFont->ascent, lang(lng_forwarded_from)); p.setFont(serviceName->f); - fwdFromName.drawElided(p, trect.x() + fromWidth, trect.y() + h1, trect.width() - fromWidth); + fwdFromName.drawElided(p, x + fromWidth, y, w - fromWidth); } else { - p.drawText(trect.x(), trect.y() + h1 + serviceFont->ascent, serviceFont->m.elidedText(lang(lng_forwarded_from), Qt::ElideRight, trect.width())); + p.drawText(x, y + serviceFont->ascent, serviceFont->m.elidedText(lang(lng_forwarded_from), Qt::ElideRight, w)); } +} + +void HistoryForwarded::drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const { + int32 h = st::msgServiceNameFont->height; + + drawForwardedFrom(p, trect.x(), trect.y(), trect.width(), (selection == FullItemSel)); QRect realtrect(trect); realtrect.setY(trect.y() + h); @@ -4783,16 +4888,22 @@ void HistoryForwarded::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y QRect trect(r.marginsAdded(-st::msgPadding)); if (y >= trect.top() && y < trect.top() + st::msgServiceNameFont->height) { - if (x >= trect.left() + fromWidth && x < trect.right() && x < trect.left() + fromWidth + fwdFromName.maxWidth()) { - lnk = fwdFrom->lnk; - } - return; + return getForwardedState(lnk, inText, x - trect.left(), trect.right() - trect.left()); } y -= st::msgServiceNameFont->height; } return HistoryMessage::getState(lnk, inText, x, y); } +void HistoryForwarded::getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const { + inText = false; + if (x >= fromWidth && x < w && x < fromWidth + fwdFromName.maxWidth()) { + lnk = fwdFrom->lnk; + } else { + lnk = TextLinkPtr(); + } +} + void HistoryForwarded::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { symbol = 0; after = false; diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index a0f7c65be..afc05c5be 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -218,6 +218,9 @@ struct History : public QList { HistoryItem *currentNotification() { return notifies.isEmpty() ? 0 : notifies.front(); } + bool hasNotification() const { + return !notifies.isEmpty(); + } void skipNotification() { if (!notifies.isEmpty()) { notifies.pop_front(); @@ -621,6 +624,7 @@ ItemAnimations &itemAnimations(); class HistoryReply; // dynamic_cast optimize class HistoryMessage; // dynamic_cast optimize +class HistoryForwarded; // dynamic_cast optimize class HistoryMedia; class HistoryItem : public HistoryElem { @@ -730,18 +734,24 @@ public: return false; } - virtual HistoryReply *toHistoryReply() { // dynamic_cast optimize - return 0; - } - virtual const HistoryReply *toHistoryReply() const { // dynamic_cast optimize - return 0; - } virtual HistoryMessage *toHistoryMessage() { // dynamic_cast optimize return 0; } virtual const HistoryMessage *toHistoryMessage() const { // dynamic_cast optimize return 0; } + virtual HistoryForwarded *toHistoryForwarded() { // dynamic_cast optimize + return 0; + } + virtual const HistoryForwarded *toHistoryForwarded() const { // dynamic_cast optimize + return 0; + } + virtual HistoryReply *toHistoryReply() { // dynamic_cast optimize + return 0; + } + virtual const HistoryReply *toHistoryReply() const { // dynamic_cast optimize + return 0; + } virtual ~HistoryItem(); @@ -1282,10 +1292,12 @@ public: void fwdNameUpdated() const; void draw(QPainter &p, uint32 selection) const; + void drawForwardedFrom(QPainter &p, int32 x, int32 y, int32 w, bool selected) const; void drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const; int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0); bool hasPoint(int32 x, int32 y) const; void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const; + void getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const; void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const; QDateTime dateForwarded() const { @@ -1296,6 +1308,13 @@ public: } QString selectedText(uint32 selection) const; + HistoryForwarded *toHistoryForwarded() { + return this; + } + const HistoryForwarded *toHistoryForwarded() const { + return this; + } + protected: QDateTime fwdDate; diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index d069232e3..e6684cd4d 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -2181,17 +2181,8 @@ namespace Local { void writeBackground(int32 id, const QImage &img) { if (!_working()) return; - if (img.isNull()) { - if (_backgroundKey) { - clearKey(_backgroundKey); - _backgroundKey = 0; - _mapChanged = true; - } - _writeMap(); - return; - } QByteArray png; - { + if (!img.isNull()) { QBuffer buf(&png); if (!img.save(&buf, "BMP")) return; } @@ -2200,9 +2191,10 @@ namespace Local { _mapChanged = true; _writeMap(WriteMapFast); } - quint32 size = sizeof(qint32) + sizeof(quint32) + sizeof(quint32) + png.size(); + quint32 size = sizeof(qint32) + sizeof(quint32) + (png.isEmpty() ? 0 : (sizeof(quint32) + png.size())); EncryptedDescriptor data(size); - data.stream << qint32(id) << png; + data.stream << qint32(id); + if (!png.isEmpty()) data.stream << png; FileWriteDescriptor file(_backgroundKey); file.writeEncrypted(data); @@ -2222,14 +2214,23 @@ namespace Local { QByteArray pngData; qint32 id; - bg.stream >> id >> pngData; + bg.stream >> id; + if (!id || id == DefaultChatBackground) { + if (bg.version < 8005) { + if (!id) cSetTileBackground(!DefaultChatBackground); + App::initBackground(DefaultChatBackground, QImage(), true); + } else { + App::initBackground(id, QImage(), true); + } + return true; + } + bg.stream >> pngData; QImage img; QBuffer buf(&pngData); QImageReader reader(&buf); if (reader.read(&img)) { - if (!id) cSetTileBackground(false); - App::initBackground(id, id ? img : QImage(), true); + App::initBackground(id, img, true); return true; } return false; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 3825496fe..d1101163b 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1592,8 +1592,10 @@ void MainWidget::checkChatBackground() { if (_background->full->loaded()) { if (_background->full->isNull()) { App::initBackground(); + } else if (_background->id == 0 || _background->id == DefaultChatBackground) { + App::initBackground(_background->id); } else { - App::initBackground(_background->id, _background->id ? _background->full->pix().toImage() : QImage()); + App::initBackground(_background->id, _background->full->pix().toImage()); } delete _background; _background = 0; @@ -2340,18 +2342,18 @@ void MainWidget::clearSkippedPtsUpdates() { bool MainWidget::updPtsUpdated(int pts, int ptsCount) { // return false if need to save that update and apply later if (!updInited || updSkipPtsUpdateLevel) return true; -updLastPts = qMax(updLastPts, pts); -updPtsCount += ptsCount; -if (updLastPts == updPtsCount) { - applySkippedPtsUpdates(); - updGoodPts = updLastPts; - return true; -} else if (updLastPts < updPtsCount) { - _byPtsTimer.startIfNotActive(1); -} else { - _byPtsTimer.startIfNotActive(WaitForSkippedTimeout); -} -return !ptsCount; + updLastPts = qMax(updLastPts, pts); + updPtsCount += ptsCount; + if (updLastPts == updPtsCount) { + applySkippedPtsUpdates(); + updGoodPts = updLastPts; + return true; + } else if (updLastPts < updPtsCount) { + _byPtsTimer.startIfNotActive(1); + } else { + _byPtsTimer.startIfNotActive(WaitForSkippedTimeout); + } + return !ptsCount; } void MainWidget::feedDifference(const MTPVector &users, const MTPVector &chats, const MTPVector &msgs, const MTPVector &other) { diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.cpp b/Telegram/SourceFiles/mtproto/mtpConnection.cpp index c4622735a..e5c9910c1 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.cpp +++ b/Telegram/SourceFiles/mtproto/mtpConnection.cpp @@ -2503,6 +2503,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt case mtpc_new_session_created: { if (badTime) return 0; + const mtpPrime *start = from; MTPNewSession msg(from, end); const MTPDnew_session_created &data(msg.c_new_session_created()); DEBUG_LOG(("Message Info: new server session created, unique_id %1, first_msg_id %2, server_salt %3").arg(data.vunique_id.v).arg(data.vfirst_msg_id.v).arg(data.vserver_salt.v)); @@ -2521,8 +2522,8 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt } resendMany(toResend, 10, true); - mtpBuffer update(end - from); - if (end > from) memcpy(update.data(), from, (end - from) * sizeof(mtpPrime)); + mtpBuffer update(from - start); + if (from > start) memcpy(update.data(), start, (from - start) * sizeof(mtpPrime)); QWriteLocker locker(sessionData->haveReceivedMutex()); mtpResponseMap &haveReceived(sessionData->haveReceivedMap()); diff --git a/Telegram/SourceFiles/mtproto/mtpSession.cpp b/Telegram/SourceFiles/mtproto/mtpSession.cpp index d0654dff4..2fabcff0e 100644 --- a/Telegram/SourceFiles/mtproto/mtpSession.cpp +++ b/Telegram/SourceFiles/mtproto/mtpSession.cpp @@ -481,7 +481,9 @@ void MTProtoSession::tryToReceive() { responses.erase(i); } if (requestId <= 0) { - _mtp_internal::globalCallback(response.constData(), response.constData() + response.size()); + if (dcId < _mtp_internal::dcShift) { // call globalCallback only in main session + _mtp_internal::globalCallback(response.constData(), response.constData() + response.size()); + } } else { _mtp_internal::execCallback(requestId, response.constData(), response.constData() + response.size()); } diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index 9ce13311e..99cee9ee5 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -906,7 +906,7 @@ void PsMainWindow::psClearNotifies(PeerId peerId) { void PsMainWindow::psNotifyShown(NotifyWindow *w) { } -void PsMainWindow::psPlatformNotify(HistoryItem *item) { +void PsMainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) { } PsApplication::PsApplication(int &argc, char **argv) : QApplication(argc, argv) { diff --git a/Telegram/SourceFiles/pspecific_linux.h b/Telegram/SourceFiles/pspecific_linux.h index d03bd5cef..d34bab2ea 100644 --- a/Telegram/SourceFiles/pspecific_linux.h +++ b/Telegram/SourceFiles/pspecific_linux.h @@ -64,7 +64,7 @@ public: void psActivateNotify(NotifyWindow *w); void psClearNotifies(PeerId peerId = 0); void psNotifyShown(NotifyWindow *w); - void psPlatformNotify(HistoryItem *item); + void psPlatformNotify(HistoryItem *item, int32 fwdCount); void psUpdateCounter(); diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index f9dfa1a18..bc614893c 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -489,11 +489,11 @@ void PsMainWindow::psNotifyShown(NotifyWindow *w) { psShowOverAll(w, false); } -void PsMainWindow::psPlatformNotify(HistoryItem *item) { +void PsMainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) { QString title = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->history()->peer->name : qsl("Telegram Desktop"); QString subtitle = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->notificationHeader() : QString(); QPixmap pix = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->history()->peer->photo->pix(st::notifyMacPhotoSize) : QPixmap(); - QString msg = (!App::passcoded() && cNotifyView() <= dbinvShowPreview) ? item->notificationText() : lang(lng_notification_preview); + QString msg = (!App::passcoded() && cNotifyView() <= dbinvShowPreview) ? (fwdCount < 2 ? item->notificationText() : lng_forward_messages(lt_count, fwdCount)) : lang(lng_notification_preview); _private.showNotify(item->history()->peer->id, item->id, pix, title, subtitle, msg, !App::passcoded() && (cNotifyView() <= dbinvShowPreview)); } diff --git a/Telegram/SourceFiles/pspecific_mac.h b/Telegram/SourceFiles/pspecific_mac.h index b905a528d..448930ca3 100644 --- a/Telegram/SourceFiles/pspecific_mac.h +++ b/Telegram/SourceFiles/pspecific_mac.h @@ -75,7 +75,7 @@ public: void psActivateNotify(NotifyWindow *w); void psClearNotifies(PeerId peerId = 0); void psNotifyShown(NotifyWindow *w); - void psPlatformNotify(HistoryItem *item); + void psPlatformNotify(HistoryItem *item, int32 fwdCount); bool eventFilter(QObject *obj, QEvent *evt); diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index 320b3eaa5..62cc470ef 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -1372,7 +1372,7 @@ void PsMainWindow::psClearNotifies(PeerId peerId) { void PsMainWindow::psNotifyShown(NotifyWindow *w) { } -void PsMainWindow::psPlatformNotify(HistoryItem *item) { +void PsMainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) { } PsApplication::PsApplication(int &argc, char **argv) : QApplication(argc, argv) { diff --git a/Telegram/SourceFiles/pspecific_wnd.h b/Telegram/SourceFiles/pspecific_wnd.h index 8be2c9159..99ed0b850 100644 --- a/Telegram/SourceFiles/pspecific_wnd.h +++ b/Telegram/SourceFiles/pspecific_wnd.h @@ -63,7 +63,7 @@ public: void psActivateNotify(NotifyWindow *w); void psClearNotifies(PeerId peerId = 0); void psNotifyShown(NotifyWindow *w); - void psPlatformNotify(HistoryItem *item); + void psPlatformNotify(HistoryItem *item, int32 fwdCount); void psUpdateCounter(); diff --git a/Telegram/SourceFiles/telegram.qrc b/Telegram/SourceFiles/telegram.qrc index c86458f3d..e15d6acaf 100644 --- a/Telegram/SourceFiles/telegram.qrc +++ b/Telegram/SourceFiles/telegram.qrc @@ -5,6 +5,7 @@ art/fonts/OpenSans-Semibold.ttf art/newmsg.wav art/bg.jpg + art/bg0.png art/sprite.png art/sprite_125x.png art/sprite_150x.png diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index fb19b8ee1..420d8b017 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -68,7 +68,7 @@ void ConnectingWidget::onReconnect() { MTP::restart(); } -NotifyWindow::NotifyWindow(HistoryItem *msg, int32 x, int32 y) : history(msg->history()), item(msg) +NotifyWindow::NotifyWindow(HistoryItem *msg, int32 x, int32 y, int32 fwdCount) : history(msg->history()), item(msg), fwdCount(fwdCount) #ifdef Q_OS_WIN , started(GetTickCount()) #endif @@ -192,8 +192,21 @@ void NotifyWindow::updateNotifyDisplay() { if (!App::passcoded() && cNotifyView() <= dbinvShowPreview) { const HistoryItem *textCachedFor = 0; Text itemTextCache(itemWidth); - bool active = false; - item->drawInDialog(p, QRect(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dlgFont->height), active, textCachedFor, itemTextCache); + QRect r(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dlgFont->height); + if (fwdCount < 2) { + bool active = false; + item->drawInDialog(p, r, active, textCachedFor, itemTextCache); + } else { + p.setFont(st::dlgHistFont->f); + if (history->peer->chat) { + itemTextCache.setText(st::dlgHistFont, item->from()->name); + p.setPen(st::dlgSystemColor->p); + itemTextCache.drawElided(p, r.left(), r.top(), r.width(), st::dlgHistFont->height); + r.setTop(r.top() + st::dlgHistFont->height); + } + p.setPen(st::dlgTextColor->p); + p.drawText(r.left(), r.top() + st::dlgHistFont->ascent, lng_forward_messages(lt_count, fwdCount)); + } } else { static QString notifyText = st::dlgHistFont->m.elidedText(lang(lng_notification_preview), Qt::ElideRight, itemWidth); p.setPen(st::dlgSystemColor->p); @@ -1237,7 +1250,8 @@ void Window::notifySchedule(History *history, HistoryItem *item) { App::wnd()->getNotifySetting(MTP_inputNotifyPeer(history->peer->input)); } - int delay = 100, t = unixtime(); + HistoryForwarded *fwd = item->toHistoryForwarded(); + int delay = fwd ? 500 : 100, t = unixtime(); uint64 ms = getms(true); bool isOnline = main->lastWasOnline(), otherNotOld = ((cOtherOnline() * uint64(1000)) + cOnlineCloudTimeout() > t * uint64(1000)); bool otherLaterThanMe = (cOtherOnline() * uint64(1000) + (ms - main->lastSetOnline()) > t * uint64(1000)); @@ -1354,7 +1368,9 @@ void Window::notifyShowNext(NotifyWindow *remove) { for (NotifyWhenAlerts::iterator i = notifyWhenAlerts.begin(); i != notifyWhenAlerts.end();) { while (!i.value().isEmpty() && i.value().begin().key() <= ms) { NotifySettingsPtr n = i.key()->peer->notify, f = i.value().begin().value() ? i.value().begin().value()->notify : UnknownNotifySettings; - i.value().erase(i.value().begin()); + while (!i.value().isEmpty() && i.value().begin().key() <= ms + 500) { // not more than one sound in 500ms from one peer - grouping + i.value().erase(i.value().begin()); + } if (n == EmptyNotifySettings || (n != UnknownNotifySettings && n->mute <= now)) { alert = true; } else if (f == EmptyNotifySettings || (f != UnknownNotifySettings && f->mute <= now)) { // notify by from() @@ -1435,40 +1451,64 @@ void Window::notifyShowNext(NotifyWindow *remove) { notifyWaitTimer.start(next - ms); break; } else { - if (cCustomNotifies()) { - NotifyWindow *notify = new NotifyWindow(notifyItem, x, y); - notifyWindows.push_back(notify); - psNotifyShown(notify); - --count; - } else { - psPlatformNotify(notifyItem); - } + HistoryForwarded *fwd = notifyItem->toHistoryForwarded(); // forwarded notify grouping + int32 fwdCount = 1; uint64 ms = getms(true); History *history = notifyItem->history(); - history->skipNotification(); NotifyWhenMaps::iterator j = notifyWhenMaps.find(history); - if (j == notifyWhenMaps.end() || !history->currentNotification()) { + + if (j == notifyWhenMaps.end()) { history->clearNotifications(); + } else { + HistoryItem *nextNotify = 0; + do { + history->skipNotification(); + if (!history->hasNotification()) { + break; + } + + j.value().remove((fwd ? fwd : notifyItem)->id); + do { + NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id); + if (k != j.value().cend()) { + nextNotify = history->currentNotification(); + notifyWaiter.value().msg = k.key(); + notifyWaiter.value().when = k.value(); + break; + } + history->skipNotification(); + } while (history->hasNotification()); + if (nextNotify) { + if (fwd) { + HistoryForwarded *nextFwd = nextNotify->toHistoryForwarded(); + if (nextFwd && fwd->from() == nextFwd->from() && qAbs(int64(nextFwd->date.toTime_t()) - int64(fwd->date.toTime_t())) < 2) { + fwd = nextFwd; + ++fwdCount; + } else { + nextNotify = 0; + } + } else { + nextNotify = 0; + } + } + } while (nextNotify); + } + + if (cCustomNotifies()) { + NotifyWindow *notify = new NotifyWindow(notifyItem, x, y, fwdCount); + notifyWindows.push_back(notify); + psNotifyShown(notify); + --count; + } else { + psPlatformNotify(notifyItem, fwdCount); + } + + if (!history->hasNotification()) { notifyWaiters.erase(notifyWaiter); if (j != notifyWhenMaps.end()) notifyWhenMaps.erase(j); continue; } - j.value().remove(notifyItem->id); - do { - NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id); - if (k != j.value().cend()) { - notifyWaiter.value().msg = k.key(); - notifyWaiter.value().when = k.value(); - break; - } - history->skipNotification(); - } while (history->currentNotification()); - if (!history->currentNotification()) { - notifyWaiters.erase(notifyWaiter); - notifyWhenMaps.erase(j); - continue; - } } } else { break; diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h index 091a97af4..e6e2f981e 100644 --- a/Telegram/SourceFiles/window.h +++ b/Telegram/SourceFiles/window.h @@ -61,7 +61,7 @@ class NotifyWindow : public QWidget, public Animated { public: - NotifyWindow(HistoryItem *item, int32 x, int32 y); + NotifyWindow(HistoryItem *item, int32 x, int32 y, int32 fwdCount); void enterEvent(QEvent *e); void leaveEvent(QEvent *e); @@ -101,6 +101,7 @@ private: #endif History *history; HistoryItem *item; + int32 fwdCount; IconedButton close; QPixmap pm; float64 alphaDuration, posDuration;