@exterio/react-native-yamap-lite 1.0.1
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.
- package/LICENSE +20 -0
- package/README.md +510 -0
- package/YamapLite.podspec +21 -0
- package/android/build.gradle +101 -0
- package/android/gradle.properties +14 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/yamaplite/ClusteredYamapLiteViewManager.kt +181 -0
- package/android/src/main/java/com/yamaplite/Components/ClusteredYamapLiteView.kt +169 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLiteCircleView.kt +145 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLiteMarkerView.kt +214 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLitePolygon.kt +149 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLitePolyline.kt +171 -0
- package/android/src/main/java/com/yamaplite/Components/YamapLiteView.kt +678 -0
- package/android/src/main/java/com/yamaplite/Events/CameraPositionChangeEvent.kt +38 -0
- package/android/src/main/java/com/yamaplite/Events/MapLoadEvent.kt +34 -0
- package/android/src/main/java/com/yamaplite/Events/PressEvent.kt +24 -0
- package/android/src/main/java/com/yamaplite/Utils/ImageCache.kt +45 -0
- package/android/src/main/java/com/yamaplite/Utils/PointParser.kt +39 -0
- package/android/src/main/java/com/yamaplite/Utils/ResolveImageHelper.kt +122 -0
- package/android/src/main/java/com/yamaplite/Utils/YamapUtils.kt +169 -0
- package/android/src/main/java/com/yamaplite/YamapLiteCircleViewManager.kt +67 -0
- package/android/src/main/java/com/yamaplite/YamapLiteMarkerViewManager.kt +82 -0
- package/android/src/main/java/com/yamaplite/YamapLitePackage.kt +41 -0
- package/android/src/main/java/com/yamaplite/YamapLitePolygonViewManager.kt +61 -0
- package/android/src/main/java/com/yamaplite/YamapLitePolylineViewManager.kt +75 -0
- package/android/src/main/java/com/yamaplite/YamapLiteViewManager.kt +176 -0
- package/ios/ClusteredYamapLiteView.h +15 -0
- package/ios/ClusteredYamapLiteView.mm +325 -0
- package/ios/ClusteredYamapLiteViewManager.mm +17 -0
- package/ios/Components/Circle.swift +108 -0
- package/ios/Components/ClusteredYamap.swift +190 -0
- package/ios/Components/Marker.swift +187 -0
- package/ios/Components/Polygon.swift +108 -0
- package/ios/Components/Polyline.swift +125 -0
- package/ios/Components/Yamap.swift +585 -0
- package/ios/Listeners/CameraListener.swift +54 -0
- package/ios/Listeners/ClusterListener.swift +38 -0
- package/ios/Listeners/MapInputListener.swift +35 -0
- package/ios/Listeners/MapLoadListener.swift +35 -0
- package/ios/Listeners/MapObjectTap.swift +12 -0
- package/ios/Listeners/UserLocationObjectListener.swift +29 -0
- package/ios/Models/YamapModels.swift +77 -0
- package/ios/Utils/ImageCache.swift +20 -0
- package/ios/Utils/PointsEqual.h +45 -0
- package/ios/Utils/ResolveImageHelper.swift +142 -0
- package/ios/YamapLiteCircleView.h +15 -0
- package/ios/YamapLiteCircleView.mm +102 -0
- package/ios/YamapLiteMarkerView.h +15 -0
- package/ios/YamapLiteMarkerView.mm +102 -0
- package/ios/YamapLitePolygonView.h +15 -0
- package/ios/YamapLitePolygonView.mm +120 -0
- package/ios/YamapLitePolylineView.h +15 -0
- package/ios/YamapLitePolylineView.mm +115 -0
- package/ios/YamapLiteView.h +15 -0
- package/ios/YamapLiteView.mm +361 -0
- package/ios/YamapLiteViewManager.mm +17 -0
- package/ios/YamapUtils.h +5 -0
- package/ios/YamapUtils.mm +205 -0
- package/lib/module/@types/index.js +8 -0
- package/lib/module/@types/index.js.map +1 -0
- package/lib/module/ClusteredYamapLiteViewNativeComponent.ts +98 -0
- package/lib/module/Components/Circle.js +20 -0
- package/lib/module/Components/Circle.js.map +1 -0
- package/lib/module/Components/ClusteredYamap.js +133 -0
- package/lib/module/Components/ClusteredYamap.js.map +1 -0
- package/lib/module/Components/Marker.js +40 -0
- package/lib/module/Components/Marker.js.map +1 -0
- package/lib/module/Components/Polygon.js +25 -0
- package/lib/module/Components/Polygon.js.map +1 -0
- package/lib/module/Components/Polyline.js +25 -0
- package/lib/module/Components/Polyline.js.map +1 -0
- package/lib/module/Components/Yamap.js +124 -0
- package/lib/module/Components/Yamap.js.map +1 -0
- package/lib/module/Components/index.js +9 -0
- package/lib/module/Components/index.js.map +1 -0
- package/lib/module/NativeYamapUtils.js +5 -0
- package/lib/module/NativeYamapUtils.js.map +1 -0
- package/lib/module/Utils/YamapUtils.js +14 -0
- package/lib/module/Utils/YamapUtils.js.map +1 -0
- package/lib/module/YamapCircleViewNativeComponent.ts +28 -0
- package/lib/module/YamapLiteViewNativeComponent.ts +93 -0
- package/lib/module/YamapMarkerViewNativeComponent.ts +32 -0
- package/lib/module/YamapPolygonViewNativeComponent.ts +28 -0
- package/lib/module/YamapPolylineViewNativeComponent.ts +31 -0
- package/lib/module/index.js +7 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/@types/index.d.ts +257 -0
- package/lib/typescript/src/@types/index.d.ts.map +1 -0
- package/lib/typescript/src/ClusteredYamapLiteViewNativeComponent.d.ts +82 -0
- package/lib/typescript/src/ClusteredYamapLiteViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/Components/Circle.d.ts +4 -0
- package/lib/typescript/src/Components/Circle.d.ts.map +1 -0
- package/lib/typescript/src/Components/ClusteredYamap.d.ts +3 -0
- package/lib/typescript/src/Components/ClusteredYamap.d.ts.map +1 -0
- package/lib/typescript/src/Components/Marker.d.ts +3 -0
- package/lib/typescript/src/Components/Marker.d.ts.map +1 -0
- package/lib/typescript/src/Components/Polygon.d.ts +4 -0
- package/lib/typescript/src/Components/Polygon.d.ts.map +1 -0
- package/lib/typescript/src/Components/Polyline.d.ts +4 -0
- package/lib/typescript/src/Components/Polyline.d.ts.map +1 -0
- package/lib/typescript/src/Components/Yamap.d.ts +3 -0
- package/lib/typescript/src/Components/Yamap.d.ts.map +1 -0
- package/lib/typescript/src/Components/index.d.ts +7 -0
- package/lib/typescript/src/Components/index.d.ts.map +1 -0
- package/lib/typescript/src/NativeYamapUtils.d.ts +30 -0
- package/lib/typescript/src/NativeYamapUtils.d.ts.map +1 -0
- package/lib/typescript/src/Utils/YamapUtils.d.ts +27 -0
- package/lib/typescript/src/Utils/YamapUtils.d.ts.map +1 -0
- package/lib/typescript/src/YamapCircleViewNativeComponent.d.ts +20 -0
- package/lib/typescript/src/YamapCircleViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapLiteViewNativeComponent.d.ts +80 -0
- package/lib/typescript/src/YamapLiteViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapMarkerViewNativeComponent.d.ts +25 -0
- package/lib/typescript/src/YamapMarkerViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapPolygonViewNativeComponent.d.ts +20 -0
- package/lib/typescript/src/YamapPolygonViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/YamapPolylineViewNativeComponent.d.ts +23 -0
- package/lib/typescript/src/YamapPolylineViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +189 -0
- package/src/@types/index.ts +314 -0
- package/src/ClusteredYamapLiteViewNativeComponent.ts +98 -0
- package/src/Components/Circle.tsx +22 -0
- package/src/Components/ClusteredYamap.tsx +194 -0
- package/src/Components/Marker.tsx +50 -0
- package/src/Components/Polygon.tsx +27 -0
- package/src/Components/Polyline.tsx +27 -0
- package/src/Components/Yamap.tsx +176 -0
- package/src/Components/index.ts +6 -0
- package/src/NativeYamapUtils.ts +47 -0
- package/src/Utils/YamapUtils.ts +63 -0
- package/src/YamapCircleViewNativeComponent.ts +28 -0
- package/src/YamapLiteViewNativeComponent.ts +93 -0
- package/src/YamapMarkerViewNativeComponent.ts +32 -0
- package/src/YamapPolygonViewNativeComponent.ts +28 -0
- package/src/YamapPolylineViewNativeComponent.ts +31 -0
- package/src/index.tsx +5 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package com.yamaplite.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
import com.facebook.react.uimanager.events.Event
|
|
6
|
+
import com.yandex.mapkit.map.MapLoadStatistics
|
|
7
|
+
|
|
8
|
+
class MapLoadEvent(
|
|
9
|
+
surfaceId: Int,
|
|
10
|
+
viewTag: Int,
|
|
11
|
+
private val statistics: MapLoadStatistics,
|
|
12
|
+
) : Event<MapLoadEvent>(surfaceId, viewTag) {
|
|
13
|
+
|
|
14
|
+
override fun getEventName(): String = EVENT_NAME
|
|
15
|
+
|
|
16
|
+
override fun getEventData(): WritableMap =
|
|
17
|
+
Arguments.createMap().apply {
|
|
18
|
+
putInt("renderObjectCount", statistics.renderObjectCount)
|
|
19
|
+
putDouble("curZoomModelsLoaded", statistics.curZoomModelsLoaded.toDouble())
|
|
20
|
+
putDouble("curZoomPlacemarksLoaded", statistics.curZoomPlacemarksLoaded.toDouble())
|
|
21
|
+
putDouble("curZoomLabelsLoaded", statistics.curZoomLabelsLoaded.toDouble())
|
|
22
|
+
putDouble("curZoomGeometryLoaded", statistics.curZoomGeometryLoaded.toDouble())
|
|
23
|
+
putDouble("tileMemoryUsage", statistics.tileMemoryUsage.toDouble())
|
|
24
|
+
putDouble("delayedGeometryLoaded", statistics.delayedGeometryLoaded.toDouble())
|
|
25
|
+
putDouble("fullyAppeared", statistics.fullyAppeared.toDouble())
|
|
26
|
+
putDouble("fullyLoaded", statistics.fullyLoaded.toDouble())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun getCoalescingKey(): Short = 0
|
|
30
|
+
|
|
31
|
+
companion object {
|
|
32
|
+
const val EVENT_NAME = "onMapLoaded"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package com.yamaplite.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
import com.facebook.react.uimanager.events.Event
|
|
6
|
+
import com.yandex.mapkit.geometry.Point
|
|
7
|
+
|
|
8
|
+
class PressEvent(
|
|
9
|
+
surfaceId: Int,
|
|
10
|
+
viewTag: Int,
|
|
11
|
+
private val eventName: String,
|
|
12
|
+
private val point: Point,
|
|
13
|
+
) : Event<PressEvent>(surfaceId, viewTag) {
|
|
14
|
+
|
|
15
|
+
override fun getEventName(): String = eventName
|
|
16
|
+
|
|
17
|
+
override fun getEventData(): WritableMap =
|
|
18
|
+
Arguments.createMap().apply {
|
|
19
|
+
putDouble("lat", point.latitude)
|
|
20
|
+
putDouble("lon", point.longitude)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override fun getCoalescingKey(): Short = 0
|
|
24
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
package com.yamaplite.utils
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
import android.util.LruCache
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import java.lang.Runtime
|
|
7
|
+
|
|
8
|
+
object ImageCache {
|
|
9
|
+
|
|
10
|
+
private val cacheSize = 50 * 1024 * 1024 // 50 МБ в байтах
|
|
11
|
+
|
|
12
|
+
private val memoryCache: LruCache<String, Bitmap> = object : LruCache<String, Bitmap>(cacheSize) {
|
|
13
|
+
override fun sizeOf(key: String, value: Bitmap): Int {
|
|
14
|
+
return value.byteCount // размер в байтах
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Получить Bitmap из кэша по URL */
|
|
19
|
+
fun get(url: String): Bitmap? {
|
|
20
|
+
val bitmap = memoryCache.get(url)
|
|
21
|
+
if (bitmap != null) {
|
|
22
|
+
Log.d("ImageCache", "Cache HIT for: $url (size: ${bitmap.byteCount} bytes)")
|
|
23
|
+
} else {
|
|
24
|
+
Log.d("ImageCache", "Cache MISS for: $url")
|
|
25
|
+
}
|
|
26
|
+
return bitmap
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Положить Bitmap в кэш по URL */
|
|
30
|
+
fun put(url: String, bitmap: Bitmap) {
|
|
31
|
+
val size = bitmap.byteCount
|
|
32
|
+
memoryCache.put(url, bitmap)
|
|
33
|
+
Log.d("ImageCache", "Cached image: $url (size: $size bytes, cache size: ${memoryCache.size()} bytes)")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Проверка наличия Bitmap в кэше */
|
|
37
|
+
fun contains(url: String): Boolean {
|
|
38
|
+
return memoryCache.get(url) != null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Очистить весь кэш */
|
|
42
|
+
fun clear() {
|
|
43
|
+
memoryCache.evictAll()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package com.yamaplite.utils
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableArray
|
|
4
|
+
import com.yandex.mapkit.ScreenPoint
|
|
5
|
+
import com.yandex.mapkit.geometry.Point
|
|
6
|
+
|
|
7
|
+
object PointParser {
|
|
8
|
+
|
|
9
|
+
fun parsePoints(points: ReadableArray?): ArrayList<Point> {
|
|
10
|
+
val result = ArrayList<Point>()
|
|
11
|
+
if (points == null) return result
|
|
12
|
+
for (i in 0 until points.size()) {
|
|
13
|
+
val map = points.getMap(i) ?: continue
|
|
14
|
+
if (!map.hasKey("lat") || !map.hasKey("lon")) continue
|
|
15
|
+
result.add(Point(map.getDouble("lat"), map.getDouble("lon")))
|
|
16
|
+
}
|
|
17
|
+
return result
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fun parseRings(rings: ReadableArray?): ArrayList<ArrayList<Point>> {
|
|
21
|
+
val result = ArrayList<ArrayList<Point>>()
|
|
22
|
+
if (rings == null) return result
|
|
23
|
+
for (i in 0 until rings.size()) {
|
|
24
|
+
result.add(parsePoints(rings.getArray(i)))
|
|
25
|
+
}
|
|
26
|
+
return result
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fun parseScreenPoints(points: ReadableArray?): ArrayList<ScreenPoint?> {
|
|
30
|
+
val result = ArrayList<ScreenPoint?>()
|
|
31
|
+
if (points == null) return result
|
|
32
|
+
for (i in 0 until points.size()) {
|
|
33
|
+
val map = points.getMap(i) ?: continue
|
|
34
|
+
if (!map.hasKey("x") || !map.hasKey("y")) continue
|
|
35
|
+
result.add(ScreenPoint(map.getDouble("x").toFloat(), map.getDouble("y").toFloat()))
|
|
36
|
+
}
|
|
37
|
+
return result
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
package com.yamaplite.utils
|
|
2
|
+
|
|
3
|
+
import com.yamaplite.utils.ImageCache
|
|
4
|
+
import com.yandex.runtime.image.ImageProvider
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import android.content.Context
|
|
7
|
+
import android.graphics.Bitmap
|
|
8
|
+
import android.graphics.BitmapFactory
|
|
9
|
+
import okhttp3.OkHttpClient
|
|
10
|
+
import okhttp3.Request
|
|
11
|
+
import okhttp3.Call
|
|
12
|
+
import okhttp3.Response
|
|
13
|
+
import java.io.IOException
|
|
14
|
+
import android.os.Handler
|
|
15
|
+
import android.os.Looper
|
|
16
|
+
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
17
|
+
import kotlinx.coroutines.Dispatchers
|
|
18
|
+
import kotlinx.coroutines.withContext
|
|
19
|
+
import kotlin.coroutines.resume
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ResolveImageHelper {
|
|
23
|
+
|
|
24
|
+
companion object {
|
|
25
|
+
private val httpClient: OkHttpClient by lazy {
|
|
26
|
+
OkHttpClient.Builder()
|
|
27
|
+
.retryOnConnectionFailure(true)
|
|
28
|
+
.build()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Volatile private var instance: ResolveImageHelper? = null
|
|
32
|
+
|
|
33
|
+
fun getInstance(): ResolveImageHelper =
|
|
34
|
+
instance ?: synchronized(this) {
|
|
35
|
+
instance ?: ResolveImageHelper().also { instance = it }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
suspend fun resolveImage(context: Context, url: String, iconSize: Int): ImageProvider? = withContext(Dispatchers.IO) {
|
|
40
|
+
// 1. Проверка кэша - всегда ресайзим изображение из кэша под нужный размер
|
|
41
|
+
Log.d("ImageLoader", "Checking cache for: $url")
|
|
42
|
+
ImageCache.get(url)?.let { cachedBitmap ->
|
|
43
|
+
Log.d("ImageLoader", "Loaded from cache: $url")
|
|
44
|
+
val resizedBitmap = resizeBitmap(context, cachedBitmap, iconSize) ?: cachedBitmap
|
|
45
|
+
return@withContext ImageProvider.fromBitmap(resizedBitmap)
|
|
46
|
+
}
|
|
47
|
+
Log.d("ImageLoader", "Cache miss, trying other sources for: $url")
|
|
48
|
+
|
|
49
|
+
// 2. Проверяем как ресурс Android (для React Native ассетов в res/drawable-*)
|
|
50
|
+
val resId = context.resources.getIdentifier(url, "drawable", context.packageName)
|
|
51
|
+
if (resId != 0) {
|
|
52
|
+
try {
|
|
53
|
+
val bmp = BitmapFactory.decodeResource(context.resources, resId)
|
|
54
|
+
val resized = resizeBitmap(context, bmp, iconSize)
|
|
55
|
+
ImageCache.put(url, resized ?: bmp)
|
|
56
|
+
Log.d("ImageLoader", "Loaded from resources: $url")
|
|
57
|
+
return@withContext ImageProvider.fromBitmap(resized ?: bmp)
|
|
58
|
+
} catch (e: Exception) {
|
|
59
|
+
Log.e("ImageLoader", "Error loading from resources: $url", e)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 3. HTTP/HTTPS → асинхронно, ждем завершения через suspendCancellableCoroutine
|
|
64
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
65
|
+
Log.d("ImageLoader", "Loading from network: $url")
|
|
66
|
+
|
|
67
|
+
return@withContext suspendCancellableCoroutine { continuation ->
|
|
68
|
+
val request = Request.Builder().url(url).build()
|
|
69
|
+
val call = httpClient.newCall(request)
|
|
70
|
+
continuation.invokeOnCancellation { call.cancel() }
|
|
71
|
+
call.enqueue(object : okhttp3.Callback {
|
|
72
|
+
override fun onFailure(call: Call, e: IOException) {
|
|
73
|
+
Log.e("ImageLoader", "Network load failed: $url", e)
|
|
74
|
+
continuation.resume(null)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
override fun onResponse(call: Call, response: Response) {
|
|
78
|
+
var bitmap: Bitmap? = null
|
|
79
|
+
try {
|
|
80
|
+
response.body?.byteStream()?.use { inputStream ->
|
|
81
|
+
try {
|
|
82
|
+
bitmap = BitmapFactory.decodeStream(inputStream)?.let { resizeBitmap(context, it, iconSize) }
|
|
83
|
+
bitmap?.let { ImageCache.put(url, it) }
|
|
84
|
+
} catch (e: Exception) {
|
|
85
|
+
Log.e("ImageLoader", "Error decoding image: $url", e)
|
|
86
|
+
} finally {
|
|
87
|
+
response.close()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} catch (e: Exception) {
|
|
91
|
+
Log.e("ImageLoader", "Error processing response: $url", e)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
val imageProvider = bitmap?.let { ImageProvider.fromBitmap(it) }
|
|
95
|
+
continuation.resume(imageProvider)
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return@withContext null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fun resizeBitmap(context: Context, bitmap: Bitmap?, targetSize: Int): Bitmap? {
|
|
105
|
+
if (bitmap == null || targetSize <= 0) return bitmap
|
|
106
|
+
|
|
107
|
+
// Convert dp to pixels based on screen density
|
|
108
|
+
val density = context.resources.displayMetrics.density
|
|
109
|
+
val targetSizePx = (targetSize * density).toInt()
|
|
110
|
+
|
|
111
|
+
val width = bitmap.width
|
|
112
|
+
val height = bitmap.height
|
|
113
|
+
|
|
114
|
+
if (width == targetSizePx && height == targetSizePx) return bitmap
|
|
115
|
+
|
|
116
|
+
val scale = targetSizePx.toFloat() / width.coerceAtLeast(height).toFloat()
|
|
117
|
+
val scaledWidth = (width * scale).toInt()
|
|
118
|
+
val scaledHeight = (height * scale).toInt()
|
|
119
|
+
|
|
120
|
+
return Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
package com.yamaplite.utils
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
8
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
9
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
10
|
+
import com.yamaplite.NativeYamapUtilsSpec
|
|
11
|
+
import com.yamaplite.components.YamapLiteView
|
|
12
|
+
import com.yandex.mapkit.MapKitFactory
|
|
13
|
+
import com.yandex.runtime.i18n.I18nManagerFactory
|
|
14
|
+
|
|
15
|
+
@ReactModule(name = NativeYamapUtilsSpec.NAME)
|
|
16
|
+
class YamapUtils(reactContext: ReactApplicationContext) : NativeYamapUtilsSpec(reactContext) {
|
|
17
|
+
|
|
18
|
+
private fun withView(viewId: Double, promise: Promise, action: (YamapLiteView) -> Unit) {
|
|
19
|
+
UiThreadUtil.runOnUiThread {
|
|
20
|
+
try {
|
|
21
|
+
val uiManager =
|
|
22
|
+
UIManagerHelper.getUIManager(getReactApplicationContext(), viewId.toInt())
|
|
23
|
+
val view = uiManager?.resolveView(viewId.toInt()) as? YamapLiteView
|
|
24
|
+
if (view != null) {
|
|
25
|
+
action(view)
|
|
26
|
+
} else {
|
|
27
|
+
promise.reject("YamapLite", "failed to get view")
|
|
28
|
+
}
|
|
29
|
+
} catch (e: Exception) {
|
|
30
|
+
promise.reject("YamapLite", "failed to resolve view", e)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override fun getCameraPosition(viewId: Double, promise: Promise) =
|
|
36
|
+
withView(viewId, promise) { view ->
|
|
37
|
+
val cameraPosition = view.getCameraPosition()
|
|
38
|
+
if (cameraPosition != null) {
|
|
39
|
+
promise.resolve(cameraPosition)
|
|
40
|
+
} else {
|
|
41
|
+
promise.reject("YamapLite", "failed to get camera position")
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override fun getMapObjectCount(viewId: Double, promise: Promise) =
|
|
46
|
+
withView(viewId, promise) { view ->
|
|
47
|
+
promise.resolve(view.getMapObjectCount().toDouble())
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override fun getScreenPoints(viewId: Double, points: ReadableArray, promise: Promise) =
|
|
51
|
+
withView(viewId, promise) { view ->
|
|
52
|
+
val screenPoints = view.getScreenPoints(PointParser.parsePoints(points))
|
|
53
|
+
promise.resolve(Arguments.createMap().apply { putArray("points", screenPoints) })
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
override fun getVisibleRegion(viewId: Double, promise: Promise) =
|
|
57
|
+
withView(viewId, promise) { view ->
|
|
58
|
+
val visibleRegion = view.getVisibleRegion()
|
|
59
|
+
if (visibleRegion != null) {
|
|
60
|
+
promise.resolve(visibleRegion)
|
|
61
|
+
} else {
|
|
62
|
+
promise.reject("YamapLite", "failed to get visible region")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override fun fitAllMarkers(viewId: Double, promise: Promise) =
|
|
67
|
+
withView(viewId, promise) { view ->
|
|
68
|
+
view.fitAllMarkers()
|
|
69
|
+
promise.resolve(null)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override fun setZoom(
|
|
73
|
+
viewId: Double,
|
|
74
|
+
zoom: Double,
|
|
75
|
+
duration: Double,
|
|
76
|
+
animation: String,
|
|
77
|
+
promise: Promise
|
|
78
|
+
) =
|
|
79
|
+
withView(viewId, promise) { view ->
|
|
80
|
+
view.setZoom(zoom.toFloat(), duration.toInt(), animation)
|
|
81
|
+
promise.resolve(null)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
override fun setCenter(
|
|
85
|
+
viewId: Double,
|
|
86
|
+
latitude: Double,
|
|
87
|
+
longitude: Double,
|
|
88
|
+
zoom: Double,
|
|
89
|
+
azimuth: Double,
|
|
90
|
+
tilt: Double,
|
|
91
|
+
duration: Double,
|
|
92
|
+
animation: String,
|
|
93
|
+
promise: Promise
|
|
94
|
+
) =
|
|
95
|
+
withView(viewId, promise) { view ->
|
|
96
|
+
view.setCenter(
|
|
97
|
+
latitude,
|
|
98
|
+
longitude,
|
|
99
|
+
zoom.toFloat(),
|
|
100
|
+
azimuth.toFloat(),
|
|
101
|
+
tilt.toFloat(),
|
|
102
|
+
duration.toInt(),
|
|
103
|
+
animation
|
|
104
|
+
)
|
|
105
|
+
promise.resolve(null)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override fun getWorldPoints(viewId: Double, points: ReadableArray, promise: Promise) =
|
|
109
|
+
withView(viewId, promise) { view ->
|
|
110
|
+
val worldPoints = view.getWorldPoints(PointParser.parseScreenPoints(points))
|
|
111
|
+
promise.resolve(Arguments.createMap().apply { putArray("points", worldPoints) })
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override fun init(apiKey: String, promise: Promise) {
|
|
115
|
+
UiThreadUtil.runOnUiThread {
|
|
116
|
+
try {
|
|
117
|
+
if (!isInitialized) {
|
|
118
|
+
MapKitFactory.setApiKey(apiKey)
|
|
119
|
+
MapKitFactory.initialize(getReactApplicationContext())
|
|
120
|
+
isInitialized = true
|
|
121
|
+
}
|
|
122
|
+
promise.resolve(null)
|
|
123
|
+
} catch (e: Exception) {
|
|
124
|
+
promise.reject("YamapLite", "failed to init MapKit", e)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
override fun getLocale(promise: Promise) {
|
|
130
|
+
UiThreadUtil.runOnUiThread {
|
|
131
|
+
try {
|
|
132
|
+
val locale = I18nManagerFactory.getLocale()
|
|
133
|
+
if (locale != null) {
|
|
134
|
+
promise.resolve(locale)
|
|
135
|
+
} else {
|
|
136
|
+
promise.reject("YamapLite", "failed to get locale")
|
|
137
|
+
}
|
|
138
|
+
} catch (e: Exception) {
|
|
139
|
+
promise.reject("YamapLite", "failed to get locale", e)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
override fun setLocale(locale: String, promise: Promise) {
|
|
145
|
+
UiThreadUtil.runOnUiThread {
|
|
146
|
+
try {
|
|
147
|
+
I18nManagerFactory.setLocale(locale)
|
|
148
|
+
promise.resolve(null)
|
|
149
|
+
} catch (e: Exception) {
|
|
150
|
+
promise.reject("YamapLite", "failed to set locale", e)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
override fun resetLocale(promise: Promise) {
|
|
156
|
+
UiThreadUtil.runOnUiThread {
|
|
157
|
+
try {
|
|
158
|
+
I18nManagerFactory.setLocale(null)
|
|
159
|
+
promise.resolve(null)
|
|
160
|
+
} catch (e: Exception) {
|
|
161
|
+
promise.reject("YamapLite", "failed to reset locale", e)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
companion object {
|
|
167
|
+
@Volatile private var isInitialized = false
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package com.yamaplite
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
9
|
+
import com.facebook.react.viewmanagers.YamapLiteCircleViewManagerInterface
|
|
10
|
+
import com.yamaplite.components.YamapCircle
|
|
11
|
+
import com.yandex.mapkit.geometry.Point
|
|
12
|
+
|
|
13
|
+
@ReactModule(name = YamapLiteCircleViewManager.NAME)
|
|
14
|
+
class YamapLiteCircleViewManager :
|
|
15
|
+
SimpleViewManager<YamapCircle>(), YamapLiteCircleViewManagerInterface<YamapCircle> {
|
|
16
|
+
|
|
17
|
+
override fun getName(): String {
|
|
18
|
+
return NAME
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override fun createViewInstance(context: ThemedReactContext): YamapCircle {
|
|
22
|
+
return YamapCircle(context)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@ReactProp(name = "fillColor")
|
|
26
|
+
override fun setFillColor(view: YamapCircle, color: Int?) {
|
|
27
|
+
view.setFillColor(color ?: Color.BLACK)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@ReactProp(name = "strokeColor")
|
|
31
|
+
override fun setStrokeColor(view: YamapCircle, color: Int?) {
|
|
32
|
+
view.setStrokeColor(color ?: Color.BLACK)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@ReactProp(name = "strokeWidth", defaultFloat = 1f)
|
|
36
|
+
override fun setStrokeWidth(view: YamapCircle, width: Float) {
|
|
37
|
+
view.setStrokeWidth(width)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ReactProp(name = "zInd", defaultInt = 0)
|
|
41
|
+
override fun setZInd(view: YamapCircle, zInd: Int) {
|
|
42
|
+
view.setZInd(zInd)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@ReactProp(name = "center")
|
|
46
|
+
override fun setCenter(view: YamapCircle, center: ReadableMap?) {
|
|
47
|
+
if (center != null) {
|
|
48
|
+
val lat = if (center.hasKey("lat")) center.getDouble("lat") else 0.0
|
|
49
|
+
val lon = if (center.hasKey("lon")) center.getDouble("lon") else 0.0
|
|
50
|
+
view.setCenter(Point(lat, lon))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@ReactProp(name = "radius", defaultFloat = 0f)
|
|
55
|
+
override fun setRadius(view: YamapCircle, radius: Float) {
|
|
56
|
+
view.setRadius(radius)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@ReactProp(name = "handled", defaultBoolean = false)
|
|
60
|
+
override fun setHandled(view: YamapCircle, handled: Boolean) {
|
|
61
|
+
view.setHandled(handled)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
companion object {
|
|
65
|
+
const val NAME = "YamapLiteCircleView"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package com.yamaplite
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
5
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
7
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
8
|
+
import com.facebook.react.viewmanagers.YamapLiteMarkerViewManagerInterface
|
|
9
|
+
import com.facebook.react.viewmanagers.YamapLiteMarkerViewManagerDelegate
|
|
10
|
+
import com.yamaplite.components.YamapLiteMarkerView
|
|
11
|
+
|
|
12
|
+
class YamapLiteMarkerViewManager : SimpleViewManager<YamapLiteMarkerView>(), YamapLiteMarkerViewManagerInterface<YamapLiteMarkerView> {
|
|
13
|
+
private val mDelegate: ViewManagerDelegate<YamapLiteMarkerView>
|
|
14
|
+
|
|
15
|
+
init {
|
|
16
|
+
mDelegate = YamapLiteMarkerViewManagerDelegate(this)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getDelegate(): ViewManagerDelegate<YamapLiteMarkerView> = mDelegate
|
|
20
|
+
|
|
21
|
+
override fun getName(): String = "YamapLiteMarkerView"
|
|
22
|
+
|
|
23
|
+
override fun createViewInstance(context: ThemedReactContext): YamapLiteMarkerView {
|
|
24
|
+
return YamapLiteMarkerView(context)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
override fun onDropViewInstance(view: YamapLiteMarkerView) {
|
|
28
|
+
view.onDrop()
|
|
29
|
+
super.onDropViewInstance(view)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@ReactProp(name = "point")
|
|
33
|
+
override fun setPoint(view: YamapLiteMarkerView, value: ReadableMap?) {
|
|
34
|
+
if (value == null) return
|
|
35
|
+
val lat = if (value.hasKey("lat")) value.getDouble("lat") else 0.0
|
|
36
|
+
val lon = if (value.hasKey("lon")) value.getDouble("lon") else 0.0
|
|
37
|
+
view.setPoint(lat, lon)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ReactProp(name = "source")
|
|
41
|
+
override fun setSource(view: YamapLiteMarkerView, value: String?) {
|
|
42
|
+
view.setIconSource(value)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@ReactProp(name = "scale")
|
|
46
|
+
override fun setScale(view: YamapLiteMarkerView, value: Double) {
|
|
47
|
+
view.setScale(value)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ReactProp(name = "zInd")
|
|
51
|
+
override fun setZInd(view: YamapLiteMarkerView, value: Int) {
|
|
52
|
+
view.setZInd(value)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@ReactProp(name = "visible")
|
|
56
|
+
override fun setVisible(view: YamapLiteMarkerView, value: Boolean) {
|
|
57
|
+
view.setVisible(value)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@ReactProp(name = "anchor")
|
|
61
|
+
override fun setAnchor(view: YamapLiteMarkerView, value: ReadableMap?) {
|
|
62
|
+
if (value == null) return
|
|
63
|
+
val x = if (value.hasKey("x")) value.getDouble("x") else 0.5
|
|
64
|
+
val y = if (value.hasKey("y")) value.getDouble("y") else 0.5
|
|
65
|
+
view.setAnchor(x, y)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@ReactProp(name = "rotated")
|
|
69
|
+
override fun setRotated(view: YamapLiteMarkerView, value: Boolean) {
|
|
70
|
+
view.setRotated(value)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@ReactProp(name = "handled")
|
|
74
|
+
override fun setHandled(view: YamapLiteMarkerView, value: Boolean) {
|
|
75
|
+
view.setHandled(value)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@ReactProp(name = "size")
|
|
79
|
+
override fun setSize(view: YamapLiteMarkerView, size: Int) {
|
|
80
|
+
view.setSize(size)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package com.yamaplite
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager
|
|
9
|
+
import com.yamaplite.utils.YamapUtils
|
|
10
|
+
|
|
11
|
+
class YamapLiteViewPackage : BaseReactPackage() {
|
|
12
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
|
|
13
|
+
when (name) {
|
|
14
|
+
NativeYamapUtilsSpec.NAME -> YamapUtils(reactContext)
|
|
15
|
+
else -> null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
|
|
19
|
+
mapOf(
|
|
20
|
+
NativeYamapUtilsSpec.NAME to
|
|
21
|
+
ReactModuleInfo(
|
|
22
|
+
NativeYamapUtilsSpec.NAME,
|
|
23
|
+
NativeYamapUtilsSpec.NAME,
|
|
24
|
+
false,
|
|
25
|
+
false,
|
|
26
|
+
false,
|
|
27
|
+
true
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
|
|
33
|
+
listOf<ViewManager<*, *>>(
|
|
34
|
+
YamapLiteViewManager(),
|
|
35
|
+
YamapLiteMarkerViewManager(),
|
|
36
|
+
YamapLiteCircleViewManager(),
|
|
37
|
+
YamapLitePolylineViewManager(),
|
|
38
|
+
YamapLitePolygonViewManager(),
|
|
39
|
+
ClusteredYamapLiteViewManager()
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
package com.yamaplite
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import com.facebook.react.bridge.ReadableArray
|
|
5
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
6
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
8
|
+
import com.facebook.react.viewmanagers.YamapLitePolygonViewManagerInterface
|
|
9
|
+
import com.yamaplite.components.YamapPolygon
|
|
10
|
+
import com.yamaplite.utils.PointParser
|
|
11
|
+
|
|
12
|
+
class YamapLitePolygonViewManager :
|
|
13
|
+
SimpleViewManager<YamapPolygon>(), YamapLitePolygonViewManagerInterface<YamapPolygon> {
|
|
14
|
+
|
|
15
|
+
override fun getName(): String {
|
|
16
|
+
return NAME
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun createViewInstance(context: ThemedReactContext): YamapPolygon {
|
|
20
|
+
return YamapPolygon(context)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@ReactProp(name = "fillColor")
|
|
24
|
+
override fun setFillColor(view: YamapPolygon, color: Int?) {
|
|
25
|
+
view.setFillColor(color ?: Color.BLACK)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@ReactProp(name = "strokeColor")
|
|
29
|
+
override fun setStrokeColor(view: YamapPolygon, color: Int?) {
|
|
30
|
+
view.setStrokeColor(color ?: Color.BLACK)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@ReactProp(name = "strokeWidth")
|
|
34
|
+
override fun setStrokeWidth(view: YamapPolygon, width: Float) {
|
|
35
|
+
view.setStrokeWidth(width)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@ReactProp(name = "zInd")
|
|
39
|
+
override fun setZInd(view: YamapPolygon, zIndex: Int) {
|
|
40
|
+
view.setZIndex(zIndex.toFloat())
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@ReactProp(name = "points")
|
|
44
|
+
override fun setPoints(view: YamapPolygon, points: ReadableArray?) {
|
|
45
|
+
view.setPoints(PointParser.parsePoints(points))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "innerRings")
|
|
49
|
+
override fun setInnerRings(view: YamapPolygon, innerRings: ReadableArray?) {
|
|
50
|
+
view.setInnerRings(PointParser.parseRings(innerRings))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@ReactProp(name = "handled")
|
|
54
|
+
override fun setHandled(view: YamapPolygon, handled: Boolean) {
|
|
55
|
+
view.setHandled(handled)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
companion object {
|
|
59
|
+
const val NAME = "YamapLitePolygonView"
|
|
60
|
+
}
|
|
61
|
+
}
|