@appcircle/react-native-code-push 0.0.4-alpha.1 → 0.1.0-alpha.1

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/CodePush.podspec CHANGED
@@ -16,6 +16,7 @@ Pod::Spec.new do |s|
16
16
  s.library = 'z'
17
17
  s.source_files = 'ios/CodePush/*.{h,m}'
18
18
  s.public_header_files = ['ios/CodePush/CodePush.h']
19
+ s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" }
19
20
 
20
21
  # Note: Even though there are copy/pasted versions of some of these dependencies in the repo,
21
22
  # we explicitly let CocoaPods pull in the versions below so all dependencies are resolved and
package/README.md CHANGED
@@ -37,6 +37,16 @@ Run the following command to add the Appcircle CodePush SDK to your project.
37
37
  npm install @appcircle/react-native-code-push
38
38
  ```
39
39
 
40
+ ## Supported Versions
41
+
42
+ | React Native version(s) | Supporting CodePush version(s) |
43
+ | --- | --- |
44
+ | `<v0.76` | Consider `microsoft/code-push-react-native` |
45
+ | `v0.76`, `v0.77`, `v0.78`, `v0.79` | `v0.0.3+` (Available for Old/New Architecture) |
46
+ | `v0.80` | `v0.0.4+` (Available for Old/New Architecture) |
47
+ | `v0.81+` | `v0.1.0+` (Available for Old/New Architecture) |
48
+ | `v0.82+` | `v0.1.0+` (Available for New Architecture) |
49
+
40
50
  ## Platform Setup
41
51
 
42
52
  ### iOS Setup
@@ -10,10 +10,6 @@ def isNewArchitectureEnabled() {
10
10
 
11
11
  def IS_NEW_ARCHITECTURE_ENABLED = isNewArchitectureEnabled()
12
12
 
13
- if (IS_NEW_ARCHITECTURE_ENABLED) {
14
- apply plugin: "com.facebook.react"
15
- }
16
-
17
13
  def DEFAULT_COMPILE_SDK_VERSION = 26
18
14
  def DEFAULT_BUILD_TOOLS_VERSION = "26.0.3"
19
15
  def DEFAULT_TARGET_SDK_VERSION = 26
@@ -40,9 +36,13 @@ android {
40
36
  defaultConfig {
41
37
  consumerProguardFiles 'proguard-rules.pro'
42
38
  }
39
+
40
+ buildFeatures {
41
+ buildConfig true
42
+ }
43
43
  }
44
44
 
45
45
  dependencies {
46
- implementation "com.facebook.react:react-native:+"
46
+ implementation 'com.facebook.react:react-android:0.82.1'
47
47
  implementation 'com.nimbusds:nimbus-jose-jwt:9.37.3'
48
48
  }
@@ -141,10 +141,10 @@ public class CodePush implements ReactPackage {
141
141
 
142
142
  private String getCustomPropertyFromStringsIfExist(String propertyName) {
143
143
  String property;
144
-
144
+
145
145
  String packageName = mContext.getPackageName();
146
146
  int resId = mContext.getResources().getIdentifier("CodePush" + propertyName, "string", packageName);
147
-
147
+
148
148
  if (resId != 0) {
149
149
  property = mContext.getString(resId);
150
150
 
@@ -152,7 +152,7 @@ public class CodePush implements ReactPackage {
152
152
  return property;
153
153
  } else {
154
154
  CodePushUtils.log("Specified " + propertyName + " is empty");
155
- }
155
+ }
156
156
  }
157
157
 
158
158
  return null;
@@ -402,10 +402,6 @@ public class CodePush implements ReactPackage {
402
402
  mReactInstanceHolder = reactInstanceHolder;
403
403
  }
404
404
 
405
- public static void setReactHost(ReactHostHolder reactHostHolder) {
406
- mReactHostHolder = reactHostHolder;
407
- }
408
-
409
405
  static ReactInstanceManager getReactInstanceManager() {
410
406
  if (mReactInstanceHolder == null) {
411
407
  return null;
@@ -413,6 +409,10 @@ public class CodePush implements ReactPackage {
413
409
  return mReactInstanceHolder.getReactInstanceManager();
414
410
  }
415
411
 
412
+ public static void setReactHost(ReactHostHolder reactHostHolder) {
413
+ mReactHostHolder = reactHostHolder;
414
+ }
415
+
416
416
  static ReactHost getReactHost() {
417
417
  if (mReactHostHolder == null) {
418
418
  return null;
@@ -432,13 +432,8 @@ public class CodePush implements ReactPackage {
432
432
  return nativeModules;
433
433
  }
434
434
 
435
- // Deprecated in RN v0.47.
436
- public List<Class<? extends JavaScriptModule>> createJSModules() {
437
- return new ArrayList<>();
438
- }
439
-
440
435
  @Override
441
436
  public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
442
437
  return new ArrayList<>();
443
438
  }
444
- }
439
+ }
@@ -118,6 +118,25 @@ public class CodePushNativeModule extends BaseJavaModule {
118
118
  });
119
119
  }
120
120
 
121
+ private Field findBundleLoaderField(Class<?> delegateClass) {
122
+ Class<?> currentClass = delegateClass;
123
+ while (currentClass != null) {
124
+ try {
125
+ return currentClass.getDeclaredField("jsBundleLoader");
126
+ } catch (NoSuchFieldException ignored) {
127
+ // Continue searching the class hierarchy and alternate field names.
128
+ }
129
+
130
+ try {
131
+ return currentClass.getDeclaredField("_jsBundleLoader");
132
+ } catch (NoSuchFieldException ignored) {
133
+ currentClass = currentClass.getSuperclass();
134
+ }
135
+ }
136
+
137
+ return null;
138
+ }
139
+
121
140
  // Use reflection to find and set the appropriate fields on ReactInstanceManager. See #556 for a proposal for a less brittle way
122
141
  // to approach this.
123
142
  private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBundleFile) throws IllegalAccessException {
@@ -149,10 +168,17 @@ public class CodePushNativeModule extends BaseJavaModule {
149
168
  latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
150
169
  }
151
170
 
152
- Field bundleLoaderField = reactHostDelegate.getClass().getDeclaredField("jsBundleLoader");
171
+ Field bundleLoaderField = findBundleLoaderField(reactHostDelegate.getClass());
172
+ if (bundleLoaderField == null) {
173
+ throw new NoSuchFieldException("jsBundleLoader");
174
+ }
153
175
  bundleLoaderField.setAccessible(true);
154
176
  bundleLoaderField.set(reactHostDelegate, latestJSBundleLoader);
155
- } catch (Exception e) {
177
+
178
+ } catch (NoSuchFieldException nsfe) {
179
+ CodePushUtils.log("Field 'jsBundleLoader' NOT FOUND on " + (reactHostDelegate != null ? reactHostDelegate.getClass().getName() : "null") + ". This is an EXPECTED and IGNORED failure with ExpoReactHostDelegate. Will rely on reactHost.reload(). Original log: Unable to set JSBundle of ReactHostDelegate - CodePush may not support this version of React Native");
180
+ // DO NOT THROW for NoSuchFieldException.
181
+ }catch (Exception e) {
156
182
  CodePushUtils.log("Unable to set JSBundle of ReactHostDelegate - CodePush may not support this version of React Native");
157
183
  throw new IllegalAccessException("Could not setJSBundle");
158
184
  }
@@ -177,18 +203,38 @@ public class CodePushNativeModule extends BaseJavaModule {
177
203
  mCodePush.clearDebugCacheIfNeeded(false);
178
204
  }
179
205
 
206
+
180
207
  try {
181
208
  // #1) Get the ReactHost instance, which is what includes the
182
209
  // logic to reload the current React context.
183
210
  final ReactHost reactHost = resolveReactHost();
184
211
  if (reactHost == null) {
212
+ loadBundleLegacy(); // Fallback if reactHost can't be resolved
185
213
  return;
186
214
  }
187
215
 
188
216
  String latestJSBundleFile = mCodePush.getJSBundleFileInternal(mCodePush.getAssetsBundleFileName());
217
+ CodePushUtils.log("[MyDebug] Latest JS bundle for New Arch: " + latestJSBundleFile);
189
218
 
190
- // #2) Update the locally stored JS bundle file path
191
- setJSBundle(getReactHostDelegate((ReactHostImpl) reactHost), latestJSBundleFile);
219
+
220
+ try {
221
+ if (reactHost instanceof ReactHostImpl) {
222
+ ReactHostDelegate delegate = getReactHostDelegate((ReactHostImpl) reactHost);
223
+ if (delegate != null) {
224
+ // #2) Update the locally stored JS bundle file path
225
+ setJSBundle(delegate, latestJSBundleFile);
226
+ } else {
227
+ CodePushUtils.log("Could not get ReactHostDelegate from ReactHostImpl.");
228
+ }
229
+ } else {
230
+ CodePushUtils.log("ReactHost is not a direct ReactHostImpl instance (" + reactHost.getClass().getName() + "), skipping direct setJSBundle reflection attempt. This is expected with Expo.");
231
+ }
232
+ } catch (ClassCastException cce) {
233
+ CodePushUtils.log(new Exception("ClassCastException trying to get/use ReactHostDelegate. Skipping reflection call to setJSBundle. This is expected for Expo.", cce));
234
+ }catch (Exception e) {
235
+ // Catch any unexpected errors from the attempt to call setJSBundle, e.g., if getReactHostDelegate itself fails
236
+ CodePushUtils.log("Exception during the reflective setJSBundle block: " + e.getMessage());
237
+ }
192
238
 
193
239
  // #3) Get the context creation method
194
240
  try {
@@ -201,8 +247,7 @@ public class CodePushNativeModule extends BaseJavaModule {
201
247
  }
202
248
 
203
249
  } catch (Exception e) {
204
- // Our reflection logic failed somewhere
205
- // so fall back to restarting the Activity (if it exists)
250
+ // reflection logic failed somewhere so fall back to restarting the Activity (if it exists)
206
251
  CodePushUtils.log("Failed to load the bundle, falling back to restarting the Activity (if it exists). " + e.getMessage());
207
252
  loadBundleLegacy();
208
253
  }
@@ -241,11 +286,6 @@ public class CodePushNativeModule extends BaseJavaModule {
241
286
  @Override
242
287
  public void run() {
243
288
  try {
244
- // We don't need to resetReactRootViews anymore
245
- // due the issue https://github.com/facebook/react-native/issues/14533
246
- // has been fixed in RN 0.46.0
247
- //resetReactRootViews(instanceManager);
248
-
249
289
  instanceManager.recreateReactContextInBackground();
250
290
  mCodePush.initializeUpdateAfterRestart();
251
291
  } catch (Exception e) {
@@ -284,20 +324,6 @@ public class CodePushNativeModule extends BaseJavaModule {
284
324
  return false;
285
325
  }
286
326
 
287
- // This workaround has been implemented in order to fix https://github.com/facebook/react-native/issues/14533
288
- // resetReactRootViews allows to call recreateReactContextInBackground without any exceptions
289
- // This fix also relates to https://github.com/microsoft/react-native-code-push/issues/878
290
- private void resetReactRootViews(ReactInstanceManager instanceManager) throws NoSuchFieldException, IllegalAccessException {
291
- Field mAttachedRootViewsField = instanceManager.getClass().getDeclaredField("mAttachedRootViews");
292
- mAttachedRootViewsField.setAccessible(true);
293
- List<ReactRootView> mAttachedRootViews = (List<ReactRootView>)mAttachedRootViewsField.get(instanceManager);
294
- for (ReactRootView reactRootView : mAttachedRootViews) {
295
- reactRootView.removeAllViews();
296
- reactRootView.setId(View.NO_ID);
297
- }
298
- mAttachedRootViewsField.set(instanceManager, mAttachedRootViews);
299
- }
300
-
301
327
  private void clearLifecycleEventListener() {
302
328
  // Remove LifecycleEventListener to prevent infinite restart loop
303
329
  if (mLifecycleEventListener != null) {
@@ -833,16 +859,29 @@ public class CodePushNativeModule extends BaseJavaModule {
833
859
  }
834
860
 
835
861
  public ReactHostDelegate getReactHostDelegate(ReactHostImpl reactHostImpl) {
836
- try {
837
- Class<?> clazz = reactHostImpl.getClass();
838
- Field field = clazz.getDeclaredField("mReactHostDelegate");
839
- field.setAccessible(true);
840
-
841
- // Get the value of the field for the provided instance
842
- return (ReactHostDelegate) field.get(reactHostImpl);
843
- } catch (NoSuchFieldException | IllegalAccessException e) {
844
- e.printStackTrace();
845
- return null;
862
+ Class<?> currentClass = reactHostImpl.getClass();
863
+
864
+ // Traverse up the class hierarchy in case the delegate field is declared in a parent.
865
+ while (currentClass != null) {
866
+ Field[] fields = currentClass.getDeclaredFields();
867
+
868
+ for (Field field : fields) {
869
+ try {
870
+ field.setAccessible(true);
871
+ Object value = field.get(reactHostImpl);
872
+
873
+ if (value instanceof ReactHostDelegate) {
874
+ return (ReactHostDelegate) value;
875
+ }
876
+ } catch (Exception ignored) {
877
+ // Keep scanning fields.
878
+ }
879
+ }
880
+
881
+ currentClass = currentClass.getSuperclass();
846
882
  }
883
+
884
+ CodePushUtils.log("Reflection failed: Could not find any field of type ReactHostDelegate in ReactHostImpl.");
885
+ return null;
847
886
  }
848
887
  }
@@ -157,6 +157,9 @@ public class CodePushUpdateManager {
157
157
 
158
158
  String downloadUrlString = updatePackage.optString(CodePushConstants.DOWNLOAD_URL_KEY, null);
159
159
  HttpURLConnection connection = null;
160
+ BufferedInputStream bin = null;
161
+ FileOutputStream fos = null;
162
+ BufferedOutputStream bout = null;
160
163
  File downloadFile = null;
161
164
  boolean isZip = false;
162
165
 
@@ -175,51 +178,52 @@ public class CodePushUpdateManager {
175
178
  }
176
179
 
177
180
  connection.setRequestProperty("Accept-Encoding", "identity");
181
+ bin = new BufferedInputStream(connection.getInputStream());
178
182
 
179
183
  long totalBytes = connection.getContentLength();
180
184
  long receivedBytes = 0;
181
185
 
182
186
  File downloadFolder = new File(getCodePushPath());
183
187
  downloadFolder.mkdirs();
184
-
185
188
  downloadFile = new File(downloadFolder, CodePushConstants.DOWNLOAD_FILE_NAME);
189
+ fos = new FileOutputStream(downloadFile);
190
+ bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE);
186
191
  byte[] data = new byte[CodePushConstants.DOWNLOAD_BUFFER_SIZE];
187
192
  byte[] header = new byte[4];
188
193
 
189
- try (
190
- BufferedInputStream bin = new BufferedInputStream(connection.getInputStream());
191
- FileOutputStream fos = new FileOutputStream(downloadFile);
192
- BufferedOutputStream bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE)
193
- ) {
194
- int numBytesRead = 0;
195
- while ((numBytesRead = bin.read(data, 0, CodePushConstants.DOWNLOAD_BUFFER_SIZE)) >= 0) {
196
- if (receivedBytes < 4) {
197
- for (int i = 0; i < numBytesRead; i++) {
198
- int headerOffset = (int) (receivedBytes) + i;
199
- if (headerOffset >= 4) {
200
- break;
201
- }
202
-
203
- header[headerOffset] = data[i];
194
+ int numBytesRead = 0;
195
+ while ((numBytesRead = bin.read(data, 0, CodePushConstants.DOWNLOAD_BUFFER_SIZE)) >= 0) {
196
+ if (receivedBytes < 4) {
197
+ for (int i = 0; i < numBytesRead; i++) {
198
+ int headerOffset = (int) (receivedBytes) + i;
199
+ if (headerOffset >= 4) {
200
+ break;
204
201
  }
205
- }
206
202
 
207
- receivedBytes += numBytesRead;
208
- bout.write(data, 0, numBytesRead);
209
- progressCallback.call(new DownloadProgress(totalBytes, receivedBytes));
203
+ header[headerOffset] = data[i];
204
+ }
210
205
  }
211
206
 
212
- if (totalBytes != receivedBytes) {
213
- throw new CodePushUnknownException("Received " + receivedBytes + " bytes, expected " + totalBytes);
214
- }
207
+ receivedBytes += numBytesRead;
208
+ bout.write(data, 0, numBytesRead);
209
+ progressCallback.call(new DownloadProgress(totalBytes, receivedBytes));
210
+ }
215
211
 
216
- isZip = ByteBuffer.wrap(header).getInt() == 0x504b0304;
212
+ if (totalBytes != receivedBytes) {
213
+ throw new CodePushUnknownException("Received " + receivedBytes + " bytes, expected " + totalBytes);
217
214
  }
215
+
216
+ isZip = ByteBuffer.wrap(header).getInt() == 0x504b0304;
218
217
  } catch (MalformedURLException e) {
219
218
  throw new CodePushMalformedDataException(downloadUrlString, e);
220
219
  } finally {
221
- if (connection != null) {
222
- connection.disconnect();
220
+ try {
221
+ if (bout != null) bout.close();
222
+ if (fos != null) fos.close();
223
+ if (bin != null) bin.close();
224
+ if (connection != null) connection.disconnect();
225
+ } catch (IOException e) {
226
+ throw new CodePushUnknownException("Error closing IO resources.", e);
223
227
  }
224
228
  }
225
229
 
@@ -343,35 +347,32 @@ public class CodePushUpdateManager {
343
347
  public void downloadAndReplaceCurrentBundle(String remoteBundleUrl, String bundleFileName) throws IOException {
344
348
  URL downloadUrl;
345
349
  HttpURLConnection connection = null;
346
-
350
+ BufferedInputStream bin = null;
351
+ FileOutputStream fos = null;
352
+ BufferedOutputStream bout = null;
347
353
  try {
348
354
  downloadUrl = new URL(remoteBundleUrl);
349
355
  connection = (HttpURLConnection) (downloadUrl.openConnection());
350
-
356
+ bin = new BufferedInputStream(connection.getInputStream());
351
357
  File downloadFile = new File(getCurrentPackageBundlePath(bundleFileName));
352
- if (downloadFile.exists() && !downloadFile.delete()) {
353
- // Silent failure, but execution continues
354
- }
355
-
356
- try (
357
- BufferedInputStream bin = new BufferedInputStream(connection.getInputStream());
358
- FileOutputStream fos = new FileOutputStream(downloadFile);
359
- BufferedOutputStream bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE)
360
- ) {
361
- byte[] data = new byte[CodePushConstants.DOWNLOAD_BUFFER_SIZE];
362
- int numBytesRead;
363
- while ((numBytesRead = bin.read(data, 0, CodePushConstants.DOWNLOAD_BUFFER_SIZE)) >= 0) {
364
- bout.write(data, 0, numBytesRead);
365
- }
358
+ downloadFile.delete();
359
+ fos = new FileOutputStream(downloadFile);
360
+ bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE);
361
+ byte[] data = new byte[CodePushConstants.DOWNLOAD_BUFFER_SIZE];
362
+ int numBytesRead = 0;
363
+ while ((numBytesRead = bin.read(data, 0, CodePushConstants.DOWNLOAD_BUFFER_SIZE)) >= 0) {
364
+ bout.write(data, 0, numBytesRead);
366
365
  }
367
-
368
366
  } catch (MalformedURLException e) {
369
367
  throw new CodePushMalformedDataException(remoteBundleUrl, e);
370
- } catch (IOException e) {
371
- throw new CodePushUnknownException("Error handling IO streams.", e);
372
368
  } finally {
373
- if (connection != null) {
374
- connection.disconnect();
369
+ try {
370
+ if (bout != null) bout.close();
371
+ if (fos != null) fos.close();
372
+ if (bin != null) bin.close();
373
+ if (connection != null) connection.disconnect();
374
+ } catch (IOException e) {
375
+ throw new CodePushUnknownException("Error closing IO resources.", e);
375
376
  }
376
377
  }
377
378
  }
@@ -379,4 +380,4 @@ public class CodePushUpdateManager {
379
380
  public void clearUpdates() {
380
381
  FileUtils.deleteDirectoryAtPath(getCodePushPath());
381
382
  }
382
- }
383
+ }
@@ -62,14 +62,11 @@ public class CodePushUpdateUtils {
62
62
  if (file.isDirectory()) {
63
63
  addContentsOfFolderToManifest(fullFilePath, relativePath, manifest);
64
64
  } else {
65
- try (FileInputStream fis = new FileInputStream(file)) {
66
- manifest.add(relativePath + ":" + computeHash(fis));
65
+ try {
66
+ manifest.add(relativePath + ":" + computeHash(new FileInputStream(file)));
67
67
  } catch (FileNotFoundException e) {
68
68
  // Should not happen.
69
69
  throw new CodePushUnknownException("Unable to compute hash of update contents.", e);
70
- } catch (IOException e) {
71
- // Should not happen.
72
- throw new CodePushUnknownException("Error occurred while reading file for hashing.", e);
73
70
  }
74
71
  }
75
72
  }
@@ -275,4 +272,4 @@ public class CodePushUpdateUtils {
275
272
 
276
273
  CodePushUtils.log("The update contents succeeded the code signing check.");
277
274
  }
278
- }
275
+ }
@@ -29,19 +29,26 @@ public class FileUtils {
29
29
  CodePushUtils.appendPathComponent(destinationDirectoryPath, sourceFile.getName()));
30
30
  } else {
31
31
  File destFile = new File(destDir, sourceFile.getName());
32
+ FileInputStream fromFileStream = null;
33
+ BufferedInputStream fromBufferedStream = null;
34
+ FileOutputStream destStream = null;
32
35
  byte[] buffer = new byte[WRITE_BUFFER_SIZE];
33
- try (
34
- FileInputStream fromFileStream = new FileInputStream(sourceFile);
35
- BufferedInputStream fromBufferedStream = new BufferedInputStream(fromFileStream);
36
- FileOutputStream destStream = new FileOutputStream(destFile)
37
- )
38
- {
36
+ try {
37
+ fromFileStream = new FileInputStream(sourceFile);
38
+ fromBufferedStream = new BufferedInputStream(fromFileStream);
39
+ destStream = new FileOutputStream(destFile);
39
40
  int bytesRead;
40
41
  while ((bytesRead = fromBufferedStream.read(buffer)) > 0) {
41
42
  destStream.write(buffer, 0, bytesRead);
42
43
  }
43
- } catch (IOException e) {
44
- throw new CodePushUnknownException("Error closing IO resources.", e);
44
+ } finally {
45
+ try {
46
+ if (fromFileStream != null) fromFileStream.close();
47
+ if (fromBufferedStream != null) fromBufferedStream.close();
48
+ if (destStream != null) destStream.close();
49
+ } catch (IOException e) {
50
+ throw new CodePushUnknownException("Error closing IO resources.", e);
51
+ }
45
52
  }
46
53
  }
47
54
  }
@@ -193,4 +200,4 @@ public class FileUtils {
193
200
  if (out != null) out.close();
194
201
  }
195
202
  }
196
- }
203
+ }
@@ -14,7 +14,4 @@ public interface ReactInstanceHolder {
14
14
  * Get the current {@link ReactInstanceManager} instance. May return null.
15
15
  */
16
16
  ReactInstanceManager getReactInstanceManager();
17
-
18
-
19
-
20
17
  }
@@ -6,7 +6,8 @@ buildscript {
6
6
  mavenCentral()
7
7
  }
8
8
  dependencies {
9
- classpath 'com.android.tools.build:gradle:1.3.0'
9
+ classpath("com.android.tools.build:gradle:8.12.0")
10
+ classpath("com.facebook.react:react-native-gradle-plugin")
10
11
 
11
12
  // NOTE: Do not place your application dependencies here; they belong
12
13
  // in the individual module build.gradle files
@@ -14,10 +15,8 @@ buildscript {
14
15
  }
15
16
 
16
17
  allprojects {
17
- android {
18
- namespace "com.microsoft.codepush.react"
19
- }
20
18
  repositories {
19
+ google()
21
20
  mavenLocal()
22
21
  mavenCentral()
23
22
  }
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
2
2
  distributionPath=wrapper/dists
3
3
  zipStoreBase=GRADLE_USER_HOME
4
4
  zipStorePath=wrapper/dists
5
- distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
5
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
@@ -16,5 +16,3 @@
16
16
  # This option should only be used with decoupled projects. More details, visit
17
17
  # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18
18
  # org.gradle.parallel=true
19
-
20
- android.useDeprecatedNdk=true
@@ -1 +1,2 @@
1
- include ':app'
1
+ include ':app'
2
+ includeBuild('../node_modules/@react-native/gradle-plugin')
@@ -32,7 +32,7 @@
32
32
  long long _latestExpectedContentLength;
33
33
  long long _latestReceivedConentLength;
34
34
  BOOL _didUpdateProgress;
35
-
35
+
36
36
  BOOL _allowed;
37
37
  BOOL _restartInProgress;
38
38
  NSMutableArray *_restartQueue;
@@ -377,7 +377,7 @@ static NSString *const LatestRollbackCountKey = @"count";
377
377
  _allowed = YES;
378
378
  _restartInProgress = NO;
379
379
  _restartQueue = [NSMutableArray arrayWithCapacity:1];
380
-
380
+
381
381
  self = [super init];
382
382
  if (self) {
383
383
  [self initializeUpdateAfterRestart];
@@ -538,10 +538,19 @@ static NSString *const LatestRollbackCountKey = @"count";
538
538
  // file (since Chrome wouldn't support it). Otherwise, update
539
539
  // the current bundle URL to point at the latest update
540
540
  if ([CodePush isUsingTestConfiguration] || ![super.bridge.bundleURL.scheme hasPrefix:@"http"]) {
541
- [super.bridge setValue:[CodePush bundleURL] forKey:@"bundleURL"];
541
+ RCTReloadCommandSetBundleURL([CodePush bundleURL]);
542
+ // [super.bridge setValue:[CodePush bundleURL] forKey:@"bundleURL"];
542
543
  }
543
544
 
544
- RCTTriggerReloadCommandListeners(@"react-native-code-push: Restart");
545
+ // Add a small delay to ensure Fabric surface initialization is complete
546
+ // before triggering reload. This fixes a race condition in React Native 0.82+
547
+ // with New Architecture where RCTInstance invalidate and RCTFabricSurface start
548
+ // can run concurrently, causing a crash when MountingCoordinator's mutex is accessed
549
+ // after being destroyed.
550
+ //
551
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
552
+ RCTTriggerReloadCommandListeners(@"react-native-code-push: Restart");
553
+ });
545
554
  });
546
555
  }
547
556
 
@@ -744,8 +753,8 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
744
753
  if (expectedContentLength == receivedContentLength) {
745
754
  _didUpdateProgress = NO;
746
755
  self.paused = YES;
747
- [self dispatchDownloadProgressEvent];
748
756
  }
757
+ [self dispatchDownloadProgressEvent];
749
758
  }
750
759
  // The download completed
751
760
  doneCallback:^{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appcircle/react-native-code-push",
3
- "version": "0.0.4-alpha.1",
3
+ "version": "0.1.0-alpha.1",
4
4
  "description": "React Native plugin for the CodePush service",
5
5
  "main": "CodePush.js",
6
6
  "typings": "typings/react-native-code-push.d.ts",
@@ -53,6 +53,7 @@
53
53
  "xcode": "3.0.1"
54
54
  },
55
55
  "devDependencies": {
56
+ "react-native": "0.82.1",
56
57
  "@types/assert": "^1.5.2",
57
58
  "@types/mkdirp": "^1.0.1",
58
59
  "@types/mocha": "^9.0.0",
@@ -83,8 +84,8 @@
83
84
  ]
84
85
  },
85
86
  "commands": {
86
- "postlink": "node node_modules/react-native-code-push/scripts/postlink/run",
87
- "postunlink": "node node_modules/react-native-code-push/scripts/postunlink/run"
87
+ "postlink": "node node_modules/@appcircle/react-native-code-push/scripts/postlink/run",
88
+ "postunlink": "node node_modules/@appcircle/react-native-code-push/scripts/postunlink/run"
88
89
  }
89
90
  }
90
91
  }
@@ -8,4 +8,4 @@ module.exports = {
8
8
  }
9
9
  }
10
10
  }
11
- };
11
+ };
@@ -13,7 +13,7 @@ exports.getJSBundleFileOverride = `
13
13
  `;
14
14
  exports.reactNativeHostInstantiation = "new ReactNativeHost(this) {";
15
15
  exports.mainActivityClassDeclaration = "public class MainActivity extends ReactActivity {";
16
- exports.codePushGradleLink = `\napply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`;
16
+ exports.codePushGradleLink = `\napply from: "../../node_modules/@appcircle/react-native-code-push/android/codepush.gradle"`;
17
17
  exports.deploymentKeyName = "CodePushDeploymentKey";
18
18
 
19
19
  exports.getMainApplicationLocation = function () {