mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-25 04:38:23 +00:00
Fix crash in DocumentData destructor.
Keep AuthSession pointer in DocumentData for loader destruction.
This commit is contained in:
parent
63c1212ef1
commit
a858ab5d0b
@ -268,14 +268,14 @@ AuthSession &Auth() {
|
||||
AuthSession::AuthSession(UserId userId)
|
||||
: _userId(userId)
|
||||
, _autoLockTimer([this] { checkAutoLock(); })
|
||||
, _data(std::make_unique<Data::Session>(this))
|
||||
, _api(std::make_unique<ApiWrap>(this))
|
||||
, _calls(std::make_unique<Calls::Instance>())
|
||||
, _downloader(std::make_unique<Storage::Downloader>())
|
||||
, _uploader(std::make_unique<Storage::Uploader>())
|
||||
, _storage(std::make_unique<Storage::Facade>())
|
||||
, _notifications(std::make_unique<Window::Notifications::System>(this))
|
||||
, _changelogs(Core::Changelogs::Create(this)) {
|
||||
, _changelogs(Core::Changelogs::Create(this))
|
||||
, _data(std::make_unique<Data::Session>(this)) {
|
||||
Expects(_userId != 0);
|
||||
|
||||
_saveDataTimer.setCallback([this] {
|
||||
|
@ -252,7 +252,6 @@ private:
|
||||
TimeMs _shouldLockAt = 0;
|
||||
base::Timer _autoLockTimer;
|
||||
|
||||
const std::unique_ptr<Data::Session> _data;
|
||||
const std::unique_ptr<ApiWrap> _api;
|
||||
const std::unique_ptr<Calls::Instance> _calls;
|
||||
const std::unique_ptr<Storage::Downloader> _downloader;
|
||||
@ -261,6 +260,9 @@ private:
|
||||
const std::unique_ptr<Window::Notifications::System> _notifications;
|
||||
const std::unique_ptr<Core::Changelogs> _changelogs;
|
||||
|
||||
// _data depends on _downloader / _uploader, including destructor.
|
||||
const std::unique_ptr<Data::Session> _data;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
@ -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<MTPDocumentAttribute> &attributes)
|
||||
DocumentData::DocumentData(DocumentId id, not_null<AuthSession*> 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<MTPDocumentAttribute>());
|
||||
}
|
||||
|
||||
DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QVector<MTPDocumentAttribute> &attributes) {
|
||||
return new DocumentData(id, dc, accessHash, version, QString(), attributes);
|
||||
}
|
||||
|
||||
DocumentData *DocumentData::create(DocumentId id, const QString &url, const QVector<MTPDocumentAttribute> &attributes) {
|
||||
return new DocumentData(id, 0, 0, 0, url, attributes);
|
||||
not_null<AuthSession*> DocumentData::session() const {
|
||||
return _session;
|
||||
}
|
||||
|
||||
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &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<FileLoader>(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<FileLoader>(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<StickerData*>(_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<SongData*>(_additional.get())
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const SongData *DocumentData::song() const {
|
||||
return const_cast<DocumentData*>(this)->song();
|
||||
}
|
||||
|
||||
VoiceData *DocumentData::voice() {
|
||||
return isVoiceMessage()
|
||||
? static_cast<VoiceData*>(_additional.get())
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const VoiceData *DocumentData::voice() const {
|
||||
return const_cast<DocumentData*>(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);
|
||||
}
|
||||
|
@ -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<uint32*>(&a)) << 32)
|
||||
| uint64(*reinterpret_cast<uint32*>(&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<MTPDocumentAttribute> &attributes);
|
||||
static DocumentData *create(
|
||||
DocumentId id,
|
||||
const QString &url,
|
||||
const QVector<MTPDocumentAttribute> &attributes);
|
||||
DocumentData(DocumentId id, not_null<AuthSession*> session);
|
||||
|
||||
not_null<AuthSession*> session() const;
|
||||
|
||||
void setattributes(
|
||||
const QVector<MTPDocumentAttribute> &attributes);
|
||||
@ -130,44 +121,14 @@ public:
|
||||
void forget();
|
||||
ImagePtr makeReplyPreview();
|
||||
|
||||
StickerData *sticker() {
|
||||
return (type == StickerDocument)
|
||||
? static_cast<StickerData*>(_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<SongData*>(_additional.get())
|
||||
: nullptr;
|
||||
}
|
||||
const SongData *song() const {
|
||||
return const_cast<DocumentData*>(this)->song();
|
||||
}
|
||||
VoiceData *voice() {
|
||||
return isVoiceMessage()
|
||||
? static_cast<VoiceData*>(_additional.get())
|
||||
: nullptr;
|
||||
}
|
||||
const VoiceData *voice() const {
|
||||
return const_cast<DocumentData*>(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<Data::UploadState> 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<MTPDocumentAttribute> &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<AuthSession*> _session;
|
||||
|
||||
FileLocation _location;
|
||||
QByteArray _data;
|
||||
std::unique_ptr<DocumentAdditionalData> _additional;
|
||||
@ -290,9 +210,6 @@ private:
|
||||
FullMsgId _actionOnLoadMsgId;
|
||||
mutable FileLoader *_loader = nullptr;
|
||||
|
||||
void destroyLoaderDelayed(
|
||||
mtpFileLoader *newValue = nullptr) const;
|
||||
|
||||
};
|
||||
|
||||
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit);
|
||||
|
@ -699,7 +699,9 @@ void Session::photoApplyFields(
|
||||
not_null<DocumentData*> 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<DocumentData>(id, _session)).first;
|
||||
}
|
||||
return i->second.get();
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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), [=] {
|
||||
|
@ -204,7 +204,7 @@ base::unique_qptr<Ui::PopupMenu> 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);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user