react-native-stallion 1.1.2 → 2.0.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.
Files changed (209) hide show
  1. package/android/src/main/java/com/stallion/Stallion.java +94 -10
  2. package/android/src/main/java/com/stallion/StallionApiUtil.java +58 -0
  3. package/android/src/main/java/com/stallion/StallionCommonUtil.java +25 -0
  4. package/android/src/main/java/com/stallion/StallionConstants.java +51 -15
  5. package/android/src/main/java/com/stallion/StallionDownloadCallback.java +7 -0
  6. package/android/src/main/java/com/stallion/StallionDownloadManager.java +121 -0
  7. package/android/src/main/java/com/stallion/StallionErrorBoundary.java +28 -4
  8. package/android/src/main/java/com/stallion/StallionEventEmitter.java +144 -0
  9. package/android/src/main/java/com/stallion/StallionFileUtil.java +129 -0
  10. package/android/src/main/java/com/stallion/StallionModule.java +100 -154
  11. package/android/src/main/java/com/stallion/StallionRollbackManager.java +82 -0
  12. package/android/src/main/java/com/stallion/StallionStorage.java +16 -6
  13. package/android/src/main/java/com/stallion/StallionSynManager.java +142 -0
  14. package/ios/main/Stallion-Bridging-Header.h +4 -0
  15. package/ios/main/Stallion.m +7 -5
  16. package/ios/main/Stallion.swift +80 -39
  17. package/ios/main/StallionConstants.swift +52 -10
  18. package/ios/main/StallionDownloader.swift +39 -52
  19. package/ios/main/StallionErrorBoundary.h +1 -1
  20. package/ios/main/StallionErrorBoundary.m +45 -28
  21. package/ios/main/StallionEventEmitter.swift +20 -0
  22. package/ios/main/StallionEventManager.h +21 -0
  23. package/ios/main/StallionEventManager.m +57 -0
  24. package/ios/main/StallionModule.m +107 -23
  25. package/ios/main/StallionObjConstants.h +46 -0
  26. package/ios/main/StallionObjConstants.m +124 -0
  27. package/ios/main/StallionObjUtil.h +14 -0
  28. package/ios/main/StallionObjUtil.m +22 -0
  29. package/ios/main/StallionRollbackHandler.h +22 -0
  30. package/ios/main/StallionRollbackHandler.m +128 -0
  31. package/ios/main/StallionSyncManager.swift +149 -0
  32. package/ios/main/StallionUtil.swift +2 -12
  33. package/package.json +6 -2
  34. package/src/index.js +5 -15
  35. package/src/index.js.map +1 -1
  36. package/src/main/components/common/ButtonFullWidth/styles.js +2 -2
  37. package/src/main/components/common/ButtonFullWidth/styles.js.map +1 -1
  38. package/src/main/components/common/Footer/index.js +24 -31
  39. package/src/main/components/common/Footer/index.js.map +1 -1
  40. package/src/main/components/common/Footer/styles.js +34 -33
  41. package/src/main/components/common/Footer/styles.js.map +1 -1
  42. package/src/main/components/common/Header/index.js +12 -8
  43. package/src/main/components/common/Header/index.js.map +1 -1
  44. package/src/main/components/common/Header/styles.js +10 -5
  45. package/src/main/components/common/Header/styles.js.map +1 -1
  46. package/src/main/components/common/ProfileOverlay/index.js +18 -7
  47. package/src/main/components/common/ProfileOverlay/index.js.map +1 -1
  48. package/src/main/components/common/ProfileOverlay/styles.js +41 -8
  49. package/src/main/components/common/ProfileOverlay/styles.js.map +1 -1
  50. package/src/main/components/common/Spinner/index.js +3 -1
  51. package/src/main/components/common/Spinner/index.js.map +1 -1
  52. package/src/main/components/modules/listing/components/BucketCard.js +3 -3
  53. package/src/main/components/modules/listing/components/BucketCard.js.map +1 -1
  54. package/src/main/components/modules/listing/components/BundleCard.js +9 -5
  55. package/src/main/components/modules/listing/components/BundleCard.js.map +1 -1
  56. package/src/main/components/modules/listing/components/BundleCardInfoSection.js +20 -12
  57. package/src/main/components/modules/listing/components/BundleCardInfoSection.js.map +1 -1
  58. package/src/main/components/modules/listing/components/CardDescriptionContent.js +3 -2
  59. package/src/main/components/modules/listing/components/CardDescriptionContent.js.map +1 -1
  60. package/src/main/components/modules/listing/components/MetaCard.js +38 -0
  61. package/src/main/components/modules/listing/components/MetaCard.js.map +1 -0
  62. package/src/main/components/modules/listing/components/SlotView.js +82 -0
  63. package/src/main/components/modules/listing/components/SlotView.js.map +1 -0
  64. package/src/main/components/modules/listing/components/styles/index.js +28 -9
  65. package/src/main/components/modules/listing/components/styles/index.js.map +1 -1
  66. package/src/main/components/modules/listing/hooks/useListing.js +9 -2
  67. package/src/main/components/modules/listing/hooks/useListing.js.map +1 -1
  68. package/src/main/components/modules/listing/index.js +12 -4
  69. package/src/main/components/modules/listing/index.js.map +1 -1
  70. package/src/main/components/modules/login/components/styles/index.js +4 -4
  71. package/src/main/components/modules/login/components/styles/index.js.map +1 -1
  72. package/src/main/components/modules/login/index.js +1 -1
  73. package/src/main/components/modules/login/index.js.map +1 -1
  74. package/src/main/components/modules/login/styles/index.js +7 -6
  75. package/src/main/components/modules/login/styles/index.js.map +1 -1
  76. package/src/main/components/modules/modal/StallionModal.js +13 -11
  77. package/src/main/components/modules/modal/StallionModal.js.map +1 -1
  78. package/src/main/components/modules/modal/hooks/useStallionModal.js +87 -24
  79. package/src/main/components/modules/modal/hooks/useStallionModal.js.map +1 -1
  80. package/src/main/components/modules/prod/index.js +3 -0
  81. package/src/main/components/modules/prod/index.js.map +1 -0
  82. package/src/main/components/modules/prod/prod.js +35 -0
  83. package/src/main/components/modules/prod/prod.js.map +1 -0
  84. package/src/main/components/modules/prod/styles/index.js +20 -0
  85. package/src/main/components/modules/prod/styles/index.js.map +1 -0
  86. package/src/main/constants/apiConstants.js +3 -1
  87. package/src/main/constants/apiConstants.js.map +1 -1
  88. package/src/main/constants/appConstants.js +40 -4
  89. package/src/main/constants/appConstants.js.map +1 -1
  90. package/src/main/constants/colors.js +8 -6
  91. package/src/main/constants/colors.js.map +1 -1
  92. package/src/main/state/actionCreators/useDownloadActions.js +17 -37
  93. package/src/main/state/actionCreators/useDownloadActions.js.map +1 -1
  94. package/src/main/state/actionCreators/useMetaActions.js +4 -5
  95. package/src/main/state/actionCreators/useMetaActions.js.map +1 -1
  96. package/src/main/state/actionCreators/useUpdateMetaActions.js +100 -0
  97. package/src/main/state/actionCreators/useUpdateMetaActions.js.map +1 -0
  98. package/src/main/state/actionCreators/useUserActions.js +4 -4
  99. package/src/main/state/actionCreators/useUserActions.js.map +1 -1
  100. package/src/main/state/index.js +15 -2
  101. package/src/main/state/index.js.map +1 -1
  102. package/src/main/state/reducers/updateMetaReducer.js +36 -0
  103. package/src/main/state/reducers/updateMetaReducer.js.map +1 -0
  104. package/src/main/utils/ErrorBoundary.js +15 -14
  105. package/src/main/utils/ErrorBoundary.js.map +1 -1
  106. package/src/main/utils/EventUtil.js +28 -0
  107. package/src/main/utils/EventUtil.js.map +1 -0
  108. package/src/main/utils/SharedDataManager.js +15 -12
  109. package/src/main/utils/SharedDataManager.js.map +1 -1
  110. package/src/main/utils/StallionEventEmitter.js +20 -0
  111. package/src/main/utils/StallionEventEmitter.js.map +1 -0
  112. package/src/main/utils/StallionNativeUtils.js +60 -0
  113. package/src/main/utils/StallionNativeUtils.js.map +1 -0
  114. package/src/main/utils/apiUtils.js +8 -0
  115. package/src/main/utils/apiUtils.js.map +1 -1
  116. package/src/main/utils/useStallionModal.js +4 -3
  117. package/src/main/utils/useStallionModal.js.map +1 -1
  118. package/src/main/utils/useStallionUpdate.js +13 -0
  119. package/src/main/utils/useStallionUpdate.js.map +1 -0
  120. package/src/main/utils/withStallion.js +1 -4
  121. package/src/main/utils/withStallion.js.map +1 -1
  122. package/src/types/meta.types.js +13 -0
  123. package/src/types/meta.types.js.map +1 -1
  124. package/src/types/updateMeta.types.js +7 -0
  125. package/src/types/updateMeta.types.js.map +1 -0
  126. package/types/index.d.ts +3 -0
  127. package/types/index.d.ts.map +1 -1
  128. package/types/main/components/common/Footer/index.d.ts +1 -4
  129. package/types/main/components/common/Footer/index.d.ts.map +1 -1
  130. package/types/main/components/common/Footer/styles.d.ts +30 -29
  131. package/types/main/components/common/Footer/styles.d.ts.map +1 -1
  132. package/types/main/components/common/Header/index.d.ts.map +1 -1
  133. package/types/main/components/common/Header/styles.d.ts +6 -1
  134. package/types/main/components/common/Header/styles.d.ts.map +1 -1
  135. package/types/main/components/common/ProfileOverlay/index.d.ts.map +1 -1
  136. package/types/main/components/common/ProfileOverlay/styles.d.ts +38 -5
  137. package/types/main/components/common/ProfileOverlay/styles.d.ts.map +1 -1
  138. package/types/main/components/common/Spinner/index.d.ts.map +1 -1
  139. package/types/main/components/modules/listing/components/BucketCard.d.ts.map +1 -1
  140. package/types/main/components/modules/listing/components/BundleCard.d.ts.map +1 -1
  141. package/types/main/components/modules/listing/components/BundleCardInfoSection.d.ts +2 -0
  142. package/types/main/components/modules/listing/components/BundleCardInfoSection.d.ts.map +1 -1
  143. package/types/main/components/modules/listing/components/CardDescriptionContent.d.ts.map +1 -1
  144. package/types/main/components/modules/listing/components/MetaCard.d.ts +8 -0
  145. package/types/main/components/modules/listing/components/MetaCard.d.ts.map +1 -0
  146. package/types/main/components/modules/listing/components/SlotView.d.ts +5 -0
  147. package/types/main/components/modules/listing/components/SlotView.d.ts.map +1 -0
  148. package/types/main/components/modules/listing/components/styles/index.d.ts +24 -5
  149. package/types/main/components/modules/listing/components/styles/index.d.ts.map +1 -1
  150. package/types/main/components/modules/listing/hooks/useListing.d.ts +2 -0
  151. package/types/main/components/modules/listing/hooks/useListing.d.ts.map +1 -1
  152. package/types/main/components/modules/listing/index.d.ts.map +1 -1
  153. package/types/main/components/modules/login/components/styles/index.d.ts +1 -1
  154. package/types/main/components/modules/login/styles/index.d.ts +4 -3
  155. package/types/main/components/modules/login/styles/index.d.ts.map +1 -1
  156. package/types/main/components/modules/modal/StallionModal.d.ts.map +1 -1
  157. package/types/main/components/modules/modal/hooks/useStallionModal.d.ts +2 -5
  158. package/types/main/components/modules/modal/hooks/useStallionModal.d.ts.map +1 -1
  159. package/types/main/components/modules/prod/index.d.ts +3 -0
  160. package/types/main/components/modules/prod/index.d.ts.map +1 -0
  161. package/types/main/components/modules/prod/prod.d.ts +4 -0
  162. package/types/main/components/modules/prod/prod.d.ts.map +1 -0
  163. package/types/main/components/modules/prod/styles/index.d.ts +16 -0
  164. package/types/main/components/modules/prod/styles/index.d.ts.map +1 -0
  165. package/types/main/constants/apiConstants.d.ts +4 -2
  166. package/types/main/constants/apiConstants.d.ts.map +1 -1
  167. package/types/main/constants/appConstants.d.ts +37 -4
  168. package/types/main/constants/appConstants.d.ts.map +1 -1
  169. package/types/main/constants/colors.d.ts +2 -0
  170. package/types/main/constants/colors.d.ts.map +1 -1
  171. package/types/main/index.d.ts +1 -1
  172. package/types/main/state/actionCreators/useDownloadActions.d.ts +3 -1
  173. package/types/main/state/actionCreators/useDownloadActions.d.ts.map +1 -1
  174. package/types/main/state/actionCreators/useMetaActions.d.ts +1 -1
  175. package/types/main/state/actionCreators/useMetaActions.d.ts.map +1 -1
  176. package/types/main/state/actionCreators/useUpdateMetaActions.d.ts +7 -0
  177. package/types/main/state/actionCreators/useUpdateMetaActions.d.ts.map +1 -0
  178. package/types/main/state/index.d.ts.map +1 -1
  179. package/types/main/state/reducers/updateMetaReducer.d.ts +9 -0
  180. package/types/main/state/reducers/updateMetaReducer.d.ts.map +1 -0
  181. package/types/main/utils/ErrorBoundary.d.ts +1 -1
  182. package/types/main/utils/ErrorBoundary.d.ts.map +1 -1
  183. package/types/main/utils/EventUtil.d.ts +9 -0
  184. package/types/main/utils/EventUtil.d.ts.map +1 -0
  185. package/types/main/utils/SharedDataManager.d.ts +8 -6
  186. package/types/main/utils/SharedDataManager.d.ts.map +1 -1
  187. package/types/main/utils/StallionEventEmitter.d.ts +14 -0
  188. package/types/main/utils/StallionEventEmitter.d.ts.map +1 -0
  189. package/types/main/utils/StallionNativeUtils.d.ts +15 -0
  190. package/types/main/utils/StallionNativeUtils.d.ts.map +1 -0
  191. package/types/main/utils/apiUtils.d.ts +5 -0
  192. package/types/main/utils/apiUtils.d.ts.map +1 -1
  193. package/types/main/utils/useStallionUpdate.d.ts +3 -0
  194. package/types/main/utils/useStallionUpdate.d.ts.map +1 -0
  195. package/types/main/utils/withStallion.d.ts +1 -2
  196. package/types/main/utils/withStallion.d.ts.map +1 -1
  197. package/types/types/globalProvider.types.d.ts +5 -1
  198. package/types/types/globalProvider.types.d.ts.map +1 -1
  199. package/types/types/meta.types.d.ts +19 -3
  200. package/types/types/meta.types.d.ts.map +1 -1
  201. package/types/types/updateMeta.types.d.ts +35 -0
  202. package/types/types/updateMeta.types.d.ts.map +1 -0
  203. package/types/types/utils.types.d.ts +9 -7
  204. package/types/types/utils.types.d.ts.map +1 -1
  205. package/android/src/main/java/com/stallion/StallionZip.java +0 -127
  206. package/src/main/utils/StallionNaitveUtils.js +0 -7
  207. package/src/main/utils/StallionNaitveUtils.js.map +0 -1
  208. package/types/main/utils/StallionNaitveUtils.d.ts +0 -7
  209. package/types/main/utils/StallionNaitveUtils.d.ts.map +0 -1
