Skip to content

Commit 46e3b86

Browse files
authored
Merge pull request #43 from gitamego/feat/map-preloading
2 parents 6b6d4bc + 94f1eff commit 46e3b86

File tree

3 files changed

+124
-16
lines changed

3 files changed

+124
-16
lines changed

android/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ dependencies {
9191
implementation "com.facebook.react:react-native:+"
9292
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
9393

94-
implementation 'com.expofp:common:4.10.0'
95-
implementation 'com.expofp:fplan:4.10.0'
94+
implementation 'com.expofp:common:4.11.0'
95+
implementation 'com.expofp:fplan:4.11.0'
9696

97-
implementation 'com.expofp:crowdconnected:4.10.0'
98-
// implementation 'com.expofp:crowdconnectedbackground:4.10.0'
97+
implementation 'com.expofp:crowdconnected:4.11.0'
98+
// implementation 'com.expofp:crowdconnectedbackground:4.11.0'
9999
implementation 'net.crowdconnected.android.core:android-core:2.0.2'
100100
implementation 'net.crowdconnected.android.ips:android-ips:2.0.2'
101101
implementation 'net.crowdconnected.android.geo:android-geo:2.0.2'

android/src/main/java/com/expofp/ExpofpViewManager.kt

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,20 @@
11
package com.expofp
22

3-
import android.Manifest
4-
import android.app.Activity
5-
import android.app.AlertDialog
63
import android.app.Application
7-
import android.os.Build
84
import android.util.Log
95
import android.view.View
10-
import android.widget.Toast
11-
import androidx.activity.result.contract.ActivityResultContracts
12-
import androidx.core.app.ActivityCompat
136
import com.expofp.common.GlobalLocationProvider
147
import com.expofp.crowdconnected.CrowdConnectedProvider
158
import com.expofp.crowdconnected.Mode
16-
import com.expofp.crowdconnected.Settings
17-
// import com.expofp.crowdconnectedbackground.CrowdConnectedBackgroundProvider
189
import com.expofp.fplan.FplanView
1910
import com.expofp.fplan.models.FplanViewState
2011
import com.facebook.react.bridge.ReadableMap
2112
import com.facebook.react.uimanager.SimpleViewManager
2213
import com.facebook.react.uimanager.ThemedReactContext
2314
import com.facebook.react.uimanager.annotations.ReactProp
2415
import com.expofp.R
16+
import com.expofp.fplan.contracts.DownloadOfflinePlanCallback
17+
import com.expofp.fplan.models.OfflinePlanInfo
2518

2619
class ExpofpViewManager : SimpleViewManager<View>() {
2720
private var reactContext: ThemedReactContext? = null
@@ -40,6 +33,67 @@ class ExpofpViewManager : SimpleViewManager<View>() {
4033
super.onDropViewInstance(view)
4134
}
4235

36+
private fun getExpoKeyFromUrl(url: String): String {
37+
return url.substringAfter("https://").substringBefore(".expofp.com")
38+
}
39+
40+
private fun openMapForUrl(view: FplanView, url: String) {
41+
val expoKey = getExpoKeyFromUrl(url)
42+
val settings = com.expofp.fplan.models.Settings().withGlobalLocationProvider()
43+
44+
val offlinePlanManager = FplanView.getOfflinePlanManager(reactContext)
45+
val latestOfflinePlan = offlinePlanManager.allOfflinePlansFromCache
46+
.filter { offlinePlanInfo -> offlinePlanInfo.expoKey == expoKey }
47+
.maxByOrNull { offlinePlanInfo -> offlinePlanInfo.version }
48+
49+
if (latestOfflinePlan != null) {
50+
Log.d("ExpofpModule", latestOfflinePlan.expoKey)
51+
view.openOfflinePlan(latestOfflinePlan, "", settings)
52+
return
53+
}
54+
55+
val ctx = this.reactContext ?: run {
56+
view.load(url, settings)
57+
return
58+
}
59+
60+
val am = ctx.assets
61+
val cachePlanExists = try {
62+
am.open("${expoKey}.zip").close()
63+
true
64+
} catch (e: Exception) {
65+
false
66+
}
67+
68+
if (cachePlanExists) {
69+
try {
70+
Log.d("ExpofpModule", "openZipFromAssets: ${expoKey}.zip")
71+
view.openZipFromAssets("${expoKey}.zip", "", settings, ctx)
72+
return
73+
} catch (e: Exception) {
74+
Log.d("ExpofpModule", "failed to open asset zip, loading url: $url")
75+
view.load(url, settings)
76+
return
77+
}
78+
}
79+
80+
Log.d("ExpofpModule", "asset zip not found, loading url: $url")
81+
view.load(url, settings)
82+
}
83+
84+
private fun triggerOfflinePlanDownload(expoKey: String) {
85+
val offlinePlanManager = FplanView.getOfflinePlanManager(reactContext)
86+
offlinePlanManager.downloadOfflinePlanToCache(expoKey, object : DownloadOfflinePlanCallback {
87+
override fun onCompleted(offlinePlanInfo: OfflinePlanInfo) {
88+
Log.d("ExpofpModule", "downloaded offline plan: ${offlinePlanInfo.expoKey} v${offlinePlanInfo.version}")
89+
}
90+
91+
override fun onError(message: String) {
92+
Log.e("ExpofpModule", "offline plan download failed: $message")
93+
}
94+
})
95+
}
96+
4397
@ReactProp(name = "settings")
4498
fun setSettings(view: FplanView, settingsMap: ReadableMap?) {
4599
println("setSettings: $settingsMap")
@@ -68,7 +122,11 @@ class ExpofpViewManager : SimpleViewManager<View>() {
68122
GlobalLocationProvider.start()
69123
}
70124
if (view.state.equals(FplanViewState.Created)) {
71-
view.load(it.getString("url") ?: "", com.expofp.fplan.models.Settings().withGlobalLocationProvider());
125+
val url = it.getString("url") ?: ""
126+
val expoKey = getExpoKeyFromUrl(url)
127+
128+
openMapForUrl(view, url)
129+
triggerOfflinePlanDownload(expoKey)
72130
}
73131
}
74132
}

ios/ExpofpViewManager.swift

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,63 @@ struct ExpoFP: View {
7676

7777
@State private var loadedUrl: NSString? = nil
7878

79+
private var defaultSettings: ExpoFpFplan.Settings { .init(useGlobalLocationProvider: true) }
80+
81+
private func expoKey(from urlString: String) -> String {
82+
return (URL(string: urlString)?.host ?? "").components(separatedBy: ".").first ?? ""
83+
}
84+
85+
private func openMap(for urlString: String) {
86+
let key = expoKey(from: urlString)
87+
print("expoKey: \(key)")
88+
89+
if let cachePath = SharedFplanView.getFilePathFromCache() {
90+
let pathComponents = cachePath.absoluteString.components(separatedBy: "/")
91+
let cachedExpoKey = pathComponents.count >= 2 ? pathComponents[pathComponents.count - 2] : ""
92+
print("cachePath: \(cachePath.absoluteString)")
93+
print("cachedExpoKey: \(cachedExpoKey)")
94+
if cachedExpoKey == key {
95+
print("loading from cache")
96+
fplanView.openFile(htmlFilePathUrl: cachePath, params: nil, settings: defaultSettings)
97+
return
98+
} else {
99+
print("cache key mismatch, expected: \(key), found: \(cachedExpoKey)")
100+
}
101+
}
102+
103+
if let path = Bundle.main.path(forResource: key, ofType: "zip", inDirectory: "maps") {
104+
print("loading from preloaded map path: \(path)")
105+
fplanView.openZip(path, params: nil, useGlobalLocationProvider: true)
106+
return
107+
}
108+
109+
print("loading from url")
110+
fplanView.load(urlString, useGlobalLocationProvider: true)
111+
}
112+
113+
private func downloadOffline(for urlString: String) {
114+
print("downloading the map")
115+
fplanView.downloadZipToCache(urlString) { htmlFilePath, error in
116+
if let error = error {
117+
print("error downloading the map: \(error)")
118+
} else {
119+
print("success downloading the map")
120+
if let htmlFilePath = htmlFilePath {
121+
print("htmlFilePath: \(htmlFilePath)")
122+
}
123+
}
124+
}
125+
}
126+
79127
var body: some View {
80128
VStack
81129
{
82130
fplanView.onAppear{
83-
if (loadedUrl !== dataStore.url) {
84-
fplanView.load(dataStore.url as String, useGlobalLocationProvider: true)
131+
if loadedUrl != dataStore.url {
132+
let urlString = dataStore.url as String
133+
openMap(for: urlString)
85134
loadedUrl = dataStore.url
135+
downloadOffline(for: urlString)
86136
}
87137
}.onDisappear{
88138
fplanView.clear()

0 commit comments

Comments
 (0)