├── .gitattributes
├── .gitignore
├── README.md
├── android
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── js
│ ├── extractor.js
│ └── jqLite.js
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── masteratul
│ ├── RNAppstoreVersionCheckerModule.java
│ └── RNAppstoreVersionCheckerPackage.java
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── index.js
├── package.json
├── screenshots
├── android-example-screenshot.jpg
└── ios-example-screenshot.jpg
├── src
├── fetcher.js
├── versionChecker.android.js
└── versionChecker.ios.js
└── yarn.lock
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 | # node.js
7 | #
8 | node_modules/
9 | npm-debug.log
10 | yarn-error.log
11 |
12 |
13 | # Xcode
14 | #
15 | build/
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata
25 | *.xccheckout
26 | *.moved-aside
27 | DerivedData
28 | *.hmap
29 | *.ipa
30 | *.xcuserstate
31 | project.xcworkspace
32 |
33 |
34 | # Android/IntelliJ
35 | #
36 | build/
37 | .idea
38 | .gradle
39 | local.properties
40 | *.iml
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-appstore-version-checker [Deprecated] 
2 |
3 | [](https://www.npmjs.com/package/react-native-appstore-version-checker)
4 |
5 | A react native module to check an app's version on playstore or ios app store.
6 | This module can be used to check if your app has a new version on playstore or apple app store.
7 | or you can even check what is the latest version of another app on playstore.
8 |
9 |
10 | # DEPRECATED
11 |
12 | This package is now deprecated and will no longer be maintained. Please use https://github.com/kimxogus/react-native-version-check as an alternative.
13 |
14 |
15 | ## Getting started
16 |
17 | `npm install react-native-appstore-version-checker --save`
18 |
19 | or
20 |
21 | `yarn add react-native-appstore-version-checker`
22 |
23 | ### Automatic installation
24 |
25 | `react-native link react-native-appstore-version-checker`
26 |
27 | ### Manual installation
28 |
29 | #### iOS
30 |
31 | Nothing to be done here ( its pure JS for IOS ;) )
32 |
33 | #### Android
34 |
35 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java`
36 |
37 | - Add `import com.masteratul.RNAppstoreVersionCheckerPackage;` to the imports at the top of the file
38 | - Add `new RNAppstoreVersionCheckerPackage()` to the list returned by the `getPackages()` method
39 |
40 | 2. Append the following lines to `android/settings.gradle`:
41 |
42 | ```
43 | include ':react-native-appstore-version-checker'
44 | project(':react-native-appstore-version-checker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-appstore-version-checker/android')
45 | ```
46 |
47 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
48 |
49 | ```
50 | compile project(':react-native-appstore-version-checker')
51 | ```
52 |
53 | ## Usage
54 |
55 | ```javascript
56 | import { getAppstoreAppMetadata } from "react-native-appstore-version-checker";
57 |
58 | or;
59 |
60 | var getAppstoreAppMetadata = require("react-native-appstore-version-checker")
61 | .getAppstoreAppMetadata;
62 |
63 | //On Android u can do
64 | getAppstoreAppMetadata("com.supercell.clashofclans") //put any apps packageId here
65 | .then(metadata => {
66 | console.log(
67 | "clashofclans android app version on playstore",
68 | metadata.version,
69 | "published on",
70 | metadata.currentVersionReleaseDate
71 | );
72 | })
73 | .catch(err => {
74 | console.log("error occurred", err);
75 | });
76 |
77 | //On IOS u can do
78 | getAppstoreAppMetadata("529479190") //put any apps id here
79 | .then(appVersion => {
80 | console.log(
81 | "clashofclans android app version on appstore",
82 | metadata.version,
83 | "published on",
84 | metadata.currentVersionReleaseDate
85 | );
86 | })
87 | .catch(err => {
88 | console.log("error occurred", err);
89 | });
90 | ```
91 |
92 | ### How To find an appid in IOS or packageId in Android
93 |
94 | #### IOS
95 |
96 | **Finding appid for an ios app**
97 |
98 | Search for an app on itunes store. Lets take the example of `clash of clans`.
99 |
100 |
101 |
102 |
103 |

104 |
105 |
106 |
107 | The area marked on red is the app's `appid`
108 |
109 | #### ANDROID
110 |
111 | **Finding packageId for an android app**
112 |
113 | Search for an app on playstore. Lets take the example of `clash of clans`.
114 |
115 |
116 |
117 |
118 |

119 |
120 |
121 |
122 | The area marked on red is the app's `packageId`
123 |
124 | ### Advanced Options
125 |
126 | ```javascript
127 | getAppstoreAppMetadata(identifier, options);
128 | ```
129 |
130 | **params:**
131 |
132 | - `identifier` is the app package id like `com.example.app`
133 |
134 | - `options` contains values which can affect the result obtained from the store
135 |
136 | - `jquerySelectors` [Android] object with metadata property names to dom dom element identifiers (much like jquery selector) for playstore app page. Currently to get the appversion from the page we do load `https://play.google.com/store/apps/details?id=` and parse `$('body > [itemprop="softwareVersion"]')` but you can optionally pass in a custom selector if you want. This is useful if dom structure of the app store page changes in the future.
137 |
138 | - `typeOfId` [iOS] (default is `id`) It can be either `id` or `bundleId`. If the `typeOfId` is `id` you need to pass `identifier` as appid and if `typeOfId` is `bundleId` you need to pass bundleIdentifier to `identifier`. It is basically, the query parameter for `https://itunes.apple.com/lookup?${typeOfId}=${identifier}`.
139 |
140 | Currently to get the ios version number from app store we hit the url `https://itunes.apple.com/lookup?id=` by default.
141 | or we can also hit
142 | `https://itunes.apple.com/lookup?bundleId=` if we pass typeOfId as `bundleId`.
143 | When we hit the above said urls we get json with all the info of the app.
144 |
145 | - `country` [iOS] (default is `us`) The two-letter country code for the store you want to search. The search uses the default store front for the specified country.
146 |
147 | ```javascript
148 | const storeSpecificId =
149 | Platform.OS === "ios" ? "529479190" : "com.supercell.clashofclans";
150 |
151 | getAppstoreAppMetadata(storeSpecificId, {
152 | jquerySelectors: {
153 | version: "[itemprop='softwareVersion']"
154 | },
155 | typeOfId: "id",
156 | country: "de"
157 | });
158 | ```
159 |
160 | ```javascript
161 | getAppstoreAppVersion(identifier, options);
162 | ```
163 |
164 | `getAppstoreAppVersion` has been maintained with previous versions for backwards compatibility. The only difference is that instead
165 | of `jquerySelectors`, the `options` objet only takes one selector for the app version and it's called `jquerySelector`.
166 |
167 | **Example**
168 |
169 | ```javascript
170 | const storeSpecificId =
171 | Platform.OS === "ios" ? "529479190" : "com.supercell.clashofclans";
172 |
173 | getAppstoreAppVersion(storeSpecificId, {
174 | jquerySelector: "[itemprop='softwareVersion']",
175 | typeOfId: "id",
176 | country: "de"
177 | });
178 | ```
179 |
180 | Quick note: it will get the public version from stores, that is, will not get alfa, beta or internal versions.
181 |
182 | ### Contributors
183 |
184 | - [Atul R](https://github.com/master-atul)
185 | - [Dmytro Gorelik](https://github.com/dhorelik)
186 | - [Oleg Filimonov](https://github.com/olegfilimonov)
187 | - [Carlos](https://github.com/carl0395)
188 | - [EricH](https://github.com/jehartzog)
189 | - [Regan Langford](https://github.com/ReganL)
190 | - [Yuttana K](https://github.com/Thunderbird7)
191 | - [Luís](https://github.com/luissmg)
192 | - [Grover TB](https://github.com/grovertb)
193 | - [David Saltares](https://github.com/dsaltares)
194 |
195 | ### License
196 |
197 | MIT
198 |
199 | © Atul R
200 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | def DEFAULT_COMPILE_SDK_VERSION = 26
2 | def DEFAULT_BUILD_TOOLS_VERSION = "26.0.3"
3 | def DEFAULT_TARGET_SDK_VERSION = 26
4 | def DEFAULT_MIN_SDK_VERSION = 16
5 |
6 | buildscript {
7 | repositories {
8 | jcenter()
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:1.3.1'
13 | }
14 | }
15 |
16 | apply plugin: 'com.android.library'
17 |
18 | android {
19 | compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION
20 | buildToolsVersion rootProject.hasProperty('buildToolsVersion') ? rootProject.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION
21 |
22 | defaultConfig {
23 | minSdkVersion rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : DEFAULT_MIN_SDK_VERSION
24 | targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION
25 | versionCode 1
26 | versionName "1.0"
27 | }
28 | lintOptions {
29 | abortOnError false
30 | }
31 | }
32 |
33 | repositories {
34 | mavenCentral()
35 | }
36 |
37 | dependencies {
38 | implementation 'com.facebook.react:react-native:+'
39 | implementation 'org.jsoup:jsoup:1.11.3'
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-appstore-version-checker/598a4c324a2fbbcdce2fb3b8948230939a2049cc/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 04 19:12:48 WIB 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/js/extractor.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-appstore-version-checker/598a4c324a2fbbcdce2fb3b8948230939a2049cc/android/js/extractor.js
--------------------------------------------------------------------------------
/android/js/jqLite.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | /* eslint no-undef:0, semi:2 */
3 | /* eslint guard-for-in:0, semi:2*/
4 |
5 | if (typeof $ === "undefined") {
6 | window.$ = {};
7 | }
8 |
9 | var eventQueue = [];
10 |
11 | document.addEventListener('DOMContentLoaded', function () {
12 | eventQueue.forEach(function (fn) {
13 | fn();
14 | });
15 | }, false);
16 |
17 |
18 |
19 | $ = function (arg) {
20 | var htmlEls;
21 |
22 | if (arg instanceof Function) {
23 |
24 | eventQueue.push(arg);
25 | return document;
26 |
27 | } else if(arg instanceof Object) {
28 | return new DOMNodeCollection([arg]);
29 | } else {
30 |
31 | if (arg instanceof HTMLElement) {
32 |
33 | htmlEls = [arg]
34 |
35 | } else {
36 | matches = arg.match(/^<(\w+)>$/);
37 |
38 | if (matches) {
39 | htmlEls = [document.createElement(matches[1])];
40 | } else {
41 | htmlEls = Array.prototype.slice.call(document.querySelectorAll(arg));
42 | }
43 | }
44 |
45 | return new DOMNodeCollection(htmlEls);
46 | }
47 | };
48 |
49 |
50 | DOMNodeCollection = function (elements) {
51 | this.elements = elements;
52 | return this;
53 | };
54 |
55 |
56 | DOMNodeCollection.prototype.html = function (string) {
57 | if (typeof string !== 'undefined') {
58 |
59 | this.elements.forEach(function (el) {
60 | el.innerHTML = string;
61 | });
62 |
63 | return this;
64 | } else {
65 | return this.elements[0].innerHTML;
66 | }
67 | };
68 |
69 |
70 |
71 | DOMNodeCollection.prototype.empty = function () {
72 | this.html("");
73 | return this;
74 | };
75 |
76 |
77 |
78 | DOMNodeCollection.prototype.appendToFirst = function (arg) {
79 | this.elements[0].appendChild(arg.cloneNode(true));
80 | };
81 |
82 |
83 |
84 | DOMNodeCollection.prototype.append = function (arg) {
85 | if (arg instanceof DOMNodeCollection) {
86 |
87 | arg.elements.forEach(function (el) {
88 | this.elements[0].appendChild(el.cloneNode(true));
89 | }.bind(this));
90 |
91 | } else if (arg instanceof HTMLElement) {
92 |
93 | this.elements[0].appendChild(arg.cloneNode(true));
94 |
95 | } else if (typeof arg === "string") {
96 |
97 | this.elements.forEach(function (el) {
98 | el.innerHTML += arg;
99 | });
100 |
101 | }
102 |
103 | return this;
104 | };
105 |
106 |
107 | DOMNodeCollection.prototype.attr = function (name, value) {
108 | if (typeof value !== 'undefined') {
109 | this.elements.forEach( function(el) {
110 | el.setAttribute(name, value);
111 | });
112 | return this;
113 | } else {
114 | return this.elements[0].getAttribute(name);
115 | }
116 | };
117 |
118 | DOMNodeCollection.prototype.get = function(index) {
119 | return new DOMNodeCollection([this.elements[index]]);
120 | };
121 |
122 | DOMNodeCollection.prototype.addClass = function (newClass) {
123 | this.elements.forEach( function (el) {
124 | el.classList.add(newClass);
125 | });
126 | return this;
127 | };
128 |
129 |
130 |
131 | DOMNodeCollection.prototype.removeClass = function (dropClass) {
132 | this.elements.forEach( function (el) {
133 | el.classList.remove(dropClass);
134 | });
135 | return this;
136 | };
137 |
138 |
139 |
140 | DOMNodeCollection.prototype.children = function () {
141 | var allChildren = [], newChildren;
142 |
143 | this.elements.forEach(function (el) {
144 | newChildren = Array.prototype.slice.call(el.children);
145 |
146 | allChildren = allChildren.concat(newChildren);
147 | });
148 |
149 | return new DOMNodeCollection(allChildren);
150 | };
151 |
152 |
153 |
154 | DOMNodeCollection.prototype.parent = function () {
155 | var parents = [], currentParent;
156 |
157 | this.elements.forEach(function (el) {
158 | // debugger
159 | currentParent = el.parentElement;
160 |
161 | if (parents.indexOf(currentParent) === -1) {
162 | parents.push(currentParent);
163 | }
164 | });
165 |
166 | return new DOMNodeCollection(parents);
167 | };
168 |
169 |
170 |
171 | DOMNodeCollection.prototype.find = function (selector) {
172 | var matchingElements = [], currentMatchesQuery, currentMatches;
173 |
174 | this.elements.forEach(function (el) {
175 | currentMatchesQuery = el.querySelectorAll(selector);
176 | currentMatches = Array.prototype.slice.call(currentMatchesQuery);
177 | currentMatches.forEach( function (match) {
178 | if (matchingElements.indexOf(match) === -1) {
179 | matchingElements.push(match);
180 | }
181 | });
182 | });
183 |
184 | return new DOMNodeCollection(matchingElements);
185 | };
186 |
187 |
188 |
189 | DOMNodeCollection.prototype.remove = function () {
190 | this.elements.forEach(function (el) {
191 | el.remove();
192 | });
193 | };
194 |
195 |
196 |
197 | DOMNodeCollection.prototype.on = function (type, callback) {
198 | this.elements.forEach(function (el) {
199 | el.addEventListener(type, callback);
200 | });
201 | return this;
202 | };
203 |
204 |
205 |
206 | DOMNodeCollection.prototype.off = function (type, callback) {
207 | this.elements.forEach(function (el) {
208 | el.removeEventListener(type, callback);
209 | });
210 | return this;
211 | };
212 |
213 | DOMNodeCollection.prototype.each = function(callback) {
214 | this.elements.forEach(callback);
215 | };
216 |
217 |
218 | DOMNodeCollection.prototype.hide = function() {
219 | this.originalDisplay = this.css("display");
220 | this.css("display", "none");
221 | return this;
222 | };
223 |
224 | DOMNodeCollection.prototype.show = function() {
225 | newDisplay = this.originalDisplay || "block";
226 | this.css("display", newDisplay);
227 | return this;
228 | };
229 |
230 | DOMNodeCollection.prototype.css = function(property, value) {
231 | if (typeof value === 'undefined') {
232 | return this.elements[0].style.getPropertyValue(property);
233 | } else {
234 | this.elements.forEach(function(element){
235 | element.style[property] = value;
236 | });
237 | return this;
238 | }
239 | };
240 |
241 | DOMNodeCollection.prototype.text = function(string) {
242 | if (typeof string !== 'undefined') {
243 |
244 | this.elements.forEach(function (el) {
245 | el.innerText = string;
246 | });
247 |
248 | return this;
249 | } else {
250 | text = "";
251 |
252 | this.elements.forEach(function(element){
253 | text += element.innerText;
254 | });
255 |
256 | return text;
257 | }
258 | };
259 |
260 | $.extend = function (base) {
261 | var objects = Array.prototype.slice.call(arguments, 1);
262 |
263 | objects.forEach( function (object) {
264 | for (var attribute in object) {
265 | base[attribute] = object[attribute];
266 | }
267 | });
268 | };
269 |
270 | var loadXMLDoc = function(options) {
271 | var xmlhttp = new XMLHttpRequest();
272 |
273 | xmlhttp.onreadystatechange = function() {
274 | if(xmlhttp.readyState == XMLHttpRequest.DONE){
275 | if (xmlhttp.status == 200) {
276 | options.success(xmlhttp.response);
277 | } else {
278 | options.error();
279 | }
280 | }
281 | };
282 |
283 | xmlhttp.open(options.method, options.url, true);
284 |
285 | if (options.method == 'POST') {
286 | xmlhttp.setRequestHeader('Content-type', options.contentType);
287 | }
288 |
289 | xmlhttp.send(options.data);
290 | };
291 |
292 | $.ajax = function (options) {
293 | var defaults = {
294 | success: function(){},
295 | error: function(){},
296 | url: window.location.href,
297 | method: "GET",
298 | data: "",
299 | contentType: "application/x-www-form-urlencoded"
300 | };
301 |
302 | $.extend(defaults, options);
303 | loadXMLDoc(defaults);
304 | };
305 |
306 | $.get = function(url, successCallback) {
307 | $.ajax({
308 | url: url,
309 | success: successCallback
310 | });
311 | };
312 |
313 | $.post = function(url, data, successCallback) {
314 | $.ajax({
315 | url: url,
316 | data: data,
317 | success: successCallback
318 | });
319 | };
320 |
321 | }());
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/src/main/java/com/masteratul/RNAppstoreVersionCheckerModule.java:
--------------------------------------------------------------------------------
1 |
2 | package com.masteratul;
3 |
4 | import com.facebook.react.bridge.Callback;
5 | import com.facebook.react.bridge.ReactApplicationContext;
6 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
7 | import com.facebook.react.bridge.ReactMethod;
8 | import com.facebook.react.bridge.ReadableMap;
9 | import com.facebook.react.bridge.WritableMap;
10 | import com.facebook.react.bridge.Arguments;
11 |
12 | import org.jsoup.Jsoup;
13 | import org.jsoup.nodes.Document;
14 | import org.jsoup.select.Elements;
15 |
16 | public class RNAppstoreVersionCheckerModule extends ReactContextBaseJavaModule {
17 |
18 | public RNAppstoreVersionCheckerModule(ReactApplicationContext rContext) {
19 | super(rContext);
20 | }
21 |
22 | @Override
23 | public String getName() {
24 | return "RNAppstoreVersionChecker";
25 | }
26 |
27 | @ReactMethod
28 | public void extractMetadata(
29 | String url, ReadableMap extractors,
30 | Callback successCallback,
31 | Callback errorCallback) {
32 | try {
33 | Document doc = Jsoup.connect(url).get();
34 | WritableMap metadata = Arguments.createMap();
35 |
36 | metadata.putString(
37 | "version",
38 | extractField(doc, "Current Version", "version", extractors)
39 | );
40 | metadata.putString(
41 | "currentVersionReleaseDate",
42 | extractField(doc, "Updated", "currentVersionReleaseDate", extractors)
43 | );
44 |
45 | // https://stackoverflow.com/a/49924787/2881112
46 | successCallback.invoke(metadata);
47 | } catch (Exception e) {
48 | errorCallback.invoke(e.getMessage());
49 | }
50 |
51 | }
52 |
53 | private String extractField(
54 | Document doc,
55 | String fieldLabel,
56 | String extractorName,
57 | ReadableMap extractors) {
58 | if(extractors.hasKey(extractorName)) {
59 | return doc.select(extractors.getString(extractorName)).text();
60 | }
61 |
62 | return doc.getElementsContainingOwnText(fieldLabel).parents().first().getAllElements().last().text();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/android/src/main/java/com/masteratul/RNAppstoreVersionCheckerPackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.masteratul;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 | public class RNAppstoreVersionCheckerPackage implements ReactPackage {
14 | @Override
15 | public List createNativeModules(ReactApplicationContext reactContext) {
16 | return Arrays.asList(new RNAppstoreVersionCheckerModule(reactContext));
17 | }
18 |
19 | //leaving it to support react-native v0.47 and less
20 | public List> createJSModules() {
21 | return Collections.emptyList();
22 | }
23 |
24 | @Override
25 | public List createViewManagers(ReactApplicationContext reactContext) {
26 | return Collections.emptyList();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-appstore-version-checker/598a4c324a2fbbcdce2fb3b8948230939a2049cc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 04 19:03:53 WIB 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import versionChecker from './src/versionChecker';
2 |
3 |
4 | module.exports = versionChecker;
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-appstore-version-checker",
3 | "version": "3.0.0",
4 | "description": "A react native module to find the app version on play store and ios app store",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "react-native",
11 | "ios",
12 | "version",
13 | "check",
14 | "android",
15 | "play store",
16 | "app store",
17 | "checker",
18 | "fetch",
19 | "parse"
20 | ],
21 | "author": "atulanand94@gmail.com",
22 | "license": "MIT",
23 | "peerDependencies": {
24 | "react-native": "*"
25 | },
26 | "dependencies": {
27 | "lodash.result": "^4.5.2"
28 | },
29 | "bugs": {
30 | "url": "https://github.com/master-atul/react-native-appstore-version-checker/issues"
31 | },
32 | "homepage": "https://github.com/master-atul/react-native-appstore-version-checker"
33 | }
34 |
--------------------------------------------------------------------------------
/screenshots/android-example-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-appstore-version-checker/598a4c324a2fbbcdce2fb3b8948230939a2049cc/screenshots/android-example-screenshot.jpg
--------------------------------------------------------------------------------
/screenshots/ios-example-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7ul/react-native-appstore-version-checker/598a4c324a2fbbcdce2fb3b8948230939a2049cc/screenshots/ios-example-screenshot.jpg
--------------------------------------------------------------------------------
/src/fetcher.js:
--------------------------------------------------------------------------------
1 | export const parseJson = (r) => new Promise((resolve, reject) => {
2 | r.json().then((result) => {
3 | r.data = result;
4 | resolve(r);
5 | }).catch((err) => {
6 | r.data = err;
7 | reject(r);
8 | });
9 | });
10 |
11 | export const get = (url) => {
12 | const config = {
13 | method: 'GET',
14 | credentials: 'include',
15 | mode: 'no-cors',
16 | headers: {
17 | 'Cache-Control': 'no-cache, no-store, must-revalidate',
18 | 'Pragma': 'no-cache',
19 | 'Expires': 0
20 | }
21 | };
22 | return fetch(url, config).then((response) => {
23 | if (response.status === 200) {
24 | return response;
25 | }
26 | throw response;
27 | });
28 | };
29 |
--------------------------------------------------------------------------------
/src/versionChecker.android.js:
--------------------------------------------------------------------------------
1 | import {NativeModules} from 'react-native';
2 |
3 | const extractMetadata = (url, jquerySelectors) => new Promise((resolve, reject) => {
4 | NativeModules.RNAppstoreVersionChecker.extractMetadata(
5 | url,
6 | jquerySelectors,
7 | resolve,
8 | reject,
9 | );
10 | });
11 |
12 | const getAppstoreAppMetadata = async (id, options = { jquerySelectors: {} }) => {
13 | const language = options.language ? `&hl=${options.language}` : 'en';
14 | const url = `https://play.google.com/store/apps/details?id=${id}&${language}`;
15 | const { version, currentVersionReleaseDate } = await extractMetadata(url, options.jquerySelectors);
16 | return {
17 | version,
18 | currentVersionReleaseDate: new Date(currentVersionReleaseDate),
19 | };
20 | }
21 |
22 | const getAppstoreAppVersion = async (id, options = { jquerySelector: "" }) => {
23 | const newOptions = {
24 | jquerySelectors: { version: options.jquerySelector },
25 | ...options,
26 | };
27 | const metadata = await getAppstoreAppMetadata(id, newOptions);
28 | return metadata.version;
29 | };
30 |
31 | module.exports = {
32 | getAppstoreAppVersion,
33 | getAppstoreAppMetadata,
34 | };
35 |
--------------------------------------------------------------------------------
/src/versionChecker.ios.js:
--------------------------------------------------------------------------------
1 | import _result from 'lodash.result';
2 | import {get, parseJson} from './fetcher';
3 |
4 | const getAppstoreAppMetadata = async (identifier, options = { typeOfId: 'id' }) => {
5 | const country = options.country ? `&country=${options.country}` : '';
6 | const url = `https://itunes.apple.com/lookup?${options.typeOfId}=${identifier}${country}`;
7 | const jsonData = await get(url);
8 | const response = await parseJson(jsonData);
9 |
10 | if (!response || !response.data || response.data.resultCount === 0 || response.data.results.length === 0) {
11 | throw new Error('App not found!');
12 | }
13 | const version = _result(response, 'data.results[0].version');
14 | const currentVersionReleaseDate = _result(response, 'data.results[0].currentVersionReleaseDate');
15 | return {
16 | version,
17 | currentVersionReleaseDate: new Date(currentVersionReleaseDate),
18 | }
19 | };
20 |
21 | const getAppstoreAppVersion = async (identifier, options) => {
22 | const metadata = await getAppstoreAppMetadata(identifier, options);
23 | return metadata.version;
24 | };
25 |
26 | module.exports = {
27 | getAppstoreAppVersion,
28 | getAppstoreAppMetadata,
29 | };
30 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | lodash.result@^4.5.2:
6 | version "4.5.2"
7 | resolved "https://registry.yarnpkg.com/lodash.result/-/lodash.result-4.5.2.tgz#cb45b27fb914eaa8d8ee6f0ce7b2870b87cb70aa"
8 | integrity sha1-y0Wyf7kU6qjY7m8M57KHC4fLcKo=
9 |
--------------------------------------------------------------------------------