diff --git a/Sources/Controllers/Map/Widgets/OASunriseSunsetWidget.mm b/Sources/Controllers/Map/Widgets/OASunriseSunsetWidget.mm index 8ce0aeb11d..b8cfd9dca0 100644 --- a/Sources/Controllers/Map/Widgets/OASunriseSunsetWidget.mm +++ b/Sources/Controllers/Map/Widgets/OASunriseSunsetWidget.mm @@ -13,6 +13,10 @@ #import "Localization.h" #import "OsmAndApp.h" #import "OsmAnd_Maps-Swift.h" +#import "OAResourcesUIHelper.h" + +static const NSTimeInterval updateInterval = 60; +static const double locationChangeAccuracy = 0.0001; @implementation OASunriseSunsetWidget { @@ -20,6 +24,12 @@ @implementation OASunriseSunsetWidget OAAppSettings *_settings; OASunriseSunsetWidgetState *_state; NSArray *_items; + CLLocationCoordinate2D _cachedCenterLatLon; + NSTimeInterval _timeToNextUpdate; + NSTimeInterval _cachedNextTime; + NSTimeInterval _lastUpdateTime; + BOOL _isForceUpdate; + BOOL _isLocationChanged; } - (instancetype)initWithState:(OASunriseSunsetWidgetState *)state @@ -46,12 +56,17 @@ - (instancetype)initWithState:(OASunriseSunsetWidgetState *)state [self setText:@"-" subtext:@""]; [self setIcon:[_state getWidgetIconName]]; + _isForceUpdate = YES; } return self; } - (BOOL) updateInfo { + [self updateCachedLocation]; + if (![self isUpdateNeeded]) + return NO; + if ([self isShowTimeLeft]) { NSTimeInterval leftTime = [self getTimeLeft]; @@ -75,12 +90,34 @@ - (BOOL) updateInfo { [self setIcon:[_state getWidgetIconName]]; } - + + _isForceUpdate = NO; + _isLocationChanged = NO; + _lastUpdateTime = [[NSDate date] timeIntervalSince1970]; + NSTimeInterval timeDifference = _cachedNextTime - _lastUpdateTime; + if (timeDifference > updateInterval) + _timeToNextUpdate = timeDifference - floor(timeDifference / updateInterval) * updateInterval; + else + _timeToNextUpdate = timeDifference; + return YES; } +- (BOOL)isUpdateNeeded +{ + if (_isForceUpdate || _isLocationChanged) + return YES; + + NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970]; + if ([self isShowTimeLeft]) + return (_lastUpdateTime + _timeToNextUpdate) <= currentTime; + else + return _cachedNextTime <= currentTime; +} + - (void) onWidgetClicked { + _isForceUpdate = YES; if ([self isShowTimeLeft]) [[self getPreference] set:EOASunriseSunsetNext]; else @@ -319,20 +356,21 @@ - (NSTimeInterval)getNextTime { NSDateComponents *dayComponent = [[NSDateComponents alloc] init]; dayComponent.day = 1; - + NSCalendar *theCalendar = [NSCalendar currentCalendar]; nextTimeDate = [theCalendar dateByAddingComponents:dayComponent toDate:nextTimeDate options:0]; } - return nextTimeDate.timeIntervalSince1970; + _cachedNextTime = nextTimeDate.timeIntervalSince1970; + return _cachedNextTime; } + return 0; } - (SunriseSunset *) createSunriseSunset:(NSDate *)date { - CLLocation *location = OsmAndApp.instance.locationServices.lastKnownLocation; - double longitude = location.coordinate.longitude; - SunriseSunset *sunriseSunset = [[SunriseSunset alloc] initWithLatitude:location.coordinate.latitude longitude:longitude < 0 ? 360 + longitude : longitude dateInputIn:date tzIn:[NSTimeZone localTimeZone]]; + double longitude = _cachedCenterLatLon.longitude; + SunriseSunset *sunriseSunset = [[SunriseSunset alloc] initWithLatitude:_cachedCenterLatLon.latitude longitude:longitude < 0 ? 360 + longitude : longitude dateInputIn:date tzIn:[NSTimeZone localTimeZone]]; return sunriseSunset; } @@ -369,4 +407,19 @@ - (NSString *) formatNextTime:(NSTimeInterval)nextTime return [dateFormatter stringFromDate:nextDate]; } +- (void) updateCachedLocation +{ + CLLocationCoordinate2D newCenterLatLon = [OAResourcesUIHelper getMapLocation]; + if (![self isLocationsEqual:_cachedCenterLatLon with:newCenterLatLon]) + { + _cachedCenterLatLon = newCenterLatLon; + _isLocationChanged = YES; + } +} + +- (BOOL) isLocationsEqual:(CLLocationCoordinate2D)firstCoordinate with:(CLLocationCoordinate2D)secondCoordinate +{ + return [OAMapUtils areLatLonEqual:firstCoordinate coordinate2:secondCoordinate precision:locationChangeAccuracy]; +} + @end diff --git a/Sources/Helpers/OAMapUtils.h b/Sources/Helpers/OAMapUtils.h index cff06badc7..1ef629f1b3 100644 --- a/Sources/Helpers/OAMapUtils.h +++ b/Sources/Helpers/OAMapUtils.h @@ -48,6 +48,7 @@ + (BOOL)areLocationEqual:(CLLocation *)l1 l2:(CLLocation *)l2; + (BOOL)areLocationEqual:(CLLocation *)l lat:(CGFloat)lat lon:(CGFloat)lon; ++ (BOOL)areLatLonEqual:(CLLocationCoordinate2D)l1 coordinate2:(CLLocationCoordinate2D)l2 precision:(double)precision; + (BOOL)areLatLonEqual:(CLLocationCoordinate2D)l1 l2:(CLLocationCoordinate2D)l2; + (BOOL)areLatLonEqual:(CLLocationCoordinate2D)l lat:(CGFloat)lat lon:(CGFloat)lon; + (BOOL)areLatLonEqual:(CGFloat)lat1 lon1:(CGFloat)lon1 lat2:(CGFloat)lat2 lon2:(CGFloat)lon2; diff --git a/Sources/Helpers/OAMapUtils.mm b/Sources/Helpers/OAMapUtils.mm index e537e1c387..f23df36f10 100644 --- a/Sources/Helpers/OAMapUtils.mm +++ b/Sources/Helpers/OAMapUtils.mm @@ -362,6 +362,22 @@ + (BOOL)areLocationEqual:(CLLocation *)l lat:(CGFloat)lat lon:(CGFloat)lon return l != nil && [self areLatLonEqual:l.coordinate.latitude lon1:l.coordinate.longitude lat2:lat lon2:lon]; } ++ (BOOL)areLatLonEqual:(CLLocationCoordinate2D)l1 coordinate2:(CLLocationCoordinate2D)l2 precision:(double)precision +{ + if (!CLLocationCoordinate2DIsValid(l1) || !CLLocationCoordinate2DIsValid(l2)) + return NO; + + double lat1 = l1.latitude; + double lon1 = l1.longitude; + double lat2 = l2.latitude; + double lon2 = l2.longitude; + + BOOL latEqual = (isnan(lat1) && isnan(lat2)) || fabs(lat1 - lat2) < precision; + BOOL lonEqual = (isnan(lon1) && isnan(lon2)) || fabs(lon1 - lon2) < precision; + + return latEqual && lonEqual; +} + + (BOOL)areLatLonEqual:(CLLocationCoordinate2D)l1 l2:(CLLocationCoordinate2D)l2 { return (!CLLocationCoordinate2DIsValid(l1) && !CLLocationCoordinate2DIsValid(l2))