mirror of https://github.com/procxx/kepka.git
				
				
				
			Load maps using mtproto instead of google.
This commit is contained in:
		
							parent
							
								
									be6e329e94
								
							
						
					
					
						commit
						9f90d3a7fc
					
				| 
						 | 
				
			
			@ -23,6 +23,8 @@ constexpr auto kWebDocumentCacheTag = 0x0000020000000000ULL;
 | 
			
		|||
constexpr auto kWebDocumentCacheMask = 0x000000FFFFFFFFFFULL;
 | 
			
		||||
constexpr auto kUrlCacheTag = 0x0000030000000000ULL;
 | 
			
		||||
constexpr auto kUrlCacheMask = 0x000000FFFFFFFFFFULL;
 | 
			
		||||
constexpr auto kGeoPointCacheTag = 0x0000040000000000ULL;
 | 
			
		||||
constexpr auto kGeoPointCacheMask = 0x000000FFFFFFFFFFULL;
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +76,18 @@ Storage::Cache::Key UrlCacheKey(const QString &location) {
 | 
			
		|||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Storage::Cache::Key GeoPointCacheKey(const GeoPointLocation &location) {
 | 
			
		||||
	const auto zoomscale = ((uint32(location.zoom) & 0x0FU) << 8)
 | 
			
		||||
		| (uint32(location.scale) & 0x0FU);
 | 
			
		||||
	const auto widthheight = ((uint32(location.width) & 0xFFFFU) << 16)
 | 
			
		||||
		| (uint32(location.height) & 0xFFFFU);
 | 
			
		||||
	return Storage::Cache::Key{
 | 
			
		||||
		Data::kGeoPointCacheTag | (uint64(zoomscale) << 32) | widthheight,
 | 
			
		||||
		(uint64(std::round(std::abs(location.lat + 360.) * 1000000)) << 32)
 | 
			
		||||
		| uint64(std::round(std::abs(location.lon + 360.) * 1000000))
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Data
 | 
			
		||||
 | 
			
		||||
void AudioMsgId::setTypeFromAudio() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ class InputField;
 | 
			
		|||
 | 
			
		||||
class StorageImageLocation;
 | 
			
		||||
class WebFileLocation;
 | 
			
		||||
struct GeoPointLocation;
 | 
			
		||||
 | 
			
		||||
namespace Data {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +41,7 @@ Storage::Cache::Key DocumentCacheKey(int32 dcId, uint64 id);
 | 
			
		|||
Storage::Cache::Key StorageCacheKey(const StorageImageLocation &location);
 | 
			
		||||
Storage::Cache::Key WebDocumentCacheKey(const WebFileLocation &location);
 | 
			
		||||
Storage::Cache::Key UrlCacheKey(const QString &location);
 | 
			
		||||
Storage::Cache::Key GeoPointCacheKey(const GeoPointLocation &location);
 | 
			
		||||
 | 
			
		||||
constexpr auto kImageCacheTag = uint8(0x01);
 | 
			
		||||
constexpr auto kStickerCacheTag = uint8(0x02);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,28 @@ namespace {
 | 
			
		|||
constexpr auto kCoordPrecision = 8;
 | 
			
		||||
constexpr auto kMaxHttpRedirects = 5;
 | 
			
		||||
 | 
			
		||||
GeoPointLocation ComputeLocation(const LocationCoords &coords) {
 | 
			
		||||
	int32 w = st::locationSize.width(), h = st::locationSize.height();
 | 
			
		||||
	int32 zoom = 15, scale = 1;
 | 
			
		||||
	if (cScale() == dbisTwo || cRetina()) {
 | 
			
		||||
		scale = 2;
 | 
			
		||||
		zoom = 16;
 | 
			
		||||
	} else {
 | 
			
		||||
		w = convertScale(w);
 | 
			
		||||
		h = convertScale(h);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto result = GeoPointLocation();
 | 
			
		||||
	result.lat = coords.lat();
 | 
			
		||||
	result.lon = coords.lon();
 | 
			
		||||
	result.access = coords.accessHash();
 | 
			
		||||
	result.width = w;
 | 
			
		||||
	result.height = h;
 | 
			
		||||
	result.zoom = zoom;
 | 
			
		||||
	result.scale = scale;
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
QString LocationClickHandler::copyToClipboardText() const {
 | 
			
		||||
| 
						 | 
				
			
			@ -37,200 +59,11 @@ void LocationClickHandler::setup() {
 | 
			
		|||
	_text = qsl("https://maps.google.com/maps?q=") + latlon + qsl("&ll=") + latlon + qsl("&z=16");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
LocationManager *locationManager = nullptr;
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
void initLocationManager() {
 | 
			
		||||
	if (!locationManager) {
 | 
			
		||||
		locationManager = new LocationManager();
 | 
			
		||||
		locationManager->init();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void deinitLocationManager() {
 | 
			
		||||
	if (locationManager) {
 | 
			
		||||
		locationManager->deinit();
 | 
			
		||||
		delete locationManager;
 | 
			
		||||
		locationManager = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationManager::init() {
 | 
			
		||||
	if (manager) delete manager;
 | 
			
		||||
	manager = new QNetworkAccessManager();
 | 
			
		||||
 | 
			
		||||
	connect(manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(onFailed(QNetworkReply*)));
 | 
			
		||||
#ifndef OS_MAC_OLD
 | 
			
		||||
	connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(onFailed(QNetworkReply*)));
 | 
			
		||||
#endif // OS_MAC_OLD
 | 
			
		||||
	connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
 | 
			
		||||
 | 
			
		||||
	if (notLoadedPlaceholder) {
 | 
			
		||||
		delete notLoadedPlaceholder->v();
 | 
			
		||||
		delete notLoadedPlaceholder;
 | 
			
		||||
	}
 | 
			
		||||
	auto data = QImage(cIntRetinaFactor(), cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
 | 
			
		||||
	data.fill(st::imageBgTransparent->c);
 | 
			
		||||
	data.setDevicePixelRatio(cRetinaFactor());
 | 
			
		||||
	notLoadedPlaceholder = new ImagePtr(App::pixmapFromImageInPlace(std::move(data)), "GIF");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationManager::deinit() {
 | 
			
		||||
	if (manager) {
 | 
			
		||||
		delete manager;
 | 
			
		||||
		manager = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
	if (notLoadedPlaceholder) {
 | 
			
		||||
		delete notLoadedPlaceholder->v();
 | 
			
		||||
		delete notLoadedPlaceholder;
 | 
			
		||||
		notLoadedPlaceholder = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
	dataLoadings.clear();
 | 
			
		||||
	imageLoadings.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationManager::getData(LocationData *data) {
 | 
			
		||||
	if (!manager) {
 | 
			
		||||
		DEBUG_LOG(("App Error: getting image link data without manager init!"));
 | 
			
		||||
		return failed(data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int32 w = st::locationSize.width(), h = st::locationSize.height();
 | 
			
		||||
	int32 zoom = 13, scale = 1;
 | 
			
		||||
	if (cScale() == dbisTwo || cRetina()) {
 | 
			
		||||
		scale = 2;
 | 
			
		||||
	} else {
 | 
			
		||||
		w = convertScale(w);
 | 
			
		||||
		h = convertScale(h);
 | 
			
		||||
	}
 | 
			
		||||
	auto coords = data->coords.latAsString() + ',' + data->coords.lonAsString();
 | 
			
		||||
	QString url = qsl("https://maps.googleapis.com/maps/api/staticmap?center=") + coords + qsl("&zoom=%1&size=%2x%3&maptype=roadmap&scale=%4&markers=color:red|size:big|").arg(zoom).arg(w).arg(h).arg(scale) + coords + qsl("&sensor=false");
 | 
			
		||||
	QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url)));
 | 
			
		||||
	imageLoadings[reply] = data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationManager::onFinished(QNetworkReply *reply) {
 | 
			
		||||
	if (!manager) return;
 | 
			
		||||
	if (reply->error() != QNetworkReply::NoError) return onFailed(reply);
 | 
			
		||||
 | 
			
		||||
	QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
 | 
			
		||||
	if (statusCode.isValid()) {
 | 
			
		||||
		int status = statusCode.toInt();
 | 
			
		||||
		if (status == 301 || status == 302) {
 | 
			
		||||
			QString loc = reply->header(QNetworkRequest::LocationHeader).toString();
 | 
			
		||||
			if (!loc.isEmpty()) {
 | 
			
		||||
				QMap<QNetworkReply*, LocationData*>::iterator i = dataLoadings.find(reply);
 | 
			
		||||
				if (i != dataLoadings.cend()) {
 | 
			
		||||
					LocationData *d = i.value();
 | 
			
		||||
					if (serverRedirects.constFind(d) == serverRedirects.cend()) {
 | 
			
		||||
						serverRedirects.insert(d, 1);
 | 
			
		||||
					} else if (++serverRedirects[d] > kMaxHttpRedirects) {
 | 
			
		||||
						DEBUG_LOG(("Network Error: Too many HTTP redirects in onFinished() for image link: %1").arg(loc));
 | 
			
		||||
						return onFailed(reply);
 | 
			
		||||
					}
 | 
			
		||||
					dataLoadings.erase(i);
 | 
			
		||||
					dataLoadings.insert(manager->get(QNetworkRequest(loc)), d);
 | 
			
		||||
					return;
 | 
			
		||||
				} else if ((i = imageLoadings.find(reply)) != imageLoadings.cend()) {
 | 
			
		||||
					LocationData *d = i.value();
 | 
			
		||||
					if (serverRedirects.constFind(d) == serverRedirects.cend()) {
 | 
			
		||||
						serverRedirects.insert(d, 1);
 | 
			
		||||
					} else if (++serverRedirects[d] > kMaxHttpRedirects) {
 | 
			
		||||
						DEBUG_LOG(("Network Error: Too many HTTP redirects in onFinished() for image link: %1").arg(loc));
 | 
			
		||||
						return onFailed(reply);
 | 
			
		||||
					}
 | 
			
		||||
					imageLoadings.erase(i);
 | 
			
		||||
					imageLoadings.insert(manager->get(QNetworkRequest(loc)), d);
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (status != 200) {
 | 
			
		||||
			DEBUG_LOG(("Network Error: Bad HTTP status received in onFinished() for image link: %1").arg(status));
 | 
			
		||||
			return onFailed(reply);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LocationData *d = 0;
 | 
			
		||||
	QMap<QNetworkReply*, LocationData*>::iterator i = dataLoadings.find(reply);
 | 
			
		||||
	if (i != dataLoadings.cend()) {
 | 
			
		||||
		d = i.value();
 | 
			
		||||
		dataLoadings.erase(i);
 | 
			
		||||
 | 
			
		||||
		QJsonParseError e;
 | 
			
		||||
		QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &e);
 | 
			
		||||
		if (e.error != QJsonParseError::NoError) {
 | 
			
		||||
			DEBUG_LOG(("JSON Error: Bad json received in onFinished() for image link"));
 | 
			
		||||
			return onFailed(reply);
 | 
			
		||||
		}
 | 
			
		||||
		failed(d);
 | 
			
		||||
 | 
			
		||||
		if (App::main()) App::main()->update();
 | 
			
		||||
	} else {
 | 
			
		||||
		i = imageLoadings.find(reply);
 | 
			
		||||
		if (i != imageLoadings.cend()) {
 | 
			
		||||
			d = i.value();
 | 
			
		||||
			imageLoadings.erase(i);
 | 
			
		||||
 | 
			
		||||
			QPixmap thumb;
 | 
			
		||||
			QByteArray format;
 | 
			
		||||
			QByteArray data(reply->readAll());
 | 
			
		||||
			{
 | 
			
		||||
				QBuffer buffer(&data);
 | 
			
		||||
				QImageReader reader(&buffer);
 | 
			
		||||
#ifndef OS_MAC_OLD
 | 
			
		||||
				reader.setAutoTransform(true);
 | 
			
		||||
#endif // OS_MAC_OLD
 | 
			
		||||
				thumb = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
 | 
			
		||||
				format = reader.format();
 | 
			
		||||
				thumb.setDevicePixelRatio(cRetinaFactor());
 | 
			
		||||
				if (format.isEmpty()) format = QByteArray("JPG");
 | 
			
		||||
			}
 | 
			
		||||
			d->loading = false;
 | 
			
		||||
			d->thumb = thumb.isNull() ? (*notLoadedPlaceholder) : ImagePtr(thumb, format);
 | 
			
		||||
			serverRedirects.remove(d);
 | 
			
		||||
			if (App::main()) App::main()->update();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationManager::onFailed(QNetworkReply *reply) {
 | 
			
		||||
	if (!manager) return;
 | 
			
		||||
 | 
			
		||||
	LocationData *d = 0;
 | 
			
		||||
	QMap<QNetworkReply*, LocationData*>::iterator i = dataLoadings.find(reply);
 | 
			
		||||
	if (i != dataLoadings.cend()) {
 | 
			
		||||
		d = i.value();
 | 
			
		||||
		dataLoadings.erase(i);
 | 
			
		||||
	} else {
 | 
			
		||||
		i = imageLoadings.find(reply);
 | 
			
		||||
		if (i != imageLoadings.cend()) {
 | 
			
		||||
			d = i.value();
 | 
			
		||||
			imageLoadings.erase(i);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(("Network Error: failed to get data for image link %1,%2 error %3").arg(d ? d->coords.latAsString() : QString()).arg(d ? d->coords.lonAsString() : QString()).arg(reply->errorString()));
 | 
			
		||||
	if (d) {
 | 
			
		||||
		failed(d);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationManager::failed(LocationData *data) {
 | 
			
		||||
	data->loading = false;
 | 
			
		||||
	data->thumb = *notLoadedPlaceholder;
 | 
			
		||||
	serverRedirects.remove(data);
 | 
			
		||||
LocationData::LocationData(const LocationCoords &coords)
 | 
			
		||||
: coords(coords)
 | 
			
		||||
, thumb(ComputeLocation(coords)) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LocationData::load(Data::FileOrigin origin) {
 | 
			
		||||
	if (!thumb->isNull()) {
 | 
			
		||||
		return thumb->load(origin, false, false);
 | 
			
		||||
	} else if (loading) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	loading = true;
 | 
			
		||||
	if (locationManager) {
 | 
			
		||||
		locationManager->getData(this);
 | 
			
		||||
	}
 | 
			
		||||
	thumb->load(origin, false, false);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
			
		|||
*/
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
void initLocationManager();
 | 
			
		||||
void deinitLocationManager();
 | 
			
		||||
 | 
			
		||||
class LocationCoords {
 | 
			
		||||
public:
 | 
			
		||||
	LocationCoords() = default;
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +29,19 @@ public:
 | 
			
		|||
			MTP_long(_access));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	float64 lat() const {
 | 
			
		||||
		return _lat;
 | 
			
		||||
	}
 | 
			
		||||
	float64 lon() const {
 | 
			
		||||
		return _lon;
 | 
			
		||||
	}
 | 
			
		||||
	uint64 accessHash() const {
 | 
			
		||||
		return _access;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static QString asString(float64 value) {
 | 
			
		||||
		static constexpr auto kPrecision = 6;
 | 
			
		||||
		constexpr auto kPrecision = 6;
 | 
			
		||||
		return QString::number(value, 'f', kPrecision);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,14 +70,13 @@ private:
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct LocationData {
 | 
			
		||||
	LocationData(const LocationCoords &coords) : coords(coords), loading(false) {
 | 
			
		||||
	}
 | 
			
		||||
	LocationData(const LocationCoords &coords);
 | 
			
		||||
 | 
			
		||||
	LocationCoords coords;
 | 
			
		||||
	ImagePtr thumb;
 | 
			
		||||
	bool loading;
 | 
			
		||||
 | 
			
		||||
	void load(Data::FileOrigin origin);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LocationClickHandler : public ClickHandler {
 | 
			
		||||
| 
						 | 
				
			
			@ -99,31 +105,3 @@ private:
 | 
			
		|||
	QString _text;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LocationManager : public QObject {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	void init();
 | 
			
		||||
	void reinit();
 | 
			
		||||
	void deinit();
 | 
			
		||||
 | 
			
		||||
	void getData(LocationData *data);
 | 
			
		||||
 | 
			
		||||
	~LocationManager() {
 | 
			
		||||
		deinit();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
	void onFinished(QNetworkReply *reply);
 | 
			
		||||
	void onFailed(QNetworkReply *reply);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void failed(LocationData *data);
 | 
			
		||||
 | 
			
		||||
	QNetworkAccessManager *manager = nullptr;
 | 
			
		||||
	QMap<QNetworkReply*, LocationData*> dataLoadings, imageLoadings;
 | 
			
		||||
	QMap<LocationData*, int32> serverRedirects;
 | 
			
		||||
	ImagePtr *notLoadedPlaceholder = nullptr;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -147,7 +147,6 @@ Messenger::Messenger(not_null<Core::Launcher*> launcher)
 | 
			
		|||
 | 
			
		||||
	Shortcuts::start();
 | 
			
		||||
 | 
			
		||||
	initLocationManager();
 | 
			
		||||
	App::initMedia();
 | 
			
		||||
 | 
			
		||||
	Local::ReadMapState state = Local::readMap(QByteArray());
 | 
			
		||||
| 
						 | 
				
			
			@ -1030,7 +1029,6 @@ Messenger::~Messenger() {
 | 
			
		|||
 | 
			
		||||
	stopWebLoadManager();
 | 
			
		||||
	App::deinitMedia();
 | 
			
		||||
	deinitLocationManager();
 | 
			
		||||
 | 
			
		||||
	Window::Theme::Unload();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -559,6 +559,30 @@ mtpFileLoader::mtpFileLoader(
 | 
			
		|||
	_queue = &i.value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mtpFileLoader::mtpFileLoader(
 | 
			
		||||
	const GeoPointLocation *location,
 | 
			
		||||
	int32 size,
 | 
			
		||||
	LoadFromCloudSetting fromCloud,
 | 
			
		||||
	bool autoLoading,
 | 
			
		||||
	uint8 cacheTag)
 | 
			
		||||
: FileLoader(
 | 
			
		||||
	QString(),
 | 
			
		||||
	size,
 | 
			
		||||
	UnknownFileLocation,
 | 
			
		||||
	LoadToCacheAsWell,
 | 
			
		||||
	fromCloud,
 | 
			
		||||
	autoLoading,
 | 
			
		||||
	cacheTag)
 | 
			
		||||
, _dcId(Global::WebFileDcId())
 | 
			
		||||
, _geoLocation(location) {
 | 
			
		||||
	auto shiftedDcId = MTP::downloadDcId(_dcId, 0);
 | 
			
		||||
	auto i = queues.find(shiftedDcId);
 | 
			
		||||
	if (i == queues.cend()) {
 | 
			
		||||
		i = queues.insert(shiftedDcId, FileLoaderQueue(kMaxFileQueries));
 | 
			
		||||
	}
 | 
			
		||||
	_queue = &i.value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32 mtpFileLoader::currentOffset(bool includeSkipped) const {
 | 
			
		||||
	return (_fileIsOpen ? _file.size() : _data.size()) - (includeSkipped ? 0 : _skippedBytes);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -663,6 +687,25 @@ void mtpFileLoader::makeRequest(int offset) {
 | 
			
		|||
				rpcFail(&mtpFileLoader::partFailed),
 | 
			
		||||
				shiftedDcId,
 | 
			
		||||
				50);
 | 
			
		||||
		} else if (_geoLocation) {
 | 
			
		||||
			Assert(requestData.dcId == _dcId);
 | 
			
		||||
			return MTP::send(
 | 
			
		||||
				MTPupload_GetWebFile(
 | 
			
		||||
					MTP_inputWebFileGeoPointLocation(
 | 
			
		||||
						MTP_inputGeoPoint(
 | 
			
		||||
							MTP_double(_geoLocation->lat),
 | 
			
		||||
							MTP_double(_geoLocation->lon)),
 | 
			
		||||
						MTP_long(_geoLocation->access),
 | 
			
		||||
						MTP_int(_geoLocation->width),
 | 
			
		||||
						MTP_int(_geoLocation->height),
 | 
			
		||||
						MTP_int(_geoLocation->zoom),
 | 
			
		||||
						MTP_int(_geoLocation->scale)),
 | 
			
		||||
					MTP_int(offset),
 | 
			
		||||
					MTP_int(limit)),
 | 
			
		||||
				rpcDone(&mtpFileLoader::webPartLoaded),
 | 
			
		||||
				rpcFail(&mtpFileLoader::partFailed),
 | 
			
		||||
				shiftedDcId,
 | 
			
		||||
				50);
 | 
			
		||||
		} else {
 | 
			
		||||
			Assert(requestData.dcId == _dcId);
 | 
			
		||||
			return MTP::send(
 | 
			
		||||
| 
						 | 
				
			
			@ -1105,9 +1148,11 @@ void mtpFileLoader::changeCDNParams(
 | 
			
		|||
std::optional<Storage::Cache::Key> mtpFileLoader::cacheKey() const {
 | 
			
		||||
	if (_urlLocation) {
 | 
			
		||||
		return Data::WebDocumentCacheKey(*_urlLocation);
 | 
			
		||||
	} else if (_geoLocation) {
 | 
			
		||||
		return Data::GeoPointCacheKey(*_geoLocation);
 | 
			
		||||
	} else if (_location) {
 | 
			
		||||
		return Data::StorageCacheKey(*_location);
 | 
			
		||||
	} else if (_toCache == LoadToCacheAsWell) {
 | 
			
		||||
	} else if (_toCache == LoadToCacheAsWell && _id != 0) {
 | 
			
		||||
		return Data::DocumentCacheKey(_dcId, _id);
 | 
			
		||||
	}
 | 
			
		||||
	return std::nullopt;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -227,6 +227,12 @@ public:
 | 
			
		|||
		LoadFromCloudSetting fromCloud,
 | 
			
		||||
		bool autoLoading,
 | 
			
		||||
		uint8 cacheTag);
 | 
			
		||||
	mtpFileLoader(
 | 
			
		||||
		const GeoPointLocation *location,
 | 
			
		||||
		int32 size,
 | 
			
		||||
		LoadFromCloudSetting fromCloud,
 | 
			
		||||
		bool autoLoading,
 | 
			
		||||
		uint8 cacheTag);
 | 
			
		||||
 | 
			
		||||
	int32 currentOffset(bool includeSkipped = false) const override;
 | 
			
		||||
	Data::FileOrigin fileOrigin() const override;
 | 
			
		||||
| 
						 | 
				
			
			@ -306,6 +312,7 @@ private:
 | 
			
		|||
	QByteArray _fileReference;
 | 
			
		||||
 | 
			
		||||
	const WebFileLocation *_urlLocation = nullptr; // for webdocument locations
 | 
			
		||||
	const GeoPointLocation *_geoLocation = nullptr; // for webdocument locations
 | 
			
		||||
 | 
			
		||||
	Data::FileOrigin _origin;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -392,6 +392,9 @@ StorageImages storageImages;
 | 
			
		|||
using WebFileImages = QMap<StorageKey, WebFileImage*>;
 | 
			
		||||
WebFileImages webFileImages;
 | 
			
		||||
 | 
			
		||||
using GeoPointImages = QMap<StorageKey, GeoPointImage*>;
 | 
			
		||||
GeoPointImages geoPointImages;
 | 
			
		||||
 | 
			
		||||
int64 globalAcquiredSize = 0;
 | 
			
		||||
 | 
			
		||||
uint64 PixKey(int width, int height, Images::Options options) {
 | 
			
		||||
| 
						 | 
				
			
			@ -947,6 +950,9 @@ void clearStorageImages() {
 | 
			
		|||
	for (auto image : base::take(webFileImages)) {
 | 
			
		||||
		delete image;
 | 
			
		||||
	}
 | 
			
		||||
	for (auto image : base::take(geoPointImages)) {
 | 
			
		||||
		delete image;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clearAllImages() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1229,6 +1235,40 @@ FileLoader *WebFileImage::createLoader(
 | 
			
		|||
			Data::kImageCacheTag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GeoPointImage::GeoPointImage(const GeoPointLocation &location)
 | 
			
		||||
: _location(location) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<Storage::Cache::Key> GeoPointImage::cacheKey() const {
 | 
			
		||||
	return Data::GeoPointCacheKey(_location);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int GeoPointImage::countWidth() const {
 | 
			
		||||
	return _location.width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int GeoPointImage::countHeight() const {
 | 
			
		||||
	return _location.height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GeoPointImage::setInformation(int size, int width, int height) {
 | 
			
		||||
	_size = size;
 | 
			
		||||
	_location.width = width;
 | 
			
		||||
	_location.height = height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileLoader *GeoPointImage::createLoader(
 | 
			
		||||
		Data::FileOrigin origin,
 | 
			
		||||
		LoadFromCloudSetting fromCloud,
 | 
			
		||||
		bool autoLoading) {
 | 
			
		||||
	return new mtpFileLoader(
 | 
			
		||||
			&_location,
 | 
			
		||||
			_size,
 | 
			
		||||
			fromCloud,
 | 
			
		||||
			autoLoading,
 | 
			
		||||
			Data::kImageCacheTag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DelayedStorageImage::DelayedStorageImage() : StorageImage(StorageImageLocation())
 | 
			
		||||
, _loadRequested(false)
 | 
			
		||||
, _loadCancelled(false)
 | 
			
		||||
| 
						 | 
				
			
			@ -1571,6 +1611,17 @@ WebFileImage *getImage(
 | 
			
		|||
	return i.value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GeoPointImage *getImage(const GeoPointLocation &location) {
 | 
			
		||||
	auto key = storageKey(location);
 | 
			
		||||
	auto i = geoPointImages.constFind(key);
 | 
			
		||||
	if (i == geoPointImages.cend()) {
 | 
			
		||||
		i = geoPointImages.insert(
 | 
			
		||||
			key,
 | 
			
		||||
			new GeoPointImage(location));
 | 
			
		||||
	}
 | 
			
		||||
	return i.value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
 | 
			
		||||
ReadAccessEnabler::ReadAccessEnabler(const PsFileBookmark *bookmark)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -251,6 +251,34 @@ inline bool operator!=(const WebFileLocation &a, const WebFileLocation &b) {
 | 
			
		|||
	return !(a == b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct GeoPointLocation {
 | 
			
		||||
	float64 lat = 0.;
 | 
			
		||||
	float64 lon = 0.;
 | 
			
		||||
	uint64 access = 0;
 | 
			
		||||
	int32 width = 0;
 | 
			
		||||
	int32 height = 0;
 | 
			
		||||
	int32 zoom = 0;
 | 
			
		||||
	int32 scale = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool operator==(
 | 
			
		||||
		const GeoPointLocation &a,
 | 
			
		||||
		const GeoPointLocation &b) {
 | 
			
		||||
	return (a.lat == b.lat)
 | 
			
		||||
		&& (a.lon == b.lon)
 | 
			
		||||
		&& (a.access == b.access)
 | 
			
		||||
		&& (a.width == b.width)
 | 
			
		||||
		&& (a.height == b.height)
 | 
			
		||||
		&& (a.zoom == b.zoom)
 | 
			
		||||
		&& (a.scale == b.scale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(
 | 
			
		||||
		const GeoPointLocation &a,
 | 
			
		||||
		const GeoPointLocation &b) {
 | 
			
		||||
	return !(a == b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class DelayedStorageImage;
 | 
			
		||||
 | 
			
		||||
class HistoryItem;
 | 
			
		||||
| 
						 | 
				
			
			@ -450,6 +478,12 @@ inline StorageKey storageKey(const WebFileLocation &location) {
 | 
			
		|||
		*reinterpret_cast<const uint64*>(sha.data()),
 | 
			
		||||
		*reinterpret_cast<const int32*>(sha.data() + sizeof(uint64)));
 | 
			
		||||
}
 | 
			
		||||
inline StorageKey storageKey(const GeoPointLocation &location) {
 | 
			
		||||
	return StorageKey(
 | 
			
		||||
		(uint64(std::round(std::abs(location.lat + 360.) * 1000000)) << 32)
 | 
			
		||||
		| uint64(std::round(std::abs(location.lon + 360.) * 1000000)),
 | 
			
		||||
		(uint64(location.width) << 32) | uint64(location.height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class RemoteImage : public Image {
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -569,6 +603,27 @@ protected:
 | 
			
		|||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class GeoPointImage : public RemoteImage {
 | 
			
		||||
public:
 | 
			
		||||
	GeoPointImage(const GeoPointLocation &location);
 | 
			
		||||
 | 
			
		||||
	std::optional<Storage::Cache::Key> cacheKey() const override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	void setInformation(int size, int width, int height) override;
 | 
			
		||||
	FileLoader *createLoader(
 | 
			
		||||
		Data::FileOrigin origin,
 | 
			
		||||
		LoadFromCloudSetting fromCloud,
 | 
			
		||||
		bool autoLoading) override;
 | 
			
		||||
 | 
			
		||||
	int countWidth() const override;
 | 
			
		||||
	int countHeight() const override;
 | 
			
		||||
 | 
			
		||||
	GeoPointLocation _location;
 | 
			
		||||
	int _size = 0;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DelayedStorageImage : public StorageImage {
 | 
			
		||||
public:
 | 
			
		||||
	DelayedStorageImage();
 | 
			
		||||
| 
						 | 
				
			
			@ -668,6 +723,8 @@ WebFileImage *getImage(
 | 
			
		|||
	const WebFileLocation &location,
 | 
			
		||||
	QSize box,
 | 
			
		||||
	int size = 0);
 | 
			
		||||
GeoPointImage *getImage(
 | 
			
		||||
	const GeoPointLocation &location);
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -700,6 +757,9 @@ public:
 | 
			
		|||
	ImagePtr(const WebFileLocation &location, QSize box, int size = 0)
 | 
			
		||||
		: Parent(internal::getImage(location, box, size)) {
 | 
			
		||||
	}
 | 
			
		||||
	ImagePtr(const GeoPointLocation &location)
 | 
			
		||||
		: Parent(internal::getImage(location)) {
 | 
			
		||||
	}
 | 
			
		||||
	ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
 | 
			
		||||
	ImagePtr(int32 width, int32 height) : Parent(internal::getImage(width, height)) {
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue