From 28aa9befbf7c49786e43f5e7bf2c11d382ac6592 Mon Sep 17 00:00:00 2001 From: kaytran2992 Date: Wed, 27 Nov 2024 12:32:40 +0700 Subject: [PATCH 1/2] Update my location state, draw markers --- gradle/libs.versions.toml | 2 + lib-compose/build.gradle.kts | 1 + .../compose/maps/W3WMapComponent.kt | 25 ++- .../components/compose/maps/W3WMapDefaults.kt | 7 + .../components/compose/maps/W3WMapManager.kt | 52 ++++-- .../maps/extensions/DomainExtensions.kt | 26 +-- .../compose/maps/mapper/DomainToUiModel.kt | 14 ++ .../compose/maps/mapper/GoogleMapConverter.kt | 10 +- .../compose/maps/mapper/MapBoxConverter.kt | 2 +- .../compose/maps/models/W3WCameraPosition.kt | 4 +- .../compose/maps/models/W3WGridLines.kt | 10 +- .../compose/maps/models/W3WLatLng.kt | 6 + .../compose/maps/models/W3WMarker.kt | 5 +- .../compose/maps/models/W3WSquare.kt | 6 + .../maps/providers/googlemap/W3WGoogleMap.kt | 4 +- .../providers/googlemap/W3WGoogleMapDrawer.kt | 155 ++++++++++-------- .../maps/providers/mapbox/W3WMapBoxDrawers.kt | 13 +- .../compose/maps/state/W3WMapState.kt | 41 +++-- .../maps/state/camera/W3WCameraState.kt | 7 + .../maps/state/camera/W3WGoogleCameraState.kt | 15 ++ .../maps/state/camera/W3WMapboxCameraState.kt | 16 ++ 21 files changed, 282 insertions(+), 139 deletions(-) create mode 100644 lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/DomainToUiModel.kt create mode 100644 lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WLatLng.kt create mode 100644 lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WSquare.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fe9e5a24..9a200338 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ #Android accompanistPermissions = "0.34.0" glide = "4.15.1" +kotlinxCollectionsImmutable = "0.3.5" minSdk = "24" compileSdk = "34" compose-compiler = "1.4.6" @@ -53,6 +54,7 @@ dokka = "1.5.0" #Kotlin accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" } glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } +kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinxCollectionsImmutable" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTest" } diff --git a/lib-compose/build.gradle.kts b/lib-compose/build.gradle.kts index 1caaeae6..12003d5f 100644 --- a/lib-compose/build.gradle.kts +++ b/lib-compose/build.gradle.kts @@ -80,6 +80,7 @@ dependencies { implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.android) testImplementation(libs.kotlinx.coroutines.test) + implementation(libs.kotlinx.collections.immutable) implementation(libs.glide) diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt index 136ffb2e..9302a49d 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt @@ -7,7 +7,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.google.accompanist.permissions.ExperimentalPermissionsApi @@ -15,6 +17,7 @@ import com.google.accompanist.permissions.rememberMultiplePermissionsState import com.what3words.components.compose.maps.buttons.W3WMapButtons import com.what3words.components.compose.maps.models.W3WLocationSource import com.what3words.components.compose.maps.models.W3WMapType +import com.what3words.components.compose.maps.models.W3WMarker import com.what3words.components.compose.maps.providers.googlemap.W3WGoogleMap import com.what3words.components.compose.maps.providers.mapbox.W3WMapBox import com.what3words.components.compose.maps.state.W3WButtonsState @@ -57,6 +60,14 @@ fun W3WMapComponent( val buttonState by mapManager.buttonState.collectAsState() val coroutineScope = rememberCoroutineScope { Dispatchers.IO } + val onMarkerClicked = remember(mapManager) { + { marker: W3WMarker -> + mapManager.setSelectedMarker(marker) + } + } + + val currentOnMarkerClicked by rememberUpdatedState(onMarkerClicked) + W3WMapContent( modifier = modifier, layoutConfig = layoutConfig, @@ -83,6 +94,7 @@ fun W3WMapComponent( coroutineScope = coroutineScope ) }, + onMarkerClicked = currentOnMarkerClicked, onError = onError ) } @@ -114,6 +126,7 @@ fun W3WMapComponent( buttonState: W3WButtonsState, mapProvider: MapProvider, content: (@Composable () -> Unit)? = null, + onMarkerClicked: ((W3WMarker) -> Unit)? = null, onMapTypeClicked: ((W3WMapType) -> Unit)? = null, onMyLocationClicked: (() -> Unit)? = null, onMapClicked: ((W3WCoordinates) -> Unit)? = null, @@ -140,6 +153,9 @@ fun W3WMapComponent( onCameraUpdated = { onCameraUpdated.invoke(it) }, + onMarkerClicked = { + onMarkerClicked?.invoke(it) + }, onError = onError ) } @@ -172,6 +188,7 @@ internal fun W3WMapContent( buttonState: W3WButtonsState, mapProvider: MapProvider, content: (@Composable () -> Unit)? = null, + onMarkerClicked: ((W3WMarker) -> Unit), onMapTypeClicked: ((W3WMapType) -> Unit), onMyLocationClicked: () -> Unit, onMapClicked: (W3WCoordinates) -> Unit, @@ -195,6 +212,7 @@ internal fun W3WMapContent( mapConfig = mapConfig, mapProvider = mapProvider, mapState = mapState, + onMarkerClicked = onMarkerClicked, onMapClicked = onMapClicked, content = content, onCameraUpdated = { @@ -287,6 +305,7 @@ internal fun W3WMapView( mapProvider: MapProvider, mapState: W3WMapState, content: (@Composable () -> Unit)? = null, + onMarkerClicked: ((W3WMarker) -> Unit), onMapClicked: ((W3WCoordinates) -> Unit), onCameraUpdated: (W3WCameraState<*>) -> Unit ) { @@ -298,6 +317,7 @@ internal fun W3WMapView( mapConfig = mapConfig, state = mapState, onMapClicked = onMapClicked, + onMarkerClicked = onMarkerClicked, content = content, onCameraUpdated = { onCameraUpdated.invoke(it) @@ -340,10 +360,7 @@ private fun fetchCurrentLocation( val location = it.fetchLocation() // Update camera state withContext(Main) { - mapManager.moveToPosition( - coordinates = W3WCoordinates(location.latitude, location.longitude), - animate = true - ) + mapManager.moveToMyLocation(W3WCoordinates(location.latitude, location.longitude)) } if (location.hasAccuracy()) { diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt index d2bc1b4e..8ce77882 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt @@ -6,6 +6,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.what3words.components.compose.maps.models.DarkModeStyle +import com.what3words.components.compose.maps.models.W3WCameraPosition +import com.what3words.components.compose.maps.models.W3WLatLng +import com.what3words.components.compose.maps.models.W3WMarkerColor enum class MapProvider { GOOGLE_MAP, @@ -19,6 +22,10 @@ enum class MapProvider { * including map configuration, grid lines, layout, and buttons. */ object W3WMapDefaults { + val LOCATION_DEFAULT = W3WLatLng(51.521251, -0.203586) + val CAMERA_POSITION_DEFAULT = W3WCameraPosition(LOCATION_DEFAULT, 19f, 0f, 0f) + val MAKER_COLOR_DEFAULT = W3WMarkerColor(background = Color.Red, slash = Color.White) + val MUlTI_MAKERS_COLOR_DEFAULT = W3WMarkerColor(background = Color.Blue, slash = Color.White) /** * Data class representing the configuration for the map. diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt index 28c36fcb..09ad1295 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt @@ -2,7 +2,6 @@ package com.what3words.components.compose.maps import android.annotation.SuppressLint import androidx.annotation.RequiresPermission -import androidx.compose.ui.graphics.Color import androidx.core.util.Consumer import com.google.maps.android.compose.CameraPositionState import com.mapbox.geojson.Point @@ -10,10 +9,14 @@ import com.mapbox.maps.CameraState import com.mapbox.maps.EdgeInsets import com.mapbox.maps.extension.compose.animation.viewport.MapViewportState import com.what3words.androidwrapper.datasource.text.api.error.BadBoundingBoxTooBigError +import com.what3words.components.compose.maps.W3WMapDefaults.CAMERA_POSITION_DEFAULT +import com.what3words.components.compose.maps.W3WMapDefaults.LOCATION_DEFAULT +import com.what3words.components.compose.maps.W3WMapDefaults.MAKER_COLOR_DEFAULT import com.what3words.components.compose.maps.extensions.computeHorizontalLines import com.what3words.components.compose.maps.extensions.computeVerticalLines import com.what3words.components.compose.maps.mapper.toGoogleCameraPosition -import com.what3words.components.compose.maps.models.W3WCameraPosition +import com.what3words.components.compose.maps.mapper.toW3WLatLong +import com.what3words.components.compose.maps.mapper.toW3WSquare import com.what3words.components.compose.maps.models.W3WGridLines import com.what3words.components.compose.maps.models.W3WMapType import com.what3words.components.compose.maps.models.W3WMarker @@ -80,8 +83,8 @@ class W3WMapManager( MapViewportState( initialCameraState = CameraState( Point.fromLngLat( - CAMERA_POSITION_DEFAULT.coordinates.lng, - CAMERA_POSITION_DEFAULT.coordinates.lat + CAMERA_POSITION_DEFAULT.latLng.lng, + CAMERA_POSITION_DEFAULT.latLng.lat ), EdgeInsets(0.0, 0.0, 0.0, 0.0), CAMERA_POSITION_DEFAULT.zoom.toDouble(), @@ -174,6 +177,10 @@ class W3WMapManager( mapState.value.cameraState?.moveToPosition(coordinates, animate) } + fun moveToMyLocation(coordinates: W3WCoordinates) { + mapState.value.cameraState?.moveToMyLocation(coordinates) + } + fun updateCameraState(newCameraState: W3WCameraState<*>) { CoroutineScope(Dispatchers.IO).launch { val newGridLine = calculateGridPolylines(newCameraState) @@ -188,8 +195,14 @@ class W3WMapManager( //endregion //region Selected Address - fun getSelectedMarker(): W3WAddress? { - return mapState.value.selectedAddress?.address + fun setSelectedMarker(marker: W3WMarker) { + _mapState.value = mapState.value.copy( + selectedAddress = marker + ) + } + + fun getSelectedMarker(): W3WMarker? { + return mapState.value.selectedAddress } fun unselect() { @@ -215,7 +228,12 @@ class W3WMapManager( when (val c23wa = textDataSource.convertToCoordinates(words)) { is W3WResult.Success -> { _mapState.value = mapState.value.addOrUpdateMarker( - marker = W3WMarker(address = c23wa.value, color = markerColor) + marker = W3WMarker( + words = c23wa.value.words, + square = c23wa.value.square?.toW3WSquare(), + latLng = c23wa.value.center?.toW3WLatLong() ?: LOCATION_DEFAULT, + color = markerColor + ) ) onSuccess?.accept(c23wa.value) } @@ -249,7 +267,12 @@ class W3WMapManager( when (val c23wa = textDataSource.convertTo3wa(coordinates, language)) { is W3WResult.Success -> { _mapState.value = mapState.value.addOrUpdateMarker( - marker = W3WMarker(address = c23wa.value, color = markerColor) + marker = W3WMarker( + words = c23wa.value.words, + square = c23wa.value.square?.toW3WSquare(), + latLng = c23wa.value.center?.toW3WLatLong() ?: LOCATION_DEFAULT, + color = markerColor + ) ) onSuccess?.accept(c23wa.value) } @@ -272,7 +295,12 @@ class W3WMapManager( when (val c23wa = textDataSource.convertTo3wa(coordinates, language)) { is W3WResult.Success -> { _mapState.value = mapState.value.copy( - selectedAddress = W3WMarker(address = c23wa.value, color = MAKER_COLOR_DEFAULT) + selectedAddress = W3WMarker( + words = c23wa.value.words, + square = c23wa.value.square?.toW3WSquare(), + latLng = c23wa.value.center?.toW3WLatLong() ?: LOCATION_DEFAULT, + color = MAKER_COLOR_DEFAULT + ) ) onSuccess?.accept(c23wa.value) } @@ -320,10 +348,4 @@ class W3WMapManager( it.copy(isLocationActive = isActive) } } - - companion object { - val CAMERA_POSITION_DEFAULT = - W3WCameraPosition(W3WCoordinates(51.521251, -0.203586), 19f, 0f, 0f) - val MAKER_COLOR_DEFAULT = W3WMarkerColor(background = Color.Red, slash = Color.Yellow) - } } \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/extensions/DomainExtensions.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/extensions/DomainExtensions.kt index e2d4c27f..8fb4b3b2 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/extensions/DomainExtensions.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/extensions/DomainExtensions.kt @@ -2,6 +2,8 @@ package com.what3words.components.compose.maps.extensions import com.google.maps.android.collections.PolylineManager import com.what3words.androidwrapper.What3WordsAndroidWrapper +import com.what3words.components.compose.maps.mapper.toW3WLatLong +import com.what3words.components.compose.maps.models.W3WLatLng import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.core.types.geometry.W3WLine import com.what3words.core.types.geometry.W3WRectangle @@ -52,9 +54,9 @@ fun Long.toCoordinates(): W3WCoordinates { * | | | * 2-----3 6 .. */ -internal fun List.computeVerticalLines(): List { +internal fun List.computeVerticalLines(): List { val computedVerticalLines = - mutableListOf() + mutableListOf() // all vertical lines val verticalLines = mutableListOf() @@ -64,11 +66,11 @@ internal fun List.computeVerticalLines(): List { while (verticalLines.isNotEmpty()) { verticalLines.maxByOrNull { it.start.lat }?.let { topLeftGrid -> if (t % 2 == 0) { - computedVerticalLines.add(topLeftGrid.start) - computedVerticalLines.add(topLeftGrid.end) + computedVerticalLines.add(topLeftGrid.start.toW3WLatLong()) + computedVerticalLines.add(topLeftGrid.end.toW3WLatLong()) } else { - computedVerticalLines.add(topLeftGrid.end) - computedVerticalLines.add(topLeftGrid.start) + computedVerticalLines.add(topLeftGrid.end.toW3WLatLong()) + computedVerticalLines.add(topLeftGrid.start.toW3WLatLong()) } verticalLines.remove(topLeftGrid) } @@ -92,9 +94,9 @@ internal fun List.computeVerticalLines(): List { * | * E-----F */ -internal fun List.computeHorizontalLines(): List { +internal fun List.computeHorizontalLines(): List { val computedHorizontalLines = - mutableListOf() + mutableListOf() // all horizontal lines val horizontalLines = mutableListOf() @@ -104,11 +106,11 @@ internal fun List.computeHorizontalLines(): List { while (horizontalLines.isNotEmpty()) { horizontalLines.minByOrNull { it.start.lng }?.let { topLeftGrid -> if (t % 2 == 0) { - computedHorizontalLines.add(topLeftGrid.start) - computedHorizontalLines.add(topLeftGrid.end) + computedHorizontalLines.add(topLeftGrid.start.toW3WLatLong()) + computedHorizontalLines.add(topLeftGrid.end.toW3WLatLong()) } else { - computedHorizontalLines.add(topLeftGrid.end) - computedHorizontalLines.add(topLeftGrid.start) + computedHorizontalLines.add(topLeftGrid.end.toW3WLatLong()) + computedHorizontalLines.add(topLeftGrid.start.toW3WLatLong()) } horizontalLines.remove(topLeftGrid) t += 1 diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/DomainToUiModel.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/DomainToUiModel.kt new file mode 100644 index 00000000..fb85d582 --- /dev/null +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/DomainToUiModel.kt @@ -0,0 +1,14 @@ +package com.what3words.components.compose.maps.mapper + +import com.what3words.components.compose.maps.models.W3WLatLng +import com.what3words.components.compose.maps.models.W3WSquare +import com.what3words.core.types.geometry.W3WCoordinates +import com.what3words.core.types.geometry.W3WRectangle + +fun W3WRectangle.toW3WSquare(): W3WSquare { + return W3WSquare(this.southwest.toW3WLatLong(), this.northeast.toW3WLatLong()) +} + +fun W3WCoordinates.toW3WLatLong(): W3WLatLng { + return W3WLatLng(this.lat, this.lng) +} \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt index 8a06fa3d..2d514ad1 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt @@ -4,17 +4,13 @@ import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.MapType import com.what3words.components.compose.maps.models.W3WCameraPosition +import com.what3words.components.compose.maps.models.W3WLatLng import com.what3words.components.compose.maps.models.W3WMapType -import com.what3words.core.types.geometry.W3WCoordinates -fun W3WCoordinates.toGoogleLatLng(): LatLng { +fun W3WLatLng.toGoogleLatLng(): LatLng { return LatLng(this.lat, this.lng) } -fun LatLng.toW3WCoordinates(): W3WCoordinates { - return W3WCoordinates(this.latitude, this.longitude) -} - fun W3WMapType.toGoogleMapType(): MapType { return when (this) { W3WMapType.NORMAL -> MapType.NORMAL @@ -26,7 +22,7 @@ fun W3WMapType.toGoogleMapType(): MapType { fun W3WCameraPosition.toGoogleCameraPosition(): CameraPosition { return CameraPosition( - this.coordinates.toGoogleLatLng(), + this.latLng.toGoogleLatLng(), this.zoom, this.tilt, this.bearing diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt index 5e8cf8d7..50c0494e 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt @@ -19,7 +19,7 @@ fun W3WCameraPosition.toMapBoxCameraOptions(): CameraOptions { return CameraOptions.Builder() .pitch(this.tilt.toDouble()) .bearing(this.bearing.toDouble()) - .center(Point.fromLngLat(this.coordinates.lng, this.coordinates.lat)) + .center(Point.fromLngLat(this.latLng.lng, this.latLng.lat)) .zoom(this.zoom.toDouble()) .build() } \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt index cca622ea..8e9d0d01 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt @@ -1,9 +1,7 @@ package com.what3words.components.compose.maps.models -import com.what3words.core.types.geometry.W3WCoordinates - data class W3WCameraPosition( - val coordinates: W3WCoordinates, + val latLng: W3WLatLng, val zoom: Float, val bearing: Float, val tilt: Float diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WGridLines.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WGridLines.kt index eed254b7..6ec8b7ce 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WGridLines.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WGridLines.kt @@ -1,17 +1,15 @@ package com.what3words.components.compose.maps.models -import com.what3words.core.types.geometry.W3WCoordinates - /** * Data class representing the grid lines displayed on a What3Words (W3W) map. * * This class holds the coordinates for the vertical and horizontal lines that * form the grid overlay on the map, visually representing the W3W squares. * - * @property verticalLines A list of [W3WCoordinates] representing the vertical grid lines. Defaults to an empty list. - * @property horizontalLines A list of [W3WCoordinates] representing the horizontal grid lines. Defaults to an empty list. + * @property verticalLines A list of [W3WLatLng] representing the vertical grid lines. Defaults to an empty list. + * @property horizontalLines A list of [W3WLatLng] representing the horizontal grid lines. Defaults to an empty list. */ data class W3WGridLines( - val verticalLines: List = emptyList(), - val horizontalLines: List = emptyList() + val verticalLines: List = emptyList(), + val horizontalLines: List = emptyList() ) \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WLatLng.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WLatLng.kt new file mode 100644 index 00000000..e6d13e5a --- /dev/null +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WLatLng.kt @@ -0,0 +1,6 @@ +package com.what3words.components.compose.maps.models + +data class W3WLatLng( + val lat: Double, + val lng: Double +) \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WMarker.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WMarker.kt index e2cf4fff..ec9d3ece 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WMarker.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WMarker.kt @@ -1,10 +1,11 @@ package com.what3words.components.compose.maps.models import androidx.compose.ui.graphics.Color -import com.what3words.core.types.domain.W3WAddress data class W3WMarker( - val address: W3WAddress, + val words: String, + val latLng: W3WLatLng, + val square: W3WSquare? = null, val color: W3WMarkerColor? = null, val title: String? = null, val snippet: String? = null diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WSquare.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WSquare.kt new file mode 100644 index 00000000..5c98c530 --- /dev/null +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WSquare.kt @@ -0,0 +1,6 @@ +package com.what3words.components.compose.maps.models + +data class W3WSquare( + val southwest: W3WLatLng, + val northeast: W3WLatLng +) \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMap.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMap.kt index 0e9f46cf..0dc3db04 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMap.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMap.kt @@ -17,6 +17,7 @@ import com.google.maps.android.compose.MapProperties import com.google.maps.android.compose.MapUiSettings import com.what3words.components.compose.maps.W3WMapDefaults import com.what3words.components.compose.maps.mapper.toGoogleMapType +import com.what3words.components.compose.maps.models.W3WMarker import com.what3words.components.compose.maps.state.W3WMapState import com.what3words.components.compose.maps.state.camera.W3WCameraState import com.what3words.components.compose.maps.state.camera.W3WGoogleCameraState @@ -50,6 +51,7 @@ fun W3WGoogleMap( mapConfig: W3WMapDefaults.MapConfig, state: W3WMapState, content: (@Composable () -> Unit)? = null, + onMarkerClicked: (W3WMarker) -> Unit, onMapClicked: (W3WCoordinates) -> Unit, onCameraUpdated: (W3WCameraState<*>) -> Unit ) { @@ -111,7 +113,7 @@ fun W3WGoogleMap( onMapClicked.invoke(W3WCoordinates(it.latitude, it.longitude)) }, ) { - W3WGoogleMapDrawer(state = state, mapConfig) + W3WGoogleMapDrawer(state = state, mapConfig, onMarkerClicked) content?.invoke() } } diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt index 37f8fdc7..be29dbdf 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt @@ -4,25 +4,26 @@ import android.content.Context import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateMapOf -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import com.google.android.gms.maps.model.BitmapDescriptor import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.LatLng -import com.google.maps.android.compose.CameraPositionState import com.google.maps.android.compose.GoogleMapComposable import com.google.maps.android.compose.Marker import com.google.maps.android.compose.Polyline import com.google.maps.android.compose.rememberMarkerState import com.what3words.components.compose.maps.W3WMapDefaults +import com.what3words.components.compose.maps.W3WMapDefaults.MAKER_COLOR_DEFAULT +import com.what3words.components.compose.maps.W3WMapDefaults.MUlTI_MAKERS_COLOR_DEFAULT +import com.what3words.components.compose.maps.mapper.toGoogleLatLng +import com.what3words.components.compose.maps.models.W3WLatLng import com.what3words.components.compose.maps.models.W3WMarker -import com.what3words.components.compose.maps.models.W3WMarkerColor import com.what3words.components.compose.maps.state.W3WListMarker import com.what3words.components.compose.maps.state.W3WMapState import com.what3words.components.compose.maps.state.isExistInOtherList @@ -30,6 +31,7 @@ import com.what3words.components.compose.maps.utils.getMarkerBitmap import com.what3words.components.compose.maps.utils.getPin import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.map.components.compose.R +import kotlinx.collections.immutable.ImmutableMap /** * A composable function that draws What3Words component support: @@ -43,7 +45,8 @@ import com.what3words.map.components.compose.R @GoogleMapComposable fun W3WGoogleMapDrawer( state: W3WMapState, - mapConfig: W3WMapDefaults.MapConfig + mapConfig: W3WMapDefaults.MapConfig, + onMarkerClicked: (W3WMarker) -> Unit ) { state.cameraState?.let { cameraState -> if (mapConfig.gridLineConfig.isGridEnabled) { @@ -64,22 +67,24 @@ fun W3WGoogleMapDrawer( selectedMarker = state.selectedAddress ) } - } - //Draw the markers -// W3WGoogleMapDrawMarkers( -// cameraState = state.cameraState?.cameraState as CameraPositionState, -// state.listMakers -// ) + //Draw the markers + W3WGoogleMapDrawMarkers( + zoomLevel = cameraState.getZoomLevel(), + zoomSwitchLevel = mapConfig.gridLineConfig.zoomSwitchLevel, + listMakers = state.listMakers, + onMarkerClicked = onMarkerClicked + ) + } } @Composable @GoogleMapComposable fun W3WGoogleMapDrawGridLines( - verticalLines: List, - horizontalLines: List, + verticalLines: List, + horizontalLines: List, zoomLevel: Float, gridLinesConfig: W3WMapDefaults.GridLinesConfig, ) { @@ -132,25 +137,19 @@ fun W3WGoogleMapDrawSelectedAddress( @GoogleMapComposable private fun DrawZoomOutSelectedMarker(selectedMarker: W3WMarker) { val context = LocalContext.current + val density = LocalDensity.current.density + val markerState = rememberMarkerState( - position = LatLng( - selectedMarker.address.center!!.lat, - selectedMarker.address.center!!.lng - ) + position = selectedMarker.latLng.toGoogleLatLng() ) - LaunchedEffect(selectedMarker.address) { - markerState.position = - LatLng(selectedMarker.address.center!!.lat, selectedMarker.address.center!!.lng) - } - val density = LocalDensity.current.density - var icon by remember { mutableStateOf(null) } + LaunchedEffect(selectedMarker.latLng) { + markerState.position = selectedMarker.latLng.toGoogleLatLng() + } - LaunchedEffect(key1 = Unit) { - icon = selectedMarker.color?.let { - BitmapDescriptorFactory.fromBitmap(getMarkerBitmap(context, density, it)) - } + val icon = remember(selectedMarker.color) { + BitmapDescriptorFactory.fromBitmap(getMarkerBitmap(context, density, selectedMarker.color?: MAKER_COLOR_DEFAULT)) } Marker( @@ -167,7 +166,7 @@ private fun DrawZoomInSelectedMarker( zoomSwitchLevel: Float ) { val context = LocalContext.current - selectedMarker.address.square?.let { square -> + selectedMarker.square?.let { square -> Polyline( points = listOf( LatLng( @@ -207,67 +206,91 @@ private fun DrawZoomInSelectedMarker( @Composable @GoogleMapComposable fun W3WGoogleMapDrawMarkers( - cameraState: CameraPositionState, - listMakers: Map, + zoomLevel: Float, + zoomSwitchLevel: Float, + listMakers: ImmutableMap, + onMarkerClicked: (W3WMarker) -> Unit +) { + if (zoomLevel < zoomSwitchLevel) { + DrawZoomOutMarkers( + listMakers = listMakers, + onMarkerClicked = onMarkerClicked + ) + } else { + DrawZoomInMarkers( + listMakers = listMakers, + onMarkerClicked = onMarkerClicked + ) + } +} + +@Composable +fun DrawZoomInMarkers( + listMakers: ImmutableMap, onMarkerClicked: ((W3WMarker) -> Unit)? = null, +) { + //TODO: GroundOverlay for list markers bitmap square +} + +@Composable +fun DrawZoomOutMarkers( + listMakers: ImmutableMap, + onMarkerClicked: (W3WMarker) -> Unit ) { val context = LocalContext.current val density = LocalDensity.current.density - val icons = rememberMarkerIcons(listMakers, context, density) - val zoomLevel = remember { - mutableFloatStateOf(cameraState.position.zoom) - } - LaunchedEffect(key1 = cameraState.position.zoom) { - zoomLevel.floatValue = cameraState.position.zoom - } + val currentOnMarkerClicked by rememberUpdatedState(onMarkerClicked) listMakers.forEach { (_, listMarker) -> listMarker.markers.forEach { marker -> - val icon = icons[marker.address.words] - val position = LatLng(marker.address.center!!.lat, marker.address.center!!.lng) - - Marker( - state = rememberMarkerState(position = position), - icon = icon, - onClick = { - onMarkerClicked?.invoke(marker) - true - }, - title = marker.title, - snippet = marker.snippet - ) + key(marker.words) { + val icon = icons[marker.words] + Marker( + state = rememberMarkerState(position = marker.latLng.toGoogleLatLng()), + icon = icon, + onClick = { + currentOnMarkerClicked(marker) + true + }, + title = marker.title, + snippet = marker.snippet + ) + } } } } - @Composable fun rememberMarkerIcons( listMakers: Map, context: Context, density: Float ): Map { + // Use rememberUpdatedState to hold the latest value of listMakers without triggering recomposition + val latestListMakers = rememberUpdatedState(listMakers) + + // Remember the icon map so that it persists across recompositions val icons = remember { mutableStateMapOf() } - // LaunchedEffect with a stable key (listMakers) - LaunchedEffect(key1 = listMakers) { - listMakers.forEach { (listId, listMarker) -> + // Use LaunchedEffect with listMakers as a key to load icons only when listMakers change + LaunchedEffect(key1 = latestListMakers.value.size) { + // Iterate over the listMakers and generate icons if not already cached + latestListMakers.value.forEach { (listId, listMarker) -> listMarker.markers.forEach { marker -> - val color = if (isExistInOtherList(listId, marker, listMakers)) { - W3WMarkerColor(Color.Blue, Color.White) - } else { - listMarker.listColor ?: marker.color ?: W3WMarkerColor( - Color.Red, - Color.White - ) - } + // Check if the icon for this marker already exists + if (icons[marker.words] == null) { + // Determine the marker's color based on conditions + val color = if (isExistInOtherList(listId, marker, latestListMakers.value)) { + MUlTI_MAKERS_COLOR_DEFAULT + } else { + listMarker.listColor ?: marker.color ?: MAKER_COLOR_DEFAULT + } - // Load the icon for the marker if not already loaded - if (icons[marker.address.words] == null) { + // Generate the icon and store it in the icons map val iconBitmap = getPin(context, color = color, density = density) - icons[marker.address.words] = iconBitmap?.let { + icons[marker.words] = iconBitmap?.let { BitmapDescriptorFactory.fromBitmap(it) } } diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt index 29eaab05..ca320fbb 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt @@ -14,6 +14,7 @@ import com.mapbox.maps.extension.compose.annotation.generated.PointAnnotation import com.mapbox.maps.extension.compose.annotation.generated.PolylineAnnotation import com.mapbox.maps.extension.compose.annotation.rememberIconImage import com.what3words.components.compose.maps.W3WMapDefaults +import com.what3words.components.compose.maps.models.W3WLatLng import com.what3words.components.compose.maps.models.W3WMarker import com.what3words.components.compose.maps.state.W3WListMarker import com.what3words.components.compose.maps.state.W3WMapState @@ -50,8 +51,8 @@ fun W3WMapBoxDrawer(state: W3WMapState, mapConfig: W3WMapDefaults.MapConfig) { @Composable @MapboxMapComposable fun W3WMapBoxDrawGridLines( - verticalLines: List, - horizontalLines: List, + verticalLines: List, + horizontalLines: List, gridColor: Color, gridLineWidth: Dp, ) { @@ -103,7 +104,7 @@ private fun DrawZoomOutSelectedMarker(selectedMarker: W3WMarker) { val density = LocalDensity.current.density val marker = rememberIconImage( - key = selectedMarker.address.words, + key = selectedMarker.words, painter = BitmapPainter( getMarkerBitmap(context, density, selectedMarker.color!!).asImageBitmap() ) @@ -111,8 +112,8 @@ private fun DrawZoomOutSelectedMarker(selectedMarker: W3WMarker) { PointAnnotation( point = Point.fromLngLat( - selectedMarker.address.center!!.lng, - selectedMarker.address.center!!.lat + selectedMarker.latLng.lng, + selectedMarker.latLng.lat ) ) { iconImage = marker @@ -127,7 +128,7 @@ private fun DrawZoomInSelectedMarker( zoomSwitchLevel: Float ) { val context = LocalContext.current - selectedMarker.address.square?.let { square -> + selectedMarker.square?.let { square -> PolylineAnnotation( points = listOf( Point.fromLngLat(square.southwest.lng, square.northeast.lat), diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/W3WMapState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/W3WMapState.kt index e2ca8a98..18cd304d 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/W3WMapState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/W3WMapState.kt @@ -1,11 +1,18 @@ package com.what3words.components.compose.maps.state +import androidx.compose.runtime.Immutable import com.what3words.components.compose.maps.models.W3WGridLines import com.what3words.components.compose.maps.models.W3WMapType import com.what3words.components.compose.maps.models.W3WMarker import com.what3words.components.compose.maps.models.W3WMarkerColor import com.what3words.components.compose.maps.state.camera.W3WCameraState import com.what3words.core.types.language.W3WRFC5646Language +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.ImmutableMap +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentMapOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toImmutableMap const val LIST_DEFAULT_ID = "LIST_DEFAULT_ID" @@ -25,6 +32,7 @@ const val LIST_DEFAULT_ID = "LIST_DEFAULT_ID" * @property cameraState The current state of the map's camera. Defaults to `null`. * @property gridLines [W3WGridLines] data class handling draw grid line on map */ +@Immutable data class W3WMapState( val language: W3WRFC5646Language = W3WRFC5646Language.EN_GB, @@ -38,7 +46,7 @@ data class W3WMapState( val selectedAddress: W3WMarker? = null, - val listMakers: Map = emptyMap(), + val listMakers: ImmutableMap = persistentMapOf(), // Control camera position of map internal val cameraState: W3WCameraState<*>? = null, @@ -47,9 +55,10 @@ data class W3WMapState( internal val gridLines: W3WGridLines = W3WGridLines(), ) +@Immutable data class W3WListMarker( val listColor: W3WMarkerColor? = null, - val markers: List = emptyList() + val markers: ImmutableList = persistentListOf() ) fun W3WMapState.addOrUpdateMarker( @@ -64,7 +73,7 @@ fun W3WMapState.addOrUpdateMarker( val currentList = listMakers[key]?.markers?.toMutableList() ?: mutableListOf() // Check if the marker already exists in the list by its address - val existingMarkerIndex = currentList.indexOfFirst { it.address == marker.address } + val existingMarkerIndex = currentList.indexOfFirst { it == marker } if (existingMarkerIndex != -1) { // Marker exists, update it in-place @@ -75,12 +84,12 @@ fun W3WMapState.addOrUpdateMarker( } // Create or update the W3WListMarker in place - val updatedList = W3WListMarker(markers = currentList) + val updatedList = W3WListMarker(markers = currentList.toImmutableList()) // Use a mutable map to update the list in-place return copy(listMakers = listMakers.toMutableMap().apply { this[key] = updatedList - }) + }.toImmutableMap()) } fun W3WMapState.addOrUpdateMarker( @@ -97,7 +106,7 @@ fun W3WMapState.addOrUpdateMarker( // Iterate over the list of new markers to add or update markers.forEach { marker -> // Check if the marker already exists in the list by its address - val existingMarkerIndex = currentList.indexOfFirst { it.address == marker.address } + val existingMarkerIndex = currentList.indexOfFirst { it == marker } if (existingMarkerIndex != -1) { // If the marker exists, update it in place (preserving the rest of the list) @@ -111,13 +120,13 @@ fun W3WMapState.addOrUpdateMarker( // Create a new W3WListMarker with the updated list of markers val updatedListMarker = W3WListMarker( listColor = listColor ?: listMakers[key]?.listColor, // Use the provided listColor, or keep the existing one - markers = currentList + markers = currentList.toImmutableList() ) // Return a new W3WMapState with the updated list of markers return copy(listMakers = listMakers.toMutableMap().apply { this[key] = updatedListMarker // Update the list in the map - }) + }.toImmutableMap()) } fun isExistInOtherList( @@ -128,7 +137,7 @@ fun isExistInOtherList( // Check if the marker exists in any other list besides the one with listId return listMakers.filter { (key, listMarker) -> // Skip the current listId - key != listId && listMarker.markers.any { it.address.words == marker.address.words } + key != listId && listMarker.markers.any { it == marker } }.isNotEmpty() } @@ -151,10 +160,10 @@ fun W3WMapState.setSelectedAddress( } -fun W3WMapState.removeMarkersByList(listId: String): W3WMapState { - return copy(listMakers = listMakers - listId) -} - -fun W3WMapState.removeAllMarkers(): W3WMapState { - return copy(listMakers = emptyMap()) -} \ No newline at end of file +//fun W3WMapState.removeMarkersByList(listId: String): W3WMapState { +// return copy(listMakers = listMakers - listId) +//} +// +//fun W3WMapState.removeAllMarkers(): W3WMapState { +// return copy(listMakers = emptyMap()) +//} \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt index c9f50a78..d846184e 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt @@ -46,4 +46,11 @@ interface W3WCameraState { * @param animate Whether to animate the camera movement. */ fun setCameraPosition(cameraPosition: W3WCameraPosition, animate: Boolean) + + /** + * Moves the camera to the current location. + * + * @param coordinates The W3W coordinates to move the camera to. + */ + fun moveToMyLocation(coordinates: W3WCoordinates) } \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt index a6fd4ce9..15e3ace1 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt @@ -16,6 +16,10 @@ import kotlinx.coroutines.launch class W3WGoogleCameraState(override val cameraState: CameraPositionState) : W3WCameraState { + companion object{ + const val MY_LOCATION_ZOOM = 21f + } + override var gridBound: W3WRectangle? = null override fun orientCamera() { @@ -48,6 +52,17 @@ class W3WGoogleCameraState(override val cameraState: CameraPositionState) : updateCameraPosition(cameraPosition.toGoogleCameraPosition(), animate) } + override fun moveToMyLocation(coordinates: W3WCoordinates) { + updateCameraPosition( + CameraPosition( + LatLng(coordinates.lat, coordinates.lng), + MY_LOCATION_ZOOM, + cameraState.position.tilt, + cameraState.position.bearing + ), true + ) + } + private fun updateCameraPosition(cameraPosition: CameraPosition, animate: Boolean) { CoroutineScope(Dispatchers.Main).launch { if (animate) { diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt index ba21b349..9f350aaa 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt @@ -2,6 +2,7 @@ package com.what3words.components.compose.maps.state.camera import com.mapbox.geojson.Point import com.mapbox.maps.CameraOptions +import com.mapbox.maps.MapConstants.MAX_ZOOM import com.mapbox.maps.extension.compose.animation.viewport.MapViewportState import com.what3words.components.compose.maps.mapper.toMapBoxCameraOptions import com.what3words.components.compose.maps.models.W3WCameraPosition @@ -11,6 +12,10 @@ import com.what3words.core.types.geometry.W3WRectangle class W3WMapboxCameraState(override val cameraState: MapViewportState) : W3WCameraState { + companion object{ + const val MY_LOCATION_ZOOM = MAX_ZOOM + } + override var gridBound: W3WRectangle? = null override fun orientCamera() { @@ -43,6 +48,17 @@ class W3WMapboxCameraState(override val cameraState: MapViewportState) : updateCameraPosition(cameraPosition.toMapBoxCameraOptions(),animate) } + override fun moveToMyLocation(coordinates: W3WCoordinates) { + val cameraOptions = CameraOptions.Builder() + .pitch(cameraState.cameraState?.pitch) + .bearing(cameraState.cameraState?.bearing) + .center(Point.fromLngLat(coordinates.lng, coordinates.lat)) + .zoom(MY_LOCATION_ZOOM) + .build() + + updateCameraPosition(cameraOptions, true) + } + private fun updateCameraPosition(cameraOptions: CameraOptions, animate: Boolean) { if (animate) { cameraState.flyTo( From 294a6bbba09dbebe6259e511c2151533ab2b3430 Mon Sep 17 00:00:00 2001 From: kaytran2992 Date: Fri, 29 Nov 2024 15:21:47 +0700 Subject: [PATCH 2/2] Update support function for camera --- .../compose/maps/W3WMapComponent.kt | 16 +++++++- .../components/compose/maps/W3WMapDefaults.kt | 2 - .../components/compose/maps/W3WMapManager.kt | 41 ++++++++++++------- .../compose/maps/mapper/GoogleMapConverter.kt | 11 ----- .../compose/maps/mapper/MapBoxConverter.kt | 12 ------ .../compose/maps/models/W3WCameraPosition.kt | 8 ---- .../providers/googlemap/W3WGoogleMapDrawer.kt | 1 - .../maps/providers/mapbox/W3WMapBoxDrawers.kt | 1 - .../maps/state/camera/W3WCameraState.kt | 17 ++++---- .../maps/state/camera/W3WGoogleCameraState.kt | 20 ++++----- .../maps/state/camera/W3WMapboxCameraState.kt | 20 ++++----- 11 files changed, 69 insertions(+), 80 deletions(-) delete mode 100644 lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt index 9302a49d..9132024f 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapComponent.kt @@ -23,6 +23,8 @@ import com.what3words.components.compose.maps.providers.mapbox.W3WMapBox import com.what3words.components.compose.maps.state.W3WButtonsState import com.what3words.components.compose.maps.state.W3WMapState import com.what3words.components.compose.maps.state.camera.W3WCameraState +import com.what3words.components.compose.maps.state.camera.W3WGoogleCameraState +import com.what3words.components.compose.maps.state.camera.W3WMapboxCameraState import com.what3words.core.types.common.W3WError import com.what3words.core.types.geometry.W3WCoordinates import kotlinx.coroutines.CoroutineScope @@ -360,7 +362,19 @@ private fun fetchCurrentLocation( val location = it.fetchLocation() // Update camera state withContext(Main) { - mapManager.moveToMyLocation(W3WCoordinates(location.latitude, location.longitude)) + mapManager.moveToPosition( + coordinates = W3WCoordinates(location.latitude,location.longitude), + zoom = when (mapManager.mapProvider) { + MapProvider.GOOGLE_MAP -> { + W3WGoogleCameraState.MY_LOCATION_ZOOM + } + + MapProvider.MAPBOX -> { + W3WMapboxCameraState.MY_LOCATION_ZOOM.toFloat() + } + }, + animate = true + ) } if (location.hasAccuracy()) { diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt index 8ce77882..0fbeab93 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapDefaults.kt @@ -6,7 +6,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.what3words.components.compose.maps.models.DarkModeStyle -import com.what3words.components.compose.maps.models.W3WCameraPosition import com.what3words.components.compose.maps.models.W3WLatLng import com.what3words.components.compose.maps.models.W3WMarkerColor @@ -23,7 +22,6 @@ enum class MapProvider { */ object W3WMapDefaults { val LOCATION_DEFAULT = W3WLatLng(51.521251, -0.203586) - val CAMERA_POSITION_DEFAULT = W3WCameraPosition(LOCATION_DEFAULT, 19f, 0f, 0f) val MAKER_COLOR_DEFAULT = W3WMarkerColor(background = Color.Red, slash = Color.White) val MUlTI_MAKERS_COLOR_DEFAULT = W3WMarkerColor(background = Color.Blue, slash = Color.White) diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt index 09ad1295..4b0ddaec 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/W3WMapManager.kt @@ -3,18 +3,18 @@ package com.what3words.components.compose.maps import android.annotation.SuppressLint import androidx.annotation.RequiresPermission import androidx.core.util.Consumer +import com.google.android.gms.maps.model.CameraPosition import com.google.maps.android.compose.CameraPositionState import com.mapbox.geojson.Point import com.mapbox.maps.CameraState import com.mapbox.maps.EdgeInsets import com.mapbox.maps.extension.compose.animation.viewport.MapViewportState import com.what3words.androidwrapper.datasource.text.api.error.BadBoundingBoxTooBigError -import com.what3words.components.compose.maps.W3WMapDefaults.CAMERA_POSITION_DEFAULT import com.what3words.components.compose.maps.W3WMapDefaults.LOCATION_DEFAULT import com.what3words.components.compose.maps.W3WMapDefaults.MAKER_COLOR_DEFAULT import com.what3words.components.compose.maps.extensions.computeHorizontalLines import com.what3words.components.compose.maps.extensions.computeVerticalLines -import com.what3words.components.compose.maps.mapper.toGoogleCameraPosition +import com.what3words.components.compose.maps.mapper.toGoogleLatLng import com.what3words.components.compose.maps.mapper.toW3WLatLong import com.what3words.components.compose.maps.mapper.toW3WSquare import com.what3words.components.compose.maps.models.W3WGridLines @@ -83,13 +83,13 @@ class W3WMapManager( MapViewportState( initialCameraState = CameraState( Point.fromLngLat( - CAMERA_POSITION_DEFAULT.latLng.lng, - CAMERA_POSITION_DEFAULT.latLng.lat + LOCATION_DEFAULT.lng, + LOCATION_DEFAULT.lat ), EdgeInsets(0.0, 0.0, 0.0, 0.0), - CAMERA_POSITION_DEFAULT.zoom.toDouble(), - CAMERA_POSITION_DEFAULT.bearing.toDouble(), - CAMERA_POSITION_DEFAULT.tilt.toDouble(), + W3WMapboxCameraState.MY_LOCATION_ZOOM, + 0.0, + 0.0 ) ) ) @@ -100,7 +100,12 @@ class W3WMapManager( it.copy( cameraState = W3WGoogleCameraState( CameraPositionState( - position = CAMERA_POSITION_DEFAULT.toGoogleCameraPosition() + position = CameraPosition( + LOCATION_DEFAULT.toGoogleLatLng(), + W3WGoogleCameraState.MY_LOCATION_ZOOM, + 0f, + 0f + ) ) ) ) @@ -173,12 +178,20 @@ class W3WMapManager( mapState.value.cameraState?.orientCamera() } - fun moveToPosition(coordinates: W3WCoordinates, animate: Boolean) { - mapState.value.cameraState?.moveToPosition(coordinates, animate) - } - - fun moveToMyLocation(coordinates: W3WCoordinates) { - mapState.value.cameraState?.moveToMyLocation(coordinates) + fun moveToPosition( + coordinates: W3WCoordinates, + zoom: Float? = null, + bearing: Float? = null, + tilt: Float? = null, + animate: Boolean = false, + ) { + mapState.value.cameraState?.moveToPosition( + coordinates = coordinates, + zoom, + bearing, + tilt, + animate + ) } fun updateCameraState(newCameraState: W3WCameraState<*>) { diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt index 2d514ad1..b463962c 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/GoogleMapConverter.kt @@ -1,9 +1,7 @@ package com.what3words.components.compose.maps.mapper -import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.MapType -import com.what3words.components.compose.maps.models.W3WCameraPosition import com.what3words.components.compose.maps.models.W3WLatLng import com.what3words.components.compose.maps.models.W3WMapType @@ -18,13 +16,4 @@ fun W3WMapType.toGoogleMapType(): MapType { W3WMapType.HYBRID -> MapType.HYBRID W3WMapType.TERRAIN -> MapType.TERRAIN } -} - -fun W3WCameraPosition.toGoogleCameraPosition(): CameraPosition { - return CameraPosition( - this.latLng.toGoogleLatLng(), - this.zoom, - this.tilt, - this.bearing - ) } \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt index 50c0494e..3068f881 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/mapper/MapBoxConverter.kt @@ -1,9 +1,6 @@ package com.what3words.components.compose.maps.mapper -import com.mapbox.geojson.Point -import com.mapbox.maps.CameraOptions import com.mapbox.maps.Style -import com.what3words.components.compose.maps.models.W3WCameraPosition import com.what3words.components.compose.maps.models.W3WMapType fun W3WMapType.toMapBoxMapType(isDarkMode: Boolean): String { @@ -13,13 +10,4 @@ fun W3WMapType.toMapBoxMapType(isDarkMode: Boolean): String { W3WMapType.HYBRID -> Style.SATELLITE_STREETS W3WMapType.TERRAIN -> Style.OUTDOORS } -} - -fun W3WCameraPosition.toMapBoxCameraOptions(): CameraOptions { - return CameraOptions.Builder() - .pitch(this.tilt.toDouble()) - .bearing(this.bearing.toDouble()) - .center(Point.fromLngLat(this.latLng.lng, this.latLng.lat)) - .zoom(this.zoom.toDouble()) - .build() } \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt deleted file mode 100644 index 8e9d0d01..00000000 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/models/W3WCameraPosition.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.what3words.components.compose.maps.models - -data class W3WCameraPosition( - val latLng: W3WLatLng, - val zoom: Float, - val bearing: Float, - val tilt: Float -) \ No newline at end of file diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt index be29dbdf..5d3beac0 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/googlemap/W3WGoogleMapDrawer.kt @@ -29,7 +29,6 @@ import com.what3words.components.compose.maps.state.W3WMapState import com.what3words.components.compose.maps.state.isExistInOtherList import com.what3words.components.compose.maps.utils.getMarkerBitmap import com.what3words.components.compose.maps.utils.getPin -import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.map.components.compose.R import kotlinx.collections.immutable.ImmutableMap diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt index ca320fbb..9427419e 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/providers/mapbox/W3WMapBoxDrawers.kt @@ -19,7 +19,6 @@ import com.what3words.components.compose.maps.models.W3WMarker import com.what3words.components.compose.maps.state.W3WListMarker import com.what3words.components.compose.maps.state.W3WMapState import com.what3words.components.compose.maps.utils.getMarkerBitmap -import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.map.components.compose.R diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt index d846184e..33dbc35c 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WCameraState.kt @@ -1,6 +1,5 @@ package com.what3words.components.compose.maps.state.camera -import com.what3words.components.compose.maps.models.W3WCameraPosition import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.core.types.geometry.W3WRectangle @@ -30,7 +29,13 @@ interface W3WCameraState { * @param coordinates The W3W coordinates to move the camera to. * @param animate Whether to animate the camera movement. */ - fun moveToPosition(coordinates: W3WCoordinates, animate: Boolean) + fun moveToPosition( + coordinates: W3WCoordinates, + zoom: Float? = null, + bearing: Float? = null, + tilt: Float? = null, + animate: Boolean = false, + ) /** * Returns the current zoom level of the camera. @@ -39,14 +44,6 @@ interface W3WCameraState { */ fun getZoomLevel(): Float - /** - * Sets the camera position to the specified camera position. - * - * @param cameraPosition The new camera position. - * @param animate Whether to animate the camera movement. - */ - fun setCameraPosition(cameraPosition: W3WCameraPosition, animate: Boolean) - /** * Moves the camera to the current location. * diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt index 15e3ace1..777c73f7 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WGoogleCameraState.kt @@ -4,8 +4,6 @@ import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.CameraPositionState -import com.what3words.components.compose.maps.mapper.toGoogleCameraPosition -import com.what3words.components.compose.maps.models.W3WCameraPosition import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.core.types.geometry.W3WRectangle import kotlinx.coroutines.CoroutineScope @@ -33,13 +31,19 @@ class W3WGoogleCameraState(override val cameraState: CameraPositionState) : ) } - override fun moveToPosition(coordinates: W3WCoordinates, animate: Boolean) { + override fun moveToPosition( + coordinates: W3WCoordinates, + zoom: Float?, + bearing: Float?, + tilt: Float?, + animate: Boolean + ) { updateCameraPosition( CameraPosition( LatLng(coordinates.lat, coordinates.lng), - cameraState.position.zoom, - cameraState.position.tilt, - cameraState.position.bearing + zoom?:cameraState.position.zoom, + bearing?:cameraState.position.tilt, + tilt?:cameraState.position.bearing ), animate ) } @@ -48,10 +52,6 @@ class W3WGoogleCameraState(override val cameraState: CameraPositionState) : return cameraState.position.zoom } - override fun setCameraPosition(cameraPosition: W3WCameraPosition, animate: Boolean) { - updateCameraPosition(cameraPosition.toGoogleCameraPosition(), animate) - } - override fun moveToMyLocation(coordinates: W3WCoordinates) { updateCameraPosition( CameraPosition( diff --git a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt index 9f350aaa..c96f3bd1 100644 --- a/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt +++ b/lib-compose/src/main/java/com/what3words/components/compose/maps/state/camera/W3WMapboxCameraState.kt @@ -4,8 +4,6 @@ import com.mapbox.geojson.Point import com.mapbox.maps.CameraOptions import com.mapbox.maps.MapConstants.MAX_ZOOM import com.mapbox.maps.extension.compose.animation.viewport.MapViewportState -import com.what3words.components.compose.maps.mapper.toMapBoxCameraOptions -import com.what3words.components.compose.maps.models.W3WCameraPosition import com.what3words.core.types.geometry.W3WCoordinates import com.what3words.core.types.geometry.W3WRectangle @@ -29,12 +27,18 @@ class W3WMapboxCameraState(override val cameraState: MapViewportState) : ) } - override fun moveToPosition(coordinates: W3WCoordinates, animate: Boolean) { + override fun moveToPosition( + coordinates: W3WCoordinates, + zoom: Float?, + bearing: Float?, + tilt: Float?, + animate: Boolean + ) { val cameraOptions = CameraOptions.Builder() - .pitch(cameraState.cameraState?.pitch) - .bearing(cameraState.cameraState?.bearing) + .pitch(tilt?.toDouble()?:cameraState.cameraState?.pitch) + .bearing(bearing?.toDouble()?:cameraState.cameraState?.bearing) .center(Point.fromLngLat(coordinates.lng, coordinates.lat)) - .zoom(cameraState.cameraState?.zoom) + .zoom(zoom?.toDouble()?:cameraState.cameraState?.zoom) .build() updateCameraPosition(cameraOptions, animate) @@ -44,10 +48,6 @@ class W3WMapboxCameraState(override val cameraState: MapViewportState) : return cameraState.cameraState?.zoom?.toFloat() ?: run { 0f } } - override fun setCameraPosition(cameraPosition: W3WCameraPosition, animate: Boolean) { - updateCameraPosition(cameraPosition.toMapBoxCameraOptions(),animate) - } - override fun moveToMyLocation(coordinates: W3WCoordinates) { val cameraOptions = CameraOptions.Builder() .pitch(cameraState.cameraState?.pitch)