diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index 9da642db0..0752658d0 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -18,6 +18,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_overview.h" #include "styles/style_boxes.h" +namespace { + +constexpr auto kBackgroundsInRow = 3; + +} // namespace + class BackgroundBox::Inner : public Ui::RpWidget , private MTP::Sender @@ -42,10 +48,9 @@ private: Fn _backgroundChosenCallback; - int _bgCount = 0; - int _rows = 0; int _over = -1; int _overDown = -1; + std::unique_ptr _check; // this is not a widget }; @@ -67,12 +72,9 @@ void BackgroundBox::prepare() { } void BackgroundBox::backgroundChosen(int index) { - if (index >= 0 && index < Auth().data().wallpapersCount()) { - const auto &paper = Auth().data().wallpaper(index); - App::main()->setChatBackground(paper); - - using Update = Window::Theme::BackgroundUpdate; - Window::Theme::Background()->notify(Update(Update::Type::Start, !paper.id)); + const auto &papers = Auth().data().wallpapers(); + if (index >= 0 && index < papers.size()) { + App::main()->setChatBackground(papers[index]); } closeBox(); } @@ -80,24 +82,21 @@ void BackgroundBox::backgroundChosen(int index) { BackgroundBox::Inner::Inner(QWidget *parent) : RpWidget(parent) , _check(std::make_unique(st::overviewCheck, [=] { update(); })) { _check->setChecked(true, Ui::RoundCheckbox::SetStyle::Fast); - if (!Auth().data().wallpapersCount()) { - resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding); - request(MTPaccount_GetWallPapers( - MTP_int(0) - )).done([=](const MTPaccount_WallPapers &result) { - result.match([&](const MTPDaccount_wallPapers &data) { - Auth().data().setWallpapers(data.vwallpapers.v); - updateWallpapers(); - }, [&](const MTPDaccount_wallPapersNotModified &) { - LOG(("API Error: account.wallPapersNotModified received.")); - }); - }).send(); + if (Auth().data().wallpapers().empty()) { + resize(kBackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding); } else { updateWallpapers(); } + request(MTPaccount_GetWallPapers( + MTP_int(Auth().data().wallpapersHash()) + )).done([=](const MTPaccount_WallPapers &result) { + if (Auth().data().updateWallpapers(result)) { + updateWallpapers(); + } + }).send(); - subscribe(Auth().downloaderTaskFinished(), [this] { update(); }); - subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { + subscribe(Auth().downloaderTaskFinished(), [=] { update(); }); + subscribe(Window::Theme::Background(), [=](const Window::Theme::BackgroundUpdate &update) { if (update.paletteChanged()) { _check->invalidateCache(); } @@ -106,15 +105,16 @@ BackgroundBox::Inner::Inner(QWidget *parent) : RpWidget(parent) } void BackgroundBox::Inner::updateWallpapers() { - _bgCount = Auth().data().wallpapersCount(); - _rows = _bgCount / BackgroundsInRow; - if (_bgCount % BackgroundsInRow) ++_rows; + const auto &papers = Auth().data().wallpapers(); + const auto count = papers.size(); + const auto rows = (count / kBackgroundsInRow) + + (count % kBackgroundsInRow ? 1 : 0); - resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, _rows * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding); - for (int i = 0; i < BackgroundsInRow * 3; ++i) { - if (i >= _bgCount) break; + resize(kBackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, rows * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding); - Auth().data().wallpaper(i).thumb->load(Data::FileOrigin()); + const auto preload = kBackgroundsInRow * 3; + for (const auto &paper : papers | ranges::view::take(preload)) { + paper.thumb->load(Data::FileOrigin()); } } @@ -122,52 +122,68 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) { QRect r(e->rect()); Painter p(this); - if (_rows) { - for (int i = 0; i < _rows; ++i) { - if ((st::backgroundSize.height() + st::backgroundPadding) * (i + 1) <= r.top()) continue; - for (int j = 0; j < BackgroundsInRow; ++j) { - int index = i * BackgroundsInRow + j; - if (index >= _bgCount) break; - - const auto &paper = Auth().data().wallpaper(index); - paper.thumb->load(Data::FileOrigin()); - - int x = st::backgroundPadding + j * (st::backgroundSize.width() + st::backgroundPadding); - int y = st::backgroundPadding + i * (st::backgroundSize.height() + st::backgroundPadding); - - const auto &pix = paper.thumb->pix( - Data::FileOrigin(), - st::backgroundSize.width(), - st::backgroundSize.height()); - p.drawPixmap(x, y, pix); - - if (paper.id == Window::Theme::Background()->id()) { - auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size; - auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size; - _check->paint(p, getms(), checkLeft, checkTop, width()); - } - } - } - } else { + const auto &papers = Auth().data().wallpapers(); + if (papers.empty()) { p.setFont(st::noContactsFont); p.setPen(st::noContactsColor); p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center); + return; + } + auto row = 0; + auto column = 0; + for (const auto &paper : papers) { + const auto increment = gsl::finally([&] { + ++column; + if (column == kBackgroundsInRow) { + column = 0; + ++row; + } + }); + if ((st::backgroundSize.height() + st::backgroundPadding) * (row + 1) <= r.top()) { + continue; + } + + paper.thumb->load(Data::FileOrigin()); + + int x = st::backgroundPadding + column * (st::backgroundSize.width() + st::backgroundPadding); + int y = st::backgroundPadding + row * (st::backgroundSize.height() + st::backgroundPadding); + + const auto &pix = paper.thumb->pix( + Data::FileOrigin(), + st::backgroundSize.width(), + st::backgroundSize.height()); + p.drawPixmap(x, y, pix); + + if (paper.id == Window::Theme::Background()->id()) { + auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size; + auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size; + _check->paint(p, getms(), checkLeft, checkTop, width()); + } } } void BackgroundBox::Inner::mouseMoveEvent(QMouseEvent *e) { - int x = e->pos().x(), y = e->pos().y(); - int row = int((y - st::backgroundPadding) / (st::backgroundSize.height() + st::backgroundPadding)); - if (y - row * (st::backgroundSize.height() + st::backgroundPadding) > st::backgroundPadding + st::backgroundSize.height()) row = _rows + 1; - - int col = int((x - st::backgroundPadding) / (st::backgroundSize.width() + st::backgroundPadding)); - if (x - col * (st::backgroundSize.width() + st::backgroundPadding) > st::backgroundPadding + st::backgroundSize.width()) row = _rows + 1; - - int newOver = row * BackgroundsInRow + col; - if (newOver >= _bgCount) newOver = -1; - if (newOver != _over) { + const auto newOver = [&] { + const auto x = e->pos().x(); + const auto y = e->pos().y(); + const auto width = st::backgroundSize.width(); + const auto height = st::backgroundSize.height(); + const auto skip = st::backgroundPadding; + const auto row = int((y - skip) / (height + skip)); + const auto column = int((x - skip) / (width + skip)); + if (y - row * (height + skip) > skip + height) { + return -1; + } else if (x - column * (width + skip) > skip + width) { + return -1; + } + const auto result = row * kBackgroundsInRow + column; + return (result < Auth().data().wallpapers().size()) ? result : -1; + }(); + if (_over != newOver) { _over = newOver; - setCursor((_over >= 0 || _overDown >= 0) ? style::cur_pointer : style::cur_default); + setCursor((_over >= 0 || _overDown >= 0) + ? style::cur_pointer + : style::cur_default); } } diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 7ff666efe..bbf97ebeb 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -81,7 +81,6 @@ enum { WebPageUserId = 701000, CacheBackgroundTimeout = 3000, // cache background scaled image after 3s - BackgroundsInRow = 3, UpdateDelayConstPart = 8 * 3600, // 8 hour min time between update check requests UpdateDelayRandPart = 8 * 3600, // 8 hour max - min time between update check requests diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index fa8fb29a9..0cd774e72 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -478,10 +478,13 @@ void DocumentData::setattributes(const QVector &attributes auto &d = attributes[i].c_documentAttributeImageSize(); dimensions = QSize(d.vw.v, d.vh.v); } break; - case mtpc_documentAttributeAnimated: if (type == FileDocument || type == StickerDocument || type == VideoDocument) { - type = AnimatedDocument; - _additional = nullptr; - } break; + case mtpc_documentAttributeAnimated: + if (type == FileDocument + || type == StickerDocument + || type == VideoDocument) { + type = AnimatedDocument; + _additional = nullptr; + } break; case mtpc_documentAttributeSticker: { auto &d = attributes[i].c_documentAttributeSticker(); if (type == FileDocument) { @@ -490,7 +493,8 @@ void DocumentData::setattributes(const QVector &attributes } if (sticker()) { sticker()->alt = qs(d.valt); - if (sticker()->set.type() != mtpc_inputStickerSetID || d.vstickerset.type() == mtpc_inputStickerSetID) { + if (sticker()->set.type() != mtpc_inputStickerSetID + || d.vstickerset.type() == mtpc_inputStickerSetID) { sticker()->set = d.vstickerset; } } @@ -498,7 +502,9 @@ void DocumentData::setattributes(const QVector &attributes case mtpc_documentAttributeVideo: { auto &d = attributes[i].c_documentAttributeVideo(); if (type == FileDocument) { - type = d.is_round_message() ? RoundVideoDocument : VideoDocument; + type = d.is_round_message() + ? RoundVideoDocument + : VideoDocument; } _duration = d.vduration.v; _supportsStreaming = d.is_supports_streaming(); @@ -568,6 +574,24 @@ void DocumentData::setattributes(const QVector &attributes validateGoodThumbnail(); } +bool DocumentData::checkWallPaperProperties() { + if (type != FileDocument + || !thumb + || !dimensions.width() + || !dimensions.height() + || dimensions.width() > Storage::kMaxWallPaperDimension + || dimensions.height() > Storage::kMaxWallPaperDimension + || size > Storage::kMaxWallPaperInMemory) { + return false; + } + type = WallPaperDocument; + return true; +} + +bool DocumentData::isWallPaper() const { + return (type == WallPaperDocument); +} + Storage::Cache::Key DocumentData::goodThumbnailCacheKey() const { return Data::DocumentThumbCacheKey(_dc, id); } @@ -610,7 +634,8 @@ void DocumentData::setGoodThumbnail(QImage &&image, QByteArray &&bytes) { bool DocumentData::saveToCache() const { return (type == StickerDocument && size < Storage::kMaxStickerInMemory) || (isAnimation() && size < Storage::kMaxAnimationInMemory) - || (isVoiceMessage() && size < Storage::kMaxVoiceInMemory); + || (isVoiceMessage() && size < Storage::kMaxVoiceInMemory) + || (type == WallPaperDocument); } void DocumentData::unload() { diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index 716960678..bb91c7a9d 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -122,7 +122,7 @@ public: FilePathResolveType type = FilePathResolveCached, bool forceSavingAs = false) const; - bool saveToCache() const; + [[nodiscard]] bool saveToCache() const; void performActionOnLoad(); @@ -158,6 +158,8 @@ public: void setData(const QByteArray &data) { _data = data; } + bool checkWallPaperProperties(); + bool isWallPaper() const; bool hasGoodStickerThumb() const; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index e1919bc9f..a12370670 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -44,6 +44,7 @@ namespace Data { namespace { constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * TimeMs(1000); +constexpr auto kMaxWallpaperSize = 10 * 1024 * 1024; using ViewElement = HistoryView::Element; @@ -3055,40 +3056,52 @@ PeerData *Session::proxyPromoted() const { return _proxyPromoted; } -int Session::wallpapersCount() const { - return _wallpapers.size(); +bool Session::updateWallpapers(const MTPaccount_WallPapers &data) { + return data.match([&](const MTPDaccount_wallPapers &data) { + setWallpapers(data.vwallpapers.v, data.vhash.v); + return true; + }, [&](const MTPDaccount_wallPapersNotModified &) { + return false; + }); } -const WallPaper &Session::wallpaper(int index) const { - Expects(index >= 0 && index < _wallpapers.size()); +void Session::setWallpapers(const QVector &data, int32 hash) { + _wallpapersHash = hash; - return _wallpapers[index]; -} - -void Session::setWallpapers(const QVector &data) { _wallpapers.clear(); _wallpapers.reserve(data.size() + 1); - auto oldBackground = Images::Create(qsl(":/gui/art/bg_initial.jpg"), "JPG"); - _wallpapers.push_back({ - Window::Theme::kInitialBackground, - oldBackground, - oldBackground - }); + const auto oldBackground = Images::Create( + qsl(":/gui/art/bg_initial.jpg"), + "JPG"); + if (oldBackground) { + _wallpapers.push_back({ + Window::Theme::kInitialBackground, + oldBackground + }); + } for (const auto &paper : data) { paper.match([&](const MTPDwallPaper &paper) { - const auto document = Auth().data().document(paper.vdocument); - if (document->thumb) { + const auto document = this->document(paper.vdocument); + if (document->checkWallPaperProperties()) { _wallpapers.push_back({ - paper.vid.v ? int32(paper.vid.v) : INT_MAX, - document->thumb, + paper.vid.v, document->thumb, + document, }); } }); } } +const std::vector &Session::wallpapers() const { + return _wallpapers; +} + +int32 Session::wallpapersHash() const { + return _wallpapersHash; +} + void Session::clearLocalStorage() { clear(); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index beffba7a6..9082ff311 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_location_manager.h" #include "base/timer.h" +class Image; class HistoryItem; class BoxContent; struct WebPageCollage; @@ -51,9 +52,9 @@ enum class FeedUpdateFlag; struct FeedUpdate; struct WallPaper { - int32 id = 0; + WallPaperId id = WallPaperId(); ImagePtr thumb; - ImagePtr full; + DocumentData *document = nullptr; }; class Session final { @@ -530,9 +531,9 @@ public: return _groups; } - int wallpapersCount() const; - const WallPaper &wallpaper(int index) const; - void setWallpapers(const QVector &data); + bool updateWallpapers(const MTPaccount_WallPapers &data); + const std::vector &wallpapers() const; + int32 wallpapersHash() const; void clearLocalStorage(); @@ -639,7 +640,6 @@ private: void unmuteByFinished(); void unmuteByFinishedDelayed(TimeMs delay); void updateNotifySettingsLocal(not_null peer); - void sendNotifySettingsUpdates(); template void enumerateItemViews( @@ -653,6 +653,8 @@ private: void step_typings(TimeMs ms, bool timer); + void setWallpapers(const QVector &data, int32 hash); + not_null _session; Storage::DatabasePointer _cache; @@ -797,6 +799,7 @@ private: rpl::event_stream _sendActionAnimationUpdate; std::vector _wallpapers; + int32 _wallpapersHash = 0; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index e325d8ff3..826dbc00e 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -270,6 +270,7 @@ using DocumentId = uint64; using WebPageId = uint64; using GameId = uint64; using PollId = uint64; +using WallPaperId = uint64; constexpr auto CancelledWebPageId = WebPageId(0xFFFFFFFFFFFFFFFFULL); using PreparedPhotoThumbs = QMap; @@ -309,6 +310,7 @@ enum DocumentType { AnimatedDocument = 4, VoiceDocument = 5, RoundVideoDocument = 6, + WallPaperDocument = 7, }; using MediaKey = QPair; diff --git a/Telegram/SourceFiles/data/data_web_page.cpp b/Telegram/SourceFiles/data/data_web_page.cpp index 4c8af1521..4a783f9a8 100644 --- a/Telegram/SourceFiles/data/data_web_page.cpp +++ b/Telegram/SourceFiles/data/data_web_page.cpp @@ -133,6 +133,7 @@ WebPageType ParseWebPageType(const MTPDwebPage &page) { if (type == qstr("photo")) return WebPageType::Photo; if (type == qstr("video")) return WebPageType::Video; if (type == qstr("profile")) return WebPageType::Profile; + if (type == qstr("telegram_wallpaper")) return WebPageType::WallPaper; return page.has_cached_page() ? WebPageType::ArticleWithIV : WebPageType::Article; @@ -217,6 +218,10 @@ bool WebPageData::applyChanges( pendingTill = newPendingTill; ++version; + if (type == WebPageType::WallPaper) { + document->checkWallPaperProperties(); + } + replaceDocumentGoodThumbnail(); return true; diff --git a/Telegram/SourceFiles/data/data_web_page.h b/Telegram/SourceFiles/data/data_web_page.h index 931128ca8..30fb70348 100644 --- a/Telegram/SourceFiles/data/data_web_page.h +++ b/Telegram/SourceFiles/data/data_web_page.h @@ -14,6 +14,7 @@ enum class WebPageType { Photo, Video, Profile, + WallPaper, Article, ArticleWithIV, }; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 27a059aff..b93f43b9d 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/toast/toast.h" #include "ui/widgets/dropdown_menu.h" #include "ui/image/image.h" +#include "ui/image/image_source.h" #include "ui/focus_persister.h" #include "ui/resize_area.h" #include "ui/text_options.h" @@ -1414,8 +1415,16 @@ void MainWidget::updateScrollColors() { void MainWidget::setChatBackground(const Data::WallPaper &background) { _background = std::make_unique(background); - _background->full->loadEvenCancelled(Data::FileOrigin()); + if (_background->document) { + _background->document->save(Data::FileOrigin(), QString()); + } else if (_background->thumb) { + _background->thumb->loadEvenCancelled(Data::FileOrigin()); + } checkChatBackground(); + + const auto tile = (background.id == Window::Theme::kInitialBackground); + using Update = Window::Theme::BackgroundUpdate; + Window::Theme::Background()->notify(Update(Update::Type::Start, tile)); } bool MainWidget::chatBackgroundLoading() { @@ -1424,27 +1433,65 @@ bool MainWidget::chatBackgroundLoading() { float64 MainWidget::chatBackgroundProgress() const { if (_background) { - return _background->full->progress(); + if (_background->document) { + return _background->document->progress(); + } else if (_background->thumb) { + return _background->thumb->progress(); + } } return 1.; } void MainWidget::checkChatBackground() { - if (_background) { - if (_background->full->loaded()) { - if (_background->full->isNull()) { - Window::Theme::Background()->setImage(Window::Theme::kDefaultBackground); - } else if (false - || _background->id == Window::Theme::kInitialBackground - || _background->id == Window::Theme::kDefaultBackground) { - Window::Theme::Background()->setImage(_background->id); - } else { - Window::Theme::Background()->setImage(_background->id, _background->full->pix(Data::FileOrigin()).toImage()); - } - _background = nullptr; - crl::on_main(this, [=] { update(); }); - } + using namespace Window::Theme; + + if (!_background) { + return; } + const auto document = _background->document; + if (document && !document->loaded()) { + return; + } else if (!document && !_background->thumb->loaded()) { + return; + } + + auto image = [&] { + if (!document) { + const auto &thumb = _background->thumb; + return thumb + ? thumb->pixNoCache(Data::FileOrigin()).toImage() + : QImage(); + } + auto bytes = document->data(); + auto format = QByteArray(); + const auto path = document->filepath(); + if (bytes.isEmpty()) { + QFile f(document->filepath()); + if (f.size() <= App::kImageSizeLimit + && f.open(QIODevice::ReadOnly)) { + bytes = f.readAll(); + } + } + return bytes.isEmpty() + ? QImage() + : App::readImage(bytes, &format, false, nullptr); + }(); + + if (image.isNull()) { + Background()->setImage(kDefaultBackground); + } else if (false + || _background->id == kInitialBackground + || _background->id == kDefaultBackground) { + Background()->setImage(_background->id); + } else { + Background()->setImage( + _background->id, + std::move(image)); + } + const auto tile = (_background->id == kInitialBackground); + Background()->setTile(tile); + _background = nullptr; + crl::on_main(this, [=] { update(); }); } ImagePtr MainWidget::newBackgroundThumb() { @@ -1483,14 +1530,14 @@ void MainWidget::setInnerFocus() { void MainWidget::scheduleViewIncrement(HistoryItem *item) { PeerData *peer = item->history()->peer; - ViewsIncrement::iterator i = _viewsIncremented.find(peer); + auto i = _viewsIncremented.find(peer); if (i != _viewsIncremented.cend()) { if (i.value().contains(item->id)) return; } else { i = _viewsIncremented.insert(peer, ViewsIncrementMap()); } i.value().insert(item->id, true); - ViewsIncrement::iterator j = _viewsToIncrement.find(peer); + auto j = _viewsToIncrement.find(peer); if (j == _viewsToIncrement.cend()) { j = _viewsToIncrement.insert(peer, ViewsIncrementMap()); _viewsIncrementTimer.start(SendViewsTimeout); @@ -1499,7 +1546,7 @@ void MainWidget::scheduleViewIncrement(HistoryItem *item) { } void MainWidget::onViewsIncrement() { - for (ViewsIncrement::iterator i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) { + for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) { if (_viewsIncrementRequests.contains(i.key())) { ++i; continue; @@ -1519,7 +1566,7 @@ void MainWidget::onViewsIncrement() { void MainWidget::viewsIncrementDone(QVector ids, const MTPVector &result, mtpRequestId req) { auto &v = result.v; if (ids.size() == v.size()) { - for (ViewsIncrementRequests::iterator i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) { + for (auto i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) { if (i.value() == req) { PeerData *peer = i.key(); ChannelId channel = peerToChannel(peer->id); @@ -1541,7 +1588,7 @@ void MainWidget::viewsIncrementDone(QVector ids, const MTPVector bool MainWidget::viewsIncrementFail(const RPCError &error, mtpRequestId req) { if (MTP::isDefaultHandledError(error)) return false; - for (ViewsIncrementRequests::iterator i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) { + for (auto i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) { if (i.value() == req) { _viewsIncrementRequests.erase(i); break; @@ -2274,7 +2321,9 @@ void MainWidget::animationCallback() { } void MainWidget::paintEvent(QPaintEvent *e) { - if (_background) checkChatBackground(); + if (_background) { + checkChatBackground(); + } Painter p(this); auto progress = _a_show.current(getms(), 1.); @@ -3059,25 +3108,19 @@ void MainWidget::ptsWaiterStartTimerFor(ChannelData *channel, int32 ms) { } void MainWidget::failDifferenceStartTimerFor(ChannelData *channel) { - int32 ms = 0; - ChannelFailDifferenceTimeout::iterator i; - if (channel) { - i = _channelFailDifferenceTimeout.find(channel); - if (i == _channelFailDifferenceTimeout.cend()) { - i = _channelFailDifferenceTimeout.insert(channel, 1); + auto &timeout = [&]() -> int32& { + if (!channel) { + return _failDifferenceTimeout; } - ms = i.value() * 1000; - } else { - ms = _failDifferenceTimeout * 1000; - } - if (getDifferenceTimeChanged(channel, ms, _channelGetDifferenceTimeAfterFail, _getDifferenceTimeAfterFail)) { + const auto i = _channelFailDifferenceTimeout.find(channel); + return (i == _channelFailDifferenceTimeout.end()) + ? _channelFailDifferenceTimeout.insert(channel, 1).value() + : i.value(); + }(); + if (getDifferenceTimeChanged(channel, timeout * 1000, _channelGetDifferenceTimeAfterFail, _getDifferenceTimeAfterFail)) { onGetDifferenceTimeAfterFail(); } - if (channel) { - if (i.value() < 64) i.value() *= 2; - } else { - if (_failDifferenceTimeout < 64) _failDifferenceTimeout *= 2; - } + if (timeout < 64) timeout *= 2; } bool MainWidget::ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 6abab911e..a25604631 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -523,8 +523,7 @@ private: bool _isIdle = false; int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails - typedef QMap ChannelFailDifferenceTimeout; - ChannelFailDifferenceTimeout _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails + QMap _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails SingleTimer _failDifferenceTimer; TimeMs _lastUpdateTime = 0; @@ -538,13 +537,10 @@ private: PhotoData *_deletingPhoto = nullptr; - typedef QMap ViewsIncrementMap; - typedef QMap ViewsIncrement; - ViewsIncrement _viewsIncremented, _viewsToIncrement; - typedef QMap ViewsIncrementRequests; - ViewsIncrementRequests _viewsIncrementRequests; - typedef QMap ViewsIncrementByRequest; - ViewsIncrementByRequest _viewsIncrementByRequest; + using ViewsIncrementMap = QMap; + QMap _viewsIncremented, _viewsToIncrement; + QMap _viewsIncrementRequests; + QMap _viewsIncrementByRequest; SingleTimer _viewsIncrementTimer; std::unique_ptr _background; diff --git a/Telegram/SourceFiles/storage/file_download.h b/Telegram/SourceFiles/storage/file_download.h index 2c1a41023..d2ff66594 100644 --- a/Telegram/SourceFiles/storage/file_download.h +++ b/Telegram/SourceFiles/storage/file_download.h @@ -19,7 +19,9 @@ struct Key; constexpr auto kMaxFileInMemory = 10 * 1024 * 1024; // 10 MB max file could be hold in memory constexpr auto kMaxVoiceInMemory = 2 * 1024 * 1024; // 2 MB audio is hold in memory and auto loaded constexpr auto kMaxStickerInMemory = 2 * 1024 * 1024; // 2 MB stickers hold in memory, auto loaded and displayed inline +constexpr auto kMaxWallPaperInMemory = kMaxFileInMemory; constexpr auto kMaxAnimationInMemory = kMaxFileInMemory; // 10 MB gif and mp4 animations held in memory while playing +constexpr auto kMaxWallPaperDimension = 4096; // 4096x4096 is max area. class Downloader final { public: diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 55cf0b712..ea03abdc4 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -3956,7 +3956,7 @@ void readSavedGifs() { } } -void writeBackground(int32 id, const QImage &img) { +void writeBackground(WallPaperId id, const QImage &img) { if (!_working() || !_backgroundCanWrite) { return; } @@ -3982,10 +3982,13 @@ void writeBackground(int32 id, const QImage &img) { _writeMap(WriteMapWhen::Fast); } quint32 size = sizeof(qint32) - + sizeof(quint32) - + (bmp.isEmpty() ? 0 : (sizeof(quint32) + bmp.size())); + + sizeof(quint64) + + Serialize::bytearraySize(bmp); EncryptedDescriptor data(size); - data.stream << qint32(id) << bmp; + data.stream + << qint32(Window::Theme::internal::kLegacyBackgroundId) + << quint64(id) + << bmp; FileWriteDescriptor file(backgroundKey); file.writeEncrypted(data); @@ -4007,8 +4010,15 @@ bool readBackground() { } QByteArray bmpData; - qint32 id; - bg.stream >> id >> bmpData; + qint32 legacyId; + quint64 id; + bg.stream >> legacyId; + if (legacyId == Window::Theme::internal::kLegacyBackgroundId) { + bg.stream >> id; + } else { + id = Window::Theme::internal::FromLegacyBackgroundId(legacyId); + } + bg.stream >> bmpData; auto oldEmptyImage = (bg.stream.status() != QDataStream::Ok); if (oldEmptyImage || id == Window::Theme::kInitialBackground diff --git a/Telegram/SourceFiles/storage/localstorage.h b/Telegram/SourceFiles/storage/localstorage.h index ef56b217b..6f8f74686 100644 --- a/Telegram/SourceFiles/storage/localstorage.h +++ b/Telegram/SourceFiles/storage/localstorage.h @@ -136,7 +136,7 @@ void writeSavedGifs(); void readSavedGifs(); int32 countSavedGifsHash(); -void writeBackground(int32 id, const QImage &img); +void writeBackground(WallPaperId id, const QImage &img); bool readBackground(); void writeTheme(const Window::Theme::Saved &saved); diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 047e94d29..50fbe1489 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -389,7 +389,7 @@ void ChatBackground::start() { } } -void ChatBackground::setImage(int32 id, QImage &&image) { +void ChatBackground::setImage(WallPaperId id, QImage &&image) { auto needResetAdjustable = (id == kDefaultBackground) && (_id != kDefaultBackground) && !nightMode() @@ -528,7 +528,7 @@ void ChatBackground::adjustPaletteUsingBackground(const QImage &img) { } } -int32 ChatBackground::id() const { +WallPaperId ChatBackground::id() const { return _id; } diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index 7169cb2bb..87dcd1e76 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -11,17 +11,22 @@ namespace Window { namespace Theme { namespace internal { -constexpr int32 kUninitializedBackground = -999; -constexpr int32 kTestingThemeBackground = -666; -constexpr int32 kTestingDefaultBackground = -665; -constexpr int32 kTestingEditorBackground = -664; +constexpr auto FromLegacyBackgroundId(int32 legacyId) -> WallPaperId { + return uint64(0xFFFFFFFF00000000ULL) | uint64(uint32(legacyId)); +} + +constexpr auto kUninitializedBackground = FromLegacyBackgroundId(-999); +constexpr auto kTestingThemeBackground = FromLegacyBackgroundId(-666); +constexpr auto kTestingDefaultBackground = FromLegacyBackgroundId(-665); +constexpr auto kTestingEditorBackground = FromLegacyBackgroundId(-664); +constexpr auto kLegacyBackgroundId = int32(-111); } // namespace internal -constexpr int32 kThemeBackground = -2; -constexpr int32 kCustomBackground = -1; -constexpr int32 kInitialBackground = 0; -constexpr int32 kDefaultBackground = 105; +constexpr auto kThemeBackground = internal::FromLegacyBackgroundId(-2); +constexpr auto kCustomBackground = internal::FromLegacyBackgroundId(-1); +constexpr auto kInitialBackground = internal::FromLegacyBackgroundId(0); +constexpr auto kDefaultBackground = internal::FromLegacyBackgroundId(105); struct Cached { QByteArray colors; @@ -98,7 +103,7 @@ public: // This method is setting the default (themed) image if none was set yet. void start(); - void setImage(int32 id, QImage &&image = QImage()); + void setImage(WallPaperId id, QImage &&image = QImage()); void setTile(bool tile); void setTileDayValue(bool tile); void setTileNightValue(bool tile); @@ -111,7 +116,7 @@ public: void setTestingDefaultTheme(); void revert(); - int32 id() const; + WallPaperId id() const; const QPixmap &pixmap() const { return _pixmap; } @@ -152,7 +157,7 @@ private: friend void KeepApplied(); friend bool IsNonDefaultBackground(); - int32 _id = internal::kUninitializedBackground; + WallPaperId _id = internal::kUninitializedBackground; QPixmap _pixmap; QPixmap _pixmapForTiled; bool _nightMode = false; @@ -163,7 +168,7 @@ private: QImage _themeImage; bool _themeTile = false; - int32 _idForRevert = internal::kUninitializedBackground; + WallPaperId _idForRevert = internal::kUninitializedBackground; QImage _imageForRevert; bool _tileForRevert = false;