Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,9 @@
package com.google.android.react.navsdk;

import androidx.annotation.Nullable;
import com.google.android.libraries.navigation.StylingOptions;

/**
* Unified property sink for buffering both fragment-level and controller-level properties that
* arrive before the fragment is created. Implements both INavigationViewProperties and
* INavigationViewControllerProperties to handle all property types in a single object.
*/
public class ViewPropertiesSink
implements INavigationViewProperties, INavigationViewControllerProperties {
// Map fragment properties
@Nullable private Integer mapColorScheme;

// Map controller properties
/** Buffers map-controller props until getMapAsync creates the MapViewController. */
public class MapViewControllerPropertiesSink implements INavigationViewControllerProperties {
@Nullable private Integer mapType;
@Nullable private Integer paddingTop;
@Nullable private Integer paddingLeft;
Expand All @@ -53,28 +43,6 @@ public class ViewPropertiesSink
@Nullable private Float minZoomLevel;
@Nullable private Float maxZoomLevel;

// Navigation fragment properties
@Nullable private Integer nightModeOption;
@Nullable private Boolean tripProgressBarEnabled;
@Nullable private Boolean trafficPromptsEnabled;
@Nullable private Boolean trafficIncidentCardsEnabled;
@Nullable private Boolean headerEnabled;
@Nullable private Boolean footerEnabled;
@Nullable private Boolean speedometerEnabled;
@Nullable private Boolean speedLimitIconEnabled;
@Nullable private Boolean recenterButtonEnabled;
@Nullable private Boolean reportIncidentButtonEnabled;
@Nullable private StylingOptions stylingOptions;

// ========== IMapViewProperties implementation ==========

@Override
public void setMapColorScheme(int colorScheme) {
this.mapColorScheme = colorScheme;
}

// ========== IMapViewControllerProperties implementation ==========

@Override
public void setMapType(int mapType) {
this.mapType = mapType;
Expand Down Expand Up @@ -173,64 +141,6 @@ public void setMaxZoomLevel(float maxZoomLevel) {
this.maxZoomLevel = maxZoomLevel;
}

// ========== INavigationViewProperties implementation ==========

@Override
public void setNightModeOption(int nightMode) {
this.nightModeOption = nightMode;
}

@Override
public void setStylingOptions(StylingOptions options) {
this.stylingOptions = options;
}

@Override
public void setTripProgressBarEnabled(boolean enabled) {
this.tripProgressBarEnabled = enabled;
}

@Override
public void setTrafficPromptsEnabled(boolean enabled) {
this.trafficPromptsEnabled = enabled;
}

@Override
public void setTrafficIncidentCardsEnabled(boolean enabled) {
this.trafficIncidentCardsEnabled = enabled;
}

@Override
public void setHeaderEnabled(boolean enabled) {
this.headerEnabled = enabled;
}

@Override
public void setFooterEnabled(boolean enabled) {
// Footer on Android is the same as ETA card
this.footerEnabled = enabled;
}

@Override
public void setSpeedometerEnabled(boolean enabled) {
this.speedometerEnabled = enabled;
}

@Override
public void setSpeedLimitIconEnabled(boolean enabled) {
this.speedLimitIconEnabled = enabled;
}

@Override
public void setRecenterButtonEnabled(boolean enabled) {
this.recenterButtonEnabled = enabled;
}

@Override
public void setReportIncidentButtonEnabled(boolean enabled) {
this.reportIncidentButtonEnabled = enabled;
}

/** Apply all buffered controller properties to the map controller. */
public void applyToController(MapViewController controller) {
if (controller == null) {
Expand Down Expand Up @@ -300,74 +210,8 @@ public void applyToController(MapViewController controller) {
}
}

/** Apply all buffered fragment properties to the fragment. */
public void applyToFragment(IMapViewFragment fragment) {
if (fragment == null) {
return;
}

// Apply map fragment properties
if (mapColorScheme != null) {
fragment.setMapColorScheme(mapColorScheme);
}

// Apply navigation fragment properties if applicable
if (fragment instanceof INavViewFragment) {
INavViewFragment navFragment = (INavViewFragment) fragment;

if (nightModeOption != null) {
navFragment.setNightModeOption(nightModeOption);
}
if (stylingOptions != null) {
navFragment.setStylingOptions(stylingOptions);
}
if (tripProgressBarEnabled != null) {
navFragment.setTripProgressBarEnabled(tripProgressBarEnabled);
}
if (trafficPromptsEnabled != null) {
navFragment.setTrafficPromptsEnabled(trafficPromptsEnabled);
}
if (trafficIncidentCardsEnabled != null) {
navFragment.setTrafficIncidentCardsEnabled(trafficIncidentCardsEnabled);
}
if (headerEnabled != null) {
navFragment.setHeaderEnabled(headerEnabled);
}
if (footerEnabled != null) {
navFragment.setFooterEnabled(footerEnabled);
}
if (speedometerEnabled != null) {
navFragment.setSpeedometerEnabled(speedometerEnabled);
}
if (speedLimitIconEnabled != null) {
navFragment.setSpeedLimitIconEnabled(speedLimitIconEnabled);
}
if (recenterButtonEnabled != null) {
navFragment.setRecenterButtonEnabled(recenterButtonEnabled);
}
if (reportIncidentButtonEnabled != null) {
navFragment.setReportIncidentButtonEnabled(reportIncidentButtonEnabled);
}
}
}

/** Clear all buffered properties (both fragment and controller). */
/** Clear all buffered properties. */
public void clear() {
// Clear fragment properties
mapColorScheme = null;
nightModeOption = null;
stylingOptions = null;
tripProgressBarEnabled = null;
trafficPromptsEnabled = null;
trafficIncidentCardsEnabled = null;
headerEnabled = null;
footerEnabled = null;
speedometerEnabled = null;
speedLimitIconEnabled = null;
recenterButtonEnabled = null;
reportIncidentButtonEnabled = null;

// Clear controller properties
mapType = null;
paddingTop = null;
paddingLeft = null;
Expand All @@ -388,5 +232,7 @@ public void clear() {
tiltGesturesEnabled = null;
zoomGesturesEnabled = null;
zoomControlsEnabled = null;
minZoomLevel = null;
maxZoomLevel = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,22 @@ public class MapViewFragment extends SupportMapFragment
private ReactApplicationContext reactContext;
private GoogleMap mGoogleMap;
private MapViewController mMapViewController;
@Nullable private MapViewControllerReadyListener mapViewControllerReadyListener;
private @MapColorScheme int mapColorScheme = MapColorScheme.FOLLOW_SYSTEM;

public static MapViewFragment newInstance(
ReactApplicationContext reactContext, int viewTag, @NonNull GoogleMapOptions mapOptions) {
ReactApplicationContext reactContext,
int viewTag,
@NonNull GoogleMapOptions mapOptions,
@Nullable MapViewControllerReadyListener mapViewControllerReadyListener) {
MapViewFragment fragment = new MapViewFragment();
Bundle args = new Bundle();
args.putParcelable("MapOptions", mapOptions);

fragment.setArguments(args);
fragment.reactContext = reactContext;
fragment.viewTag = viewTag;
fragment.mapViewControllerReadyListener = mapViewControllerReadyListener;

return fragment;
}
Expand All @@ -76,6 +81,9 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat

// Setup map listeners with the provided callback
mMapViewController.setupMapListeners(MapViewFragment.this);
if (mapViewControllerReadyListener != null) {
mapViewControllerReadyListener.onMapViewControllerReady(viewTag);
}
applyMapColorSchemeToMap();

emitEvent("onMapReady", null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.android.react.navsdk;

import androidx.annotation.Nullable;
import com.google.android.libraries.navigation.StylingOptions;

/** Buffers fragment-level props until the native map or navigation fragment is attached. */
public class MapViewPropertiesSink implements INavigationViewProperties {
@Nullable private Integer mapColorScheme;
@Nullable private Integer nightModeOption;
@Nullable private Boolean tripProgressBarEnabled;
@Nullable private Boolean trafficPromptsEnabled;
@Nullable private Boolean trafficIncidentCardsEnabled;
@Nullable private Boolean headerEnabled;
@Nullable private Boolean footerEnabled;
@Nullable private Boolean speedometerEnabled;
@Nullable private Boolean speedLimitIconEnabled;
@Nullable private Boolean recenterButtonEnabled;
@Nullable private Boolean reportIncidentButtonEnabled;
@Nullable private StylingOptions stylingOptions;

@Override
public void setMapColorScheme(int colorScheme) {
this.mapColorScheme = colorScheme;
}

@Override
public void setNightModeOption(int nightMode) {
this.nightModeOption = nightMode;
}

@Override
public void setStylingOptions(StylingOptions options) {
this.stylingOptions = options;
}

@Override
public void setTripProgressBarEnabled(boolean enabled) {
this.tripProgressBarEnabled = enabled;
}

@Override
public void setTrafficPromptsEnabled(boolean enabled) {
this.trafficPromptsEnabled = enabled;
}

@Override
public void setTrafficIncidentCardsEnabled(boolean enabled) {
this.trafficIncidentCardsEnabled = enabled;
}

@Override
public void setHeaderEnabled(boolean enabled) {
this.headerEnabled = enabled;
}

@Override
public void setFooterEnabled(boolean enabled) {
// Footer on Android is the same as ETA card.
this.footerEnabled = enabled;
}

@Override
public void setSpeedometerEnabled(boolean enabled) {
this.speedometerEnabled = enabled;
}

@Override
public void setSpeedLimitIconEnabled(boolean enabled) {
this.speedLimitIconEnabled = enabled;
}

@Override
public void setRecenterButtonEnabled(boolean enabled) {
this.recenterButtonEnabled = enabled;
}

@Override
public void setReportIncidentButtonEnabled(boolean enabled) {
this.reportIncidentButtonEnabled = enabled;
}

/** Apply all buffered fragment properties to the fragment. */
public void applyToFragment(IMapViewFragment fragment) {
if (fragment == null) {
return;
}

if (mapColorScheme != null) {
fragment.setMapColorScheme(mapColorScheme);
}

if (fragment instanceof INavViewFragment) {
INavViewFragment navFragment = (INavViewFragment) fragment;

if (nightModeOption != null) {
navFragment.setNightModeOption(nightModeOption);
}
if (stylingOptions != null) {
navFragment.setStylingOptions(stylingOptions);
}
if (tripProgressBarEnabled != null) {
navFragment.setTripProgressBarEnabled(tripProgressBarEnabled);
}
if (trafficPromptsEnabled != null) {
navFragment.setTrafficPromptsEnabled(trafficPromptsEnabled);
}
if (trafficIncidentCardsEnabled != null) {
navFragment.setTrafficIncidentCardsEnabled(trafficIncidentCardsEnabled);
}
if (headerEnabled != null) {
navFragment.setHeaderEnabled(headerEnabled);
}
if (footerEnabled != null) {
navFragment.setFooterEnabled(footerEnabled);
}
if (speedometerEnabled != null) {
navFragment.setSpeedometerEnabled(speedometerEnabled);
}
if (speedLimitIconEnabled != null) {
navFragment.setSpeedLimitIconEnabled(speedLimitIconEnabled);
}
if (recenterButtonEnabled != null) {
navFragment.setRecenterButtonEnabled(recenterButtonEnabled);
}
if (reportIncidentButtonEnabled != null) {
navFragment.setReportIncidentButtonEnabled(reportIncidentButtonEnabled);
}
}
}

/** Clear all buffered properties. */
public void clear() {
mapColorScheme = null;
nightModeOption = null;
stylingOptions = null;
tripProgressBarEnabled = null;
trafficPromptsEnabled = null;
trafficIncidentCardsEnabled = null;
headerEnabled = null;
footerEnabled = null;
speedometerEnabled = null;
speedLimitIconEnabled = null;
recenterButtonEnabled = null;
reportIncidentButtonEnabled = null;
}
}
Loading
Loading