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
10 changes: 0 additions & 10 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,7 @@ jobs:
with:
xcode-version: ${{ env.XCODE_VERSION }}

- name: Cache Pods
id: pods-cache
uses: actions/cache@v4.2.4
with:
path: example/ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('example/ios/Podfile', 'example/ios/Podfile.lock', 'example/package.json') }}
restore-keys: |
${{ runner.os }}-pods-

- name: Install cocoapods
if: steps.pods-cache.outputs.cache-hit != 'true'
working-directory: example
run: yarn ios:pods

Expand Down
91 changes: 86 additions & 5 deletions android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.rngooglemapsplus

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.location.Location
import android.util.Base64
import android.util.Size
import android.widget.FrameLayout
import androidx.core.graphics.scale
import com.facebook.react.bridge.LifecycleEventListener
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.uimanager.PixelUtil.dpToPx
Expand All @@ -29,11 +33,15 @@ import com.google.android.gms.maps.model.PolylineOptions
import com.google.android.gms.maps.model.TileOverlay
import com.google.android.gms.maps.model.TileOverlayOptions
import com.google.maps.android.data.kml.KmlLayer
import com.margelo.nitro.core.Promise
import com.rngooglemapsplus.extensions.toGooglePriority
import com.rngooglemapsplus.extensions.toLocationErrorCode
import com.rngooglemapsplus.extensions.toRNIndoorBuilding
import com.rngooglemapsplus.extensions.toRNIndoorLevel
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.nio.charset.StandardCharsets

class GoogleMapsViewImpl(
Expand Down Expand Up @@ -188,6 +196,8 @@ class GoogleMapsViewImpl(
if (cameraPosition == lastSubmittedCameraPosition) {
return
}
lastSubmittedCameraPosition = cameraPosition

val isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason

val latDelta = bounds.northeast.latitude - bounds.southwest.latitude
Expand All @@ -207,7 +217,6 @@ class GoogleMapsViewImpl(
),
isGesture,
)
lastSubmittedCameraPosition = cameraPosition
}

