| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "platform/mac/current_geo_location_mac.h"
- #include "base/platform/mac/base_utilities_mac.h"
- #include "core/current_geo_location.h"
- #include <CoreLocation/CoreLocation.h>
- @interface LocationDelegate : NSObject<CLLocationManagerDelegate>
- - (id) initWithCallback:(Fn<void(Core::GeoLocation)>)callback;
- - (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations;
- - (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
- - (void) locationManager:(CLLocationManager *) manager didChangeAuthorizationStatus:(CLAuthorizationStatus) status;
- - (void) dealloc;
- @end
- @implementation LocationDelegate {
- CLLocationManager *_manager;
- Fn<void(Core::GeoLocation)> _callback;
- }
- - (void) fail {
- [_manager stopUpdatingLocation];
- const auto onstack = _callback;
- [self release];
- onstack({});
- }
- - (void) processWithStatus:(CLAuthorizationStatus)status {
- switch (status) {
- case kCLAuthorizationStatusNotDetermined:
- if (@available(macOS 10.15, *)) {
- [_manager requestWhenInUseAuthorization];
- } else {
- [_manager startUpdatingLocation];
- }
- break;
- case kCLAuthorizationStatusAuthorizedAlways:
- [_manager startUpdatingLocation];
- return;
- case kCLAuthorizationStatusRestricted:
- case kCLAuthorizationStatusDenied:
- default:
- [self fail];
- return;
- }
- }
- - (id) initWithCallback:(Fn<void(Core::GeoLocation)>)callback {
- if (self = [super init]) {
- _callback = std::move(callback);
- _manager = [[CLLocationManager alloc] init];
- _manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
- _manager.delegate = self;
- if ([CLLocationManager locationServicesEnabled]) {
- if (@available(macOS 11, *)) {
- [self processWithStatus:[_manager authorizationStatus]];
- } else {
- [self processWithStatus:[CLLocationManager authorizationStatus]];
- }
- } else {
- [self fail];
- }
- }
- return self;
- }
- - (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation*>*)locations {
- [_manager stopUpdatingLocation];
- auto result = Core::GeoLocation();
- if ([locations count] > 0) {
- const auto coordinate = [locations lastObject].coordinate;
- result.accuracy = Core::GeoLocationAccuracy::Exact;
- result.point = QPointF(coordinate.latitude, coordinate.longitude);
- }
- const auto onstack = _callback;
- [self release];
- onstack(result);
- }
- - (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
- if (error.code != kCLErrorLocationUnknown) {
- [self fail];
- }
- }
- - (void) locationManager:(CLLocationManager *) manager didChangeAuthorizationStatus:(CLAuthorizationStatus) status {
- [self processWithStatus:status];
- }
- - (void) dealloc {
- if (_manager) {
- _manager.delegate = nil;
- [_manager release];
- }
- [super dealloc];
- }
- @end
- namespace Platform {
- void ResolveCurrentExactLocation(Fn<void(Core::GeoLocation)> callback) {
- [[LocationDelegate alloc] initWithCallback:std::move(callback)];
- }
- void ResolveLocationAddress(
- const Core::GeoLocation &location,
- const QString &language,
- Fn<void(Core::GeoAddress)> callback) {
- CLGeocoder *geocoder = [[CLGeocoder alloc] init];
- CLLocation *request = [[CLLocation alloc]
- initWithLatitude:location.point.x()
- longitude:location.point.y()];
- [geocoder reverseGeocodeLocation:request completionHandler:^(
- NSArray<CLPlacemark*> * __nullable placemarks,
- NSError * __nullable error) {
- if (placemarks && [placemarks count] > 0) {
- CLPlacemark *placemark = [placemarks firstObject];
- auto list = QStringList();
- const auto push = [&](NSString *text) {
- if (text) {
- const auto qt = NS2QString(text);
- if (!qt.isEmpty()) {
- list.push_back(qt);
- }
- }
- };
- push([placemark thoroughfare]);
- push([placemark locality]);
- push([placemark country]);
- callback({ .name = list.join(u", "_q) });
- } else {
- callback({});
- }
- [geocoder release];
- }];
- [request release];
- }
- } // namespace Platform
|