Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Existing layers when the map is offline #3152

Open
orca-nazar opened this issue Nov 1, 2023 · 10 comments
Open

[Bug]: Existing layers when the map is offline #3152

orca-nazar opened this issue Nov 1, 2023 · 10 comments

Comments

@orca-nazar
Copy link
Contributor

orca-nazar commented Nov 1, 2023

Mapbox Implementation

Mapbox

Mapbox Version

10.16.1

Platform

Android

@rnmapbox/maps version

#main

Standalone component to reproduce

import Mapbox, { Camera, MapView } from '@rnmapbox/maps';
import React, { useState } from 'react';
import { Button } from 'react-native';

const getStyles = (isDark) => ({
  mapView: { flex: 1 },
  overlay: {
    fillColor: isDark ? 'hsl(76,26%,75%)' : 'hsl(200,46%,69%)',
  },
});

const { Dark, Light } = Mapbox.StyleURL;

const BugReportExample = () => {
  const [styleUrl, setStyleUrl] = useState(Light);
  const isDark = styleUrl === Dark;
  const buttonTitle = isDark ? 'Set Light' : 'Set Dark';
  const styles = getStyles(isDark);

  return (
    <>
      <Button
        title={buttonTitle}
        onPress={() => setStyleUrl(isDark ? Light : Dark)}
      />
      <MapView style={styles.mapView} styleURL={styleUrl}>
        <Camera centerCoordinate={[-74.00597, 40.71427]} zoomLevel={14} />
        <Mapbox.VectorSource id="composite">
          <Mapbox.FillLayer
            id="national-park"
            sourceLayerID="landuse_overlay"
            sourceID="composite"
            style={styles.overlay}
          />
        </Mapbox.VectorSource>
      </MapView>
    </>
  );
};

export default BugReportExample;

Observed behavior and steps to reproduce