override fun onCameraIdle() {
Expand Down Expand Up @@ -503,7 +512,7 @@ class GoogleMapsViewImpl(
fun setCamera(
cameraPosition: CameraPosition,
animated: Boolean,
durationMS: Int,
durationMs: Int,
) {
onUi {
val current = googleMap?.cameraPosition
Expand All @@ -514,7 +523,7 @@ class GoogleMapsViewImpl(
val update = CameraUpdateFactory.newCameraPosition(cameraPosition)

if (animated) {
googleMap?.animateCamera(update, durationMS, null)
googleMap?.animateCamera(update, durationMs, null)
} else {
googleMap?.moveCamera(update)
}
Expand All @@ -525,7 +534,7 @@ class GoogleMapsViewImpl(
coordinates: Array<RNLatLng>,
padding: RNMapPadding,
animated: Boolean,
durationMS: Int,
durationMs: Int,
) {
if (coordinates.isEmpty()) {
return
Expand Down Expand Up @@ -583,13 +592,85 @@ class GoogleMapsViewImpl(
0,
)
if (animated) {
googleMap?.animateCamera(update, durationMS, null)
googleMap?.animateCamera(update, durationMs, null)
} else {
googleMap?.moveCamera(update)
}
}
}

fun setCameraBounds(bounds: LatLngBounds?) {
onUi {
googleMap?.setLatLngBoundsForCameraTarget(bounds)
}
}

fun animateToBounds(
bounds: LatLngBounds,
padding: Int,
durationMs: Int,
lockBounds: Boolean,
) {
onUi {
if (lockBounds) {
googleMap?.setLatLngBoundsForCameraTarget(bounds)
}
val update =
CameraUpdateFactory.newLatLngBounds(
bounds,
padding,
)
googleMap?.animateCamera(update, durationMs, null)
}
}

fun snapshot(
size: Size?,
format: String,
compressFormat: Bitmap.CompressFormat,
quality: Double,
resultIsFile: Boolean,
): Promise<String?> {
val promise = Promise<String?>()
onUi {
googleMap?.snapshot { bitmap ->
try {
if (bitmap == null) {
promise.resolve(null)
return@snapshot
}

val scaledBitmap =
size?.let {
bitmap.scale(it.width, it.height)
} ?: bitmap

val output = ByteArrayOutputStream()
scaledBitmap.compress(compressFormat, (quality * 100).toInt().coerceIn(0, 100), output)
val bytes = output.toByteArray()

if (resultIsFile) {
val file = File(context.cacheDir, "map_snapshot_${System.currentTimeMillis()}.$format")
FileOutputStream(file).use { it.write(bytes) }
promise.resolve(file.absolutePath)
} else {
val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP)
promise.resolve("data:image/$format;base64,$base64")
}

if (scaledBitmap != bitmap) {
scaledBitmap.recycle()
}
bitmap.recycle()
} catch (e: Exception) {
promise.resolve(null)
}
}
}

return promise
}

fun addMarker(
id: String,
opts: MarkerOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ class LocationHandler(

private fun restartLocationUpdates() {
stop()
// 4) Google Play Services checken – früh zurückmelden
val playServicesStatus =
GoogleApiAvailability
.getInstance()
Expand Down
42 changes: 38 additions & 4 deletions android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import com.facebook.react.uimanager.ThemedReactContext
import com.google.android.gms.maps.model.MapStyleOptions
import com.margelo.nitro.core.Promise
import com.rngooglemapsplus.extensions.circleEquals
import com.rngooglemapsplus.extensions.isFileResult
import com.rngooglemapsplus.extensions.markerEquals
import com.rngooglemapsplus.extensions.polygonEquals
import com.rngooglemapsplus.extensions.polylineEquals
import com.rngooglemapsplus.extensions.toCameraPosition
import com.rngooglemapsplus.extensions.toCompressFormat
import com.rngooglemapsplus.extensions.toFileExtension
import com.rngooglemapsplus.extensions.toLatLngBounds
import com.rngooglemapsplus.extensions.toMapColorScheme
import com.rngooglemapsplus.extensions.toSize

@DoNotStrip
class RNGoogleMapsPlusView(
Expand Down Expand Up @@ -343,25 +348,54 @@ class RNGoogleMapsPlusView(
override fun setCamera(
camera: RNCamera,
animated: Boolean?,
durationMS: Double?,
durationMs: Double?,
) {
view.setCamera(camera.toCameraPosition(), animated == true, durationMS?.toInt() ?: 3000)
view.setCamera(camera.toCameraPosition(), animated == true, durationMs?.toInt() ?: 3000)
}

override fun setCameraToCoordinates(
coordinates: Array<RNLatLng>,
padding: RNMapPadding?,
animated: Boolean?,
durationMS: Double?,
durationMs: Double?,
) {
view.setCameraToCoordinates(
coordinates,
padding = padding ?: RNMapPadding(0.0, 0.0, 0.0, 0.0),
animated == true,
durationMS?.toInt() ?: 3000,
durationMs?.toInt() ?: 3000,
)
}

override fun setCameraBounds(bounds: RNLatLngBounds?) {
view.setCameraBounds(
bounds?.toLatLngBounds(),
)
}

override fun animateToBounds(
bounds: RNLatLngBounds,
padding: Double?,
durationMs: Double?,
lockBounds: Boolean?,
) {
view.animateToBounds(
bounds.toLatLngBounds(),
padding = padding?.toInt() ?: 0,
durationMs?.toInt() ?: 3000,
lockBounds = false,
)
}

override fun snapshot(options: RNSnapshotOptions): Promise<String?> =
view.snapshot(
size = options.size.toSize(),
format = options.format.toFileExtension(),
compressFormat = options.format.toCompressFormat(),
quality = options.quality,
resultIsFile = options.resultType.isFileResult(),
)

override fun showLocationDialog() {
locationHandler.showLocationDialog()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.rngooglemapsplus.extensions

import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.rngooglemapsplus.RNLatLngBounds

fun RNLatLngBounds.toLatLngBounds(): LatLngBounds =
LatLngBounds(
LatLng(
southWest.latitude,
southWest.longitude,
),
LatLng(
northEast.latitude,
northEast.longitude,
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.rngooglemapsplus.extensions

import android.util.Size
import com.facebook.react.uimanager.PixelUtil.dpToPx
import com.rngooglemapsplus.RNSize

fun RNSize?.toSize(): Size? = this?.let { Size(width.dpToPx().toInt(), height.dpToPx().toInt()) }
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.rngooglemapsplus.extensions

import android.graphics.Bitmap
import com.rngooglemapsplus.RNSnapshotFormat

fun RNSnapshotFormat?.toCompressFormat(): Bitmap.CompressFormat =
when (this) {
RNSnapshotFormat.JPG, RNSnapshotFormat.JPEG -> Bitmap.CompressFormat.JPEG
RNSnapshotFormat.PNG, null -> Bitmap.CompressFormat.PNG
}

fun RNSnapshotFormat?.toFileExtension(): String =
when (this) {
RNSnapshotFormat.JPG, RNSnapshotFormat.JPEG -> "jpg"
RNSnapshotFormat.PNG, null -> "png"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.rngooglemapsplus.extensions

import com.rngooglemapsplus.RNSnapshotResultType

fun RNSnapshotResultType?.isFileResult(): Boolean =
when (this) {
RNSnapshotResultType.FILE -> true
RNSnapshotResultType.BASE64, null -> false
}
3 changes: 3 additions & 0 deletions example/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { AppRegistry } from 'react-native';
import App from './src/App';
import { name as appName } from './app.json';
import { LogBox } from 'react-native';

LogBox.ignoreLogs(['InteractionManager has been deprecated']);

AppRegistry.registerComponent(appName, () => App);
14 changes: 13 additions & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { useColorScheme } from 'react-native';
import BlankScreen from './screens/BlankScreen';
import IndoorLevelMapScreen from './screens/IndoorLevelMapScreen';
import CameraTestScreen from './screens/CameraTestScreen';
import type { RootStackParamList } from './types/navigation';
import SnapshotTestScreen from './screens/SnaptshotTestScreen';

const Stack = createStackNavigator<RootStackParamList>();

Expand Down Expand Up @@ -100,10 +102,20 @@ export default function App() {
component={IndoorLevelMapScreen}
options={{ title: 'Indoor level map' }}
/>
<Stack.Screen
name="Camera"
component={CameraTestScreen}
options={{ title: 'Camera test' }}
/>
<Stack.Screen
name="Snapshot"
component={SnapshotTestScreen}
options={{ title: 'Snapshot test' }}
/>
<Stack.Screen
name="StressTest"
component={StressTestScreen}
options={{ title: 'Stress Test' }}
options={{ title: 'Stress test' }}
/>
</Stack.Navigator>
</NavigationContainer>
Expand Down
Loading
Loading