From cd36d367ed25474be893907d502af6f5ce32f3ce Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 8 Jul 2016 16:56:53 +0300
Subject: [PATCH] Version raised to 0.9.58. Version field of documents
 supported.

---
 Telegram/Resources/winrc/Telegram.rc          |   8 +-
 Telegram/Resources/winrc/Updater.rc           |   8 +-
 Telegram/SourceFiles/app.cpp                  |  35 +-
 Telegram/SourceFiles/app.h                    |   2 +-
 Telegram/SourceFiles/boxes/stickersetbox.cpp  |   2 +-
 Telegram/SourceFiles/core/version.h           |   4 +-
 .../inline_bots/inline_bot_result.cpp         |   2 +-
 Telegram/SourceFiles/localimageloader.cpp     |   4 +-
 Telegram/SourceFiles/localstorage.cpp         |   6 +-
 .../SourceFiles/mtproto/file_download.cpp     |  22 +-
 Telegram/SourceFiles/mtproto/file_download.h  |  19 +-
 Telegram/SourceFiles/mtproto/scheme.tl        |  14 +-
 Telegram/SourceFiles/mtproto/scheme_auto.cpp  |  78 +++-
 Telegram/SourceFiles/mtproto/scheme_auto.h    | 337 ++++++++++++++----
 .../serialize/serialize_document.cpp          |  24 +-
 .../serialize/serialize_document.h            |   6 +-
 Telegram/SourceFiles/structs.cpp              |  29 +-
 Telegram/SourceFiles/structs.h                |  10 +-
 Telegram/SourceFiles/ui/images.h              |   9 +-
 Telegram/Telegram.xcodeproj/project.pbxproj   |   4 +-
 Telegram/build/version                        |   6 +-
 21 files changed, 461 insertions(+), 168 deletions(-)

diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc
index a04176115f..3132ab97ac 100644
--- a/Telegram/Resources/winrc/Telegram.rc
+++ b/Telegram/Resources/winrc/Telegram.rc
@@ -34,8 +34,8 @@ IDI_ICON1               ICON                    "..\\art\\icon256.ico"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,9,57,0
- PRODUCTVERSION 0,9,57,0
+ FILEVERSION 0,9,58,0
+ PRODUCTVERSION 0,9,58,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -51,10 +51,10 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "CompanyName", "Telegram Messenger LLP"
-            VALUE "FileVersion", "0.9.57.0"
+            VALUE "FileVersion", "0.9.58.0"
             VALUE "LegalCopyright", "Copyright (C) 2014-2016"
             VALUE "ProductName", "Telegram Desktop"
-            VALUE "ProductVersion", "0.9.57.0"
+            VALUE "ProductVersion", "0.9.58.0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc
index edc6944fb6..69822ab7a5 100644
--- a/Telegram/Resources/winrc/Updater.rc
+++ b/Telegram/Resources/winrc/Updater.rc
@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,9,57,0
- PRODUCTVERSION 0,9,57,0
+ FILEVERSION 0,9,58,0
+ PRODUCTVERSION 0,9,58,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -43,10 +43,10 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Telegram Messenger LLP"
             VALUE "FileDescription", "Telegram Updater"
-            VALUE "FileVersion", "0.9.57.0"
+            VALUE "FileVersion", "0.9.58.0"
             VALUE "LegalCopyright", "Copyright (C) 2014-2016"
             VALUE "ProductName", "Telegram Desktop"
-            VALUE "ProductVersion", "0.9.57.0"
+            VALUE "ProductVersion", "0.9.58.0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index 048dc3bab3..888a7db717 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "lang.h"
 #include "data/data_abstract_structure.h"
 #include "history/history_service_layout.h"
+#include "inline_bots/inline_bot_layout_item.h"
 #include "audio.h"
 #include "application.h"
 #include "fileuploader.h"
@@ -1454,7 +1455,7 @@ namespace {
 		switch (document.type()) {
 		case mtpc_document: {
 			const auto &d(document.c_document());
-			return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation());
+			return App::documentSet(d.vid.v, 0, d.vaccess_hash.v, d.vversion.v, d.vdate.v, d.vattributes.c_vector().v, qs(d.vmime_type), ImagePtr(thumb, "JPG"), d.vdc_id.v, d.vsize.v, StorageImageLocation());
 		} break;
 		case mtpc_documentEmpty: return App::document(document.c_documentEmpty().vid.v);
 		}
