Skip to content

Commit 76d4289

Browse files
authored
chore: merge dev into main
2 parents 27a5cd2 + 995b851 commit 76d4289

File tree

18 files changed

+300
-223
lines changed

18 files changed

+300
-223
lines changed

README.md

Lines changed: 107 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
# react-native-google-maps-plus
22

33
[![npm version](https://img.shields.io/npm/v/react-native-google-maps-plus.svg?logo=npm&color=cb0000)](https://www.npmjs.com/package/react-native-google-maps-plus)
4-
[![Dev Release](https://img.shields.io/npm/v/react-native-google-maps-plus/dev.svg?label=dev%20release&color=orange&logo=githubactions)](https://www.npmjs.com/package/react-native-google-maps-plus)
5-
[![Release](https://github.com/pinpong/react-native-google-maps-plus/actions/workflows/release.yml/badge.svg)](https://github.com/pinpong/react-native-google-maps-plus/actions/workflows/release.yml)
6-
[![Issues](https://img.shields.io/github/issues/pinpong/react-native-google-maps-plus?logo=github)](https://github.com/pinpong/react-native-google-maps-plus/issues)
7-
[![License](https://img.shields.io/github/license/pinpong/react-native-google-maps-plus?logo=open-source-initiative&logoColor=green)](./LICENSE)
8-
[![Code Style: Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?logo=prettier&logoColor=white)](https://prettier.io/)
9-
[![TypeScript](https://img.shields.io/badge/%3C/%3E-TypeScript-blue.svg?logo=typescript)](https://www.typescriptlang.org/)
10-
[![Lint](https://img.shields.io/badge/lint-eslint-green.svg?logo=eslint&logoColor=white)](https://eslint.org/)
11-
[![React Native](https://img.shields.io/badge/react--native-%3E%3D0.81.0-61dafb.svg?logo=react)](https://reactnative.dev/)
12-
[![Platform: Android](https://img.shields.io/badge/platform-android-green.svg?logo=android&logoColor=white)](https://developer.android.com/)
13-
[![Platform: iOS](https://img.shields.io/badge/platform-iOS-lightgrey.svg?logo=apple&logoColor=black)](https://developer.apple.com/ios/)
4+
[![Dev Release](https://img.shields.io/npm/v/react-native-google-maps-plus/dev.svg?label=dev%20release&color=orange)](https://www.npmjs.com/package/react-native-google-maps-plus)
5+
[![Build](https://github.com/pinpong/react-native-google-maps-plus/actions/workflows/release.yml/badge.svg)](https://github.com/pinpong/react-native-google-maps-plus/actions/workflows/release.yml)
6+
![React Native](https://img.shields.io/badge/react--native-%3E%3D0.81.0-61dafb.svg?logo=react)
7+
![Platform: Android](https://img.shields.io/badge/android-supported-brightgreen.svg?logo=android&logoColor=white)
8+
![Platform: iOS](https://img.shields.io/badge/ios-supported-lightgrey.svg?logo=apple&logoColor=black)
149

1510
React Native wrapper for Android & iOS Google Maps SDK.
1611

@@ -22,6 +17,58 @@ React Native wrapper for Android & iOS Google Maps SDK.
2217
yarn add react-native-google-maps-plus react-native-nitro-modules
2318
```
2419

20+
**iOS**
21+
22+
Add this to your Podfile only for bare React Native apps.
23+
(Not required for Expo, handled by the config plugin.)
24+
25+
```ruby
26+
post_install do |installer|
27+
react_native_post_install(
28+
installer,
29+
config[:reactNativePath],
30+
:mac_catalyst_enabled => false,
31+
)
32+
# Force iOS 16+ to avoid deployment target warnings
33+
installer.pods_project.targets.each do |target|
34+
target.build_configurations.each do |config|
35+
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
36+
end
37+
end
38+
39+
# --- SVGKit Patch ---
40+
require 'fileutils'
41+
svgkit_path = File.join(installer.sandbox.pod_dir('SVGKit'), 'Source')
42+
43+
# node fix
44+
Dir.glob(File.join(svgkit_path, '**', '*.{h,m}')).each do |file|
45+
FileUtils.chmod("u+w", file)
46+
text = File.read(file)
47+
new_contents = text.gsub('#import "Node.h"', '#import "SVGKit/Node.h"')
48+
File.open(file, 'w') { |f| f.write(new_contents) }
49+
# puts "Patched Node import in: #{file}"
50+
end
51+
52+
# import CSSValue.h
53+
Dir.glob(File.join(svgkit_path, '**', '*.{h,m}')).each do |file|
54+
FileUtils.chmod("u+w", file)
55+
text = File.read(file)
56+
new_contents = text.gsub('#import "CSSValue.h"', '#import "SVGKit/CSSValue.h"')
57+
File.open(file, 'w') { |f| f.write(new_contents) }
58+
# puts "Patched CSSValue import in: #{file}"
59+
end
60+
61+
# import SVGLength.h
62+
Dir.glob(File.join(svgkit_path, '**', '*.{h,m}')).each do |file|
63+
FileUtils.chmod("u+w", file)
64+
text = File.read(file)
65+
new_contents = text.gsub('#import "SVGLength.h"', '#import "SVGKit/SVGLength.h"')
66+
File.open(file, 'w') { |f| f.write(new_contents) }
67+
# puts "Patched SVGLength import in: #{file}"
68+
end
69+
end
70+
```
71+
2572
### Expo Projects
2673

2774
Add your keys to the `app.json`.
@@ -43,148 +90,79 @@ The config plugin automatically injects them into your native Android and iOS bu
4390
}
4491
```
4592

46-
# Dependencies
47-
48-
This package builds on native libraries for SVG rendering and Google Maps integration:
49-
50-
- **iOS**: [SVGKit](https://github.com/SVGKit/SVGKit)
51-
- **Android**: [AndroidSVG](https://bigbadaboom.github.io/androidsvg/)
52-
- **iOS Maps SDK**: [Google Maps SDK for iOS](https://developers.google.com/maps/documentation/ios-sdk)
53-
- **Android Maps SDK**: [Google Maps SDK for Android](https://developers.google.com/maps/documentation/android-sdk)
54-
- **Maps Utility Libraries**: [Google Maps Utils for iOS](https://developers.google.com/maps/documentation/ios-sdk/utility) and [Google Maps Utils for Android](https://developers.google.com/maps/documentation/android-sdk/utility)
55-
56-
These are automatically linked when you install the package, but you may need to clean/rebuild your native projects after first install.
57-
5893
## Setup API Key
5994

6095
You will need a valid **Google Maps API Key** from the [Google Cloud Console](https://console.cloud.google.com/).
6196

6297
### Android
6398

64-
It's recommend to use [Secrets Gradle Plugin](https://developers.google.com/maps/documentation/android-sdk/secrets-gradle-plugin) to securely manage your Google Maps API Key.
99+
**Note:** These instructions apply to **bare React Native apps only**.
100+
Expo projects should use the config plugin instead (see Expo section above).
65101

66-
---
102+
See the official [Google Maps Android SDK configuration guide](https://developers.google.com/maps/documentation/android-sdk/config#step_3_add_your_api_key_to_the_project) for more details.
67103

68104
### iOS
69105

70-
See the official [Google Maps iOS SDK configuration guide](https://developers.google.com/maps/documentation/ios-sdk/config#get-key) for more details.
106+
**Note:** These instructions apply to **bare React Native apps only**.
107+
Expo projects should use the config plugin instead (see Expo section above).
71108

72-
1. Create a `Secrets.xcconfig` file inside the **ios/** folder:
109+
See the official [Google Maps iOS SDK configuration guide](https://developers.google.com/maps/documentation/ios-sdk/config#get-key) for more details.
73110

74-
```properties
75-
MAPS_API_KEY=YOUR_IOS_MAPS_API_KEY
76-
```
111+
## Dependencies & Native Documentation
77112

78-
Include it in your project configuration file:
113+
This package is React Native wrapper around the official Google Maps SDKs.
114+
For full API behavior, configuration options, and feature reference, please consult the native documentation:
79115

80-
```xcconfig
81-
#include? "Secrets.xcconfig"
82-
```
116+
- **iOS Google Maps SDK**
117+
https://developers.google.com/maps/documentation/ios-sdk
83118

84-
2. Reference the API key in your **Info.plist**:
119+
- **Android Google Maps SDK**
120+
https://developers.google.com/maps/documentation/android-sdk
85121

86-
```xml
87-
<key>MAPS_API_KEY</key>
88-
<string>$(MAPS_API_KEY)</string>
89-
```
122+
- **Maps Utility Libraries (iOS & Android)**
123+
https://developers.google.com/maps/documentation/ios-sdk/utility
124+
https://developers.google.com/maps/documentation/android-sdk/utility
90125

91-
3. Provide the key programmatically in **AppDelegate.swift**:
126+
- **SVG Rendering** (used for custom marker icons)
127+
- iOS: https://github.com/SVGKit/SVGKit
128+
- Android: https://bigbadaboom.github.io/androidsvg/
92129

93-
```swift
94-
import GoogleMaps
130+
These libraries are automatically linked during installation.
131+
If you encounter build issues, try cleaning and rebuilding your native project.
95132

96-
@UIApplicationMain
97-
class AppDelegate: UIResponder, UIApplicationDelegate {
98-
func application(_ application: UIApplication,
99-
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
100-
if let apiKey = Bundle.main.object(forInfoDictionaryKey: "MAPS_API_KEY") as? String {
101-
GMSServices.provideAPIKey(apiKey)
102-
}
103-
return true
104-
}
105-
}
106-
```
107-
108-
---
133+
> **Note:** This package follows the native SDKs closely. Props and behavior match the underlying Google Maps APIs whenever possible.
109134
110135
## Usage
111136

112-
Checkout the example app in the [example](./example) folder.
113-
114-
# Troubleshooting
115-
116-
## Android
117-
118-
- **API key not found**
119-
Make sure `secrets.properties` exists under `android/` and contains your `MAPS_API_KEY`.
120-
Run `./gradlew clean` and rebuild.
121-
122-
## iOS
123-
124-
- **`GMSServices must be configured before use`**
125-
Ensure your key is in `Info.plist` and/or provided via `GMSServices.provideAPIKey(...)` in `AppDelegate.swift`.
126-
127-
- **Build fails with `Node.h`, `CSSValue.h`, or `SVGLength.h` import errors from SVGKit**
128-
SVGKit includes headers (`Node.h`, `CSSValue.h`, `SVGLength.h`) that can conflict with
129-
iOS system headers and React Native Reanimated’s internal types.
130-
You can patch them automatically in your **Podfile** inside the `post_install`
131-
132-
```ruby
133-
post_install do |installer|
134-
react_native_post_install(
135-
installer,
136-
config[:reactNativePath],
137-
:mac_catalyst_enabled => false,
138-
)
139-
# Force iOS 16+ to avoid deployment target warnings
140-
installer.pods_project.targets.each do |target|
141-
target.build_configurations.each do |config|
142-
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
143-
end
144-
end
145-
146-
# --- SVGKit Patch ---
147-
require 'fileutils'
148-
svgkit_path = File.join(installer.sandbox.pod_dir('SVGKit'), 'Source')
149-
150-
# node fix
151-
Dir.glob(File.join(svgkit_path, '**', '*.{h,m}')).each do |file|
152-
FileUtils.chmod("u+w", file)
153-
text = File.read(file)
154-
new_contents = text.gsub('#import "Node.h"', '#import "SVGKit/Node.h"')
155-
File.open(file, 'w') { |f| f.write(new_contents) }
156-
# puts "Patched Node import in: #{file}"
157-
end
158-
159-
# import CSSValue.h
160-
Dir.glob(File.join(svgkit_path, '**', '*.{h,m}')).each do |file|
161-
FileUtils.chmod("u+w", file)
162-
text = File.read(file)
163-
new_contents = text.gsub('#import "CSSValue.h"', '#import "SVGKit/CSSValue.h"')
164-
File.open(file, 'w') { |f| f.write(new_contents) }
165-
# puts "Patched CSSValue import in: #{file}"
166-
end
167-
168-
# import SVGLength.h
169-
Dir.glob(File.join(svgkit_path, '**', '*.{h,m}')).each do |file|
170-
FileUtils.chmod("u+w", file)
171-
text = File.read(file)
172-
new_contents = text.gsub('#import "SVGLength.h"', '#import "SVGKit/SVGLength.h"')
173-
File.open(file, 'w') { |f| f.write(new_contents) }
174-
# puts "Patched SVGLength import in: #{file}"
175-
end
176-
end
177-
```
178-
179-
After applying this, run:
180-
181-
```sh
182-
cd ios && pod install --repo-update
183-
```
137+
Basic map:
138+
139+
```tsx
140+
import React from 'react';
141+
import { GoogleMapsView } from 'react-native-google-maps-plus';
142+
143+
export default function App() {
144+
return (
145+
<GoogleMapsView
146+
style={{ flex: 1 }}
147+
initialProps={{
148+
camera: {
149+
center: { latitude: 37.7749, longitude: -122.4194 },
150+
zoom: 12,
151+
},
152+
}}
153+
markers={[
154+
{
155+
id: '1',
156+
zIndex: 1,
157+
coordinate: { latitude: 37.7749, longitude: -122.4194 },
158+
},
159+
]}
160+
/>
161+
);
162+
}
163+
```
184164

185-
- **Maps not rendering**
186-
- Check that your API key has **Maps SDK for Android/iOS** enabled in Google Cloud Console.
187-
- Make sure the key is not restricted to wrong bundle IDs or SHA1 fingerprints.
165+
Check out the example app in the [example](./example) folder.
188166

189167
## Contributing
190168

android/src/main/java/com/rngooglemapsplus/extensions/RNUserInterfaceExtension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ fun RNUserInterfaceStyle?.toMapColorScheme(): Int? =
77
when (this) {
88
RNUserInterfaceStyle.LIGHT -> MapColorScheme.LIGHT
99
RNUserInterfaceStyle.DARK -> MapColorScheme.DARK
10-
RNUserInterfaceStyle.DEFAULT -> MapColorScheme.FOLLOW_SYSTEM
10+
RNUserInterfaceStyle.SYSTEM -> MapColorScheme.FOLLOW_SYSTEM
1111
null -> null
1212
}

example/src/components/ControlPanel.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ import type { GoogleMapsViewRef } from 'react-native-google-maps-plus';
1717
import { useAppTheme } from '../hooks/useAppTheme';
1818
import { useNavigation } from '@react-navigation/native';
1919
import type { RootNavigationProp } from '../types/navigation';
20+
import {
21+
type EdgeInsets,
22+
useSafeAreaInsets,
23+
} from 'react-native-safe-area-context';
24+
import type { AppTheme } from '../theme';
2025

2126
export type ButtonItem = { title: string; onPress: () => void };
2227

@@ -29,7 +34,8 @@ export default function ControlPanel({ mapRef, buttons }: Props) {
2934
const theme = useAppTheme();
3035
const navigation = useNavigation<RootNavigationProp>();
3136
const progress = useSharedValue(0);
32-
const styles = useMemo(() => getThemedStyles(theme), [theme]);
37+
const layout = useSafeAreaInsets();
38+
const styles = useMemo(() => getThemedStyles(theme, layout), [layout, theme]);
3339

3440
const toggle = () => {
3541
progress.value = withTiming(progress.value === 1 ? 0 : 1, {
@@ -124,7 +130,7 @@ export default function ControlPanel({ mapRef, buttons }: Props) {
124130
);
125131
}
126132

127-
const getThemedStyles = (theme: any) =>
133+
const getThemedStyles = (theme: AppTheme, layout: EdgeInsets) =>
128134
StyleSheet.create({
129135
scrollView: {
130136
position: 'absolute',
@@ -136,7 +142,7 @@ const getThemedStyles = (theme: any) =>
136142
backgroundColor: theme.bgPrimary,
137143
},
138144
scrollContent: {
139-
paddingBottom: 40,
145+
paddingBottom: layout.bottom + 8,
140146
},
141147
header: {
142148
borderRadius: 10,

example/src/components/HeaderButton.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useMemo } from 'react';
22
import { Pressable, StyleSheet, Text } from 'react-native';
33
import { useAppTheme } from '../hooks/useAppTheme';
4+
import type { AppTheme } from '../theme';
45

56
type Props = {
67
title: string;
@@ -18,7 +19,7 @@ export default function HeaderButton({ title, onPress }: Props) {
1819
);
1920
}
2021

21-
const getThemedStyles = (theme: any) =>
22+
const getThemedStyles = (theme: AppTheme) =>
2223
StyleSheet.create({
2324
headerButton: {
2425
paddingHorizontal: 12,

example/src/components/MapWrapper.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import {
2525
} from 'react-native-google-maps-plus';
2626
import { useSafeAreaInsets } from 'react-native-safe-area-context';
2727
import { callback } from 'react-native-nitro-modules';
28-
import { useTheme } from '@react-navigation/native';
28+
import type { AppTheme } from '../theme';
29+
import { useAppTheme } from '../hooks/useAppTheme';
2930

3031
type Props = ViewProps &
3132
RNGoogleMapsPlusViewProps & {
@@ -47,7 +48,7 @@ function wrapCallback<T extends (...args: any[]) => void>(
4748

4849
export default function MapWrapper(props: Props) {
4950
const { children, ...rest } = props;
50-
const theme = useTheme();
51+
const theme = useAppTheme();
5152
const styles = useMemo(() => getThemedStyles(theme), [theme]);
5253
const layout = useSafeAreaInsets();
5354

@@ -119,7 +120,8 @@ export default function MapWrapper(props: Props) {
119120
indoorEnabled={props.indoorEnabled ?? false}
120121
style={[styles.map, props.style]}
121122
userInterfaceStyle={
122-
props.userInterfaceStyle ?? (theme.dark ? 'dark' : 'light')
123+
props.userInterfaceStyle ??
124+
(theme.theme === 'dark' ? 'dark' : 'light')
123125
}
124126
mapType={props.mapType ?? 'normal'}
125127
mapZoomConfig={props.mapZoomConfig ?? mapZoomConfig}
@@ -231,18 +233,18 @@ export default function MapWrapper(props: Props) {
231233
{children}
232234
{!mapLoaded && (
233235
<View style={styles.loadingOverlay}>
234-
<ActivityIndicator size="large" color={theme.colors.primary} />
236+
<ActivityIndicator size="large" color={theme.bgAccent} />
235237
</View>
236238
)}
237239
</View>
238240
);
239241
}
240242

241-
const getThemedStyles = (theme: any) =>
243+
const getThemedStyles = (theme: AppTheme) =>
242244
StyleSheet.create({
243245
container: {
244246
flex: 1,
245-
backgroundColor: theme.background,
247+
backgroundColor: theme.bgPrimary,
246248
},
247249
map: {
248250
position: 'absolute',

0 commit comments

Comments
 (0)