From 6170144fe92dde9f9a3ec9a149f4e7b1a0d18403 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 23 Dec 2015 19:48:44 +0300 Subject: [PATCH] inline gifs playback / stopping done --- Telegram/SourceFiles/app.cpp | 1 - Telegram/SourceFiles/config.h | 4 +- Telegram/SourceFiles/facades.cpp | 25 +++++++++-- Telegram/SourceFiles/gui/animation.cpp | 3 ++ Telegram/SourceFiles/gui/animation.h | 3 ++ Telegram/SourceFiles/history.cpp | 42 +++++++++++-------- Telegram/SourceFiles/history.h | 6 +-- Telegram/SourceFiles/historywidget.cpp | 11 +++++ Telegram/SourceFiles/historywidget.h | 2 + Telegram/SourceFiles/localstorage.cpp | 4 ++ Telegram/SourceFiles/mainwidget.cpp | 7 ++++ Telegram/SourceFiles/mainwidget.h | 2 + Telegram/SourceFiles/mediaview.cpp | 6 ++- .../SourceFiles/mtproto/mtpFileLoader.cpp | 26 ++++++++---- Telegram/SourceFiles/mtproto/mtpFileLoader.h | 4 +- Telegram/SourceFiles/structs.cpp | 32 +++++++++++--- Telegram/SourceFiles/structs.h | 7 ++++ 17 files changed, 143 insertions(+), 42 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 55e492d818..49e8cab332 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -2407,7 +2407,6 @@ namespace App { } void regGifItem(ClipReader *reader, HistoryItem *item) { - stopGifItems(); ::gifItems.insert(reader, item); } diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 3d91019c8c..a832dedcc6 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -116,10 +116,10 @@ enum { AudioVoiceMsgInMemory = 2 * 1024 * 1024, // 2 Mb audio is hold in memory and auto loaded AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over - StickerInMemory = 2 * 1024 * 1024, // 1 Mb stickers hold in memory, auto loaded and displayed inline + StickerInMemory = 2 * 1024 * 1024, // 2 Mb stickers hold in memory, auto loaded and displayed inline StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker - AnimationInMemory = 2 * 1024 * 1024, // 2 Mb gif and mp4 animations held in memory while playing + AnimationInMemory = 10 * 1024 * 1024, // 10 Mb gif and mp4 animations held in memory while playing MediaViewImageSizeLimit = 100 * 1024 * 1024, // show up to 100mb jpg/png/gif docs in app MaxZoomLevel = 7, // x8 diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 651cc4043f..07c50614c9 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -147,9 +147,28 @@ namespace Notify { if (it != items.cend()) { HistoryItem *item = it.value(); - item->initDimensions(); // can delete reader and items entry it - Notify::historyItemResized(item, true); - Notify::historyItemLayoutChanged(item); + bool stopped = false; + if (reader->paused()) { + if (MainWidget *m = App::main()) { + if (!m->isItemVisible(item)) { // stop animation if it is not visible + if (HistoryMedia *media = item->getMedia()) { + media->stopInline(item); + if (DocumentData *document = media->getDocument()) { // forget data from memory + if (!document->data.isEmpty()) { + document->data.clear(); + document->prepareAutoLoader(); + } + } + stopped = true; + } + } + } + } + if (!stopped) { + item->initDimensions(); // can delete reader and items entry it + Notify::historyItemResized(item); + Notify::historyItemLayoutChanged(item); + } } if (Window *w = App::wnd()) w->notify_clipReinit(reader); } diff --git a/Telegram/SourceFiles/gui/animation.cpp b/Telegram/SourceFiles/gui/animation.cpp index d1d3f859d9..3ba869d937 100644 --- a/Telegram/SourceFiles/gui/animation.cpp +++ b/Telegram/SourceFiles/gui/animation.cpp @@ -783,6 +783,7 @@ public: stop(); setBadPointer(_location); setBadPointer(_implementation); + _data.clear(); } private: @@ -870,6 +871,8 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess if (it.key()->_lastDisplayMs.get() + WaitBeforeGifPause >= qMax(reader->_previousMs, ms)) { it.key()->_paused.set(false); reader->_paused = false; + } else { + result = ClipProcessReinit; } } } diff --git a/Telegram/SourceFiles/gui/animation.h b/Telegram/SourceFiles/gui/animation.h index 355d575802..ded2f39d4b 100644 --- a/Telegram/SourceFiles/gui/animation.h +++ b/Telegram/SourceFiles/gui/animation.h @@ -474,6 +474,9 @@ public: bool currentDisplayed() const { return _currentDisplayed.get(); } + bool paused() const { + return _paused.get(); + } int32 width() const; int32 height() const; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 579d9ae973..b078b2130f 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -3772,13 +3772,12 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, b if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); - - if (!_data->loader && _data->status == FileReady && !already && !hasdata && _data->size < AudioVoiceMsgInMemory) { + bool loaded = _data->loaded(); + if (!loaded && _data->status == FileReady && _data->loader && !_data->loader->loading() && !_data->loader->paused()) { _data->save(QString()); } - if (_data->loader) { + if (_data->loader && (_data->loader->loading() || _data->loader->paused())) { ensureAnimation(parent); if (!_animation->radial.animating()) { _animation->radial.start(_data->progress()); @@ -4394,10 +4393,18 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo bool bubble = parent->hasBubble(); bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + bool loaded = _data->loaded(_gif ? false : true); + if (!loaded && _data->status == FileReady && _data->loader && !_data->loader->loading() && !_data->loader->paused()) { + _data->save(QString()); + } + if (loaded && !_gif) { + const_cast(this)->playInline(const_cast(parent)); + } + bool animating = (_gif && _gif->started()); if (!animating) { - if (_data->loader) { + if (_data->loader && !_data->loader->tryingLocal()) { ensureAnimation(parent); if (!_animation->radial.animating()) { _animation->radial.start(_data->progress()); @@ -4429,7 +4436,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); } - if (!animating || radial) { + if (radial || (!animating && !_gif && (!_data->loader || !_data->loader->tryingLocal() || _data->size > AnimationInMemory))) { QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); p.setPen(Qt::NoPen); if (selected) { @@ -4453,7 +4460,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo } style::sprite icon; - if (!_data->already().isEmpty() && !radial) { + if (_data->loaded() && !radial) { icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); } else if (_data->loader || radial) { icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); @@ -4497,9 +4504,8 @@ void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, } if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { if (_gif && _gif->started()) { - lnk = _savel; } else { - lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _savel; + lnk = _data->loaded() ? _savel : (_data->loader ? _cancell : _savel); } if (parent->getMedia() == this) { @@ -4514,11 +4520,11 @@ void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, } const QString HistoryGif::inDialogsText() const { - return _data->name.isEmpty() ? lang(lng_in_dlg_file) : _data->name; + return qsl("GIF"); } const QString HistoryGif::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_file) + (_data->name.isEmpty() ? QString() : (qsl(" : ") + _data->name)) + qsl(" ]"); + return qsl("[ GIF ]"); } void HistoryGif::setStatusSize(int32 newSize) const { @@ -4534,7 +4540,7 @@ void HistoryGif::updateStatusText(const HistoryItem *parent) const { statusSize = _data->uploadOffset; } else if (_data->loader) { statusSize = _data->loader->currentOffset(); - } else if (!_data->already().isEmpty()) { + } else if (_data->loaded()) { statusSize = FileStatusSizeLoaded; } else { statusSize = FileStatusSizeReady; @@ -4629,7 +4635,10 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); + bool loaded = _data->loaded(); + if (!loaded && _data->status == FileReady && _data->loader && !_data->loader->loading() && !_data->loader->paused()) { + _data->save(QString()); + } int32 usew = _maxw, usex = 0; const HistoryReply *reply = toHistoryReply(parent); @@ -4642,11 +4651,8 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, } if (rtl()) usex = _width - usex - usew; - if (!already && !hasdata && !_data->loader && _data->status == FileReady) { - _data->save(QString()); - } - if (_data->sticker()->img->isNull() && (already || hasdata)) { - if (already) { + if (_data->sticker()->img->isNull() && loaded) { + if (_data->data.isEmpty()) { _data->sticker()->img = ImagePtr(_data->already()); } else { _data->sticker()->img = ImagePtr(_data->data); diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 1ae4d6bdd4..b2351845d7 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -1467,7 +1467,7 @@ protected: return !_data->loader; } bool dataLoaded() const { - return !_data->already().isEmpty() || !_data->data.isEmpty(); + return _data->loaded(); } private: @@ -1542,7 +1542,7 @@ protected: return !_data->loader; } bool dataLoaded() const { - return !_data->already().isEmpty() || !_data->data.isEmpty(); + return _data->loaded(); } private: @@ -1628,7 +1628,7 @@ protected: return !_data->loader; } bool dataLoaded() const { - return !_data->already().isEmpty() && !_data->data.isEmpty(); + return _data->loaded(); } private: diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 5e46f2b3af..cbf8b4cdcf 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -5576,6 +5576,17 @@ void HistoryWidget::peerMessagesUpdated() { if (_list) peerMessagesUpdated(_peer->id); } +bool HistoryWidget::isItemVisible(HistoryItem *item) { + if (isHidden() || _a_show.animating() || !_list) { + return false; + } + int32 top = _list->itemTop(item), st = _scroll.scrollTop(); + if (top < 0 || top + item->height() <= st || top >= st + _scroll.height()) { + return false; + } + return true; +} + void HistoryWidget::ui_redrawHistoryItem(const HistoryItem *item) { if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) { _list->redrawItem(item); diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index bfe92fe5a1..8d1eada03b 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -554,6 +554,8 @@ public: resizeEvent(0); } + bool isItemVisible(HistoryItem *item); + void ui_redrawHistoryItem(const HistoryItem *item); void notify_historyItemLayoutChanged(const HistoryItem *item); diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index ad7b2cc257..418f1cfb11 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -2357,6 +2357,10 @@ namespace Local { } virtual void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, quint32 &type, QByteArray &data) = 0; virtual void clearInMap() = 0; + virtual ~AbstractCachedLoadTask() { + delete _result; + setBadPointer(_result); + } protected: FileKey _key; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index ee8ff73189..f3e9f455d2 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -723,6 +723,13 @@ QPixmap MainWidget::grabInner() { } } +bool MainWidget::isItemVisible(HistoryItem *item) { + if (isHidden() || _a_show.animating()) { + return false; + } + return history.isItemVisible(item); +} + QPixmap MainWidget::grabTopBar() { if (!_topBar.isHidden()) { return myGrab(&_topBar); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 64fc769012..88aecd2573 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -405,6 +405,8 @@ public: QPixmap grabTopBar(); QPixmap grabInner(); + bool isItemVisible(HistoryItem *item); + void ui_showStickerPreview(DocumentData *sticker); void ui_hideStickerPreview(); void ui_redrawHistoryItem(const HistoryItem *item); diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 9a43c33129..61bc899838 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -1000,7 +1000,11 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty int32 maxw = st::mvDocSize.width() - st::mvDocIconSize - st::mvDocPadding * 3; - _docName = (!_doc || _doc->name.isEmpty()) ? lang(_doc ? (_doc->type == StickerDocument ? lng_in_dlg_sticker : lng_mediaview_doc_image) : lng_message_empty) : _doc->name; + if (_doc) { + _docName = (_doc->type == StickerDocument) ? lang(lng_in_dlg_sticker) : (_doc->type == AnimatedDocument ? qsl("GIF") : (_doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name)); + } else { + _docName = lang(lng_message_empty); + } _docNameWidth = st::mvDocNameFont->width(_docName); if (_docNameWidth > maxw) { _docName = st::mvDocNameFont->elided(_docName, maxw, Qt::ElideMiddle); diff --git a/Telegram/SourceFiles/mtproto/mtpFileLoader.cpp b/Telegram/SourceFiles/mtproto/mtpFileLoader.cpp index 536d54bdef..81b81daf52 100644 --- a/Telegram/SourceFiles/mtproto/mtpFileLoader.cpp +++ b/Telegram/SourceFiles/mtproto/mtpFileLoader.cpp @@ -48,7 +48,7 @@ namespace { } mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size) : prev(0), next(0), -priority(0), inQueue(false), complete(false), +priority(0), _paused(false), inQueue(false), complete(false), _localStatus(LocalNotTried), skippedBytes(0), nextRequestOffset(0), lastComplete(false), dc(dc), _locationType(UnknownFileLocation), volume(volume), local(local), secret(secret), id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown), _localTaskId(0) { @@ -60,7 +60,7 @@ id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown), } mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, bool todata) : prev(0), next(0), -priority(0), inQueue(false), complete(false), +priority(0), _paused(false), inQueue(false), complete(false), _localStatus(LocalNotTried), skippedBytes(0), nextRequestOffset(0), lastComplete(false), dc(dc), _locationType(type), volume(0), local(0), secret(0), id(id), access(access), file(to), fname(to), fileIsOpen(false), duplicateInData(todata), size(size), type(mtpc_storage_fileUnknown), _localTaskId(0) { @@ -114,7 +114,7 @@ int32 mtpFileLoader::fullSize() const { } void mtpFileLoader::setFileName(const QString &fileName) { - if (duplicateInData && fname.isEmpty()) { + if (duplicateInData && fname.isEmpty() && !fileName.isEmpty()) { file.setFileName(fname = fileName); } } @@ -318,6 +318,7 @@ void mtpFileLoader::removeFromQueue() { void mtpFileLoader::pause() { removeFromQueue(); + _paused = true; } bool mtpFileLoader::tryLoadLocal() { @@ -330,10 +331,6 @@ bool mtpFileLoader::tryLoadLocal() { if (_locationType == UnknownFileLocation) { _localTaskId = Local::startImageLoad(storageKey(dc, volume, local), this); - if (_localTaskId) { - _localStatus = LocalLoading; - return true; - } } else { if (duplicateInData) { MediaKey mkey = mediaKey(_locationType, dc, id); @@ -346,6 +343,10 @@ bool mtpFileLoader::tryLoadLocal() { } if (data.isEmpty()) { + if (_localTaskId) { + _localStatus = LocalLoading; + return true; + } _localStatus = LocalNotFound; return false; } @@ -410,7 +411,14 @@ void mtpFileLoader::localLoaded(const StorageImageSaved &result, const QByteArra loadNext(); } +bool mtpFileLoader::tryingLocal() const { + return (_localStatus == LocalLoading); +} + void mtpFileLoader::start(bool loadFirst, bool prior) { + if (_paused) { + _paused = false; + } if (complete || tryLoadLocal()) return; if (!fname.isEmpty() && !duplicateInData && !fileIsOpen) { @@ -545,6 +553,10 @@ bool mtpFileLoader::loading() const { return inQueue; } +bool mtpFileLoader::paused() const { + return _paused; +} + void mtpFileLoader::started(bool loadFirst, bool prior) { if ((queue->queries >= MaxFileQueries && (!loadFirst || !prior)) || complete) return; loadPart(); diff --git a/Telegram/SourceFiles/mtproto/mtpFileLoader.h b/Telegram/SourceFiles/mtproto/mtpFileLoader.h index 4cbed0a84e..aee364c545 100644 --- a/Telegram/SourceFiles/mtproto/mtpFileLoader.h +++ b/Telegram/SourceFiles/mtproto/mtpFileLoader.h @@ -140,6 +140,8 @@ public: void start(bool loadFirst = false, bool prior = true); void cancel(); bool loading() const; + bool paused() const; + bool tryingLocal() const; uint64 objId() const; @@ -158,7 +160,7 @@ signals: private: mtpFileLoaderQueue *queue; - bool inQueue, complete; + bool _paused, inQueue, complete; LocalLoadStatus _localStatus; bool tryLoadLocal(); diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 3d5dad92d6..7709719ecc 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -844,11 +844,18 @@ bool StickerData::setInstalled() const { AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) : id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0) { _location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id)); + if (!loaded() && size < AudioVoiceMsgInMemory) { + loader = new mtpFileLoader(dc, id, access, AudioFileLocation, QString(), size, true); + } } void AudioData::save(const QString &toFile) { - cancel(true); - loader = new mtpFileLoader(dc, id, access, AudioFileLocation, toFile, size, (size < AudioVoiceMsgInMemory)); + if (loader && loader->fileName().isEmpty()) { + loader->setFileName(toFile); + } else { + cancel(true); + loader = new mtpFileLoader(dc, id, access, AudioFileLocation, toFile, size, (size < AudioVoiceMsgInMemory)); + } loader->connect(loader, SIGNAL(progress(mtpFileLoader*)), App::main(), SLOT(audioLoadProgress(mtpFileLoader*))); loader->connect(loader, SIGNAL(failed(mtpFileLoader*, bool)), App::main(), SLOT(audioLoadFailed(mtpFileLoader*, bool))); loader->start(); @@ -1025,8 +1032,8 @@ DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 dat , loader(0) , _additional(0) , _isImage(false) { - setattributes(attributes); _location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id)); + setattributes(attributes); } void DocumentData::setattributes(const QVector &attributes) { @@ -1071,19 +1078,32 @@ void DocumentData::setattributes(const QVector &attributes case mtpc_documentAttributeFilename: name = qs(attributes[i].c_documentAttributeFilename().vfile_name); break; } } + prepareAutoLoader(); +} + +void DocumentData::prepareAutoLoader() { if (type == StickerDocument) { if (dimensions.width() <= 0 || dimensions.height() <= 0 || dimensions.width() > StickerMaxSize || dimensions.height() > StickerMaxSize || size > StickerInMemory) { type = FileDocument; delete _additional; _additional = 0; + } else if (!loader && !loaded(true)) { + loader = new mtpFileLoader(dc, id, access, DocumentFileLocation, QString(), size, true); + } + } else if (isAnimation()) { + if (size <= AnimationInMemory && !loader && !loaded(true)) { + loader = new mtpFileLoader(dc, id, access, DocumentFileLocation, QString(), size, true); } } } void DocumentData::save(const QString &toFile) { - cancel(true); - bool isSticker = (type == StickerDocument) && (dimensions.width() > 0) && (dimensions.height() > 0) && (size < StickerInMemory); - loader = new mtpFileLoader(dc, id, access, DocumentFileLocation, toFile, size, isSticker); + if (loader && loader->fileName().isEmpty()) { + loader->setFileName(toFile); + } else { + cancel(true); + loader = new mtpFileLoader(dc, id, access, DocumentFileLocation, toFile, size, (type == StickerDocument)); + } loader->connect(loader, SIGNAL(progress(mtpFileLoader*)), App::main(), SLOT(documentLoadProgress(mtpFileLoader*))); loader->connect(loader, SIGNAL(failed(mtpFileLoader*, bool)), App::main(), SLOT(documentLoadFailed(mtpFileLoader*, bool))); loader->start(); diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 0af6f20c3a..ac19e4a299 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -942,6 +942,9 @@ struct AudioData { _location = loc; } } + bool loaded(bool check = false) { + return !data.isEmpty() || !already(check).isEmpty(); + } float64 progress() const { return loader ? loader->currentProgress() : ((status == FileDownloadFailed || (_location.name().isEmpty() && data.isEmpty())) ? 0 : 1); @@ -1135,6 +1138,10 @@ struct DocumentData { _location = loc; } } + bool loaded(bool check = false) { + return !data.isEmpty() || !already(check).isEmpty(); + } + void prepareAutoLoader(); StickerData *sticker() { return (type == StickerDocument) ? static_cast(_additional) : 0; }