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
21 changes: 21 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.Circle
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.IndoorBuilding
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.MapColorScheme
Expand All @@ -30,6 +31,8 @@ import com.google.android.gms.maps.model.TileOverlayOptions
import com.google.maps.android.data.kml.KmlLayer
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.nio.charset.StandardCharsets

Expand All @@ -48,6 +51,7 @@ class GoogleMapsViewImpl(
GoogleMap.OnPolygonClickListener,
GoogleMap.OnCircleClickListener,
GoogleMap.OnMarkerDragListener,
GoogleMap.OnIndoorStateChangeListener,
LifecycleEventListener {
private var initialized = false
private var mapReady = false
Expand Down Expand Up @@ -490,6 +494,8 @@ class GoogleMapsViewImpl(
var onMarkerDragStart: ((String?, RNLatLng) -> Unit)? = null
var onMarkerDrag: ((String?, RNLatLng) -> Unit)? = null
var onMarkerDragEnd: ((String?, RNLatLng) -> Unit)? = null
var onIndoorBuildingFocused: ((RNIndoorBuilding) -> Unit)? = null
var onIndoorLevelActivated: ((RNIndoorLevel) -> Unit)? = null
var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChange: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChangeComplete: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
Expand Down Expand Up @@ -1003,6 +1009,21 @@ class GoogleMapsViewImpl(
RNLatLng(marker.position.latitude, marker.position.longitude),
)
}

override fun onIndoorBuildingFocused() {
val building = googleMap?.focusedBuilding ?: return
onIndoorBuildingFocused?.invoke(building.toRNIndoorBuilding())
}

override fun onIndoorLevelActivated(indoorBuilding: IndoorBuilding) {
val activeLevel = indoorBuilding.levels.getOrNull(indoorBuilding.activeLevelIndex) ?: return
onIndoorLevelActivated?.invoke(
activeLevel.toRNIndoorLevel(
indoorBuilding.activeLevelIndex,
true,
),
)
}
}

private inline fun onUi(crossinline block: () -> Unit) {
Expand Down
10 changes: 10 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,16 @@ class RNGoogleMapsPlusView(
view.onMarkerDragEnd = cb
}

override var onIndoorBuildingFocused: ((RNIndoorBuilding) -> Unit)? = null
set(cb) {
view.onIndoorBuildingFocused = cb
}

override var onIndoorLevelActivated: ((RNIndoorLevel) -> Unit)? = null
set(cb) {
view.onIndoorLevelActivated = cb
}

override var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
set(cb) {
view.onCameraChangeStart = cb
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.rngooglemapsplus.extensions

import com.google.android.gms.maps.model.IndoorBuilding
import com.google.android.gms.maps.model.IndoorLevel
import com.rngooglemapsplus.RNIndoorBuilding
import com.rngooglemapsplus.RNIndoorLevel

fun IndoorBuilding.toRNIndoorBuilding(): RNIndoorBuilding {
val mappedLevels =
levels
.mapIndexed { index, level ->
val active = index == activeLevelIndex
level.toRNIndoorLevel(index, active)
}.toTypedArray()

return RNIndoorBuilding(
activeLevelIndex = activeLevelIndex.toDouble(),
defaultLevelIndex = defaultLevelIndex.toDouble(),
levels = mappedLevels,
underground = isUnderground,
)
}

fun IndoorLevel.toRNIndoorLevel(
index: Int,
active: Boolean,
): RNIndoorLevel =
RNIndoorLevel(
index = index.toDouble(),
name = name,
shortName = shortName,
active = active,
)
6 changes: 6 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import StressTestScreen from './screens/StressTestScreen';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { useColorScheme } from 'react-native';
import BlankScreen from './screens/BlankScreen';
import IndoorLevelMapScreen from './screens/IndoorLevelMapScreen';
import type { RootStackParamList } from './types/navigation';

const Stack = createStackNavigator<RootStackParamList>();
Expand Down Expand Up @@ -94,6 +95,11 @@ export default function App() {
component={CustomStyleScreen}
options={{ title: 'Custom Map Style' }}
/>
<Stack.Screen
name="IndoorLevelMap"
component={IndoorLevelMapScreen}
options={{ title: 'Indoor level map' }}
/>
<Stack.Screen
name="StressTest"
component={StressTestScreen}
Expand Down
18 changes: 17 additions & 1 deletion example/src/components/MapWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React, { useMemo } from 'react';
import { StyleSheet, useColorScheme, View } from 'react-native';
import { GoogleMapsView } from 'react-native-google-maps-plus';
import {
GoogleMapsView,
type RNIndoorBuilding,
type RNIndoorLevel,
} from 'react-native-google-maps-plus';
import type {
GoogleMapsViewRef,
RNGoogleMapsPlusViewProps,
Expand Down Expand Up @@ -143,6 +147,18 @@ export default function MapWrapper(props: Props) {
console.log('Marker drag end', id, latLng),
}
)}
onIndoorBuildingFocused={callback(
props.onIndoorBuildingFocused ?? {
f: (building: RNIndoorBuilding) =>
console.log('Indoor building focused', building),
}
)}
onIndoorLevelActivated={callback(
props.onIndoorLevelActivated ?? {
f: (level: RNIndoorLevel) =>
console.log('Indoor level activated', level),
}
)}
onCameraChangeStart={callback(
props.onCameraChangeStart ?? {
f: (r: RNRegion, cam: RNCamera, g: boolean) =>
Expand Down
1 change: 1 addition & 0 deletions example/src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const screens = [
{ name: 'KmlLayer', title: 'KML Layer' },
{ name: 'Location', title: 'Location & Permissions' },
{ name: 'CustomStyle', title: 'Custom Map Style' },
{ name: 'IndoorLevelMap', title: 'Indoor level map' },
{ name: 'StressTest', title: 'Stress Test' },
];

Expand Down
26 changes: 26 additions & 0 deletions example/src/screens/IndoorLevelMapScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { useRef } from 'react';
import MapWrapper from '../components/MapWrapper';
import type { GoogleMapsViewRef } from 'react-native-google-maps-plus';
import ControlPanel from '../components/ControlPanel';

export default function IndoorLevelMapScreen() {
const mapRef = useRef<GoogleMapsViewRef | null>(null);
return (
<MapWrapper
mapRef={mapRef}
initialProps={{
camera: {
center: {
latitude: 37.617596832174385,
longitude: -122.38253440707922,
},
zoom: 18,
},
}}
indoorEnabled={true}
buildingEnabled={true}
>
<ControlPanel mapRef={mapRef} buttons={[]} />
</MapWrapper>
);
}
1 change: 1 addition & 0 deletions example/src/types/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type RootStackParamList = {
KmlLayer: undefined;
Location: undefined;
CustomStyle: undefined;
IndoorLevelMap: undefined;
StressTest: undefined;
};

Expand Down
30 changes: 28 additions & 2 deletions ios/GoogleMapViewImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import GoogleMaps
import GoogleMapsUtils
import UIKit

final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate {
final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate,
GMSIndoorDisplayDelegate {

private let locationHandler: LocationHandler
private let markerBuilder: MapMarkerBuilder
Expand Down Expand Up @@ -136,7 +137,10 @@ final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate {
myLocationEnabled.map { mapView?.isMyLocationEnabled = $0 }
buildingEnabled.map { mapView?.isBuildingsEnabled = $0 }
trafficEnabled.map { mapView?.isTrafficEnabled = $0 }
indoorEnabled.map { mapView?.isIndoorEnabled = $0 }
indoorEnabled.map {
mapView?.isIndoorEnabled = $0
mapView?.indoorDisplay.delegate = $0 == true ? self : nil
}
customMapStyle.map { mapView?.mapStyle = $0 }
mapType.map { mapView?.mapType = $0 }
userInterfaceStyle.map { mapView?.overrideUserInterfaceStyle = $0 }
Expand Down Expand Up @@ -236,6 +240,7 @@ final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate {
var indoorEnabled: Bool? {
didSet {
mapView?.isIndoorEnabled = indoorEnabled ?? false
mapView?.indoorDisplay.delegate = indoorEnabled == true ? self : nil
}
}

Expand Down Expand Up @@ -304,6 +309,8 @@ final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate {
var onMarkerDragStart: ((String?, RNLatLng) -> Void)?
var onMarkerDrag: ((String?, RNLatLng) -> Void)?
var onMarkerDragEnd: ((String?, RNLatLng) -> Void)?
var onIndoorBuildingFocused: ((RNIndoorBuilding) -> Void)?
var onIndoorLevelActivated: ((RNIndoorLevel) -> Void)?
var onCameraChangeStart: ((RNRegion, RNCamera, Bool) -> Void)?
var onCameraChange: ((RNRegion, RNCamera, Bool) -> Void)?
var onCameraChangeComplete: ((RNRegion, RNCamera, Bool) -> Void)?
Expand Down Expand Up @@ -766,4 +773,23 @@ final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate {
RNLatLng(marker.position.latitude, marker.position.longitude)
)
}

func didChangeActiveBuilding(_ building: GMSIndoorBuilding?) {
guard let display = mapView?.indoorDisplay, let building else { return }
onIndoorBuildingFocused?(building.toRNIndoorBuilding(from: display))
}

func didChangeActiveLevel(_ level: GMSIndoorLevel?) {
guard
let display = mapView?.indoorDisplay,
let building = display.activeBuilding,
let level,
let index = building.levels.firstIndex(where: {
$0.name == level.name && $0.shortName == level.shortName
})
else { return }

onIndoorLevelActivated?(level.toRNIndoorLevel(index: index, active: true))
}

}
6 changes: 6 additions & 0 deletions ios/RNGoogleMapsPlusView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,12 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
var onMarkerDragEnd: ((String?, RNLatLng) -> Void)? {
didSet { impl.onMarkerDragEnd = onMarkerDragEnd }
}
var onIndoorBuildingFocused: ((RNIndoorBuilding) -> Void)? {
didSet { impl.onIndoorBuildingFocused = onIndoorBuildingFocused }
}
var onIndoorLevelActivated: ((RNIndoorLevel) -> Void)? {
didSet { impl.onIndoorLevelActivated = onIndoorLevelActivated }
}
var onCameraChangeStart: ((RNRegion, RNCamera, Bool) -> Void)? {
didSet { impl.onCameraChangeStart = onCameraChangeStart }
}
Expand Down
33 changes: 33 additions & 0 deletions ios/extensions/IndoorBuilding+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import GoogleMaps
import NitroModules

extension GMSIndoorLevel {
func toRNIndoorLevel(index: Int, active: Bool) -> RNIndoorLevel {
RNIndoorLevel(
index: Double(index),
name: self.name,
shortName: self.shortName,
active: active
)
}
}

extension GMSIndoorBuilding {
func toRNIndoorBuilding(from indoorDisplay: GMSIndoorDisplay)
-> RNIndoorBuilding {
let activeLevel = indoorDisplay.activeLevel
let levels = self.levels.enumerated().map {
(index, level) -> RNIndoorLevel in
let isActive = (level == activeLevel)
return level.toRNIndoorLevel(index: index, active: isActive)
}
let activeIndex = self.levels.firstIndex(where: { $0 == activeLevel })

return RNIndoorBuilding(
activeLevelIndex: activeIndex.map { Double($0) } ?? nil,
defaultLevelIndex: nil,
levels: levels,
underground: self.isUnderground
)
}
}
4 changes: 4 additions & 0 deletions src/RNGoogleMapsPlusView.nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import type {
RNMapZoomConfig,
RNHeatmap,
RNKMLayer,
RNIndoorBuilding,
RNIndoorLevel,
} from './types';

export interface RNGoogleMapsPlusViewProps extends HybridViewProps {
Expand Down Expand Up @@ -57,6 +59,8 @@ export interface RNGoogleMapsPlusViewProps extends HybridViewProps {
onMarkerDragStart?: (id: string | undefined, location: RNLatLng) => void;
onMarkerDrag?: (id: string | undefined, location: RNLatLng) => void;
onMarkerDragEnd?: (id: string | undefined, location: RNLatLng) => void;
onIndoorBuildingFocused?: (indoorBuilding: RNIndoorBuilding) => void;
onIndoorLevelActivated?: (indoorLevel: RNIndoorLevel) => void;
onCameraChangeStart?: (
region: RNRegion,
camera: RNCamera,
Expand Down
14 changes: 14 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,20 @@ export type RNKMLayer = {
kmlString: string;
};

export type RNIndoorBuilding = {
activeLevelIndex?: number;
defaultLevelIndex?: number;
levels: RNIndoorLevel[];
underground?: boolean;
};

export type RNIndoorLevel = {
index: number;
name?: string;
shortName?: string;
active?: boolean;
};

export type RNLocationConfig = {
android?: RNAndroidLocationConfig;
ios?: RNIOSLocationConfig;
Expand Down
Loading