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

Uniffi React Native Integration #401

Open
wants to merge 39 commits into
base: main
Choose a base branch
from

Conversation

bjtrounson
Copy link
Collaborator

@bjtrounson bjtrounson commented Dec 23, 2024

Background

After testing an expo modules approach in this PR #394 . We have found that the work to maintain the record types between the Rust layer and expo modules would be too tendinous. So this PR has an initial implementation of using uniffi-bindgen-react-native to create a similar binding as Android and iOS. One downside of this is we have to implement the views all again just for react-native but this downside is worth it long term definitely since the FerrostarCore-RS is still changing it's model quite frequently.

Implementation overview

Implementation of the core integration is following the current Android implementation quite closely apart from segments where there our missing language features and such. We are using uniffi-bindgen-react-native to create the Rust binding the generated TypeScript types are located in src/generated.

Current status

Please let me know missing implementations that should be on the list and I will update it.

  • FerrostarCore
  • LocationProvider
  • RouteProvider
  • AlternativeRouteProcessor
  • RouteDeviationHandler
  • NavigationUiState
  • BorderedPolyline
  • NavigationView
  • NavigationMapViewCamera
  • TripProgressView
  • Navigating Puck (snap to route still needs to be sorted.)
  • InstructionView

Moved to be separate issues

@bjtrounson
Copy link
Collaborator Author

bjtrounson commented Dec 23, 2024

/react-native/cpp/generated/ and /react-native/src/generated should be ignored from the CI checks other typos need to be fixed

Edit: I've added these.

@bjtrounson
Copy link
Collaborator Author

bjtrounson commented Dec 23, 2024

Initial version of puck, route and trip progress view.

Screenrecorder-2024-12-24-07-28-28-106.mp4

I have discover one issue and it's that I don't think we can currently override the current location that MapLibre is using within maplibre-react-native. I'm wondering if @KiwiKilian might know of any available solution here or if it's something that's going to need to be exposed on that libraries side.

@KiwiKilian
Copy link

Just glanced at your recent commits, do I understand correctly:

  • Ferrostar retrieves the location from MapLibre Native and snaps to the route
  • You are rendering the UserLocation component from MapLibre React Native
  • You want the UserLocation component to use the snapped coordinates instead of the actual ones, correct?

Currently there is no clean way to do this.

I'm not sure if we you actually want to override the LocationManager. Users might want to use both locations for some reason? We could just extract a dumb UserLocationPuck component, which you can feed any coordinate?

@bjtrounson
Copy link
Collaborator Author

bjtrounson commented Dec 23, 2024

You want the UserLocation component to use the snapped coordinates instead of the actual ones, correct?

Yes we only want to use the snapped location when we are navigating and if our snappedToRoute options is enable in the FerrostarCore, I think the android version does this using a StaticEngine and inserts that into MapLibre @ianthetechie might be able to explain that a bit better. But I don't think that will probably be the best approach here.

I'm not sure if we you actually want to override the LocationManager. Users might want to use both locations for some reason? We could just extract a dumb UserLocationPuck component, which you can feed any coordinate?

I really like this idea and I agree users might want a different functionality here, is this something that could be extracted here or have to be expose on the maplibre-react-native side?

@bjtrounson bjtrounson marked this pull request as draft December 26, 2024 03:58
@bjtrounson
Copy link
Collaborator Author

MapControl need a bit of work, we need some fonts for the +, -, mute, route and recenter button (I've tried + & - as just normal character but it doesn't look good) will look at extracting some google fonts as I think that's what we are using on Android.

We will also need to sort out the camera state mostly for the route overview and recenter. I don't think we can just apply a the navigation camera again to reset like we do on Android. So will have to look at keeping a camera state some where probably a provider that will get updated via the onUserTrackingModeChange event. Then we can reset the camera state that is looking at the provider, not 100% sure this will reset the pitch and zoom though will need to test this.

@bjtrounson
Copy link
Collaborator Author

All the extra stuff has been split into separate issues, I wouldn't mind committing my current map control stuff before we merge this though.

Will let you know once that's done @ianthetechie

@bjtrounson bjtrounson self-assigned this Jan 14, 2025
@bjtrounson
Copy link
Collaborator Author

Okay that should be everything for this. I even added the example app and got that stored.

Feel free to finish the review now @ianthetechie

react-native/android/build.gradle Outdated Show resolved Hide resolved
react-native/CONTRIBUTING.md Outdated Show resolved Hide resolved
react-native/README.md Outdated Show resolved Hide resolved
react-native/LICENSE Outdated Show resolved Hide resolved
react-native/CODE_OF_CONDUCT.md Outdated Show resolved Hide resolved
react-native/src/core/FerrostarCore.ts Outdated Show resolved Hide resolved
react-native/src/core/NavigationUiState.ts Show resolved Hide resolved
react-native/src/views/TripProgressView.tsx Show resolved Hide resolved
react-native/src/views/_utils.ts Show resolved Hide resolved
@@ -0,0 +1,1287 @@
import Svg, { Path, type SvgProps } from 'react-native-svg';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's find a way to make this reproducible since it's currently just copying from SVGs that the web uses and we'll want to keep them in sync.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be able to align them by using the raw svg files using https://github.com/kristerkari/react-native-svg-transformer for the react native side

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided to put this under the same issue as the formatter so we can sync web and react native up at the same time.
#427


sourceSets {
main {
manifest.srcFile "src/main/AndroidManifestNew.xml"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why you have two AndroidManifests. I think one wants to keep it for better compatibility?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah makes sense, I think maybe uniffi-bindgen-react-native generates one and moved the old one not 100% sure.
I've changed that to look at the current.

It also pointed out that I needed to change the package name in the manifest.

Copy link

@KiwiKilian KiwiKilian Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think one wants to have two files:

  • AndroidManifest.xml
    • It has the package attribute on <manifest> tag
    • Used automatically, even without reference in build.gradle, when supportsNamespace is false
  • AndroidManifestNew.xml
    • Doesn't have the package attribute on <manifest> tag, because the namespace is that withing build.gradle
    • Is only used when supportsNamespace is true
  • Everything else is the same in both files
  • This is the default setup from React Native Builder Bob

Otherwise you will get the following warning:

Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported.

Copy link

@KiwiKilian KiwiKilian Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is explained here: callstack/react-native-builder-bob#431

On the other hand, if you only aim for most recent React Native versions support, it might not be necessary? But then the supportsNameSpace check should be removed and the one and only AndroidManifest.xml should not contain a package attribute?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wow this is good to know I'll add those back then.

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

Successfully merging this pull request may close these issues.

3 participants