@@ -0,0 +1,142 @@
1
+ package com.stallion;
2
+
3
+ import android.content.Context;
4
+ import android.content.pm.PackageInfo;
5
+ import android.content.res.Resources;
6
+
7
+ import com.facebook.react.bridge.Arguments;
8
+ import com.facebook.react.bridge.WritableMap;
9
+
10
+ import org.json.JSONObject;
11
+
12
+ public class StallionSynManager {
13
+ public static void sync() {
14
+ new Thread(() -> {
15
+ try {
16
+ StallionStorage stallionStorage = StallionStorage.getInstance();
17
+ Context appContext = stallionStorage.mContext;
18
+ String parentPackageName= appContext.getPackageName();
19
+ PackageInfo pInfo = appContext.getPackageManager().getPackageInfo(parentPackageName, 0);
20
+ String appVersion = pInfo.versionName;
21
+ Resources res = appContext.getResources();
22
+ int stallionProjectIdRes = res.getIdentifier(StallionConstants.STALLION_PROJECT_ID_IDENTIFIER, "string", parentPackageName);
23
+ int stallionTokenRes = res.getIdentifier(StallionConstants.STALLION_APP_TOKEN_IDENTIFIER, "string", parentPackageName);
24
+ String projectId = appContext.getString(stallionProjectIdRes);
25
+ String appToken = appContext.getString(stallionTokenRes);
26
+ String platform = "android";
27
+ String currentProdSlot = stallionStorage.get(StallionConstants.CURRENT_PROD_SLOT_KEY);
28
+ String appliedBundleHash = stallionStorage.get(StallionConstants.PROD_DIRECTORY + currentProdSlot);
29
+ String sdkToken = stallionStorage.get(StallionConstants.STALLION_SDK_TOKEN_KEY);
30
+ JSONObject releaseMeta = StallionApiUtil.post(
31
+ StallionConstants.STALLION_API_BASE + StallionConstants.STALLION_INFO_API_PATH,
32
+ String.format(String.format("{\"appVersion\": \"%s\", \"platform\": \"%s\", \"projectId\": \"%s\", \"appliedBundleHash\": \"%s\" }", appVersion, platform, projectId, appliedBundleHash)),
33
+ appToken,
34
+ sdkToken
35
+ );
36
+ if(releaseMeta.optBoolean("success")) {
37
+ JSONObject data = releaseMeta.optJSONObject("data");
38
+ if(data == null) return;
39
+ JSONObject newReleaseData = data.optJSONObject("newBundleData");
40
+ JSONObject appliedReleaseData = data.optJSONObject("appliedBundleData");
41
+ if(appliedReleaseData != null) {
42
+ boolean isRolledBack = appliedReleaseData.optBoolean("isRolledBack");
43
+ String targetAppVersion = appliedReleaseData.optString("targetAppVersion");
44
+ if(isRolledBack && targetAppVersion.equals(appVersion)) {
45
+ StallionRollbackManager.rollbackProd(false);
46
+ }
47
+ }
48
+ if(newReleaseData != null) {
49
+ String newReleaseUrl = newReleaseData.optString("downloadUrl");
50
+ String newReleaseHash = newReleaseData.optString("checksum");
51
+ String lastRolledBackHash = stallionStorage.get(StallionConstants.LAST_ROLLED_BACK_RELEASE_HASH_KEY);
52
+ if(!newReleaseHash.equals(lastRolledBackHash)) {
53
+ stallionStorage.set(StallionConstants.NEW_RELEASE_HASH_ID, newReleaseHash);
54
+ stallionStorage.set(StallionConstants.NEW_RELEASE_URL_ID, newReleaseUrl);
55
+ checkAndDownload();
56
+ }
57
+ }
58
+ }
59
+ } catch (Exception e) {
60
+ WritableMap syncErrorPayload = Arguments.createMap();
61
+ syncErrorPayload.putString("error", e.toString().substring(0,100));
62
+ StallionEventEmitter.sendEvent(
63
+ StallionEventEmitter.getEventPayload(
64
+ StallionConstants.NativeEventTypesProd.SYNC_ERROR_PROD.toString(),
65
+ syncErrorPayload
66
+ )
67
+ );
68
+ }
69
+ }).start();
70
+ }
71
+
72
+ public static void checkAndDownload () {
73
+ StallionStorage stallionStorage = StallionStorage.getInstance();
74
+ Context appContext = stallionStorage.mContext;
75
+ String parentPackageName= appContext.getPackageName();
76
+ String newReleaseHash = stallionStorage.get(StallionConstants.NEW_RELEASE_HASH_ID);
77
+ String newReleaseUrl = stallionStorage.get(StallionConstants.NEW_RELEASE_URL_ID);
78
+ if(!newReleaseUrl.isEmpty() && !newReleaseHash.isEmpty()) {
79
+ Resources res = appContext.getResources();
80
+ int stallionProjectIdRes = res.getIdentifier(StallionConstants.STALLION_PROJECT_ID_IDENTIFIER, "string", parentPackageName);
81
+ int stallionTokenRes = res.getIdentifier(StallionConstants.STALLION_APP_TOKEN_IDENTIFIER, "string", parentPackageName);
82
+ String projectId = appContext.getString(stallionProjectIdRes);
83
+ String appToken = appContext.getString(stallionTokenRes);
84
+ stallionStorage.set(StallionConstants.NEW_RELEASE_HASH_ID, "");
85
+ stallionStorage.set(StallionConstants.NEW_RELEASE_URL_ID, "");
86
+ WritableMap newReleasePayload = Arguments.createMap();
87
+ newReleasePayload.putString("releaseHash", newReleaseHash);
88
+ StallionEventEmitter.sendEvent(
89
+ StallionEventEmitter.getEventPayload(
90
+ StallionConstants.NativeEventTypesProd.DOWNLOAD_STARTED_PROD.toString(),
91
+ newReleasePayload
92
+ )
93
+ );
94
+ StallionDownloadManager.downloadBundle(
95
+ newReleaseUrl + "?projectId=" + projectId,
96
+ appContext.getFilesDir().getAbsolutePath() + StallionConstants.PROD_DIRECTORY + StallionConstants.TEMP_FOLDER_SLOT,
97
+ "",
98
+ appToken,
99
+ new StallionDownloadCallback() {
100
+ @Override
101
+ public void onReject(String prefix, String error) {
102
+ WritableMap errorEventPayload = Arguments.createMap();
103
+ errorEventPayload.putString("releaseHash", newReleaseHash);
104
+ StallionEventEmitter.sendEvent(
105
+ StallionEventEmitter.getEventPayload(
106
+ StallionConstants.NativeEventTypesProd.DOWNLOAD_ERROR_PROD.toString(),
107
+ errorEventPayload
108
+ )
109
+ );
110
+ }
111
+
112
+ @Override
113
+ public void onSuccess(String successPayload) {
114
+ stallionStorage.set(StallionConstants.CURRENT_PROD_SLOT_KEY, StallionConstants.TEMP_FOLDER_SLOT);
115
+ stallionStorage.set(StallionConstants.PROD_DIRECTORY + StallionConstants.TEMP_FOLDER_SLOT, newReleaseHash);
116
+ WritableMap successEventPayload = Arguments.createMap();
117
+ successEventPayload.putString("releaseHash", newReleaseHash);
118
+ StallionEventEmitter.sendEvent(
119
+ StallionEventEmitter.getEventPayload(
120
+ StallionConstants.NativeEventTypesProd.DOWNLOAD_COMPLETE_PROD.toString(),
121
+ successEventPayload
122
+ )
123
+ );
124
+ }
125
+
126
+ @Override
127
+ public void onProgress(double downloadFraction) {
128
+ WritableMap progressEventPayload = Arguments.createMap();
129
+ progressEventPayload.putString("releaseHash", newReleaseHash);
130
+ progressEventPayload.putDouble("progress", downloadFraction);
131
+ StallionEventEmitter.sendEvent(
132
+ StallionEventEmitter.getEventPayload(
133
+ StallionConstants.NativeEventTypesProd.DOWNLOAD_PROGRESS_PROD.toString(),
134
+ progressEventPayload
135
+ )
136
+ );
137
+ }
138
+ }
139
+ );
140
+ }
141
+ }
142
+ }
@@ -2,3 +2,7 @@
2
2
  #import <React/RCTViewManager.h>
