<lambda>null1 // Copyright 2015-present 650 Industries. All rights reserved.
2 package host.exp.exponent.exceptions
3
4 import host.exp.exponent.Constants
5 import host.exp.expoview.ExpoViewBuildConfig
6 import org.json.JSONArray
7 import org.json.JSONException
8 import org.json.JSONObject
9 import java.lang.Exception
10 import java.lang.NumberFormatException
11
12 class ManifestException : ExponentException {
13 private val manifestUrl: String
14 private var errorJSON: JSONObject? = null
15 val errorHeader: String?
16 get() = errorJSON?.let {
17 try {
18 when (it.getString("errorCode")) {
19 "EXPERIENCE_SDK_VERSION_OUTDATED" -> "Project is incompatible with this version of Expo Go"
20 "EXPERIENCE_SDK_VERSION_TOO_NEW" -> "Project is incompatible with this version of Expo Go"
21 "SNACK_NOT_FOUND_FOR_SDK_VERSION" -> "This Snack is incompatible with this version of Expo Go"
22 else -> null
23 }
24 } catch (e: JSONException) {
25 null
26 }
27 }
28
29 constructor(originalException: Exception?, manifestUrl: String) : super(originalException) {
30 this.manifestUrl = manifestUrl
31 this.errorJSON = null
32 }
33
34 constructor(originalException: Exception?, manifestUrl: String, errorJSON: JSONObject?) : super(
35 originalException
36 ) {
37 this.errorJSON = errorJSON
38 this.manifestUrl = manifestUrl
39 }
40
41 override fun toString(): String {
42 val extraMessage = if (ExpoViewBuildConfig.DEBUG) {
43 // This will get hit in a detached app.
44 " Are you sure expo-cli is running?"
45 } else {
46 ""
47 }
48
49 return when (manifestUrl) {
50 Constants.INITIAL_URL -> "Could not load app.$extraMessage"
51 else -> {
52 var formattedMessage = "Could not load $manifestUrl.$extraMessage"
53 val supportedSdks = Constants.SDK_VERSIONS_LIST.map {
54 it.substring(0, it.indexOf('.')).toInt()
55 }.sorted()
56 val supportedSdksString = { conjunction: String ->
57 supportedSdks.subList(0, supportedSdks.size - 1)
58 .joinToString(", ") + " $conjunction ${supportedSdks.last()}"
59 }
60
61 if (errorJSON != null) {
62 try {
63 val errorCode = errorJSON!!.getString("errorCode")
64 val rawMessage = errorJSON!!.getString("message")
65 when (errorCode) {
66 "EXPERIENCE_NOT_FOUND", // Really doesn't exist
67 "EXPERIENCE_NOT_PUBLISHED_ERROR", // Not published
68 "EXPERIENCE_RELEASE_NOT_FOUND_ERROR" -> // Can't find a release for the requested release channel
69 formattedMessage =
70 "No project found at $manifestUrl."
71 "EXPERIENCE_SDK_VERSION_OUTDATED" -> {
72 val metadata = errorJSON!!.getJSONObject("metadata")
73 val availableSDKVersions = metadata.getJSONArray("availableSDKVersions")
74 val sdkVersionRequired = availableSDKVersions.getString(0).let {
75 it.substring(0, it.indexOf('.'))
76 }
77
78 formattedMessage =
79 "This project uses SDK $sdkVersionRequired, but this version of Expo Go supports only SDKs ${supportedSdksString("and")}.<br><br>" +
80 "To open this project:<br>" +
81 "• Update it to SDK ${supportedSdksString("or")}.<br>" +
82 "• Install an older version of Expo Go that supports the project's SDK version.<br><br>" +
83 "If you are unsure how to update the project or install a suitable version of Expo Go, refer to the <a href='https://docs.expo.dev/get-started/expo-go/#sdk-versions'>SDK Versions Guide</a>."
84 }
85 "SNACK_NOT_FOUND_FOR_SDK_VERSION" -> {
86 formattedMessage =
87 "Incompatible SDK version or no SDK version specified. This version of Expo Go only supports the following SDKs (runtimes): " + Constants.SDK_VERSIONS_LIST.joinToString() + ". A development build must be used to load other runtimes.<br><a href='https://docs.expo.dev/develop/development-builds/introduction/'>Learn more about development builds</a>."
88 }
89 "EXPERIENCE_SDK_VERSION_TOO_NEW" ->
90 formattedMessage =
91 "This project requires a newer version of Expo Go - please download the latest version from the Play Store."
92 "EXPERIENCE_NOT_VIEWABLE" ->
93 formattedMessage =
94 rawMessage // From server: The experience you requested is not viewable by you. You will need to log in or ask the owner to grant you access.
95 "USER_SNACK_NOT_FOUND", "SNACK_NOT_FOUND" ->
96 formattedMessage =
97 "No snack found at $manifestUrl."
98 "SNACK_RUNTIME_NOT_RELEASED" ->
99 formattedMessage =
100 rawMessage // From server: `The Snack runtime for corresponding sdk version of this Snack ("${sdkVersions[0]}") is not released.`,
101 "SNACK_NOT_FOUND_FOR_SDK_VERSION" -> run closure@{
102 val metadata = errorJSON!!.getJSONObject("metadata")
103 val fullName = metadata["fullName"] ?: ""
104 val snackSdkVersion =
105 (metadata["sdkVersions"] as? JSONArray)?.get(0) as? String ?: "unknown"
106
107 if (snackSdkVersion == "unknown" || snackSdkVersion.indexOf(".") == -1) {
108 formattedMessage = rawMessage
109 return@closure
110 }
111
112 val snackSdkVersionValue = try {
113 Integer.parseInt(snackSdkVersion.substring(0, snackSdkVersion.indexOf(".")))
114 } catch (e: NumberFormatException) {
115 formattedMessage = rawMessage
116 return@closure
117 }
118 formattedMessage =
119 "The snack \"${fullName}\" was found, but it is not compatible with your version of Expo Go. It was released for SDK $snackSdkVersionValue, but your Expo Go supports only SDKs ${supportedSdksString("and")}."
120 formattedMessage += if (supportedSdks.last() < snackSdkVersionValue) {
121 "<br><br>You need to update your Expo Go app in order to run this Snack."
122 } else {
123 "<br><br>Snack needs to be upgraded to a current SDK version. To do it, open the project at <a href='https://snack.expo.dev'>Expo Snack website</a>. It will be automatically upgraded to a supported SDK version."
124 }
125 formattedMessage += "<br><br><a href='https://docs.expo.dev/get-started/expo-go/#sdk-versions'>Learn more about SDK versions and Expo Go</a>."
126 }
127 }
128 } catch (e: JSONException) {
129 return formattedMessage
130 }
131 }
132 formattedMessage
133 }
134 }
135 }
136 }
137