In our app we experience this issue when styles are switched in 2 scenarios

  1. Fast switching between dark and satellite mode (can't reproduce it in Example app). Our workaround is to apply(mount) custom sources and layers only after onDidFinishLoadingMap is fired
  2. In offline mode between switching dark and light mode

The second scenario could be reproducable by using BugReportExample

  1. In online mode open Bug Report Template TS
  2. Go Offline
  3. Switch to Dark mode. Dark styles will be missed as no connection
  4. Switch back to Light mode.
    Actual result: Error while updating property 'reactStyle' of a view managed by: RNMBXFillLayer null Set layer property "fill-color" failed: Layer national-park is not in style:

Expected behavior

No issues

Notes / preliminary analysis

It happens only when color is dynamically changed:
fillColor: isDark ? 'hsl(76,26%,75%)' : 'hsl(200,46%,69%)',
No issues in this case:
fillColor: 'hsl(76,26%,75%)'

Additional links and references

No response

@bviebahn
Copy link

bviebahn commented Nov 6, 2023

I got some similar errors when changing the styleURL. This one seems to be caused by the compass:

Error while updating property 'reactStyle' of a view managed by: RCTMGLSymbolLayer
...
Caused by com.mapbox.maps.MapboxStyleException: Set layer property "icon-rotate" failed:
Layer mapboxUserLocationHeadingIndicator is not in style
159.71372985839844
       at com.mapbox.maps.extension.style.layers.Layer.updateProperty(Layer.kt:152)
       at com.mapbox.maps.extension.style.layers.Layer.setProperty$extension_style_publicRelease(Layer.kt:141)
       at com.mapbox.maps.extension.style.layers.generated.SymbolLayer.iconRotate(SymbolLayer.kt:809)
       at com.mapbox.rctmgl.components.styles.RCTMGLStyleFactory.setIconRotate(RCTMGLStyleFactory.java:1318)
       at com.mapbox.rctmgl.components.styles.RCTMGLStyleFactory.setSymbolLayerStyle(RCTMGLStyleFactory.java:255)
       at com.mapbox.rctmgl.components.styles.layers.RCTMGLSymbolLayer.addStyles(RCTMGLSymbolLayer.kt:31)
       at com.mapbox.rctmgl.components.styles.layers.RCTLayer.setReactStyle(RCTLayer.kt:124)
       at com.mapbox.rctmgl.components.styles.layers.RCTMGLSymbolLayerManager.setReactStyle(RCTMGLSymbolLayerManager.kt:60)
       at java.lang.reflect.Method.invoke(Method.java)
       ...

@mfazekas
Copy link
Contributor

mfazekas commented Nov 14, 2023

image

I don't see this warning on main.

I've needed to add existing flags for the source and layer as those were referring to existing layers in the style:

import Mapbox, { Camera, MapView } from '@rnmapbox/maps';
import React, { useState } from 'react';
import { Button } from 'react-native';

const getStyles = (isDark) => ({
  mapView: { flex: 1 },
  overlay: {
    fillColor: isDark ? 'hsl(76,26%,75%)' : 'hsl(200,46%,69%)',
  },
});

const { Dark, Light } = Mapbox.StyleURL;

const BugReportExample = () => {
  const [styleUrl, setStyleUrl] = useState(Light);
  const isDark = styleUrl === Dark;
  const buttonTitle = isDark ? 'Set Light' : 'Set Dark';
  const styles = getStyles(isDark);

  return (
    <>
      <Button
        title={buttonTitle}
        onPress={() => setStyleUrl(isDark ? Light : Dark)}
      />
      <MapView style={styles.mapView} styleURL={styleUrl}>
        <Camera centerCoordinate={[-74.00597, 40.71427]} zoomLevel={14} />
        <Mapbox.VectorSource id="composite" existing>
          <Mapbox.FillLayer
            id="national-park"
            sourceLayerID="landuse_overlay"
            sourceID="composite"
            existing
            style={styles.overlay}
          />
        </Mapbox.VectorSource>
      </MapView>
    </>
  );
};

export default BugReportExample;

@orca-nazar
Copy link
Contributor Author

@mfazekas It always reproduces even with existing property.
The problem is the next: once the new styles are applied, all features will be removed from map including "existing", but the logic to recreate them doesn't exist. Should not they be skipped, as creating/deleting "existing" features should be handled by mapbox itself

@mfazekas
Copy link
Contributor

mfazekas commented Dec 6, 2023

@mfazekas It always reproduces even with existing property.
The problem is the next: once the new styles are applied, all features will be removed from map including "existing", but the logic to recreate them doesn't exist. Should not they be skipped, as creating/deleting "existing" features should be handled by mapbox itself

@orca-nazar can you be please more specific. Which @rnmapbox/maps version have you tested with , which component you've tried? The one in my comment? - #3152 (comment)

@orca-nazar
Copy link
Contributor Author

Correct, I use the latest version and your component

@mfazekas
Copy link
Contributor

mfazekas commented Dec 6, 2023

@orca-nazar I don't see the issue on current #main.

import Mapbox, { Camera, MapView } from '@rnmapbox/maps';
import React, { useState } from 'react';
import { Button } from 'react-native';

const getStyles = (isDark) => ({
  mapView: { flex: 1 },
  overlay: {
    fillColor: isDark ? 'hsl(76,26%,75%)' : 'hsl(200,46%,69%)',
  },
});

const { Dark, Light } = Mapbox.StyleURL;

const BugReportExample = () => {
  const [styleUrl, setStyleUrl] = useState(Light);
  const isDark = styleUrl === Dark;
  const buttonTitle = isDark ? 'Set Light' : 'Set Dark';
  const styles = getStyles(isDark);

  return (
    <>
      <Button
        title={buttonTitle}
        onPress={() => setStyleUrl(isDark ? Light : Dark)}
      />
      <MapView style={styles.mapView} styleURL={styleUrl}>
        <Camera
          defaultSettings={{
            centerCoordinate: [-74.00597, 40.71427],
            zoomLevel: 8,
          }}
        />
        <Mapbox.VectorSource id="composite" existing>
          <Mapbox.FillLayer
            id="national-park"
            sourceLayerID="landuse_overlay"
            sourceID="composite"
            existing
            style={styles.overlay}
          />
        </Mapbox.VectorSource>
      </MapView>
    </>
  );
};

export default BugReportExample;
Screen.Recording.2023-12-06.at.14.14.14.mov

@orca-nazar
Copy link
Contributor Author

orca-nazar commented Dec 6, 2023

Please check the steps to reproduce, the main point here was to go to offline mode.
But before it, you need to clear the map data. You can go to app settings and clear data storage or delete/install the app. Then please follow the steps in the video.
Thanks :) @mfazekas

@mfazekas
Copy link
Contributor

mfazekas commented Dec 6, 2023

I think we need to add a check that if component is declared mExisitng but layer doesn't exists then we need to defer adding the layer until it's available, ideally we can use mapView.waitForLayer( for that.

val exists = style.styleLayerExists(id)
var existingLayer: T? = null;
if (exists) {
if (mExisting == null) {
Logger.e(LOG_TAG, "Layer $id seems to refer to an existing layer but existing flag is not specified, this is deprecated")
}
existingLayer = getLayerAs(style, id)
}
if (existingLayer != null) {
mLayer = existingLayer
} else {
mLayer = makeLayer()
insertLayer()
}

@orca-nazar
Copy link
Contributor Author

orca-nazar commented Dec 6, 2023

Sounds good. Also, I'm wondering if this technique can be useful for the next case:

Fast switching between dark and satellite mode (can't reproduce it in Example app). Our workaround is to apply(mount) custom sources and layers only after onDidFinishLoadingMap is fired

So it could applied to filters and styles props updates

@mfazekas mfazekas changed the title [Bug]: Error while updating property 'reactStyle' of a view managed by: RNMBXFillLayer [Bug]: Existing layers when the map is offline Dec 7, 2023
@mfazekas mfazekas reopened this Dec 7, 2023
@jnocz
Copy link

jnocz commented Feb 14, 2024

Hi, any updates on this issue? I'm experiencing the same issue on Android, on iOS it looks without any problem. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants