diff --git a/include.nmml b/include.nmml index 09e1a8d..b5e4e38 100644 --- a/include.nmml +++ b/include.nmml @@ -4,9 +4,13 @@ - + + + + + - \ No newline at end of file + diff --git a/ndll/iPhone/libHypRate.iphoneos-v7.a b/ndll/iPhone/libHypRate.iphoneos-v7.a index 83f9021..5974938 100644 Binary files a/ndll/iPhone/libHypRate.iphoneos-v7.a and b/ndll/iPhone/libHypRate.iphoneos-v7.a differ diff --git a/ndll/iPhone/libHypRate.iphoneos.a b/ndll/iPhone/libHypRate.iphoneos.a index b9ae4e0..cee5818 100644 Binary files a/ndll/iPhone/libHypRate.iphoneos.a and b/ndll/iPhone/libHypRate.iphoneos.a differ diff --git a/ndll/iPhone/libHypRate.iphonesim.a b/ndll/iPhone/libHypRate.iphonesim.a index b530613..7ea2978 100644 Binary files a/ndll/iPhone/libHypRate.iphonesim.a and b/ndll/iPhone/libHypRate.iphonesim.a differ diff --git a/project/Build.xml b/project/Build.xml index a6ab2b9..7819a43 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -46,6 +46,7 @@ + diff --git a/project/android/fr/hyperfiction/HypRate.java b/project/android/fr/hyperfiction/HypRate.java index e3a1956..52c5eeb 100644 --- a/project/android/fr/hyperfiction/HypRate.java +++ b/project/android/fr/hyperfiction/HypRate.java @@ -58,6 +58,16 @@ static public void show( ) { rmm.forceShow( ); } + /** + * + * + * @public + * @return void + */ + static public void setAppId( String appId ){ + trace("setAppId does nothing on Android"); + } + /** * * @@ -128,4 +138,4 @@ static public void setNegative_text( String s ){ public static void trace( String s ){ Log.w( TAG, "HypFacebookFrag ::: "+s ); } -} \ No newline at end of file +} diff --git a/project/common/ExternalInterface.cpp b/project/common/ExternalInterface.cpp index a766955..43bb9ec 100644 --- a/project/common/ExternalInterface.cpp +++ b/project/common/ExternalInterface.cpp @@ -35,46 +35,51 @@ extern "C"{ // iPhone --------------------------------------------------------------------------------------------------------- #ifdef IPHONE + value HypRate_setAppId( value s ) { + Hyperfiction::setAppId( val_string( s ) ); + return alloc_null( ); + } + DEFINE_PRIM( HypRate_setAppId , 1 ); value HypRate_setDialog_title( value s ) { - setDialog_title( val_string( s ) ); + Hyperfiction::setDialog_title( val_string( s ) ); return alloc_null( ); } DEFINE_PRIM( HypRate_setDialog_title , 1 ); value HypRate_setDialog_msg( value s ) { - setDialog_msg( val_string( s ) ); + Hyperfiction::setDialog_msg( val_string( s ) ); return alloc_null( ); } DEFINE_PRIM( HypRate_setDialog_msg , 1 ); value HypRate_setPositive_text( value s ) { - setPositive_text( val_string( s ) ); + Hyperfiction::setPositive_text( val_string( s ) ); return alloc_null( ); } DEFINE_PRIM( HypRate_setPositive_text , 1 ); value HypRate_setNeutral_text( value s ) { - setNeutral_text( val_string( s ) ); + Hyperfiction::setNeutral_text( val_string( s ) ); return alloc_null( ); } DEFINE_PRIM( HypRate_setNeutral_text , 1 ); value HypRate_setNegative_text( value s ) { - setCancel_text( val_string( s ) ); + Hyperfiction::setCancel_text( val_string( s ) ); return alloc_null( ); } DEFINE_PRIM( HypRate_setNegative_text , 1 ); value HypRate_start( value minL , value minD , value untilL , value untilD ){ - start( val_int( minL ) , val_int( minD ) , val_int( untilL ) , val_int( untilD )); + Hyperfiction::start( val_int( minL ) , val_int( minD ) , val_int( untilL ) , val_int( untilD )); return alloc_null( ); } DEFINE_PRIM( HypRate_start , 4 ); value HypRate_show( ){ - show( ); - return alloc_nul( ); + Hyperfiction::show( ); + return alloc_null( ); } DEFINE_PRIM( HypRate_show , 0 ); diff --git a/project/iPhone/HypRate.mm b/project/iPhone/HypRate.mm index 9d14af2..14f4148 100644 --- a/project/iPhone/HypRate.mm +++ b/project/iPhone/HypRate.mm @@ -11,8 +11,19 @@ */ #import #include +#include "include/Appirater.h" namespace Hyperfiction{ + /** + * + * + * @public + * @return void + */ + void setAppId( const char *s ){ + [Appirater setAppId:[[[NSString alloc] initWithUTF8String:s] autorelease]]; + } + /** * * @@ -62,7 +73,7 @@ void setNeutral_text( const char *s ){ void setCancel_text( const char *s ){ [Appirater setCancel_text:[[[NSString alloc] initWithUTF8String:s] autorelease]]; } - + /** * * @@ -70,11 +81,11 @@ void setCancel_text( const char *s ){ * @return void */ void start( int minL , int minD , int untilL , int unitD ){ - [Appirater setAppId:@"552035781"]; - [Appirater setDaysUntilPrompt:1]; - [Appirater setUsesUntilPrompt:10]; + [Appirater setUsesUntilPrompt:minL]; + [Appirater setDaysUntilPrompt:minD]; + // Disable significant event criterion [Appirater setSignificantEventsUntilPrompt:-1]; - [Appirater setTimeBeforeReminding:2]; + [Appirater setTimeBeforeReminding:unitD]; [Appirater setDebug:YES]; } @@ -85,8 +96,8 @@ void start( int minL , int minD , int untilL , int unitD ){ * @return void */ void show( ){ - //showPrompt( ) + [Appirater showPrompt]; } -} \ No newline at end of file +} diff --git a/project/iPhone/include/Appirater.h b/project/iPhone/include/Appirater.h old mode 100644 new mode 100755 index 3cb8d3a..8b0bb2b --- a/project/iPhone/include/Appirater.h +++ b/project/iPhone/include/Appirater.h @@ -1,9 +1,9 @@ /* This file is part of Appirater. - + Copyright (c) 2012, Arash Payan All rights reserved. - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without @@ -12,10 +12,10 @@ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -46,12 +46,52 @@ extern NSString *const kAppiraterRatedCurrentVersion; extern NSString *const kAppiraterDeclinedToRate; extern NSString *const kAppiraterReminderRequestDate; +/* + Your localized app's name. + */ +#define APPIRATER_LOCALIZED_APP_NAME [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"] + +/* + Your app's name. + */ +#define APPIRATER_APP_NAME APPIRATER_LOCALIZED_APP_NAME ? APPIRATER_LOCALIZED_APP_NAME : [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] + +/* + This is the message your users will see once they've passed the day+launches + threshold. + */ +#define APPIRATER_LOCALIZED_MESSAGE NSLocalizedStringFromTableInBundle(@"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_MESSAGE [NSString stringWithFormat:APPIRATER_LOCALIZED_MESSAGE, APPIRATER_APP_NAME] + +/* + This is the title of the message alert that users will see. + */ +#define APPIRATER_LOCALIZED_MESSAGE_TITLE NSLocalizedStringFromTableInBundle(@"Rate %@", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_MESSAGE_TITLE [NSString stringWithFormat:APPIRATER_LOCALIZED_MESSAGE_TITLE, APPIRATER_APP_NAME] + +/* + The text of the button that rejects reviewing the app. + */ +#define APPIRATER_CANCEL_BUTTON NSLocalizedStringFromTableInBundle(@"No, Thanks", @"AppiraterLocalizable", [Appirater bundle], nil) + +/* + Text of button that will send user to app review page. + */ +#define APPIRATER_LOCALIZED_RATE_BUTTON NSLocalizedStringFromTableInBundle(@"Rate %@", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_RATE_BUTTON [NSString stringWithFormat:APPIRATER_LOCALIZED_RATE_BUTTON, APPIRATER_APP_NAME] + +/* + Text for button to remind the user to review later. + */ +#define APPIRATER_RATE_LATER NSLocalizedStringFromTableInBundle(@"Remind me later", @"AppiraterLocalizable", [Appirater bundle], nil) + @interface Appirater : NSObject { UIAlertView *ratingAlert; } @property(nonatomic, strong) UIAlertView *ratingAlert; +@property(nonatomic) BOOL openInAppStore; #if __has_feature(objc_arc_weak) @property(nonatomic, weak) NSObject *delegate; #else @@ -63,7 +103,7 @@ extern NSString *const kAppiraterReminderRequestDate; support multitasking, the 'uses' count will be incremented. You should call this method at the end of your application delegate's application:didFinishLaunchingWithOptions: method. - + If the app has been used enough to be rated (and enough significant events), you can suppress the rating alert by passing NO for canPromptForRating. The rating alert will simply be postponed @@ -77,7 +117,7 @@ extern NSString *const kAppiraterReminderRequestDate; Tells Appirater that the app was brought to the foreground on multitasking devices. You should call this method from the application delegate's applicationWillEnterForeground: method. - + If the app has been used enough to be rated (and enough significant events), you can suppress the rating alert by passing NO for canPromptForRating. The rating alert will simply be postponed @@ -93,7 +133,7 @@ extern NSString *const kAppiraterReminderRequestDate; calls, then you might want to call this method whenever the user places a call. If it's a game, you might want to call this whenever the user beats a level boss. - + If the user has performed enough significant events and used the app enough, you can suppress the rating alert by passing NO for canPromptForRating. The rating alert will simply be postponed until it is called again with YES for @@ -107,7 +147,7 @@ extern NSString *const kAppiraterReminderRequestDate; Tells Appirater to show the prompt (a rating alert). The prompt will be showed if there is connection available, the user hasn't declined to rate or hasn't rated current version. - + You could call to show the prompt regardless Appirater settings, e.g., in case of some special event in your app. */ @@ -152,7 +192,7 @@ extern NSString *const kAppiraterReminderRequestDate; a 'use'. You tell Appirater about these events using the two methods: [Appirater appLaunched:] [Appirater appEnteredForeground:] - + Users need to 'use' the same version of the app this many times before before they will be prompted to rate it. */ @@ -200,23 +240,36 @@ extern NSString *const kAppiraterReminderRequestDate; */ + (void)setOpenInAppStore:(BOOL)openInAppStore; -+(void) setCancel_text:(NSString)value; -+(void) setRate_text:(NSString)value; -+(void) setMsg_text:(NSString)value; -+(void) setRate_text:(NSString)value; -+(void) setTitle_text:(NSString)value; +/* + If set to YES, the main bundle will always be used to load localized strings. + Set this to YES if you have provided your own custom localizations in AppiraterLocalizable.strings + in your main bundle. Default is NO. + */ ++ (void)setAlwaysUseMainBundle:(BOOL)useMainBundle; @end +/* + Methods in this interface are public out of necessity, but may change without notice + */ +@interface Appirater(Unsafe) + +/* + The bundle localized strings will be loaded from. +*/ ++(NSBundle *)bundle; + +@end + @interface Appirater(Deprecated) /* DEPRECATED: While still functional, it's better to use appLaunched:(BOOL)canPromptForRating instead. - + Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality. */ -+ (void)appLaunched __attribute__((deprecated)); ++ (void)appLaunched __attribute__((deprecated)); @end diff --git a/project/iPhone/include/Appirater.m b/project/iPhone/include/Appirater.m old mode 100644 new mode 100755 index adb760d..d80c589 --- a/project/iPhone/include/Appirater.m +++ b/project/iPhone/include/Appirater.m @@ -1,9 +1,9 @@ /* This file is part of Appirater. - + Copyright (c) 2012, Arash Payan All rights reserved. - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without @@ -12,10 +12,10 @@ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -51,6 +51,7 @@ NSString *const kAppiraterReminderRequestDate = @"kAppiraterReminderRequestDate"; NSString *templateReviewURL = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID"; +NSString *templateReviewURLiOS7 = @"itms-apps://itunes.apple.com/app/idAPP_ID"; static NSString *_appId; static double _daysUntilPrompt = 30; @@ -58,17 +59,15 @@ static NSInteger _significantEventsUntilPrompt = -1; static double _timeBeforeReminding = 1; static BOOL _debug = NO; -static id _delegate; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 + static id _delegate; +#else + __weak static id _delegate; +#endif static BOOL _usesAnimation = TRUE; -static BOOL _openInAppStore = NO; static UIStatusBarStyle _statusBarStyle; static BOOL _modalOpen = false; - -static NSString *APPIRATER_CANCEL_BUTTON = ""; -static NSString *APPIRATER_RATE_BUTTON = ""; -static NSString *APPIRATER_MESSAGE = ""; -static NSString *APPIRATER_RATE_LATER = ""; -static NSString *APPIRATER_MESSAGE_TITLE = ""; +static BOOL _alwaysUseMainBundle = NO; @interface Appirater () - (BOOL)connectedToNetwork; @@ -79,7 +78,7 @@ - (void)incrementUseCount; - (void)hideRatingAlert; @end -@implementation Appirater +@implementation Appirater @synthesize ratingAlert; @@ -113,7 +112,7 @@ + (void)setUsesAnimation:(BOOL)animation { _usesAnimation = animation; } + (void)setOpenInAppStore:(BOOL)openInAppStore { - _openInAppStore = openInAppStore; + [Appirater sharedInstance].openInAppStore = openInAppStore; } + (void)setStatusBarStyle:(UIStatusBarStyle)style { _statusBarStyle = style; @@ -121,25 +120,41 @@ + (void)setStatusBarStyle:(UIStatusBarStyle)style { + (void)setModalOpen:(BOOL)open { _modalOpen = open; } - -+(void) setCancel_text:(NSString)value{ - APPIRATER_CANCEL_BUTTON = value; -} -+(void) setRate_text:(NSString)value{ - APPIRATER_RATE_BUTTON = value; ++ (void)setAlwaysUseMainBundle:(BOOL)alwaysUseMainBundle { + _alwaysUseMainBundle = alwaysUseMainBundle; } -+(void) setMsg_text:(NSString)value{ - APPIRATER_MESSAGE = value; -} -+(void) setRate_text:(NSString)value{ - APPIRATER_MESSAGE = value; -} -+(void) setTitle_text:(NSString)value{ - APPIRATER_MESSAGE_TITLE = value; + ++ (NSBundle *)bundle +{ + NSBundle *bundle; + + if (_alwaysUseMainBundle) { + bundle = [NSBundle mainBundle]; + } else { + NSURL *appiraterBundleURL = [[NSBundle mainBundle] URLForResource:@"Appirater" withExtension:@"bundle"]; + + if (appiraterBundleURL) { + // Appirater.bundle will likely only exist when used via CocoaPods + bundle = [NSBundle bundleWithURL:appiraterBundleURL]; + } else { + bundle = [NSBundle mainBundle]; + } + } + + return bundle; } -+(void) setNeutral_text:(NSString)value{ - APPIRATER_RATE_LATER = value, +- (id)init { + self = [super init]; + if (self) { + if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) { + self.openInAppStore = YES; + } else { + self.openInAppStore = NO; + } + } + + return self; } - (BOOL)connectedToNetwork { @@ -148,28 +163,28 @@ - (BOOL)connectedToNetwork { bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; - + // Recover reachability flags SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); SCNetworkReachabilityFlags flags; - + BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); CFRelease(defaultRouteReachability); - + if (!didRetrieveFlags) { NSLog(@"Error. Could not recover network reachability flags"); return NO; } - + BOOL isReachable = flags & kSCNetworkFlagsReachable; BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired; BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection; - + NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"]; NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0]; NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self]; - + return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO; } @@ -185,7 +200,7 @@ + (Appirater*)sharedInstance { UIApplicationWillResignActiveNotification object:nil]; }); } - + return appirater; } @@ -196,57 +211,58 @@ - (void)showRatingAlert { cancelButtonTitle:APPIRATER_CANCEL_BUTTON otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil]; self.ratingAlert = alertView; - [alertView show]; + [alertView show]; - if(self.delegate && [self.delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]){ - [self.delegate appiraterDidDisplayAlert:self]; - } + id delegate = _delegate; + if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]) { + [delegate appiraterDidDisplayAlert:self]; + } } - (BOOL)ratingConditionsHaveBeenMet { if (_debug) return YES; - + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - + NSDate *dateOfFirstLaunch = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterFirstUseDate]]; NSTimeInterval timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch]; NSTimeInterval timeUntilRate = 60 * 60 * 24 * _daysUntilPrompt; if (timeSinceFirstLaunch < timeUntilRate) return NO; - + // check if the app has been used enough int useCount = [userDefaults integerForKey:kAppiraterUseCount]; if (useCount <= _usesUntilPrompt) return NO; - + // check if the user has done enough significant events int sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; if (sigEventCount <= _significantEventsUntilPrompt) return NO; - + // has the user previously declined to rate this version of the app? if ([userDefaults boolForKey:kAppiraterDeclinedToRate]) return NO; - + // has the user already rated the app? if ([self userHasRatedCurrentVersion]) return NO; - + // if the user wanted to be reminded later, has enough time passed? NSDate *reminderRequestDate = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterReminderRequestDate]]; NSTimeInterval timeSinceReminderRequest = [[NSDate date] timeIntervalSinceDate:reminderRequestDate]; NSTimeInterval timeUntilReminder = 60 * 60 * 24 * _timeBeforeReminding; if (timeSinceReminderRequest < timeUntilReminder) return NO; - + return YES; } - (void)incrementUseCount { // get the app's version NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; - + // get the version number that we've been tracking NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion]; @@ -255,10 +271,10 @@ - (void)incrementUseCount { trackingVersion = version; [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; } - + if (_debug) NSLog(@"APPIRATER Tracking version: %@", trackingVersion); - + if ([trackingVersion isEqualToString:version]) { // check if the first use date has been set. if not, set it. @@ -268,7 +284,7 @@ - (void)incrementUseCount { timeInterval = [[NSDate date] timeIntervalSince1970]; [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; } - + // increment the use count int useCount = [userDefaults integerForKey:kAppiraterUseCount]; useCount++; @@ -287,14 +303,14 @@ - (void)incrementUseCount { [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } - + [userDefaults synchronize]; } - (void)incrementSignificantEventCount { // get the app's version NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; - + // get the version number that we've been tracking NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion]; @@ -303,10 +319,10 @@ - (void)incrementSignificantEventCount { trackingVersion = version; [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; } - + if (_debug) NSLog(@"APPIRATER Tracking version: %@", trackingVersion); - + if ([trackingVersion isEqualToString:version]) { // check if the first use date has been set. if not, set it. @@ -316,7 +332,7 @@ - (void)incrementSignificantEventCount { timeInterval = [[NSDate date] timeIntervalSince1970]; [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; } - + // increment the significant event count int sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; sigEventCount++; @@ -335,13 +351,13 @@ - (void)incrementSignificantEventCount { [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } - + [userDefaults synchronize]; } - (void)incrementAndRate:(BOOL)canPromptForRating { [self incrementUseCount]; - + if (canPromptForRating && [self ratingConditionsHaveBeenMet] && [self connectedToNetwork]) @@ -355,7 +371,7 @@ - (void)incrementAndRate:(BOOL)canPromptForRating { - (void)incrementSignificantEventAndRate:(BOOL)canPromptForRating { [self incrementSignificantEventCount]; - + if (canPromptForRating && [self ratingConditionsHaveBeenMet] && [self connectedToNetwork]) @@ -391,7 +407,7 @@ - (void)hideRatingAlert { if (_debug) NSLog(@"APPIRATER Hiding Alert"); [self.ratingAlert dismissWithClickedButtonIndex:-1 animated:NO]; - } + } } + (void)appWillResignActive { @@ -432,7 +448,7 @@ + (id)getRootViewController { } } } - + for (UIView *subView in [window subviews]) { UIResponder *responder = [subView nextResponder]; @@ -440,7 +456,7 @@ + (id)getRootViewController { return [self topMostViewController: (UIViewController *) responder]; } } - + return nil; } @@ -453,42 +469,52 @@ + (UIViewController *) topMostViewController: (UIViewController *) controller { if(presented != nil) { controller = presented; } - + } while (isPresenting); - + return controller; } + (void)rateApp { - + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion]; [userDefaults synchronize]; //Use the in-app StoreKit view if available (iOS 6) and imported. This works in the simulator. - if (!_openInAppStore && NSStringFromClass([SKStoreProductViewController class]) != nil) { - + if (![Appirater sharedInstance].openInAppStore && NSStringFromClass([SKStoreProductViewController class]) != nil) { + SKStoreProductViewController *storeViewController = [[SKStoreProductViewController alloc] init]; NSNumber *appId = [NSNumber numberWithInteger:_appId.integerValue]; [storeViewController loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier:appId} completionBlock:nil]; storeViewController.delegate = self.sharedInstance; - if ([self.sharedInstance.delegate respondsToSelector:@selector(appiraterWillPresentModalView:animated:)]) { - [self.sharedInstance.delegate appiraterWillPresentModalView:self.sharedInstance animated:_usesAnimation]; + + id delegate = self.sharedInstance.delegate; + if ([delegate respondsToSelector:@selector(appiraterWillPresentModalView:animated:)]) { + [delegate appiraterWillPresentModalView:self.sharedInstance animated:_usesAnimation]; } [[self getRootViewController] presentViewController:storeViewController animated:_usesAnimation completion:^{ [self setModalOpen:YES]; //Temporarily use a black status bar to match the StoreKit view. [self setStatusBarStyle:[UIApplication sharedApplication].statusBarStyle]; - [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:_usesAnimation]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent animated:_usesAnimation]; +#endif }]; - + //Use the standard openUrl method if StoreKit is unavailable. } else { - + #if TARGET_IPHONE_SIMULATOR NSLog(@"APPIRATER NOTE: iTunes App Store is not supported on the iOS simulator. Unable to open App Store page."); #else NSString *reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]]; + + // iOS 7 needs a different templateReviewURL @see https://github.com/arashpayan/appirater/issues/131 + if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { + reviewURL = [templateReviewURLiOS7 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]]; + } + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:reviewURL]]; #endif } @@ -496,15 +522,17 @@ + (void)rateApp { - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - + + id delegate = _delegate; + switch (buttonIndex) { case 0: { // they don't want to rate it [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; [userDefaults synchronize]; - if(self.delegate && [self.delegate respondsToSelector:@selector(appiraterDidDeclineToRate:)]){ - [self.delegate appiraterDidDeclineToRate:self]; + if(delegate && [delegate respondsToSelector:@selector(appiraterDidDeclineToRate:)]){ + [delegate appiraterDidDeclineToRate:self]; } break; } @@ -512,8 +540,8 @@ - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger) { // they want to rate it [Appirater rateApp]; - if(self.delegate && [self.delegate respondsToSelector:@selector(appiraterDidOptToRate:)]){ - [self.delegate appiraterDidOptToRate:self]; + if(delegate&& [delegate respondsToSelector:@selector(appiraterDidOptToRate:)]){ + [delegate appiraterDidOptToRate:self]; } break; } @@ -521,8 +549,8 @@ - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger) // remind them later [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterReminderRequestDate]; [userDefaults synchronize]; - if(self.delegate && [self.delegate respondsToSelector:@selector(appiraterDidOptToRemindLater:)]){ - [self.delegate appiraterDidOptToRemindLater:self]; + if(delegate && [delegate respondsToSelector:@selector(appiraterDidOptToRemindLater:)]){ + [delegate appiraterDidOptToRemindLater:self]; } break; default: @@ -541,13 +569,14 @@ + (void)closeModal { [[UIApplication sharedApplication]setStatusBarStyle:_statusBarStyle animated:_usesAnimation]; BOOL usedAnimation = _usesAnimation; [self setModalOpen:NO]; - + // get the top most controller (= the StoreKit Controller) and dismiss it UIViewController *presentingController = [UIApplication sharedApplication].keyWindow.rootViewController; presentingController = [self topMostViewController: presentingController]; [presentingController dismissViewControllerAnimated:_usesAnimation completion:^{ - if ([self.sharedInstance.delegate respondsToSelector:@selector(appiraterDidDismissModalView:animated:)]) { - [self.sharedInstance.delegate appiraterDidDismissModalView:(Appirater *)self animated:usedAnimation]; + id delegate = self.sharedInstance.delegate; + if ([delegate respondsToSelector:@selector(appiraterDidDismissModalView:animated:)]) { + [delegate appiraterDidDismissModalView:(Appirater *)self animated:usedAnimation]; } }]; [self.class setStatusBarStyle:(UIStatusBarStyle)nil]; diff --git a/project/iPhone/include/AppiraterDelegate.h b/project/iPhone/include/AppiraterDelegate.h new file mode 100755 index 0000000..d7722d3 --- /dev/null +++ b/project/iPhone/include/AppiraterDelegate.h @@ -0,0 +1,22 @@ +// +// AppiraterDelegate.h +// Banana Stand +// +// Created by Robert Haining on 9/25/12. +// Copyright (c) 2012 News.me. All rights reserved. +// + +#import + +@class Appirater; + +@protocol AppiraterDelegate + +@optional +-(void)appiraterDidDisplayAlert:(Appirater *)appirater; +-(void)appiraterDidDeclineToRate:(Appirater *)appirater; +-(void)appiraterDidOptToRate:(Appirater *)appirater; +-(void)appiraterDidOptToRemindLater:(Appirater *)appirater; +-(void)appiraterWillPresentModalView:(Appirater *)appirater animated:(BOOL)animated; +-(void)appiraterDidDismissModalView:(Appirater *)appirater animated:(BOOL)animated; +@end diff --git a/project/include/HypRate.h b/project/include/HypRate.h index 477bf55..6eb20e1 100644 --- a/project/include/HypRate.h +++ b/project/include/HypRate.h @@ -13,6 +13,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #define Device namespace Hyperfiction{ + void setAppId( const char *s ); void setDialog_title( const char *s ); void setDialog_msg( const char *s ); void setPositive_text( const char *s ); @@ -22,4 +23,4 @@ namespace Hyperfiction{ void show( ); } -#endif \ No newline at end of file +#endif diff --git a/project/iphone.sh b/project/iphone.sh old mode 100644 new mode 100755 diff --git a/project/obj/iphoneos-v7/iPhone/HypRate.o b/project/obj/iphoneos-v7/iPhone/HypRate.o index 72c4f36..819323a 100644 Binary files a/project/obj/iphoneos-v7/iPhone/HypRate.o and b/project/obj/iphoneos-v7/iPhone/HypRate.o differ diff --git a/project/obj/iphoneos/iPhone/HypRate.o b/project/obj/iphoneos/iPhone/HypRate.o index a43b304..339ab4e 100644 Binary files a/project/obj/iphoneos/iPhone/HypRate.o and b/project/obj/iphoneos/iPhone/HypRate.o differ diff --git a/project/obj/iphonesim/iPhone/HypRate.o b/project/obj/iphonesim/iPhone/HypRate.o index 636361d..4571d3a 100644 Binary files a/project/obj/iphonesim/iPhone/HypRate.o and b/project/obj/iphonesim/iPhone/HypRate.o differ diff --git a/src/fr/hyperfiction/HypRate.hx b/src/fr/hyperfiction/HypRate.hx index 24317d1..a4699ca 100644 --- a/src/fr/hyperfiction/HypRate.hx +++ b/src/fr/hyperfiction/HypRate.hx @@ -30,6 +30,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_start") + #end static public function start( iMin_launches : Int, iMin_days : Int, @@ -37,6 +40,22 @@ class HypRate{ iMin_days_until_next : Int ) : Void { } + + /** + * + * + * @public + * @return void + */ + #if android + @JNI + #end + #if ios + @CPP("HypRate", "HypRate_setAppId") + #end + static public function setAppId( appId : String ) : Void { + + } /** * @@ -47,6 +66,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_setDialog_title") + #end static public function setDialog_title( s : String ) : Void { } @@ -60,6 +82,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_setDialog_message") + #end static public function setDialog_message( s : String ) : Void { } @@ -73,6 +98,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_setPositive_text") + #end static public function setPositive_text( s : String ) : Void { } @@ -86,6 +114,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_setNeutral_text") + #end static public function setNeutral_text( s : String ) : Void { } @@ -99,6 +130,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_setNegative_text") + #end static public function setNegative_text( s : String ) : Void { } @@ -113,6 +147,9 @@ class HypRate{ #if android @JNI #end + #if ios + @CPP("HypRate", "HypRate_show") + #end static public function show( ) : Void { } @@ -123,4 +160,4 @@ class HypRate{ // -------o misc -} \ No newline at end of file +}