Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 87 additions & 2 deletions android/src/main/java/com/expofp/ExpofpModule.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,102 @@
package com.expofp

import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.expofp.fplan.api.app.ExpoFpPlan
import com.expofp.fplan.api.app.model.ExpoFpLinkType
import com.expofp.fplan.api.preloader.ExpoFpPreloadedPlanInfo
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
import java.util.concurrent.ConcurrentHashMap

object ExpofpUrlUtils {
fun getExpoKeyFromUrl(url: String): String? {
val host = try {
Uri.parse(url).host
} catch (_: Throwable) {
null
} ?: return null

return host.substringBefore(".expofp.com").takeIf { it.isNotBlank() }
}

fun extractAdditionalParamsFromUrl(url: String): List<com.expofp.fplan.api.app.model.ExpoFpPlanParameter> {
val query = try {
Uri.parse(url).encodedQuery
} catch (_: Throwable) {
null
} ?: return emptyList()

if (query.isBlank()) return emptyList()

if (!query.contains("=") && !query.contains("&")) {
return listOf(com.expofp.fplan.api.app.model.ExpoFpPlanParameter.SearchText(Uri.decode(query)))
}

return emptyList()
}
}

object ExpofpPreloadCache {
private val byExpoKey = ConcurrentHashMap<String, ExpoFpPreloadedPlanInfo>()

fun put(expoKey: String, info: ExpoFpPreloadedPlanInfo) {
byExpoKey[expoKey] = info
}

fun get(expoKey: String): ExpoFpPreloadedPlanInfo? = byExpoKey[expoKey]

fun clear() {
byExpoKey.clear()
}
}

class ExpofpModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName() = "ExpofpModule"

@ReactMethod
fun preload(url: String, promise: Promise) {
Log.d("ExpofpModule", "preload: not implemented")
promise.reject("PRELOAD_UNAVAILABLE", "ExpoFP Android v5 preload is not implemented yet")
Log.d("ExpofpModule", "preload: $url")
Log.d("ExpofpModule", "reactApplicationContext: $reactApplicationContext")
val context = reactApplicationContext.applicationContext
Log.d("ExpofpModule", "context: $context")
val expoKey = ExpofpUrlUtils.getExpoKeyFromUrl(url)
Log.d("ExpofpModule", "expoKey: $expoKey")
if (expoKey.isNullOrBlank()) {
promise.reject("PRELOAD_INVALID_URL", "Invalid ExpoFP URL: missing host/expoKey")
return
}

val additionalParams = ExpofpUrlUtils.extractAdditionalParamsFromUrl(url)

Handler(Looper.getMainLooper()).post {
try {
ExpoFpPlan.initialize(context)

val preloadedPlanInfo = ExpoFpPlan.preloader.preloadPlan(
ExpoFpLinkType.ExpoKey(expoKey),
additionalParams,
null,
null,
false
)
Log.d("ExpofpModule", "preloadedPlanInfo: $preloadedPlanInfo")
ExpofpPreloadCache.put(expoKey, preloadedPlanInfo)

val result = Arguments.createMap().apply {
putString("expoKey", expoKey)
putString("url", url)
}
promise.resolve(result)
} catch (t: Throwable) {
Log.e("ExpofpModule", "preload failed", t)
promise.reject("PRELOAD_FAILED", t.message, t)
}
}
}
}
24 changes: 18 additions & 6 deletions android/src/main/java/com/expofp/ExpofpViewManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ class ExpofpViewManager : SimpleViewManager<ExpoFpView>() {
super.onDropViewInstance(view)
}

private fun getExpoKeyFromUrl(url: String): String {
return url.substringAfter("https://").substringBefore(".expofp.com")
}

private fun createCrowdConnectedProvider(settingsMap: ReadableMap): IExpoFpLocationProvider? {
val context = reactContext?.applicationContext ?: return null
val application = (context as? Application) ?: return null
Expand Down Expand Up @@ -67,10 +63,26 @@ class ExpofpViewManager : SimpleViewManager<ExpoFpView>() {
if (settingsMap == null) return
val url = settingsMap.getString("url") ?: return
val context = reactContext?.applicationContext ?: return
val expoKey = getExpoKeyFromUrl(url)
val expoKey = ExpofpUrlUtils.getExpoKeyFromUrl(url) ?: return
val additionalParams = ExpofpUrlUtils.extractAdditionalParamsFromUrl(url)

ExpoFpPlan.initialize(context)
val p = ExpoFpPlan.createPlanPresenter(planLink = ExpoFpLinkType.ExpoKey(expoKey))
val preloadedPresenter = try {
val preloadedInfo = ExpofpPreloadCache.get(expoKey)
if (preloadedInfo != null) {
// Prefer preloaded presenter if available (faster, can reuse within session).
ExpoFpPlan.preloader.getPreloadedPlanPresenter(preloadedInfo)
} else {
null
}
} catch (_: Throwable) {
null
}

val p = preloadedPresenter ?: ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.ExpoKey(expoKey),
additionalParams = additionalParams
)
val ccProvider = createCrowdConnectedProvider(settingsMap)
if (ccProvider != null) p.setLocationProvider(ccProvider)
view.attachPresenter(p)
Expand Down