3
3
  #import <React/RCTEventEmitter.h>
4
4
  #import <StallionErrorBoundary.h>
5
+ #import <StallionEventManager.h>
6
+ #import <StallionObjConstants.h>
7
+ #import <StallionRollbackHandler.h>
8
+ #import <StallionObjUtil.h>
@@ -3,15 +3,17 @@
3
3
 
4
4
  @interface RCT_EXTERN_MODULE(Stallion, NSObject)
5
5
 
6
+ RCT_EXTERN_METHOD(onLaunch: (NSString *)launchMessage)
7
+ RCT_EXTERN_METHOD(sync)
6
8
  RCT_EXTERN_METHOD(downloadPackage:(NSDictionary *)bundleInfo
7
9
  withResolver:(RCTPromiseResolveBlock)resolve
8
10
  withRejecter:(RCTPromiseRejectBlock)reject
9
11
  )
10
-
11
- RCT_EXTERN_METHOD(getStallionMeta: (RCTResponseSenderBlock)callback)
12
- RCT_EXTERN_METHOD(getApiKey: (RCTResponseSenderBlock)callback)
13
- RCT_EXTERN_METHOD(setApiKey: (NSString *)apiKey)
14
- RCT_EXTERN_METHOD(toggleStallionSwitch: (BOOL *)isOn)
12
+ RCT_EXTERN_METHOD(getStorage: (NSString *)storageKey callback:(RCTResponseSenderBlock)callback)
13
+ RCT_EXTERN_METHOD(getUniqueId: (RCTResponseSenderBlock)callback)
14
+ RCT_EXTERN_METHOD(getProjectId: (RCTResponseSenderBlock)callback)
15
+ RCT_EXTERN_METHOD(getAppToken: (RCTResponseSenderBlock)callback)
16
+ RCT_EXTERN_METHOD(setStorage: (NSString *)storageKey value:(NSString *)value)
15
17
 
