mirror of https://github.com/procxx/kepka.git
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)
|
AuthSession::AuthSession(UserId userId)
|
||||||
: _userId(userId)
|
: _userId(userId)
|
||||||
, _autoLockTimer([this] { checkAutoLock(); })
|
, _autoLockTimer([this] { checkAutoLock(); })
|
||||||
, _data(std::make_unique<Data::Session>(this))
|
|
||||||
, _api(std::make_unique<ApiWrap>(this))
|
, _api(std::make_unique<ApiWrap>(this))
|
||||||
, _calls(std::make_unique<Calls::Instance>())
|
, _calls(std::make_unique<Calls::Instance>())
|
||||||
, _downloader(std::make_unique<Storage::Downloader>())
|
, _downloader(std::make_unique<Storage::Downloader>())
|
||||||
, _uploader(std::make_unique<Storage::Uploader>())
|
, _uploader(std::make_unique<Storage::Uploader>())
|
||||||
, _storage(std::make_unique<Storage::Facade>())
|
, _storage(std::make_unique<Storage::Facade>())
|
||||||
, _notifications(std::make_unique<Window::Notifications::System>(this))
|
, _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);
|
Expects(_userId != 0);
|
||||||
|
|
||||||
_saveDataTimer.setCallback([this] {
|
_saveDataTimer.setCallback([this] {
|
||||||
|
|
|
@ -252,7 +252,6 @@ private:
|
||||||
TimeMs _shouldLockAt = 0;
|
TimeMs _shouldLockAt = 0;
|
||||||
base::Timer _autoLockTimer;
|
base::Timer _autoLockTimer;
|
||||||
|
|
||||||
const std::unique_ptr<Data::Session> _data;
|
|
||||||
const std::unique_ptr<ApiWrap> _api;
|
const std::unique_ptr<ApiWrap> _api;
|
||||||
const std::unique_ptr<Calls::Instance> _calls;
|
const std::unique_ptr<Calls::Instance> _calls;
|
||||||
const std::unique_ptr<Storage::Downloader> _downloader;
|
const std::unique_ptr<Storage::Downloader> _downloader;
|
||||||
|
@ -261,6 +260,9 @@ private:
|
||||||
const std::unique_ptr<Window::Notifications::System> _notifications;
|
const std::unique_ptr<Window::Notifications::System> _notifications;
|
||||||
const std::unique_ptr<Core::Changelogs> _changelogs;
|
const std::unique_ptr<Core::Changelogs> _changelogs;
|
||||||
|
|
||||||
|
// _data depends on _downloader / _uploader, including destructor.
|
||||||
|
const std::unique_ptr<Data::Session> _data;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -152,28 +152,6 @@ QString saveFileName(const QString &title, const QString &filter, const QString
|
||||||
return name;
|
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()) {
|
QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = false, const QString already = QString(), const QDir &dir = QDir()) {
|
||||||
auto alreadySavingFilename = data->loadingFilePath();
|
auto alreadySavingFilename = data->loadingFilePath();
|
||||||
if (!alreadySavingFilename.isEmpty()) {
|
if (!alreadySavingFilename.isEmpty()) {
|
||||||
|
@ -253,9 +231,7 @@ void DocumentOpenClickHandler::doOpen(
|
||||||
auto audio = AudioMsgId(data, msgId);
|
auto audio = AudioMsgId(data, msgId);
|
||||||
Media::Player::mixer()->play(audio);
|
Media::Player::mixer()->play(audio);
|
||||||
Media::Player::Updated().notify(audio);
|
Media::Player::Updated().notify(audio);
|
||||||
if (App::main()) {
|
data->session()->data().markMediaRead(data);
|
||||||
Auth().data().markMediaRead(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (playMusic) {
|
} else if (playMusic) {
|
||||||
auto state = Media::Player::mixer()->currentState(AudioMsgId::Type::Song);
|
auto state = Media::Player::mixer()->currentState(AudioMsgId::Type::Song);
|
||||||
|
@ -282,24 +258,24 @@ void DocumentOpenClickHandler::doOpen(
|
||||||
File::Launch(filepath);
|
File::Launch(filepath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Auth().data().markMediaRead(data);
|
data->session()->data().markMediaRead(data);
|
||||||
} else if (data->isVoiceMessage() || data->isAudioFile() || data->isVideoFile()) {
|
} else if (data->isVoiceMessage() || data->isAudioFile() || data->isVideoFile()) {
|
||||||
auto filepath = location.name();
|
auto filepath = location.name();
|
||||||
if (documentIsValidMediaFile(filepath)) {
|
if (documentIsValidMediaFile(filepath)) {
|
||||||
File::Launch(filepath);
|
File::Launch(filepath);
|
||||||
}
|
}
|
||||||
Auth().data().markMediaRead(data);
|
data->session()->data().markMediaRead(data);
|
||||||
} else if (data->size < App::kImageSizeLimit) {
|
} else if (data->size < App::kImageSizeLimit) {
|
||||||
if (!data->data().isEmpty() && playAnimation) {
|
if (!data->data().isEmpty() && playAnimation) {
|
||||||
if (action == ActionOnLoadPlayInline && context) {
|
if (action == ActionOnLoadPlayInline && context) {
|
||||||
Auth().data().requestAnimationPlayInline(context);
|
data->session()->data().requestAnimationPlayInline(context);
|
||||||
} else {
|
} else {
|
||||||
Messenger::Instance().showDocument(data, context);
|
Messenger::Instance().showDocument(data, context);
|
||||||
}
|
}
|
||||||
} else if (location.accessEnable()) {
|
} else if (location.accessEnable()) {
|
||||||
if (playAnimation || QImageReader(location.name()).canRead()) {
|
if (playAnimation || QImageReader(location.name()).canRead()) {
|
||||||
if (playAnimation && action == ActionOnLoadPlayInline && context) {
|
if (playAnimation && action == ActionOnLoadPlayInline && context) {
|
||||||
Auth().data().requestAnimationPlayInline(context);
|
data->session()->data().requestAnimationPlayInline(context);
|
||||||
} else {
|
} else {
|
||||||
Messenger::Instance().showDocument(data, context);
|
Messenger::Instance().showDocument(data, context);
|
||||||
}
|
}
|
||||||
|
@ -378,35 +354,22 @@ void DocumentCancelClickHandler::onClickImpl() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceData::~VoiceData() {
|
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;
|
TaskId taskId = 0;
|
||||||
memcpy(&taskId, waveform.constData() + 1, sizeof(taskId));
|
memcpy(&taskId, waveform.constData() + 1, sizeof(taskId));
|
||||||
Local::cancelTask(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)
|
: id(id)
|
||||||
, _dc(dc)
|
, _session(session) {
|
||||||
, _access(accessHash)
|
|
||||||
, _version(version)
|
|
||||||
, _url(url) {
|
|
||||||
setattributes(attributes);
|
|
||||||
if (_dc && _access) {
|
|
||||||
_location = Local::readFileLocation(mediaKey());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentData *DocumentData::create(DocumentId id) {
|
not_null<AuthSession*> DocumentData::session() const {
|
||||||
return new DocumentData(id, 0, 0, 0, QString(), QVector<MTPDocumentAttribute>());
|
return _session;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
|
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
|
||||||
|
@ -577,7 +540,7 @@ void DocumentData::performActionOnLoad() {
|
||||||
}
|
}
|
||||||
} else if (Media::Player::IsStopped(state.state)) {
|
} else if (Media::Player::IsStopped(state.state)) {
|
||||||
Media::Player::mixer()->play(AudioMsgId(this, _actionOnLoadMsgId));
|
Media::Player::mixer()->play(AudioMsgId(this, _actionOnLoadMsgId));
|
||||||
Auth().data().markMediaRead(this);
|
_session->data().markMediaRead(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (playMusic) {
|
} else if (playMusic) {
|
||||||
|
@ -598,7 +561,7 @@ void DocumentData::performActionOnLoad() {
|
||||||
} else if (playAnimation) {
|
} else if (playAnimation) {
|
||||||
if (loaded()) {
|
if (loaded()) {
|
||||||
if (_actionOnLoad == ActionOnLoadPlayInline && item) {
|
if (_actionOnLoad == ActionOnLoadPlayInline && item) {
|
||||||
Auth().data().requestAnimationPlayInline(item);
|
_session->data().requestAnimationPlayInline(item);
|
||||||
} else {
|
} else {
|
||||||
Messenger::Instance().showDocument(this, item);
|
Messenger::Instance().showDocument(this, item);
|
||||||
}
|
}
|
||||||
|
@ -613,7 +576,7 @@ void DocumentData::performActionOnLoad() {
|
||||||
if (documentIsValidMediaFile(already)) {
|
if (documentIsValidMediaFile(already)) {
|
||||||
File::Launch(already);
|
File::Launch(already);
|
||||||
}
|
}
|
||||||
Auth().data().markMediaRead(this);
|
_session->data().markMediaRead(this);
|
||||||
} else if (loc.accessEnable()) {
|
} else if (loc.accessEnable()) {
|
||||||
if (showImage && QImageReader(loc.name()).canRead()) {
|
if (showImage && QImageReader(loc.name()).canRead()) {
|
||||||
Messenger::Instance().showDocument(this, item);
|
Messenger::Instance().showDocument(this, item);
|
||||||
|
@ -642,7 +605,7 @@ bool DocumentData::loaded(FilePathResolveType type) const {
|
||||||
}
|
}
|
||||||
destroyLoaderDelayed();
|
destroyLoaderDelayed();
|
||||||
}
|
}
|
||||||
Auth().data().notifyDocumentLayoutChanged(this);
|
_session->data().notifyDocumentLayoutChanged(this);
|
||||||
}
|
}
|
||||||
return !data().isEmpty() || !filepath(type).isEmpty();
|
return !data().isEmpty() || !filepath(type).isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -650,7 +613,7 @@ bool DocumentData::loaded(FilePathResolveType type) const {
|
||||||
void DocumentData::destroyLoaderDelayed(mtpFileLoader *newValue) const {
|
void DocumentData::destroyLoaderDelayed(mtpFileLoader *newValue) const {
|
||||||
_loader->stop();
|
_loader->stop();
|
||||||
auto loader = std::unique_ptr<FileLoader>(std::exchange(_loader, newValue));
|
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 {
|
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->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
|
||||||
_loader->start();
|
_loader->start();
|
||||||
}
|
}
|
||||||
Auth().data().notifyDocumentLayoutChanged(this);
|
_session->data().notifyDocumentLayoutChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentData::cancel() {
|
void DocumentData::cancel() {
|
||||||
|
@ -763,9 +726,8 @@ void DocumentData::cancel() {
|
||||||
auto loader = std::unique_ptr<FileLoader>(std::exchange(_loader, CancelledMtpFileLoader));
|
auto loader = std::unique_ptr<FileLoader>(std::exchange(_loader, CancelledMtpFileLoader));
|
||||||
loader->cancel();
|
loader->cancel();
|
||||||
loader->stop();
|
loader->stop();
|
||||||
Auth().downloader().delayedDestroyLoader(std::move(loader));
|
_session->downloader().delayedDestroyLoader(std::move(loader));
|
||||||
|
_session->data().notifyDocumentLayoutChanged(this);
|
||||||
Auth().data().notifyDocumentLayoutChanged(this);
|
|
||||||
if (auto main = App::main()) {
|
if (auto main = App::main()) {
|
||||||
main->documentLoadProgress(this);
|
main->documentLoadProgress(this);
|
||||||
}
|
}
|
||||||
|
@ -870,6 +832,31 @@ QString DocumentData::filepath(FilePathResolveType type, bool forceSavingAs) con
|
||||||
return result;
|
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() {
|
ImagePtr DocumentData::makeReplyPreview() {
|
||||||
if (replyPreview->isNull() && !thumb->isNull()) {
|
if (replyPreview->isNull() && !thumb->isNull()) {
|
||||||
if (thumb->loaded()) {
|
if (thumb->loaded()) {
|
||||||
|
@ -889,6 +876,105 @@ ImagePtr DocumentData::makeReplyPreview() {
|
||||||
return replyPreview;
|
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 {
|
bool DocumentData::isVoiceMessage() const {
|
||||||
return (type == VoiceDocument);
|
return (type == VoiceDocument);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "data/data_types.h"
|
#include "data/data_types.h"
|
||||||
|
|
||||||
|
class AuthSession;
|
||||||
|
|
||||||
inline uint64 mediaMix32To64(int32 a, int32 b) {
|
inline uint64 mediaMix32To64(int32 a, int32 b) {
|
||||||
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32)
|
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32)
|
||||||
| uint64(*reinterpret_cast<uint32*>(&b));
|
| uint64(*reinterpret_cast<uint32*>(&b));
|
||||||
|
@ -42,10 +44,7 @@ struct DocumentAdditionalData {
|
||||||
struct StickerData : public DocumentAdditionalData {
|
struct StickerData : public DocumentAdditionalData {
|
||||||
ImagePtr img;
|
ImagePtr img;
|
||||||
QString alt;
|
QString alt;
|
||||||
|
|
||||||
MTPInputStickerSet set = MTP_inputStickerSetEmpty();
|
MTPInputStickerSet set = MTP_inputStickerSetEmpty();
|
||||||
bool setInstalled() const;
|
|
||||||
|
|
||||||
StorageImageLocation loc; // doc thumb location
|
StorageImageLocation loc; // doc thumb location
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -72,17 +71,9 @@ class Document;
|
||||||
|
|
||||||
class DocumentData {
|
class DocumentData {
|
||||||
public:
|
public:
|
||||||
static DocumentData *create(DocumentId id);
|
DocumentData(DocumentId id, not_null<AuthSession*> session);
|
||||||
static DocumentData *create(
|
|
||||||
DocumentId id,
|
not_null<AuthSession*> session() const;
|
||||||
int32 dc,
|
|
||||||
uint64 accessHash,
|
|
||||||
int32 version,
|
|
||||||
const QVector<MTPDocumentAttribute> &attributes);
|
|
||||||
static DocumentData *create(
|
|
||||||
DocumentId id,
|
|
||||||
const QString &url,
|
|
||||||
const QVector<MTPDocumentAttribute> &attributes);
|
|
||||||
|
|
||||||
void setattributes(
|
void setattributes(
|
||||||
const QVector<MTPDocumentAttribute> &attributes);
|
const QVector<MTPDocumentAttribute> &attributes);
|
||||||
|
@ -130,44 +121,14 @@ public:
|
||||||
void forget();
|
void forget();
|
||||||
ImagePtr makeReplyPreview();
|
ImagePtr makeReplyPreview();
|
||||||
|
|
||||||
StickerData *sticker() {
|
StickerData *sticker() const;
|
||||||
return (type == StickerDocument)
|
void checkSticker();
|
||||||
? static_cast<StickerData*>(_additional.get())
|
bool isStickerSetInstalled() const;
|
||||||
: nullptr;
|
SongData *song();
|
||||||
}
|
const SongData *song() const;
|
||||||
void checkSticker() {
|
VoiceData *voice();
|
||||||
StickerData *s = sticker();
|
const VoiceData *voice() const;
|
||||||
if (!s) return;
|
|
||||||
|
|
||||||
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 isVoiceMessage() const;
|
||||||
bool isVideoMessage() const;
|
bool isVideoMessage() const;
|
||||||
bool isSong() const;
|
bool isSong() const;
|
||||||
|
@ -187,20 +148,9 @@ public:
|
||||||
bool setRemoteVersion(int32 version); // Returns true if version has changed.
|
bool setRemoteVersion(int32 version); // Returns true if version has changed.
|
||||||
void setRemoteLocation(int32 dc, uint64 access);
|
void setRemoteLocation(int32 dc, uint64 access);
|
||||||
void setContentUrl(const QString &url);
|
void setContentUrl(const QString &url);
|
||||||
bool hasRemoteLocation() const {
|
bool hasRemoteLocation() const;
|
||||||
return (_dc != 0 && _access != 0);
|
bool isValid() const;
|
||||||
}
|
MTPInputDocument mtpInput() const;
|
||||||
bool isValid() const {
|
|
||||||
return hasRemoteLocation() || !_url.isEmpty();
|
|
||||||
}
|
|
||||||
MTPInputDocument mtpInput() const {
|
|
||||||
if (_access) {
|
|
||||||
return MTP_inputDocument(
|
|
||||||
MTP_long(id),
|
|
||||||
MTP_long(_access));
|
|
||||||
}
|
|
||||||
return MTP_inputDocumentEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// When we have some client-side generated document
|
// When we have some client-side generated document
|
||||||
// (for example for displaying an external inline bot result)
|
// (for example for displaying an external inline bot result)
|
||||||
|
@ -208,18 +158,18 @@ public:
|
||||||
// to (this) received from the server "same" document.
|
// to (this) received from the server "same" document.
|
||||||
void collectLocalData(DocumentData *local);
|
void collectLocalData(DocumentData *local);
|
||||||
|
|
||||||
QString filename() const {
|
QString filename() const;
|
||||||
return _filename;
|
QString mimeString() const;
|
||||||
}
|
bool hasMimeType(QLatin1String mime) const;
|
||||||
QString mimeString() const {
|
void setMimeString(const QString &mime);
|
||||||
return _mimeString;
|
|
||||||
}
|
MediaKey mediaKey() const;
|
||||||
bool hasMimeType(QLatin1String mime) const {
|
|
||||||
return !_mimeString.compare(mime, Qt::CaseInsensitive);
|
static QString ComposeNameString(
|
||||||
}
|
const QString &filename,
|
||||||
void setMimeString(const QString &mime) {
|
const QString &songTitle,
|
||||||
_mimeString = mime;
|
const QString &songPerformer);
|
||||||
}
|
QString composeNameString() const;
|
||||||
|
|
||||||
~DocumentData();
|
~DocumentData();
|
||||||
|
|
||||||
|
@ -234,44 +184,12 @@ public:
|
||||||
|
|
||||||
std::unique_ptr<Data::UploadState> uploadingData;
|
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:
|
private:
|
||||||
DocumentData(
|
|
||||||
DocumentId id,
|
|
||||||
int32 dc,
|
|
||||||
uint64 accessHash,
|
|
||||||
int32 version,
|
|
||||||
const QString &url,
|
|
||||||
const QVector<MTPDocumentAttribute> &attributes);
|
|
||||||
|
|
||||||
friend class Serialize::Document;
|
friend class Serialize::Document;
|
||||||
|
|
||||||
LocationType locationType() const {
|
LocationType locationType() const;
|
||||||
return isVoiceMessage()
|
|
||||||
? AudioFileLocation
|
void destroyLoaderDelayed(mtpFileLoader *newValue = nullptr) const;
|
||||||
: isVideoFile()
|
|
||||||
? VideoFileLocation
|
|
||||||
: DocumentFileLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Two types of location: from MTProto by dc+access+version or from web by url
|
// Two types of location: from MTProto by dc+access+version or from web by url
|
||||||
int32 _dc = 0;
|
int32 _dc = 0;
|
||||||
|
@ -281,6 +199,8 @@ private:
|
||||||
QString _filename;
|
QString _filename;
|
||||||
QString _mimeString;
|
QString _mimeString;
|
||||||
|
|
||||||
|
not_null<AuthSession*> _session;
|
||||||
|
|
||||||
FileLocation _location;
|
FileLocation _location;
|
||||||
QByteArray _data;
|
QByteArray _data;
|
||||||
std::unique_ptr<DocumentAdditionalData> _additional;
|
std::unique_ptr<DocumentAdditionalData> _additional;
|
||||||
|
@ -290,9 +210,6 @@ private:
|
||||||
FullMsgId _actionOnLoadMsgId;
|
FullMsgId _actionOnLoadMsgId;
|
||||||
mutable FileLoader *_loader = nullptr;
|
mutable FileLoader *_loader = nullptr;
|
||||||
|
|
||||||
void destroyLoaderDelayed(
|
|
||||||
mtpFileLoader *newValue = nullptr) const;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit);
|
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit);
|
||||||
|
|
|
@ -699,7 +699,9 @@ void Session::photoApplyFields(
|
||||||
not_null<DocumentData*> Session::document(DocumentId id) {
|
not_null<DocumentData*> Session::document(DocumentId id) {
|
||||||
auto i = _documents.find(id);
|
auto i = _documents.find(id);
|
||||||
if (i == _documents.cend()) {
|
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();
|
return i->second.get();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1004,7 +1004,7 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (media->type() == MediaTypeSticker) {
|
if (media->type() == MediaTypeSticker) {
|
||||||
if (const auto document = media->getDocument()) {
|
if (const auto document = media->getDocument()) {
|
||||||
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
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);
|
showStickerPackInfo(document);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1517,7 +1517,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
if (media->type() == MediaTypeSticker) {
|
if (media->type() == MediaTypeSticker) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
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);
|
showStickerPackInfo(document);
|
||||||
});
|
});
|
||||||
_menu->addAction(lang(Stickers::IsFaved(document) ? lng_faved_stickers_remove : lng_faved_stickers_add), [=] {
|
_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 (media->type() == MediaTypeSticker) {
|
||||||
if (auto document = media->getDocument()) {
|
if (auto document = media->getDocument()) {
|
||||||
if (document->sticker() && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
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);
|
ShowStickerPackInfo(document);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue