From 2decaa19e312e52a1da3d4b7daa9ba9e4b14d82a Mon Sep 17 00:00:00 2001 From: VladiMihaylenko Date: Thu, 5 Apr 2018 14:42:10 +0300 Subject: [PATCH] [ios] Notification about unsent ugc --- .../MWMMapViewControlsManager.h | 2 + .../MWMMapViewControlsManager.mm | 5 ++ iphone/Maps/Classes/MapViewController.h | 1 + iphone/Maps/Classes/MapViewController.mm | 27 +++++++ iphone/Maps/Classes/MapsAppDelegate.mm | 12 +++ .../Notifications/LocalNotificationManager.h | 4 + .../Notifications/LocalNotificationManager.mm | 80 +++++++++++++++++++ map/cloud.cpp | 2 +- 8 files changed, 132 insertions(+), 1 deletion(-) diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h index 83f807bbd4..8432daa44f 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h @@ -33,6 +33,8 @@ class Info; #pragma mark - Layout +- (UIView *)anchorView; + - (void)mwm_refreshUI; - (void)viewWillTransitionToSize:(CGSize)size diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm index e74f8a8a39..8495bce7a4 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm @@ -89,6 +89,11 @@ extern NSString * const kAlohalyticsTapEventKey; #pragma mark - Layout +- (UIView *)anchorView +{ + return self.menuController.view; +} + - (void)mwm_refreshUI { [self.trafficButton mwm_refreshUI]; diff --git a/iphone/Maps/Classes/MapViewController.h b/iphone/Maps/Classes/MapViewController.h index d1b0f99f5b..0ec8d3da87 100644 --- a/iphone/Maps/Classes/MapViewController.h +++ b/iphone/Maps/Classes/MapViewController.h @@ -24,6 +24,7 @@ - (void)openEditor; - (void)openHotelFacilities; - (void)openBookmarkEditorWithData:(MWMPlacePageData *)data; +- (void)showUGCAuth; - (void)setPlacePageTopBound:(CGFloat)bound; diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 024a7a9a9e..5a982d0351 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -397,6 +397,33 @@ BOOL gIsFirstMyPositionMode = YES; [self performSegueWithIdentifier:kPP2BookmarkEditingSegue sender:data]; } +- (void)showUGCAuth +{ + [Statistics logEvent:kStatUGCReviewAuthShown]; + if (IPAD) + { + auto controller = [[MWMAuthorizationViewController alloc] + initWithPopoverSourceView:self.controlsManager.anchorView + sourceComponent:MWMAuthorizationSourceUGC + permittedArrowDirections:UIPopoverArrowDirectionDown + successHandler:nil + errorHandler:nil + completionHandler:nil]; + + [self presentViewController:controller animated:YES completion:nil]; + return; + } + + auto controller = [[MWMAuthorizationViewController alloc] + initWithBarButtonItem:nil + sourceComponent:MWMAuthorizationSourceUGC + successHandler:nil + errorHandler:nil + completionHandler:nil]; + + [self presentViewController:controller animated:YES completion:nil]; +} + - (void)processMyPositionStateModeEvent:(MWMMyPositionMode)mode { [MWMLocationManager setMyPositionMode:mode]; diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index 54e28fe709..d29e924724 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -393,6 +393,18 @@ using namespace osm_auth_ios; - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + auto onTap = ^{ + MapViewController * mapViewController = [MapViewController controller]; + [mapViewController.navigationController popToRootViewControllerAnimated:NO]; + [mapViewController showUGCAuth]; + }; + + if ([LocalNotificationManager.sharedManager showUGCNotificationIfNeeded:onTap]) + { + completionHandler(UIBackgroundFetchResultNewData); + return; + } + auto tasks = @[ [[MWMBackgroundStatisticsUpload alloc] init], [[MWMBackgroundEditsUpload alloc] init], [[MWMBackgroundUGCUpload alloc] init], [[MWMBackgroundDownloadMapNotification alloc] init] diff --git a/iphone/Maps/Core/Notifications/LocalNotificationManager.h b/iphone/Maps/Core/Notifications/LocalNotificationManager.h index bc25531f2f..09ad657f81 100644 --- a/iphone/Maps/Core/Notifications/LocalNotificationManager.h +++ b/iphone/Maps/Core/Notifications/LocalNotificationManager.h @@ -1,9 +1,13 @@ +#import "MWMTypes.h" + typedef void (^CompletionHandler)(UIBackgroundFetchResult); @interface LocalNotificationManager : NSObject + (instancetype)sharedManager; +- (BOOL)showUGCNotificationIfNeeded:(MWMVoidBlock)onTap; + - (void)showDownloadMapNotificationIfNeeded:(CompletionHandler)completionHandler; - (void)processNotification:(UILocalNotification *)notification onLaunch:(BOOL)onLaunch; diff --git a/iphone/Maps/Core/Notifications/LocalNotificationManager.mm b/iphone/Maps/Core/Notifications/LocalNotificationManager.mm index b830cb8399..5541a47d7e 100644 --- a/iphone/Maps/Core/Notifications/LocalNotificationManager.mm +++ b/iphone/Maps/Core/Notifications/LocalNotificationManager.mm @@ -10,8 +10,14 @@ #include "storage/country_info_getter.hpp" #include "storage/storage_helpers.hpp" +#include "map/framework_light.hpp" + +#include "platform/network_policy_ios.h" + namespace { +NSString * const kLocalNotificationNameKey = @"LocalNotificationName"; +NSString * const kUGCNotificationValue = @"UGC"; NSString * const kDownloadMapActionKey = @"DownloadMapActionKey"; NSString * const kDownloadMapActionName = @"DownloadMapActionName"; NSString * const kDownloadMapCountryId = @"DownloadMapCountryId"; @@ -20,6 +26,7 @@ NSString * const kFlagsKey = @"DownloadMapNotificationFlags"; NSTimeInterval constexpr kRepeatedNotificationIntervalInSeconds = 3 * 30 * 24 * 60 * 60; // three months +NSString * const kLastUGCNotificationDate = @"LastUGCNotificationDate"; } // namespace using namespace storage; @@ -29,6 +36,7 @@ using namespace storage; @property(nonatomic) CLLocationManager * locationManager; @property(copy, nonatomic) CompletionHandler downloadMapCompletionHandler; @property(weak, nonatomic) NSTimer * timer; +@property(copy, nonatomic) MWMVoidBlock onTap; @end @@ -44,6 +52,40 @@ using namespace storage; return manager; } ++ (BOOL)shouldShowUGCNotification +{ + if (!network_policy::CanUseNetwork()) + return NO; + + + auto ud = [NSUserDefaults standardUserDefaults]; + if (NSDate * date = [ud objectForKey:kLastUGCNotificationDate]) + { + auto calendar = [NSCalendar currentCalendar]; + auto components = [calendar components:NSCalendarUnitDay fromDate:date + toDate:[NSDate date] options:NSCalendarWrapComponents]; + + auto constexpr minDaysSinceLast = 5u; + if (components.day <= minDaysSinceLast) + return NO; + } + + using namespace lightweight; + lightweight::Framework f(REQUEST_TYPE_NUMBER_OF_UNSENT_UGC | REQUEST_TYPE_USER_AUTH_STATUS); + if (f.Get() || f.Get() < 2) + return NO; + + return YES; +} + ++ (void)UGCNotificationWasShown +{ + auto ud = [NSUserDefaults standardUserDefaults]; + [ud setObject:[NSDate date] forKey:kLastUGCNotificationDate]; + [ud synchronize]; + [Statistics logEvent:@"UGC_UnsentNotification_shown"]; +} + - (void)dealloc { _locationManager.delegate = nil; } - (void)processNotification:(UILocalNotification *)notification onLaunch:(BOOL)onLaunch { @@ -68,10 +110,48 @@ using namespace storage; GetFramework().ShowNode(countryId); }]; } + else if ([userInfo[kLocalNotificationNameKey] isEqualToString:kUGCNotificationValue]) + { + if (self.onTap) + self.onTap(); + + [Statistics logEvent:@"UGC_UnsentNotification_clicked"]; + } } #pragma mark - Location Notifications +- (BOOL)showUGCNotificationIfNeeded:(MWMVoidBlock)onTap +{ + auto application = UIApplication.sharedApplication; + auto identifier = UIBackgroundTaskInvalid; + auto handler = [&identifier] { + [[UIApplication sharedApplication] endBackgroundTask:identifier]; + }; + + identifier = [application beginBackgroundTaskWithExpirationHandler:^{ + handler(); + }]; + + if (![LocalNotificationManager shouldShowUGCNotification]) { + handler(); + return NO; + } + + self.onTap = onTap; + UILocalNotification * notification = [[UILocalNotification alloc] init]; + notification.alertTitle = L(@"notification_unsent_reviews_title"); + notification.alertBody = L(@"notification_unsent_reviews_message"); + notification.alertAction = L(@"authorization_button_sign_in"); + notification.soundName = UILocalNotificationDefaultSoundName; + notification.userInfo = @{kLocalNotificationNameKey : kUGCNotificationValue}; + + [application presentLocalNotificationNow:notification]; + [LocalNotificationManager UGCNotificationWasShown]; + handler(); + return YES; +} + - (void)showDownloadMapNotificationIfNeeded:(CompletionHandler)completionHandler { NSTimeInterval const completionTimeIndent = 2.0; diff --git a/map/cloud.cpp b/map/cloud.cpp index a5936a6331..9aef1158ba 100644 --- a/map/cloud.cpp +++ b/map/cloud.cpp @@ -1019,7 +1019,7 @@ Cloud::RequestResult Cloud::ExecuteUploading(UploadingResponseData const & respo urls.push_back(responseData.m_fallbackUrl); std::string errorStr; - int code; + int code = 0; for (size_t i = 0; i < urls.size(); ++i) { platform::HttpUploader request;