maplibre / maplibre-native

MapLibre Native - Interactive vector tile maps for iOS, Android and other platforms.
https://maplibre.org
BSD 2-Clause "Simplified" License
1.01k stars 296 forks source link

MapLibre Native Compose Multiplatform Library #2638

Open louwers opened 1 month ago

louwers commented 1 month ago

StreetComplete is looking to implement an iOS version of the app. The largest blocker is that there is no Compose Multiplatform library that uses MapLibre Native. If you are also interested in this, please reach out to @westnordost, maybe some kind of collaboration to work on this is possible.

Jetbrains has a template available here: https://github.com/KevinnZou/compose-multiplatform-library-template/tree/main

An example Compose Multiplatform library is WebView for JetBrains Compose Multiplatform

It uses Native C Interop: https://kotlinlang.org/docs/native-c-interop.html#simple-example with cinterop.

Related PR: https://github.com/maplibre/maplibre-native/pull/1254

tarkvara commented 1 month ago

For the record, we were able to get MapLibre working in our KMP app (both Android and iOS). It was however a home-grown solution, and there were some rough edges.

louwers commented 1 month ago

@tarkvara Can you share more details?

tarkvara commented 1 month ago

I wasn't ambitious enough to create a KMP library, so Android and iOS directly refer to the native libraries. Perhaps somebody with a better understanding of the KMP build tools can wrap them together into a single KMP library.

For Android, it was enough to add maplibre-android = { group = "org.maplibre.gl", name = "android-sdk", version = "11.0.1" } and the corresponding dependency under androidMain.dependencies.

For iOS, I added

        with (iosTarget.compilations) {
            getByName("main") {
                cinterops {
                    create("MapLibre") {
                        packageName("org.maplibre")
                        compilerOpts(
                            "-framework",
                            "MapboxLibre",
                            "-Fsrc/iosFrameworks/MapLibre.xcframework/$subDir"
                        )
                    }
                }
            }
        }
        iosTarget.binaries.all {
            // Tell the linker where the framework is located.
            linkerOpts(
                "-framework",
                "MapLibre",
                "-F../composeApp/src/iosFrameworks/MapLibre.xcframework/$subDir"
            )
        }

Which unfortunately isn't quite correct; the Gradle build doesn't correctly link, so I had to build the app from within Xcode.

As I said, it seems to work for our app, but I wouldn't recommend it as a general solution.

amirhammad commented 1 month ago

Hi! I just posted this today this in Slack and then found this issue.

Hello! I'm just wondering if there is anybody already working on maplibre in compose multiplatform. I think it is the missing piece in compose multiplatform app development - maps. I have already started creating a compose multiplatform library that uses maplibre native(ios and android) under the hood. I reworked the expressions to kotlin and the first tests look promising: loading styles, updating camera, adding layers and sources programatically. But maybe before going any further I just wanted to check if there is already a project doing this exact same thing. Is there? Thanks :slightly_smiling_face:

I was thinking of creating a proper opensource library for it, but I wanted to make sure it didn't exist yet. But seeing this issue, gives me enough motivation to continue.

westnordost commented 1 month ago

Thank you for posting this ticket, @louwers !

@amirhammad Wow, that's cool! There exists in fact a Compose library using MapLibre, Ramani-Maps. But it is for Jetpack Compose and Android-only. Additionally, I am not sure if the API of this library has been designed to support the whole feature set of MapLibre in mind. (see https://github.com/ramani-maps/ramani-maps/issues/77 which I just opened) At the very least, it can serve as a base or inspiration how the API could look like and how to wire together MapLibre with Compose in general. (But I just realized that I didn't read your cited message to the end - you already did that)

I am also highly interested in this, though I just started using Compose a few months ago, so I don't feel confident to help implementing a Compose library and design its API just yet. In terms of designing a perfect compose API, it might also be worth looking at and learning from the Google's Maps Compose library.

JonasVautherin commented 1 month ago

Hej! Co-author of Ramani-Maps here. We would love it if Ramani-Maps worked with Compose Multiplatform! Back when we started, I quickly tried to get Maplibre to run on Compose Multiplatform on my Linux system ("natively", i.e. not with a WebView and Javascript) and my conclusion was that it would take some work there.

If you manage to make Ramani-Maps work "natively" on iOS or Desktop, I would be willing to have a look and help bring that upstream. I am however not very open to solving it with a WebView and Javascript :see_no_evil:.

Additionally, I am not sure if the API of this library has been designed to support the whole feature set of MapLibre in mind.

Completely open to contributions! And of course if you feel like you will be better off on your own fork, feel free (it's MPLv2-licensed).

ianthetechie commented 1 month ago

Looping in @Archdoog here. We currently have a fork of Ramani that's a bit more active (would love to upstream but it's been a bit tough getting responses, and Ramani is currently a good bit broader with Mapbox support, drawing, and a lot of things besides just a core composable library).