16
18
  + (BOOL)requiresMainQueueSetup
17
19
  {
@@ -7,62 +7,103 @@ class Stallion: RCTEventEmitter {
7
7
  override init() {
8
8
  super.init()
9
9
  Stallion.shared = self
10
+ StallionSyncManager.sync()
11
+ NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
10
12
  }
11
-
13
+
12
14
  override func supportedEvents() -> [String]! {
13
- return [StallionConstants.DOWNLOAD_PROGRESS_EVENT]
15
+ return [StallionConstants.STALLION_NATIVE_EVENT_NAME]
16
+ }
17
+
18
+ @objc func appDidBecomeActive() {
19
+ StallionSyncManager.sync()
14
20
  }
15
21
 
16
- @objc(downloadPackage:withResolver:withRejecter:)
22
+ @objc(downloadPackage:withResolver:withRejecter:)
17
23
  func downloadPackage(bundleInfo: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
18
- guard let receivedBucketId = bundleInfo.value(forKey: StallionConstants.DownloadReqBodyKeys.BucketId) else {return}
19
- guard var receiveDownloadUrl = bundleInfo.value(forKey: StallionConstants.DownloadReqBodyKeys.DownloadUrl) else {return}
20
- let receivedVersion = bundleInfo.value(forKey: StallionConstants.DownloadReqBodyKeys.Version) as? Int ?? nil
21
- var reqJson: [String: Any] = [
22
- StallionConstants.DownloadReqBodyKeys.BucketId: receivedBucketId,
23
- StallionConstants.DownloadReqBodyKeys.Platform: StallionConstants.PlatformValue,
24
- ]
25
- if (receivedVersion != nil) {
26
- reqJson[StallionConstants.DownloadReqBodyKeys.Version] = receivedVersion
27
- }
28
- guard let fromUrl = URL(string: receiveDownloadUrl as? String ?? "") else { return }
24
+ let receivedDownloadUrl = (bundleInfo.value(forKey: StallionConstants.DownloadReqBodyKeys.DownloadUrl) as? String) ?? ""
25
+ let receivedReleaseHash = (bundleInfo.value(forKey: StallionConstants.DownloadReqBodyKeys.Hash) as? String) ?? ""
26
+ let stageDownloadEventBody = ["releaseHash": receivedReleaseHash]
27
+
28
+ guard let fromUrl = URL(string: receivedDownloadUrl) else { return }
29
29
 
30
30
  do {
31
- try StallionDownloader().load(
32
- url: fromUrl,
33
- reqBody: reqJson,
34
- resolve: resolve,
35
- reject: reject
36
- )
31
+ try StallionDownloader().load(
32
+ url: fromUrl,
33
+ downloadPaths: [StallionConstants.STAGE_DIRECTORY, StallionConstants.TEMP_FOLDER_SLOT],
34
+ onProgress: {progress in
35
+ StallionEventEmitter.sendEvent(eventType: StallionConstants.NativeEventTypesStage.DOWNLOAD_PROGRESS_STAGE, data: ["releaseHash": receivedReleaseHash, "progress": progress]
36
+ )
37
+ },
38
+ resolve: {resOp in
39
+ StallionUtil.setLs(key: StallionConstants.CURRENT_STAGE_SLOT_KEY, value: "/" + StallionConstants.TEMP_FOLDER_SLOT)
40
+ StallionUtil.setLs(key: "/" + StallionConstants.STAGE_DIRECTORY + "/" + StallionConstants.TEMP_FOLDER_SLOT, value: receivedReleaseHash)
41
+ StallionEventEmitter.sendEvent(eventType: StallionConstants.NativeEventTypesStage.DOWNLOAD_COMPLETE_STAGE, data: stageDownloadEventBody
42
+ )
43
+ resolve(resOp)
44
+ },
45
+ reject: {code, message, error in
46
+ StallionEventEmitter.sendEvent(eventType: StallionConstants.NativeEventTypesStage.DOWNLOAD_ERROR_STAGE, data: stageDownloadEventBody
47
+ )
48
+ reject(code, message, error)
49
+ }
50
+ )
37
51
  } catch {
38
52
  let errorString = StallionConstants.DownloadPromiseResponses.GenericError
53
+ StallionEventEmitter.sendEvent(eventType: StallionConstants.NativeEventTypesStage.DOWNLOAD_ERROR_STAGE, data: stageDownloadEventBody
54
+ )
39
55
  reject("500", errorString, NSError(domain: errorString, code: 500))
40
56
  }
41
57
  }
42
-
43
- @objc(setApiKey:)
44
- func setApiKey(apiKey: String) {
45
- StallionUtil.setLs(key: StallionUtil.LSKeys.apiKey, value: apiKey)
58
+
59
+ @objc
60
+ func getStorage(_ storageKey: String, callback: RCTResponseSenderBlock) {
61
+ let value = StallionUtil.getLs(key: storageKey)
62
+ callback([value])
46
63
  }
47
64
 
48
- @objc(getApiKey:)
49
- func getApiKey(_ callback: RCTResponseSenderBlock) {
50
- let apiKey = StallionUtil.getLs(key: StallionUtil.LSKeys.apiKey)
51
- callback([apiKey ?? ""])
65
+ @objc
66
+ func setStorage(_ storageKey: String, value: String) {
67
+ StallionUtil.setLs(key: storageKey, value: value)
52
68
  }
53
69
 
54
- @objc(toggleStallionSwitch:)
55
- func toggleStallionSwitch(isOn: Bool) {
56
- StallionUtil.setLs(key: StallionUtil.LSKeys.switchStateKey, value: isOn ? StallionUtil.SwitchStates.ON : StallionUtil.SwitchStates.OFF)
70
+ @objc
71
+ func onLaunch(_ launchData: String) {
72
+ StallionObjUtil.isMounted = true
73
+ emitPendingEvents()
74
+ }
75
+
76
+ @objc
77
+ func sync() {
78
+ StallionSyncManager.sync()
79
+ }
80
+
81
+ @objc
82
+ func getUniqueId(_ callback: RCTResponseSenderBlock) {
83
+ callback([StallionSyncManager.getUniqueId()])
84
+ }
85
+
86
+ @objc
87
+ func getProjectId(_ callback: RCTResponseSenderBlock) {
88
+ let projectId = Bundle.main.infoDictionary?[StallionConstants.STALLION_PROJECT_ID_IDENTIFIER] as? String ?? ""
89
+ callback([projectId])
57
90
  }
58
91
 
59
- @objc(getStallionMeta:)
60
- func getStallionMeta(_ callback: RCTResponseSenderBlock) {
61
- var metaDictionary = [String:Any]()
62
- metaDictionary[StallionUtil.LSKeys.bucketKey] = StallionUtil.getLs(key: StallionUtil.LSKeys.bucketKey)
63
- metaDictionary[StallionUtil.LSKeys.versionKey] = StallionUtil.getLs(key: StallionUtil.LSKeys.versionKey)
64
- metaDictionary[StallionUtil.LSKeys.switchStateKey] = StallionUtil.getLs(key: StallionUtil.LSKeys.switchStateKey) == StallionUtil.SwitchStates.ON
65
- let stallionMeta = NSDictionary(dictionary: metaDictionary)
66
- callback([stallionMeta])
92
+ @objc
93
+ func getAppToken(_ callback: RCTResponseSenderBlock) {
94
+ let appToken = Bundle.main.infoDictionary?[StallionConstants.STALLION_APP_TOKEN_IDENTIFIER] as? String ?? ""
95
+ callback([appToken])
96
+ }
97
+
98
+ func emitPendingEvents() {
99
+ let flushedEvents = StallionEventManager.sharedInstance().flushAllEvents() as NSArray
100
+ for event in flushedEvents {
101
+ if var eventDict = event as? [String: Any] {
102
+ var payload = eventDict["payload"] as? Dictionary<String, Any> ?? [:]
103
+ payload[StallionConstants.APP_VERION_EVENT_KEY] = StallionSyncManager.getAppVersion()
104
+ eventDict["payload"] = payload
105
+ Stallion.shared?.sendEvent(withName: StallionConstants.STALLION_NATIVE_EVENT_NAME, body: eventDict)
106
+ }
107
+ }
67
108
  }
68
109
  }
@@ -14,19 +14,11 @@ class StallionConstants {
14
14
  static let ZipFolderName = "build"
15
15
  static let ZipExtension = "zip"
16
16
  }
17
- public struct HeaderKeys {
18
- static let AccessKey = "x-sdk-access-token"
19
- static let ContentType = "Content-Type"
20
- }
21
17
  public struct DownloadReqBodyKeys {
22
18
  static let DownloadUrl = "url"
23
- static let BucketId = "bucketId"
24
- static let Version = "version"
25
- static let Platform = "platform"
26
- static let ProjectId = "projectId"
19
+ static let Hash = "hash"
27
20
  }
28
21
  static let PlatformValue = "ios"
29
- static let DownloadApiUrl = "https://stallion-api.redhorse.tech/api/v1/bundle/download"
30
22
  public struct DownloadPromiseResponses {
31
23
  static let Success = "Success"
32
24
  static let GenericError = "Something went wrong internally"
@@ -34,11 +26,61 @@ class StallionConstants {
34
26
  static let ApiError = "Download api error"
35
27
  static let InitError = "Download initialisation error"
36
28
  static let DirectoryInitError = "Directory initialisation error"
29
+ static let SyncApiError = "Sync api error"
37
30
  }
38
31
  public struct AuthTokens {
39
32
  static let ApiKey = "apiKey"
40
33
  static let SecretKey = "secretKey"
41
34
  }
42
- static let DOWNLOAD_PROGRESS_EVENT = "StallionDownloadProgress";
43
35
  static let PROGRESS_EVENT_THRESHOLD: Float = 0.05;
36
+
37
+ static let PROD_DIRECTORY = "StallionProd"
38
+ static let STAGE_DIRECTORY = "StallionStage"
39
+ static let TEMP_FOLDER_SLOT = "temp"
40
+ static let NEW_FOLDER_SLOT = "StallionNew"
41
+ static let STABLE_FOLDER_SLOT = "StallionStable"
42
+ static let DEFAULT_FOLDER_SLOT = "Default"
43
+
44
+ static let CURRENT_PROD_SLOT_KEY = "stallionProdCurrentSlot"
45
+ static let CURRENT_STAGE_SLOT_KEY = "stallionStageCurrentSlot"
46
+ static let STALLION_API_BASE = "https://api.stalliontech.io"
47
+ static let STALLION_INFO_API_PATH = "/api/v1/promoted/get-update-meta"
48
+ static let STALLION_PROJECT_ID_IDENTIFIER = "StallionProjectId"
49
+ static let STALLION_APP_TOKEN_IDENTIFIER = "StallionAppToken"
50
+ static let APP_VERION_IDENTIFIER = "CFBundleShortVersionString"
51
+ static let STALLION_APP_TOKEN_KEY = "x-app-token"
52
+ static let STALLION_SDK_TOKEN_KEY = "x-sdk-access-token"
53
+ static let STALLION_UID_KEY = "uid"
54
+ static let UNIQUE_ID_IDENTIFIER = "stallionDeviceId"
55
+
56
+ static let NEW_RELEASE_HASH_ID = "stallionNewReleaseHash"
57
+ static let NEW_RELEASE_URL_ID = "stallionNewReleaseUrl"
58
+
59
+ static let STALLION_SWITCH_STATE_IDENTIFIER = "switchState";
60
+ static let LAST_ROLLED_BACK_RELEASE_HASH_KEY = "LAST_ROLLED_BACK_RELEASE_HASH";
61
+
62
+ static let APP_VERION_EVENT_KEY = "AppVersion"
63
+
64
+ public struct SwitchState {
65
+ static let PROD = "PROD"
66
+ static let STAGE = "STAGE"
67
+ }
68
+
69
+ static let STALLION_NATIVE_EVENT_NAME = "STALLION_NATIVE_EVENT"
70
+ public struct NativeEventTypesProd {
71
+ static let DOWNLOAD_STARTED_PROD = "DOWNLOAD_STARTED_PROD"
72
+ static let DOWNLOAD_ERROR_PROD = "DOWNLOAD_ERROR_PROD"
73
+ static let DOWNLOAD_PROGRESS_PROD = "DOWNLOAD_PROGRESS_PROD"
74
+ static let DOWNLOAD_COMPLETE_PROD = "DOWNLOAD_COMPLETE_PROD"
75
+ static let SYNC_ERROR_PROD = "SYNC_ERROR_PROD"
76
+ static let ROLLED_BACK_PROD = "ROLLED_BACK_PROD"
77
+ static let INSTALLED_PROD = "INSTALLED_PROD"
78
+ static let STABILIZED_PROD = "STABILIZED_PROD"
79
+ static let EXCEPTION_PROD = "EXCEPTION_PROD"
80
+ }
81
+ public struct NativeEventTypesStage {
82
+ static let DOWNLOAD_ERROR_STAGE = "DOWNLOAD_ERROR_STAGE"
83
+ static let DOWNLOAD_PROGRESS_STAGE = "DOWNLOAD_PROGRESS_STAGE"
84
+ static let DOWNLOAD_COMPLETE_STAGE = "DOWNLOAD_COMPLETE_STAGE"
85
+ }
44
86
  }
@@ -7,40 +7,42 @@
7
7
  import Foundation
8
8
  import ZIPFoundation
9
9
 
10
- enum StallionError: Error {
11
- case runtimeError(String)
12
- }
13
-
14
10
  class StallionDownloader: NSObject {
15
11
 
16
- private lazy var urlSession = URLSession(configuration: .default,
12
+ private lazy var urlSession = URLSession(configuration: .default,
17
13
  delegate: self,
18
14
  delegateQueue: nil)
15
+ var downloadTask : URLSessionDownloadTask?;
16
+ var _downloadPaths: [String] = [];
19
17
 
20
- var downloadTask : URLSessionDownloadTask?;
21
- var reqJson: [String: Any]?;
18
+ var _resolve: RCTPromiseResolveBlock?;
19
+ var _reject: RCTPromiseRejectBlock?;
20
+ var _onProgress: ((Float) -> Void)?
21
+ var lastSentProgress: Float = 0;
22
22
 
23
- var _resolve: RCTPromiseResolveBlock?;
24
- var _reject: RCTPromiseRejectBlock?;
25
- var lastSentProgress: Float = 0;
26
-
27
- override init() {
28
- super.init()
29
- }
23
+ override init() {
24
+ super.init()
25
+ }
30
26
 
31
- func load(url: URL, reqBody: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) throws {
32
- self.reqJson = reqBody
33
- self._resolve = resolve
34
- self._reject = reject
35
-
36
- var request = URLRequest(url: url)
37
- request.httpMethod = "GET"
27
+ func load(url: URL, downloadPaths: [String], onProgress: @escaping ((Float) -> Void), resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) throws {
28
+ self._resolve = resolve
29
+ self._reject = reject
30
+ self._downloadPaths = downloadPaths
31
+ self._onProgress = onProgress
32
+
33
+ var request = URLRequest(url: url)
34
+ request.httpMethod = "GET"
38
35
 
39
- request.setValue(StallionUtil.getLs(key: StallionUtil.LSKeys.apiKey) ?? "", forHTTPHeaderField: StallionConstants.HeaderKeys.AccessKey)
40
- let task = urlSession.downloadTask(with: request)
41
- task.resume()
42
- self.downloadTask = task
43
- }
36
+ let sdkToken = StallionSyncManager.getSdkToken()
37
+
38
+ request.setValue(StallionSyncManager.getAppToken(), forHTTPHeaderField: StallionConstants.STALLION_APP_TOKEN_KEY)
39
+ if(!sdkToken.isEmpty) {
40
+ request.setValue(sdkToken, forHTTPHeaderField: StallionConstants.STALLION_SDK_TOKEN_KEY)
41
+ }
42
+ let task = urlSession.downloadTask(with: request)
43
+ task.resume()
44
+ self.downloadTask = task
45
+ }
44
46
  }
45
47
 
46
48
  extension StallionDownloader: URLSessionDownloadDelegate {
@@ -54,9 +56,7 @@ extension StallionDownloader: URLSessionDownloadDelegate {
54
56
  let calculatedProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
55
57
  if((calculatedProgress - self.lastSentProgress) > StallionConstants.PROGRESS_EVENT_THRESHOLD) {
56
58
  self.lastSentProgress = calculatedProgress
57
- DispatchQueue.main.async {
58
- Stallion.shared?.sendEvent(withName: StallionConstants.DOWNLOAD_PROGRESS_EVENT, body: calculatedProgress)
59
- }
59
+ self._onProgress?(calculatedProgress)
60
60
  }
61
61
  }
62
62
  }
@@ -71,19 +71,18 @@ extension StallionDownloader: URLSessionDownloadDelegate {
71
71
  let response = downloadTask.response as? HTTPURLResponse
72
72
  if (response?.statusCode == 200) {
73
73
  do {
74
- let tempDownloadDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
75
- .appendingPathComponent(StallionConstants.FilePaths.DownloadDirectory, isDirectory: true)
76
-
77
- if !FileManager.default.fileExists(atPath: tempDownloadDirectory.path) {
78
- try FileManager.default.createDirectory(atPath: tempDownloadDirectory.path, withIntermediateDirectories: true, attributes: nil)
74
+ let documentFolderPath = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
75
+ let finalDestinationDirectory = self._downloadPaths.reduce(documentFolderPath, { url, pathComponent in
76
+ url.appendingPathComponent(String(pathComponent), isDirectory: true)
77
+ })
78
+
79
+ if !FileManager.default.fileExists(atPath: finalDestinationDirectory.path) {
80
+ try FileManager.default.createDirectory(atPath: finalDestinationDirectory.path, withIntermediateDirectories: true, attributes: nil)
79
81
  }
80
82
 
81
- let finalDestinationDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
82
- .appendingPathComponent(StallionConstants.FilePaths.TargetDirectory, isDirectory: true)
83
-
84
- let downloadedBuildDirectory = tempDownloadDirectory.appendingPathComponent(StallionConstants.FilePaths.ZipFolderName, isDirectory: true)
83
+ let downloadedBuildDirectory = finalDestinationDirectory.appendingPathComponent(StallionConstants.FilePaths.ZipFolderName, isDirectory: true)
85
84
 
86
- let downloadedZipFilePath = tempDownloadDirectory.appendingPathComponent(StallionConstants.FilePaths.ZipFolderName, isDirectory: false).appendingPathExtension(StallionConstants.FilePaths.ZipExtension)
85
+ let downloadedZipFilePath = finalDestinationDirectory.appendingPathComponent(StallionConstants.FilePaths.ZipFolderName, isDirectory: false).appendingPathExtension(StallionConstants.FilePaths.ZipExtension)
87
86
 
88
87
  let fileManager = FileManager()
89
88
 
@@ -97,20 +96,8 @@ extension StallionDownloader: URLSessionDownloadDelegate {
97
96
  if FileManager.default.fileExists(atPath: downloadedBuildDirectory.path) {
98
97
  try fileManager.removeItem(at: downloadedBuildDirectory)
99
98
  }
100
- try fileManager.unzipItem(at: downloadedZipFilePath, to: tempDownloadDirectory, skipCRC32: false, progress: nil, preferredEncoding: nil)
99
+ try fileManager.unzipItem(at: downloadedZipFilePath, to: finalDestinationDirectory, skipCRC32: false, progress: nil, pathEncoding: nil)
101
100
  try fileManager.removeItem(at: downloadedZipFilePath)
102
-
103
- // if build exists in final destination, ovverride it
104
- if FileManager.default.fileExists(atPath: finalDestinationDirectory.path) {
105
- try fileManager.removeItem(at: finalDestinationDirectory)
106
- }
107
- try fileManager.moveItem(at: tempDownloadDirectory, to: finalDestinationDirectory)
108
- let bucketId = self.reqJson?[StallionConstants.DownloadReqBodyKeys.BucketId] as? String ?? ""
109
- let receivedVersion = self.reqJson?[StallionConstants.DownloadReqBodyKeys.Version] as? Int ?? -1
110
- StallionUtil.setLs(key: StallionUtil.LSKeys.bucketKey, value: bucketId)
111
- if receivedVersion > -1 {
112
- StallionUtil.setLs(key: StallionUtil.LSKeys.versionKey, value: String(receivedVersion))
113
- }
114
101
  self._resolve?(StallionConstants.DownloadPromiseResponses.Success)
115
102
  } catch {
116
103
  // throw exception here
@@ -2,7 +2,7 @@
2
2
  // StallionErrorBoundary.h
3
3
  // react-native-stallion
4
4
  //
5
- // Created by Jasbir Singh on 24/12/23.
5
+ // Created by Thor963 on 24/12/23.
6
6
  //
7
7
 
8
8
  #import <Foundation/Foundation.h>
@@ -2,10 +2,14 @@
2
2
  // StallionErrorBoundary.m
3
3
  // react-native-stallion
4
4
  //
5
- // Created by Jasbir Singh on 24/12/23.
5
+ // Created by Thor963 on 24/12/23.
6
6
  //
7
7
 
8
8
  #import "StallionErrorBoundary.h"
9
+ #import "StallionEventManager.h"
10
+ #import "StallionObjConstants.h"
11
+ #import "StallionObjUtil.h"
12
+ #import "StallionRollbackHandler.h"
9
13
 
10
14
  @implementation StallionErrorBoundary
11
15
 
@@ -29,34 +33,47 @@ BOOL exceptionAlertDismissed = FALSE;
29
33
  void handleException(NSException *exception)
30
34
  {
31
35
  NSString *switchState = [[NSUserDefaults standardUserDefaults]
32
- stringForKey:@"switchState"];
33
- if([switchState isEqual:@"STALLION_ON"]) {
34
- [[NSUserDefaults standardUserDefaults] setObject:@"DEFAULT" forKey:@"switchState"];
35
- [[NSUserDefaults standardUserDefaults] synchronize];
36
- NSString * readeableError = [exception reason];
37
- UIAlertController* alert = [UIAlertController
38
- alertControllerWithTitle:@"Stallion Error Boundary"
39
- message:[NSString stringWithFormat:@"%@\n%@",
40
- @"A crash occurred in the app. We have switched Stallion off. Check crash report below. Continue crash to invoke other exception handlers. \n \n",
41
- readeableError]
42
- preferredStyle:UIAlertControllerStyleAlert];
43
-
44
- [alert addAction:[UIAlertAction actionWithTitle:@"Continue Crash"
45
- style:UIAlertActionStyleDefault
46
- handler:^(UIAlertAction *action) {
47
- exceptionAlertDismissed = TRUE;
48
- }]];
49
-
50
- UIApplication* app = [UIApplication sharedApplication];
51
- UIViewController * rootViewController = app.delegate.window.rootViewController;
52
- dispatch_async(dispatch_get_main_queue(), ^{
53
- [rootViewController presentViewController:alert animated:YES completion:nil];
54
- });
55
- while (exceptionAlertDismissed == FALSE)
56
- {
57
- [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
58
- }
36
+ stringForKey:[StallionObjConstants switch_state_identifier]];
37
+ NSString * readeableError = [exception reason];
38
+ if([switchState isEqual:[StallionObjConstants switch_state_prod]]) {
39
+ NSString *currentProdSlot = [[NSUserDefaults standardUserDefaults] stringForKey:StallionObjConstants.current_prod_slot_key] ?: @"";
40
+ NSString *currentHashPath = [NSString stringWithFormat:@"/%@%@", [StallionObjConstants prod_directory], currentProdSlot];
41
+ NSString *currentHash = [[NSUserDefaults standardUserDefaults] stringForKey:currentHashPath] ?: @"";
42
+ BOOL isAutoRollback = ![StallionObjUtil isMounted];
43
+ if(![currentProdSlot isEqual:StallionObjConstants.default_folder_slot]) {
44
+ [[StallionEventManager sharedInstance] queueRNEvent:[StallionObjConstants exception_prod_event] withData:@{@"error" : readeableError, StallionObjConstants.release_hash_key: currentHash, StallionObjConstants.is_auto_rollback_key: isAutoRollback ? @"true" : @"false" }];
45
+ }
46
+ if(isAutoRollback) {
47
+ [StallionRollbackHandler rollbackProd:true];
48
+ }
49
+ } else if([switchState isEqual:[StallionObjConstants switch_state_stage]]) {
50
+ [StallionRollbackHandler rollbackStage];
51
+ UIAlertController* alert = [UIAlertController
52
+ alertControllerWithTitle:@"Stallion Error Boundary"
53
+ message:[NSString stringWithFormat:@"%@\n%@",
54
+ @"A crash occurred in the app. Build was rolled back. Check crash report below. Continue crash to invoke other exception handlers. \n \n",
55
+ readeableError]
56
+ preferredStyle:UIAlertControllerStyleAlert];
57
+
58
+ [alert addAction:[UIAlertAction actionWithTitle:@"Continue Crash"
59
+ style:UIAlertActionStyleDefault
60
+ handler:^(UIAlertAction *action) {
61
+ exceptionAlertDismissed = TRUE;
62
+ }]];
63
+
64
+ UIApplication* app = [UIApplication sharedApplication];
65
+ UIViewController * rootViewController = app.delegate.window.rootViewController;
66
+ dispatch_async(dispatch_get_main_queue(), ^{
67
+ [rootViewController presentViewController:alert animated:YES completion:nil];
68
+ });
69
+ while (exceptionAlertDismissed == FALSE)
70
+ {
71
+ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
72
+ }
59
73
  }
74
+ if(_defaultExceptionHandler) {
75
+ _defaultExceptionHandler(exception);
76
+ }
60
77
  }
61
78
 
62
79
  @end