diff --git a/ios/StandardNotes.xcodeproj/project.pbxproj b/ios/StandardNotes.xcodeproj/project.pbxproj index e743e542..d5de5a60 100644 --- a/ios/StandardNotes.xcodeproj/project.pbxproj +++ b/ios/StandardNotes.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 2DCD954D1E0B4F2C00145EB5 /* StandardNotesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* StandardNotesTests.m */; }; 40F325481D4F4F04AC15D0A9 /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 48127930FB1344778C168838 /* libRNVectorIcons.a */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; + 6C1915C4DE9040A9BB17CFBB /* libRNStoreReview.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADB6F6B9BC7144FCB2C08D40 /* libRNStoreReview.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 965031D980094619B7DBA0FD /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1F569402A90047A59845394A /* Ionicons.ttf */; }; 9A2C235D0ABA4B0CB9A428CA /* libRNKeychain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDCF33ADCFE845D588CC4E66 /* libRNKeychain.a */; }; @@ -253,6 +254,13 @@ remoteGlobalIDString = CD2830C11F795AB7002B9529; remoteInfo = SNTextView; }; + CD4D91841F7BE11800080678 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5C13FDBBDDEE4F1285F88B41 /* RNStoreReview.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RNStoreReview; + }; CD885F771F70228400B91C20 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 737AF67874434967865855D8 /* BugsnagReactNative.xcodeproj */; @@ -386,12 +394,14 @@ 48127930FB1344778C168838 /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = ""; }; 54ED130E749A46A3B15B27F2 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; }; 59DCF8530F2945FFAA0300FD /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; }; + 5C13FDBBDDEE4F1285F88B41 /* RNStoreReview.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNStoreReview.xcodeproj; path = "../node_modules/react-native-store-review/ios/RNStoreReview.xcodeproj"; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 6314B32C63AC4827A9329AA6 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = ""; }; 6F30913DACE34E71895FBF91 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 737AF67874434967865855D8 /* BugsnagReactNative.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = BugsnagReactNative.xcodeproj; path = "../node_modules/bugsnag-react-native/cocoa/BugsnagReactNative.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + ADB6F6B9BC7144FCB2C08D40 /* libRNStoreReview.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNStoreReview.a; sourceTree = ""; }; ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; B5409EE82FED4DA9B57CA746 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; }; CD17664C1F795AE500165C83 /* SNTextView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SNTextView.xcodeproj; path = "../vendor/sn-textview/ios/SNTextView.xcodeproj"; sourceTree = ""; }; @@ -440,6 +450,7 @@ 40F325481D4F4F04AC15D0A9 /* libRNVectorIcons.a in Frameworks */, F0D84FDB75374348BC0017C2 /* libBugsnagReactNative.a in Frameworks */, C00E89E3E7F949A4AA0F613E /* libz.tbd in Frameworks */, + 6C1915C4DE9040A9BB17CFBB /* libRNStoreReview.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -638,6 +649,7 @@ 0BA1C89777414706A3F02AC6 /* RNKeychain.xcodeproj */, 54ED130E749A46A3B15B27F2 /* RNVectorIcons.xcodeproj */, 737AF67874434967865855D8 /* BugsnagReactNative.xcodeproj */, + 5C13FDBBDDEE4F1285F88B41 /* RNStoreReview.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -695,6 +707,14 @@ name = Products; sourceTree = ""; }; + CD4D91811F7BE11800080678 /* Products */ = { + isa = PBXGroup; + children = ( + CD4D91851F7BE11800080678 /* libRNStoreReview.a */, + ); + name = Products; + sourceTree = ""; + }; CD885F741F70228400B91C20 /* Products */ = { isa = PBXGroup; children = ( @@ -758,6 +778,7 @@ CDCF33ADCFE845D588CC4E66 /* libRNKeychain.a */, 48127930FB1344778C168838 /* libRNVectorIcons.a */, EFD3F9197A5F41C0904D7E60 /* libBugsnagReactNative.a */, + ADB6F6B9BC7144FCB2C08D40 /* libRNStoreReview.a */, ); name = "Recovered References"; sourceTree = ""; @@ -966,6 +987,10 @@ ProductGroup = CDB58A111F6C5178009EF868 /* Products */; ProjectRef = CDB58A101F6C5178009EF868 /* RNMail.xcodeproj */; }, + { + ProductGroup = CD4D91811F7BE11800080678 /* Products */; + ProjectRef = 5C13FDBBDDEE4F1285F88B41 /* RNStoreReview.xcodeproj */; + }, { ProductGroup = CDB58A641F6C5294009EF868 /* Products */; ProjectRef = 54ED130E749A46A3B15B27F2 /* RNVectorIcons.xcodeproj */; @@ -1175,6 +1200,13 @@ remoteRef = CD1766771F795AE500165C83 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + CD4D91851F7BE11800080678 /* libRNStoreReview.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNStoreReview.a; + remoteRef = CD4D91841F7BE11800080678 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; CD885F781F70228400B91C20 /* libBugsnagReactNative.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1416,6 +1448,7 @@ "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/bugsnag-react-native/cocoa/**", + "$(SRCROOT)/../node_modules/react-native-store-review/ios", ); INFOPLIST_FILE = StandardNotesTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1425,6 +1458,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1446,6 +1480,7 @@ "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/bugsnag-react-native/cocoa/**", + "$(SRCROOT)/../node_modules/react-native-store-review/ios", ); INFOPLIST_FILE = StandardNotesTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1455,6 +1490,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1480,6 +1516,7 @@ "$(SRCROOT)/../vendor/react-native-navigation/ios", "$(SRCROOT)/../node_modules/bugsnag-react-native/cocoa/**", "$(SRCROOT)/../node_modules/react-native/Libraries/Text", + "$(SRCROOT)/../node_modules/react-native-store-review/ios", ); INFOPLIST_FILE = StandardNotes/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1511,6 +1548,7 @@ "$(SRCROOT)/../vendor/react-native-navigation/ios", "$(SRCROOT)/../node_modules/bugsnag-react-native/cocoa/**", "$(SRCROOT)/../node_modules/react-native/Libraries/Text", + "$(SRCROOT)/../node_modules/react-native-store-review/ios", ); INFOPLIST_FILE = StandardNotes/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1545,6 +1583,7 @@ "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/bugsnag-react-native/cocoa/**", + "$(SRCROOT)/../node_modules/react-native-store-review/ios", ); INFOPLIST_FILE = "StandardNotes-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1553,6 +1592,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1583,6 +1623,7 @@ "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/bugsnag-react-native/cocoa/**", + "$(SRCROOT)/../node_modules/react-native-store-review/ios", ); INFOPLIST_FILE = "StandardNotes-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1591,6 +1632,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1622,6 +1664,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.StandardNotes-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1649,6 +1692,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.StandardNotes-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/package.json b/package.json index abb712e6..617fffda 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "react-native": "^0.48.4", "react-native-keychain": "^1.2.1", "react-native-search-box": "0.0.11", + "react-native-store-review": "^0.1.3", "react-native-vector-icons": "^4.3.0" }, "devDependencies": { diff --git a/src/app.js b/src/app.js index e2f829e6..bda827b6 100644 --- a/src/app.js +++ b/src/app.js @@ -16,6 +16,7 @@ import {registerScreens} from './screens'; import KeysManager from './lib/keysManager' import Auth from './lib/auth' +import ReviewManager from './lib/reviewManager'; import GlobalStyles from "./Styles" import Icons from "./Icons" import OptionsState from "./OptionsState" @@ -58,6 +59,9 @@ export default class App { this.lockStatusObservers = []; this._isAndroid = Platform.OS === "android"; + // Initialize iOS review manager. Will automatically handle requesting review logic. + ReviewManager.initialize(); + // Configure Moment locale moment.locale(this.getLocale()); diff --git a/src/lib/reviewManager.js b/src/lib/reviewManager.js new file mode 100644 index 00000000..d9bc0e0b --- /dev/null +++ b/src/lib/reviewManager.js @@ -0,0 +1,34 @@ +import * as StoreReview from 'react-native-store-review'; +import {Platform} from 'react-native'; +import Storage from "./storage"; + +let NumRunsBeforeAskingForReview = [5, 20, 50] + +export default class ReviewManager { + + static initialize() { + if(Platform.OS == "android" || !StoreReview.isAvailable) { + return; + } + + this.getRunCount().then((runCount) => { + this.setRunCount(runCount + 1); + if(NumRunsBeforeAskingForReview.includes(runCount)) { + setTimeout(function () { + StoreReview.requestReview(); + }, 1000); + } + }) + } + + static async getRunCount() { + return Storage.getItem("runCount").then((runCount) => { + return JSON.parse(runCount); + }) + } + + static async setRunCount(runCount) { + return Storage.setItem("runCount", JSON.stringify(runCount)); + } + +} diff --git a/yarn.lock b/yarn.lock index 0a909619..50de66fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1636,15 +1636,7 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" -form-data@^2.1.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.1.1: +form-data@^2.1.1, form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" dependencies: @@ -1901,11 +1893,11 @@ iconv-lite@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" -iconv-lite@0.4.13: +iconv-lite@0.4.13, iconv-lite@~0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" -iconv-lite@^0.4.17, iconv-lite@~0.4.13: +iconv-lite@^0.4.17: version "0.4.18" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" @@ -2848,6 +2840,10 @@ minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: dependencies: minimist "0.0.8" +moment@^2.18.1: + version "2.18.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" + morgan@~1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" @@ -3336,6 +3332,10 @@ react-native-search-box@0.0.11: dependencies: prop-types "^15.5.10" +react-native-store-review@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/react-native-store-review/-/react-native-store-review-0.1.3.tgz#55929cd95bcc82fd1f25da963e1eb406739ac23a" + react-native-vector-icons@^4.3.0: version "4.4.0" resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.4.0.tgz#cdfc1cd86ab495b2a4926bcec8f08c155475cbf1" @@ -3344,9 +3344,9 @@ react-native-vector-icons@^4.3.0: prop-types "^15.5.10" yargs "^8.0.2" -react-native@0.48.1: - version "0.48.1" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.1.tgz#052ba5a86d3bdb748c288124248727d02b1c0939" +react-native@^0.48.4: + version "0.48.4" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.4.tgz#f305e9fef069a5b3f6a7250ddd50f603cf30ab2d" dependencies: absolute-path "^0.0.0" art "^0.10.0" @@ -3457,11 +3457,10 @@ react-transform-hmr@^1.0.4: global "^4.3.0" react-proxy "^1.1.7" -react@16.0.0-alpha.12: - version "16.0.0-alpha.12" - resolved "https://registry.yarnpkg.com/react/-/react-16.0.0-alpha.12.tgz#8c59485281485df319b6f77682d8dd0621c08194" +react@16.0.0-beta.5: + version "16.0.0-beta.5" + resolved "https://registry.yarnpkg.com/react/-/react-16.0.0-beta.5.tgz#b4abba9bce7db72c30633db54a148614b6574e79" dependencies: - create-react-class "^15.5.2" fbjs "^0.8.9" loose-envify "^1.1.0" object-assign "^4.1.0"