We are not presently targeting compose multi platform but aren't opposed to it :)

Does anyone on the thread know how different or related Jetpack Compose and Compose Multiplatform are? EDIT: It looks like the JetBrains README has a helpful excerpt. The devil lies in the details, but this looks promising:

Compose Multiplatform shares most of its API with Jetpack Compose, the Android UI framework developed by Google. You can use the same APIs to build user interfaces for both Android and iOS.

Assuming they are similar, I think it would be a shame to have too many diverging approaches, since we are all going to run into most of the same challenges. Jacob and I have put a lot of work into getting camera stuff correct, as this is a HUGE pain in every similar UI framework (same on iOS, where we are developing a similar wrapper for SwiftUI).

JonasVautherin commented 1 month ago

would love to upstream but it's been a bit tough getting responses

@ianthetechie: have I missed questions somewhere? :confused:

Also note that we have dropped Mapbox support (because Mapbox doesn't play nice with us).

Archdoog commented 1 month ago

Hey @JonasVautherin! I think @ianthetechie had some initial chats with you on the maplibre slack channel. We tried reaching out there a handful of times.

As for a path forward, I'd suggest we set up a call to give you an introduction to where we've gone from forking ramani to where https://github.com/Rallista/maplibre-compose-playground sits now. There are a few key differences that we could chat about.

louwers commented 1 month ago

You are always welcome to put this on the agenda for the MapLibre Native TSC Meeting as well.

JonasVautherin commented 1 month ago

We tried reaching out there a handful of times.

I see. I have not been active on Slack there for a while indeed. The best way to upstream changes is probably to open an issue/PR on the git repository (i.e. the MapLibre Slack is not the official way to reach Ramani-Maps).

We can definitely have a call, I would be happy to hear your thoughts. However I probably won't bring your fork upstream myself. I am happy to discuss, review and merge contributions (on a best-effort basis), but someone would have to make those contributions :blush:. If that isn't possible, then as I said you are welcome to keep working on your fork (as long as you honour the licence) :+1:.

This said, I wouldn't say Ramani is not active. I believe I have been pretty responsive regarding issues and PRs on the repo. To be honest, I find it a bit unfair to say it has been "tough getting responses".

westnordost commented 1 month ago

~Does anyone on the thread know how different or related Jetpack Compose and Compose Multiplatform are?~

Compose Multiplatform is a soft fork of Jetpack Compose, for example, the package names are the same. So theoretically, one could switch out the dependency and be ready for multiplatform. Furthermore, some Jetpack compose APIs may not be available on multiplatform, i.e. they cannot be used or need to have an implementation for every platform. For example stringResource(stringResId: Long), painterResource(drawableResId: Long) etc. are only available on the Android platform (as they access Android resources).

Otherwise, so that the library itself is multiplatform and not only uses a multiplatform library as a dependency, it itself needs to be set up like one, i.e. with the directly structure like src/commonMain, src/androidMain etc. and the correct gradle configuration.

I recently migrated a smallish Java library to a Kotlin Multiplatform library (nothing with Compose though). Maybe this can help:

Jacob and I have put a lot of work into getting camera stuff correct, as this is a HUGE pain in every similar UI framework (same on iOS, where we are developing a similar wrapper for SwiftUI).

Interesting, I would think that the easiest approach would be to ... uh ... basically don't worry about camera animations at all but leave that up to Compose. I.e. just expose the camera position on the API and users would just use the usual Compose stuff for animations. Or is even that a PITA? (I am somewhat of a newbie with Compose, so I only have a very rough idea how that would look like.)

westnordost commented 1 month ago

Anyway, there is talk about a call - I'd like to join too. Did someone mention a date or a doodle for date-finding? If not, @ianthetechie would you mind setting this up? You two seem to be the ones that advanced the most from what I read here.

ydrea commented 1 month ago

+1 on the call initiative!

SebastianAigner commented 3 weeks ago

Hi! Seb from JetBrains / Compose Multiplatform here. Would be awesome to have MapLibre available for Compose Multiplatform apps on iOS and Android (or even beyond!) – Let us know if there is something we can help with or if there's any questions that come up during your discussions – happy to connect!

ianthetechie commented 3 weeks ago

I've created a Doodle here so we can all get on a call for an hour to discuss :) https://doodle.com/meeting/participate/id/b44RqJ7b

See you soon!

boldtrn commented 2 weeks ago

Thanks for organising this. I'd be interested in joining too, if we can find a good slot 😺

westnordost commented 2 days ago

By the way, there is another. When one searches for MapLibre Compose on DuckDuckGo, one will find this: https://github.com/dellisd/maplibre-compose

It's a bit older, but just yesterday, the guy added new commits.

So, to summarize, there are now: