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.
- package/android/src/main/java/com/stallion/Stallion.java +94 -10
- package/android/src/main/java/com/stallion/StallionApiUtil.java +58 -0
- package/android/src/main/java/com/stallion/StallionCommonUtil.java +25 -0
- package/android/src/main/java/com/stallion/StallionConstants.java +51 -15
- package/android/src/main/java/com/stallion/StallionDownloadCallback.java +7 -0
- package/android/src/main/java/com/stallion/StallionDownloadManager.java +121 -0
- package/android/src/main/java/com/stallion/StallionErrorBoundary.java +28 -4
- package/android/src/main/java/com/stallion/StallionEventEmitter.java +144 -0
- package/android/src/main/java/com/stallion/StallionFileUtil.java +129 -0
- package/android/src/main/java/com/stallion/StallionModule.java +100 -154
- package/android/src/main/java/com/stallion/StallionRollbackManager.java +82 -0
- package/android/src/main/java/com/stallion/StallionStorage.java +16 -6
- package/android/src/main/java/com/stallion/StallionSynManager.java +142 -0
- package/ios/main/Stallion-Bridging-Header.h +4 -0
- package/ios/main/Stallion.m +7 -5
- package/ios/main/Stallion.swift +80 -39
- package/ios/main/StallionConstants.swift +52 -10
- package/ios/main/StallionDownloader.swift +39 -52
- package/ios/main/StallionErrorBoundary.h +1 -1
- package/ios/main/StallionErrorBoundary.m +45 -28
- package/ios/main/StallionEventEmitter.swift +20 -0
- package/ios/main/StallionEventManager.h +21 -0
- package/ios/main/StallionEventManager.m +57 -0
- package/ios/main/StallionModule.m +107 -23
- package/ios/main/StallionObjConstants.h +46 -0
- package/ios/main/StallionObjConstants.m +124 -0
- package/ios/main/StallionObjUtil.h +14 -0
- package/ios/main/StallionObjUtil.m +22 -0
- package/ios/main/StallionRollbackHandler.h +22 -0
- package/ios/main/StallionRollbackHandler.m +128 -0
- package/ios/main/StallionSyncManager.swift +149 -0
- package/ios/main/StallionUtil.swift +2 -12
- package/package.json +6 -2
- package/src/index.js +5 -15
- package/src/index.js.map +1 -1
- package/src/main/components/common/ButtonFullWidth/styles.js +2 -2
- package/src/main/components/common/ButtonFullWidth/styles.js.map +1 -1
- package/src/main/components/common/Footer/index.js +24 -31
- package/src/main/components/common/Footer/index.js.map +1 -1
- package/src/main/components/common/Footer/styles.js +34 -33
- package/src/main/components/common/Footer/styles.js.map +1 -1
- package/src/main/components/common/Header/index.js +12 -8
- package/src/main/components/common/Header/index.js.map +1 -1
- package/src/main/components/common/Header/styles.js +10 -5
- package/src/main/components/common/Header/styles.js.map +1 -1
- package/src/main/components/common/ProfileOverlay/index.js +18 -7
- package/src/main/components/common/ProfileOverlay/index.js.map +1 -1
- package/src/main/components/common/ProfileOverlay/styles.js +41 -8
- package/src/main/components/common/ProfileOverlay/styles.js.map +1 -1
- package/src/main/components/common/Spinner/index.js +3 -1
- package/src/main/components/common/Spinner/index.js.map +1 -1
- package/src/main/components/modules/listing/components/BucketCard.js +3 -3
- package/src/main/components/modules/listing/components/BucketCard.js.map +1 -1
- package/src/main/components/modules/listing/components/BundleCard.js +9 -5
- package/src/main/components/modules/listing/components/BundleCard.js.map +1 -1
- package/src/main/components/modules/listing/components/BundleCardInfoSection.js +20 -12
- package/src/main/components/modules/listing/components/BundleCardInfoSection.js.map +1 -1
- package/src/main/components/modules/listing/components/CardDescriptionContent.js +3 -2
- package/src/main/components/modules/listing/components/CardDescriptionContent.js.map +1 -1
- package/src/main/components/modules/listing/components/MetaCard.js +38 -0
- package/src/main/components/modules/listing/components/MetaCard.js.map +1 -0
- package/src/main/components/modules/listing/components/SlotView.js +82 -0
- package/src/main/components/modules/listing/components/SlotView.js.map +1 -0
- package/src/main/components/modules/listing/components/styles/index.js +28 -9
- package/src/main/components/modules/listing/components/styles/index.js.map +1 -1
- package/src/main/components/modules/listing/hooks/useListing.js +9 -2
- package/src/main/components/modules/listing/hooks/useListing.js.map +1 -1
- package/src/main/components/modules/listing/index.js +12 -4
- package/src/main/components/modules/listing/index.js.map +1 -1
- package/src/main/components/modules/login/components/styles/index.js +4 -4
- package/src/main/components/modules/login/components/styles/index.js.map +1 -1
- package/src/main/components/modules/login/index.js +1 -1
- package/src/main/components/modules/login/index.js.map +1 -1
- package/src/main/components/modules/login/styles/index.js +7 -6
- package/src/main/components/modules/login/styles/index.js.map +1 -1
- package/src/main/components/modules/modal/StallionModal.js +13 -11
- package/src/main/components/modules/modal/StallionModal.js.map +1 -1
- package/src/main/components/modules/modal/hooks/useStallionModal.js +87 -24
- package/src/main/components/modules/modal/hooks/useStallionModal.js.map +1 -1
- package/src/main/components/modules/prod/index.js +3 -0
- package/src/main/components/modules/prod/index.js.map +1 -0
- package/src/main/components/modules/prod/prod.js +35 -0
- package/src/main/components/modules/prod/prod.js.map +1 -0
- package/src/main/components/modules/prod/styles/index.js +20 -0
- package/src/main/components/modules/prod/styles/index.js.map +1 -0
- package/src/main/constants/apiConstants.js +3 -1
- package/src/main/constants/apiConstants.js.map +1 -1
- package/src/main/constants/appConstants.js +40 -4
- package/src/main/constants/appConstants.js.map +1 -1
- package/src/main/constants/colors.js +8 -6
- package/src/main/constants/colors.js.map +1 -1
- package/src/main/state/actionCreators/useDownloadActions.js +17 -37
- package/src/main/state/actionCreators/useDownloadActions.js.map +1 -1
- package/src/main/state/actionCreators/useMetaActions.js +4 -5
- package/src/main/state/actionCreators/useMetaActions.js.map +1 -1
- package/src/main/state/actionCreators/useUpdateMetaActions.js +100 -0
- package/src/main/state/actionCreators/useUpdateMetaActions.js.map +1 -0
- package/src/main/state/actionCreators/useUserActions.js +4 -4
- package/src/main/state/actionCreators/useUserActions.js.map +1 -1
- package/src/main/state/index.js +15 -2
- package/src/main/state/index.js.map +1 -1
- package/src/main/state/reducers/updateMetaReducer.js +36 -0
- package/src/main/state/reducers/updateMetaReducer.js.map +1 -0
- package/src/main/utils/ErrorBoundary.js +15 -14
- package/src/main/utils/ErrorBoundary.js.map +1 -1
- package/src/main/utils/EventUtil.js +28 -0
- package/src/main/utils/EventUtil.js.map +1 -0
- package/src/main/utils/SharedDataManager.js +15 -12
- package/src/main/utils/SharedDataManager.js.map +1 -1
- package/src/main/utils/StallionEventEmitter.js +20 -0
- package/src/main/utils/StallionEventEmitter.js.map +1 -0
- package/src/main/utils/StallionNativeUtils.js +60 -0
- package/src/main/utils/StallionNativeUtils.js.map +1 -0
- package/src/main/utils/apiUtils.js +8 -0
- package/src/main/utils/apiUtils.js.map +1 -1
- package/src/main/utils/useStallionModal.js +4 -3
- package/src/main/utils/useStallionModal.js.map +1 -1
- package/src/main/utils/useStallionUpdate.js +13 -0
- package/src/main/utils/useStallionUpdate.js.map +1 -0
- package/src/main/utils/withStallion.js +1 -4
- package/src/main/utils/withStallion.js.map +1 -1
- package/src/types/meta.types.js +13 -0
- package/src/types/meta.types.js.map +1 -1
- package/src/types/updateMeta.types.js +7 -0
- package/src/types/updateMeta.types.js.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -1
- package/types/main/components/common/Footer/index.d.ts +1 -4
- package/types/main/components/common/Footer/index.d.ts.map +1 -1
- package/types/main/components/common/Footer/styles.d.ts +30 -29
- package/types/main/components/common/Footer/styles.d.ts.map +1 -1
- package/types/main/components/common/Header/index.d.ts.map +1 -1
- package/types/main/components/common/Header/styles.d.ts +6 -1
- package/types/main/components/common/Header/styles.d.ts.map +1 -1
- package/types/main/components/common/ProfileOverlay/index.d.ts.map +1 -1
- package/types/main/components/common/ProfileOverlay/styles.d.ts +38 -5
- package/types/main/components/common/ProfileOverlay/styles.d.ts.map +1 -1
- package/types/main/components/common/Spinner/index.d.ts.map +1 -1
- package/types/main/components/modules/listing/components/BucketCard.d.ts.map +1 -1
- package/types/main/components/modules/listing/components/BundleCard.d.ts.map +1 -1
- package/types/main/components/modules/listing/components/BundleCardInfoSection.d.ts +2 -0
- package/types/main/components/modules/listing/components/BundleCardInfoSection.d.ts.map +1 -1
- package/types/main/components/modules/listing/components/CardDescriptionContent.d.ts.map +1 -1
- package/types/main/components/modules/listing/components/MetaCard.d.ts +8 -0
- package/types/main/components/modules/listing/components/MetaCard.d.ts.map +1 -0
- package/types/main/components/modules/listing/components/SlotView.d.ts +5 -0
- package/types/main/components/modules/listing/components/SlotView.d.ts.map +1 -0
- package/types/main/components/modules/listing/components/styles/index.d.ts +24 -5
- package/types/main/components/modules/listing/components/styles/index.d.ts.map +1 -1
- package/types/main/components/modules/listing/hooks/useListing.d.ts +2 -0
- package/types/main/components/modules/listing/hooks/useListing.d.ts.map +1 -1
- package/types/main/components/modules/listing/index.d.ts.map +1 -1
- package/types/main/components/modules/login/components/styles/index.d.ts +1 -1
- package/types/main/components/modules/login/styles/index.d.ts +4 -3
- package/types/main/components/modules/login/styles/index.d.ts.map +1 -1
- package/types/main/components/modules/modal/StallionModal.d.ts.map +1 -1
- package/types/main/components/modules/modal/hooks/useStallionModal.d.ts +2 -5
- package/types/main/components/modules/modal/hooks/useStallionModal.d.ts.map +1 -1
- package/types/main/components/modules/prod/index.d.ts +3 -0
- package/types/main/components/modules/prod/index.d.ts.map +1 -0
- package/types/main/components/modules/prod/prod.d.ts +4 -0
- package/types/main/components/modules/prod/prod.d.ts.map +1 -0
- package/types/main/components/modules/prod/styles/index.d.ts +16 -0
- package/types/main/components/modules/prod/styles/index.d.ts.map +1 -0
- package/types/main/constants/apiConstants.d.ts +4 -2
- package/types/main/constants/apiConstants.d.ts.map +1 -1
- package/types/main/constants/appConstants.d.ts +37 -4
- package/types/main/constants/appConstants.d.ts.map +1 -1
- package/types/main/constants/colors.d.ts +2 -0
- package/types/main/constants/colors.d.ts.map +1 -1
- package/types/main/index.d.ts +1 -1
- package/types/main/state/actionCreators/useDownloadActions.d.ts +3 -1
- package/types/main/state/actionCreators/useDownloadActions.d.ts.map +1 -1
- package/types/main/state/actionCreators/useMetaActions.d.ts +1 -1
- package/types/main/state/actionCreators/useMetaActions.d.ts.map +1 -1
- package/types/main/state/actionCreators/useUpdateMetaActions.d.ts +7 -0
- package/types/main/state/actionCreators/useUpdateMetaActions.d.ts.map +1 -0
- package/types/main/state/index.d.ts.map +1 -1
- package/types/main/state/reducers/updateMetaReducer.d.ts +9 -0
- package/types/main/state/reducers/updateMetaReducer.d.ts.map +1 -0
- package/types/main/utils/ErrorBoundary.d.ts +1 -1
- package/types/main/utils/ErrorBoundary.d.ts.map +1 -1
- package/types/main/utils/EventUtil.d.ts +9 -0
- package/types/main/utils/EventUtil.d.ts.map +1 -0
- package/types/main/utils/SharedDataManager.d.ts +8 -6
- package/types/main/utils/SharedDataManager.d.ts.map +1 -1
- package/types/main/utils/StallionEventEmitter.d.ts +14 -0
- package/types/main/utils/StallionEventEmitter.d.ts.map +1 -0
- package/types/main/utils/StallionNativeUtils.d.ts +15 -0
- package/types/main/utils/StallionNativeUtils.d.ts.map +1 -0
- package/types/main/utils/apiUtils.d.ts +5 -0
- package/types/main/utils/apiUtils.d.ts.map +1 -1
- package/types/main/utils/useStallionUpdate.d.ts +3 -0
- package/types/main/utils/useStallionUpdate.d.ts.map +1 -0
- package/types/main/utils/withStallion.d.ts +1 -2
- package/types/main/utils/withStallion.d.ts.map +1 -1
- package/types/types/globalProvider.types.d.ts +5 -1
- package/types/types/globalProvider.types.d.ts.map +1 -1
- package/types/types/meta.types.d.ts +19 -3
- package/types/types/meta.types.d.ts.map +1 -1
- package/types/types/updateMeta.types.d.ts +35 -0
- package/types/types/updateMeta.types.d.ts.map +1 -0
- package/types/types/utils.types.d.ts +9 -7
- package/types/types/utils.types.d.ts.map +1 -1
- package/android/src/main/java/com/stallion/StallionZip.java +0 -127
- package/src/main/utils/StallionNaitveUtils.js +0 -7
- package/src/main/utils/StallionNaitveUtils.js.map +0 -1
- package/types/main/utils/StallionNaitveUtils.d.ts +0 -7
- 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
|
+
}
|
package/ios/main/Stallion.m
CHANGED
|
@@ -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(
|
|
12
|
-
RCT_EXTERN_METHOD(
|
|
13
|
-
RCT_EXTERN_METHOD(
|
|
14
|
-
RCT_EXTERN_METHOD(
|
|
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
|
{
|
package/ios/main/Stallion.swift
CHANGED
|
@@ -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
|
-
|
|
15
|
+
return [StallionConstants.STALLION_NATIVE_EVENT_NAME]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@objc func appDidBecomeActive() {
|
|
19
|
+
StallionSyncManager.sync()
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
@objc(downloadPackage:withResolver:withRejecter:)
|
|
17
23
|
func downloadPackage(bundleInfo: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
44
|
-
func
|
|
45
|
-
StallionUtil.
|
|
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
|
|
49
|
-
func
|
|
50
|
-
|
|
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
|
|
55
|
-
func
|
|
56
|
-
|
|
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
|
|
60
|
-
func
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
21
|
-
|
|
18
|
+
var _resolve: RCTPromiseResolveBlock?;
|
|
19
|
+
var _reject: RCTPromiseRejectBlock?;
|
|
20
|
+
var _onProgress: ((Float) -> Void)?
|
|
21
|
+
var lastSentProgress: Float = 0;
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
override init() {
|
|
28
|
-
super.init()
|
|
29
|
-
}
|
|
23
|
+
override init() {
|
|
24
|
+
super.init()
|
|
25
|
+
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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,10 +2,14 @@
|
|
|
2
2
|
// StallionErrorBoundary.m
|
|
3
3
|
// react-native-stallion
|
|
4
4
|
//
|
|
5
|
-
// Created by
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|