@@ -1467,14 +1468,14 @@ namespace {
 			return feedDocument(document.c_document(), convert);
 		} break;
 		case mtpc_documentEmpty: {
-			return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, QVector<MTPDocumentAttribute>(), QString(), ImagePtr(), 0, 0, StorageImageLocation());
+			return App::documentSet(document.c_documentEmpty().vid.v, convert, 0, 0, 0, QVector<MTPDocumentAttribute>(), QString(), ImagePtr(), 0, 0, StorageImageLocation());
 		} break;
 		}
 		return App::document(0);
 	}
 
 	DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert) {
-		return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb));
+		return App::documentSet(document.vid.v, convert, document.vaccess_hash.v, document.vversion.v, document.vdate.v, document.vattributes.c_vector().v, qs(document.vmime_type), App::image(document.vthumb), document.vdc_id.v, document.vsize.v, App::imageLocation(document.vthumb));
 	}
 
 	WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert) {
@@ -1631,11 +1632,13 @@ namespace {
 		return i.value();
 	}
 
-	DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) {
+	DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) {
+		bool versionChanged = false;
 		bool sentSticker = false;
 		if (convert) {
 			MediaKey oldKey = convert->mediaKey();
-			if (convert->id != document) {
+			bool idChanged = (convert->id != document);
+			if (idChanged) {
 				DocumentsData::iterator i = ::documentsData.find(convert->id);
 				if (i != ::documentsData.cend() && i.value() == convert) {
 					::documentsData.erase(i);
@@ -1647,10 +1650,11 @@ namespace {
 			}
 			if (date) {
 				convert->setattributes(attributes);
+				versionChanged = convert->setRemoteVersion(version);
 				convert->setRemoteLocation(dc, access);
 				convert->date = date;
 				convert->mime = mime;
-				if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height())) {
+				if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height() || versionChanged)) {
 					updateImage(convert->thumb, thumb);
 				}
 				convert->size = size;
@@ -1660,7 +1664,7 @@ namespace {
 				}
 
 				MediaKey newKey = convert->mediaKey();
-				if (newKey != oldKey) {
+				if (idChanged) {
 					if (convert->voice()) {
 						Local::copyAudio(oldKey, newKey);
 					} else if (convert->sticker() || convert->isAnimation()) {
@@ -1679,7 +1683,7 @@ namespace {
 			if (convert) {
 				result = convert;
 			} else {
-				result = DocumentData::create(document, dc, access, attributes);
+				result = DocumentData::create(document, dc, access, version, attributes);
 				result->date = date;
 				result->mime = mime;
 				result->thumb = thumb;
@@ -1694,12 +1698,13 @@ namespace {
 			result = i.value();
 			if (result != convert && date) {
 				result->setattributes(attributes);
+				versionChanged = result->setRemoteVersion(version);
 				if (!result->isValid()) {
 					result->setRemoteLocation(dc, access);
 				}
 				result->date = date;
 				result->mime = mime;
-				if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height())) {
+				if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height() || versionChanged)) {
 					result->thumb = thumb;
 				}
 				result->size = size;
@@ -1712,6 +1717,18 @@ namespace {
 		if (sentSticker && App::main()) {
 			App::main()->incrementSticker(result);
 		}
+		if (versionChanged) {
+			if (result->sticker()) {
+				Local::writeStickers();
+			}
+			auto &items = App::documentItems();
+			auto i = items.constFind(result);
+			if (i != items.cend()) {
+				for (auto j = i->cbegin(), e = i->cend(); j != e; ++j) {
+					j.key()->setPendingInitDimensions();
+				}
+			}
+		}
 		return result;
 	}
 
diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h
index 9bdb14fdf8..0c12a7615e 100644
--- a/Telegram/SourceFiles/app.h
+++ b/Telegram/SourceFiles/app.h
@@ -149,7 +149,7 @@ namespace App {
 	PhotoData *photo(const PhotoId &photo);
 	PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
 	DocumentData *document(const DocumentId &document);
-	DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
+	DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
 	WebPageData *webPage(const WebPageId &webPage);
 	WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill);
 	LocationData *location(const LocationCoords &coords);
diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp
index 6d838b0ce5..78837cc1e6 100644
--- a/Telegram/SourceFiles/boxes/stickersetbox.cpp
+++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp
@@ -530,7 +530,7 @@ void StickersInner::paintRow(Painter &p, int32 index) {
 		int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::defaultActiveButton.height) / 2;
 		QRect add(myrtlrect(addx, addy, addw, st::defaultActiveButton.height));
 
-		App::roundRect(p, add, st::defaultActiveButton.textBgOver);
+		App::roundRect(p, add, st::defaultActiveButton.textBgOver, ImageRoundRadius::Small);
 		p.setFont(st::defaultActiveButton.font);
 		p.setPen(st::defaultActiveButton.textFg);
 		p.drawTextLeft(addx - st::defaultActiveButton.width / 2, addy + st::defaultActiveButton.textTop, width(), _addText, _addWidth);
diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h
index 7e443e7811..795b8bef4e 100644
--- a/Telegram/SourceFiles/core/version.h
+++ b/Telegram/SourceFiles/core/version.h
@@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 
 #define BETA_VERSION_MACRO (0ULL)
 
-constexpr int AppVersion = 9057;
-constexpr str_const AppVersionStr = "0.9.57";
+constexpr int AppVersion = 9058;
+constexpr str_const AppVersionStr = "0.9.58";
 constexpr bool AppAlphaVersion = true;
 constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;
diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp
index 29a4909c70..d3afc27b4a 100644
--- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp
+++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp
@@ -352,7 +352,7 @@ void Result::createDocument() {
 		attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes()));
 	}
 
-	MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
+	MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
 
 	_document = App::feedDocument(document);
 	_document->setContentUrl(_content_url);
diff --git a/Telegram/SourceFiles/localimageloader.cpp b/Telegram/SourceFiles/localimageloader.cpp
index f484ccb9bf..3d3e162ce1 100644
--- a/Telegram/SourceFiles/localimageloader.cpp
+++ b/Telegram/SourceFiles/localimageloader.cpp
@@ -413,9 +413,9 @@ void FileLoadTask::process() {
 	if (voice) {
 		attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform)));
 		attributes.resize(1);
-		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
+		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
 	} else {
-		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
+		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
 		if (photo.type() == mtpc_photoEmpty) {
 			_type = PrepareDocument;
 		}
diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp
index aeec358466..4b2e792c26 100644
--- a/Telegram/SourceFiles/localstorage.cpp
+++ b/Telegram/SourceFiles/localstorage.cpp
@@ -3145,7 +3145,7 @@ namespace Local {
 				attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
 			}
 
-			DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
+			DocumentData *doc = App::documentSet(id, 0, access, 0, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
 			if (!doc->sticker()) continue;
 
 			if (value > 0) {
@@ -3247,7 +3247,7 @@ namespace Local {
 			Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName);
 			OrderedSet<DocumentId> read;
 			for (int32 j = 0; j < scnt; ++j) {
-				auto document = Serialize::Document::readStickerFromStream(stickers.stream, info);
+				auto document = Serialize::Document::readStickerFromStream(stickers.version, stickers.stream, info);
 				if (!document || !document->sticker()) continue;
 
 				if (read.contains(document->id)) continue;
@@ -3407,7 +3407,7 @@ namespace Local {
 		saved.reserve(cnt);
 		OrderedSet<DocumentId> read;
 		for (uint32 i = 0; i < cnt; ++i) {
-			DocumentData *document = Serialize::Document::readFromStream(gifs.stream);
+			DocumentData *document = Serialize::Document::readFromStream(gifs.version, gifs.stream);
 			if (!document || !document->isAnimation()) continue;
 
 			if (read.contains(document->id)) continue;
diff --git a/Telegram/SourceFiles/mtproto/file_download.cpp b/Telegram/SourceFiles/mtproto/file_download.cpp
index ab8a25af52..f8a5c0018b 100644
--- a/Telegram/SourceFiles/mtproto/file_download.cpp
+++ b/Telegram/SourceFiles/mtproto/file_download.cpp
@@ -350,13 +350,8 @@ void FileLoader::startLoading(bool loadFirst, bool prior) {
 
 mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
 : FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading)
-, _lastComplete(false)
-, _skippedBytes(0)
-, _nextRequestOffset(0)
 , _dc(location->dc())
-, _location(location)
-, _id(0)
-, _access(0) {
+, _location(location) {
 	LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0));
 	if (i == queues.cend()) {
 		i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries));
@@ -364,15 +359,12 @@ mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, L
 	_queue = &i.value();
 }
 
-mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
+mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
 : FileLoader(to, size, type, toCache, fromCloud, autoLoading)
-, _lastComplete(false)
-, _skippedBytes(0)
-, _nextRequestOffset(0)
 , _dc(dc)
-, _location(0)
 , _id(id)
-, _access(access) {
+, _access(access)
+, _version(version) {
 	LoaderQueues::iterator i = queues.find(MTP::dldDcId(_dc, 0));
 	if (i == queues.cend()) {
 		i = queues.insert(MTP::dldDcId(_dc, 0), FileLoaderQueue(MaxFileQueries));
@@ -421,7 +413,7 @@ bool mtpFileLoader::loadPart() {
 		switch (_locationType) {
 		case VideoFileLocation:
 		case AudioFileLocation:
-		case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access)); break;
+		case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access), MTP_int(_version)); break;
 		default: cancel(true); return false; break;
 		}
 	}
@@ -531,7 +523,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
 
 		if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
 			if (_locationType != UnknownFileLocation) { // audio, video, document
-				MediaKey mkey = mediaKey(_locationType, _dc, _id);
+				MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
 				if (!_fname.isEmpty()) {
 					Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname));
 				}
@@ -593,7 +585,7 @@ bool mtpFileLoader::tryLoadLocal() {
 		_localTaskId = Local::startImageLoad(storageKey(*_location), this);
 	} else {
 		if (_toCache == LoadToCacheAsWell) {
-			MediaKey mkey = mediaKey(_locationType, _dc, _id);
+			MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
 			if (_locationType == DocumentFileLocation) {
 				_localTaskId = Local::startStickerImageLoad(mkey, this);
 			} else if (_locationType == AudioFileLocation) {
diff --git a/Telegram/SourceFiles/mtproto/file_download.h b/Telegram/SourceFiles/mtproto/file_download.h
index f8a05d7ea6..94b65fb2b4 100644
--- a/Telegram/SourceFiles/mtproto/file_download.h
+++ b/Telegram/SourceFiles/mtproto/file_download.h
@@ -28,6 +28,8 @@ namespace MTP {
 
 enum LocationType {
 	UnknownFileLocation  = 0,
+	// 1, 2, etc are used as "version" value in mediaKey() method.
+
 	DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
 	AudioFileLocation    = 0x74dc404d, // mtpc_inputAudioFileLocation
 	VideoFileLocation    = 0x3d0364ec, // mtpc_inputVideoFileLocation
@@ -221,9 +223,8 @@ class mtpFileLoader : public FileLoader, public RPCSender {
 	Q_OBJECT
 
 public:
-
 	mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
-	mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading);
+	mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading);
 
 	virtual int32 currentOffset(bool includeSkipped = false) const;
 
@@ -245,7 +246,6 @@ public:
 	~mtpFileLoader();
 
 protected:
-
 	virtual bool tryLoadLocal();
 	virtual void cancelRequests();
 
@@ -256,15 +256,16 @@ protected:
 	void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req);
 	bool partFailed(const RPCError &error);
 
-	bool _lastComplete;
-	int32 _skippedBytes;
-	int32 _nextRequestOffset;
+	bool _lastComplete = false;
+	int32 _skippedBytes = 0;
+	int32 _nextRequestOffset = 0;
 
 	int32 _dc;
-	const StorageImageLocation *_location;
+	const StorageImageLocation *_location = nullptr;
 
-	uint64 _id; // for other locations
-	uint64 _access;
+	uint64 _id = 0; // for other locations
+	uint64 _access = 0;
+	int32 _version = 0;
 
 };
 
diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl
index aaa8866758..d1179d198a 100644
--- a/Telegram/SourceFiles/mtproto/scheme.tl
+++ b/Telegram/SourceFiles/mtproto/scheme.tl
@@ -168,7 +168,7 @@ inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
 
 inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
 inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
-inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
+inputDocumentFileLocation#430f0724 id:long access_hash:long version:int = InputFileLocation;
 
 inputPhotoCropAuto#ade6b004 = InputPhotoCrop;
 inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop;
@@ -393,6 +393,7 @@ updateInlineBotCallbackQuery#2cbd95af query_id:long user_id:int msg_id:InputBotI
 updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = Update;
 updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update;
 updateReadFeaturedStickers#571d2742 = Update;
+updateRecentStickers#9a422c20 = Update;
 
 updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
 
@@ -455,7 +456,7 @@ inputDocumentEmpty#72f0eaae = InputDocument;
 inputDocument#18798952 id:long access_hash:long = InputDocument;
 
 documentEmpty#36f8c871 id:long = Document;
-document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
+document#87232bc7 id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int version:int attributes:Vector<DocumentAttribute> = Document;
 
 help.support#17c6b5f6 phone_number:string user:User = help.Support;
 
@@ -507,7 +508,6 @@ documentAttributeSticker#3a556302 alt:string stickerset:InputStickerSet = Docume
 documentAttributeVideo#5910cccb duration:int w:int h:int = DocumentAttribute;
 documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute;
 documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
-documentAttributeVersion#99cd09ab version:int = DocumentAttribute;
 
 messages.stickersNotModified#f1749a22 = messages.Stickers;
 messages.stickers#8a8ecd32 hash:string stickers:Vector<Document> = messages.Stickers;
@@ -549,7 +549,7 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
 chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
 
 chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
-chatInvite#93e99b60 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string = ChatInvite;
+chatInvite#2d492881 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:ChatPhoto participants:flags.4?Vector<User> = ChatInvite;
 
 inputStickerSetEmpty#ffb62b95 = InputStickerSet;
 inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
@@ -701,6 +701,9 @@ draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?in
 messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers;
 messages.featuredStickers#ed6392b7 hash:int sets:Vector<StickerSet> unread:Vector<long> = messages.FeaturedStickers;
 
+messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
+messages.recentStickers#5ce20970 hash:int stickers:Vector<Document> = messages.RecentStickers;
+
 ---functions---
 
 invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -837,6 +840,9 @@ messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flag
 messages.getAllDrafts#6a3f8d65 = Updates;
 messages.getFeaturedStickers#2dacca4f hash:int = messages.FeaturedStickers;
 messages.readFeaturedStickers#e21cbb = Bool;
+messages.getRecentStickers#99197c2c hash:int = messages.RecentStickers;
+messages.clearRecentStickers#ab02e5d2 = Bool;
+messages.getUnusedStickers#a978d356 limit:int = Vector<StickerSet>;
 
 updates.getState#edd4882a = updates.State;
 updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.cpp b/Telegram/SourceFiles/mtproto/scheme_auto.cpp
index 9b4b655c16..5669a5323b 100644
--- a/Telegram/SourceFiles/mtproto/scheme_auto.cpp
+++ b/Telegram/SourceFiles/mtproto/scheme_auto.cpp
@@ -828,6 +828,7 @@ void _serialize_inputDocumentFileLocation(MTPStringLogger &to, int32 stage, int3
 	switch (stage) {
 	case 0: to.add("  id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	case 1: to.add("  access_hash: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 2: to.add("  version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -3016,6 +3017,10 @@ void _serialize_updateReadFeaturedStickers(MTPStringLogger &to, int32 stage, int
 	to.add("{ updateReadFeaturedStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 }
 
+void _serialize_updateRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	to.add("{ updateRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+}
+
 void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
@@ -3676,7 +3681,8 @@ void _serialize_document(MTPStringLogger &to, int32 stage, int32 lev, Types &typ
 	case 4: to.add("  size: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	case 5: to.add("  thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	case 6: to.add("  dc_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 7: to.add("  attributes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 7: to.add("  version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 8: to.add("  attributes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -4018,19 +4024,6 @@ void _serialize_documentAttributeFilename(MTPStringLogger &to, int32 stage, int3
 	}
 }
 
-void _serialize_documentAttributeVersion(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
-	if (stage) {
-		to.add(",\n").addSpaces(lev);
-	} else {
-		to.add("{ documentAttributeVersion");
-		to.add("\n").addSpaces(lev);
-	}
-	switch (stage) {
-	case 0: to.add("  version: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
-	}
-}
-
 void _serialize_messages_stickersNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	to.add("{ messages_stickersNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 }
@@ -4356,6 +4349,8 @@ void _serialize_chatInvite(MTPStringLogger &to, int32 stage, int32 lev, Types &t
 	case 3: to.add("  public: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_public) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
 	case 4: to.add("  megagroup: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_megagroup) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
 	case 5: to.add("  title: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 6: to.add("  photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 7: to.add("  participants: "); ++stages.back(); if (flag & MTPDchatInvite::Flag::f_participants) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -5783,6 +5778,24 @@ void _serialize_messages_featuredStickers(MTPStringLogger &to, int32 stage, int3
 	}
 }
 
+void _serialize_messages_recentStickersNotModified(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	to.add("{ messages_recentStickersNotModified }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+}
+
+void _serialize_messages_recentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	if (stage) {
+		to.add(",\n").addSpaces(lev);
+	} else {
+		to.add("{ messages_recentStickers");
+		to.add("\n").addSpaces(lev);
+	}
+	switch (stage) {
+	case 0: to.add("  hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 1: to.add("  stickers: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
+	}
+}
+
 void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
@@ -6405,6 +6418,10 @@ void _serialize_messages_readFeaturedStickers(MTPStringLogger &to, int32 stage,
 	to.add("{ messages_readFeaturedStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 }
 
+void _serialize_messages_clearRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	to.add("{ messages_clearRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+}
+
 void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
@@ -8084,6 +8101,32 @@ void _serialize_messages_getFeaturedStickers(MTPStringLogger &to, int32 stage, i
 	}
 }
 
+void _serialize_messages_getRecentStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	if (stage) {
+		to.add(",\n").addSpaces(lev);
+	} else {
+		to.add("{ messages_getRecentStickers");
+		to.add("\n").addSpaces(lev);
+	}
+	switch (stage) {
+	case 0: to.add("  hash: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
+	}
+}
+
+void _serialize_messages_getUnusedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	if (stage) {
+		to.add(",\n").addSpaces(lev);
+	} else {
+		to.add("{ messages_getUnusedStickers");
+		to.add("\n").addSpaces(lev);
+	}
+	switch (stage) {
+	case 0: to.add("  limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
+	}
+}
+
 void _serialize_updates_getState(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	to.add("{ updates_getState }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 }
@@ -8542,6 +8585,7 @@ namespace {
 		_serializers.insert(mtpc_updateReadChannelOutbox, _serialize_updateReadChannelOutbox);
 		_serializers.insert(mtpc_updateDraftMessage, _serialize_updateDraftMessage);
 		_serializers.insert(mtpc_updateReadFeaturedStickers, _serialize_updateReadFeaturedStickers);
+		_serializers.insert(mtpc_updateRecentStickers, _serialize_updateRecentStickers);
 		_serializers.insert(mtpc_updates_state, _serialize_updates_state);
 		_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
 		_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
@@ -8625,7 +8669,6 @@ namespace {
 		_serializers.insert(mtpc_documentAttributeVideo, _serialize_documentAttributeVideo);
 		_serializers.insert(mtpc_documentAttributeAudio, _serialize_documentAttributeAudio);
 		_serializers.insert(mtpc_documentAttributeFilename, _serialize_documentAttributeFilename);
-		_serializers.insert(mtpc_documentAttributeVersion, _serialize_documentAttributeVersion);
 		_serializers.insert(mtpc_messages_stickersNotModified, _serialize_messages_stickersNotModified);
 		_serializers.insert(mtpc_messages_stickers, _serialize_messages_stickers);
 		_serializers.insert(mtpc_stickerPack, _serialize_stickerPack);
@@ -8758,6 +8801,8 @@ namespace {
 		_serializers.insert(mtpc_draftMessage, _serialize_draftMessage);
 		_serializers.insert(mtpc_messages_featuredStickersNotModified, _serialize_messages_featuredStickersNotModified);
 		_serializers.insert(mtpc_messages_featuredStickers, _serialize_messages_featuredStickers);
+		_serializers.insert(mtpc_messages_recentStickersNotModified, _serialize_messages_recentStickersNotModified);
+		_serializers.insert(mtpc_messages_recentStickers, _serialize_messages_recentStickers);
 
 		_serializers.insert(mtpc_req_pq, _serialize_req_pq);
 		_serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params);
@@ -8805,6 +8850,7 @@ namespace {
 		_serializers.insert(mtpc_messages_setBotCallbackAnswer, _serialize_messages_setBotCallbackAnswer);
 		_serializers.insert(mtpc_messages_saveDraft, _serialize_messages_saveDraft);
 		_serializers.insert(mtpc_messages_readFeaturedStickers, _serialize_messages_readFeaturedStickers);
+		_serializers.insert(mtpc_messages_clearRecentStickers, _serialize_messages_clearRecentStickers);
 		_serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart);
 		_serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart);
 		_serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog);
@@ -8924,6 +8970,8 @@ namespace {
 		_serializers.insert(mtpc_messages_getBotCallbackAnswer, _serialize_messages_getBotCallbackAnswer);
 		_serializers.insert(mtpc_messages_getPeerDialogs, _serialize_messages_getPeerDialogs);
 		_serializers.insert(mtpc_messages_getFeaturedStickers, _serialize_messages_getFeaturedStickers);
+		_serializers.insert(mtpc_messages_getRecentStickers, _serialize_messages_getRecentStickers);
+		_serializers.insert(mtpc_messages_getUnusedStickers, _serialize_messages_getUnusedStickers);
 		_serializers.insert(mtpc_updates_getState, _serialize_updates_getState);
 		_serializers.insert(mtpc_updates_getDifference, _serialize_updates_getDifference);
 		_serializers.insert(mtpc_updates_getChannelDifference, _serialize_updates_getChannelDifference);
diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.h b/Telegram/SourceFiles/mtproto/scheme_auto.h
index 0c0d69db2c..e0e2cb8975 100644
--- a/Telegram/SourceFiles/mtproto/scheme_auto.h
+++ b/Telegram/SourceFiles/mtproto/scheme_auto.h
@@ -112,7 +112,7 @@ enum {
 	mtpc_inputPhoto = 0xfb95c6c4,
 	mtpc_inputFileLocation = 0x14637196,
 	mtpc_inputEncryptedFileLocation = 0xf5235d55,
-	mtpc_inputDocumentFileLocation = 0x4e45abe9,
+	mtpc_inputDocumentFileLocation = 0x430f0724,
 	mtpc_inputPhotoCropAuto = 0xade6b004,
 	mtpc_inputPhotoCrop = 0xd9915325,
 	mtpc_inputAppEvent = 0x770656a8,
@@ -289,6 +289,7 @@ enum {
 	mtpc_updateReadChannelOutbox = 0x25d6c9c7,
 	mtpc_updateDraftMessage = 0xee2bb969,
 	mtpc_updateReadFeaturedStickers = 0x571d2742,
+	mtpc_updateRecentStickers = 0x9a422c20,
 	mtpc_updates_state = 0xa56c2a3e,
 	mtpc_updates_differenceEmpty = 0x5d75a138,
 	mtpc_updates_difference = 0xf49ca0,
@@ -331,7 +332,7 @@ enum {
 	mtpc_inputDocumentEmpty = 0x72f0eaae,
 	mtpc_inputDocument = 0x18798952,
 	mtpc_documentEmpty = 0x36f8c871,
-	mtpc_document = 0xf9a39f4f,
+	mtpc_document = 0x87232bc7,
 	mtpc_help_support = 0x17c6b5f6,
 	mtpc_notifyPeer = 0x9fd40bd8,
 	mtpc_notifyUsers = 0xb4c83b4c,
@@ -372,7 +373,6 @@ enum {
 	mtpc_documentAttributeVideo = 0x5910cccb,
 	mtpc_documentAttributeAudio = 0x9852f9c6,
 	mtpc_documentAttributeFilename = 0x15590068,
-	mtpc_documentAttributeVersion = 0x99cd09ab,
 	mtpc_messages_stickersNotModified = 0xf1749a22,
 	mtpc_messages_stickers = 0x8a8ecd32,
 	mtpc_stickerPack = 0x12b299d4,
@@ -398,7 +398,7 @@ enum {
 	mtpc_chatInviteEmpty = 0x69df3769,
 	mtpc_chatInviteExported = 0xfc2e05bc,
 	mtpc_chatInviteAlready = 0x5a686d7c,
-	mtpc_chatInvite = 0x93e99b60,
+	mtpc_chatInvite = 0x2d492881,
 	mtpc_inputStickerSetEmpty = 0xffb62b95,
 	mtpc_inputStickerSetID = 0x9de7a269,
 	mtpc_inputStickerSetShortName = 0x861cc8a0,
@@ -505,6 +505,8 @@ enum {
 	mtpc_draftMessage = 0xfd8e711f,
 	mtpc_messages_featuredStickersNotModified = 0x4ede3cf,
 	mtpc_messages_featuredStickers = 0xed6392b7,
+	mtpc_messages_recentStickersNotModified = 0xb17f890,
+	mtpc_messages_recentStickers = 0x5ce20970,
 	mtpc_invokeAfterMsg = 0xcb9f372d,
 	mtpc_invokeAfterMsgs = 0x3dc4b4f0,
 	mtpc_initConnection = 0x69796de9,
@@ -634,6 +636,9 @@ enum {
 	mtpc_messages_getAllDrafts = 0x6a3f8d65,
 	mtpc_messages_getFeaturedStickers = 0x2dacca4f,
 	mtpc_messages_readFeaturedStickers = 0xe21cbb,
+	mtpc_messages_getRecentStickers = 0x99197c2c,
+	mtpc_messages_clearRecentStickers = 0xab02e5d2,
+	mtpc_messages_getUnusedStickers = 0xa978d356,
 	mtpc_updates_getState = 0xedd4882a,
 	mtpc_updates_getDifference = 0xa041495,
 	mtpc_updates_getChannelDifference = 0xbb32d7c0,
@@ -1139,7 +1144,6 @@ class MTPDdocumentAttributeSticker;
 class MTPDdocumentAttributeVideo;
 class MTPDdocumentAttributeAudio;
 class MTPDdocumentAttributeFilename;
-class MTPDdocumentAttributeVersion;
 
 class MTPmessages_stickers;
 class MTPDmessages_stickers;
@@ -1363,6 +1367,9 @@ class MTPDdraftMessage;
 class MTPmessages_featuredStickers;
 class MTPDmessages_featuredStickers;
 
+class MTPmessages_recentStickers;
+class MTPDmessages_recentStickers;
+
 
 // Boxed types definitions
 typedef MTPBoxed<MTPresPQ> MTPResPQ;
@@ -1538,6 +1545,7 @@ typedef MTPBoxed<MTPtopPeerCategoryPeers> MTPTopPeerCategoryPeers;
 typedef MTPBoxed<MTPcontacts_topPeers> MTPcontacts_TopPeers;
 typedef MTPBoxed<MTPdraftMessage> MTPDraftMessage;
 typedef MTPBoxed<MTPmessages_featuredStickers> MTPmessages_FeaturedStickers;
+typedef MTPBoxed<MTPmessages_recentStickers> MTPmessages_RecentStickers;
 
 // Type classes definitions
 
@@ -6973,18 +6981,6 @@ public:
 		return *(const MTPDdocumentAttributeFilename*)data;
 	}
 
-	MTPDdocumentAttributeVersion &_documentAttributeVersion() {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_documentAttributeVersion) throw mtpErrorWrongTypeId(_type, mtpc_documentAttributeVersion);
-		split();
-		return *(MTPDdocumentAttributeVersion*)data;
-	}
-	const MTPDdocumentAttributeVersion &c_documentAttributeVersion() const {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_documentAttributeVersion) throw mtpErrorWrongTypeId(_type, mtpc_documentAttributeVersion);
-		return *(const MTPDdocumentAttributeVersion*)data;
-	}
-
 	uint32 innerLength() const;
 	mtpTypeId type() const;
 	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
@@ -6999,7 +6995,6 @@ private:
 	explicit MTPdocumentAttribute(MTPDdocumentAttributeVideo *_data);
 	explicit MTPdocumentAttribute(MTPDdocumentAttributeAudio *_data);
 	explicit MTPdocumentAttribute(MTPDdocumentAttributeFilename *_data);
-	explicit MTPdocumentAttribute(MTPDdocumentAttributeVersion *_data);
 
 	friend class MTP::internal::TypeCreator;
 
@@ -9593,6 +9588,43 @@ private:
 };
 typedef MTPBoxed<MTPmessages_featuredStickers> MTPmessages_FeaturedStickers;
 
+class MTPmessages_recentStickers : private mtpDataOwner {
+public:
+	MTPmessages_recentStickers() : mtpDataOwner(0), _type(0) {
+	}
+	MTPmessages_recentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) {
+		read(from, end, cons);
+	}
+
+	MTPDmessages_recentStickers &_messages_recentStickers() {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_messages_recentStickers) throw mtpErrorWrongTypeId(_type, mtpc_messages_recentStickers);
+		split();
+		return *(MTPDmessages_recentStickers*)data;
+	}
+	const MTPDmessages_recentStickers &c_messages_recentStickers() const {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_messages_recentStickers) throw mtpErrorWrongTypeId(_type, mtpc_messages_recentStickers);
+		return *(const MTPDmessages_recentStickers*)data;
+	}
+
+	uint32 innerLength() const;
+	mtpTypeId type() const;
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
+	void write(mtpBuffer &to) const;
+
+	typedef void ResponseType;
+
+private:
+	explicit MTPmessages_recentStickers(mtpTypeId type);
+	explicit MTPmessages_recentStickers(MTPDmessages_recentStickers *_data);
+
+	friend class MTP::internal::TypeCreator;
+
+	mtpTypeId _type;
+};
+typedef MTPBoxed<MTPmessages_recentStickers> MTPmessages_RecentStickers;
+
 // Type constructors with data
 
 class MTPDresPQ : public mtpDataImpl<MTPDresPQ> {
@@ -10185,11 +10217,12 @@ class MTPDinputDocumentFileLocation : public mtpDataImpl<MTPDinputDocumentFileLo
 public:
 	MTPDinputDocumentFileLocation() {
 	}
-	MTPDinputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash) : vid(_id), vaccess_hash(_access_hash) {
+	MTPDinputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash, MTPint _version) : vid(_id), vaccess_hash(_access_hash), vversion(_version) {
 	}
 
 	MTPlong vid;
 	MTPlong vaccess_hash;
+	MTPint vversion;
 };
 
 class MTPDinputPhotoCrop : public mtpDataImpl<MTPDinputPhotoCrop> {
@@ -12612,7 +12645,7 @@ class MTPDdocument : public mtpDataImpl<MTPDdocument> {
 public:
 	MTPDdocument() {
 	}
-	MTPDdocument(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, const MTPVector<MTPDocumentAttribute> &_attributes) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vmime_type(_mime_type), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vattributes(_attributes) {
+	MTPDdocument(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _version, const MTPVector<MTPDocumentAttribute> &_attributes) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vmime_type(_mime_type), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vversion(_version), vattributes(_attributes) {
 	}
 
 	MTPlong vid;
@@ -12622,6 +12655,7 @@ public:
 	MTPint vsize;
 	MTPPhotoSize vthumb;
 	MTPint vdc_id;
+	MTPint vversion;
 	MTPVector<MTPDocumentAttribute> vattributes;
 };
 
@@ -12833,16 +12867,6 @@ public:
 	MTPstring vfile_name;
 };
 
-class MTPDdocumentAttributeVersion : public mtpDataImpl<MTPDdocumentAttributeVersion> {
-public:
-	MTPDdocumentAttributeVersion() {
-	}
-	MTPDdocumentAttributeVersion(MTPint _version) : vversion(_version) {
-	}
-
-	MTPint vversion;
-};
-
 class MTPDmessages_stickers : public mtpDataImpl<MTPDmessages_stickers> {
 public:
 	MTPDmessages_stickers() {
@@ -13121,8 +13145,9 @@ public:
 		f_broadcast = (1 << 1),
 		f_public = (1 << 2),
 		f_megagroup = (1 << 3),
+		f_participants = (1 << 4),
 
-		MAX_FIELD = (1 << 3),
+		MAX_FIELD = (1 << 4),
 	};
 	Q_DECLARE_FLAGS(Flags, Flag);
 	friend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }
@@ -13131,14 +13156,17 @@ public:
 	bool is_broadcast() const { return vflags.v & Flag::f_broadcast; }
 	bool is_public() const { return vflags.v & Flag::f_public; }
 	bool is_megagroup() const { return vflags.v & Flag::f_megagroup; }
+	bool has_participants() const { return vflags.v & Flag::f_participants; }
 
 	MTPDchatInvite() {
 	}
-	MTPDchatInvite(const MTPflags<MTPDchatInvite::Flags> &_flags, const MTPstring &_title) : vflags(_flags), vtitle(_title) {
+	MTPDchatInvite(const MTPflags<MTPDchatInvite::Flags> &_flags, const MTPstring &_title, const MTPChatPhoto &_photo, const MTPVector<MTPUser> &_participants) : vflags(_flags), vtitle(_title), vphoto(_photo), vparticipants(_participants) {
 	}
 
 	MTPflags<MTPDchatInvite::Flags> vflags;
 	MTPstring vtitle;
+	MTPChatPhoto vphoto;
+	MTPVector<MTPUser> vparticipants;
 };
 
 class MTPDinputStickerSetID : public mtpDataImpl<MTPDinputStickerSetID> {
@@ -14500,6 +14528,17 @@ public:
 	MTPVector<MTPlong> vunread;
 };
 
+class MTPDmessages_recentStickers : public mtpDataImpl<MTPDmessages_recentStickers> {
+public:
+	MTPDmessages_recentStickers() {
+	}
+	MTPDmessages_recentStickers(MTPint _hash, const MTPVector<MTPDocument> &_stickers) : vhash(_hash), vstickers(_stickers) {
+	}
+
+	MTPint vhash;
+	MTPVector<MTPDocument> vstickers;
+};
+
 // RPC methods
 
 class MTPreq_pq { // RPC method 'req_pq'
@@ -20561,6 +20600,115 @@ public:
 	}
 };
 
+class MTPmessages_getRecentStickers { // RPC method 'messages.getRecentStickers'
+public:
+	MTPint vhash;
+
+	MTPmessages_getRecentStickers() {
+	}
+	MTPmessages_getRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getRecentStickers) {
+		read(from, end, cons);
+	}
+	MTPmessages_getRecentStickers(MTPint _hash) : vhash(_hash) {
+	}
+
+	uint32 innerLength() const {
+		return vhash.innerLength();
+	}
+	mtpTypeId type() const {
+		return mtpc_messages_getRecentStickers;
+	}
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getRecentStickers) {
+		vhash.read(from, end);
+	}
+	void write(mtpBuffer &to) const {
+		vhash.write(to);
+	}
+
+	typedef MTPmessages_RecentStickers ResponseType;
+};
+class MTPmessages_GetRecentStickers : public MTPBoxed<MTPmessages_getRecentStickers> {
+public:
+	MTPmessages_GetRecentStickers() {
+	}
+	MTPmessages_GetRecentStickers(const MTPmessages_getRecentStickers &v) : MTPBoxed<MTPmessages_getRecentStickers>(v) {
+	}
+	MTPmessages_GetRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_getRecentStickers>(from, end, cons) {
+	}
+	MTPmessages_GetRecentStickers(MTPint _hash) : MTPBoxed<MTPmessages_getRecentStickers>(MTPmessages_getRecentStickers(_hash)) {
+	}
+};
+
+class MTPmessages_clearRecentStickers { // RPC method 'messages.clearRecentStickers'
+public:
+	MTPmessages_clearRecentStickers() {
+	}
+	MTPmessages_clearRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_clearRecentStickers) {
+		read(from, end, cons);
+	}
+
+	uint32 innerLength() const {
+		return 0;
+	}
+	mtpTypeId type() const {
+		return mtpc_messages_clearRecentStickers;
+	}
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_clearRecentStickers) {
+	}
+	void write(mtpBuffer &to) const {
+	}
+
+	typedef MTPBool ResponseType;
+};
+class MTPmessages_ClearRecentStickers : public MTPBoxed<MTPmessages_clearRecentStickers> {
+public:
+	MTPmessages_ClearRecentStickers() {
+	}
+	MTPmessages_ClearRecentStickers(const MTPmessages_clearRecentStickers &v) : MTPBoxed<MTPmessages_clearRecentStickers>(v) {
+	}
+	MTPmessages_ClearRecentStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_clearRecentStickers>(from, end, cons) {
+	}
+};
+
+class MTPmessages_getUnusedStickers { // RPC method 'messages.getUnusedStickers'
+public:
+	MTPint vlimit;
+
+	MTPmessages_getUnusedStickers() {
+	}
+	MTPmessages_getUnusedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getUnusedStickers) {
+		read(from, end, cons);
+	}
+	MTPmessages_getUnusedStickers(MTPint _limit) : vlimit(_limit) {
+	}
+
+	uint32 innerLength() const {
+		return vlimit.innerLength();
+	}
+	mtpTypeId type() const {
+		return mtpc_messages_getUnusedStickers;
+	}
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getUnusedStickers) {
+		vlimit.read(from, end);
+	}
+	void write(mtpBuffer &to) const {
+		vlimit.write(to);
+	}
+
+	typedef MTPVector<MTPStickerSet> ResponseType;
+};
+class MTPmessages_GetUnusedStickers : public MTPBoxed<MTPmessages_getUnusedStickers> {
+public:
+	MTPmessages_GetUnusedStickers() {
+	}
+	MTPmessages_GetUnusedStickers(const MTPmessages_getUnusedStickers &v) : MTPBoxed<MTPmessages_getUnusedStickers>(v) {
+	}
+	MTPmessages_GetUnusedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_getUnusedStickers>(from, end, cons) {
+	}
+	MTPmessages_GetUnusedStickers(MTPint _limit) : MTPBoxed<MTPmessages_getUnusedStickers>(MTPmessages_getUnusedStickers(_limit)) {
+	}
+};
+
 class MTPupdates_getState { // RPC method 'updates.getState'
 public:
 	MTPupdates_getState() {
@@ -22574,8 +22722,8 @@ public:
 	inline static MTPinputFileLocation new_inputEncryptedFileLocation(const MTPlong &_id, const MTPlong &_access_hash) {
 		return MTPinputFileLocation(new MTPDinputEncryptedFileLocation(_id, _access_hash));
 	}
-	inline static MTPinputFileLocation new_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash) {
-		return MTPinputFileLocation(new MTPDinputDocumentFileLocation(_id, _access_hash));
+	inline static MTPinputFileLocation new_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash, MTPint _version) {
+		return MTPinputFileLocation(new MTPDinputDocumentFileLocation(_id, _access_hash, _version));
 	}
 	inline static MTPinputPhotoCrop new_inputPhotoCropAuto() {
 		return MTPinputPhotoCrop(mtpc_inputPhotoCropAuto);
@@ -23105,6 +23253,9 @@ public:
 	inline static MTPupdate new_updateReadFeaturedStickers() {
 		return MTPupdate(mtpc_updateReadFeaturedStickers);
 	}
+	inline static MTPupdate new_updateRecentStickers() {
+		return MTPupdate(mtpc_updateRecentStickers);
+	}
 	inline static MTPupdates_state new_updates_state(MTPint _pts, MTPint _qts, MTPint _date, MTPint _seq, MTPint _unread_count) {
 		return MTPupdates_state(new MTPDupdates_state(_pts, _qts, _date, _seq, _unread_count));
 	}
@@ -23231,8 +23382,8 @@ public:
 	inline static MTPdocument new_documentEmpty(const MTPlong &_id) {
 		return MTPdocument(new MTPDdocumentEmpty(_id));
 	}
-	inline static MTPdocument new_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, const MTPVector<MTPDocumentAttribute> &_attributes) {
-		return MTPdocument(new MTPDdocument(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _attributes));
+	inline static MTPdocument new_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _version, const MTPVector<MTPDocumentAttribute> &_attributes) {
+		return MTPdocument(new MTPDdocument(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _version, _attributes));
 	}
 	inline static MTPhelp_support new_help_support(const MTPstring &_phone_number, const MTPUser &_user) {
 		return MTPhelp_support(new MTPDhelp_support(_phone_number, _user));
@@ -23354,9 +23505,6 @@ public:
 	inline static MTPdocumentAttribute new_documentAttributeFilename(const MTPstring &_file_name) {
 		return MTPdocumentAttribute(new MTPDdocumentAttributeFilename(_file_name));
 	}
-	inline static MTPdocumentAttribute new_documentAttributeVersion(MTPint _version) {
-		return MTPdocumentAttribute(new MTPDdocumentAttributeVersion(_version));
-	}
 	inline static MTPmessages_stickers new_messages_stickersNotModified() {
 		return MTPmessages_stickers(mtpc_messages_stickersNotModified);
 	}
@@ -23432,8 +23580,8 @@ public:
 	inline static MTPchatInvite new_chatInviteAlready(const MTPChat &_chat) {
 		return MTPchatInvite(new MTPDchatInviteAlready(_chat));
 	}
-	inline static MTPchatInvite new_chatInvite(const MTPflags<MTPDchatInvite::Flags> &_flags, const MTPstring &_title) {
-		return MTPchatInvite(new MTPDchatInvite(_flags, _title));
+	inline static MTPchatInvite new_chatInvite(const MTPflags<MTPDchatInvite::Flags> &_flags, const MTPstring &_title, const MTPChatPhoto &_photo, const MTPVector<MTPUser> &_participants) {
+		return MTPchatInvite(new MTPDchatInvite(_flags, _title, _photo, _participants));
 	}
 	inline static MTPinputStickerSet new_inputStickerSetEmpty() {
 		return MTPinputStickerSet(mtpc_inputStickerSetEmpty);
@@ -23753,6 +23901,12 @@ public:
 	inline static MTPmessages_featuredStickers new_messages_featuredStickers(MTPint _hash, const MTPVector<MTPStickerSet> &_sets, const MTPVector<MTPlong> &_unread) {
 		return MTPmessages_featuredStickers(new MTPDmessages_featuredStickers(_hash, _sets, _unread));
 	}
+	inline static MTPmessages_recentStickers new_messages_recentStickersNotModified() {
+		return MTPmessages_recentStickers(mtpc_messages_recentStickersNotModified);
+	}
+	inline static MTPmessages_recentStickers new_messages_recentStickers(MTPint _hash, const MTPVector<MTPDocument> &_stickers) {
+		return MTPmessages_recentStickers(new MTPDmessages_recentStickers(_hash, _stickers));
+	}
 	};
 
 } // namespace internal
@@ -25419,7 +25573,7 @@ inline uint32 MTPinputFileLocation::innerLength() const {
 		}
 		case mtpc_inputDocumentFileLocation: {
 			const MTPDinputDocumentFileLocation &v(c_inputDocumentFileLocation());
-			return v.vid.innerLength() + v.vaccess_hash.innerLength();
+			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vversion.innerLength();
 		}
 	}
 	return 0;
@@ -25449,6 +25603,7 @@ inline void MTPinputFileLocation::read(const mtpPrime *&from, const mtpPrime *en
 			MTPDinputDocumentFileLocation &v(_inputDocumentFileLocation());
 			v.vid.read(from, end);
 			v.vaccess_hash.read(from, end);
+			v.vversion.read(from, end);
 		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPinputFileLocation");
 	}
@@ -25470,6 +25625,7 @@ inline void MTPinputFileLocation::write(mtpBuffer &to) const {
 			const MTPDinputDocumentFileLocation &v(c_inputDocumentFileLocation());
 			v.vid.write(to);
 			v.vaccess_hash.write(to);
+			v.vversion.write(to);
 		} break;
 	}
 }
@@ -25493,8 +25649,8 @@ inline MTPinputFileLocation MTP_inputFileLocation(const MTPlong &_volume_id, MTP
 inline MTPinputFileLocation MTP_inputEncryptedFileLocation(const MTPlong &_id, const MTPlong &_access_hash) {
 	return MTP::internal::TypeCreator::new_inputEncryptedFileLocation(_id, _access_hash);
 }
-inline MTPinputFileLocation MTP_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash) {
-	return MTP::internal::TypeCreator::new_inputDocumentFileLocation(_id, _access_hash);
+inline MTPinputFileLocation MTP_inputDocumentFileLocation(const MTPlong &_id, const MTPlong &_access_hash, MTPint _version) {
+	return MTP::internal::TypeCreator::new_inputDocumentFileLocation(_id, _access_hash, _version);
 }
 
 inline uint32 MTPinputPhotoCrop::innerLength() const {
@@ -28971,6 +29127,7 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
 			v.vdraft.read(from, end);
 		} break;
 		case mtpc_updateReadFeaturedStickers: _type = cons; break;
+		case mtpc_updateRecentStickers: _type = cons; break;
 		default: throw mtpErrorUnexpected(cons, "MTPupdate");
 	}
 }
@@ -29305,6 +29462,7 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) {
 		case mtpc_updateReadChannelOutbox: setData(new MTPDupdateReadChannelOutbox()); break;
 		case mtpc_updateDraftMessage: setData(new MTPDupdateDraftMessage()); break;
 		case mtpc_updateReadFeaturedStickers: break;
+		case mtpc_updateRecentStickers: break;
 		default: throw mtpErrorBadTypeId(type, "MTPupdate");
 	}
 }
@@ -29555,6 +29713,9 @@ inline MTPupdate MTP_updateDraftMessage(const MTPPeer &_peer, const MTPDraftMess
 inline MTPupdate MTP_updateReadFeaturedStickers() {
 	return MTP::internal::TypeCreator::new_updateReadFeaturedStickers();
 }
+inline MTPupdate MTP_updateRecentStickers() {
+	return MTP::internal::TypeCreator::new_updateRecentStickers();
+}
 
 inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) {
 }
@@ -30864,7 +31025,7 @@ inline uint32 MTPdocument::innerLength() const {
 		}
 		case mtpc_document: {
 			const MTPDdocument &v(c_document());
-			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vattributes.innerLength();
+			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vversion.innerLength() + v.vattributes.innerLength();
 		}
 	}
 	return 0;
@@ -30891,6 +31052,7 @@ inline void MTPdocument::read(const mtpPrime *&from, const mtpPrime *end, mtpTyp
 			v.vsize.read(from, end);
 			v.vthumb.read(from, end);
 			v.vdc_id.read(from, end);
+			v.vversion.read(from, end);
 			v.vattributes.read(from, end);
 		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPdocument");
@@ -30911,6 +31073,7 @@ inline void MTPdocument::write(mtpBuffer &to) const {
 			v.vsize.write(to);
 			v.vthumb.write(to);
 			v.vdc_id.write(to);
+			v.vversion.write(to);
 			v.vattributes.write(to);
 		} break;
 	}
@@ -30929,8 +31092,8 @@ inline MTPdocument::MTPdocument(MTPDdocument *_data) : mtpDataOwner(_data), _typ
 inline MTPdocument MTP_documentEmpty(const MTPlong &_id) {
 	return MTP::internal::TypeCreator::new_documentEmpty(_id);
 }
-inline MTPdocument MTP_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, const MTPVector<MTPDocumentAttribute> &_attributes) {
-	return MTP::internal::TypeCreator::new_document(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _attributes);
+inline MTPdocument MTP_document(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _version, const MTPVector<MTPDocumentAttribute> &_attributes) {
+	return MTP::internal::TypeCreator::new_document(_id, _access_hash, _date, _mime_type, _size, _thumb, _dc_id, _version, _attributes);
 }
 
 inline MTPhelp_support::MTPhelp_support() : mtpDataOwner(new MTPDhelp_support()) {
@@ -31487,10 +31650,6 @@ inline uint32 MTPdocumentAttribute::innerLength() const {
 			const MTPDdocumentAttributeFilename &v(c_documentAttributeFilename());
 			return v.vfile_name.innerLength();
 		}
-		case mtpc_documentAttributeVersion: {
-			const MTPDdocumentAttributeVersion &v(c_documentAttributeVersion());
-			return v.vversion.innerLength();
-		}
 	}
 	return 0;
 }
@@ -31535,11 +31694,6 @@ inline void MTPdocumentAttribute::read(const mtpPrime *&from, const mtpPrime *en
 			MTPDdocumentAttributeFilename &v(_documentAttributeFilename());
 			v.vfile_name.read(from, end);
 		} break;
-		case mtpc_documentAttributeVersion: _type = cons; {
-			if (!data) setData(new MTPDdocumentAttributeVersion());
-			MTPDdocumentAttributeVersion &v(_documentAttributeVersion());
-			v.vversion.read(from, end);
-		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPdocumentAttribute");
 	}
 }
@@ -31573,10 +31727,6 @@ inline void MTPdocumentAttribute::write(mtpBuffer &to) const {
 			const MTPDdocumentAttributeFilename &v(c_documentAttributeFilename());
 			v.vfile_name.write(to);
 		} break;
-		case mtpc_documentAttributeVersion: {
-			const MTPDdocumentAttributeVersion &v(c_documentAttributeVersion());
-			v.vversion.write(to);
-		} break;
 	}
 }
 inline MTPdocumentAttribute::MTPdocumentAttribute(mtpTypeId type) : mtpDataOwner(0), _type(type) {
@@ -31587,7 +31737,6 @@ inline MTPdocumentAttribute::MTPdocumentAttribute(mtpTypeId type) : mtpDataOwner
 		case mtpc_documentAttributeVideo: setData(new MTPDdocumentAttributeVideo()); break;
 		case mtpc_documentAttributeAudio: setData(new MTPDdocumentAttributeAudio()); break;
 		case mtpc_documentAttributeFilename: setData(new MTPDdocumentAttributeFilename()); break;
-		case mtpc_documentAttributeVersion: setData(new MTPDdocumentAttributeVersion()); break;
 		default: throw mtpErrorBadTypeId(type, "MTPdocumentAttribute");
 	}
 }
@@ -31601,8 +31750,6 @@ inline MTPdocumentAttribute::MTPdocumentAttribute(MTPDdocumentAttributeAudio *_d
 }
 inline MTPdocumentAttribute::MTPdocumentAttribute(MTPDdocumentAttributeFilename *_data) : mtpDataOwner(_data), _type(mtpc_documentAttributeFilename) {
 }
-inline MTPdocumentAttribute::MTPdocumentAttribute(MTPDdocumentAttributeVersion *_data) : mtpDataOwner(_data), _type(mtpc_documentAttributeVersion) {
-}
 inline MTPdocumentAttribute MTP_documentAttributeImageSize(MTPint _w, MTPint _h) {
 	return MTP::internal::TypeCreator::new_documentAttributeImageSize(_w, _h);
 }
@@ -31622,9 +31769,6 @@ inline MTPdocumentAttribute MTP_documentAttributeAudio(const MTPflags<MTPDdocume
 inline MTPdocumentAttribute MTP_documentAttributeFilename(const MTPstring &_file_name) {
 	return MTP::internal::TypeCreator::new_documentAttributeFilename(_file_name);
 }
-inline MTPdocumentAttribute MTP_documentAttributeVersion(MTPint _version) {
-	return MTP::internal::TypeCreator::new_documentAttributeVersion(_version);
-}
 
 inline uint32 MTPmessages_stickers::innerLength() const {
 	switch (_type) {
@@ -32297,7 +32441,7 @@ inline uint32 MTPchatInvite::innerLength() const {
 		}
 		case mtpc_chatInvite: {
 			const MTPDchatInvite &v(c_chatInvite());
-			return v.vflags.innerLength() + v.vtitle.innerLength();
+			return v.vflags.innerLength() + v.vtitle.innerLength() + v.vphoto.innerLength() + (v.has_participants() ? v.vparticipants.innerLength() : 0);
 		}
 	}
 	return 0;
@@ -32319,6 +32463,8 @@ inline void MTPchatInvite::read(const mtpPrime *&from, const mtpPrime *end, mtpT
 			MTPDchatInvite &v(_chatInvite());
 			v.vflags.read(from, end);
 			v.vtitle.read(from, end);
+			v.vphoto.read(from, end);
+			if (v.has_participants()) { v.vparticipants.read(from, end); } else { v.vparticipants = MTPVector<MTPUser>(); }
 		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPchatInvite");
 	}
@@ -32333,6 +32479,8 @@ inline void MTPchatInvite::write(mtpBuffer &to) const {
 			const MTPDchatInvite &v(c_chatInvite());
 			v.vflags.write(to);
 			v.vtitle.write(to);
+			v.vphoto.write(to);
+			if (v.has_participants()) v.vparticipants.write(to);
 		} break;
 	}
 }
@@ -32351,8 +32499,8 @@ inline MTPchatInvite MTP_chatInviteAlready(const MTPChat &_chat) {
 	return MTP::internal::TypeCreator::new_chatInviteAlready(_chat);
 }
 Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDchatInvite::Flags)
-inline MTPchatInvite MTP_chatInvite(const MTPflags<MTPDchatInvite::Flags> &_flags, const MTPstring &_title) {
-	return MTP::internal::TypeCreator::new_chatInvite(_flags, _title);
+inline MTPchatInvite MTP_chatInvite(const MTPflags<MTPDchatInvite::Flags> &_flags, const MTPstring &_title, const MTPChatPhoto &_photo, const MTPVector<MTPUser> &_participants) {
+	return MTP::internal::TypeCreator::new_chatInvite(_flags, _title, _photo, _participants);
 }
 
 inline uint32 MTPinputStickerSet::innerLength() const {
@@ -35152,6 +35300,57 @@ inline MTPmessages_featuredStickers MTP_messages_featuredStickersNotModified() {
 inline MTPmessages_featuredStickers MTP_messages_featuredStickers(MTPint _hash, const MTPVector<MTPStickerSet> &_sets, const MTPVector<MTPlong> &_unread) {
 	return MTP::internal::TypeCreator::new_messages_featuredStickers(_hash, _sets, _unread);
 }
+
+inline uint32 MTPmessages_recentStickers::innerLength() const {
+	switch (_type) {
+		case mtpc_messages_recentStickers: {
+			const MTPDmessages_recentStickers &v(c_messages_recentStickers());
+			return v.vhash.innerLength() + v.vstickers.innerLength();
+		}
+	}
+	return 0;
+}
+inline mtpTypeId MTPmessages_recentStickers::type() const {
+	if (!_type) throw mtpErrorUninitialized();
+	return _type;
+}
+inline void MTPmessages_recentStickers::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
+	if (cons != _type) setData(0);
+	switch (cons) {
+		case mtpc_messages_recentStickersNotModified: _type = cons; break;
+		case mtpc_messages_recentStickers: _type = cons; {
+			if (!data) setData(new MTPDmessages_recentStickers());
+			MTPDmessages_recentStickers &v(_messages_recentStickers());
+			v.vhash.read(from, end);
+			v.vstickers.read(from, end);
+		} break;
+		default: throw mtpErrorUnexpected(cons, "MTPmessages_recentStickers");
+	}
+}
+inline void MTPmessages_recentStickers::write(mtpBuffer &to) const {
+	switch (_type) {
+		case mtpc_messages_recentStickers: {
+			const MTPDmessages_recentStickers &v(c_messages_recentStickers());
+			v.vhash.write(to);
+			v.vstickers.write(to);
+		} break;
+	}
+}
+inline MTPmessages_recentStickers::MTPmessages_recentStickers(mtpTypeId type) : mtpDataOwner(0), _type(type) {
+	switch (type) {
+		case mtpc_messages_recentStickersNotModified: break;
+		case mtpc_messages_recentStickers: setData(new MTPDmessages_recentStickers()); break;
+		default: throw mtpErrorBadTypeId(type, "MTPmessages_recentStickers");
+	}
+}
+inline MTPmessages_recentStickers::MTPmessages_recentStickers(MTPDmessages_recentStickers *_data) : mtpDataOwner(_data), _type(mtpc_messages_recentStickers) {
+}
+inline MTPmessages_recentStickers MTP_messages_recentStickersNotModified() {
+	return MTP::internal::TypeCreator::new_messages_recentStickersNotModified();
+}
+inline MTPmessages_recentStickers MTP_messages_recentStickers(MTPint _hash, const MTPVector<MTPDocument> &_stickers) {
+	return MTP::internal::TypeCreator::new_messages_recentStickers(_hash, _stickers);
+}
 inline MTPDmessage::Flags mtpCastFlags(MTPDmessageService::Flags flags) { return MTPDmessage::Flags(QFlag(flags)); }
 inline MTPDmessage::Flags mtpCastFlags(MTPflags<MTPDmessageService::Flags> flags) { return mtpCastFlags(flags.v); }
 inline MTPDmessage::Flags mtpCastFlags(MTPDupdateShortMessage::Flags flags) { return MTPDmessage::Flags(QFlag(flags)); }
diff --git a/Telegram/SourceFiles/serialize/serialize_document.cpp b/Telegram/SourceFiles/serialize/serialize_document.cpp
index 73823edf56..6f489e690a 100644
--- a/Telegram/SourceFiles/serialize/serialize_document.cpp
+++ b/Telegram/SourceFiles/serialize/serialize_document.cpp
@@ -37,6 +37,7 @@ namespace Serialize {
 
 void Document::writeToStream(QDataStream &stream, DocumentData *document) {
 	stream << quint64(document->id) << quint64(document->_access) << qint32(document->date);
+	stream << qint32(document->_version);
 	stream << document->name << document->mime << qint32(document->_dc) << qint32(document->size);
 	stream << qint32(document->dimensions.width()) << qint32(document->dimensions.height());
 	stream << qint32(document->type);
@@ -61,11 +62,16 @@ void Document::writeToStream(QDataStream &stream, DocumentData *document) {
 	}
 }
 
-DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info) {
+DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info) {
 	quint64 id, access;
 	QString name, mime;
-	qint32 date, dc, size, width, height, type;
+	qint32 date, dc, size, width, height, type, version;
 	stream >> id >> access >> date;
+	if (streamAppVersion >= 9058) {
+		stream >> version;
+	} else {
+		version = 0;
+	}
 	stream >> name >> mime >> dc >> size;
 	stream >> width >> height;
 	stream >> type;
@@ -122,22 +128,22 @@ DocumentData *Document::readFromStreamHelper(QDataStream &stream, const StickerS
 	if (!dc && !access) {
 		return nullptr;
 	}
-	return App::documentSet(id, nullptr, access, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb);
+	return App::documentSet(id, nullptr, access, version, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb);
 }
 
-DocumentData *Document::readStickerFromStream(QDataStream &stream, const StickerSetInfo &info) {
-	return readFromStreamHelper(stream, &info);
+DocumentData *Document::readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info) {
+	return readFromStreamHelper(streamAppVersion, stream, &info);
 }
 
-DocumentData *Document::readFromStream(QDataStream &stream) {
-	return readFromStreamHelper(stream, nullptr);
+DocumentData *Document::readFromStream(int streamAppVersion, QDataStream &stream) {
+	return readFromStreamHelper(streamAppVersion, stream, nullptr);
 }
 
 int Document::sizeInStream(DocumentData *document) {
 	int result = 0;
 
-	// id + access + date
-	result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32);
+	// id + access + date + version
+	result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32);
 	// + namelen + name + mimelen + mime + dc + size
 	result += stringSize(document->name) + stringSize(document->mime) + sizeof(qint32) + sizeof(qint32);
 	// + width + height
diff --git a/Telegram/SourceFiles/serialize/serialize_document.h b/Telegram/SourceFiles/serialize/serialize_document.h
index b0ed77282d..44ad8cd2fe 100644
--- a/Telegram/SourceFiles/serialize/serialize_document.h
+++ b/Telegram/SourceFiles/serialize/serialize_document.h
@@ -39,12 +39,12 @@ public:
 	};
 
 	static void writeToStream(QDataStream &stream, DocumentData *document);
-	static DocumentData *readStickerFromStream(QDataStream &stream, const StickerSetInfo &info);
-	static DocumentData *readFromStream(QDataStream &stream);
+	static DocumentData *readStickerFromStream(int streamAppVersion, QDataStream &stream, const StickerSetInfo &info);
+	static DocumentData *readFromStream(int streamAppVersion, QDataStream &stream);
 	static int sizeInStream(DocumentData *document);
 
 private:
-	static DocumentData *readFromStreamHelper(QDataStream &stream, const StickerSetInfo *info);
+	static DocumentData *readFromStreamHelper(int streamAppVersion, QDataStream &stream, const StickerSetInfo *info);
 
 };
 
diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp
index 662420bc30..cd57d76aa8 100644
--- a/Telegram/SourceFiles/structs.cpp
+++ b/Telegram/SourceFiles/structs.cpp
@@ -1082,10 +1082,11 @@ VoiceData::~VoiceData() {
 DocumentAdditionalData::~DocumentAdditionalData() {
 }
 
-DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QString &url, const QVector<MTPDocumentAttribute> &attributes)
+DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector<MTPDocumentAttribute> &attributes)
 : id(id)
 , _dc(dc)
 , _access(accessHash)
+, _version(version)
 , _url(url) {
 	setattributes(attributes);
 	if (_dc && _access) {
@@ -1094,15 +1095,15 @@ DocumentData::DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QSt
 }
 
 DocumentData *DocumentData::create(DocumentId id) {
-	return new DocumentData(id, 0, 0, QString(), QVector<MTPDocumentAttribute>());
+	return new DocumentData(id, 0, 0, 0, QString(), QVector<MTPDocumentAttribute>());
 }
 
-DocumentData *DocumentData::create(DocumentId id, int32 dc, uint64 accessHash, const QVector<MTPDocumentAttribute> &attributes) {
-	return new DocumentData(id, dc, accessHash, QString(), attributes);
+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, url, attributes);
+	return new DocumentData(id, 0, 0, 0, url, attributes);
 }
 
 void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
@@ -1385,7 +1386,7 @@ void DocumentData::save(const QString &toFile, ActionOnLoad action, const FullMs
 		if (!_access && !_url.isEmpty()) {
 			_loader = new webFileLoader(_url, toFile, fromCloud, autoLoading);
 		} else {
-			_loader = new mtpFileLoader(_dc, id, _access, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
+			_loader = new mtpFileLoader(_dc, id, _access, _version, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
 		}
 		_loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*)));
 		_loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
@@ -1526,6 +1527,22 @@ void DocumentData::recountIsImage() {
 	_duration = fileIsImage(name, mime) ? 1 : -1; // hack
 }
 
+bool DocumentData::setRemoteVersion(int32 version) {
+	if (_version == version) {
+		return false;
+	}
+	_version = version;
+	_location = FileLocation();
+	_data = QByteArray();
+	status = FileReady;
+	if (loading()) {
+		_loader->deleteLater();
+		_loader->stop();
+		_loader = nullptr;
+	}
+	return true;
+}
+
 void DocumentData::setRemoteLocation(int32 dc, uint64 access) {
 	_dc = dc;
 	_access = access;
diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h
index 1a948de465..876d6a9d66 100644
--- a/Telegram/SourceFiles/structs.h
+++ b/Telegram/SourceFiles/structs.h
@@ -1068,7 +1068,7 @@ class Document;
 class DocumentData {
 public:
 	static DocumentData *create(DocumentId id);
-	static DocumentData *create(DocumentId id, int32 dc, uint64 accessHash, const QVector<MTPDocumentAttribute> &attributes);
+	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);
 
 	void setattributes(const QVector<MTPDocumentAttribute> &attributes);
@@ -1159,6 +1159,7 @@ public:
 		_data = data;
 	}
 
+	bool setRemoteVersion(int32 version); // Returns true if version has changed.
 	void setRemoteLocation(int32 dc, uint64 access);
 	void setContentUrl(const QString &url);
 	bool hasRemoteLocation() const {
@@ -1196,11 +1197,11 @@ public:
 	int32 md5[8];
 
 	MediaKey mediaKey() const {
-		return ::mediaKey(locationType(), _dc, id);
+		return ::mediaKey(locationType(), _dc, id, _version);
 	}
 
 private:
-	DocumentData(DocumentId id, int32 dc, uint64 accessHash, const QString &url, const QVector<MTPDocumentAttribute> &attributes);
+	DocumentData(DocumentId id, int32 dc, uint64 accessHash, int32 version, const QString &url, const QVector<MTPDocumentAttribute> &attributes);
 
 	friend class Serialize::Document;
 
@@ -1208,9 +1209,10 @@ private:
 		return voice() ? AudioFileLocation : (isVideo() ? VideoFileLocation : DocumentFileLocation);
 	}
 
-	// Two types of location: from MTProto by dc+access or from web by url
+	// Two types of location: from MTProto by dc+access+version or from web by url
 	int32 _dc = 0;
 	uint64 _access = 0;
+	int32 _version = 0;
 	QString _url;
 
 	FileLocation _location;
diff --git a/Telegram/SourceFiles/ui/images.h b/Telegram/SourceFiles/ui/images.h
index 8596dbfc47..5bb7c28117 100644
--- a/Telegram/SourceFiles/ui/images.h
+++ b/Telegram/SourceFiles/ui/images.h
@@ -486,8 +486,13 @@ typedef QPair<uint64, uint64> MediaKey;
 inline uint64 mediaMix32To64(int32 a, int32 b) {
 	return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
 }
-inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
-	return MediaKey(mediaMix32To64(type, dc), id);
+// Old method, should not be used anymore.
+//inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
+//	return MediaKey(mediaMix32To64(type, dc), id);
+//}
+// New method when version was introduced, type is not relevant anymore (all files are Documents).
+inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id, int32 version) {
+	return (version > 0) ? MediaKey(mediaMix32To64(version, dc), id) : MediaKey(mediaMix32To64(type, dc), id);
 }
 inline StorageKey mediaKey(const MTPDfileLocation &location) {
 	return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj
index a50bf242c1..e5022f18dd 100644
--- a/Telegram/Telegram.xcodeproj/project.pbxproj
+++ b/Telegram/Telegram.xcodeproj/project.pbxproj
@@ -2375,7 +2375,7 @@
 				SDKROOT = macosx;
 				SYMROOT = ./../Mac;
 				TDESKTOP_MAJOR_VERSION = 0.9;
-				TDESKTOP_VERSION = 0.9.57;
+				TDESKTOP_VERSION = 0.9.58;
 			};
 			name = Release;
 		};
@@ -2516,7 +2516,7 @@
 				SDKROOT = macosx;
 				SYMROOT = ./../Mac;
 				TDESKTOP_MAJOR_VERSION = 0.9;
-				TDESKTOP_VERSION = 0.9.57;
+				TDESKTOP_VERSION = 0.9.58;
 			};
 			name = Debug;
 		};
diff --git a/Telegram/build/version b/Telegram/build/version
index 4a048eef7e..f5aff1e62d 100644
--- a/Telegram/build/version
+++ b/Telegram/build/version
@@ -1,6 +1,6 @@
-AppVersion         9057
+AppVersion         9058
 AppVersionStrMajor 0.9
-AppVersionStrSmall 0.9.57
-AppVersionStr      0.9.57
+AppVersionStrSmall 0.9.58
+AppVersionStr      0.9.58
 AlphaChannel       1
 BetaVersion        0