react-native-pointr 8.14.0 → 8.15.0

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.
@@ -0,0 +1,777 @@
1
+ package com.pointr
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.os.Handler
5
+ import android.os.Looper.getMainLooper
6
+ import android.util.Log
7
+ import android.view.Choreographer
8
+ import android.view.View
9
+ import android.widget.FrameLayout
10
+ import androidx.fragment.app.FragmentActivity
11
+ import com.facebook.react.bridge.ReactApplicationContext
12
+ import com.facebook.react.bridge.ReadableArray
13
+ import com.facebook.react.bridge.WritableMap
14
+ import com.facebook.react.bridge.WritableNativeMap
15
+ import com.facebook.react.uimanager.ThemedReactContext
16
+ import com.facebook.react.uimanager.ViewGroupManager
17
+ import com.facebook.react.uimanager.events.RCTEventEmitter
18
+ import com.pointrlabs.core.configuration.MutableConfiguration
19
+ import com.pointrlabs.core.management.DataManager
20
+ import com.pointrlabs.core.management.Pointr
21
+ import com.pointrlabs.core.management.interfaces.PointrListener
22
+ import com.pointrlabs.core.management.models.ErrorMessage
23
+ import com.pointrlabs.core.management.models.Site
24
+ import com.pointrlabs.core.map.handlers.MapWidgetEventsHandler
25
+ import com.pointrlabs.core.map.handlers.PathFindingEventsHandler
26
+ import com.pointrlabs.core.map.handlers.PathUpdatesEventHandler
27
+ import com.pointrlabs.core.map.models.PTRDeepLinkAction
28
+ import com.pointrlabs.core.map.models.PTRDeepLinkLocation
29
+ import com.pointrlabs.core.map.models.PTRDeepLinkPathfindingAction
30
+ import com.pointrlabs.core.map.models.PTRDeepLinkPoiLocation
31
+ import com.pointrlabs.core.map.models.PTRError
32
+ import com.pointrlabs.core.map.models.PTRMapSymbolLayer
33
+ import com.pointrlabs.core.map.models.events_listeners.MapEventsListener
34
+ import com.pointrlabs.core.map.models.events_listeners.MarkMyCarDetailsEvent
35
+ import com.pointrlabs.core.map.models.events_listeners.MarkMyCarDetailsEventsListener
36
+ import com.pointrlabs.core.map.models.events_listeners.PathFindingEventsListener
37
+ import com.pointrlabs.core.map.viewmodels.PTRMapWidgetConfiguration
38
+ import com.pointrlabs.core.map.views.PTRMapAnimationType
39
+ import com.pointrlabs.core.map.views.PTRMapFragment
40
+ import com.pointrlabs.core.map.views.PTRMapWidgetFragment
41
+ import com.pointrlabs.core.map.views.pathfinding.MarkMyCarBottomSheet
42
+ import com.pointrlabs.core.nativecore.wrappers.Plog
43
+ import com.pointrlabs.core.pathfinding.PathManager
44
+ import com.pointrlabs.core.pathfinding.session.PathSession
45
+ import com.pointrlabs.core.pathfinding.session.PathSessionState
46
+ import com.pointrlabs.core.positioning.model.PositioningTypes
47
+ import com.pointrlabs.core.site.SiteManager
48
+ import java.util.concurrent.Semaphore
49
+
50
+
51
+ @SuppressLint("LogNotTimber")
52
+ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
53
+ ViewGroupManager<FrameLayout>(), MapEventsListener, MarkMyCarDetailsEventsListener {
54
+
55
+ override fun getName() = REACT_CLASS
56
+
57
+ private var markMyCarButtonSheet: MarkMyCarBottomSheet? = null
58
+ private lateinit var frameLayout: FrameLayout
59
+
60
+ // TODO: Uncomment 1
61
+ // private var _ptrMapWidgetFragment: PTRMapWidgetFragment? = null
62
+ private val ptrMapWidgetFragment: PTRMapWidgetFragment?
63
+ get() {
64
+ // TODO: Uncomment 1
65
+ // _ptrMapWidgetFragment?.let { return it }
66
+ Log.i("PTRMapWidgetManager", "Creating map widget fragment")
67
+ // TODO: Uncomment 1
68
+ //_ptrMapWidgetFragment = createMapWidgetFragment()
69
+ // TODO: Comment 1
70
+ val _ptrMapWidgetFragment = createMapWidgetFragment()
71
+ Choreographer.getInstance().postFrameCallback(frameCallback)
72
+ _ptrMapWidgetFragment?.addListener(this)
73
+ return _ptrMapWidgetFragment
74
+ }
75
+
76
+ private fun createMapWidgetFragment(): PTRMapWidgetFragment {
77
+ waitForPointrToRun()
78
+ // TODO: wait for configuration to be ready
79
+ val configuration = PointrMapWidgetActivity.mapWidgetConfiguration
80
+ configuration.isExitButtonShown = false
81
+ @Suppress("DEPRECATION")
82
+ val widget = PTRMapWidgetFragment.newInstance(configuration).show(
83
+ (reactContext.currentActivity as FragmentActivity).supportFragmentManager,
84
+ frameLayout.id
85
+ )
86
+ return widget
87
+ }
88
+
89
+ /**
90
+ * Return a FrameLayout which will later hold the Fragment
91
+ */
92
+ override fun createViewInstance(reactContext: ThemedReactContext): FrameLayout {
93
+ frameLayout = FrameLayout(reactContext)
94
+ return frameLayout
95
+ }
96
+
97
+ /**
98
+ * Handle "create" command (called from JS) and call createFragment method
99
+ */
100
+ override fun receiveCommand(
101
+ root: FrameLayout, command: String, args: ReadableArray?
102
+ ) {
103
+ super.receiveCommand(root, command, args)
104
+ val args1 = args ?: return
105
+ val ptrMapWidgetFragment = this.ptrMapWidgetFragment ?: run {
106
+ Log.e(
107
+ "PTRMapWidgetManager",
108
+ "PTRMapWidgetFragment is null"
109
+ )
110
+ return
111
+ }
112
+ // TODO: Uncomment 1
113
+ // clearPath(ptrMapWidgetFragment)
114
+ // dismissMarkMyCarDetails(ptrMapWidgetFragment)
115
+ executeCommand(ptrMapWidgetFragment, command, args1)
116
+ }
117
+
118
+ private fun dismissMarkMyCarDetails(ptrMapWidgetFragment: PTRMapWidgetFragment) {
119
+ val markMyCarButtonSheet = markMyCarButtonSheet ?: return
120
+ val handler = ptrMapWidgetFragment.markMyCarEventsHandler
121
+ ?: return Plog.w("Mark my car events handler is null")
122
+ Plog.i("Dismissing mark my car details")
123
+ handler.onMarkMyCarDetailsEvent(markMyCarButtonSheet, MarkMyCarDetailsEvent.Cancel)
124
+ handler.onMarkMyCarDetailsEvent(markMyCarButtonSheet, MarkMyCarDetailsEvent.Close)
125
+ }
126
+
127
+ private fun clearPath(ptrMapWidgetFragment: PTRMapWidgetFragment) {
128
+ ptrMapWidgetFragment.mapFragment?.removeAllFeatures { isSuccess, message ->
129
+ if (!isSuccess) {
130
+ Log.e(
131
+ "PTRMapWidgetManager",
132
+ "Error removing features: $message"
133
+ )
134
+ }
135
+ ptrMapWidgetFragment.mapFragment?.removeLayer(LAYER_STATIC_PATH) { b, e ->
136
+ if (!b) {
137
+ Log.e(
138
+ "PTRMapWidgetManager",
139
+ "Error removing layer: $e"
140
+ )
141
+ }
142
+ ptrMapWidgetFragment.mapFragment?.currentPath = null
143
+ ptrMapWidgetFragment.mapFragment?.currentPathSession?.abort()
144
+ }
145
+ }
146
+ }
147
+
148
+ private fun executeCommand(
149
+ ptrMapWidgetFragment: PTRMapWidgetFragment,
150
+ command: String,
151
+ args1: ReadableArray
152
+ ) {
153
+ when (command) {
154
+ PTRMapWidgetCommandType.SITE -> showSite(ptrMapWidgetFragment, args1.getString(0))
155
+ PTRMapWidgetCommandType.BUILDING -> showBuilding(
156
+ ptrMapWidgetFragment,
157
+ args1.getString(0),
158
+ args1.getString(1)
159
+ )
160
+
161
+ PTRMapWidgetCommandType.LEVEL -> showLevel(
162
+ ptrMapWidgetFragment,
163
+ args1.getString(0),
164
+ args1.getString(1),
165
+ args1.getInt(2)
166
+ )
167
+
168
+ PTRMapWidgetCommandType.POI -> showPoi(
169
+ ptrMapWidgetFragment,
170
+ args1.getString(0),
171
+ args1.getString(1)
172
+ )
173
+
174
+ PTRMapWidgetCommandType.PATH -> showPath(
175
+ ptrMapWidgetFragment,
176
+ args1.getString(0),
177
+ args1.getString(1)
178
+ )
179
+
180
+ PTRMapWidgetCommandType.STATIC_PATH -> showStaticPath(
181
+ ptrMapWidgetFragment,
182
+ args1.getString(0),
183
+ args1.getString(1),
184
+ args1.getString(2)
185
+ )
186
+
187
+ PTRMapWidgetCommandType.MARK_MY_CAR_SITE -> {
188
+ showMarkMyCarDetails(
189
+ ptrMapWidgetFragment,
190
+ args1.getString(0),
191
+ shouldShowPopup = args1.getBoolean(1),
192
+ animationType = args1.getInt(2)
193
+ )
194
+ }
195
+
196
+ PTRMapWidgetCommandType.MARK_MY_CAR_LEVEL -> {
197
+ showMarkMyCarDetails(
198
+ ptrMapWidgetFragment,
199
+ args1.getString(0),
200
+ args1.getString(1),
201
+ args1.getInt(2),
202
+ args1.getBoolean(3),
203
+ args1.getInt(4)
204
+ )
205
+ }
206
+
207
+ PTRMapWidgetCommandType.MY_CAR_SITE -> {
208
+ showMyCarDetails(ptrMapWidgetFragment, args1.getString(0), args1.getInt(1))
209
+ }
210
+
211
+ else -> return
212
+ }
213
+ }
214
+
215
+ private fun showMyCarDetails(
216
+ ptrMapWidgetFragment: PTRMapWidgetFragment,
217
+ siteExternalIdentifier: String,
218
+ animationTypeOrdinal: Int
219
+ ) {
220
+ val animationType = PTRMapAnimationType.entries[animationTypeOrdinal]
221
+ ptrMapWidgetFragment.showMyCarDetails(
222
+ siteExternalIdentifier,
223
+ shouldShowDialog = false,
224
+ animationType = animationType
225
+ ) onComplete@{ error ->
226
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
227
+ PTRMapWidgetCommandType.MY_CAR_SITE,
228
+ siteExternalIdentifier,
229
+ animationType,
230
+ error ?: ""
231
+ )
232
+ error?.let {
233
+ Plog.e("Error showing mark my car details: $it")
234
+ return@onComplete
235
+ }
236
+ Plog.i("Mark my car details is shown")
237
+ }
238
+ }
239
+
240
+ private fun showMarkMyCarDetails(
241
+ ptrMapWidgetFragment: PTRMapWidgetFragment,
242
+ siteExternalIdentifier: String,
243
+ buildingExternalIdentifier: String? = null,
244
+ levelIndex: Int? = null,
245
+ shouldShowPopup: Boolean,
246
+ animationType: Int
247
+ ) {
248
+
249
+ ptrMapWidgetFragment.showMarkMyCarDetails(
250
+ siteExternalIdentifier,
251
+ buildingExternalIdentifier,
252
+ levelIndex,
253
+ PTRMapAnimationType.entries[animationType],
254
+ shouldShowPopup
255
+ ) onComplete@{ error ->
256
+ if (buildingExternalIdentifier == null || levelIndex == null || levelIndex == PositioningTypes.INVALID_INTEGER) {
257
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
258
+ PTRMapWidgetCommandType.MARK_MY_CAR_LEVEL,
259
+ siteExternalIdentifier,
260
+ buildingExternalIdentifier ?: "",
261
+ levelIndex ?: PositioningTypes.INVALID_INTEGER,
262
+ shouldShowPopup,
263
+ animationType,
264
+ error ?: ""
265
+ )
266
+ } else {
267
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
268
+ PTRMapWidgetCommandType.MARK_MY_CAR_SITE,
269
+ siteExternalIdentifier,
270
+ shouldShowPopup,
271
+ animationType,
272
+ error ?: ""
273
+ )
274
+ }
275
+ error?.let {
276
+ Plog.e("Error showing mark my car details: $it")
277
+ return@onComplete
278
+ }
279
+ Plog.i("Mark my car details is shown")
280
+ }
281
+ }
282
+
283
+ private fun mapWidgetDidEndLoading(
284
+ @PTRMapWidgetCommandType command: String,
285
+ vararg args: Any
286
+ ) {
287
+ val event: WritableMap = WritableNativeMap()
288
+ event.putString("command", command)
289
+ when (command) {
290
+ PTRMapWidgetCommandType.SITE -> {
291
+ event.putString("siteExternalIdentifier", args[0] as String)
292
+ event.putString("error", args[1] as String)
293
+ }
294
+
295
+ PTRMapWidgetCommandType.BUILDING -> {
296
+ event.putString("siteExternalIdentifier", args[0] as String)
297
+ event.putString("buildingExternalIdentifier", args[1] as String)
298
+ event.putString("error", args[2] as String)
299
+ }
300
+
301
+ PTRMapWidgetCommandType.LEVEL -> {
302
+ event.putString("siteExternalIdentifier", args[0] as String)
303
+ event.putString("buildingExternalIdentifier", args[1] as String)
304
+ event.putInt("levelIndex", args[2] as Int)
305
+ event.putString("error", args[3] as String)
306
+ }
307
+
308
+ PTRMapWidgetCommandType.POI -> {
309
+ event.putString("siteExternalIdentifier", args[0] as String)
310
+ event.putString("poiExternalIdentifier", args[1] as String)
311
+ event.putString("error", args[2] as String)
312
+ }
313
+
314
+ PTRMapWidgetCommandType.PATH -> {
315
+ event.putString("siteExternalIdentifier", args[0] as String)
316
+ event.putString("poiExternalIdentifier", args[1] as String)
317
+ event.putString("error", args[2] as String)
318
+ }
319
+
320
+ PTRMapWidgetCommandType.STATIC_PATH -> {
321
+ event.putString("siteExternalIdentifier", args[0] as String)
322
+ event.putString("fromPoiExternalIdentifier", args[1] as String)
323
+ event.putString("toPoiExternalIdentifier", args[2] as String)
324
+ event.putString("error", args[3] as String)
325
+ }
326
+
327
+ else -> {
328
+ return
329
+ }
330
+ }
331
+ reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(
332
+ frameLayout.id,
333
+ "onMapWidgetDidEndLoading",
334
+ event
335
+ )
336
+ }
337
+
338
+ override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
339
+ return mapOf(
340
+ "onMapWidgetDidEndLoading" to mapOf(
341
+ "phasedRegistrationNames" to mapOf(
342
+ "bubbled" to "onMapWidgetDidEndLoading"
343
+ )
344
+ )
345
+ )
346
+ }
347
+
348
+
349
+ private fun showStaticPath(
350
+ ptrMapWidgetFragment: PTRMapWidgetFragment,
351
+ site: String,
352
+ fromPoi: String,
353
+ toPoi: String
354
+ ) {
355
+ val siteObject = getSite(site) ?: run {
356
+ mapWidgetDidEndLoading(
357
+ PTRMapWidgetCommandType.STATIC_PATH,
358
+ site,
359
+ fromPoi,
360
+ toPoi,
361
+ "Site not found"
362
+ )
363
+ return
364
+ }
365
+ if (!waitForSiteData(siteObject)) {
366
+ mapWidgetDidEndLoading(
367
+ PTRMapWidgetCommandType.STATIC_PATH,
368
+ site,
369
+ fromPoi,
370
+ toPoi,
371
+ "Site data not found"
372
+ )
373
+ return
374
+ }
375
+ val source = Pointr.getPointr()?.poiManager?.getPoiByExternalIdentifier(siteObject, fromPoi)
376
+ ?: run {
377
+ mapWidgetDidEndLoading(
378
+ PTRMapWidgetCommandType.STATIC_PATH,
379
+ site,
380
+ fromPoi,
381
+ toPoi,
382
+ "Source POI not found"
383
+ )
384
+ return
385
+ }
386
+ val target =
387
+ Pointr.getPointr()?.poiManager?.getPoiByExternalIdentifier(siteObject, toPoi) ?: run {
388
+ mapWidgetDidEndLoading(
389
+ PTRMapWidgetCommandType.STATIC_PATH,
390
+ site,
391
+ fromPoi,
392
+ toPoi,
393
+ "Target POI not found"
394
+ )
395
+ return
396
+ }
397
+ if (!waitForPathManager(siteObject)) {
398
+ mapWidgetDidEndLoading(
399
+ PTRMapWidgetCommandType.STATIC_PATH,
400
+ site,
401
+ fromPoi,
402
+ toPoi,
403
+ "Path manager not ready"
404
+ )
405
+ return
406
+ }
407
+ val pathManager = Pointr.getPointr()?.pathManager ?: run {
408
+ mapWidgetDidEndLoading(
409
+ PTRMapWidgetCommandType.STATIC_PATH,
410
+ site,
411
+ fromPoi,
412
+ toPoi,
413
+ "Path manager not found"
414
+ )
415
+ return
416
+ }
417
+ val path = pathManager.calculatePath(source, listOf(target)) ?: run {
418
+ mapWidgetDidEndLoading(
419
+ PTRMapWidgetCommandType.STATIC_PATH,
420
+ site,
421
+ fromPoi,
422
+ toPoi,
423
+ "Path not found"
424
+ )
425
+ return
426
+ }
427
+ val onCompleted = { error: String? ->
428
+ error?.let {
429
+ mapWidgetDidEndLoading(
430
+ PTRMapWidgetCommandType.STATIC_PATH,
431
+ site,
432
+ fromPoi,
433
+ toPoi,
434
+ "Error loading the map: $it"
435
+ )
436
+ Plog.e("Error showing level: $it")
437
+ return@let
438
+ }
439
+ ptrMapWidgetFragment.focusOnCoordinate(
440
+ source.location.site?.internalIdentifier ?: PositioningTypes.INVALID_INTEGER,
441
+ source.location.building?.internalIdentifier ?: PositioningTypes.INVALID_INTEGER,
442
+ source.location.level?.index ?: PositioningTypes.INVALID_INTEGER,
443
+ source.location.lat,
444
+ source.location.lon
445
+ ) {
446
+ val layer = PTRMapSymbolLayer(LAYER_STATIC_PATH)
447
+ val mapFragment = ptrMapWidgetFragment.mapFragment ?: return@focusOnCoordinate
448
+ mapFragment.addLayer(layer) { b1, e1 ->
449
+ if (!b1) {
450
+ mapWidgetDidEndLoading(
451
+ PTRMapWidgetCommandType.STATIC_PATH,
452
+ site,
453
+ fromPoi,
454
+ toPoi,
455
+ "Error adding layer: $e1"
456
+ )
457
+ Plog.e("Error adding layer: $e1")
458
+ return@addLayer
459
+ }
460
+ mapFragment.addFeatures(
461
+ listOf(source, target), layer.identifier
462
+ ) { b2, e2 ->
463
+ if (!b2) {
464
+ mapWidgetDidEndLoading(
465
+ PTRMapWidgetCommandType.STATIC_PATH,
466
+ site,
467
+ fromPoi,
468
+ toPoi,
469
+ "Error adding features: $e2"
470
+ )
471
+ Plog.e("Error adding features: $e2")
472
+ return@addFeatures
473
+ }
474
+ mapFragment.currentPath = path
475
+ mapWidgetDidEndLoading(
476
+ PTRMapWidgetCommandType.STATIC_PATH,
477
+ site,
478
+ fromPoi,
479
+ toPoi,
480
+ ""
481
+ )
482
+ Plog.i("Path shown")
483
+ }
484
+ }
485
+ }
486
+ }
487
+ source.level?.let {
488
+ ptrMapWidgetFragment.showLevel(it, onComplete = onCompleted)
489
+ } ?: ptrMapWidgetFragment.showSite(
490
+ source.location.site?.internalIdentifier ?: 0, onComplete = onCompleted
491
+ )
492
+
493
+ }
494
+
495
+ private fun showPath(ptrMapWidgetFragment: PTRMapWidgetFragment, site: String, toPoi: String) {
496
+
497
+
498
+ val siteObject = getSite(site) ?: run {
499
+ mapWidgetDidEndLoading(
500
+ PTRMapWidgetCommandType.PATH,
501
+ site,
502
+ toPoi,
503
+ "Site not found"
504
+ )
505
+ return
506
+ }
507
+ if (!waitForSiteData(siteObject)) {
508
+ mapWidgetDidEndLoading(
509
+ PTRMapWidgetCommandType.PATH,
510
+ site,
511
+ toPoi,
512
+ "Site data not found"
513
+ )
514
+ return
515
+ }
516
+ val target =
517
+ Pointr.getPointr()?.poiManager?.getPoiByExternalIdentifier(siteObject, toPoi) ?: run {
518
+ mapWidgetDidEndLoading(
519
+ PTRMapWidgetCommandType.PATH,
520
+ site,
521
+ toPoi,
522
+ "Target POI not found"
523
+ )
524
+ return
525
+ }
526
+
527
+ val action = PTRDeepLinkPathfindingAction(
528
+ PTRDeepLinkPoiLocation(
529
+ siteObject.internalIdentifier,
530
+ target.id
531
+ )
532
+ )
533
+ ptrMapWidgetFragment.performDeepLinkAction(action) { error ->
534
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
535
+ PTRMapWidgetCommandType.PATH,
536
+ site,
537
+ toPoi,
538
+ error ?: ""
539
+ )
540
+ error?.let {
541
+ Plog.e("Error showing path: $it")
542
+ return@performDeepLinkAction
543
+ }
544
+ Plog.i("Path shown")
545
+ }
546
+ }
547
+
548
+ private fun showPoi(ptrMapWidgetFragment: PTRMapWidgetFragment, site: String, poi: String) {
549
+ ptrMapWidgetFragment.showPoiDetails(site, poi) { error ->
550
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
551
+ PTRMapWidgetCommandType.POI,
552
+ site,
553
+ poi,
554
+ error ?: ""
555
+ )
556
+ error?.let {
557
+ Plog.e("Error showing poi: $it")
558
+ return@showPoiDetails
559
+ }
560
+ Plog.i("Poi shown")
561
+ }
562
+ }
563
+
564
+ private fun showLevel(
565
+ ptrMapWidgetFragment: PTRMapWidgetFragment,
566
+ site: String,
567
+ building: String,
568
+ level: Int
569
+ ) {
570
+ ptrMapWidgetFragment.showLevel(site, building, level) showLevelInternal@{ error ->
571
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
572
+ PTRMapWidgetCommandType.LEVEL,
573
+ site,
574
+ building,
575
+ level,
576
+ error ?: ""
577
+ )
578
+ error?.let {
579
+ Plog.e("Error showing level: $it")
580
+ return@showLevelInternal
581
+ }
582
+ Plog.i("Level shown")
583
+ }
584
+ }
585
+
586
+ private fun showBuilding(
587
+ ptrMapWidgetFragment: PTRMapWidgetFragment,
588
+ site: String,
589
+ building: String
590
+ ) {
591
+ ptrMapWidgetFragment.showBuilding(site, building) showBuildingInternal@{ error ->
592
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
593
+ PTRMapWidgetCommandType.BUILDING,
594
+ site,
595
+ building,
596
+ error ?: ""
597
+ )
598
+ error?.let {
599
+ Plog.e("Error showing building: $it")
600
+ return@showBuildingInternal
601
+ }
602
+ Plog.i("Building shown")
603
+ }
604
+ }
605
+
606
+ private fun showSite(ptrMapWidgetFragment: PTRMapWidgetFragment, site: String) {
607
+ ptrMapWidgetFragment.showSite(site) showSiteInternal@{ error ->
608
+ this@PTRMapWidgetManager.mapWidgetDidEndLoading(
609
+ PTRMapWidgetCommandType.SITE,
610
+ site,
611
+ error ?: ""
612
+ )
613
+ error?.let {
614
+ Plog.e("Error showing site: $it")
615
+ return@showSiteInternal
616
+ }
617
+ Plog.i("Site shown")
618
+ }
619
+ }
620
+
621
+ // region Show path
622
+
623
+ private fun waitForPathManager(theSite: Site): Boolean {
624
+ val pathManager = Pointr.getPointr()?.pathManager ?: return false
625
+ val semaphore = Semaphore(0)
626
+ val listener = object : PathManager.Listener {
627
+ override fun onPathManagerReadyForSite(site: Site) {
628
+ if (site != theSite) return
629
+ semaphore.release()
630
+ }
631
+ }
632
+ pathManager.addListener(listener)
633
+ if (!pathManager.isReadyForSite(theSite)) {
634
+ semaphore.tryAcquire(15, java.util.concurrent.TimeUnit.SECONDS)
635
+ }
636
+ pathManager.removeListener(listener)
637
+ return pathManager.isReadyForSite(theSite)
638
+ }
639
+
640
+ private fun waitForSiteData(theSite: Site): Boolean {
641
+ val dataManager = Pointr.getPointr()?.dataManager ?: return false
642
+ val semaphore = Semaphore(0)
643
+ val listener = object : DataManager.Listener {
644
+ override fun onDataManagerCompleteAllForSite(
645
+ site: Site,
646
+ isSuccessful: Boolean,
647
+ isOnlineData: Boolean,
648
+ errors: List<ErrorMessage?>?
649
+ ) {
650
+ if (site != theSite) return
651
+ if (!isOnlineData) return
652
+ semaphore.release()
653
+ }
654
+ }
655
+ dataManager.addListener(listener)
656
+ if (Pointr.getPointr()?.poiManager?.hasContentForSite(theSite) != true) {
657
+ dataManager.loadDataForSite(theSite)
658
+ semaphore.tryAcquire(15, java.util.concurrent.TimeUnit.SECONDS)
659
+ }
660
+ dataManager.removeListener(listener)
661
+ return Pointr.getPointr()?.poiManager?.hasContentForSite(theSite) == true
662
+ }
663
+
664
+ private fun getSite(site: String): Site? {
665
+ val siteManager = Pointr.getPointr()?.siteManager ?: return null
666
+ val semaphore = Semaphore(0)
667
+ val listener = object : SiteManager.Listener {
668
+ override fun onSiteManagerDataChanged() {
669
+ semaphore.release()
670
+ }
671
+ }
672
+ siteManager.addListener(listener)
673
+ if (siteManager.getSites().isEmpty()) {
674
+ semaphore.tryAcquire(10, java.util.concurrent.TimeUnit.SECONDS)
675
+ }
676
+ siteManager.removeListener(listener)
677
+ return siteManager.getSite(site)
678
+ }
679
+
680
+ // endregion
681
+
682
+ private fun waitForPointrToRun(): Boolean {
683
+ Log.e(
684
+ "PTRMapWidgetManager",
685
+ "Waiting for Pointr to run"
686
+ )
687
+ val semaphore = Semaphore(0)
688
+ val listener = object : PointrListener {
689
+ override fun onStateUpdated(p0: Pointr.State?) {
690
+ Log.e(
691
+ "PTRMapWidgetManager",
692
+ "Pointr state updated to: $p0"
693
+ )
694
+ val state = p0 ?: return
695
+ if (state.`val` < Pointr.State.OFF.`val` || state == Pointr.State.RUNNING) {
696
+ semaphore.release()
697
+ return
698
+ }
699
+ }
700
+ }
701
+ Log.e(
702
+ "PTRMapWidgetManager",
703
+ "Adding listener to Pointr"
704
+ )
705
+ Pointr.getPointr()?.addListener(listener)
706
+ Log.e(
707
+ "PTRMapWidgetManager",
708
+ "Pointr state: ${Pointr.getPointr()?.state}"
709
+ )
710
+ if (Pointr.getPointr()?.state == Pointr.State.RUNNING) {
711
+ Log.e(
712
+ "PTRMapWidgetManager",
713
+ "Already running Pointr"
714
+ )
715
+ Pointr.getPointr()?.removeListener(listener)
716
+ return true
717
+ }
718
+ Log.e(
719
+ "PTRMapWidgetManager",
720
+ "Starting Pointr"
721
+ )
722
+ Pointr.getPointr()?.start()
723
+ Log.e(
724
+ "PTRMapWidgetManager",
725
+ "Pointr started"
726
+ )
727
+ semaphore.tryAcquire(10, java.util.concurrent.TimeUnit.SECONDS)
728
+ Log.e(
729
+ "PTRMapWidgetManager",
730
+ "Final Pointr state: ${Pointr.getPointr()?.state}"
731
+ )
732
+ Pointr.getPointr()?.removeListener(listener)
733
+ return Pointr.getPointr()?.state == Pointr.State.RUNNING
734
+ }
735
+
736
+ override fun mapDidEndLoading(mapFragment: PTRMapFragment) {
737
+ super.mapDidEndLoading(mapFragment)
738
+ Log.i("PTRMapWidgetManager", "Map loaded")
739
+ }
740
+
741
+ override fun mapDidFailToLoad(mapFragment: PTRMapFragment, ptrError: PTRError) {
742
+ super.mapDidFailToLoad(mapFragment, ptrError)
743
+ Log.e("PTRMapWidgetManager", "Map failed to load: $ptrError")
744
+ }
745
+
746
+ override fun onMarkMyCarDetailsEvent(
747
+ markMyCarSheet: MarkMyCarBottomSheet,
748
+ markMyCarDetailsEvent: MarkMyCarDetailsEvent
749
+ ) {
750
+ super.onMarkMyCarDetailsEvent(markMyCarSheet, markMyCarDetailsEvent)
751
+ this.markMyCarButtonSheet = markMyCarSheet
752
+ Plog.i("Mark my car details event: $markMyCarDetailsEvent")
753
+ }
754
+
755
+ private val frameCallback = object : Choreographer.FrameCallback {
756
+ override fun doFrame(frameTimeNanos: Long) {
757
+ frameLayout.measure(
758
+ View.MeasureSpec.makeMeasureSpec(frameLayout.width, View.MeasureSpec.EXACTLY),
759
+ View.MeasureSpec.makeMeasureSpec(frameLayout.height, View.MeasureSpec.EXACTLY)
760
+ )
761
+ frameLayout.layout(
762
+ frameLayout.left,
763
+ frameLayout.top,
764
+ frameLayout.right,
765
+ frameLayout.bottom
766
+ )
767
+ frameLayout.viewTreeObserver.dispatchOnGlobalLayout()
768
+ Choreographer.getInstance().postFrameCallback(this)
769
+ }
770
+ }
771
+
772
+ companion object {
773
+ const val REACT_CLASS = "PTRMapWidget"
774
+ const val LAYER_STATIC_PATH = "sym-static-path"
775
+ }
776
+
777
+ }