1 // Copyright 2015-present 650 Industries. All rights reserved.
2 package host.exp.exponent
3 
4 import android.util.Log
5 import com.facebook.proguard.annotations.DoNotStrip
6 import com.facebook.react.common.JavascriptException
7 import host.exp.exponent.network.ExponentNetwork
8 import host.exp.expoview.Exponent
9 import okhttp3.CookieJar
10 import okhttp3.OkHttpClient
11 import java.util.concurrent.TimeUnit
12 
13 @DoNotStrip
14 object ReactNativeStaticHelpers {
15   private val TAG = ReactNativeStaticHelpers::class.java.simpleName
16 
17   @DoNotStrip
18   @JvmStatic fun reloadFromManifest(activityId: Int) {
19     try {
20       Class.forName("host.exp.exponent.kernel.Kernel")
21         .getMethod("reloadVisibleExperience", Int::class.javaPrimitiveType)
22         .invoke(null, activityId)
23     } catch (e: Exception) {
24       Log.e("reloadFromManifest", "Unable to reload visible experience", e)
25     }
26   }
27 
28   @DoNotStrip
29   @JvmStatic fun getBundleUrlForActivityId(
30     activityId: Int,
31     host: String?,
32     mainModuleId: String?,
33     bundleTypeId: String?,
34     devMode: Boolean,
35     jsMinify: Boolean
36   ): String? {
37     return try {
38       Class.forName("host.exp.exponent.kernel.Kernel")
39         .getMethod(
40           "getBundleUrlForActivityId",
41           Int::class.javaPrimitiveType,
42           String::class.java,
43           String::class.java,
44           String::class.java,
45           Boolean::class.javaPrimitiveType,
46           Boolean::class.javaPrimitiveType
47         )
48         .invoke(null, activityId, host, mainModuleId, bundleTypeId, devMode, jsMinify) as String
49     } catch (e: Exception) {
50       null
51     }
52   }
53 
54   // <= SDK 25
55   @DoNotStrip
56   @JvmStatic fun getBundleUrlForActivityId(
57     activityId: Int,
58     host: String?,
59     jsModulePath: String?,
60     devMode: Boolean,
61     jsMinify: Boolean
62   ): String? {
63     return try {
64       Class.forName("host.exp.exponent.kernel.Kernel")
65         .getMethod(
66           "getBundleUrlForActivityId",
67           Int::class.javaPrimitiveType,
68           String::class.java,
69           String::class.java,
70           Boolean::class.javaPrimitiveType,
71           Boolean::class.javaPrimitiveType
72         )
73         .invoke(null, activityId, host, jsModulePath, devMode, jsMinify) as String
74     } catch (e: Exception) {
75       null
76     }
77   }
78 
79   // <= SDK 21
80   @DoNotStrip
81   @JvmStatic fun getBundleUrlForActivityId(
82     activityId: Int,
83     host: String?,
84     jsModulePath: String?,
85     devMode: Boolean,
86     hmr: Boolean,
87     jsMinify: Boolean
88   ): String? {
89     return try {
90       Class.forName("host.exp.exponent.kernel.Kernel")
91         .getMethod(
92           "getBundleUrlForActivityId",
93           Int::class.javaPrimitiveType,
94           String::class.java,
95           String::class.java,
96           Boolean::class.javaPrimitiveType,
97           Boolean::class.javaPrimitiveType,
98           Boolean::class.javaPrimitiveType
99         )
100         .invoke(null, activityId, host, jsModulePath, devMode, hmr, jsMinify) as String
101     } catch (e: Exception) {
102       null
103     }
104   }
105 
106   @DoNotStrip
107   @JvmStatic fun handleReactNativeError(
108     errorMessage: String?,
109     stackUnversioned: Any?,
110     exceptionId: Int?,
111     isFatal: Boolean?
112   ) {
113     try {
114       Class.forName("host.exp.exponent.kernel.Kernel").getMethod(
115         "handleReactNativeError",
116         String::class.java,
117         Any::class.java,
118         Int::class.java,
119         Boolean::class.java
120       ).invoke(null, errorMessage, stackUnversioned, exceptionId, isFatal)
121     } catch (e: Exception) {
122       throw JavascriptException(errorMessage)
123     }
124   }
125 
126   @DoNotStrip
127   @JvmStatic fun handleReactNativeError(
128     throwable: Throwable?,
129     errorMessage: String?,
130     stackUnversioned: Any?,
131     exceptionId: Int?,
132     isFatal: Boolean?
133   ) {
134     try {
135       Class.forName("host.exp.exponent.kernel.Kernel").getMethod(
136         "handleReactNativeError",
137         Throwable::class.java,
138         String::class.java,
139         Any::class.java,
140         Int::class.java,
141         Boolean::class.java
142       ).invoke(null, throwable, errorMessage, stackUnversioned, exceptionId, isFatal)
143     } catch (e: Exception) {
144       throw JavascriptException(errorMessage)
145     }
146   }
147 
148   @DoNotStrip
149   @JvmStatic fun getBundleSourceForPath(path: String?): String? {
150     return try {
151       Exponent.instance.getBundleSource(path!!)
152     } catch (e: Exception) {
153       null
154     }
155   }
156 
157   private var exponentNetwork: ExponentNetwork? = null
158   fun setExponentNetwork(exponentNetwork: ExponentNetwork?) {
159     this.exponentNetwork = exponentNetwork
160   }
161 
162   @DoNotStrip
163   @JvmStatic fun getOkHttpClient(callingClass: Class<*>): Any {
164     // we build the OkHttp client here so that one cache instance is shared by all concurrent OkHttp instances
165     val version = RNObject.versionForClassname(callingClass.name)
166     val cookieJar =
167       RNObject("com.facebook.react.modules.network.ReactCookieJarContainer").loadVersion(version)
168         .construct().get()
169     val client = OkHttpClient.Builder()
170       .connectTimeout(0, TimeUnit.MILLISECONDS)
171       .readTimeout(0, TimeUnit.MILLISECONDS)
172       .writeTimeout(0, TimeUnit.MILLISECONDS)
173       .cookieJar(cookieJar as CookieJar)
174       .cache(exponentNetwork!!.cache)
175     return client.build()
176   }
177 }
178