diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp index 450aed20aa..12807e32da 100644 --- a/Telegram/SourceFiles/auth_session.cpp +++ b/Telegram/SourceFiles/auth_session.cpp @@ -268,14 +268,14 @@ AuthSession &Auth() { AuthSession::AuthSession(UserId userId) : _userId(userId) , _autoLockTimer([this] { checkAutoLock(); }) -, _data(std::make_unique(this)) , _api(std::make_unique(this)) , _calls(std::make_unique()) , _downloader(std::make_unique()) , _uploader(std::make_unique()) , _storage(std::make_unique()) , _notifications(std::make_unique(this)) -, _changelogs(Core::Changelogs::Create(this)) { +, _changelogs(Core::Changelogs::Create(this)) +, _data(std::make_unique(this)) { Expects(_userId != 0); _saveDataTimer.setCallback([this] { diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h index ea67eb5856..69ad94c881 100644 --- a/Telegram/SourceFiles/auth_session.h +++ b/Telegram/SourceFiles/auth_session.h @@ -252,7 +252,6 @@ private: TimeMs _shouldLockAt = 0; base::Timer _autoLockTimer; - const std::unique_ptr _data; const std::unique_ptr _api; const std::unique_ptr _calls; const std::unique_ptr _downloader; @@ -261,6 +260,9 @@ private: const std::unique_ptr _notifications; const std::unique_ptr _changelogs; + // _data depends on _downloader / _uploader, including destructor. + const std::unique_ptr _data; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 3afdd21e2d..70c8b2011e 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -152,28 +152,6 @@ QString saveFileName(const QString &title, const QString &filter, const QString return name; } -bool StickerData::setInstalled() const { - switch (set.type()) { - case mtpc_inputStickerSetID: { - auto it = Auth().data().stickerSets().constFind( - set.c_inputStickerSetID().vid.v); - return (it != Auth().data().stickerSets().cend()) - && !(it->flags & MTPDstickerSet::Flag::f_archived) - && (it->flags & MTPDstickerSet::Flag::f_installed_date); - } break; - case mtpc_inputStickerSetShortName: { - auto name = qs(set.c_inputStickerSetShortName().vshort_name).toLower(); - for (auto it = Auth().data().stickerSets().cbegin(), e = Auth().data().stickerSets().cend(); it != e; ++it) { - if (it->shortName.toLower() == name) { - return !(it->flags & MTPDstickerSet::Flag::f_archived) - && (it->flags & MTPDstickerSet::Flag::f_installed_date); - } - } - } break; - } - return false; -} - QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = false, const QString already = QString(), const QDir &dir = QDir()) { auto alreadySavingFilename = data->loadingFilePath(); if (!alreadySavingFilename.isEmpty()) { @@ -253,9 +231,7 @@ void DocumentOpenClickHandler::doOpen( auto audio = AudioMsgId(data, msgId); Media::Player::mixer()->play(audio); Media::Player::Updated().notify(audio); - if (App::main()) { - Auth().data().markMediaRead(data); - } + data->session()->data().markMediaRead(data); } } else if (playMusic) { auto state = Media::Player::mixer()->currentState(AudioMsgId::Type::Song); @@ -282,24 +258,24 @@ void DocumentOpenClickHandler::doOpen( File::Launch(filepath); } } - Auth().data().markMediaRead(data); + data->session()->data().markMediaRead(data); } else if (data->isVoiceMessage() || data->isAudioFile() || data->isVideoFile()) { auto filepath = location.name(); if (documentIsValidMediaFile(filepath)) { File::Launch(filepath); } - Auth().data().markMediaRead(data); + data->session()->data().markMediaRead(data); } else if (data->size < App::kImageSizeLimit) { if (!data->data().isEmpty() && playAnimation) { if (action == ActionOnLoadPlayInline && context) { - Auth().data().requestAnimationPlayInline(context); + data->session()->data().requestAnimationPlayInline(context); } else { Messenger::Instance().showDocument(data, context); } } else if (location.accessEnable()) { if (playAnimation || QImageReader(location.name()).canRead()) { if (playAnimation && action == ActionOnLoadPlayInline && context) { - Auth().data().requestAnimationPlayInline(context); + data->session()->data().requestAnimationPlayInline(context); } else { Messenger::Instance().showDocument(data, context); } @@ -378,35 +354,22 @@ void DocumentCancelClickHandler::onClickImpl() const { } VoiceData::~VoiceData() { - if (!waveform.isEmpty() && waveform.at(0) == -1 && waveform.size() > int32(sizeof(TaskId))) { + if (!waveform.isEmpty() + && waveform[0] == -1 + && waveform.size() > int32(sizeof(TaskId))) { TaskId taskId = 0; memcpy(&taskId, waveform.constData() + 1, sizeof(taskId)); Local::cancelTask(taskId); } } -DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector &attributes) +DocumentData::DocumentData(DocumentId id, not_null session) : id(id) -, _dc(dc) -, _access(accessHash) -, _version(version) -, _url(url) { - setattributes(attributes); - if (_dc && _access) { - _location = Local::readFileLocation(mediaKey()); - } +, _session(session) { } -DocumentData *DocumentData::create(DocumentId id) { - return new DocumentData(id, 0, 0, 0, QString(), QVector()); -} - -DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector &attributes) { - return new DocumentData(id, dc, accessHash, version, QString(), attributes); -} - -DocumentData *DocumentData::create(DocumentId id, const QString &url, const QVector &attributes) { - return new DocumentData(id, 0, 0, 0, url, attributes); +not_null DocumentData::session() const { + return _session; } void DocumentData::setattributes(const QVector &attributes) { @@ -577,7 +540,7 @@ void DocumentData::performActionOnLoad() { } } else if (Media::Player::IsStopped(state.state)) { Media::Player::mixer()->play(AudioMsgId(this, _actionOnLoadMsgId)); - Auth().data().markMediaRead(this); + _session->data().markMediaRead(this); } } } else if (playMusic) { @@ -598,7 +561,7 @@ void DocumentData::performActionOnLoad() { } else if (playAnimation) { if (loaded()) { if (_actionOnLoad == ActionOnLoadPlayInline && item) { - Auth().data().requestAnimationPlayInline(item); + _session->data().requestAnimationPlayInline(item); } else { Messenger::Instance().showDocument(this, item); } @@ -613,7 +576,7 @@ void DocumentData::performActionOnLoad() { if (documentIsValidMediaFile(already)) { File::Launch(already); } - Auth().data().markMediaRead(this); + _session->data().markMediaRead(this); } else if (loc.accessEnable()) { if (showImage && QImageReader(loc.name()).canRead()) { Messenger::Instance().showDocument(this, item); @@ -642,7 +605,7 @@ bool DocumentData::loaded(FilePathResolveType type) const { } destroyLoaderDelayed(); } - Auth().data().notifyDocumentLayoutChanged(this); + _session->data().notifyDocumentLayoutChanged(this); } return !data().isEmpty() || !filepath(type).isEmpty(); } @@ -650,7 +613,7 @@ bool DocumentData::loaded(FilePathResolveType type) const { void DocumentData::destroyLoaderDelayed(mtpFileLoader *newValue) const { _loader->stop(); auto loader = std::unique_ptr(std::exchange(_loader, newValue)); - Auth().downloader().delayedDestroyLoader(std::move(loader)); + _session->downloader().delayedDestroyLoader(std::move(loader)); } bool DocumentData::loading() const { @@ -752,7 +715,7 @@ void DocumentData::save( _loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool))); _loader->start(); } - Auth().data().notifyDocumentLayoutChanged(this); + _session->data().notifyDocumentLayoutChanged(this); } void DocumentData::cancel() { @@ -763,9 +726,8 @@ void DocumentData::cancel() { auto loader = std::unique_ptr(std::exchange(_loader, CancelledMtpFileLoader)); loader->cancel(); loader->stop(); - Auth().downloader().delayedDestroyLoader(std::move(loader)); - - Auth().data().notifyDocumentLayoutChanged(this); + _session->downloader().delayedDestroyLoader(std::move(loader)); + _session->data().notifyDocumentLayoutChanged(this); if (auto main = App::main()) { main->documentLoadProgress(this); } @@ -870,6 +832,31 @@ QString DocumentData::filepath(FilePathResolveType type, bool forceSavingAs) con return result; } +bool DocumentData::isStickerSetInstalled() const { + Expects(sticker() != nullptr); + + const auto &set = sticker()->set; + const auto &sets = _session->data().stickerSets(); + switch (set.type()) { + case mtpc_inputStickerSetID: { + auto it = sets.constFind(set.c_inputStickerSetID().vid.v); + return (it != sets.cend()) + && !(it->flags & MTPDstickerSet::Flag::f_archived) + && (it->flags & MTPDstickerSet::Flag::f_installed_date); + } break; + case mtpc_inputStickerSetShortName: { + auto name = qs(set.c_inputStickerSetShortName().vshort_name).toLower(); + for (auto it = sets.cbegin(), e = sets.cend(); it != e; ++it) { + if (it->shortName.toLower() == name) { + return !(it->flags & MTPDstickerSet::Flag::f_archived) + && (it->flags & MTPDstickerSet::Flag::f_installed_date); + } + } + } break; + } + return false; +} + ImagePtr DocumentData::makeReplyPreview() { if (replyPreview->isNull() && !thumb->isNull()) { if (thumb->loaded()) { @@ -889,6 +876,105 @@ ImagePtr DocumentData::makeReplyPreview() { return replyPreview; } +StickerData *DocumentData::sticker() const { + return (type == StickerDocument) + ? static_cast(_additional.get()) + : nullptr; +} + +void DocumentData::checkSticker() { + const auto data = sticker(); + if (!data) return; + + automaticLoad(nullptr); + if (data->img->isNull() && loaded()) { + if (_data.isEmpty()) { + const FileLocation &loc(location(true)); + if (loc.accessEnable()) { + data->img = ImagePtr(loc.name()); + loc.accessDisable(); + } + } else { + data->img = ImagePtr(_data); + } + } +} + +SongData *DocumentData::song() { + return isSong() + ? static_cast(_additional.get()) + : nullptr; +} + +const SongData *DocumentData::song() const { + return const_cast(this)->song(); +} + +VoiceData *DocumentData::voice() { + return isVoiceMessage() + ? static_cast(_additional.get()) + : nullptr; +} + +const VoiceData *DocumentData::voice() const { + return const_cast(this)->voice(); +} + +bool DocumentData::hasRemoteLocation() const { + return (_dc != 0 && _access != 0); +} + +bool DocumentData::isValid() const { + return hasRemoteLocation() || !_url.isEmpty(); +} + +MTPInputDocument DocumentData::mtpInput() const { + if (_access) { + return MTP_inputDocument( + MTP_long(id), + MTP_long(_access)); + } + return MTP_inputDocumentEmpty(); +} + +QString DocumentData::filename() const { + return _filename; +} + +QString DocumentData::mimeString() const { + return _mimeString; +} + +bool DocumentData::hasMimeType(QLatin1String mime) const { + return !_mimeString.compare(mime, Qt::CaseInsensitive); +} + +void DocumentData::setMimeString(const QString &mime) { + _mimeString = mime; +} + +MediaKey DocumentData::mediaKey() const { + return ::mediaKey(locationType(), _dc, id, _version); +} + +QString DocumentData::composeNameString() const { + if (auto songData = song()) { + return ComposeNameString( + _filename, + songData->title, + songData->performer); + } + return ComposeNameString(_filename, QString(), QString()); +} + +LocationType DocumentData::locationType() const { + return isVoiceMessage() + ? AudioFileLocation + : isVideoFile() + ? VideoFileLocation + : DocumentFileLocation; +} + bool DocumentData::isVoiceMessage() const { return (type == VoiceDocument); } diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index 982ff627e7..37f9cff2b1 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_types.h" +class AuthSession; + inline uint64 mediaMix32To64(int32 a, int32 b) { return (uint64(*reinterpret_cast(&a)) << 32) | uint64(*reinterpret_cast(&b)); @@ -42,10 +44,7 @@ struct DocumentAdditionalData { struct StickerData : public DocumentAdditionalData { ImagePtr img; QString alt; - MTPInputStickerSet set = MTP_inputStickerSetEmpty(); - bool setInstalled() const; - StorageImageLocation loc; // doc thumb location }; @@ -72,17 +71,9 @@ class Document; class DocumentData { public: - static DocumentData *create(DocumentId id); - static DocumentData *create( - DocumentId id, - int32 dc, - uint64 accessHash, - int32 version, - const QVector &attributes); - static DocumentData *create( - DocumentId id, - const QString &url, - const QVector &attributes); + DocumentData(DocumentId id, not_null session); + + not_null session() const; void setattributes( const QVector &attributes); @@ -130,44 +121,14 @@ public: void forget(); ImagePtr makeReplyPreview(); - StickerData *sticker() { - return (type == StickerDocument) - ? static_cast(_additional.get()) - : nullptr; - } - void checkSticker() { - StickerData *s = sticker(); - if (!s) return; + StickerData *sticker() const; + void checkSticker(); + bool isStickerSetInstalled() const; + SongData *song(); + const SongData *song() const; + VoiceData *voice(); + const VoiceData *voice() const; - automaticLoad(nullptr); - if (s->img->isNull() && loaded()) { - if (_data.isEmpty()) { - const FileLocation &loc(location(true)); - if (loc.accessEnable()) { - s->img = ImagePtr(loc.name()); - loc.accessDisable(); - } - } else { - s->img = ImagePtr(_data); - } - } - } - SongData *song() { - return isSong() - ? static_cast(_additional.get()) - : nullptr; - } - const SongData *song() const { - return const_cast(this)->song(); - } - VoiceData *voice() { - return isVoiceMessage() - ? static_cast(_additional.get()) - : nullptr; - } - const VoiceData *voice() const { - return const_cast(this)->voice(); - } bool isVoiceMessage() const; bool isVideoMessage() const; bool isSong() const; @@ -187,20 +148,9 @@ public: bool setRemoteVersion(int32 version); // Returns true if version has changed. void setRemoteLocation(int32 dc, uint64 access); void setContentUrl(const QString &url); - bool hasRemoteLocation() const { - return (_dc != 0 && _access != 0); - } - bool isValid() const { - return hasRemoteLocation() || !_url.isEmpty(); - } - MTPInputDocument mtpInput() const { - if (_access) { - return MTP_inputDocument( - MTP_long(id), - MTP_long(_access)); - } - return MTP_inputDocumentEmpty(); - } + bool hasRemoteLocation() const; + bool isValid() const; + MTPInputDocument mtpInput() const; // When we have some client-side generated document // (for example for displaying an external inline bot result) @@ -208,18 +158,18 @@ public: // to (this) received from the server "same" document. void collectLocalData(DocumentData *local); - QString filename() const { - return _filename; - } - QString mimeString() const { - return _mimeString; - } - bool hasMimeType(QLatin1String mime) const { - return !_mimeString.compare(mime, Qt::CaseInsensitive); - } - void setMimeString(const QString &mime) { - _mimeString = mime; - } + QString filename() const; + QString mimeString() const; + bool hasMimeType(QLatin1String mime) const; + void setMimeString(const QString &mime); + + MediaKey mediaKey() const; + + static QString ComposeNameString( + const QString &filename, + const QString &songTitle, + const QString &songPerformer); + QString composeNameString() const; ~DocumentData(); @@ -234,44 +184,12 @@ public: std::unique_ptr uploadingData; - int32 md5[8]; - - MediaKey mediaKey() const { - return ::mediaKey(locationType(), _dc, id, _version); - } - - static QString ComposeNameString( - const QString &filename, - const QString &songTitle, - const QString &songPerformer); - QString composeNameString() const { - if (auto songData = song()) { - return ComposeNameString( - _filename, - songData->title, - songData->performer); - } - return ComposeNameString(_filename, QString(), QString()); - } - private: - DocumentData( - DocumentId id, - int32 dc, - uint64 accessHash, - int32 version, - const QString &url, - const QVector &attributes); - friend class Serialize::Document; - LocationType locationType() const { - return isVoiceMessage() - ? AudioFileLocation - : isVideoFile() - ? VideoFileLocation - : DocumentFileLocation; - } + LocationType locationType() const; + + void destroyLoaderDelayed(mtpFileLoader *newValue = nullptr) const; // Two types of location: from MTProto by dc+access+version or from web by url int32 _dc = 0; @@ -281,6 +199,8 @@ private: QString _filename; QString _mimeString; + not_null _session; + FileLocation _location; QByteArray _data; std::unique_ptr _additional; @@ -290,9 +210,6 @@ private: FullMsgId _actionOnLoadMsgId; mutable FileLoader *_loader = nullptr; - void destroyLoaderDelayed( - mtpFileLoader *newValue = nullptr) const; - }; VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 731cc3216b..334f35949e 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -699,7 +699,9 @@ void Session::photoApplyFields( not_null Session::document(DocumentId id) { auto i = _documents.find(id); if (i == _documents.cend()) { - i = _documents.emplace(id, DocumentData::create(id)).first; + i = _documents.emplace( + id, + std::make_unique(id, _session)).first; } return i->second.get(); } diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 00bf5b09e9..260daa3619 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -1004,7 +1004,7 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { if (media->type() == MediaTypeSticker) { if (const auto document = media->getDocument()) { if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) { - _menu->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] { + _menu->addAction(lang(document->isStickerSetInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] { showStickerPackInfo(document); }); } diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index c6f93ae44e..99938c4cf3 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1517,7 +1517,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { if (media->type() == MediaTypeSticker) { if (auto document = media->getDocument()) { if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) { - _menu->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] { + _menu->addAction(lang(document->isStickerSetInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] { showStickerPackInfo(document); }); _menu->addAction(lang(Stickers::IsFaved(document) ? lng_faved_stickers_remove : lng_faved_stickers_add), [=] { diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 81ffda7fbf..86c01df3a6 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -204,7 +204,7 @@ base::unique_qptr FillContextMenu( if (media->type() == MediaTypeSticker) { if (auto document = media->getDocument()) { if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) { - result->addAction(lang(document->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] { + result->addAction(lang(document->isStickerSetInstalled() ? lng_context_pack_info : lng_context_pack_add), [=] { ShowStickerPackInfo(document); }); }