@parrotnavy/rn-native-updates 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +246 -0
- package/README.md +245 -0
- package/android/build.gradle +56 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/parrotnavy/nativeupdates/NativeUpdatesExceptions.kt +33 -0
- package/android/src/main/java/com/parrotnavy/nativeupdates/NativeUpdatesModule.kt +171 -0
- package/expo-module.config.json +9 -0
- package/ios/NativeUpdatesExceptions.swift +26 -0
- package/ios/NativeUpdatesModule.swift +77 -0
- package/lib/module/NativeUpdatesModule.js +5 -0
- package/lib/module/NativeUpdatesModule.js.map +1 -0
- package/lib/module/api.js +163 -0
- package/lib/module/api.js.map +1 -0
- package/lib/module/hooks/index.js +4 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useAppUpdate.js +135 -0
- package/lib/module/hooks/useAppUpdate.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +157 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/versionUtils.js +18 -0
- package/lib/module/versionUtils.js.map +1 -0
- package/lib/typescript/src/NativeUpdatesModule.d.ts +3 -0
- package/lib/typescript/src/NativeUpdatesModule.d.ts.map +1 -0
- package/lib/typescript/src/api.d.ts +15 -0
- package/lib/typescript/src/api.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +2 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAppUpdate.d.ts +3 -0
- package/lib/typescript/src/hooks/useAppUpdate.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +246 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/versionUtils.d.ts +3 -0
- package/lib/typescript/src/versionUtils.d.ts.map +1 -0
- package/package.json +103 -0
- package/rn-native-updates.podspec +19 -0
- package/src/NativeUpdatesModule.ts +5 -0
- package/src/api.ts +239 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAppUpdate.ts +189 -0
- package/src/index.ts +36 -0
- package/src/types.ts +315 -0
- package/src/versionUtils.ts +28 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
package com.parrotnavy.nativeupdates
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.pm.PackageManager
|
|
5
|
+
import expo.modules.kotlin.Promise
|
|
6
|
+
import expo.modules.kotlin.modules.Module
|
|
7
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
8
|
+
import expo.modules.kotlin.exception.CodedException
|
|
9
|
+
import com.google.android.play.core.appupdate.AppUpdateInfo
|
|
10
|
+
import com.google.android.play.core.appupdate.AppUpdateManager
|
|
11
|
+
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
|
|
12
|
+
import com.google.android.play.core.appupdate.AppUpdateOptions
|
|
13
|
+
import com.google.android.play.core.install.InstallStateUpdatedListener
|
|
14
|
+
import com.google.android.play.core.install.model.AppUpdateType
|
|
15
|
+
import com.google.android.play.core.install.model.InstallStatus
|
|
16
|
+
import com.google.android.play.core.install.model.UpdateAvailability
|
|
17
|
+
import java.util.Locale
|
|
18
|
+
|
|
19
|
+
class NativeUpdatesModule : Module() {
|
|
20
|
+
private var appUpdateManager: AppUpdateManager? = null
|
|
21
|
+
private var installStateListener: InstallStateUpdatedListener? = null
|
|
22
|
+
|
|
23
|
+
private val context
|
|
24
|
+
get() = requireNotNull(appContext.reactContext)
|
|
25
|
+
|
|
26
|
+
private val currentActivity
|
|
27
|
+
get() = appContext.currentActivity
|
|
28
|
+
|
|
29
|
+
override fun definition() = ModuleDefinition {
|
|
30
|
+
Name("NativeUpdates")
|
|
31
|
+
|
|
32
|
+
Constants {
|
|
33
|
+
val packageName = context.packageName
|
|
34
|
+
val packageInfo = try {
|
|
35
|
+
context.packageManager.getPackageInfo(packageName, 0)
|
|
36
|
+
} catch (e: PackageManager.NameNotFoundException) {
|
|
37
|
+
null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
mapOf(
|
|
41
|
+
"currentVersion" to (packageInfo?.versionName ?: "0.0.0"),
|
|
42
|
+
"buildNumber" to (packageInfo?.longVersionCode?.toString() ?: "0"),
|
|
43
|
+
"packageName" to packageName,
|
|
44
|
+
"country" to Locale.getDefault().country
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Events("onUpdateProgress", "onUpdateDownloaded", "onUpdateInstalled", "onUpdateFailed")
|
|
49
|
+
|
|
50
|
+
OnCreate {
|
|
51
|
+
appUpdateManager = AppUpdateManagerFactory.create(context)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
OnDestroy {
|
|
55
|
+
installStateListener?.let {
|
|
56
|
+
appUpdateManager?.unregisterListener(it)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
AsyncFunction("checkPlayStoreUpdate") { promise: Promise ->
|
|
61
|
+
val manager = appUpdateManager ?: run {
|
|
62
|
+
promise.reject(PlayStoreNotAvailableException())
|
|
63
|
+
return@AsyncFunction
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
manager.appUpdateInfo
|
|
67
|
+
.addOnSuccessListener { info ->
|
|
68
|
+
val result = mapOf(
|
|
69
|
+
"updateAvailability" to info.updateAvailability(),
|
|
70
|
+
"availableVersionCode" to if (info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
|
|
71
|
+
info.availableVersionCode()
|
|
72
|
+
} else null,
|
|
73
|
+
"isFlexibleUpdateAllowed" to info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE),
|
|
74
|
+
"isImmediateUpdateAllowed" to info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE),
|
|
75
|
+
"clientVersionStalenessDays" to info.clientVersionStalenessDays(),
|
|
76
|
+
"updatePriority" to info.updatePriority(),
|
|
77
|
+
"totalBytesToDownload" to info.totalBytesToDownload(),
|
|
78
|
+
"packageName" to info.packageName()
|
|
79
|
+
)
|
|
80
|
+
promise.resolve(result)
|
|
81
|
+
}
|
|
82
|
+
.addOnFailureListener { e ->
|
|
83
|
+
if (e.message?.contains("API not available") == true ||
|
|
84
|
+
e.message?.contains("not installed from Play Store") == true) {
|
|
85
|
+
promise.reject(NotFromPlayStoreException())
|
|
86
|
+
} else {
|
|
87
|
+
promise.reject(CheckFailedException(e.message))
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
AsyncFunction("startUpdate") { updateType: Int, promise: Promise ->
|
|
93
|
+
val manager = appUpdateManager ?: run {
|
|
94
|
+
promise.reject(PlayStoreNotAvailableException())
|
|
95
|
+
return@AsyncFunction
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
val activity = currentActivity ?: run {
|
|
99
|
+
promise.reject(NoActivityException())
|
|
100
|
+
return@AsyncFunction
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
manager.appUpdateInfo
|
|
104
|
+
.addOnSuccessListener { info ->
|
|
105
|
+
if (info.updateAvailability() != UpdateAvailability.UPDATE_AVAILABLE) {
|
|
106
|
+
promise.reject(UpdateNotAvailableException())
|
|
107
|
+
return@addOnSuccessListener
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Register listener for flexible updates
|
|
111
|
+
if (updateType == AppUpdateType.FLEXIBLE) {
|
|
112
|
+
installStateListener = InstallStateUpdatedListener { state ->
|
|
113
|
+
val progress = if (state.totalBytesToDownload() > 0) {
|
|
114
|
+
((state.bytesDownloaded() * 100) / state.totalBytesToDownload()).toInt()
|
|
115
|
+
} else 0
|
|
116
|
+
|
|
117
|
+
when (state.installStatus()) {
|
|
118
|
+
InstallStatus.DOWNLOADING -> {
|
|
119
|
+
sendEvent("onUpdateProgress", mapOf(
|
|
120
|
+
"installStatus" to state.installStatus(),
|
|
121
|
+
"bytesDownloaded" to state.bytesDownloaded(),
|
|
122
|
+
"totalBytesToDownload" to state.totalBytesToDownload(),
|
|
123
|
+
"downloadProgress" to progress
|
|
124
|
+
))
|
|
125
|
+
}
|
|
126
|
+
InstallStatus.DOWNLOADED -> {
|
|
127
|
+
sendEvent("onUpdateDownloaded", mapOf(
|
|
128
|
+
"installStatus" to state.installStatus(),
|
|
129
|
+
"bytesDownloaded" to state.bytesDownloaded(),
|
|
130
|
+
"totalBytesToDownload" to state.totalBytesToDownload(),
|
|
131
|
+
"downloadProgress" to 100
|
|
132
|
+
))
|
|
133
|
+
}
|
|
134
|
+
InstallStatus.INSTALLED -> {
|
|
135
|
+
sendEvent("onUpdateInstalled", mapOf(
|
|
136
|
+
"installStatus" to state.installStatus()
|
|
137
|
+
))
|
|
138
|
+
installStateListener?.let { manager.unregisterListener(it) }
|
|
139
|
+
}
|
|
140
|
+
InstallStatus.FAILED, InstallStatus.CANCELED -> {
|
|
141
|
+
sendEvent("onUpdateFailed", mapOf(
|
|
142
|
+
"installStatus" to state.installStatus()
|
|
143
|
+
))
|
|
144
|
+
installStateListener?.let { manager.unregisterListener(it) }
|
|
145
|
+
}
|
|
146
|
+
else -> {}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
manager.registerListener(installStateListener!!)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
val options = AppUpdateOptions.newBuilder(updateType).build()
|
|
153
|
+
|
|
154
|
+
manager.startUpdateFlow(info, activity, options)
|
|
155
|
+
.addOnSuccessListener {
|
|
156
|
+
promise.resolve(null)
|
|
157
|
+
}
|
|
158
|
+
.addOnFailureListener { e ->
|
|
159
|
+
promise.reject(UpdateFailedException(e.message))
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
.addOnFailureListener { e ->
|
|
163
|
+
promise.reject(CheckFailedException(e.message))
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
Function("completeUpdate") {
|
|
168
|
+
appUpdateManager?.completeUpdate()
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
enum AppStoreError: Error {
|
|
4
|
+
case invalidBundleId
|
|
5
|
+
case invalidURL
|
|
6
|
+
case networkError
|
|
7
|
+
case appNotFound
|
|
8
|
+
case rateLimited
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
extension AppStoreError: CustomStringConvertible {
|
|
12
|
+
var description: String {
|
|
13
|
+
switch self {
|
|
14
|
+
case .invalidBundleId:
|
|
15
|
+
return "Invalid bundle identifier"
|
|
16
|
+
case .invalidURL:
|
|
17
|
+
return "Invalid App Store URL"
|
|
18
|
+
case .networkError:
|
|
19
|
+
return "Network request failed"
|
|
20
|
+
case .appNotFound:
|
|
21
|
+
return "App not found on App Store"
|
|
22
|
+
case .rateLimited:
|
|
23
|
+
return "App Store API rate limit exceeded"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
public class NativeUpdatesModule: Module {
|
|
4
|
+
private var cachedAppStoreInfo: [String: Any]?
|
|
5
|
+
private var cacheTimestamp: Date?
|
|
6
|
+
private let cacheDuration: TimeInterval = 3600 // 1 hour
|
|
7
|
+
|
|
8
|
+
public func definition() -> ModuleDefinition {
|
|
9
|
+
Name("NativeUpdates")
|
|
10
|
+
|
|
11
|
+
Constants([
|
|
12
|
+
"currentVersion": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0",
|
|
13
|
+
"buildNumber": Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "0",
|
|
14
|
+
"packageName": Bundle.main.bundleIdentifier ?? "",
|
|
15
|
+
"country": Locale.current.region?.identifier ?? "US"
|
|
16
|
+
])
|
|
17
|
+
|
|
18
|
+
AsyncFunction("getAppStoreVersion") { (country: String?, forceRefresh: Bool) -> [String: Any] in
|
|
19
|
+
if !forceRefresh,
|
|
20
|
+
let cached = self.cachedAppStoreInfo,
|
|
21
|
+
let timestamp = self.cacheTimestamp,
|
|
22
|
+
Date().timeIntervalSince(timestamp) < self.cacheDuration {
|
|
23
|
+
return cached
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
guard let bundleId = Bundle.main.bundleIdentifier else {
|
|
27
|
+
throw AppStoreError.invalidBundleId
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let countryCode = country ?? Locale.current.region?.identifier ?? "US"
|
|
31
|
+
let timestamp = Int(Date().timeIntervalSince1970)
|
|
32
|
+
let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)&country=\(countryCode)&date=\(timestamp)"
|
|
33
|
+
|
|
34
|
+
guard let url = URL(string: urlString) else {
|
|
35
|
+
throw AppStoreError.invalidURL
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
var request = URLRequest(url: url)
|
|
39
|
+
request.cachePolicy = .reloadIgnoringLocalCacheData
|
|
40
|
+
request.timeoutInterval = 30
|
|
41
|
+
|
|
42
|
+
let (data, response) = try await URLSession.shared.data(for: request)
|
|
43
|
+
|
|
44
|
+
guard let httpResponse = response as? HTTPURLResponse else {
|
|
45
|
+
throw AppStoreError.networkError
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if httpResponse.statusCode == 429 {
|
|
49
|
+
throw AppStoreError.rateLimited
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if httpResponse.statusCode != 200 {
|
|
53
|
+
throw AppStoreError.networkError
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
57
|
+
let results = json["results"] as? [[String: Any]],
|
|
58
|
+
let first = results.first else {
|
|
59
|
+
throw AppStoreError.appNotFound
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let result: [String: Any] = [
|
|
63
|
+
"version": first["version"] as? String ?? "",
|
|
64
|
+
"trackId": first["trackId"] as? Int ?? 0,
|
|
65
|
+
"trackViewUrl": first["trackViewUrl"] as? String ?? "",
|
|
66
|
+
"currentVersionReleaseDate": first["currentVersionReleaseDate"] as? String ?? "",
|
|
67
|
+
"releaseNotes": first["releaseNotes"] as? String as Any,
|
|
68
|
+
"minimumOsVersion": first["minimumOsVersion"] as? String ?? ""
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
self.cachedAppStoreInfo = result
|
|
72
|
+
self.cacheTimestamp = Date()
|
|
73
|
+
|
|
74
|
+
return result
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["requireNativeModule","NativeUpdatesModule"],"sourceRoot":"../../src","sources":["NativeUpdatesModule.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,mBAAmB;AAIvD,OAAO,MAAMC,mBAAmB,GAAGD,mBAAmB,CAA0B,eAAe,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Linking, Platform } from 'react-native';
|
|
4
|
+
import { NativeUpdatesModule } from "./NativeUpdatesModule.js";
|
|
5
|
+
import { AppUpdateError, AppUpdateErrorCode, UpdateAvailability } from "./types.js";
|
|
6
|
+
import { isNewerVersion } from "./versionUtils.js";
|
|
7
|
+
export function getPackageName() {
|
|
8
|
+
return NativeUpdatesModule.packageName;
|
|
9
|
+
}
|
|
10
|
+
export function getCurrentVersion() {
|
|
11
|
+
return NativeUpdatesModule.currentVersion;
|
|
12
|
+
}
|
|
13
|
+
export function getCurrentBuildNumber() {
|
|
14
|
+
return Number.parseInt(NativeUpdatesModule.buildNumber, 10) || 0;
|
|
15
|
+
}
|
|
16
|
+
export function getCountry() {
|
|
17
|
+
return NativeUpdatesModule.country;
|
|
18
|
+
}
|
|
19
|
+
export async function getLatestVersion(options) {
|
|
20
|
+
if (Platform.OS === 'ios') {
|
|
21
|
+
const info = await NativeUpdatesModule.getAppStoreVersion(options?.country ?? null, options?.forceRefresh ?? false);
|
|
22
|
+
return info.version;
|
|
23
|
+
}
|
|
24
|
+
if (Platform.OS === 'android') {
|
|
25
|
+
const info = await checkPlayStoreUpdate();
|
|
26
|
+
if (info.updateAvailability === UpdateAvailability.UPDATE_AVAILABLE && info.availableVersionCode) {
|
|
27
|
+
return info.availableVersionCode.toString();
|
|
28
|
+
}
|
|
29
|
+
return getCurrentVersion();
|
|
30
|
+
}
|
|
31
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, `Platform ${Platform.OS} is not supported`);
|
|
32
|
+
}
|
|
33
|
+
export async function getStoreUrl(options) {
|
|
34
|
+
const packageName = getPackageName();
|
|
35
|
+
if (Platform.OS === 'ios') {
|
|
36
|
+
try {
|
|
37
|
+
const info = await NativeUpdatesModule.getAppStoreVersion(options?.country ?? null, false);
|
|
38
|
+
return info.trackViewUrl;
|
|
39
|
+
} catch {
|
|
40
|
+
const country = options?.country ?? getCountry();
|
|
41
|
+
return `https://apps.apple.com/${country.toLowerCase()}/app/id`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (Platform.OS === 'android') {
|
|
45
|
+
return `https://play.google.com/store/apps/details?id=${packageName}`;
|
|
46
|
+
}
|
|
47
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, `Platform ${Platform.OS} is not supported`);
|
|
48
|
+
}
|
|
49
|
+
export async function needUpdate(options) {
|
|
50
|
+
const currentVersion = options?.currentVersion ?? getCurrentVersion();
|
|
51
|
+
const depth = options?.depth ?? Number.POSITIVE_INFINITY;
|
|
52
|
+
let latestVersion;
|
|
53
|
+
let storeUrl;
|
|
54
|
+
if (options?.latestVersion) {
|
|
55
|
+
latestVersion = options.latestVersion;
|
|
56
|
+
storeUrl = await getStoreUrl({
|
|
57
|
+
country: options?.country
|
|
58
|
+
});
|
|
59
|
+
} else {
|
|
60
|
+
if (Platform.OS === 'ios') {
|
|
61
|
+
const info = await NativeUpdatesModule.getAppStoreVersion(options?.country ?? null, options?.forceRefresh ?? false);
|
|
62
|
+
latestVersion = info.version;
|
|
63
|
+
storeUrl = info.trackViewUrl;
|
|
64
|
+
} else if (Platform.OS === 'android') {
|
|
65
|
+
const info = await checkPlayStoreUpdate();
|
|
66
|
+
latestVersion = info.availableVersionCode?.toString() ?? currentVersion;
|
|
67
|
+
storeUrl = `https://play.google.com/store/apps/details?id=${getPackageName()}`;
|
|
68
|
+
} else {
|
|
69
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, `Platform ${Platform.OS} is not supported`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const isNeeded = isNewerVersion(currentVersion, latestVersion, depth);
|
|
73
|
+
return {
|
|
74
|
+
isNeeded,
|
|
75
|
+
currentVersion,
|
|
76
|
+
latestVersion,
|
|
77
|
+
storeUrl
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export async function openStore(options) {
|
|
81
|
+
const url = await getStoreUrl(options);
|
|
82
|
+
const canOpen = await Linking.canOpenURL(url);
|
|
83
|
+
if (canOpen) {
|
|
84
|
+
await Linking.openURL(url);
|
|
85
|
+
} else {
|
|
86
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, `Cannot open store URL: ${url}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export async function getAppStoreInfo(options) {
|
|
90
|
+
if (Platform.OS !== 'ios') {
|
|
91
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, 'getAppStoreInfo is only available on iOS');
|
|
92
|
+
}
|
|
93
|
+
return NativeUpdatesModule.getAppStoreVersion(options?.country ?? null, options?.forceRefresh ?? false);
|
|
94
|
+
}
|
|
95
|
+
export async function checkPlayStoreUpdate() {
|
|
96
|
+
if (Platform.OS !== 'android') {
|
|
97
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, 'checkPlayStoreUpdate is only available on Android');
|
|
98
|
+
}
|
|
99
|
+
return NativeUpdatesModule.checkPlayStoreUpdate();
|
|
100
|
+
}
|
|
101
|
+
export async function startInAppUpdate(type) {
|
|
102
|
+
if (Platform.OS !== 'android') {
|
|
103
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, 'startInAppUpdate is only available on Android');
|
|
104
|
+
}
|
|
105
|
+
return NativeUpdatesModule.startUpdate(type);
|
|
106
|
+
}
|
|
107
|
+
export function completeInAppUpdate() {
|
|
108
|
+
if (Platform.OS !== 'android') {
|
|
109
|
+
throw new AppUpdateError(AppUpdateErrorCode.UNKNOWN, 'completeInAppUpdate is only available on Android');
|
|
110
|
+
}
|
|
111
|
+
NativeUpdatesModule.completeUpdate();
|
|
112
|
+
}
|
|
113
|
+
let eventSubscription = null;
|
|
114
|
+
const listeners = new Set();
|
|
115
|
+
function setupEventListener() {
|
|
116
|
+
if (eventSubscription || Platform.OS !== 'android') return;
|
|
117
|
+
const {
|
|
118
|
+
EventEmitter
|
|
119
|
+
} = require('expo-modules-core');
|
|
120
|
+
const emitter = new EventEmitter(NativeUpdatesModule);
|
|
121
|
+
const handleEvent = (_eventName, data) => {
|
|
122
|
+
const state = {
|
|
123
|
+
installStatus: data.installStatus ?? 0,
|
|
124
|
+
bytesDownloaded: data.bytesDownloaded ?? 0,
|
|
125
|
+
totalBytesToDownload: data.totalBytesToDownload ?? 0,
|
|
126
|
+
downloadProgress: data.downloadProgress ?? 0
|
|
127
|
+
};
|
|
128
|
+
for (const listener of listeners) {
|
|
129
|
+
listener(state);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const progressSub = emitter.addListener('onUpdateProgress', data => handleEvent('onUpdateProgress', data));
|
|
133
|
+
const downloadedSub = emitter.addListener('onUpdateDownloaded', data => handleEvent('onUpdateDownloaded', data));
|
|
134
|
+
const installedSub = emitter.addListener('onUpdateInstalled', data => handleEvent('onUpdateInstalled', data));
|
|
135
|
+
const failedSub = emitter.addListener('onUpdateFailed', data => handleEvent('onUpdateFailed', data));
|
|
136
|
+
eventSubscription = {
|
|
137
|
+
remove: () => {
|
|
138
|
+
progressSub.remove();
|
|
139
|
+
downloadedSub.remove();
|
|
140
|
+
installedSub.remove();
|
|
141
|
+
failedSub.remove();
|
|
142
|
+
eventSubscription = null;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export function addUpdateListener(listener) {
|
|
147
|
+
if (Platform.OS !== 'android') {
|
|
148
|
+
return {
|
|
149
|
+
remove: () => {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
setupEventListener();
|
|
153
|
+
listeners.add(listener);
|
|
154
|
+
return {
|
|
155
|
+
remove: () => {
|
|
156
|
+
listeners.delete(listener);
|
|
157
|
+
if (listeners.size === 0 && eventSubscription) {
|
|
158
|
+
eventSubscription.remove();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Linking","Platform","NativeUpdatesModule","AppUpdateError","AppUpdateErrorCode","UpdateAvailability","isNewerVersion","getPackageName","packageName","getCurrentVersion","currentVersion","getCurrentBuildNumber","Number","parseInt","buildNumber","getCountry","country","getLatestVersion","options","OS","info","getAppStoreVersion","forceRefresh","version","checkPlayStoreUpdate","updateAvailability","UPDATE_AVAILABLE","availableVersionCode","toString","UNKNOWN","getStoreUrl","trackViewUrl","toLowerCase","needUpdate","depth","POSITIVE_INFINITY","latestVersion","storeUrl","isNeeded","openStore","url","canOpen","canOpenURL","openURL","getAppStoreInfo","startInAppUpdate","type","startUpdate","completeInAppUpdate","completeUpdate","eventSubscription","listeners","Set","setupEventListener","EventEmitter","require","emitter","handleEvent","_eventName","data","state","installStatus","bytesDownloaded","totalBytesToDownload","downloadProgress","listener","progressSub","addListener","downloadedSub","installedSub","failedSub","remove","addUpdateListener","add","delete","size"],"sourceRoot":"../../src","sources":["api.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useAppUpdate"],"sourceRoot":"../../../src","sources":["hooks/index.ts"],"mappings":";;AAAA,SAASA,YAAY,QAAQ,mBAAgB","ignoreList":[]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { Platform } from 'react-native';
|
|
5
|
+
import { addUpdateListener, checkPlayStoreUpdate, completeInAppUpdate, getCurrentVersion, needUpdate, openStore, startInAppUpdate } from "../api.js";
|
|
6
|
+
import { AppUpdateError, AppUpdateErrorCode, InstallStatus, UpdateAvailability } from "../types.js";
|
|
7
|
+
export function useAppUpdate(options) {
|
|
8
|
+
const [isChecking, setIsChecking] = useState(false);
|
|
9
|
+
const [isUpdateAvailable, setIsUpdateAvailable] = useState(false);
|
|
10
|
+
const [currentVersion] = useState(getCurrentVersion);
|
|
11
|
+
const [latestVersion, setLatestVersion] = useState(null);
|
|
12
|
+
const [storeUrl, setStoreUrl] = useState(null);
|
|
13
|
+
const [error, setError] = useState(null);
|
|
14
|
+
const [isDownloading, setIsDownloading] = useState(false);
|
|
15
|
+
const [downloadProgress, setDownloadProgress] = useState(0);
|
|
16
|
+
const [isReadyToInstall, setIsReadyToInstall] = useState(false);
|
|
17
|
+
const [playStoreInfo, setPlayStoreInfo] = useState(null);
|
|
18
|
+
const subscriptionRef = useRef(null);
|
|
19
|
+
const mountedRef = useRef(true);
|
|
20
|
+
const checkUpdate = useCallback(async () => {
|
|
21
|
+
if (!mountedRef.current) return;
|
|
22
|
+
setIsChecking(true);
|
|
23
|
+
setError(null);
|
|
24
|
+
try {
|
|
25
|
+
const result = await needUpdate({
|
|
26
|
+
country: options?.country,
|
|
27
|
+
forceRefresh: true
|
|
28
|
+
});
|
|
29
|
+
if (!mountedRef.current) return;
|
|
30
|
+
setIsUpdateAvailable(result.isNeeded);
|
|
31
|
+
setLatestVersion(result.latestVersion);
|
|
32
|
+
setStoreUrl(result.storeUrl);
|
|
33
|
+
if (Platform.OS === 'android') {
|
|
34
|
+
try {
|
|
35
|
+
const info = await checkPlayStoreUpdate();
|
|
36
|
+
if (mountedRef.current) {
|
|
37
|
+
setPlayStoreInfo(info);
|
|
38
|
+
setIsUpdateAvailable(info.updateAvailability === UpdateAvailability.UPDATE_AVAILABLE);
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
if (mountedRef.current) {
|
|
42
|
+
setPlayStoreInfo(null);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch (e) {
|
|
47
|
+
if (!mountedRef.current) return;
|
|
48
|
+
const appError = e instanceof AppUpdateError ? e : new AppUpdateError(AppUpdateErrorCode.CHECK_FAILED, String(e));
|
|
49
|
+
setError(appError);
|
|
50
|
+
options?.onError?.(appError);
|
|
51
|
+
} finally {
|
|
52
|
+
if (mountedRef.current) {
|
|
53
|
+
setIsChecking(false);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, [options?.country, options?.onError]);
|
|
57
|
+
const handleOpenStore = useCallback(async () => {
|
|
58
|
+
try {
|
|
59
|
+
await openStore({
|
|
60
|
+
country: options?.country
|
|
61
|
+
});
|
|
62
|
+
} catch (e) {
|
|
63
|
+
const appError = e instanceof AppUpdateError ? e : new AppUpdateError(AppUpdateErrorCode.UNKNOWN, String(e));
|
|
64
|
+
setError(appError);
|
|
65
|
+
options?.onError?.(appError);
|
|
66
|
+
}
|
|
67
|
+
}, [options?.country, options?.onError]);
|
|
68
|
+
const handleStartUpdate = useCallback(async type => {
|
|
69
|
+
if (Platform.OS !== 'android') return;
|
|
70
|
+
setError(null);
|
|
71
|
+
subscriptionRef.current?.remove();
|
|
72
|
+
subscriptionRef.current = addUpdateListener(state => {
|
|
73
|
+
if (!mountedRef.current) return;
|
|
74
|
+
setDownloadProgress(state.downloadProgress);
|
|
75
|
+
if (state.installStatus === InstallStatus.DOWNLOADING) {
|
|
76
|
+
setIsDownloading(true);
|
|
77
|
+
setIsReadyToInstall(false);
|
|
78
|
+
} else if (state.installStatus === InstallStatus.DOWNLOADED) {
|
|
79
|
+
setIsDownloading(false);
|
|
80
|
+
setIsReadyToInstall(true);
|
|
81
|
+
} else if (state.installStatus === InstallStatus.INSTALLED || state.installStatus === InstallStatus.FAILED || state.installStatus === InstallStatus.CANCELED) {
|
|
82
|
+
setIsDownloading(false);
|
|
83
|
+
if (state.installStatus !== InstallStatus.INSTALLED) {
|
|
84
|
+
setIsReadyToInstall(false);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
await startInAppUpdate(type);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
const appError = e instanceof AppUpdateError ? e : new AppUpdateError(AppUpdateErrorCode.UPDATE_FAILED, String(e));
|
|
92
|
+
setError(appError);
|
|
93
|
+
options?.onError?.(appError);
|
|
94
|
+
}
|
|
95
|
+
}, [options?.onError]);
|
|
96
|
+
const handleCompleteUpdate = useCallback(async () => {
|
|
97
|
+
if (Platform.OS !== 'android') return;
|
|
98
|
+
try {
|
|
99
|
+
completeInAppUpdate();
|
|
100
|
+
} catch (e) {
|
|
101
|
+
const appError = e instanceof AppUpdateError ? e : new AppUpdateError(AppUpdateErrorCode.UPDATE_FAILED, String(e));
|
|
102
|
+
setError(appError);
|
|
103
|
+
options?.onError?.(appError);
|
|
104
|
+
}
|
|
105
|
+
}, [options?.onError]);
|
|
106
|
+
|
|
107
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: checkOnMount is intentionally only checked once on mount
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
mountedRef.current = true;
|
|
110
|
+
if (options?.checkOnMount) {
|
|
111
|
+
checkUpdate();
|
|
112
|
+
}
|
|
113
|
+
return () => {
|
|
114
|
+
mountedRef.current = false;
|
|
115
|
+
subscriptionRef.current?.remove();
|
|
116
|
+
};
|
|
117
|
+
}, []);
|
|
118
|
+
return {
|
|
119
|
+
isChecking,
|
|
120
|
+
isUpdateAvailable,
|
|
121
|
+
currentVersion,
|
|
122
|
+
latestVersion,
|
|
123
|
+
storeUrl,
|
|
124
|
+
error,
|
|
125
|
+
isDownloading,
|
|
126
|
+
downloadProgress,
|
|
127
|
+
isReadyToInstall,
|
|
128
|
+
playStoreInfo,
|
|
129
|
+
checkUpdate,
|
|
130
|
+
openStore: handleOpenStore,
|
|
131
|
+
startUpdate: handleStartUpdate,
|
|
132
|
+
completeUpdate: handleCompleteUpdate
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=useAppUpdate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useRef","useState","Platform","addUpdateListener","checkPlayStoreUpdate","completeInAppUpdate","getCurrentVersion","needUpdate","openStore","startInAppUpdate","AppUpdateError","AppUpdateErrorCode","InstallStatus","UpdateAvailability","useAppUpdate","options","isChecking","setIsChecking","isUpdateAvailable","setIsUpdateAvailable","currentVersion","latestVersion","setLatestVersion","storeUrl","setStoreUrl","error","setError","isDownloading","setIsDownloading","downloadProgress","setDownloadProgress","isReadyToInstall","setIsReadyToInstall","playStoreInfo","setPlayStoreInfo","subscriptionRef","mountedRef","checkUpdate","current","result","country","forceRefresh","isNeeded","OS","info","updateAvailability","UPDATE_AVAILABLE","e","appError","CHECK_FAILED","String","onError","handleOpenStore","UNKNOWN","handleStartUpdate","type","remove","state","installStatus","DOWNLOADING","DOWNLOADED","INSTALLED","FAILED","CANCELED","UPDATE_FAILED","handleCompleteUpdate","checkOnMount","startUpdate","completeUpdate"],"sourceRoot":"../../../src","sources":["hooks/useAppUpdate.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export { addUpdateListener, checkPlayStoreUpdate, completeInAppUpdate, getAppStoreInfo, getCountry, getCurrentBuildNumber, getCurrentVersion, getLatestVersion, getPackageName, getStoreUrl, needUpdate, openStore, startInAppUpdate } from "./api.js";
|
|
4
|
+
export { useAppUpdate } from "./hooks/index.js";
|
|
5
|
+
export { AppUpdateError, AppUpdateErrorCode, InstallStatus, UpdateAvailability, UpdateType } from "./types.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["addUpdateListener","checkPlayStoreUpdate","completeInAppUpdate","getAppStoreInfo","getCountry","getCurrentBuildNumber","getCurrentVersion","getLatestVersion","getPackageName","getStoreUrl","needUpdate","openStore","startInAppUpdate","useAppUpdate","AppUpdateError","AppUpdateErrorCode","InstallStatus","UpdateAvailability","UpdateType"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SACEA,iBAAiB,EACjBC,oBAAoB,EACpBC,mBAAmB,EACnBC,eAAe,EACfC,UAAU,EACVC,qBAAqB,EACrBC,iBAAiB,EACjBC,gBAAgB,EAChBC,cAAc,EACdC,WAAW,EACXC,UAAU,EACVC,SAAS,EACTC,gBAAgB,QACX,UAAO;AACd,SAASC,YAAY,QAAQ,kBAAS;AACtC,SAEEC,cAAc,EACdC,kBAAkB,EAIlBC,aAAa,EAMbC,kBAAkB,EAGlBC,UAAU,QAGL,YAAS","ignoreList":[]}
|