AppNavigator.openMap() now works on iOS
Also implemented currently unused AppNavigator.openWalkingDirections()
This commit is contained in:
@@ -1,7 +1,49 @@
|
||||
@file:OptIn(ExperimentalForeignApi::class)
|
||||
|
||||
package app.klottr.platform
|
||||
|
||||
import platform.Foundation.NSURL
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import kotlinx.cinterop.useContents
|
||||
import platform.Foundation.NSURL
|
||||
import platform.UIKit.UIApplication
|
||||
import platform.Foundation.NSURLComponents
|
||||
import platform.Foundation.NSURLQueryItem
|
||||
import platform.darwin.dispatch_async
|
||||
import platform.darwin.dispatch_get_main_queue
|
||||
import platform.Foundation.*
|
||||
|
||||
private fun urlEncode(query: String): String {
|
||||
// Percent-encode for use in URL query
|
||||
val encoded = (query as NSString)
|
||||
.stringByAddingPercentEncodingWithAllowedCharacters(
|
||||
NSCharacterSet.URLQueryAllowedCharacterSet()
|
||||
)
|
||||
return encoded ?: query
|
||||
}
|
||||
|
||||
|
||||
private fun isAtLeast(major: Int, minor: Int = 0, patch: Int = 0): Boolean {
|
||||
val current = NSProcessInfo.processInfo.operatingSystemVersion
|
||||
return current.useContents {
|
||||
when {
|
||||
this.majorVersion > major -> true
|
||||
this.majorVersion < major -> false
|
||||
this.minorVersion > minor -> true
|
||||
this.minorVersion < minor -> false
|
||||
else -> this.patchVersion >= patch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openUrlOnMain(url: NSURL) {
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
UIApplication.sharedApplication.openURL(
|
||||
url,
|
||||
options = emptyMap<Any?, Any?>(),
|
||||
completionHandler = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
actual object AppNavigator {
|
||||
actual fun openUrl(url: String) {
|
||||
@@ -10,13 +52,35 @@ actual object AppNavigator {
|
||||
}
|
||||
actual fun openMap(lat: Double, lon: Double, label: String?) {
|
||||
// Use Apple Maps URL scheme
|
||||
val encoded = label?.let { it } ?: "Place"
|
||||
val url = "http://maps.apple.com/?ll=$lat,$lon&q=$encoded"
|
||||
openUrl(url)
|
||||
// This always opens apple maps, regardless of what navigation app you've set in system settings.
|
||||
// There seems to be no way around that without implementing your own chooser.
|
||||
val comps = NSURLComponents(string = "maps://")
|
||||
comps.path = "/"
|
||||
comps.queryItems = listOf(
|
||||
NSURLQueryItem(name = "ll", value = "$lat,$lon"),
|
||||
NSURLQueryItem(name = "q", value = label ?: "Place")
|
||||
)
|
||||
val nsUrl = comps.URL ?: return
|
||||
openUrlOnMain(nsUrl)
|
||||
}
|
||||
|
||||
actual fun openWalkingDirections(lat: Double?, lon: Double?, title: String?) {
|
||||
//TODO: Implement
|
||||
// On iOS 18.4+ there is a "default navigation app" setting in EU countries.
|
||||
// This implementation makes sure to use it if available
|
||||
|
||||
// Build a destination string. You can replace this with a full address if you have one.
|
||||
val destination = "$lat,$lon"
|
||||
val encoded = urlEncode(destination)
|
||||
|
||||
val urlString = if (isAtLeast(18, 4, 0)) {
|
||||
// iOS routes this to the user's chosen default navigation app
|
||||
"geo-navigation:///directions?destination=$encoded"
|
||||
} else {
|
||||
// Apple Maps fallback: driving directions to destination
|
||||
"maps://?daddr=$encoded&dirflg=d"
|
||||
}
|
||||
|
||||
openUrlOnMain((NSURL(string = urlString)))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user