diff --git a/README.md b/README.md
index 08ffce0..ef40859 100644
--- a/README.md
+++ b/README.md
@@ -120,9 +120,12 @@ To enable in-app reviews for the Samsung Galaxy Store, ensure that your app is c
- **Development Mode**: The in-app review dialog is always displayed in development mode, regardless of rate limits. This is useful for testing purposes.
- **Best Practices**: According to operating system guidelines, it is recommended to request a review during a natural flow in your app, rather than from a button. For example, you might request a review after a user has completed a task or achieved a milestone within your app.
-[Apple Documentation](https://developer.apple.com/documentation/storekit/skstorereviewcontroller/3566727-requestreview#discussion)
+[Apple Documentation iOS 14+](https://developer.apple.com/documentation/storekit/skstorereviewcontroller/3566727-requestreview#discussion)
+[Apple Documentation iOS 16+](https://developer.apple.com/documentation/storekit/requestreviewaction)
[Google Documentation](https://developer.android.com/guide/playcore/in-app-review)
+Below iOS 16 library is using the deprecated SKStoreReviewController and on iOS 16+ it uses the new RequestReviewAction API. Both implementations provide the same functionality and user experience.
+
### `RateApp.openStoreForReview(options)`
Opens the app store page for the app, allowing the user to leave a review.
diff --git a/RateApp.podspec b/RateApp.podspec
index 68bea15..4f55ced 100644
--- a/RateApp.podspec
+++ b/RateApp.podspec
@@ -14,7 +14,7 @@ Pod::Spec.new do |s|
s.platforms = { :ios => min_ios_version_supported }
s.source = { :git => "https://github.com/huextrat/react-native-rate-app.git", :tag => "#{s.version}" }
- s.source_files = "ios/**/*.{h,m,mm,cpp}"
+ s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
s.private_header_files = "ios/generated/**/*.h"
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 3b8d2ae..53f25eb 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -8,7 +8,7 @@ PODS:
- hermes-engine (0.78.0):
- hermes-engine/Pre-built (= 0.78.0)
- hermes-engine/Pre-built (0.78.0)
- - RateApp (1.2.2):
+ - RateApp (1.2.3):
- DoubleConversion
- glog
- hermes-engine
@@ -1769,7 +1769,7 @@ SPEC CHECKSUMS:
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8
hermes-engine: b417d2b2aee3b89b58e63e23a51e02be91dc876d
- RateApp: 4ae46fe22bc16dfa26d931ce1cb4968185eaa9d3
+ RateApp: d3cbe9933fd0ea0ce2b23522293bd99a85acf92b
RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82
RCTDeprecation: b2eecf2d60216df56bc5e6be5f063826d3c1ee35
RCTRequired: 78522de7dc73b81f3ed7890d145fa341f5bb32ea
diff --git a/example/src/App.tsx b/example/src/App.tsx
index 7597175..003983b 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -33,5 +33,6 @@ const styles = StyleSheet.create({
alignItems: "center",
justifyContent: "center",
gap: 8,
+ backgroundColor: "white",
},
});
diff --git a/ios/RateApp-Bridging-Header.h b/ios/RateApp-Bridging-Header.h
new file mode 100644
index 0000000..5a4bae0
--- /dev/null
+++ b/ios/RateApp-Bridging-Header.h
@@ -0,0 +1 @@
+#import
\ No newline at end of file
diff --git a/ios/RateApp.mm b/ios/RateApp.mm
index 2ea1dd4..f941d0b 100644
--- a/ios/RateApp.mm
+++ b/ios/RateApp.mm
@@ -1,55 +1,15 @@
-#import "RateApp.h"
-#import
+#import
-static NSString *const kNoActiveSceneError = @"no_active_scene";
-static NSString *const kUnsupportedPlatformError = @"unsupported_platform";
+@interface RCT_EXTERN_MODULE(RateApp, NSObject)
-@implementation RateApp
-RCT_EXPORT_MODULE()
-
-RCT_EXPORT_METHOD(requestReview:(RCTPromiseResolveBlock)resolve
+RCT_EXTERN_METHOD(requestReview:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
-{
- UIWindowScene *scene = [self findActiveScene];
- if (scene) {
- [SKStoreReviewController requestReviewInScene:scene];
- resolve(@(YES));
- } else {
- reject(kNoActiveSceneError, @"No active scene found", nil);
- }
-}
-RCT_EXPORT_METHOD(requestReviewAppGallery:(RCTPromiseResolveBlock)resolve
+RCT_EXTERN_METHOD(requestReviewAppGallery:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
-{
- // Since this is iOS, we should reject with an appropriate message
- reject(kUnsupportedPlatformError, @"App Gallery reviews are not supported on iOS", nil);
-}
-RCT_EXPORT_METHOD(requestReviewGalaxyStore:(NSString *)packageName
+RCT_EXTERN_METHOD(requestReviewGalaxyStore:(NSString *)packageName
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
-{
- // Since this is iOS, we should reject with an appropriate message
- reject(kUnsupportedPlatformError, @"Galaxy Store reviews are not supported on iOS", nil);
-}
-- (UIWindowScene *) findActiveScene {
- for (UIWindowScene *scene in UIApplication.sharedApplication.connectedScenes) {
- if (scene.activationState == UISceneActivationStateForegroundActive) {
- return scene;
- }
- }
- return nil;
-}
-
-// Don't compile this code when we build for the old architecture.
-#ifdef RCT_NEW_ARCH_ENABLED
-- (std::shared_ptr)getTurboModule:
- (const facebook::react::ObjCTurboModule::InitParams &)params
-{
- return std::make_shared(params);
-}
-#endif
-
-@end
+@end
\ No newline at end of file
diff --git a/ios/RateApp.swift b/ios/RateApp.swift
new file mode 100644
index 0000000..cb9363f
--- /dev/null
+++ b/ios/RateApp.swift
@@ -0,0 +1,50 @@
+import Foundation
+import StoreKit
+
+@objc(RateApp)
+class RateApp: NSObject {
+
+ private let noActiveSceneError = "no_active_scene"
+ private let unsupportedPlatformError = "unsupported_platform"
+
+ @objc
+ static func requiresMainQueueSetup() -> Bool {
+ return false
+ }
+
+ @objc
+ func requestReview(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+ if let scene = findActiveScene() {
+ if #available(iOS 16.0, *) {
+ Task { @MainActor in
+ AppStore.requestReview(in: scene)
+ }
+ } else {
+ SKStoreReviewController.requestReview(in: scene)
+ }
+ resolve(true)
+ } else {
+ reject(noActiveSceneError, "No active scene found", nil)
+ }
+ }
+
+ @objc
+ func requestReviewAppGallery(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+ reject(unsupportedPlatformError, "App Gallery reviews are not supported on iOS", nil)
+ }
+
+ @objc
+ func requestReviewGalaxyStore(_ packageName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+ reject(unsupportedPlatformError, "Galaxy Store reviews are not supported on iOS", nil)
+ }
+
+ private func findActiveScene() -> UIWindowScene? {
+ for scene in UIApplication.shared.connectedScenes {
+ if let windowScene = scene as? UIWindowScene,
+ windowScene.activationState == .foregroundActive {
+ return windowScene
+ }
+ }
+ return nil
+ }
+}
\ No newline at end of file